Знающие люди ткнули носом в раздел документации sqlite, где описан набор прагм (pragma) для получения исчерпывающей информации о структуре базы. Подробно расписывать не буду, разработчики sqlite прекрасно сделали это сами.
Как выяснилось, эта метаинформация может быть довольно полезной при разработке интерфейсов к базе данных.
Для ее извлечения из базы применяю такой вот класс:
from PyQt4.QtSql import QSqlQuery
class DBMetadata(dict):
u'''
Описывает метаданные базы данных sqlite.
Заполняется при создании, использует соединение по умолчанию.
'''
class TableMetadata(object):
u'''
Описывает структуру таблицы sqlite (поля, внешние ключи).
Заполняется при создании, использует соединение по умолчанию.
'''
class FieldDetail(object):
u'''
Описание поля таблицы
(индекс, тип, обязательность, значение по умолчанию).
'''
def __init__(self, query):
self.cid = query.value(0).toInt()[0]
self.type = unicode(query.value(2).toString())
self.required = query.value(3).toBool()
self.default = query.value(4)
class FKDetail(object):
u'''
Описание внешнего ключа.
'''
def __init__(self, query):
self.table = unicode(query.value(2).toString())
self.to = unicode(query.value(4).toString())
self.on_update = unicode(query.value(5).toString())
self.on_delete = unicode(query.value(6).toString())
self.match = unicode(query.value(7).toString())
def __init__(self, table_name):
self.fld = {}
qpragma = QSqlQuery(u'pragma table_info({0})'.format(table_name))
qpragma.exec_()
while qpragma.next():
self.fld[unicode(qpragma.value(1).toString())] = self.FieldDetail(qpragma)
self.fk = {}
qpragma = QSqlQuery(u'pragma foreign_key_list({0})'.format(table_name))
qpragma.exec_()
while qpragma.next():
self.fk[unicode(qpragma.value(3).toString())] = self.FKDetail(qpragma)
def __init__(self, *args, **kwargs):
dict.__init__(self, *args, **kwargs)
qsel = QSqlQuery(u"select tbl_name from sqlite_master "
"where type = 'table' and tbl_name not like 'sqlite%'")
qsel.exec_()
while qsel.next():
table_name = unicode(qsel.value(0).toString())
self[table_name] = self.TableMetadata(table_name)Несколько примеров использования:
md = DBMetadata() # порядковый номер поля sometable.somefield (начиная с 0) md[u'sometable'].fld[u'somefield'].cid # тип поля sometable.somefield md[u'sometable'].fld[u'somefield'].type # имя таблицы, на которую ссылается внешний ключ sometable.somefieldfk md[u'sometable'].fk[u'somefieldfk'].table # имя поля, на которое ссылается внешний ключ sometable.somefieldfk md[u'sometable'].fk[u'somefieldfk'].to
Использовать метаданные можно в следующих задачах:
- формирование модельного индекса ячейки модели по индексу строки и имени поля в таблице (а также все остальные задачи, где требуется индекс колонки);
- пакетное создание моделей для всех таблиц базы;
- пакетный маппинг виджетов и колонок модели (при использовании QDataWidgetMapper);
- проверка возможности удаления записи модели (ссылочная целостность);
- и, наверняка, многое другое...
Об использовании метаданных в реальном проекте с примерами кода по всем задачам напишу отдельный пост. Продолжение следует...
Комментариев нет:
Отправить комментарий