information_schema スキーマのcolumns テーブルについては以下のように決め打ちで対応した。
Datastore 側の key_name にはスキーマ、テーブル、カラム名を結合したものを設定した。
key = information_schema_columns.table_schema + "_"
key += information_schema_columns.table_name+ "."
key += information_schema_columns.column_name
Information_schema_columns.get_or_insert(key,
table_catalog = self.request.get('table_catalog'),
table_schema = self.request.get('table_schema'),
table_name = self.request.get('table_name'),
column_name = self.request.get('column_name'),
ordinal_position = ordinal_position,
column_default = column_default,
is_nullable = self.request.get('is_nullable'),
data_type = self.request.get('data_type'),
character_maximum_length = character_maximum_length,
character_octet_length = character_octet_length,
numeric_precision = numeric_precision,
numeric_scale = numeric_scale,
character_set_name = self.request.get('character_set_name'),
collation_name = self.request.get('collation_name'),
column_type = self.request.get('column_type'),
column_key = self.request.get('column_key') ,
extra = self.request.get('extra'),
privileges = self.request.get('privileges'),
column_comment = self.request.get('column_comment'))
けれども、この情報を利用してデータを転送する汎用的なものを作成しなければならない。
RDBMSには動的SQLという仕組みがあるが、 Datastore ではどのように対応したらいいのであろうか。
「
Pythonでリフレクションする」*1 などと参考にいろいろと試行錯誤、ようやくそれらしいものができた。
苦労したのはまず、
1. 動的に Class を作成するには ?
clazz = globals()[cls.capitalize()]
obj = clazz()
2. 動的に作成できた Class の Attribute を動的に作成するには ?
setattr
3. get_or_insert() でなくて、単純に put() するときの key_name の指定方法 ?
4. key_name にはなにを設定するか ?
Joomla! では id あるいは cid 列を設定しているようなので、まずはこれらを利用することに。
def post_mysql_data(self,cls):
clazz = globals()[cls.capitalize()]
obj = clazz()
table = cls
rr = db.GqlQuery("select * from Information_schema_columns where table_name = :1", table )
col = ""
for r in rr:
if r.column_name == 'id' or r.column_name == 'cid':
column_value = self.request.get(r.column_name)
key_name = 'id' + column_value
j = clazz(key_name = key_name)
if j:
for r in rr:
column_value = self.request.get(r.column_name)
if r.data_type == 'varchar' or r.data_type == 'text' or r.data_type == 'longtext' :
if column_value : setattr(j,r.column_name,column_value)
if r.data_type == 'bigint' or r.data_type == 'tinyint' or r.data_type == 'int' :
if column_value : setattr(j,r.column_name,int(column_value))
if r.data_type == 'datetime':
if column_value :
if column_value == '0000-00-00 00:00:00':column_value = '1901-01-01 00:00:00'
column_value = datetime.datetime.strptime(column_value,'%Y-%m-%d %H:%M:%S')
setattr(j,r.column_name,column_value)
col = j.put()
*1 shisashiの開発日記
http://shisashi.blogspot.com/