> On 3/01/2017, at 4:48 AM, claude.del-vi...@laposte.net wrote:
> 
> Hi, 
> 
> The problem described here occurs both with the x32 and x64 versions of the 
> expert personal 4 (Windows 10). Hereafter, a little database to show the bug. 
> 
> The table "sample" is used to store words occurring in texts. Texts are 
> identified by an id number. 
> 
> CREATE TABLE IF NOT EXISTS sample ( 
> textid INT, 
> word VARCHAR(100), 
> UNIQUE (textid,word) 
> ); 
> 
> CREATE INDEX [word index] ON [sample] ([word]); 
> 
> INSERT INTO sample VALUES 
> (1,"hello"), 
> (1,"world"), 
> (1,"apple"), 
> (1,"fruit"), 
> (2,"fruit"), 
> (2,"banana"), 
> (3,"database") 
> ; 
> 
> Now, one wants to list all the tuples corresponding to the texts containing 
> the word "fruit". In the table above, only the texts 1 and 2 contains the 
> word "fruit". Therefore, the expected result must be : 
> 
> RecNo textid word 
> ----- ------ ------ 
> 1 1 apple 
> 2 1 fruit 
> 3 1 hello 
> 4 1 world 
> 5 2 banana 
> 6 2 fruit 
> 
> The following SQL request should achieve the goal : 
> 
> SELECT l2.textid, l2.[word] 
> FROM sample AS l1, sample AS l2 
> WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
> ; 
> 
> But il does not since it delivers the wrong answer : 
> 
> RecNo textid word 
> ----- ------ ----- 
> 1 1 fruit 
> 2 1 fruit 
> 3 1 fruit 
> 4 1 fruit 
> 5 2 fruit 
> 6 2 fruit 
> 
> However, by adjoining in the SELECT part of the above request either a 
> constant string or the command DISTINCT , then the result becomes correct ! 
> 
> SELECT "happy new year", l2.textid, l2.[word] 
> FROM sample AS l1, sample AS l2 
> WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
> ; 
> 
> RecNo 'happy new year' textid word 
> ----- ---------------- ------ ------ 
> 1 happy new year 1 apple 
> 2 happy new year 1 fruit 
> 3 happy new year 1 hello 
> 4 happy new year 1 world 
> 5 happy new year 2 banana 
> 6 happy new year 2 fruit 
> 
> SELECT DISTINCT l2.textid, l2.[word] 
> FROM sample AS l1, sample AS l2 
> WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
> ; 
> 
> RecNo textid word 
> ----- ------ ------ 
> 1 1 apple 
> 2 1 fruit 
> 3 1 hello 
> 4 1 world 
> 5 2 banana 
> 6 2 fruit 
> 
> Thank you for your reading. Please, notice that this "strange" behavior does 
> not occur with the version 3 of Sqlite expert personal. 
> 
> Claude Del Vigna 


SQLite Expert Personal is a third party product which uses the SQLite database 
engine. It is not using “SQLite 4” (which is in early development stages and 
not been released), but will be using some version of SQLite 3.

This mailing list is not an appropriate place to get support for products which 
use SQLite, but this looks like odd behaviour with SQLite itself, which may be 
worth investigating further.

The current version of SQLite Expert Personal is 4.2.0, available here:

http://www.sqliteexpert.com/download.html

They don’t appear to give any clues as to which version of SQLite the 
application is using.

I downloaded the 32-bit version, ran it under Windows 7 and tried the SQL you 
specified, and it produced the same result. 

CREATE TABLE IF NOT EXISTS sample ( 
textid INT, 
word VARCHAR(100), 
UNIQUE (textid,word) 
); 

CREATE INDEX [word index] ON [sample] ([word]); 

INSERT INTO sample VALUES 
(1,"hello"), 
(1,"world"), 
(1,"apple"), 
(1,"fruit"), 
(2,"fruit"), 
(2,"banana"), 
(3,"database") 
; 

SELECT l2.textid, l2.[word] 
FROM sample AS l1, sample AS l2 
WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
; 

textid  word
1       fruit
1       fruit
1       fruit
1       fruit
2       fruit
2       fruit

Executing this command in SQLite Expert Personal 4.2.0:

SELECT sqlite_version();

