diff --git a/sat/memory/migration/versions/129ac51807e4_create_virtual_table_for_full_text_.py b/sat/memory/migration/versions/129ac51807e4_create_virtual_table_for_full_text_.py new file mode 100644 index 00000000..5d1fca0b --- /dev/null +++ b/sat/memory/migration/versions/129ac51807e4_create_virtual_table_for_full_text_.py @@ -0,0 +1,49 @@ +"""create virtual table for Full-Text Search + +Revision ID: 129ac51807e4 +Revises: 8974efc51d22 +Create Date: 2021-08-13 19:13:54.112538 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '129ac51807e4' +down_revision = '8974efc51d22' +branch_labels = None +depends_on = None + + +def upgrade(): + queries = [ + "CREATE VIRTUAL TABLE pubsub_items_fts " + "USING fts5(data, content=pubsub_items, content_rowid=id)", + "CREATE TRIGGER pubsub_items_fts_sync_ins AFTER INSERT ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(rowid, data) VALUES (new.id, new.data);" + "END", + "CREATE TRIGGER pubsub_items_fts_sync_del AFTER DELETE ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(pubsub_items_fts, rowid, data) " + "VALUES('delete', old.id, old.data);" + "END", + "CREATE TRIGGER pubsub_items_fts_sync_upd AFTER UPDATE ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(pubsub_items_fts, rowid, data) VALUES" + "('delete', old.id, old.data);" + " INSERT INTO pubsub_items_fts(rowid, data) VALUES(new.id, new.data);" + "END", + "INSERT INTO pubsub_items_fts(rowid, data) SELECT id, data from pubsub_items" + ] + for q in queries: + op.execute(sa.DDL(q)) + + +def downgrade(): + queries = [ + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_ins", + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_del", + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_upd", + "DROP TABLE IF EXISTS pubsub_items_fts", + ] + for q in queries: + op.execute(sa.DDL(q)) diff --git a/sat/memory/sqla_mapping.py b/sat/memory/sqla_mapping.py index 96d99f8e..c5671dec 100644 --- a/sat/memory/sqla_mapping.py +++ b/sat/memory/sqla_mapping.py @@ -23,7 +23,7 @@ import time import enum from sqlalchemy import ( MetaData, Column, Integer, Text, Float, Boolean, DateTime, Enum, JSON, ForeignKey, - UniqueConstraint, Index + UniqueConstraint, Index, DDL, event ) from sqlalchemy.orm import declarative_base, relationship @@ -56,7 +56,7 @@ class SyncState(enum.Enum): COMPLETED = 2 #: something wrong happened during synchronisation, won't sync ERROR = 3 - #: synchronisation won't be done even if a syncing analyser match + #: synchronisation won't be done even if a syncing analyser matches NO_SYNC = 4 @@ -529,3 +529,48 @@ class PubsubItem(Base): parsed = Column(JSON) node = relationship("PubsubNode", back_populates="items") + + +## Full-Text Search + +# create + +@event.listens_for(PubsubItem.__table__, "after_create") +def fts_create(target, connection, **kw): + """Full-Text Search table creation""" + if connection.engine.name == "sqlite": + # Using SQLite FTS5 + queries = [ + "CREATE VIRTUAL TABLE pubsub_items_fts " + "USING fts5(data, content=pubsub_items, content_rowid=id)", + "CREATE TRIGGER pubsub_items_fts_sync_ins AFTER INSERT ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(rowid, data) VALUES (new.id, new.data);" + "END", + "CREATE TRIGGER pubsub_items_fts_sync_del AFTER DELETE ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(pubsub_items_fts, rowid, data) " + "VALUES('delete', old.id, old.data);" + "END", + "CREATE TRIGGER pubsub_items_fts_sync_upd AFTER UPDATE ON pubsub_items BEGIN" + " INSERT INTO pubsub_items_fts(pubsub_items_fts, rowid, data) VALUES" + "('delete', old.id, old.data);" + " INSERT INTO pubsub_items_fts(rowid, data) VALUES(new.id, new.data);" + "END" + ] + for q in queries: + connection.execute(DDL(q)) + +# drop + +@event.listens_for(PubsubItem.__table__, "before_drop") +def fts_drop(target, connection, **kw): + "Full-Text Search table drop" "" + if connection.engine.name == "sqlite": + # Using SQLite FTS5 + queries = [ + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_ins", + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_del", + "DROP TRIGGER IF EXISTS pubsub_items_fts_sync_upd", + "DROP TABLE IF EXISTS pubsub_items_fts", + ] + for q in queries: + connection.execute(DDL(q))