前置き
PyMySQL使ってますか?
え?ORM使ってるからそんなもん使わない?
まぁまぁ、ORMはORMでめんどくさいときがあるじゃないですか。
チョクでSQL書いたら楽なときもあるでしょ?
でPyMySQL
import pymysql.cursors
# Connect to the database
connection = pymysql.connect(host='localhost',
user='user',
password='passwd',
db='db',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
with connection.cursor() as cursor:
# Create a new record
sql = "SELECT * from users where first_name = 'bob'"
cursor.execute(sql, connection)
とか。
cursorclass=pymysql.cursors.DictCursor
ってのが便利です。
{'name': 'bob', 'id': 1}
のようにDictを返してくれるからです。
でもこれ。NULLがあるとこうなるんですわ。
[{'first_name': 'bob', 'last_name': 'smith', 'id': 1, 'phone_num': None},
{'first_name': 'bob', 'last_name': 'jones', 'id': 2, 'phone_num': None}]
None
じゃなくて"NULL"
って返してほしい。
NULL
のときは"NULL"
って返せって仕様書にあるんだもん。
んで戻り値をfor i in ...:
とかやって置き換えてませんか?
ソースコード
DictCursorってなにやってんの?
class DictCursor(DictCursorMixin, Cursor):
"""A cursor which returns results as a dictionary"""
なんも。
DictCursorMixinは?
class DictCursorMixin(object):
# You can override this to use OrderedDict or other dict-like types.
dict_type = dict
「Dict-likeでオーバーライドしてね!」と。
テストでもやってるからやっていいんでしょうね
じゃあ
d = {"foo": "bar", "baz": None}
assert d["baz"] == "NULL"
こういうDict作ればいいんじゃね?
class MyDict(dict):
def __init__(self):
# なんか処理する
とりあえずこんな感じ? dunderいじくりたいのですが、dictってどんな実装になってるんでしょうね・・・・
ここみると・・・ソースがCなので読めないっす。(つよつよな方は読めるんでしょうが・・・)
「OrderedDictとか入れてね」ってソースにあるのでOrderdDictのソースを・・・
OrderedDictでもいいかな
class OrderedDict(dict):
def __init__(self, other=(), /, **kwds):
# (略)
self.__update(other, **kwds)
updateはこっち?だけどいまいちよくわかんないので適当に実装します。
まとめ
class MyDict(dict):
def __init__(self, other=None):
super().__init__()
self._update(other)
def _update(self, other=None):
if other is not None:
for h, i in other:
if i:
self[h] = i
else:
self[h] = "NULL"
class MyDictCursor(cursors.DictCursor):
dict_type = MyDict
connection = pymysql.connect(host='localhost',
user='user',
password='passwd',
db='db',
charset='utf8mb4',
cursorclass=MyDict)
んでこうなると。
[{'first_name': 'bob', 'last_name': 'smith', 'id': 1, 'phone_num': "NULL"},
{'first_name': 'bob', 'last_name': 'jones', 'id': 2, 'phone_num': "NULL"}]