On Wednesday, 9 October, 2019 12:01, Jens Alfke <j...@mooseyard.com> said:

>BETWEEN doesn't work well because it's inclusive, i.e. `BETWEEN 'foo' and
>'fop'` doesn't work because it matches 'fop'. Coming up with the upper
>end of a string prefix match is super annoying — `BETWEEN 'foo' and
>'foo\xff' only works until some wise guy adds the key `foo\xff` to the
>table, and is invalid UTF-8 anyway.

I don't think that the UTF-8 point is meaningful.  However, If *I* were in need 
of doing this I would use a construct that looks like this:

where (name between :prefix and (:prefix || char(255)) and substr(name, 1, 
length(:prefix)) collate nocase == :prefix)

where the "name between :prefix and (:prefix || char(255))" constrains the 
index search and "substr(name, 1, length(:prefix)) collate nocase == :prefix" 
constrains the resulting candidates.

(Replace all instances of "collate nocase" with the collation you want to use, 
omit entirely to use the default BINARY collation).

>sqlite
SQLite version 3.30.0 2019-10-09 16:25:22
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> create table nodes(name text not null collate nocase unique);
sqlite> insert into nodes values ('dangtalk');
sqlite> insert into nodes values ('dingdong');
sqlite> insert into nodes values ('dingwhit');
sqlite> insert into nodes values ('dongdong');
sqlite> .param init
sqlite> .param set :prefix 'DING'
sqlite> .eqp full
sqlite> select * from nodes where name between :prefix and (:prefix || 
char(255)) and substr(name,1,length(:prefix)) collate nocase == :prefix;
QUERY PLAN
`--SEARCH TABLE nodes USING COVERING INDEX sqlite_autoindex_nodes_1 (name>? AND 
name<?) (~15360 rows)
addr  opcode         p1    p2    p3    p4             p5  comment
----  -------------  ----  ----  ----  -------------  --  -------------
0     Init           0     24    0                    00  Start at 24
1     OpenRead       1     3     0     k(1,NOCASE)    00  root=3 iDb=0; 
sqlite_autoindex_nodes_1
2     ColumnsUsed    1     0     0     1              00
3     Explain        3     0     0     SEARCH TABLE nodes USING COVERING INDEX 
sqlite_autoindex_nodes_1 (name>? AND name<?) (~15360 rows)  00
4     Noop           0     0     0                    00  Begin WHERE-loop0: 
nodes
5     CursorHint     1     0     0     AND(expr,EQ(expr,expr))  00
6     Variable       1     1     0     :prefix        00  
r[1]=parameter(1,:prefix)
7     IsNull         1     22    0                    00  if r[1]==NULL goto 22
8     Affinity       1     1     0     B              00  affinity(r[1])
9     SeekGE         1     22    1     1              00  key=r[1]
10    Concat         3     2     1                    00  r[1]=r[2]+r[3]
11    IsNull         1     22    0                    00  if r[1]==NULL goto 22
12    Affinity       1     1     0     B              00  affinity(r[1])
13      IdxGT          1     22    1     1              00  key=r[1]
14      Column         1     0     5                    00  r[5]=nodes.name
15      Function0      6     5     4     substr(3)      03  r[4]=func(r[5..7])
16      Ne             2     21    4     (NOCASE)       50  if r[4]!=r[2] goto 
21
17      Noop           0     0     0                    00  Begin WHERE-core
18      Column         1     0     8                    00  r[8]=nodes.name
19      ResultRow      8     1     0                    00  output=r[8]
20      Noop           0     0     0                    00  End WHERE-core
21    Next           1     13    0                    00
22    Noop           0     0     0                    00  End WHERE-loop0: nodes
23    Halt           0     0     0                    00
24    Transaction    0     0     1     0              01  usesStmtJournal=0
25    Variable       1     2     0     :prefix        00  
r[2]=parameter(1,:prefix)
26    Integer        255   9     0                    00  r[9]=255
27    Function0      1     9     3     char(-1)       01  r[3]=func(r[9])
28    Integer        1     6     0                    00  r[6]=1
29    Variable       1     10    0     :prefix        00  
r[10]=parameter(1,:prefix)
30    Function0      1     10    7     length(1)      01  r[7]=func(r[10])
31    Goto           0     1     0                    00
dingdong
dingwhit

-- 
The fact that there's a Highway to Hell but only a Stairway to Heaven says a 
lot about anticipated traffic volume.



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

Reply via email to