Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 68dc8151e0 | |||
| 9b9fc74f2e | |||
| 57c58b4de8 | |||
| ec778d2724 | |||
| 4d7f335e8b | |||
| a1c8151bab | |||
| e482fde6ee | |||
| d323a3a515 |
@@ -372,6 +372,8 @@ static int qpvtabBestIndex(
|
||||
pIdxInfo->aOrderBy[i].desc
|
||||
);
|
||||
}
|
||||
sqlite3_str_appendf(pStr, "sqlite3_vtab_distinct,%d,,,,\n",
|
||||
sqlite3_vtab_distinct(pIdxInfo));
|
||||
sqlite3_str_appendf(pStr, "idxFlags,%d,,,,\n", pIdxInfo->idxFlags);
|
||||
sqlite3_str_appendf(pStr, "colUsed,%d,,,,\n", (int)pIdxInfo->colUsed);
|
||||
pIdxInfo->estimatedCost = (double)10;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Add\srequirements\smarks\sand\stuning.
|
||||
D 2022-01-21T00:38:49.617
|
||||
C Bring\ssqlite3_vtab_distinct()\sup\sto\sspec\sso\sthat\sit\sworks\sas\sdescribed\sin\sthe\ndocumentation.
|
||||
D 2022-01-22T20:45:57.210
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@@ -316,7 +316,7 @@ F ext/misc/noop.c 81efe4cad9ec740e64388b14281cb983e6e2c223fed43eb77ab3e34946e0c1
|
||||
F ext/misc/normalize.c bd84355c118e297522aba74de34a4fd286fc775524e0499b14473918d09ea61f
|
||||
F ext/misc/percentile.c b9086e223d583bdaf8cb73c98a6539d501a2fc4282654adbfea576453d82e691
|
||||
F ext/misc/prefixes.c 0f4f8cff5aebc00a7e3ac4021fd59cfe1a8e17c800ceaf592859ecb9cbc38196
|
||||
F ext/misc/qpvtab.c d40b07a8c341d16629010c3e8d8801f1477f70d6257e052973a8ddf14c07cd8d
|
||||
F ext/misc/qpvtab.c c662fa0a452ad286e49b6c83ac917600656b2eb47d2225ff6185c56bf80cf8d2
|
||||
F ext/misc/regexp.c b267fd05ff8d38b22f4c2809d7b7a2c61d522e9faf2feb928dbb9662e4a3a386
|
||||
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
|
||||
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
|
||||
@@ -499,7 +499,7 @@ F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f
|
||||
F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1
|
||||
F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191
|
||||
F src/date.c e25773f06a8f9043bfa1e5fa0bee93483c41933adfff0891752f00eadd12ab1c
|
||||
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
|
||||
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
|
||||
F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c
|
||||
@@ -515,7 +515,7 @@ F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743
|
||||
F src/json.c 78fdec9af3a8bfb5ae685707b2701276fec1942b8f5f26689b2701debe32bcd2
|
||||
F src/legacy.c d7874bc885906868cd51e6c2156698f2754f02d9eee1bae2d687323c3ca8e5aa
|
||||
F src/loadext.c 9a693eb89575af5d54b025c1e927b2ea8114bbeee3db346e8abc81676dd82160
|
||||
F src/loadext.c 657534339585ac234839e5187aa51d8802f292e0771c4f874b3af1f1223f81e2
|
||||
F src/main.c 2b6b0dbfeb14d4bb57e368604b0736b2aa42b51b00339d399b01d6b1fc9b4960
|
||||
F src/malloc.c ef796bcc0e81d845d59a469f1cf235056caf9024172fd524e32136e65593647b
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
@@ -554,9 +554,9 @@ F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c ab5717255420972e69b9b9ce4d1c4730fe82cfbdc14b7743e389a8bdb79ca027
|
||||
F src/shell.c.in 4690f216dc4da0c104a8fd9f9e12bec0483242e630324aa7a3ccd155922e346e
|
||||
F src/sqlite.h.in 67e49a50bb29e3af86d2b3606af6b3fe20a0d09cf326cc574d632d878c0696d6
|
||||
F src/sqlite.h.in 31c2c8d737814369bd3b71f3849c4a97ef7ede0aa3ce976ecb11632fa5f1f863
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 234b5ff5c20512a116b14d6d08e23caeb68667749f8a94117779a9d38afc7e5c
|
||||
F src/sqlite3ext.h 5d54cf13d3406d8eb65d921a0d3c349de6126b732e695e79ecd4830ce86b4f8a
|
||||
F src/sqliteInt.h 21a31abf60222f50c1d654cdc27ad9d4040249f0341129dd8286b8b5b32bcd30
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
@@ -639,9 +639,9 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d
|
||||
F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a
|
||||
F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b
|
||||
F src/where.c 6b4cd84869dafc250d2b0f47a2c190759904a4bb6a31fc930bc8e6a9fd9a8d77
|
||||
F src/whereInt.h 91865afa4a3540bb3bd643619acc56fbceff7defeb8f249b8e157fd5325d88be
|
||||
F src/wherecode.c 6a594ed25bfbeb60d455868b7be62637575e4f1949152de4336e4825e0c54ba6
|
||||
F src/where.c 9824d15f2a92cbe4d6566e2a97fa4466ce6297e68693322e64281db5e942fa92
|
||||
F src/whereInt.h 8a215acde0f833a4dea3d30a7bbed9f48b4b547b5d5e34cd02acee366476ab80
|
||||
F src/wherecode.c a0a5138b28550dd95916435283c507aa6bf24607ef38a0a18011e6626684330a
|
||||
F src/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3
|
||||
F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
@@ -868,8 +868,8 @@ F test/e_createtable.test 04c50b7fe41c12ed9cd88fbbc09b4900bcfc66f98ad198874fc993
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 235c610f8bf8ec44513e222b9085c7e49fad65ad0c1975ac2577109dd06fd8fa
|
||||
F test/e_dropview.test 74e405df7fa0f762e0c9445b166fe03955856532e2bb234c372f7c51228d75e7
|
||||
F test/e_expr.test e164550b9f8fd9c130283d1eae692dff9e2ba67f4dbd35f7325021f5d4b8851c
|
||||
F test/e_fkey.test ee321dbca3c53204da46cb40b8ec80192e995035f9ea26576ddcd842b1f0877f
|
||||
F test/e_expr.test bc6aa5906ba967587525bc746ea403011557cf6d8e4fc9efb1fab5dae7fb4fd6
|
||||
F test/e_fkey.test feeba6238aeff9d809fb6236b351da8df4ae9bda89e088e54526b31a0cbfeec5
|
||||
F test/e_fts3.test 17ba7c373aba4d4f5696ba147ee23fd1a1ef70782af050e03e262ca187c5ee07
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 2b0e29344497d9a8a999453a003cb476b6b1d2eef2d6c120f83c2d3a429f3164
|
||||
@@ -1292,7 +1292,7 @@ F test/pragma5.test 7b33fc43e2e41abf17f35fb73f71b49671a380ea92a6c94b6ce530a25f8d
|
||||
F test/pragmafault.test 275edaf3161771d37de60e5c2b412627ac94cef11739236bec12ed1258b240f8
|
||||
F test/prefixes.test b524a1c44bffec225b9aec98bd728480352aa8532ac4c15771fb85e8beef65d9
|
||||
F test/printf.test 390d0d7fcffc3c4ea3c1bb4cbb267444e32b33b048ae21895f23a291844fe1da
|
||||
F test/printf2.test 30b5dd0b4b992dc5626496846ecce17ff592cacbcb11c3e589f3ac4d7e129dae
|
||||
F test/printf2.test 3f55c1871a5a65507416076f6eb97e738d5210aeda7595a74ee895f2224cce60
|
||||
F test/progress.test ebab27f670bd0d4eb9d20d49cef96e68141d92fb
|
||||
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
|
||||
F test/pushdown.test 5e72c51c5e33253ed639ccee1e01ce62d62b6eee5ca893cd82334e4ee7b1d7fc
|
||||
@@ -1322,7 +1322,7 @@ F test/round1.test 768018b04522ca420b1aba8a24bd76091d269f3bce3902af3ec6ebcee41ab
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test e29025be95baf6b32f0d5edef59a7633028325896a98f1caa8019559ca910350
|
||||
F test/rowvalue.test 37effea4dd83555ea969a9461dfcffb25e6731a5db7c388e232410999c100853
|
||||
F test/rowvalue.test 02214016f747854ef636e64ff204778649937aa801ca78e2495a960f8e0d509d
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
|
||||
F test/rowvalue4.test 441e7e366ac6d939a3a95a574031c56ec2a854077a91d66eee5ff1d86cb5be58
|
||||
@@ -1724,6 +1724,7 @@ F test/vtabK.test 13293177528fada1235c0112db0d187d754af1355c5a39371abd365104e3af
|
||||
F test/vtab_alter.test 736e66fb5ec7b4fee58229aa3ada2f27ec58bc58c00edae4836890c3784c6783
|
||||
F test/vtab_err.test dcc8b7b9cb67522b3fe7a272c73856829dae4ab7fdb30399aea1b6981bda2b65
|
||||
F test/vtab_shared.test 5253bff2355a9a3f014c15337da7e177ab0ef8ad
|
||||
F test/vtabdistinct.test 7688f0889358f849fd60bbfde1ded38b014b18066076d4bfbb75395804dfe072
|
||||
F test/vtabdrop.test 65d4cf6722972e5499bdaf0c0d70ee3b8133944a4e4bc31862563f32a7edca12
|
||||
F test/vtabrhs1.test c138346be341916ecc9d918dcfc2657d27bce211a350a82b01d62d224b167b56
|
||||
F test/wal.test b7cc6984709f54afbf8441747ced1f646af120bf0c1b1d847bfa39306fbea089
|
||||
@@ -1940,8 +1941,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 577d3d66558368c34acab8a9e552957cf3fa054c348f1383a9121de6e8b281b7
|
||||
R 90012b52ae4dda5b0e0f59cd4c524b70
|
||||
P 7af03f02940b5380ee7375672ca8d0ff68c5f741d0ea206911631f3eb5a78555
|
||||
R 8c92b45cd50ac9ababc3056da5861966
|
||||
U drh
|
||||
Z 0ca7e1064e9e25edf7c6ed09bdf60dba
|
||||
Z 0f40ebbc8d49180e2de4a825f9a960d1
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
ac951490fd7d5864fe422a80ee8557478e823e79461bec2ee538f57b6733eb5a
|
||||
4289edf3c5e32a05b51f232020099b33f6f5e79b0ceca2b96baf1186168d9af6
|
||||
+5
-2
@@ -658,7 +658,8 @@ static int parseModifier(
|
||||
sqlite3_context *pCtx, /* Function context */
|
||||
const char *z, /* The text of the modifier */
|
||||
int n, /* Length of zMod in bytes */
|
||||
DateTime *p /* The date/time value to be modified */
|
||||
DateTime *p, /* The date/time value to be modified */
|
||||
int idx /* Parameter index of the modifier */
|
||||
){
|
||||
int rc = 1;
|
||||
double r;
|
||||
@@ -671,6 +672,7 @@ static int parseModifier(
|
||||
** a unix timestamp, depending on its magnitude.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "auto")==0 ){
|
||||
if( idx>1 ) return 1; /* IMP: R-33611-57934 */
|
||||
if( !p->rawS || p->validJD ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
@@ -695,6 +697,7 @@ static int parseModifier(
|
||||
** SQLite (0..5373484.5) then the result will be NULL.
|
||||
*/
|
||||
if( sqlite3_stricmp(z, "julianday")==0 ){
|
||||
if( idx>1 ) return 1;
|
||||
if( p->validJD && p->rawS ){
|
||||
rc = 0;
|
||||
p->rawS = 0;
|
||||
@@ -938,7 +941,7 @@ static int isDate(
|
||||
for(i=1; i<argc; i++){
|
||||
z = sqlite3_value_text(argv[i]);
|
||||
n = sqlite3_value_bytes(argv[i]);
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p) ) return 1;
|
||||
if( z==0 || parseModifier(context, (char*)z, n, p, i) ) return 1;
|
||||
}
|
||||
computeJD(p);
|
||||
if( p->isError || !validJulianDay(p->iJD) ) return 1;
|
||||
|
||||
@@ -488,6 +488,7 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
/* Version 3.38.0 and later */
|
||||
sqlite3_error_offset,
|
||||
sqlite3_vtab_rhs_value,
|
||||
sqlite3_vtab_distinct,
|
||||
};
|
||||
|
||||
/* True if x is the directory separator character
|
||||
|
||||
+69
-3
@@ -9471,13 +9471,14 @@ int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine The Collation For a Virtual Table Constraint
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This function may only be called from within a call to the [xBestIndex]
|
||||
** method of a [virtual table]. This function returns a pointer to a string
|
||||
** that is the name of the appropriate collation sequence to use for text
|
||||
** comparisons on the constraint identified by its arguments.
|
||||
**
|
||||
** The first argument must be the pointer to the sqlite3_index_info object
|
||||
** The first argument must be the pointer to the [sqlite3_index_info] object
|
||||
** that is the first parameter to the xBestIndex() method. The second argument
|
||||
** must be an index into the aConstraint[] array belonging to the
|
||||
** sqlite3_index_info structure passed to xBestIndex.
|
||||
@@ -9485,7 +9486,7 @@ int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
** Important:
|
||||
** The first parameter must be the same pointer that is passed into the
|
||||
** xBestMethod() method. The first parameter may not be a pointer to a
|
||||
** different sqlite3_index_info object, even an exact copy.
|
||||
** different [sqlite3_index_info] object, even an exact copy.
|
||||
**
|
||||
** The return value is computed as follows:
|
||||
**
|
||||
@@ -9503,6 +9504,71 @@ int sqlite3_vtab_nochange(sqlite3_context*);
|
||||
*/
|
||||
SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Determine if a virtual table query is DISTINCT
|
||||
** METHOD: sqlite3_index_info
|
||||
**
|
||||
** This API may only be used from within an xBestIndex() callback. The
|
||||
** results of calling it from outside of an xBestIndex() callback are
|
||||
** undefined and probably harmful.
|
||||
**
|
||||
** ^The sqlite3_vtab_distinct() returns an integer that is either 0, 1, or
|
||||
** 2. The integer returned by sqlite3_vtab_distinct() gives the virtual table
|
||||
** additional information about how the query planner wants the output to be
|
||||
** ordered. As long as the virtual table can meet the ordering requirements
|
||||
** of the query planner, it may set the "orderByConsumed" flag.
|
||||
**
|
||||
** <ol><li value="0"><p>
|
||||
** ^If the sqlite3_vtab_distinct() interface returns 0, that means
|
||||
** that the query planner needs the virtual table to return all rows in the
|
||||
** sort order defined by the "nOrderBy" and "aOrderBy" fields of the
|
||||
** [sqlite3_index_info] object. This is the default expectation. If the
|
||||
** virtual table outputs all rows in sorted order, then it is always safe for
|
||||
** the xBestIndex method to set the "orderByConsumed" flag, regardless of
|
||||
** what the return value from sqlite3_vtab_distinct().
|
||||
** <li value="1"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 1, that means
|
||||
** that the query planner does not need the rows to be returned in sorted order
|
||||
** as long as all rows with the same values in all columns identified by the
|
||||
** "aOrderBy" field are adjacent.)^ This mode is used when the query planner
|
||||
** is doing a GROUP BY.
|
||||
** <li value="2"><p>
|
||||
** ^(If the sqlite3_vtab_distinct() interface returns 2, that means
|
||||
** that the query planner does not need the rows returned in any particular
|
||||
** order, as long as rows with the same values in all "aOrderBy" columns
|
||||
** are adjacent.)^ ^(Furthermore, only a single row for each particular
|
||||
** combination of values in the columns identified by the "aOrderBy" field
|
||||
** needs to be returned.)^ ^It is ok always for two or more rows with the same
|
||||
** values in all "aOrderBy" columns to be returned, as long as all such rows
|
||||
** are adjacent. ^The virtual table may, if it chooses, omit extra rows
|
||||
** that have the same value for all columns identified by "aOrderBy".
|
||||
** ^However omitting the extra rows is optional.
|
||||
** This mode is used for a DISTINCT query.
|
||||
** </ol>
|
||||
**
|
||||
** ^For the purposes of comparing virtual table output values to see if the
|
||||
** values are same value for sorting purposes, two NULL values are considered
|
||||
** to be the same. In other words, the comparison operator is "IS"
|
||||
** (or "IS NOT DISTINCT FROM") and not "==".
|
||||
**
|
||||
** If a virtual table implementation is unable to meet the requirements
|
||||
** specified above, then it must not set the "orderByConsumed" flag in the
|
||||
** [sqlite3_index_info] object or an incorrect answer may result.
|
||||
**
|
||||
** ^A virtual table implementation is always free to return rows in any order
|
||||
** it wants, as long as the "orderByConsumed" flag is not set. ^When the
|
||||
** the "orderByConsumed" flag is unset, the query planner will add extra
|
||||
** [bytecode] to ensure that the final results returned by the SQL query are
|
||||
** ordered correctly. The use of the "orderByConsumed" flag and the
|
||||
** sqlite3_vtab_distinct() interface is merely an optimization. ^Careful
|
||||
** use of the sqlite3_vtab_distinct() interface and the "orderByConsumed"
|
||||
** flag might help queries against a virtual table to run faster. Being
|
||||
** overly aggressive and setting the "orderByConsumed" flag when it is not
|
||||
** valid to do so, on the other hand, might cause SQLite to return incorrect
|
||||
** results.
|
||||
*/
|
||||
int sqlite3_vtab_distinct(sqlite3_index_info*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Constraint values in xBestIndex()
|
||||
** METHOD: sqlite3_index_info
|
||||
@@ -9513,7 +9579,7 @@ SQLITE_EXPERIMENTAL const char *sqlite3_vtab_collation(sqlite3_index_info*,int);
|
||||
**
|
||||
** ^When the sqlite3_vtab_rhs_value(P,J,V) interface is invoked from within
|
||||
** the [xBestIndex] method of a [virtual table] implementation, with P being
|
||||
** a copy of the sqlite3_index_info object pointer passed into xBestIndex and
|
||||
** a copy of the [sqlite3_index_info] object pointer passed into xBestIndex and
|
||||
** J being a 0-based index into P->aConstraint[], then this routine
|
||||
** attempts to set *V to be the value on the right-hand side of
|
||||
** that constraint if the right-hand side is a known constant. ^If the
|
||||
|
||||
@@ -347,6 +347,7 @@ struct sqlite3_api_routines {
|
||||
/* Version 3.38.0 and later */
|
||||
int (*error_offset)(sqlite3*);
|
||||
int (*vtab_rhs_value)(sqlite3_index_info*,int,sqlite3_value**);
|
||||
int (*vtab_distinct)(sqlite3_index_info*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -661,6 +662,7 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
/* Version 3.38.0 and later */
|
||||
#define sqlite3_error_offset sqlite3_api->error_offset
|
||||
#define sqlite3_vtab_rhs_value sqlite3_api->vtab_rhs_value
|
||||
#define sqlite3_vtab_distinct sqlite3_api->vtab_distinct
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+24
-8
@@ -32,6 +32,7 @@ typedef struct HiddenIndexInfo HiddenIndexInfo;
|
||||
struct HiddenIndexInfo {
|
||||
WhereClause *pWC; /* The Where clause being analyzed */
|
||||
Parse *pParse; /* The parsing context */
|
||||
int eDistinct; /* Value to return from sqlite3_vtab_distinct() */
|
||||
sqlite3_value *aRhs[1]; /* RHS values for constraints. MUST BE LAST
|
||||
** because extra space is allocated to hold up
|
||||
** to nTerm such values */
|
||||
@@ -1101,15 +1102,15 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
|
||||
** by passing the pointer returned by this function to freeIndexInfo().
|
||||
*/
|
||||
static sqlite3_index_info *allocateIndexInfo(
|
||||
Parse *pParse, /* The parsing context */
|
||||
WhereInfo *pWInfo, /* The WHERE clause */
|
||||
WhereClause *pWC, /* The WHERE clause being analyzed */
|
||||
Bitmask mUnusable, /* Ignore terms with these prereqs */
|
||||
SrcItem *pSrc, /* The FROM clause term that is the vtab */
|
||||
ExprList *pOrderBy, /* The ORDER BY clause */
|
||||
u16 *pmNoOmit /* Mask of terms not to omit */
|
||||
){
|
||||
int i, j;
|
||||
int nTerm;
|
||||
Parse *pParse = pWInfo->pParse;
|
||||
struct sqlite3_index_constraint *pIdxCons;
|
||||
struct sqlite3_index_orderby *pIdxOrderBy;
|
||||
struct sqlite3_index_constraint_usage *pUsage;
|
||||
@@ -1119,7 +1120,9 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
sqlite3_index_info *pIdxInfo;
|
||||
u16 mNoOmit = 0;
|
||||
const Table *pTab;
|
||||
|
||||
int eDistinct = 0;
|
||||
ExprList *pOrderBy = pWInfo->pOrderBy;
|
||||
|
||||
assert( pSrc!=0 );
|
||||
pTab = pSrc->pTab;
|
||||
assert( pTab!=0 );
|
||||
@@ -1203,6 +1206,9 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
}
|
||||
if( i==n){
|
||||
nOrderBy = n;
|
||||
if( (pWInfo->wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY)) ){
|
||||
eDistinct = 1 + ((pWInfo->wctrlFlags & WHERE_DISTINCTBY)!=0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1225,6 +1231,7 @@ static sqlite3_index_info *allocateIndexInfo(
|
||||
pIdxInfo->aConstraintUsage = pUsage;
|
||||
pHidden->pWC = pWC;
|
||||
pHidden->pParse = pParse;
|
||||
pHidden->eDistinct = eDistinct;
|
||||
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||
u16 op;
|
||||
if( (pTerm->wtFlags & TERM_OK)==0 ) continue;
|
||||
@@ -3684,13 +3691,25 @@ int sqlite3_vtab_rhs_value(
|
||||
}
|
||||
*ppVal = pVal;
|
||||
|
||||
if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-60459-24801 */
|
||||
if( rc==SQLITE_OK && pVal==0 ){ /* IMP: R-19933-32160 */
|
||||
rc = SQLITE_NOTFOUND; /* IMP: R-36424-56542 */
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return true if ORDER BY clause may be handled as DISTINCT.
|
||||
*/
|
||||
int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){
|
||||
HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1];
|
||||
assert( pHidden->eDistinct==0
|
||||
|| pHidden->eDistinct==1
|
||||
|| pHidden->eDistinct==2 );
|
||||
return pHidden->eDistinct;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add all WhereLoop objects for a table of the join identified by
|
||||
** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table.
|
||||
@@ -3740,8 +3759,7 @@ static int whereLoopAddVirtual(
|
||||
pNew = pBuilder->pNew;
|
||||
pSrc = &pWInfo->pTabList->a[pNew->iTab];
|
||||
assert( IsVirtual(pSrc->pTab) );
|
||||
p = allocateIndexInfo(pParse, pWC, mUnusable, pSrc, pBuilder->pOrderBy,
|
||||
&mNoOmit);
|
||||
p = allocateIndexInfo(pWInfo, pWC, mUnusable, pSrc, &mNoOmit);
|
||||
if( p==0 ) return SQLITE_NOMEM_BKPT;
|
||||
pNew->rSetup = 0;
|
||||
pNew->wsFlags = WHERE_VIRTUALTABLE;
|
||||
@@ -3873,7 +3891,6 @@ static int whereLoopAddOr(
|
||||
int i, j;
|
||||
|
||||
sSubBuild = *pBuilder;
|
||||
sSubBuild.pOrderBy = 0;
|
||||
sSubBuild.pOrSet = &sCur;
|
||||
|
||||
WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
|
||||
@@ -5265,7 +5282,6 @@ WhereInfo *sqlite3WhereBegin(
|
||||
/* An ORDER/GROUP BY clause of more than 63 terms cannot be optimized */
|
||||
testcase( pOrderBy && pOrderBy->nExpr==BMS-1 );
|
||||
if( pOrderBy && pOrderBy->nExpr>=BMS ) pOrderBy = 0;
|
||||
sWLB.pOrderBy = pOrderBy;
|
||||
|
||||
/* The number of tables in the FROM clause is limited by the number of
|
||||
** bits in a Bitmask
|
||||
|
||||
@@ -386,7 +386,6 @@ struct WhereMaskSet {
|
||||
struct WhereLoopBuilder {
|
||||
WhereInfo *pWInfo; /* Information about this WHERE */
|
||||
WhereClause *pWC; /* WHERE clause terms */
|
||||
ExprList *pOrderBy; /* ORDER BY clause */
|
||||
WhereLoop *pNew; /* Template WhereLoop */
|
||||
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
|
||||
#ifdef SQLITE_ENABLE_STAT4
|
||||
|
||||
@@ -824,6 +824,9 @@ static int codeAllEqualityTerms(
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, r1, regBase+j);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(j=nSkip; j<nEq; j++){
|
||||
pTerm = pLoop->aLTerm[j];
|
||||
if( pTerm->eOperator & WO_IN ){
|
||||
if( pTerm->pExpr->flags & EP_xIsSelect ){
|
||||
/* No affinity ever needs to be (or should be) applied to a value
|
||||
|
||||
+4
-7
@@ -265,13 +265,10 @@ do_execsql_test e_expr-6.4 {SELECT -72%5} {-2}
|
||||
do_execsql_test e_expr-6.5 {SELECT 72.35%5} {2.0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that the results of all binary operators are either numeric or
|
||||
# NULL, except for the || operator, which may evaluate to either a text
|
||||
# value or NULL.
|
||||
#
|
||||
# EVIDENCE-OF: R-20665-17792 The result of any binary operator is either
|
||||
# a numeric value or NULL, except for the || concatenation operator
|
||||
# which always evaluates to either NULL or a text value.
|
||||
# EVIDENCE-OF: R-15904-00746 The result of any binary operator is either
|
||||
# a numeric value or NULL, except for the || concatenation operator, and
|
||||
# the -> and ->> extract operators which evaluate to either
|
||||
# NULL or a text value.
|
||||
#
|
||||
set literals {
|
||||
1 'abc' 2 'hexadecimal' 3 ''
|
||||
|
||||
+2
-2
@@ -48,9 +48,9 @@ proc do_detail_test {tn sql res} {
|
||||
###########################################################################
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# EVIDENCE-OF: R-33710-56344 In order to use foreign key constraints in
|
||||
# EVIDENCE-OF: R-37672-59189 In order to use foreign key constraints in
|
||||
# SQLite, the library must be compiled with neither
|
||||
# SQLITE_OMIT_FOREIGN_KEY or SQLITE_OMIT_TRIGGER defined.
|
||||
# SQLITE_OMIT_FOREIGN_KEY nor SQLITE_OMIT_TRIGGER defined.
|
||||
#
|
||||
ifcapable trigger&&foreignkey {
|
||||
do_test e_fkey-1 {
|
||||
|
||||
+11
-8
@@ -12,10 +12,13 @@
|
||||
# focus of this file is testing the printf() SQL function.
|
||||
#
|
||||
#
|
||||
# EVIDENCE-OF: R-63057-40065 The printf(FORMAT,...) SQL function works
|
||||
# EVIDENCE-OF: R-32560-14372 The format(FORMAT,...) SQL function works
|
||||
# like the sqlite3_mprintf() C-language function and the printf()
|
||||
# function from the standard C library.
|
||||
#
|
||||
# EVIDENCE-OF: R-64900-53159 The printf() SQL function is an alias for
|
||||
# the format() SQL function.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -24,7 +27,7 @@ source $testdir/tester.tcl
|
||||
# then the result is NULL.
|
||||
#
|
||||
do_execsql_test printf2-1.1 {
|
||||
SELECT quote(printf()), quote(printf(NULL,1,2,3));
|
||||
SELECT quote(format()), quote(format(NULL,1,2,3));
|
||||
} {NULL NULL}
|
||||
|
||||
|
||||
@@ -32,31 +35,31 @@ do_execsql_test printf2-1.2 {
|
||||
SELECT printf('hello');
|
||||
} {hello}
|
||||
do_execsql_test printf2-1.3 {
|
||||
SELECT printf('%d,%d,%d',55,-11,3421);
|
||||
SELECT format('%d,%d,%d',55,-11,3421);
|
||||
} {55,-11,3421}
|
||||
do_execsql_test printf2-1.4 {
|
||||
SELECT printf('%d,%d,%d',55,'-11',3421);
|
||||
} {55,-11,3421}
|
||||
do_execsql_test printf2-1.5 {
|
||||
SELECT printf('%d,%d,%d,%d',55,'-11',3421);
|
||||
SELECT format('%d,%d,%d,%d',55,'-11',3421);
|
||||
} {55,-11,3421,0}
|
||||
do_execsql_test printf2-1.6 {
|
||||
SELECT printf('%.2f',3.141592653);
|
||||
} {3.14}
|
||||
do_execsql_test printf2-1.7 {
|
||||
SELECT printf('%.*f',2,3.141592653);
|
||||
SELECT format('%.*f',2,3.141592653);
|
||||
} {3.14}
|
||||
do_execsql_test printf2-1.8 {
|
||||
SELECT printf('%*.*f',5,2,3.141592653);
|
||||
} {{ 3.14}}
|
||||
do_execsql_test printf2-1.9 {
|
||||
SELECT printf('%d',314159.2653);
|
||||
SELECT format('%d',314159.2653);
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.10 {
|
||||
SELECT printf('%lld',314159.2653);
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.11 {
|
||||
SELECT printf('%lld%n',314159.2653,'hi');
|
||||
SELECT format('%lld%n',314159.2653,'hi');
|
||||
} {314159}
|
||||
do_execsql_test printf2-1.12 {
|
||||
SELECT printf('%n',0);
|
||||
@@ -65,7 +68,7 @@ do_execsql_test printf2-1.12 {
|
||||
# EVIDENCE-OF: R-17002-27534 The %z format is interchangeable with %s.
|
||||
#
|
||||
do_execsql_test printf2-1.12 {
|
||||
SELECT printf('%.*z',5,'abcdefghijklmnop');
|
||||
SELECT format('%.*z',5,'abcdefghijklmnop');
|
||||
} {abcde}
|
||||
do_execsql_test printf2-1.13 {
|
||||
SELECT printf('%c','abcdefghijklmnop');
|
||||
|
||||
@@ -692,6 +692,21 @@ do_execsql_test 30.3 {
|
||||
UPDATE t2 SET (d,d,a)=(SELECT EXISTS(SELECT 1 IN(SELECT max( 1 IN(SELECT x ORDER BY 1)) OVER(PARTITION BY sum((SELECT y FROM t1 UNION SELECT x ORDER BY 1)))INTERSECT SELECT EXISTS(SELECT 1 FROM t1 UNION SELECT x ORDER BY 1) ORDER BY 1) ORDERa)|9 AS blob, 2, 3) FROM t1 WHERE x<a;
|
||||
}
|
||||
|
||||
# 2022-01-21 https://sqlite.org/forum/forumpost/ab95010d410a0a55
|
||||
reset_db
|
||||
do_execsql_test 31.1 {
|
||||
CREATE TABLE a(a1 PRIMARY KEY,a2);
|
||||
INSERT INTO a VALUES(1,5);
|
||||
CREATE TABLE b(b1 UNIQUE,b2);
|
||||
SELECT * FROM a LEFT JOIN b ON b2=NULL AND b2=5 WHERE (b1,substr(b.b1,1,1))==(SELECT 1024,'b');
|
||||
} {}
|
||||
do_execsql_test 31.2 {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(0);
|
||||
CREATE TABLE t2(b,c,d);
|
||||
INSERT INTO t2 VALUES(NULL,123,456);
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON b=NULL WHERE (c,d)==(SELECT 123, 456+a);
|
||||
} {}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# 2022-01-21
|
||||
#
|
||||
# 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 tests for sqlite3_vtab_distinct() interface.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix vtabdistinct
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
load_static_extension db qpvtab
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT ix FROM qpvtab WHERE vn='sqlite3_vtab_distinct';
|
||||
} {0}
|
||||
do_execsql_test 1.2 {
|
||||
SELECT DISTINCT ix FROM qpvtab WHERE vn='sqlite3_vtab_distinct';
|
||||
} {2}
|
||||
do_execsql_test 1.3 {
|
||||
SELECT distinct vn, ix FROM qpvtab(3)
|
||||
WHERE +vn IN ('sqlite3_vtab_distinct','nOrderBy');
|
||||
} {nOrderBy 2 sqlite3_vtab_distinct 2}
|
||||
do_execsql_test 1.4 {
|
||||
SELECT vn, ix FROM qpvtab
|
||||
GROUP BY vn
|
||||
HAVING vn='sqlite3_vtab_distinct';
|
||||
} {sqlite3_vtab_distinct 1}
|
||||
|
||||
finish_test
|
||||
Reference in New Issue
Block a user