I'd like to use SQLite FTS3 (FTS4, actually) to index a table with integer columns, conceptually something like this:
CREATE VIRTUAL TABLE whole (document INTEGER, page INTEGER, content TEXT,
UNIQUE(document, page)) USING fts4();
I know that FTS3 treats all columns other than rowid as TEXT, so I'll have to use two tables:
CREATE VIRTUAL TABLE data USING fts4();
CREATE TABLE metadata(document INTEGER, page INTEGER, UNIQUE(document, page));
I want to be able to query for documents, or for pages in a given document:
SELECT DISTINCT document FROM metadata NATURAL JOIN data WHERE content MATCH 'foo';
SELECT page FROM metadata NATURAL JOIN data
WHERE document = 123 AND content MATCH 'foo';
I think the NATURAL JOIN requires me to ensure that the rowids are kept in sync, but what's the best way to do that? Should I be using a FOREIGN KEY or other constraint? Would a sub-select be better than a join?
I'd like an insertion for a document and page already in the database to overwrite the text content. Is that possible programmatically via SQL or will I have to check to see if the row already exists in the info table?
I'm also going to be wanting to DELETE FROM both tables for a given document -- is there a way to do this in a single statement?
All advice gratefully received, but as I am a SQL newbie, code samples particularly appreciated!
Update: It's not at all clear to me how I can create a foreign key constraint here. If I choose metadata
as the parent table (which would be my preference, in the absence of a bidirectional constraint):
PRAGMA foreign_keys = ON;
CREATE TABLE metadata (document INTEGER, page INTEGER);
CREATE VIRTUAL TABLE data USING fts4(content TEXT, docid REFERENCES metadata);
I get Error: vtable constructor failed: data
(unsurprisingly, because docid
is an alias for rowid
, but of course I can't use another column because all columns except rowid
must be TEXT
).
Whereas if I try the other way round:
PRAGMA foreign_keys = ON;
CREATE VIRTUAL TABLE data USING fts4();
CREATE TABLE metadata (document INTEGER, page INTEGER, docid REFERENCES data);
the table construction succeeds, but if I try:
INSERT INTO data (docid, content) VALUES (123, 'testing');
INSERT INTO metadata (docid, document, page) VALUES (123, 12, 23);
I get Error: foreign key mismatch
.