OK,Thank you very much,I will have a try

?取 Outlook for Android<https://aka.ms/ghei36>

________________________________
From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> on behalf of 
Dan Kennedy <danielk1...@gmail.com>
Sent: Thursday, March 22, 2018 7:26:29 PM
To: sqlite-users@mailinglists.sqlite.org
Subject: Re: [sqlite] here is my test case//Re: SQLITE3 FTS5 prefix query get 
mismatch result

On 03/22/2018 06:05 PM, Dan Kennedy wrote:
> On 03/22/2018 05:38 PM, zheng xiaojin wrote:
>> Sorry, but testcase maybe have some format problem, changed belowed,
>> I run this on SQLITE 3.15.2, both on Windows and linux. and only less
>> than 2min can happen. It doesn't matter about threadsafe, because the
>> write func is only used to protect the test data. It means you can
>> stop the. write func when problem happen, and then you can just shell
>> to the db and run the same query then problem happen definitely.
>
>
> Can you do that (create a db that exhibits the problem) and upload it
> somewhere or email it directly to me? Then I'll be able to demonstrate
> the problem using just the shell.

Actually don't worry. I finally got it to work. I think it's the bug
fixed exactly a year and a day ago here:

   http://www.sqlite.org/src/info/840042cb2bed2924

Fix was published in 3.19.0. Can you confirm that 3.19.0 do not produce
the problem for you?

Thanks,
Dan.





