Casey Rodarmor
Casey Rodarmor

Reputation: 15568

Can a SQLite FTS table be backed by a view?

I've created a FTS table backed by a VIEW using the 'content' argument, but it isn't producing the results that I would expect:

CREATE TABLE tracks(docid INTEGER PRIMARY KEY, track_name varchar, ref_aid integer, ref_rid integer);
CREATE TABLE artists(artist_name varchar, aid integer);
CREATE TABLE releases(release_name varchar, rid integer);

CREATE VIEW v AS
SELECT docid, track_name, artist_name, release_name
FROM tracks, artists, releases
WHERE ref_aid = aid AND ref_rid = rid;

CREATE VIRTUAL TABLE t USING fts4(content="v", track_name, artist_name, release_name);

INSERT INTO tracks VALUES(0, 'xxx', 1, 1);
INSERT INTO tracks VALUES(1, 'yyy', 1, 1);
INSERT INTO artists VALUES('aaa', 1);
INSERT INTO releases VALUES('rrr', 1);

INSERT INTO t (docid, track_name, artist_name, release_name)
SELECT docid, track_name, artist_name, release_name
FROM v;

-- this prints 0 as expected:
SELECT docid FROM t WHERE t MATCH 'xxx';

-- this prints ||, indicating that it failed to look up the content in the view:
SELECT * FROM t WHERE t MATCH 'xxx';

I would expect the second SELECT statement to return xxx|aaa|rrr, but it doesn't return anything.

Upvotes: 3

Views: 326

Answers (1)

Casey Rodarmor
Casey Rodarmor

Reputation: 15568

The external content table needs to have a column named rowid in order for data to be retrievable. This worked:

CREATE TABLE tracks(rowid INTEGER PRIMARY KEY, track_name varchar, ref_aid integer, ref_rid integer);
CREATE TABLE artists(artist_name varchar, aid integer);
CREATE TABLE releases(release_name varchar, rid integer);

CREATE VIEW v AS
SELECT rowid, track_name, artist_name, release_name
FROM tracks, artists, releases
WHERE ref_aid = aid AND ref_rid = rid;

CREATE VIRTUAL TABLE t USING fts4(content="v", track_name, artist_name, release_name);

INSERT INTO tracks VALUES(0, 'xxx', 1, 1);
INSERT INTO tracks VALUES(1, 'yyy', 1, 1);
INSERT INTO artists VALUES('aaa', 1);
INSERT INTO releases VALUES('rrr', 1);

INSERT INTO t (rowid, track_name, artist_name, release_name)
SELECT rowid, track_name, artist_name, release_name
FROM v;

-- this prints 0 as expected:
SELECT docid FROM t WHERE t MATCH 'xxx';

-- this prints xxx|aaa|rrr as expected:
SELECT * FROM t WHERE t MATCH 'xxx';

Upvotes: 4

Related Questions