minor correction, char(255) should be x'ff' ... char(255) does not return the byte 0xff, but x'ff' is the byte 0xff ...
where (name between :prefix and (:prefix || x'ff') and substr(name, 1, length(:prefix)) collate nocase == :prefix) -- The fact that there's a Highway to Hell but only a Stairway to Heaven says a lot about anticipated traffic volume. >-----Original Message----- >From: sqlite-users <sqlite-users-boun...@mailinglists.sqlite.org> On >Behalf Of Keith Medcalf >Sent: Wednesday, 9 October, 2019 13:04 >To: SQLite mailing list <sqlite-users@mailinglists.sqlite.org> >Subject: Re: [sqlite] SELECT uses index with SUBSTR but UPDATE doesn't > > >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 _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users