Skip to content

Commit

Permalink
Create virtual table in more idomatic way.~
Browse files Browse the repository at this point in the history
  • Loading branch information
danielballan committed May 14, 2024
1 parent 598cae8 commit f46a5f1
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 35 deletions.
33 changes: 3 additions & 30 deletions tiled/catalog/adapter.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import collections
import functools
import importlib
import itertools as it
import logging
Expand All @@ -15,21 +14,7 @@

import anyio
from fastapi import HTTPException
from sqlalchemy import (
JSON,
Column,
Integer,
Table,
delete,
event,
func,
not_,
or_,
select,
text,
type_coerce,
update,
)
from sqlalchemy import delete, event, func, not_, or_, select, text, type_coerce, update
from sqlalchemy.dialects.postgresql import JSONB, REGCONFIG
from sqlalchemy.engine import make_url
from sqlalchemy.exc import IntegrityError
Expand Down Expand Up @@ -380,9 +365,8 @@ def apply_conditions(self, statement):
if (self.context.engine.dialect.name == "sqlite") and any(
isinstance(condition.type, MatchType) for condition in self.conditions
):
metadata_fts5 = _sqlite_fts5_virtual_table(orm.Node.metadata)
statement = statement.join(
metadata_fts5, metadata_fts5.c.rowid == orm.Node.id
orm.metadata_fts5, orm.metadata_fts5.c.rowid == orm.Node.id
)
for condition in self.conditions:
statement = statement.filter(condition)
Expand Down Expand Up @@ -1197,8 +1181,7 @@ def contains(query, tree):
def full_text(query, tree):
dialect_name = tree.engine.url.get_dialect().name
if dialect_name == "sqlite":
metadata_fts5 = _sqlite_fts5_virtual_table(orm.Node.metadata)
condition = metadata_fts5.c.metadata.match(query.text)
condition = orm.metadata_fts5.c.metadata.match(query.text)
elif dialect_name == "postgresql":
tsvector = func.jsonb_to_tsvector(
cast("simple", REGCONFIG), orm.Node.metadata_, cast(["string"], JSONB)
Expand Down Expand Up @@ -1446,13 +1429,3 @@ def specs_array_to_json(specs):
StructureFamily.sparse: CatalogSparseAdapter,
StructureFamily.table: CatalogTableAdapter,
}


@functools.lru_cache(1)
def _sqlite_fts5_virtual_table(sqlalchemy_metadata):
return Table(
"metadata_fts5",
sqlalchemy_metadata,
Column("rowid", Integer, primary_key=True),
Column("metadata", JSON),
)
34 changes: 29 additions & 5 deletions tiled/catalog/orm.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
ForeignKey,
Index,
Integer,
Table,
Unicode,
event,
schema,
text,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.schema import UniqueConstraint
from sqlalchemy.sql import func
Expand Down Expand Up @@ -271,15 +274,36 @@ def create_index_metadata_tsvector_search(target, connection, **kw):
)


@event.listens_for(Node.__table__, "after_create")
class FTS5Table(Table):
pass


@compiles(schema.CreateTable, "sqlite")
def _compile(element: schema.CreateTable, compiler, **kw):
if not isinstance(element.target, FTS5Table):
return compiler.visit_create_table(element, **kw)
name = compiler.preparer.format_table(element.target)
cols = ", ".join(
# Skip last column (rowid).
compiler.preparer.format_column(col)
for col in element.target.columns[1:]
)
return f"CREATE VIRTUAL TABLE {name} USING fts5({cols}, content='nodes', content_rowid='id')"


metadata_fts5 = FTS5Table(
"metadata_fts5", Base.metadata, Column("rowid", Integer), Column("metadata", JSON)
)


@event.listens_for(metadata_fts5, "after_create")
def create_virtual_table_fits5(target, connection, **kw):
if connection.engine.dialect.name == "sqlite":
statements = [
# Create an external content fts5 table.
# See https://www.sqlite.org/fts5.html Section 4.4.3.
"""
CREATE VIRTUAL TABLE metadata_fts5 USING fts5(metadata, content='nodes', content_rowid='id');
""",
# """
# CREATE VIRTUAL TABLE metadata_fts5 USING fts5(metadata, content='nodes', content_rowid='id');
# """,
# Triggers keep the index synchronized with the nodes table.
"""
CREATE TRIGGER nodes_metadata_fts5_sync_ai AFTER INSERT ON nodes BEGIN
Expand Down

0 comments on commit f46a5f1

Please sign in to comment.