Add scalar function "prefix_length()" to ext/misc/prefixes.c.

FossilOrigin-Name: 0bf1550507d9d3c8a41f8a50db3a59bf808f0a4e24637dc0905d35579305eca7
This commit is contained in:
dan
2019-01-14 20:44:00 +00:00
parent 9274ad898f
commit 9c039d9f2e
8 changed files with 157 additions and 11 deletions
+1
View File
@@ -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 \
+1
View File
@@ -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 \
+52
View File
@@ -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<nByte; i++){
if( zL[i]!=zR[i] ) break;
if( (zL[i] & 0xC0)!=0x80 ) nRet++;
}
if( (zL[i] & 0xC0)==0x80 ) nRet--;
sqlite3_result_int(ctx, nRet);
}
#ifdef _WIN32
__declspec(dllexport)
@@ -261,5 +308,10 @@ int sqlite3_prefixes_init(
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
rc = sqlite3_create_module(db, "prefixes", &prefixesModule, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "prefix_length", 2, SQLITE_UTF8, 0, prefixLengthFunc, 0, 0
);
}
return rc;
}
+1
View File
@@ -369,6 +369,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 \
+11 -10
View File
@@ -1,10 +1,10 @@
C Fix\sa\sproblem\scausing\ssome\sTcl\stest\scases\sto\sfail\swith\serrors\slike\s"expected:\s[<multiline-whitespace>],\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
+1 -1
View File
@@ -1 +1 @@
11b8a4cba747ca214fe3506caa3b711c87be4d55412754e673cc0603afefb086
0bf1550507d9d3c8a41f8a50db3a59bf808f0a4e24637dc0905d35579305eca7
+2
View File
@@ -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 },
+88
View File
@@ -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