reports it is using version 3.15.2 of the SQLite database engine (as a DLL 
installed alongside the application), which was the latest version until 
version 3.16.0 was released today.

Repeating the same test using the SQLite command line tool (version 3.15.2) 
does NOT produce the same behaviour. Here is what I get for the final select 
statement:

SELECT l2.textid, l2.[word] 
FROM sample AS l1, sample AS l2 
WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
; 

1|apple
1|fruit
1|hello
1|world
2|banana
2|fruit

Therefore the problem is somehow specific to SQLite Expert Personal 4.2.0 (or 
the 32-bit DLL of SQLite 3.15.2), or maybe something in the way it has 
configured the SQLite database engine.

Going back to SQLite Expert Personal, I checked the output of EXPLAIN QUERY 
PLAN and EXPLAIN and they appear to be identical to the command line tool.

First, SQLite Expert:

EXPLAIN QUERY PLAN
SELECT l2.textid, l2.[word] 
FROM sample AS l1, sample AS l2 
WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
; 

selectid        order   from    detail
0       0       0       SEARCH TABLE sample AS l1 USING INDEX word index 
(word=?)
0       1       1       SEARCH TABLE sample AS l2 USING COVERING INDEX 
sqlite_autoindex_sample_1 (textid=?)


EXPLAIN
SELECT l2.textid, l2.[word] 
FROM sample AS l1, sample AS l2 
WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
; 

addr    opcode  p1      p2      p3      p4      p5      comment
0       Init    0       22      0               00      Start at 22
1       OpenRead        0       2       0       2       00      root=2 iDb=0; 
sample
2       OpenRead        2       4       0       k(2,,)  02      root=4 iDb=0; 
word index
3       OpenRead        3       3       0       k(3,,,) 02      root=3 iDb=0; 
sqlite_autoindex_sample_1
4       String8 0       1       0       fruit   00      r[1]='fruit'
5       SeekGE  2       18      1       1       00      key=r[1]
6       IdxGT   2       18      1       1       00      key=r[1]
7       Seek    2       0       0               00      Move 0 to 2.rowid
8       Column  0       0       2               00      r[2]=sample.textid
9       IsNull  2       17      0               00      if r[2]==NULL goto 17
10      Affinity        2       1       0       D       00      affinity(r[2])
11      SeekGE  3       17      2       1       00      key=r[2]
12      IdxGT   3       17      2       1       00      key=r[2]
13      Column  3       0       3               00      r[3]=sample.textid
14      Column  3       1       4               00      r[4]=sample.word
15      ResultRow       3       2       0               00      output=r[3..4]
16      Next    3       12      0               00      
17      Next    2       6       1               00      
18      Close   0       0       0               00      
19      Close   2       0       0               00      
20      Close   3       0       0               00      
21      Halt    0       0       0               00      
22      Transaction     0       0       2       0       01      
usesStmtJournal=0
23      TableLock       0       2       0       sample  00      iDb=0 root=2 
write=0
24      Goto    0       1       0               00      

Here is the EXPLAIN QUERY PLAN output from the sqlite3 command line tool:

0|0|0|SEARCH TABLE sample AS l1 USING INDEX word index (word=?)
0|1|1|SEARCH TABLE sample AS l2 USING COVERING INDEX sqlite_autoindex_sample_1 
(textid=?)

Here is the EXPLAIN output from the sqlite3 command line tool:

addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     22    0                    00  Start at 22
1     OpenRead       0     2     0     2              00  root=2 iDb=0; sample
2     OpenRead       2     4     0     k(2,,)         02  root=4 iDb=0; word 
index
3     OpenRead       3     3     0     k(3,,,)        02  root=3 iDb=0; 
sqlite_autoindex_sample_1
4     String8        0     1     0     fruit          00  r[1]='fruit'
5     SeekGE         2     18    1     1              00  key=r[1]
6       IdxGT          2     18    1     1              00  key=r[1]
7       Seek           2     0     0                    00  Move 0 to 2.rowid
8       Column         0     0     2                    00  r[2]=sample.textid
9       IsNull         2     17    0                    00  if r[2]==NULL goto 
17
10      Affinity       2     1     0     D              00  affinity(r[2])
11      SeekGE         3     17    2     1              00  key=r[2]
12        IdxGT          3     17    2     1              00  key=r[2]
13        Column         3     0     3                    00  r[3]=sample.textid
14        Column         3     1     4                    00  r[4]=sample.word
15        ResultRow      3     2     0                    00  output=r[3..4]
16      Next           3     12    0                    00
17    Next           2     6     1                    00
18    Close          0     0     0                    00
19    Close          2     0     0                    00
20    Close          3     0     0                    00
21    Halt           0     0     0                    00
22    Transaction    0     0     2     0              01  usesStmtJournal=0
23    TableLock      0     2     0     sample         00  iDb=0 root=2 write=0
24    Goto           0     1     0                    00

