From: dan Date: Mon, 14 Jan 2019 20:44:00 +0000 (+0000) Subject: Add scalar function "prefix_length()" to ext/misc/prefixes.c. X-Git-Tag: version-3.27.0~152 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9c039d9f2e8d0ed9645c7ea419e24f08a268fb95;p=thirdparty%2Fsqlite.git Add scalar function "prefix_length()" to ext/misc/prefixes.c. FossilOrigin-Name: 0bf1550507d9d3c8a41f8a50db3a59bf808f0a4e24637dc0905d35579305eca7 --- diff --git a/Makefile.in b/Makefile.in index 4eec340b0f..219fc4f0ca 100644 --- a/Makefile.in +++ b/Makefile.in @@ -452,6 +452,7 @@ TESTSRC += \ $(TOP)/ext/misc/nextchar.c \ $(TOP)/ext/misc/normalize.c \ $(TOP)/ext/misc/percentile.c \ + $(TOP)/ext/misc/prefixes.c \ $(TOP)/ext/misc/regexp.c \ $(TOP)/ext/misc/remember.c \ $(TOP)/ext/misc/series.c \ diff --git a/Makefile.msc b/Makefile.msc index 179215ecf4..a4f0e1ef64 100644 --- a/Makefile.msc +++ b/Makefile.msc @@ -1527,6 +1527,7 @@ TESTEXT = \ $(TOP)\ext\misc\nextchar.c \ $(TOP)\ext\misc\normalize.c \ $(TOP)\ext\misc\percentile.c \ + $(TOP)\ext\misc\prefixes.c \ $(TOP)\ext\misc\regexp.c \ $(TOP)\ext\misc\remember.c \ $(TOP)\ext\misc\series.c \ diff --git a/ext/misc/prefixes.c b/ext/misc/prefixes.c index b74cb61a67..a2f5b3289d 100644 --- a/ext/misc/prefixes.c +++ b/ext/misc/prefixes.c @@ -249,6 +249,53 @@ static sqlite3_module prefixesModule = { /* xShadowName */ 0 }; +/* +** This is a copy of the SQLITE_SKIP_UTF8(zIn) macro in sqliteInt.h. +** +** Assuming zIn points to the first byte of a UTF-8 character, +** advance zIn to point to the first byte of the next UTF-8 character. +*/ +#define PREFIX_SKIP_UTF8(zIn) { \ + if( (*(zIn++))>=0xc0 ){ \ + while( (*zIn & 0xc0)==0x80 ){ zIn++; } \ + } \ +} + +/* +** Implementation of function prefix_length(). This function accepts two +** strings as arguments and returns the length in characters (not bytes), +** of the longest prefix shared by the two strings. For example: +** +** prefix_length('abcdxxx', 'abcyy') == 3 +** prefix_length('abcdxxx', 'bcyyy') == 0 +** prefix_length('abcdxxx', 'ab') == 2 +** prefix_length('ab', 'abcd') == 2 +** +** This function assumes the input is well-formed utf-8. If it is not, +** it is possible for this function to return -1. +*/ +static void prefixLengthFunc( + sqlite3_context *ctx, + int nVal, + sqlite3_value **apVal +){ + int nByte; /* Number of bytes to compare */ + int nRet = 0; /* Return value */ + const unsigned char *zL = sqlite3_value_text(apVal[0]); + const unsigned char *zR = sqlite3_value_text(apVal[1]); + int nL = sqlite3_value_bytes(apVal[0]); + int nR = sqlite3_value_bytes(apVal[1]); + int i; + + nByte = (nL > nR ? nL : nR); + for(i=0; i],\sgot:\s[]". -D 2019-01-14T19:13:30.596 +C Add\sscalar\sfunction\s"prefix_length()"\sto\sext/misc/prefixes.c. +D 2019-01-14T20:44:00.309 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea -F Makefile.in 45a3fef4d325ac0220c2172aeec4e4321da351f073f3b8e8ddea655f49ef6f2b +F Makefile.in 2a9d0331ab57c68173a4c2fe9046fe89c4d916a888e04dd7a2d36958c2bff777 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 -F Makefile.msc 3c4c7e94419ff28cb68850188c9d153b343aed4c5ebed5965426232ed67ff9d9 +F Makefile.msc 54c5921b0c65c49ea8fb5010e763c181526d6cdc1109c7ab7115c4f5bb71e13c F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee F VERSION 453e2f4529ca208196d5567db28d549d7151f79efd33f6e6cfe6e613e583a0be F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50 @@ -295,7 +295,7 @@ F ext/misc/mmapwarm.c 8c5fe90d807a23e44a8b93e96e8b812b19b300d5fd8c1d40a4fd1d8224 F ext/misc/nextchar.c 279f80fe8ef5ba413242e2704e246503ac601f005eefb180d19e6c920338a0ba F ext/misc/normalize.c b4290464f542bae7a97b43f15bd197949b833ffd668b7c313631bd5d4610212c F ext/misc/percentile.c a6a1594c104da2d0ceab38fe609eb2f65529272377827f6f8a2b5c9fa6119e7e -F ext/misc/prefixes.c ac95cf723927b9e4b6f2b45eec743986259e3c2618f92ffa9fd780e13c75f70e +F ext/misc/prefixes.c 1eb85b7b64b8adf5cbb18a72c51a8f2910a7bc0fd5fbc81a9213ba4af2d51811 F ext/misc/regexp.c 79345bf03496155a640ee0300d3307296761cebb5e115b4e342cc2fb5861ec10 F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c F ext/misc/rot13.c 540a169cb0d74f15522a8930b0cccdcb37a4fd071d219a5a083a319fc6e8db77 @@ -435,7 +435,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 -F main.mk 8456b6b4a5ecdb7b6b59283236b3be6393bc7eed6cbda3bcf1d552e1a63e03ff +F main.mk 20d344434cec07680fb7d7e66f6401b0f3bf915277018ac93d229b8f73678216 F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504 @@ -523,7 +523,7 @@ F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6 F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34 F src/tclsqlite.c e72862a271348d779672b45a730c33fd0c535e630ff927e8ce4a0c908d1d28c6 -F src/test1.c f78dcd39d5cad63d33306bb963354f976007968bc95c45bc9fdfaeb2e1ec0eae +F src/test1.c 64cdc914a77102e008dfae7adaa4ded54c2d4953d1464ea8709805a2aab755eb F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5 F src/test3.c 61798bb0d38b915067a8c8e03f5a534b431181f802659a6616f9b4ff7d872644 F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6 @@ -1199,6 +1199,7 @@ F test/pragma3.test 8300aa9c63cff1027006ca34bf413a148abbd6dcd471fa9a1ded322fe18c F test/pragma4.test 52d8186f9e8d09b87189432cdd401dfa66d0b32445e837fa19046c8ae7621b0e F test/pragma5.test 824ce6ced5d6b7ec71abe37fc6005ff836fe39d638273dc5192b39864b9ee983 F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8 +F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9 F test/printf.test a3e559bc9d922e7fe44e9d05c6965fee34fe3bc28300a4248c6a063425246ffd F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb @@ -1799,7 +1800,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f0fd2163fc23a555ef03af43294a14fcabae6921f52e64c979286c745b4f6218 -R 238e457d65f075aa5a49baa7e28c3f0b +P 11b8a4cba747ca214fe3506caa3b711c87be4d55412754e673cc0603afefb086 +R 32ab1d3eba68373a1b0b1f4de28ca909 U dan -Z 9ed1f14f70bf3f4d25df868a0ff2534c +Z fb1a50e31aa836559e45fed0b6204d9c diff --git a/manifest.uuid b/manifest.uuid index a9f6a5e408..e315bc4b42 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -11b8a4cba747ca214fe3506caa3b711c87be4d55412754e673cc0603afefb086 \ No newline at end of file +0bf1550507d9d3c8a41f8a50db3a59bf808f0a4e24637dc0905d35579305eca7 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index def9c7e2fd..1fd48fec6b 100644 --- a/src/test1.c +++ b/src/test1.c @@ -7141,6 +7141,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*); + extern int sqlite3_prefixes_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_remember_init(sqlite3*,char**,const sqlite3_api_routines*); extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*); @@ -7166,6 +7167,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd( { "ieee754", sqlite3_ieee_init }, { "nextchar", sqlite3_nextchar_init }, { "percentile", sqlite3_percentile_init }, + { "prefixes", sqlite3_prefixes_init }, { "regexp", sqlite3_regexp_init }, { "remember", sqlite3_remember_init }, { "series", sqlite3_series_init }, diff --git a/test/prefixes.test b/test/prefixes.test new file mode 100644 index 0000000000..2080905805 --- /dev/null +++ b/test/prefixes.test @@ -0,0 +1,88 @@ +# 2018-01-15 +# +# 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 implements regression tests for SQLite library. The +# focus of this file is prefixes.c extension +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl +set testprefix unionvtab + +ifcapable !vtab { + finish_test + return +} + +load_static_extension db prefixes + +foreach {tn zLeft zRight expected} { + 1 abcdxxx abcyy 3 + 2 abcdxxx bcyyy 0 + 3 abcdxxx ab 2 + 4 ab abcd 2 + + 5 "xyz\u1234xz" "xyz\u1234xy" 5 + 6 "xyz\u1234" "xyz\u1234xy" 4 + 7 "xyz\u1234" "xyz\u1234" 4 + 8 "xyz\u1234xy" "xyz\u1234" 4 + 9 "xyz\u1234xy" "xyz\u1233" 3 + 10 "xyz\u1234xy" "xyz\u1235" 3 +} { + do_execsql_test 1.$tn { SELECT prefix_length($zLeft, $zRight) } $expected +} + + +do_execsql_test 2.0 { + CREATE TABLE t1(k TEXT UNIQUE, v INTEGER); + INSERT INTO t1 VALUES + ('aback', 1), + ('abaft', 2), + ('abandon', 3), + ('abandoned', 4), + ('abandoning', 5), + ('abandonment', 6), + ('abandons', 7), + ('abase', 8), + ('abased', 9), + ('abasement', 10), + ('abasements', 11), + ('abases', 12), + ('abash', 13), + ('abashed', 14), + ('abashes', 15), + ('abashing', 16), + ('abasing', 17), + ('abate', 18), + ('abated', 19), + ('abatement', 20), + ('abatements', 21); +} + +foreach {tn INPUT expected} { + 1 abatementt abatement + 2 abashet abash + 3 abandonio abandon + 4 abasemenu abase +} { + do_execsql_test 2.$tn { + WITH finder(str) AS ( + SELECT (SELECT max(k) FROM t1 WHERE k<=$INPUT) + UNION ALL + SELECT ( + SELECT max(k) FROM t1 + WHERE k<=substr($INPUT, 1, prefix_length(finder.str, $INPUT)) + ) FROM finder WHERE length(finder.str)>0 + ) + SELECT str FROM finder WHERE length(str)==prefix_length(str, $INPUT) LIMIT 1 + } $expected +} + +finish_test