>
> Thanks,
> Dan.
>
>
>
>>
>>
>>
>>> "create trigger if not exists trigger_insert_tbl after insert on tbl \
>>> begin \
>>> replace into tbl_fts(rowid, name, uid)
>>> values(new.rowid<http://new.rowid>,new.name<http://new.name>,,new.uid<http://new.uid>);
>>> \
>>> end;",
>>> "create trigger if not exists trigger_update_tbl after update on tbl \
>>> begin \
>>> replace into tbl_fts(rowid, name, uid)
>>> values(new.rowi<http://new.rowid>d,new.name<http://new.name>,new.uid<http://new.uid>);\
>>> end;"
>>
>> ?取 Outlook for Android<https://aka.ms/ghei36>
>>
>> ________________________________
>> From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> on
>> behalf of Dan Kennedy <danielk1...@gmail.com>
>> Sent: Thursday, March 22, 2018 4:56:15 PM
>> To: sqlite-users@mailinglists.sqlite.org
>> Subject: Re: [sqlite] here is my test case//Re: SQLITE3 FTS5 prefix
>> query get mismatch result
>>
>> On 03/21/2018 03:16 PM, zheng xiaojin wrote:
>>> (Please add.the head file and sqlite lib yourself, Thank you very much)
>>
>> Hi,
>>
>> Thanks for doing this. I'm running this version of the test program
>> modified for posix threads:
>>
>>     https://pastebin.com/d1HCX2aJ
>>
>> but I haven't seen any errors yet. How long do you usually have to run
>> it for before seeing the mismatch error?
>>
>> Which version of SQLite are you seeing the errors with?
>>
>> Are you building SQLite with SQLITE_THREADSAFE=0?
>>
>> Do you have access to a Linux or similar system on which you can run the
>> pthreads version above? Does it produce errors for you?
>>
>> Thanks,
>> Dan Kennedy.
>>
>>
>>
>>
>>
>>> char *orgName[] = {
>>> "yun j ji yunji yunj yji yj z zh zha zhao q qi qia qian d du dua
>>> duan zhaoqian zhaoq zhqian zhq zqian zq qianduan qiand qduan qd
>>> zhaoqianduan zhaoqiand zhaoqduan zhaoqd zhqianduan zhqiand zhqduan
>>> zhqd zqianduan zqiand zqduan zqd",
>>> "murren m mu l lu lun mulun mul mlun ml",
>>> "l lu m ma man luman lum lman lm",
>>> "d   di   din   ding   d   di   din   ding   f   fu   w   wu
>>> dingding   dingd   dding   dd   dingfu   dingf   dfu   df fuwu
>>> fuw   fwu   fw   dingdingfu   dingdingf   dingdfu dingdf   ddingfu
>>> ddingf   ddfu   ddf   dingfuwu   dingfuw dingfwu   dingfw   dfuwu
>>> dfuw   dfwu   dfw   dingdingfuwu dingdingfuw   dingdingfwu
>>> dingdingfw   dingdfuwu dingdfuw   dingdfwu   dingdfw   ddingfuwu
>>> ddingfuw ddingfwu   ddingfw   ddfuwu   ddfuw   ddfwu   ddfw   l   li
>>> x   xi   xia   lixia   lix   lxia   lx",
>>> "lucy y ya yan x xi yanxi yanx yxi yx",
>>> "p pe pen peng l le lei penglei pengl plei pl lucy"
>>> };
>>> char *nickName[] = {
>>> "ab",
>>> "bc",
>>> "cd",
>>> "de",
>>> "ef",
>>> "fg"
>>> };
>>> int id[] = { 21078,21218,21125,53234,40824,164873 };
>>>
>>> void prepareSchema_prefix(sqlite3 *db) {
>>> char *schemas[] = {
>>> "PRAGMA journal_mode=WAL;",
>>> "drop table if exists tbl;",
>>> "drop table if exists tbl_fts;",
>>> "create table if not exists tbl(name text, uid int primary key, nick
>>> text);",
>>> "create virtual table if not exists tbl_fts USING fts5(name, uid);",
>>> "create trigger if not exists trigger_insert_tbl after insert on tbl \
>>> begin \
>>> replace into tbl_fts(rowid, name, uid)
>>> values(new.rowid<http://new.rowid>,new.name<http://new.name>,new.uid<http://new.uid>);
>>> \
>>> end;",
>>> "create trigger if not exists trigger_update_tbl after update on tbl \
>>> begin \
>>> replace into tbl_fts(rowid, name, uid)
>>> values(new.rowid<http://new.rowid>,new.name<http://new.name>,new.uid<http://new.uid>);\
>>> end;"
>>> };
>>> int i, j, rc, cnt;
>>> cnt = sizeof(schemas) / sizeof(char*);
>>> char *errMsg;
>>> for (i = 0; i < cnt; i++) {
>>> rc = sqlite3_exec(db, schemas[i], NULL, NULL, &errMsg);
>>> if (rc != SQLITE_OK&&rc != SQLITE_DONE) {
>>> printf("prepareSchema error: %s\n", errMsg);
>>> return;
>>> }
>>> }
>>> printf("prepareSchema over\n");
>>> }
>>>
>>> void fts5_prefix_match_test() {
>>> sqlite3 *db;
>>> int i, j, k, rc;
>>> char *errMsg;
>>> char *append = "abcdefghijklmnopqrstuvwxyz";
>>> sqlite3_open("a.db<http://a.db>", &db);
>>> prepareSchema_prefix(db);
>>> int test_cnt = 300, rc_copy = 0;
>>> char zSql[2048];
>>> char *tmp;
>>> const int len_zSql = 2047;
>>> int len_left;
>>> int nRow = 0, nCol = 0;
>>> char **pazResult;
>>> const int trx_cnt = 10000;
>>> int trx_idx;
>>> for (trx_idx = 0; trx_idx < 10000; trx_idx++) {
>>> for (i = 0; i < test_cnt; i++) {
>>> j = random(6);
>>> len_left = len_zSql;
>>> tmp = zSql;
>>> if (j < 4) {
>>> int uid = id[j] + random(300);
>>> rc_copy = snprintf(tmp, len_left, "insert into tbl
>>> values(\"%s%c\",%d,\"%s%c\");",
>>> orgName[j], append[random(26)], uid, nickName[j], append[random(26)]);
>>> //printf("%s\n", zSql);
>>> rc = sqlite3_exec(db, zSql, NULL, NULL, &errMsg);
>>> if (rc != SQLITE_OK&&rc != SQLITE_DONE) {
>>> if (rc != SQLITE_CONSTRAINT) {
>>> printf("error %s: %s\n", zSql, errMsg);
>>> continue;
>>> }
>>> else {
>>> rc_copy = snprintf(tmp, len_left, "update tbl set name=\"%s%c\"
>>> where uid=%d\n",
>>> orgName[j], append[random(26)], uid);
>>> rc = sqlite3_exec(db, zSql, NULL, NULL, &errMsg);
>>> if (rc != SQLITE_OK&&rc != SQLITE_DONE) {
>>> printf("error %s: %s\n", zSql, errMsg);
>>> continue;
>>> }
>>> }
>>> }
>>> }
>>> else {
>>> rc_copy = snprintf(zSql, len_zSql, "select * from tbl where
>>> uid=%d;", id[j]);
>>> rc = sqlite3_get_table(db, zSql, &pazResult, &nRow, &nCol, &errMsg);
>>> if (nRow == 0) {
>>> rc_copy = snprintf(tmp, len_left, "insert into tbl(name, uid, nick)
>>> values(\"%s\",%d,\"%s\");",
>>> orgName[j], id[j], nickName[j]);
>>> }
>>> else {
>>> rc_copy = snprintf(zSql, len_zSql, "update tbl set name=\"%s\" where
>>> uid=%d;",
>>> orgName[j], id[j]);
>>> }
>>> rc = sqlite3_exec(db, zSql, NULL, NULL, &errMsg);
>>> if (rc != SQLITE_OK&&rc != SQLITE_DONE) {
>>> printf("error %s: %s\n", zSql, errMsg);
>>> continue;
>>> }
>>> }
>>> }
>>> printf("insert 300 records\n");
>>> sqlite3_sleep(200);
>>> }
>>> }
>>>
>>>
>>> unsigned __stdcall writeFunc(void *pIn) {
>>> fts5_prefix_match_test();
>>> printf("write over\n");
>>> return 0;
>>> }
>>> unsigned __stdcall readFunc(void *pIn) {
>>> sqlite3 *db;
>>> int i, j, rc;
>>> char *errMsg;
>>> char **pazResult;
>>> int nRow, nCol;
>>> sqlite3_sleep(2000);
>>> rc = sqlite3_open("a.db<http://a.db>", &db);
>>> if (rc != SQLITE_OK) {
>>> printf("open db error\n");
>>> return 0;
>>> }
>>> char *zSql = "select rowid, * from tbl_fts where tbl_fts match
>>> \'lucy*\';";
>>> while (1) {
>>> rc = sqlite3_get_table(db, zSql, &pazResult, &nRow, &nCol, &errMsg);
>>> if (nRow > 2) {
>>> printf("mis-match\n");
>>> for (i = 0; i <= nRow; i++) {
>>> for (j = 0; j < nCol; j++) {
>>> printf("%s\t", pazResult[i*nCol + j]);
>>> }
>>> printf("\n");
>>> }
>>> return 0;
>>> }
>>> else {
>>> printf("match cnt = %d\n", nRow);
>>> }
>>> sqlite3_free_table(pazResult);
>>> sqlite3_sleep(3000);
>>> }
>>> return 0;
>>> }
>>> #define THREAD_NUM 2
>>>
>>> int thread(ThreadFuncType writeFunc, ThreadFuncType readFunc) {
>>> HANDLE handle[THREAD_NUM];
>>> if (writeFunc) {
>>> handle[0] = (HANDLE)_beginthreadex(NULL, 0, writeFunc, NULL, 0, NULL);
>>> //WaitForMultipleObjects(1, handle, TRUE, INFINITE);
>>> }
>>> if (readFunc) {
>>> for (int i = 1; i < THREAD_NUM; i++) {
>>> handle[i] = (HANDLE)_beginthreadex(NULL, 0, readFunc, NULL, 0, NULL);
>>> Sleep(5);
>>> }
>>> if (writeFunc) {
>>> WaitForMultipleObjects(THREAD_NUM, &handle[0], TRUE, INFINITE);
>>> }
>>> else {
>>> WaitForMultipleObjects(THREAD_NUM - 1, &handle[1], TRUE, INFINITE);
>>> }
>>> printf("multithread are all over now.\n");
>>> }
>>> else {
>>> WaitForMultipleObjects(1, &handle[0], TRUE, INFINITE);
>>> printf("multithread are all over now.\n");
>>> }
>>> return 0;
>>> }
>>>
>>> int main() {
>>> thread(writeFunc, readFunc);
>>> return 0;
>>> }
>>>
>>>
>>>
>>>
>>>
>>>
>>> ?取 Outlook for Android<https://aka.ms/ghei36>
>>>
>>> ________________________________
>>> From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> on
>>> behalf of Dan Kennedy <danielk1...@gmail.com>
>>> Sent: Tuesday, March 20, 2018 7:49:37 PM
>>> To: sqlite-users@mailinglists.sqlite.org
>>> Subject: Re: [sqlite] SQLITE3 FTS5 prefix query get mismatch result
>>>
>>> On 03/20/2018 02:31 PM, zheng xiaojin wrote:
>>>> (I am not sure whether you have seen my message, so resend again)
>>>> Hi,
>>>> When I use FTS5, I have met that, there are some cases which will
>>>> get mis-match results with prefix search.
>>>>
>>>> Like "select * from tbl_fts where tbl_fts match 'lucy*';",which I
>>>> want to get records like "lucya","lucyabc" etc, and
>>>>
>>>> "lux" or "lulu" is not what I want but returned.
>>>>
>>>> Such problems are not common, But I have tried to build such test
>>>> case which can lead to this problem very easy.
>>> Thanks for looking into and reporting this problem. Are you able to
>>> post
>>> the source for the program you used to execute the test described
>>> below?
>>>
>>> Dan.
>>>
>>>
>>>> Here is how I generate it:
>>>>
>>>> 1) create an fts5 table. and insert some record like "lucya","lucyb".
>>>>
>>>> 2) prepare some records: a) lusheng b)lulu; c)lunix; d)luma; e)
>>>> pengyu. a,b,c,d are have some same prefix(lu), e is some other
>>>> random case.
>>>>
>>>> 3) before insert into the fts table with 2) records, appending some
>>>> random letter to make each record different.
>>>>
>>>> Like: "lulu","luluabc","luluefg", also "lunix","lunixabc",etc
>>>>
>>>> 4) for-loop insert, and each loop trying to lantch the query
>>>> 'lucy*', \
>>>>
>>>> check the match result will finding the mis-match result, the
>>>> corrent results should be "lucya","lucyb", not "luluabc"...
>>>>
>>>>
>>>> When mis-match happen, I try to analyze the prefix search mechanism
>>>> and find that, there are 2 points which I think have problems:
>>>>
>>>> 1) fts5LeafSeek, when search failed, and exec goto search_failed,
>>>> in search_failed, the 2 if condition will not satisfy commonly. In
>>>> my mind, I think it should return,
>>>>
>>>> but not, and then the search_success logic exec.
>>>>
>>>> 2) fts5SetupPrefixIter, when gather results, the logic to set the
>>>> flag bNewTerm has some leak, which will set bNewTerm=false,
>>>>
>>>> but the record is not what we want indeed.
>>>>
>>>>
>>>> These 2 logic problems lead to mis-match results. I try to remove
>>>> the bNewTerm logic directly, and make it compare every loog,
>>>>
>>>> then, the mis-match results disappear.
>>>>
>>>> // relevant code
>>>>
>>>> Change below
>>>>
>>>> if (bNewTerm) {
>>>>
>>>> if (nTerm < nToken || memcmp(pToken, pTerm, nToken)) break;
>>>>
>>>> }
>>>>
>>>> to
>>>>
>>>> if (nTerm < nToken || memcmp(pToken, pTerm, nToken)) break;
>>>>
>>>>
>>>> Need your help to recheck the FTS5 prefix search logic, thank you
>>>> very much.
>>>>
>>>> Yours,
>>>>
>>>> xiaojin zheng
>>>>
>>>>
>>>> ?取 Outlook for Android<https://aka.ms/ghei36>
>>>>
>>>> _______________________________________________
>>>> sqlite-users mailing list
>>>> sqlite-users@mailinglists.sqlite.org
>>>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>> _______________________________________________
>>> sqlite-users mailing list
>>> sqlite-users@mailinglists.sqlite.org
>>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>> _______________________________________________
>>> sqlite-users mailing list
>>> sqlite-users@mailinglists.sqlite.org
>>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>>
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users@mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>> _______________________________________________
>> sqlite-users mailing list
>> sqlite-users@mailinglists.sqlite.org
>> http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
>
>

_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to