def VocabModel(cls, table_type='row', table=None): if table_type not in ('row', 'col', 'instance'): raise ValueError('table_type must be either "row", "col" or ' '"instance".') attr = '_vocab_model_%s' % table_type if not hasattr(cls, attr): class Meta: database = cls._meta.database table_name = table or cls._meta.table_name + '_v' extension_module = fn.fts5vocab(cls._meta.entity, SQL(table_type)) attrs = { 'term': VirtualField(TextField), 'doc': IntegerField(), 'cnt': IntegerField(), 'rowid': RowIDField(), 'Meta': Meta, } if table_type == 'col': attrs['col'] = VirtualField(TextField) elif table_type == 'instance': attrs['offset'] = VirtualField(IntegerField) class_name = '%sVocab' % cls.__name__ setattr(cls, attr, type(class_name, (VirtualModel, ), attrs)) return getattr(cls, attr)
class BaseClosureTable(VirtualModel): depth = VirtualField(IntegerField) id = VirtualField(IntegerField) idcolumn = VirtualField(TextField) parentcolumn = VirtualField(TextField) root = VirtualField(IntegerField) tablename = VirtualField(TextField) class Meta: extension_module = 'transitive_closure' @classmethod def descendants(cls, node, depth=None, include_node=False): query = (model_class .select(model_class, cls.depth.alias('depth')) .join(cls, on=(source_key == cls.id)) .where(cls.root == node) .objects()) if depth is not None: query = query.where(cls.depth == depth) elif not include_node: query = query.where(cls.depth > 0) return query @classmethod def ancestors(cls, node, depth=None, include_node=False): query = (model_class .select(model_class, cls.depth.alias('depth')) .join(cls, on=(source_key == cls.root)) .where(cls.id == node) .objects()) if depth: query = query.where(cls.depth == depth) elif not include_node: query = query.where(cls.depth > 0) return query @classmethod def siblings(cls, node, include_node=False): if referencing_class is model_class: # self-join fk_value = node.__data__.get(foreign_key.name) query = model_class.select().where(foreign_key == fk_value) else: # siblings as given in reference_class siblings = (referencing_class .select(referencing_key) .join(cls, on=(foreign_key == cls.root)) .where((cls.id == node) & (cls.depth == 1))) # the according models query = (model_class .select() .where(source_key << siblings) .objects()) if not include_node: query = query.where(source_key != node) return query