Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Add an optional 5th parameter to the next_char() function that is the collating sequence to use for comparison. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9415db6ef255d27ca8473c17e65749a1 |
User & Date: | drh 2013-07-08 01:27:43.173 |
Context
2013-07-08
| ||
21:12 | Fix an adverse interaction between the IS NOT NULL optimization (available only with SQLITE_ENABLE_STAT3) and the transitive constraint processing. Fix for ticket [d805526eae253] (check-in: 3b30b75b34 user: drh tags: trunk) | |
01:27 | Add an optional 5th parameter to the next_char() function that is the collating sequence to use for comparison. (check-in: 9415db6ef2 user: drh tags: trunk) | |
2013-07-06
| ||
18:07 | Fixes for test cases running in the "mmap" permutation. (check-in: cdb97d41ab user: dan tags: trunk) | |
Changes
Changes to ext/misc/nextchar.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 2013-02-28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** | | | | | | > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* ** 2013-02-28 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ****************************************************************************** ** ** This file contains code to implement the next_char(A,T,F,W,C) SQL function. ** ** The next_char(A,T,F,W,C) function finds all valid "next" characters for ** string A given the vocabulary in T.F. If the W value exists and is a ** non-empty string, then it is an SQL expression that limits the entries ** in T.F that will be considered. If C exists and is a non-empty string, ** then it is the name of the collating sequence to use for comparison. If ** ** Only the first three arguments are required. If the C parameter is ** omitted or is NULL or is an empty string, then the default collating ** sequence of T.F is used for comparision. If the W parameter is omitted ** or is NULL or is an empty string, then no filtering of the output is ** done. ** ** The T.F column should be indexed using collation C or else this routine ** will be quite slow. ** ** For example, suppose an application has a dictionary like this: ** ** CREATE TABLE dictionary(word TEXT UNIQUE); ** ** Further suppose that for user keypad entry, it is desired to disable ** (gray out) keys that are not valid as the next character. If the |
︙ | ︙ | |||
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | int argc, sqlite3_value **argv ){ nextCharContext c; const unsigned char *zTable = sqlite3_value_text(argv[1]); const unsigned char *zField = sqlite3_value_text(argv[2]); const unsigned char *zWhere; char *zSql; int rc; memset(&c, 0, sizeof(c)); c.db = sqlite3_context_db_handle(context); c.zPrefix = sqlite3_value_text(argv[0]); c.nPrefix = sqlite3_value_bytes(argv[0]); if( zTable==0 || zField==0 || c.zPrefix==0 ) return; | > > > | | | | | > > > > > > | > > > | < < > > > > > > > | | | | | | | < > > > | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 | int argc, sqlite3_value **argv ){ nextCharContext c; const unsigned char *zTable = sqlite3_value_text(argv[1]); const unsigned char *zField = sqlite3_value_text(argv[2]); const unsigned char *zWhere; const unsigned char *zCollName; char *zWhereClause = 0; char *zColl = 0; char *zSql; int rc; memset(&c, 0, sizeof(c)); c.db = sqlite3_context_db_handle(context); c.zPrefix = sqlite3_value_text(argv[0]); c.nPrefix = sqlite3_value_bytes(argv[0]); if( zTable==0 || zField==0 || c.zPrefix==0 ) return; if( argc>=4 && (zWhere = sqlite3_value_text(argv[3]))!=0 && zWhere[0]!=0 ){ zWhereClause = sqlite3_mprintf("AND (%s)", zWhere); if( zWhereClause==0 ){ sqlite3_result_error_nomem(context); return; } }else{ zWhereClause = ""; } if( argc>=5 && (zCollName = sqlite3_value_text(argv[4]))!=0 && zCollName[0]!=0 ){ zColl = sqlite3_mprintf("collate \"%w\"", zCollName); if( zColl==0 ){ sqlite3_result_error_nomem(context); if( zWhereClause[0] ) sqlite3_free(zWhereClause); return; } }else{ zColl = ""; } zSql = sqlite3_mprintf( "SELECT \"%w\" FROM \"%w\"" " WHERE \"%w\">=(?1 || ?2) %s" " AND \"%w\"<=(?1 || char(1114111)) %s" /* 1114111 == 0x10ffff */ " %s" " ORDER BY 1 %s ASC LIMIT 1", zField, zTable, zField, zColl, zField, zColl, zWhereClause, zColl ); if( zWhereClause[0] ) sqlite3_free(zWhereClause); if( zColl[0] ) sqlite3_free(zColl); if( zSql==0 ){ sqlite3_result_error_nomem(context); return; } rc = sqlite3_prepare_v2(c.db, zSql, -1, &c.pStmt, 0); sqlite3_free(zSql); |
︙ | ︙ | |||
257 258 259 260 261 262 263 264 265 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0, nextCharFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } return rc; } | > > > > | 286 287 288 289 290 291 292 293 294 295 296 297 298 | (void)pzErrMsg; /* Unused parameter */ rc = sqlite3_create_function(db, "next_char", 3, SQLITE_UTF8, 0, nextCharFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 4, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "next_char", 5, SQLITE_UTF8, 0, nextCharFunc, 0, 0); } return rc; } |
Changes to test/spellfix.test.
︙ | ︙ | |||
100 101 102 103 104 105 106 107 108 109 110 111 112 113 | } {ae} do_execsql_test 1.13 { SELECT next_char('','vocab','w'); } {r} do_test 1.14 { catchsql {SELECT next_char('','xyzzy','a')} } {1 {no such table: xyzzy}} do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm'); SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5; } {psalm 4} | > > > > > > > > > > > > > > > > | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | } {ae} do_execsql_test 1.13 { SELECT next_char('','vocab','w'); } {r} do_test 1.14 { catchsql {SELECT next_char('','xyzzy','a')} } {1 {no such table: xyzzy}} do_execsql_test 1.20 { CREATE TABLE vocab2(w TEXT); CREATE INDEX vocab2w ON vocab2(w COLLATE nocase); INSERT INTO vocab2 VALUES('abc'), ('ABD'), ('aBe'), ('AbF'); SELECT next_char('ab', 'vocab2', 'w', null, 'nocase'); } {cDeF} do_execsql_test 1.21 { SELECT next_char('ab','vocab2','w',null,null); } {c} do_execsql_test 1.22 { SELECT next_char('AB','vocab2','w',null,'NOCASE'); } {cDeF} do_execsql_test 1.23 { SELECT next_char('ab','vocab2','w',null,'binary'); } {c} do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING spellfix1; INSERT INTO t2 (word, soundslike) VALUES('school', 'skuul'); INSERT INTO t2 (word, soundslike) VALUES('psalm', 'sarm'); SELECT word, matchlen FROM t2 WHERE word MATCH 'sar*' LIMIT 5; } {psalm 4} |
︙ | ︙ |