Investigating further in SQLite Expert Personal, it appears that the join 
operator is the critical detail. If I rewrite the SELECT statement as follows, 
replacing the comma operator with the word JOIN, it produces the correct result:

SELECT l2.textid, l2.[word] 
FROM sample AS l1 JOIN sample AS l2 
WHERE (l1.[word] = 'fruit' ) and (l2.[textid] = l1.[textid]) 
; 

textid  word
1       apple
1       fruit
1       hello
1       world
2       banana
2       fruit

The same output is produced if using INNER JOIN or CROSS JOIN.

How can the comma join operator produce a different result to the word JOIN?

Trying the select statement again without the WHERE clause and adding a few 
more columns produces interesting results:

First, with JOIN:

SELECT l1.textid, l1.word, l2.textid, l2.word
FROM sample AS l1 JOIN sample AS l2 
;

textid  word    textid_1        word_1
1       hello   1       hello
1       hello   1       world
1       hello   1       apple
1       hello   1       fruit
1       hello   2       fruit
1       hello   2       banana
1       hello   3       database
1       world   1       hello
1       world   1       world
1       world   1       apple
1       world   1       fruit
1       world   2       fruit
1       world   2       banana
1       world   3       database
1       apple   1       hello
1       apple   1       world
1       apple   1       apple
1       apple   1       fruit
1       apple   2       fruit
1       apple   2       banana
1       apple   3       database
1       fruit   1       hello
1       fruit   1       world
1       fruit   1       apple
1       fruit   1       fruit
1       fruit   2       fruit
1       fruit   2       banana
1       fruit   3       database
2       fruit   1       hello
2       fruit   1       world
2       fruit   1       apple
2       fruit   1       fruit
2       fruit   2       fruit
2       fruit   2       banana
2       fruit   3       database
2       banana  1       hello
2       banana  1       world
2       banana  1       apple
2       banana  1       fruit
2       banana  2       fruit
2       banana  2       banana
2       banana  3       database
3       database        1       hello
3       database        1       world
3       database        1       apple
3       database        1       fruit
3       database        2       fruit
3       database        2       banana
3       database        3       database


Now with comma instead of JOIN:

SELECT l1.textid, l1.word, l2.textid, l2.word
FROM sample AS l1, sample AS l2 
;

textid  word    textid_1        word_1
1       hello   1       hello
1       hello   1       hello
1       hello   1       hello
1       hello   1       hello
1       hello   1       hello
1       hello   1       hello
1       hello   1       hello
1       world   1       world
1       world   1       world
1       world   1       world
1       world   1       world
1       world   1       world
1       world   1       world
1       world   1       world
1       apple   1       apple
1       apple   1       apple
1       apple   1       apple
1       apple   1       apple
1       apple   1       apple
1       apple   1       apple
1       apple   1       apple
1       fruit   1       fruit
1       fruit   1       fruit
1       fruit   1       fruit
1       fruit   1       fruit
1       fruit   1       fruit
1       fruit   1       fruit
1       fruit   1       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       fruit   2       fruit
2       banana  2       banana
2       banana  2       banana
2       banana  2       banana
2       banana  2       banana
2       banana  2       banana
2       banana  2       banana
2       banana  2       banana
3       database        3       database
3       database        3       database
3       database        3       database
3       database        3       database
3       database        3       database
3       database        3       database
3       database        3       database

This looks like the SELECT statement is somehow outputting values from l1 
twice, instead of l1 and l2.

Is there some pragma or compile option which makes SQLite handle a comma join 
operator differently?

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

Reply via email to