0

I'm trying to use FTS in my existing SQLite database, so I'm using an external source for the virtual table- but I'm getting confusing results for an FTS3 table, which I'll end up having to use if I plan on supporting < 11 Android API

In this static function from my DB Contract class I create the initialization string for SQL to create my virtual table.

Db Contract:

public static String getVirtualCreate(){
    if (VIRTUAL_TABLE_NAME == "")
        return "";
    String createstring = "CREATE VIRTUAL TABLE IF NOT EXISTS " + VIRTUAL_TABLE_NAME + " USING fts4(content=\"" + TABLE_NAME +"\",";
    for (int a = 0; a < virtualCount(); a++){
        createstring += getVirtualColumn(a).getName();
        if (a < count() - 1){
            createstring += ",";
        }
    }
    createstring += ")";
    return createstring;
}

And this code to create the triggers

public static String getVirtualCreateTriggers(){

    String rowstring = "";
    String postrowstring = "";

    for(int a = 0; a < virtualCount(); a++){
        rowstring += getVirtualColumn(a);
        postrowstring += "new." + getVirtualColumn(a);

        if (a < virtualCount() - 1){
            rowstring += ",";
            postrowstring += ",";
        }
    }

    String ret =
            "CREATE TRIGGER IF NOT EXISTS TABLE_NAME_bu BEFORE UPDATE ON TABLE_NAME BEGIN\n" +
                    "  DELETE FROM VIRTUAL_TABLE_NAME WHERE docid=old."+COLUMN_NAME_ID+";\n" +
                    "END;\n" +
                    "CREATE TRIGGER TABLE_NAME_bd BEFORE DELETE ON TABLE_NAME BEGIN\n" +
                    "  DELETE FROM VIRTUAL_TABLE_NAME WHERE docid=old."+COLUMN_NAME_ID+";\n" +
                    "END;\n" +
                    "CREATE TRIGGER TABLE_NAME_au AFTER UPDATE ON TABLE_NAME BEGIN\n" +
                    "  INSERT INTO VIRTUAL_TABLE_NAME(docid,"+rowstring+") VALUES("+postrowstring+");\n" +
                    "END;\n" +
                    "CREATE TRIGGER TABLE_NAME_ai AFTER INSERT ON TABLE_NAME BEGIN\n" +
                    "  INSERT INTO VIRTUAL_TABLE_NAME(docid, "+rowstring+") VALUES("+postrowstring+");\n" +
                    "END;";

    return ret;
}

DB Helper:

The DBContract creation strings seem to work fine in the implementation. If I call something like:

Cursor mCursor = db.rawQuery("SELECT * FROM " + DbContract.PartEntry.VIRTUAL_TABLE_NAME ,null);

It will return all of the values of the original table.

However if I call that exact same code, but change the CreateString to FTS3

String createstring = "CREATE VIRTUAL TABLE IF NOT EXISTS " + VIRTUAL_TABLE_NAME + " USING fts3(content=\"" + TABLE_NAME +"\",";

Even after adding additional rows after the virtual table changed The SELECT * returns 0 rows.

Upon changing it back, everything functions normally.

Secondarily, and probably related, if I use a function like Cursor mCursor = db.rawQuery("SELECT * FROM " + DbContract.PartEntry.VIRTUAL_TABLE_NAME + " WHERE " + DbContract.PartEntry.VIRTUAL_TABLE_NAME + " match '" + search + "'",null);

Where search is an (unescaped on purpose for now) String that is most definitely found in the original AND virtual table (verified by a select *) it returns 0 rows for FTS4, currently un-testable in FTS3 because of the previously mentioned issue with no data appearing.

Question:

Am I doing something incorrectly in my table definitions? Or perhaps is there something else that could cause a wildcard search in FTS3 to return no results, seemingly without any error messages thrown? Unfortunately this is my first experience with anything outside of vanilla SQL, so it's likely I'm doing something wrong somewhere.

If I don't have enough code, or a good enough example, is there a better example or more relevant code I can add to help give a better understanding of the situation?

Community
  • 1
  • 1
wizebin
  • 730
  • 5
  • 15
  • Fixed one issue to use `match` on the FTS4 table I needed to rebuild the indexes `INSERT INTO vtable(vtable) VALUES('rebuild');` – wizebin May 22 '15 at 22:18
  • Shoot... took a long look at the manual again, it looks like external content is one of the FTS4 exclusive options... Issue #2 resolved. – wizebin May 22 '15 at 22:34

1 Answers1

1

I dislike having to answer my own question... however after quite a bit of puzzling I discovered the answers to both of my questions.

The reason the FTS4 match request returned 0 rows was because it wasn't indexed.

The fix:

INSERT INTO vtable(vtable) VALUES('rebuild');

The reason changing the table definition from FTS4 to FTS3 didn't function properly was the option to use external content (at least as far as I can tell) is an FTS4 exclusive option. Meaning it's not available on FTS3..

My solution is to build two versions of the virtual table, one for pre API 11 with FTS3 and no external source, and one using FTS4 which allows us to use external sources.

wizebin
  • 730
  • 5
  • 15