Знающие люди ткнули носом в раздел документации 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);
- проверка возможности удаления записи модели (ссылочная целостность);
- и, наверняка, многое другое...
Об использовании метаданных в реальном проекте с примерами кода по всем задачам напишу отдельный пост. Продолжение следует...
Комментариев нет:
Отправить комментарий