Compare commits

...

28 Commits

Author SHA1 Message Date
drh f6f7888622 Add a NEVER() on an unreachable branch.
FossilOrigin-Name: 388926254b9da6169da7267bd4d5a1a66a26576be435c88269ab8db9eaedc079
2022-01-28 23:19:01 +00:00
drh cee5cb484d Include hidden columns of table valued functions that are constrained
by the function arguments in the colUsed bitmask.

FossilOrigin-Name: 8f8cab0d0e219f0c4bc2b8061c0013d90a2a5e598dd6cf420d302dfd1b7cbe11
2022-01-28 19:53:37 +00:00
drh d0c7baf505 Remove a NEVER() that has become reachable now that we have the
sqlite3_vtab_rhs_value() interface.

FossilOrigin-Name: c4c30df7cd858315359bd9bfa90a07152d87a2301eaec865c5bc1c65e272eec8
2022-01-28 18:43:33 +00:00
drh 0ae56fbdd0 Enable SQLITE_INDEX_CONSTRAINT_LIMIT/OFFSET even if there are vector
comparison operators in the WHERE clause.  Also:  Do not enable
sqlite3_vtab_rhs_value() for LIMIT/OFFSET if the value is negative, as this
violates an invariant on Expr.u.iValue.

FossilOrigin-Name: 140480b3ec5466513b165d4818f1180cff6e4a5edcd47efb54cbff74a7107507
2022-01-28 13:18:40 +00:00
drh 8f2c0b59da Query planner always honors the aConstraintUsage[].omit flag for the
SQLITE_INDEX_CONSTRAINT_OFFSET constraint.

FossilOrigin-Name: 38c5151eb8cc789ad082a1b40d16b2ddb55454219bd685b6e420995af6a15f55
2022-01-27 21:18:14 +00:00
drh 233ba1b8eb Make LIMIT and OFFSET values available to sqlite3_vtab_rhs_value().
FossilOrigin-Name: b2d37c086c87fe4aee013bba4eab26f642207cd2a797fe4888a6ef868884c191
2022-01-27 18:45:26 +00:00
drh 895bab3383 Give the virtual table xBestIndex method access to (some) OFFSET and LIMIT
clauses.

FossilOrigin-Name: 74fa5757ee0a8499bcd6546dac1a3ecc6048ba9cff9e3e574e28e6e82e894a3d
2022-01-27 16:14:50 +00:00
drh 4b51e8bd68 Enforce the restriction that 'unixepoch' only works as the first modifier
after the time-value.  This has been documented since 2004, but has never
actually been enforced before.  Also add new test cases for date/time
functions with evidence marks.

FossilOrigin-Name: 64fa9e8c87179211cec248e6dfd7578502e6e969a19e91a4f0e21ed9b972a6bc
2022-01-27 13:52:01 +00:00
drh a5c9a70757 Minor adjustment to error handling in sqlite3FinishCoding().
FossilOrigin-Name: a8db69411b0d1275909adeb21027784ada17af24efe3a59ae0ae2a897659ff17
2022-01-25 00:03:25 +00:00
drh 15b01def1e Remove an unnecessary assert() that is sometimes not true following an OOM.
FossilOrigin-Name: e9361d72f362b390a31f667363b01cf9d4b78aa19ed5c97f21afe9da764b89c0
2022-01-24 21:47:00 +00:00
drh a2417ec75c New dbsqlfuzz cases added to test/fuzzdata8.db.
FossilOrigin-Name: d1fbf63330830c4b9549d0e67f6cdc19fe7a9dc3fcf509795fd1175499fddc82
2022-01-24 20:20:35 +00:00
drh b32b30930f One of the ALWAYS() macros in the previous check-in could sometimes be
false, following an OOM.  Remove it.  Problem found by dbsqlfuzz.

FossilOrigin-Name: 11df9187dad0eb33b0f6288b76d74f9700420ec855e8106b0bc71df48c485ad1
2022-01-24 20:16:37 +00:00
drh 1da88b5ce6 Add ALWAYS() macros. Change some existing ALWAYS() into assert(). Other
code simplifications.

FossilOrigin-Name: 4aa27b4fcd1ffd06c38357a87ba3f5776367570439c49652f0903873def0bb23
2022-01-24 19:38:56 +00:00
drh 0c7d3d399d Remove many redundant checks for sqlite3.mallocFailed now that any OOM should
cause Parse.nErr to be non-zero.

FossilOrigin-Name: 1f7fa46126ea33ed30e93186aff3df51068aeb4be6f79a102bfe8c4e44941d71
2022-01-24 16:47:12 +00:00
drh c692df2784 Make it so that any Parse object is always linked into the database conenction
while it is active.  Hence, an OOM will cause Parse.nErr to be set.

FossilOrigin-Name: 6a45d8fe8bfbc11a5b86d25237e1f8bccfb0f22f3dcaf004ba797aeb57b365ec
2022-01-24 15:34:55 +00:00
larrybr b5d4473221 Fix testcase for CLI .read recursion.
FossilOrigin-Name: 53d4404458fb6f0b6b2b69c2225d66b39f09099c356ba3c3e990474f14aba31a
2022-01-24 14:01:31 +00:00
drh 3cdb1394b9 Make sure the sqlite3OomFault() routine sets an error in the Parse object
if there is a Parse object active and linked to the database connection.

FossilOrigin-Name: ad7aace761c6b21ba453eaf43c68d985be7cbd5a200fe0d2e27a0c7150f99874
2022-01-24 12:48:54 +00:00
dan f5bc444077 Ensure that any error encountered while coding a trigger program is transfered to the main Parse structure before it is used with any other routine that might set the error code.
FossilOrigin-Name: 4293656578811b500786335de7cc9ac0d6ccc6fb273b9419a86968a095404c43
2022-01-24 11:25:42 +00:00
larrybr d48e88e56d Limit CLI input redirect nesting
FossilOrigin-Name: 7a073931752d16ba71f1a606091461e427ca5ccf4d135d3c5141bfdd4e67e2d5
2022-01-24 06:36:16 +00:00
drh bcba3655ee Add support for the sqlite3_vtab_distinct() interface. Virtual table
implementations can use this API to determine more detail about the ordering
requirements needed by the query plan and perhaps reduce the amount of
work required to compute a correct answer.  This is an optimization
opportunity for the virtual table implementation.  The correct answer should
still be obtained (though perhaps more slowly) even if sqlite3_vtab_distinct()
is ignored.

FossilOrigin-Name: e4caf1e3932b1bd0dea072df7fc9458aed98c84ea397b6948b89292603949c41
2022-01-22 22:28:32 +00:00
drh 68dc8151e0 Bring sqlite3_vtab_distinct() up to spec so that it works as described in the
documentation.

FossilOrigin-Name: 4289edf3c5e32a05b51f232020099b33f6f5e79b0ceca2b96baf1186168d9af6
2022-01-22 20:45:57 +00:00
drh 9b9fc74f2e Iimproved documentation for sqlite3_vtab_distinct(). No changes to code.
FossilOrigin-Name: 7af03f02940b5380ee7375672ca8d0ff68c5f741d0ea206911631f3eb5a78555
2022-01-22 19:19:35 +00:00
drh 57c58b4de8 Omit the WhereLoopBuilder.pOrderBy field, which is no longer needed.
FossilOrigin-Name: a13afc909c8bb643aa154b39ba8c023bae7352d3cd7cfb96be3891fa0e4bc045
2022-01-22 02:52:22 +00:00
drh ec778d2724 An initial attempt to implement sqlite3_vtab_distinct().
FossilOrigin-Name: d571262d2345bb11e71bef395cf078e5d7303b974b38b4e319adda6194ccc1c5
2022-01-22 00:18:01 +00:00
drh 4d7f335e8b Update evidence marks for the latest changes to the documentation.
FossilOrigin-Name: 19247e919fab9748cae561cb12c4c3c106064390a37e32e724d9a9066cfaff8e
2022-01-21 19:26:18 +00:00
drh a1c8151bab Fix some of the new date/time function features to comply with the spec.
Update requirement marks.

FossilOrigin-Name: 2f5dc7a9eed89baf6814e9e123354b262c806c853dee1243c93286c564b9aba8
2022-01-21 18:57:30 +00:00
drh e482fde6ee When computing a vector to be used as a key for an index lookup, do not
check for NULL values and abort until after all key values have been
computed, in case one of the later key values involves some initialization
that is needed by a LEFT JOIN.  Fix for the problem identified by
[forum:/forumpost/ab95010d410a0a55|Forum post ab95010d410a0a55].

FossilOrigin-Name: 4db5217a28ce767fa14ddfe51cf3ca25eceb72079d46a2fc00f7d6b8ae9abe0b
2022-01-21 16:41:11 +00:00
drh d323a3a515 Add the sqlite3_vtab_rhs_value() interface, allowing the xBestIndex method
of a virtual table to access known values on the right-hand side of
constraint expressions.

FossilOrigin-Name: e19a0b132a641f0e9f3d72586af538b95b4db8665b1555f84bc0a291bf1a4056
2022-01-21 01:00:53 +00:00
43 changed files with 798 additions and 209 deletions
+34 -7
View File
@@ -40,7 +40,7 @@
**
** Option 1 is the default behavior. 2 is use if there is a usable
** constraint on "flags" with an integer right-hand side that where the
** value of the right-hand side has its 0x01 bit set.
** value of the right-hand side has its 0x001 bit set.
**
** All constraints on columns "a" through "e" are marked as "omit".
**
@@ -48,6 +48,12 @@
** is an integer and that integer has its 0x02 bit set, then the
** orderByConsumed flag is set.
**
** FLAGS SUMMARY:
**
** 0x001 Columns 'a' through 'e' have INT values
** 0x002 orderByConsumed is set
** 0x004 OFFSET and LIMIT have omit set
**
** COMPILE:
**
** gcc -Wall -g -shared -fPIC -I. qpvtab.c -o qqvtab.so
@@ -103,7 +109,8 @@ static const char *azColname[] = {
"ux",
"rhs",
"a", "b", "c", "d", "e",
"flags"
"flags",
""
};
/*
@@ -143,6 +150,7 @@ static int qpvtabConnect(
#define QPVTAB_D 9
#define QPVTAB_E 10
#define QPVTAB_FLAGS 11
#define QPVTAB_NONE 12
if( rc==SQLITE_OK ){
pNew = sqlite3_malloc( sizeof(*pNew) );
*ppVtab = (sqlite3_vtab*)pNew;
@@ -226,7 +234,7 @@ static int qpvtabColumn(
sqlite3_result_text64(ctx, z, zEnd-z, SQLITE_TRANSIENT, SQLITE_UTF8);
}
}else if( i>=QPVTAB_A && i<=QPVTAB_E ){
if( pCur->flags & 1 ){
if( pCur->flags & 0x001 ){
sqlite3_result_int(ctx, i-QPVTAB_A+1);
}else{
char x = 'a'+i-QPVTAB_A;
@@ -338,19 +346,25 @@ static int qpvtabBestIndex(
for(i=0; i<pIdxInfo->nConstraint; i++){
sqlite3_value *pVal;
int iCol = pIdxInfo->aConstraint[i].iColumn;
int op = pIdxInfo->aConstraint[i].op;
if( iCol==QPVTAB_FLAGS && pIdxInfo->aConstraint[i].usable ){
pVal = 0;
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
assert( rc==SQLITE_OK || pVal==0 );
if( pVal ){
pIdxInfo->idxNum = sqlite3_value_int(pVal);
if( pIdxInfo->idxNum & 2 ) pIdxInfo->orderByConsumed = 1;
if( pIdxInfo->idxNum & 0x002 ) pIdxInfo->orderByConsumed = 1;
}
}
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
){
iCol = QPVTAB_NONE;
}
sqlite3_str_appendf(pStr,"aConstraint,%d,%s,%d,%d,",
i,
azColname[iCol],
pIdxInfo->aConstraint[i].op,
op,
pIdxInfo->aConstraint[i].usable);
pVal = 0;
rc = sqlite3_vtab_rhs_value(pIdxInfo, i, &pVal);
@@ -359,9 +373,20 @@ static int qpvtabBestIndex(
qpvtabStrAppendValue(pStr, pVal);
}
sqlite3_str_append(pStr, "\n", 1);
}
for(i=0; i<pIdxInfo->nConstraint; i++){
int iCol = pIdxInfo->aConstraint[i].iColumn;
int op = pIdxInfo->aConstraint[i].op;
if( op==SQLITE_INDEX_CONSTRAINT_LIMIT
|| op==SQLITE_INDEX_CONSTRAINT_OFFSET
){
iCol = QPVTAB_NONE;
}
if( iCol>=QPVTAB_A && pIdxInfo->aConstraint[i].usable ){
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
pIdxInfo->aConstraintUsage[i].omit = 1;
pIdxInfo->aConstraintUsage[i].argvIndex = ++k;
if( iCol<=QPVTAB_FLAGS || (pIdxInfo->idxNum & 0x004)!=0 ){
pIdxInfo->aConstraintUsage[i].omit = 1;
}
}
}
sqlite3_str_appendf(pStr, "nOrderBy,%d,,,,\n", pIdxInfo->nOrderBy);
@@ -372,6 +397,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;
+46 -44
View File
@@ -1,5 +1,5 @@
C Add\srequirements\smarks\sand\stuning.
D 2022-01-21T00:38:49.617
C Add\sa\sNEVER()\son\san\sunreachable\sbranch.
D 2022-01-28T23:19:01.285
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 09738419e25f603a35c0ac8bd0a04daab794f48d08a9bc07a6085b9057b99009
F ext/misc/regexp.c b267fd05ff8d38b22f4c2809d7b7a2c61d522e9faf2feb928dbb9662e4a3a386
F ext/misc/remember.c add730f0f7e7436cd15ea3fd6a90fd83c3f706ab44169f7f048438b7d6baa69c
F ext/misc/rot13.c 51ac5f51e9d5fd811db58a9c23c628ad5f333c173f1fc53c8491a3603d38556c
@@ -485,39 +485,39 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c e3943d8fbcaf60f79f39d4aecc56a6a8092f51f93d6a7c5b1db2633c5fa10c30
F src/alter.c e8ac1df663bf4ec74920edd1299435f2a616d2404de0ac4013c151ea4e7a11f2
F src/analyze.c 7518b99e07c5494111fe3bd867f28f804b6c5c1ad0703ec3d116de9bab3fa516
F src/attach.c e3f9d9a2a4a844750f3f348f37afb244535f21382cbfcd840152cb21cb41cfaf
F src/attach.c f26d400f3ffe2cdca01406bca70e5f58c5488bf165b4fc37c228136dfcf1b583
F src/auth.c f4fa91b6a90bbc8e0d0f738aa284551739c9543a367071f55574681e0f24f8cf
F src/backup.c 3014889fa06e20e6adfa0d07b60097eec1f6e5b06671625f476a714d2356513d
F src/backup.c 58880b9a9adf88f1a57cb3b0db6b891626ae76113ebd0f2417a87c2634edfc65
F src/bitvec.c 7c849aac407230278445cb069bebc5f89bf2ddd87c5ed9459b070a9175707b3d
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c ddab31c38d5f16114bc68392430556b1063fe14e0020f9a56d2c35ddd58ba7e3
F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
F src/btreeInt.h ee9348c4cb9077243b049edc93a82c1f32ca48baeabf2140d41362b9f9139ff7
F src/build.c c72407a27a28982a384cd453a3a6b6992a1ceae8bd8d95e96d7fb9c0d645a32f
F src/build.c 9329120c4522d1ad881b9e62108870c8a5e994e31f4d813d0eb3de323d25e362
F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 2cce39df1a13e05b7633e6d21b651f21492471f991dd7b323a4ee4e7b7f0b7f1
F src/date.c ab8e01d928f201f5dee0bc6d54d6702fdcec96dff4d58c387447671f6a46d191
F src/date.c 41627dec396f3d33e2c317a065f9d59bb535982b2ea3a561c96e4d4cf1137b65
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 861e08690fcb0f2ee1165eff0060ea8d4f3e2ea10f80dab7d32ad70443a6ff2d
F src/delete.c 19814f621cde10b1771a0dea7fe25d3d7d39975b8d4be4888537d30860e7c08c
F src/expr.c 827179c78d2ca7cc318392811de8151c60eacf7ce804b13e61bb7ef38f954846
F src/delete.c b5f1716b4d723db48254ee0f896e362cd029e865e05414139ea7f539f3884e1d
F src/expr.c 9658bccd1598211ace848c8ca9480dbf8be08dfee1db5cf03897b34b7b6e8fef
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 5b73f7a7c00f06017531a5bd258cbc2c7a294e55a7f84a729fe27aa525242560
F src/fkey.c 06e4ac33031b02dde7130c12e79cddf4dc5cfa72b23d8e63a3c26878fc9c1d3c
F src/func.c 8fddc42bce95d17938252a543f86fe29e479366e80fbd112a1822913b6247776
F src/global.c 1f56aead86e8a18c4415638f5e6c4d0a0550427f4b3f5d065ba5164cc09c22e8
F src/hash.c 8d7dda241d0ebdafb6ffdeda3149a412d7df75102cecfc1021c98d6219823b19
F src/hash.h 3340ab6e1d13e725571d7cee6d3e3135f0779a7d8e76a9ce0a85971fa3953c51
F src/hwtime.h cb1d7e3e1ed94b7aa6fde95ae2c2daccc3df826be26fc9ed7fd90d1750ae6144
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
F src/insert.c e528416ff5d86fc5d656ea6a26f03fde39836b6175f93048c32a03cb2ee16743
F src/insert.c 1eea44389de3768ac98588c1410171cd53e7c6ad1af74049983dcbac82093de0
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/malloc.c fec841aa0a0400a6f7d20706178a5d8e8219a6bf562b6fe712c17f6c26813266
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
F src/mem2.c c8bfc9446fd0798bddd495eb5d9dbafa7d4b7287d8c22d50a83ac9daa26d8a75
@@ -545,19 +545,19 @@ F src/parse.y 04f61db1cdd7036c6d74baad1c342d3e3110cb0765c48fcfd3bdf4e974a1e5bb
F src/pcache.c 084e638432c610f95aea72b8509f0845d2791293f39d1b82f0c0a7e089c3bb6b
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 54881292a9a5db202b2c0ac541c5e3ef9a5e8c4f1c1383adb2601d5499a60e65
F src/pragma.c c536665ce8431c8b1efbf7e0a5c01852f49f7bf28f1954f8118b2d28e4a3797f
F src/pragma.c 7c024d690a3dc93f61830f11f900e4af2357f31d081b0c79099ca5e28919cba7
F src/pragma.h 87330ed2fbfa2a1274de93ca0ab850fba336189228cb256089202c3b52766fad
F src/prepare.c 45fe7408eb78d80eca8392669070a6e5caf231b09e5c7b1ff65c1ad64a3734c5
F src/prepare.c 1e23522c934d90ff42de1b9b4f782fdf0fb690b06b92d7480b471ccb2b5899ea
F src/printf.c 975f1f5417f2526365b6e6d7f22332e3e11806dad844701d92846292b654ba9a
F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
F src/resolve.c 359bc0e445d427583d2ab6110433a5dc777f64a0ecdf8d24826d8b475233ead9
F src/resolve.c 24032ae57aec10df2f3fa2e20be0aae7d256bc704124b76c52d763440c7c0fe9
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
F src/select.c ab5717255420972e69b9b9ce4d1c4730fe82cfbdc14b7743e389a8bdb79ca027
F src/shell.c.in 4690f216dc4da0c104a8fd9f9e12bec0483242e630324aa7a3ccd155922e346e
F src/sqlite.h.in 67e49a50bb29e3af86d2b3606af6b3fe20a0d09cf326cc574d632d878c0696d6
F src/select.c a6d2d4bed279d7fe4fcedaf297eaf6441e8e17c6e3947a32d24d23be52ac02f2
F src/shell.c.in e80a140e92e342e2f92d405a77155c8e3a67c9b1d0bdbacb92885960cd4fc8f2
F src/sqlite.h.in da0e94f140f3f054f0eca8fc4a183167bedc7ae9c51822390c62369455eae5f8
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 234b5ff5c20512a116b14d6d08e23caeb68667749f8a94117779a9d38afc7e5c
F src/sqliteInt.h 21a31abf60222f50c1d654cdc27ad9d4040249f0341129dd8286b8b5b32bcd30
F src/sqlite3ext.h 5d54cf13d3406d8eb65d921a0d3c349de6126b732e695e79ecd4830ce86b4f8a
F src/sqliteInt.h 8ef2996e02476f73e41ba977f819bda0cc68b7ce238cf404b9b8930df57bc1d0
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -574,7 +574,7 @@ F src/test9.c 12e5ba554d2d1cbe0158f6ab3f7ffcd7a86ee4e5
F src/test_async.c 195ab49da082053fdb0f949c114b806a49ca770a
F src/test_autoext.c 915d245e736652a219a907909bb6710f0d587871
F src/test_backup.c bf5da90c9926df0a4b941f2d92825a01bbe090a0
F src/test_bestindex.c 78809f11026f18a93fcfd798d9479cba37e1201c830260bf1edc674b2fa9b857
F src/test_bestindex.c ba0314d3bca8b00fa0daaf113a314986f73ea8ad85a7562f983638d09a29045c
F src/test_blob.c ae4a0620b478548afb67963095a7417cd06a4ec0a56adb453542203bfdcb31ce
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
F src/test_config.c 284c29912736f68b0a583a920bf63fd8f9125dffb8a75cb0676e58502b2f7908
@@ -618,32 +618,32 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c b74d878aa7c82ec8460779468061a96185e22257f68ab785b69abce354b70446
F src/treeview.c 9dfdb7ff7f6645d0a6458dbdf4ffac041c071c4533a6db8bb6e502b979ac67bc
F src/trigger.c 40e7c3dcff57a770d5fa38ba21ed4725572fd2e224c58af61eb980598b60f9c8
F src/update.c d6f5c7b9e072660757ac7d58175aca11c07cb95ebbb297ae7f38853700f52328
F src/trigger.c 692972e4393dfc8017a1a527c1ea1b96ce3d101e84584cd832fcfb83d22b50b2
F src/update.c f875b0d59da5c3055a0b2ac20560e1650229c6787e78de5e9836267b5cbb8359
F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
F src/utf.c ee39565f0843775cc2c81135751ddd93eceb91a673ea2c57f61c76f288b041a0
F src/util.c 89e51820bcb468ff3877a8d942f5cc807208087f021227e0927693e928a195bc
F src/util.c 602fe229f32a96ceccae4f40824129669582096f7c355f53dbac156c9fecef23
F src/vacuum.c 6c38ddc52f0619865c91dae9c441d4d48bf3040d7dc1bc5b22da1e45547ed0b3
F src/vdbe.c cfe1980fbeb87eb35297b4a41808034761f26277cf45c9cf3e4eac20edcba1d5
F src/vdbe.h 25dabb25c7e157b84e59260cfb5b466c3ac103ede9f36f4db371332c47601abe
F src/vdbeInt.h d89d5d2150500cfb08615329fd20aea9d746bba5f2c3ecb8a17e2d2d9be029e5
F src/vdbeapi.c 22c79072ae7d8a01e9bcae8ba16e918d60d202eaa9553b5fda38f99f7464d99a
F src/vdbeaux.c c1b452cc17f5887b3d36bc277a2181914d6bed508ea45827b5f348160491e6a6
F src/vdbeblob.c 29c4118f7ee615cdee829e8401f6ead1b96b95d545b4de0042f6de39c962c652
F src/vdbemem.c da4d594084d581be6436582bb44bb128feeb138a3e6c313eda6749ebdc3a65ec
F src/vdbeaux.c e761b8011baec7a4773f0a7594783f2cd71f699ab187c4aad917529ab8acd3fe
F src/vdbeblob.c 5e61ce31aca17db8fb60395407457a8c1c7fb471dde405e0cd675974611dcfcd
F src/vdbemem.c eb6042667c02c3ef1f968235b4a170e31b23a4b6a57f65a8454eab4d36f14b7f
F src/vdbesort.c 43756031ca7430f7aec3ef904824a7883c4ede783e51f280d99b9b65c0796e35
F src/vdbetrace.c fe0bc29ebd4e02c8bc5c1945f1d2e6be5927ec12c06d89b03ef2a4def34bf823
F src/vdbevtab.c f99b275366c5fc5e2d99f734729880994ab9500bdafde7fae3b02d562b9d323c
F src/vtab.c a47cc12ebaa350800c0c87b6b0095debbb5a6ed32727bcab9d82ad070a81b738
F src/vtab.c e0eaf5b8f7f8929088485a76bea2ff6124adb12e0eb5c0997287ff5e0e4c0517
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/whereexpr.c 9f64c39e53070584e99e4d20c1dd3397e125fabbae8fd414ffec574c410ac7d3
F src/window.c 5d3b397b0c026d0ff5890244ac41359e524c01ae31e78782e1ff418c3e271a9e
F src/where.c f61ca6dbb4bbb7171aa5f5459982d8d98aac24852572bcee250f9c469a1963ba
F src/whereInt.h 0748a6fce98b41862445906922a809146ff7ef4de16ed9022b0bc4e5c43aa60a
F src/wherecode.c c313ccf5ed13dc7e88c64f93733f414dee369a212508a866878696d83c64fc36
F src/whereexpr.c becee225f104abd0253e0ceecd2a6253589f269395d98fc3ff98fdd64fecb34c
F src/window.c dfaec4abc6012cbc18e4a202ca3a5d5a0efcc4011d86a06d882ddaab8aedee4d
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
F test/affinity3.test eecb0dabee4b7765a8465439d5e99429279ffba23ca74a7eae270a452799f9e7
@@ -837,6 +837,7 @@ F test/cursorhint2.test 6f3aa9cb19e7418967a10ec6905209bcbb5968054da855fc36c8beee
F test/dataversion1.test 6e5e86ac681f0782e766ebcb56c019ae001522d114e0e111e5ebf68ccf2a7bb8
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 7e12ec14aaf4d5e6294b4ba140445b0eca06ea50062a9c3a69c4ee13d0b6f8b1
F test/date3.test a1b77abf05c6772fe5ca2337cac1398892f2a41e62bce7e6be0f4a08a0e64ae5
F test/dbdata.test 042f49acff3438f940eeba5868d3af080ae64ddf26ae78f80c92bec3ca7d8603
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz001.test 55e1a3504f8dea84155e09912fe3b1c3ad77e0b1a938ec42ca03b8e51b321e30
@@ -868,8 +869,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
@@ -1069,7 +1070,7 @@ F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e4
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db 0166b56fd7a6b9636a1d60ef0a060f86ddaecf99400a666bb6e5bbd7199ad1f2
F test/fuzzdata8.db a0c7af954bcbb226ed7ae087b3b6d6e48eaac8fac5671150ffd23c35b55bffe6
F test/fuzzdata8.db 738ed275638f2423cdef240a44eba3b9bc272eec619e68b00429d4575a15e50b
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test f64c4aef4c9e9edf1d6dc0d3f1e65dcc81e67c996403c88d14f09b74807a42bc
@@ -1292,7 +1293,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 +1323,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
@@ -1388,7 +1389,7 @@ F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
F test/shell1.test 70f46b5d07776a107335c3c2c9cbd0431d44637bfeae1f6b9ded5e33b4c7c0bf
F test/shell2.test f00a0501c00583cbc46f7510e1d713366326b2b3e63d06d15937284171a8787c
F test/shell3.test cb4b835a901742c9719437a89171172ecc4a8823ad97349af8e4e841e6f82566
F test/shell4.test 3ed6c4b42fd695efcbc25d69ef759dbb15855ca8e52ba6c5ee076f8b435f48be
F test/shell4.test 8f6c0fce4abed19a8a7f7262517149812a04caa905d01bdc8f5e92573504b759
F test/shell5.test b85069bfcf3159b225228629ab2c3e69aa923d098fea8ea074b5dcd743522e2c
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
@@ -1724,6 +1725,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 +1942,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 8f8cab0d0e219f0c4bc2b8061c0013d90a2a5e598dd6cf420d302dfd1b7cbe11
R 2886f1ce9cf06aa83d320b384893e940
U drh
Z 0ca7e1064e9e25edf7c6ed09bdf60dba
Z 20c096da0533f9910b77ed2d57db0dcc
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
ac951490fd7d5864fe422a80ee8557478e823e79461bec2ee538f57b6733eb5a
388926254b9da6169da7267bd4d5a1a66a26576be435c88269ab8db9eaedc079
+8 -4
View File
@@ -324,7 +324,9 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
int r1; /* Temporary registers */
db = pParse->db;
if( pParse->nErr || db->mallocFailed ) return;
assert( db->pParse==pParse );
if( pParse->nErr ) return;
assert( db->mallocFailed==0 );
pNew = pParse->pNewTable;
assert( pNew );
@@ -735,7 +737,9 @@ struct RenameCtx {
** following a valid object, it may not be used in comparison operations.
*/
static void renameTokenCheckAll(Parse *pParse, const void *pPtr){
if( pParse->nErr==0 && pParse->db->mallocFailed==0 ){
assert( pParse==pParse->db->pParse );
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
if( pParse->nErr==0 ){
const RenameToken *p;
u8 i = 0;
for(p=pParse->pRename; p; p=p->pNext){
@@ -1132,7 +1136,7 @@ static int renameParseSql(
/* Parse the SQL statement passed as the first argument. If no error
** occurs and the parse does not result in a new table, index or
** trigger object, the database must be corrupt. */
memset(p, 0, sizeof(Parse));
sqlite3ParseObjectInit(p, db);
p->eParseMode = PARSE_MODE_RENAME;
p->db = db;
p->nQueryLoop = 1;
@@ -1417,7 +1421,7 @@ static void renameParseCleanup(Parse *pParse){
sqlite3DeleteTrigger(db, pParse->pNewTrigger);
sqlite3DbFree(db, pParse->zErrMsg);
renameTokenFree(db, pParse->pRename);
sqlite3ParserReset(pParse);
sqlite3ParseObjectReset(pParse);
}
/*
+1 -1
View File
@@ -354,7 +354,7 @@ static void codeAttach(
}
#ifndef SQLITE_OMIT_AUTHORIZATION
if( pAuthArg ){
if( ALWAYS(pAuthArg) ){
char *zAuthArg;
if( pAuthArg->op==TK_STRING ){
assert( !ExprHasProperty(pAuthArg, EP_IntValue) );
+2 -3
View File
@@ -85,14 +85,13 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
if( i==1 ){
Parse sParse;
int rc = 0;
memset(&sParse, 0, sizeof(sParse));
sParse.db = pDb;
sqlite3ParseObjectInit(&sParse,pErrorDb);
if( sqlite3OpenTempDatabase(&sParse) ){
sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
sqlite3ParserReset(&sParse);
sqlite3ParseObjectReset(&sParse);
if( rc ){
return 0;
}
+16 -10
View File
@@ -143,11 +143,13 @@ void sqlite3FinishCoding(Parse *pParse){
assert( pParse->pToplevel==0 );
db = pParse->db;
assert( db->pParse==pParse );
if( pParse->nested ) return;
if( db->mallocFailed || pParse->nErr ){
if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
if( pParse->nErr ){
if( db->mallocFailed ) pParse->rc = SQLITE_NOMEM;
return;
}
assert( db->mallocFailed==0 );
/* Begin by generating some termination code at the end of the
** vdbe program
@@ -280,7 +282,9 @@ void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
if( v && pParse->nErr==0 && !db->mallocFailed ){
assert( v!=0 || pParse->nErr );
assert( db->mallocFailed==0 || pParse->nErr );
if( pParse->nErr==0 ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
assert( pParse->pAinc==0 || pParse->nTab>0 );
@@ -2384,10 +2388,11 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
pTab->iPKey = -1;
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
SQLITE_IDXTYPE_PRIMARYKEY);
if( db->mallocFailed || pParse->nErr ){
if( pParse->nErr ){
pTab->tabFlags &= ~TF_WithoutRowid;
return;
}
assert( db->mallocFailed==0 );
pPk = sqlite3PrimaryKeyIndex(pTab);
assert( pPk->nKeyCol==1 );
}else{
@@ -3128,10 +3133,10 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
*/
sqlite3ColumnsFromExprList(pParse, pTable->pCheck,
&pTable->nCol, &pTable->aCol);
if( db->mallocFailed==0
&& pParse->nErr==0
if( pParse->nErr==0
&& pTable->nCol==pSel->pEList->nExpr
){
assert( db->mallocFailed==0 );
sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
SQLITE_AFF_NONE);
}
@@ -3750,7 +3755,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
tnum = pIndex->tnum;
}
pKey = sqlite3KeyInfoOfIndex(pParse, pIndex);
assert( pKey!=0 || db->mallocFailed || pParse->nErr );
assert( pKey!=0 || pParse->nErr );
/* Open the sorter cursor if we are to use one. */
iSorter = pParse->nTab++;
@@ -3914,9 +3919,11 @@ void sqlite3CreateIndex(
char *zExtra = 0; /* Extra space after the Index object */
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
if( db->mallocFailed || pParse->nErr>0 ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto exit_create_index;
}
assert( db->mallocFailed==0 );
if( IN_DECLARE_VTAB && idxType!=SQLITE_IDXTYPE_PRIMARYKEY ){
goto exit_create_index;
}
@@ -3980,7 +3987,6 @@ void sqlite3CreateIndex(
pDb = &db->aDb[iDb];
assert( pTab!=0 );
assert( pParse->nErr==0 );
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
&& db->init.busy==0
&& pTblName!=0
@@ -4544,10 +4550,10 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
sqlite3 *db = pParse->db;
int iDb;
assert( pParse->nErr==0 ); /* Never called with prior errors */
if( db->mallocFailed ){
goto exit_drop_index;
}
assert( pParse->nErr==0 ); /* Never called with prior non-OOM errors */
assert( pName->nSrc==1 );
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
goto exit_drop_index;
+6 -2
View File
@@ -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; /* IMP: R-31176-64601 */
if( p->validJD && p->rawS ){
rc = 0;
p->rawS = 0;
@@ -725,6 +728,7 @@ static int parseModifier(
** seconds since 1970. Convert to a real julian day number.
*/
if( sqlite3_stricmp(z, "unixepoch")==0 && p->rawS ){
if( idx>1 ) return 1; /* IMP: R-49255-55373 */
r = p->s*1000.0 + 210866760000000.0;
if( r>=0.0 && r<464269060800000.0 ){
clearYMD_HMS_TZ(p);
@@ -938,7 +942,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;
+4 -2
View File
@@ -293,9 +293,11 @@ void sqlite3DeleteFrom(
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto delete_from_cleanup;
}
assert( db->mallocFailed==0 );
assert( pTabList->nSrc==1 );
@@ -476,7 +478,7 @@ void sqlite3DeleteFrom(
** ONEPASS_SINGLE: One-pass approach - at most one row deleted.
** ONEPASS_MULTI: One-pass approach - any number of rows may be deleted.
*/
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, wcf, iTabCur+1);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0,0,wcf,iTabCur+1);
if( pWInfo==0 ) goto delete_from_cleanup;
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
+5 -8
View File
@@ -2803,8 +2803,7 @@ int sqlite3FindInIndex(
CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs);
int j;
assert( pReq!=0 || pRhs->iColumn==XN_ROWID
|| pParse->nErr || db->mallocFailed );
assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr );
for(j=0; j<nExpr; j++){
if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue;
assert( pIdx->azColl[j] );
@@ -3280,10 +3279,8 @@ int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
}
pSel->iLimit = 0;
if( sqlite3Select(pParse, pSel, &dest) ){
if( pParse->nErr ){
pExpr->op2 = pExpr->op;
pExpr->op = TK_ERROR;
}
pExpr->op2 = pExpr->op;
pExpr->op = TK_ERROR;
return 0;
}
pExpr->iTable = rReg = dest.iSDParm;
@@ -3500,10 +3497,10 @@ static void sqlite3ExprCodeIN(
}else{
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
}
if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
// if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
for(i=0; i<nVector; i++){
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
if( pParse->db->mallocFailed ) goto sqlite3ExprCodeIN_oom_error;
if( pParse->nErr ) goto sqlite3ExprCodeIN_oom_error;
if( sqlite3ExprCanBeNull(p) ){
sqlite3VdbeAddOp2(v, OP_IsNull, rLhs+i, destStep2);
VdbeCoverage(v);
+1 -1
View File
@@ -651,7 +651,7 @@ static void fkScanChildren(
** clause. For each row found, increment either the deferred or immediate
** foreign key constraint counter. */
if( pParse->nErr==0 ){
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0);
pWInfo = sqlite3WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0, 0);
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr);
if( pWInfo ){
sqlite3WhereEnd(pWInfo);
+6 -2
View File
@@ -715,9 +715,11 @@ void sqlite3Insert(
#endif
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto insert_cleanup;
}
assert( db->mallocFailed==0 );
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
/* If the Select object is really just a simple VALUES() list with a
@@ -893,7 +895,9 @@ void sqlite3Insert(
dest.nSdst = pTab->nCol;
rc = sqlite3Select(pParse, pSelect, &dest);
regFromSelect = dest.iSdst;
if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
assert( db->pParse==pParse );
if( rc || pParse->nErr ) goto insert_cleanup;
assert( db->mallocFailed==0 );
sqlite3VdbeEndCoroutine(v, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
assert( pSelect->pEList );
+1
View File
@@ -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
+10 -1
View File
@@ -759,8 +759,15 @@ void sqlite3SetString(char **pz, sqlite3 *db, const char *zNew){
** has happened. This routine will set db->mallocFailed, and also
** temporarily disable the lookaside memory allocator and interrupt
** any running VDBEs.
**
** Always return a NULL pointer so that this routine can be invoked using
**
** return sqlite3OomFault(db);
**
** and thereby avoid unnecessary stack frame allocations for the overwhelmingly
** common case where no OOM occurs.
*/
void sqlite3OomFault(sqlite3 *db){
void *sqlite3OomFault(sqlite3 *db){
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
db->mallocFailed = 1;
if( db->nVdbeExec>0 ){
@@ -768,9 +775,11 @@ void sqlite3OomFault(sqlite3 *db){
}
DisableLookaside;
if( db->pParse ){
sqlite3ErrorMsg(db->pParse, "out of memory");
db->pParse->rc = SQLITE_NOMEM_BKPT;
}
}
return 0;
}
/*
+4
View File
@@ -1250,6 +1250,10 @@ void sqlite3Pragma(
(void)sqlite3_finalize(pDummy);
sqlite3DbFree(db, zSql);
}
if( db->mallocFailed ){
sqlite3ErrorMsg(db->pParse, "out of memory");
db->pParse->rc = SQLITE_NOMEM_BKPT;
}
pHash = &db->aDb[ii].pSchema->tblHash;
break;
}
+34 -10
View File
@@ -568,8 +568,10 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
void sqlite3ParseObjectReset(Parse *pParse){
sqlite3 *db = pParse->db;
assert( db!=0 );
assert( db->pParse==pParse );
assert( pParse->nested==0 );
#ifndef SQLITE_OMIT_SHARED_CACHE
sqlite3DbFree(db, pParse->aTableLock);
@@ -584,11 +586,12 @@ void sqlite3ParserReset(Parse *pParse){
if( pParse->pConstExpr ){
sqlite3ExprListDelete(db, pParse->pConstExpr);
}
if( db ){
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
}
assert( db->lookaside.bDisable >= pParse->disableLookaside );
db->lookaside.bDisable -= pParse->disableLookaside;
db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
assert( pParse->db->pParse==pParse );
db->pParse = pParse->pOuterParse;
pParse->db = 0;
pParse->disableLookaside = 0;
}
@@ -601,7 +604,7 @@ void sqlite3ParserReset(Parse *pParse){
** cost for this mechansim (an extra malloc), so it should not be used
** for common cleanups that happen on most calls. But for less
** common cleanups, we save a single NULL-pointer comparison in
** sqlite3ParserReset(), which reduces the total CPU cycle count.
** sqlite3ParseObjectReset(), which reduces the total CPU cycle count.
**
** If a memory allocation error occurs, then the cleanup happens immediately.
** When either SQLITE_DEBUG or SQLITE_COVERAGE_TEST are defined, the
@@ -641,6 +644,24 @@ void *sqlite3ParserAddCleanup(
return pPtr;
}
/*
** Turn bulk memory into a valid Parse object and link that Parse object
** into database connection db.
**
** Call sqlite3ParseObjectReset() to undo this operation.
**
** Caution: Do not confuse this routine with sqlite3ParseObjectInit() which
** is generated by Lemon.
*/
void sqlite3ParseObjectInit(Parse *pParse, sqlite3 *db){
memset(PARSE_HDR(pParse), 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
assert( db->pParse!=pParse );
pParse->pOuterParse = db->pParse;
db->pParse = pParse;
pParse->db = db;
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@@ -657,8 +678,12 @@ static int sqlite3Prepare(
int i; /* Loop counter */
Parse sParse; /* Parsing context */
memset(&sParse, 0, PARSE_HDR_SZ);
/* sqlite3ParseObjectInit(&sParse, db); // inlined for performance */
memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ);
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
sParse.pOuterParse = db->pParse;
db->pParse = &sParse;
sParse.db = db;
sParse.pReprepare = pReprepare;
assert( ppStmt && *ppStmt==0 );
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
@@ -714,7 +739,6 @@ static int sqlite3Prepare(
sqlite3VtabUnlockList(db);
sParse.db = db;
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
char *zSqlCopy;
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
@@ -781,7 +805,7 @@ static int sqlite3Prepare(
end_prepare:
sqlite3ParserReset(&sParse);
sqlite3ParseObjectReset(&sParse);
return rc;
}
static int sqlite3LockAndPrepare(
+5 -3
View File
@@ -1214,7 +1214,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
break;
}
}
return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue;
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
return pParse->nErr ? WRC_Abort : WRC_Continue;
}
/*
@@ -1628,7 +1629,7 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
*/
if( (p->selFlags & SF_Expanded)==0 ){
sqlite3SelectPrep(pParse, p, pOuterNC);
return (pParse->nErr || db->mallocFailed) ? WRC_Abort : WRC_Prune;
return pParse->nErr ? WRC_Abort : WRC_Prune;
}
isCompound = p->pPrior!=0;
@@ -1676,7 +1677,8 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
if( pItem->zName ) pParse->zAuthContext = pItem->zName;
sqlite3ResolveSelectNames(pParse, pItem->pSelect, pOuterNC);
pParse->zAuthContext = zSavedContext;
if( pParse->nErr || db->mallocFailed ) return WRC_Abort;
if( pParse->nErr ) return WRC_Abort;
assert( db->mallocFailed==0 );
/* If the number of references to the outer context changed when
** expressions in the sub-select were resolved, the sub-select
+19 -12
View File
@@ -1404,7 +1404,7 @@ KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
p->nRef = 1;
memset(&p[1], 0, nExtra);
}else{
sqlite3OomFault(db);
return (KeyInfo*)sqlite3OomFault(db);
}
return p;
}
@@ -5588,7 +5588,8 @@ static int selectExpander(Walker *pWalker, Select *p){
/* Process NATURAL keywords, and ON and USING clauses of joins.
*/
if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
assert( db->mallocFailed==0 || pParse->nErr!=0 );
if( pParse->nErr || sqliteProcessJoin(pParse, p) ){
return WRC_Abort;
}
@@ -5885,12 +5886,13 @@ void sqlite3SelectPrep(
NameContext *pOuterNC /* Name context for container */
){
assert( p!=0 || pParse->db->mallocFailed );
assert( pParse->db->pParse==pParse );
if( pParse->db->mallocFailed ) return;
if( p->selFlags & SF_HasTypeInfo ) return;
sqlite3SelectExpand(pParse, p);
if( pParse->nErr || pParse->db->mallocFailed ) return;
if( pParse->nErr ) return;
sqlite3ResolveSelectNames(pParse, p, pOuterNC);
if( pParse->nErr || pParse->db->mallocFailed ) return;
if( pParse->nErr ) return;
sqlite3SelectAddTypeInfo(pParse, p);
}
@@ -5907,8 +5909,10 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pFunc;
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
assert( pParse->db->pParse==pParse );
assert( pParse->db->mallocFailed==0 || pParse->nErr!=0 );
if( nReg==0 ) return;
if( pParse->nErr || pParse->db->mallocFailed ) return;
if( pParse->nErr ) return;
#ifdef SQLITE_DEBUG
/* Verify that all AggInfo registers are within the range specified by
** AggInfo.mnReg..AggInfo.mxReg */
@@ -6331,10 +6335,12 @@ int sqlite3Select(
u8 minMaxFlag; /* Flag for min/max queries */
db = pParse->db;
assert( pParse==db->pParse );
v = sqlite3GetVdbe(pParse);
if( p==0 || db->mallocFailed || pParse->nErr ){
if( p==0 || pParse->nErr ){
return 1;
}
assert( db->mallocFailed==0 );
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
@@ -6369,9 +6375,10 @@ int sqlite3Select(
p->selFlags |= SF_NoopOrderBy;
}
sqlite3SelectPrep(pParse, p, 0);
if( pParse->nErr || db->mallocFailed ){
if( pParse->nErr ){
goto select_end;
}
assert( db->mallocFailed==0 );
assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x104 ){
@@ -6415,7 +6422,7 @@ int sqlite3Select(
#ifndef SQLITE_OMIT_WINDOWFUNC
if( sqlite3WindowRewrite(pParse, p) ){
assert( db->mallocFailed || pParse->nErr>0 );
assert( pParse->nErr );
goto select_end;
}
#if SELECTTRACE_ENABLED
@@ -6891,7 +6898,7 @@ int sqlite3Select(
/* Begin the database scan. */
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, sSort.pOrderBy,
p->pEList, wctrlFlags, p->nSelectRow);
p->pEList, p, wctrlFlags, p->nSelectRow);
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereOutputRowCount(pWInfo) < p->nSelectRow ){
p->nSelectRow = sqlite3WhereOutputRowCount(pWInfo);
@@ -7155,7 +7162,7 @@ int sqlite3Select(
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, pDistinct,
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0) | distFlag, 0
0, (WHERE_GROUPBY|(orderByGrp ? WHERE_SORTBYGROUP : 0)|distFlag), 0
);
if( pWInfo==0 ){
sqlite3ExprListDelete(db, pDistinct);
@@ -7453,7 +7460,7 @@ int sqlite3Select(
SELECTTRACE(1,pParse,p,("WhereBegin\n"));
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pMinMaxOrderBy,
pDistinct, minMaxFlag|distFlag, 0);
pDistinct, 0, minMaxFlag|distFlag, 0);
if( pWInfo==0 ){
goto select_end;
}
@@ -7510,7 +7517,7 @@ int sqlite3Select(
*/
select_end:
assert( db->mallocFailed==0 || db->mallocFailed==1 );
pParse->nErr += db->mallocFailed;
assert( db->mallocFailed==0 || pParse->nErr!=0 );
sqlite3ExprListDelete(db, pMinMaxOrderBy);
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
+15
View File
@@ -1086,6 +1086,7 @@ struct ShellState {
u8 bSafeModePersist; /* The long-term value of bSafeMode */
unsigned statsOn; /* True to display memory stats before each finalize */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int inputNesting; /* Track nesting level of .read and other redirects */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
int lineno; /* Line number of last line read from in */
@@ -1250,6 +1251,12 @@ static const char *modeDescr[] = {
#define SEP_Unit "\x1F"
#define SEP_Record "\x1E"
/*
** Limit input nesting via .read or any other input redirect.
** It's not too expensive, so a generous allowance can be made.
*/
#define MAX_INPUT_NESTING 25
/*
** A callback for the sqlite3_log() interface.
*/
@@ -10940,6 +10947,13 @@ static int process_input(ShellState *p){
int startline = 0; /* Line number for start of current input */
QuickScanState qss = QSS_Start; /* Accumulated line status (so far) */
if( p->inputNesting==MAX_INPUT_NESTING ){
/* This will be more informative in a later version. */
utf8_printf(stderr,"Input nesting limit (%d) reached at line %d."
" Check recursion.\n", MAX_INPUT_NESTING, p->lineno);
return 1;
}
++p->inputNesting;
p->lineno = 0;
while( errCnt==0 || !bail_on_error || (p->in==0 && stdin_is_interactive) ){
fflush(p->out);
@@ -11022,6 +11036,7 @@ static int process_input(ShellState *p){
}
free(zSql);
free(zLine);
--p->inputNesting;
return errCnt>0;
}
+71 -3
View File
@@ -7148,6 +7148,8 @@ struct sqlite3_index_info {
#define SQLITE_INDEX_CONSTRAINT_ISNOTNULL 70
#define SQLITE_INDEX_CONSTRAINT_ISNULL 71
#define SQLITE_INDEX_CONSTRAINT_IS 72
#define SQLITE_INDEX_CONSTRAINT_LIMIT 73
#define SQLITE_INDEX_CONSTRAINT_OFFSET 74
#define SQLITE_INDEX_CONSTRAINT_FUNCTION 150
/*
@@ -9471,13 +9473,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 +9488,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 +9506,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 +9581,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
+2
View File
@@ -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)
+8 -4
View File
@@ -3585,6 +3585,7 @@ struct Parse {
**************************************************************************/
int aTempReg[8]; /* Holding area for temporary registers */
Parse *pOuterParse; /* Outer Parse object when nested */
Token sNameToken; /* Token with unqualified schema object name */
/************************************************************************
@@ -3635,7 +3636,8 @@ struct Parse {
/*
** Sizes and pointers of various parts of the Parse object.
*/
#define PARSE_HDR_SZ offsetof(Parse,aTempReg) /* Recursive part w/o aColCache*/
#define PARSE_HDR(X) (((char*)(X))+offsetof(Parse,zErrMsg))
#define PARSE_HDR_SZ (offsetof(Parse,aTempReg)-offsetof(Parse,zErrMsg)) /* Recursive part w/o aColCache*/
#define PARSE_RECURSE_SZ offsetof(Parse,sLastToken) /* Recursive part */
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
@@ -4575,7 +4577,8 @@ void sqlite3CodeChangeCount(Vdbe*,int,const char*);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*,
Upsert*);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int);
WhereInfo *sqlite3WhereBegin(Parse*,SrcList*,Expr*,ExprList*,
ExprList*,Select*,u16,int);
void sqlite3WhereEnd(WhereInfo*);
LogEst sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
@@ -4975,7 +4978,7 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
FuncDestructor *pDestructor
);
void sqlite3NoopDestructor(void*);
void sqlite3OomFault(sqlite3*);
void *sqlite3OomFault(sqlite3*);
void sqlite3OomClear(sqlite3*);
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3OpenTempDatabase(Parse *);
@@ -5096,7 +5099,8 @@ FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
void sqlite3ParseObjectInit(Parse*,sqlite3*);
void sqlite3ParseObjectReset(Parse*);
void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*);
#ifdef SQLITE_ENABLE_NORMALIZE
char *sqlite3Normalize(Vdbe*, const char*);
+4
View File
@@ -424,6 +424,10 @@ static int tclBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
zOp = "isnull"; break;
case SQLITE_INDEX_CONSTRAINT_IS:
zOp = "is"; break;
case SQLITE_INDEX_CONSTRAINT_LIMIT:
zOp = "limit"; break;
case SQLITE_INDEX_CONSTRAINT_OFFSET:
zOp = "offset"; break;
}
Tcl_ListObjAppendElement(0, pElem, Tcl_NewStringObj("op", -1));
+29 -28
View File
@@ -918,6 +918,7 @@ static void codeReturningTrigger(
assert( v!=0 );
assert( pParse->bReturning );
assert( db->pParse==pParse );
pReturning = pParse->u1.pReturning;
assert( pTrigger == &(pReturning->retTrig) );
memset(&sSelect, 0, sizeof(sSelect));
@@ -928,7 +929,8 @@ static void codeReturningTrigger(
sFrom.a[0].pTab = pTab;
sFrom.a[0].iCursor = -1;
sqlite3SelectPrep(pParse, &sSelect, 0);
if( db->mallocFailed==0 && pParse->nErr==0 ){
if( pParse->nErr==0 ){
assert( db->mallocFailed==0 );
sqlite3GenerateColumnNames(pParse, &sSelect);
}
sqlite3ExprListDelete(db, sSelect.pEList);
@@ -946,7 +948,7 @@ static void codeReturningTrigger(
pParse->eTriggerOp = pTrigger->op;
pParse->pTriggerTab = pTab;
if( sqlite3ResolveExprListNames(&sNC, pNew)==SQLITE_OK
&& !db->mallocFailed
&& ALWAYS(!db->mallocFailed)
){
int i;
int nCol = pNew->nExpr;
@@ -1110,8 +1112,8 @@ static TriggerPrg *codeRowTrigger(
Vdbe *v; /* Temporary VM */
NameContext sNC; /* Name context for sub-vdbe */
SubProgram *pProgram = 0; /* Sub-vdbe for trigger program */
Parse *pSubParse; /* Parse context for sub-vdbe */
int iEndTrigger = 0; /* Label to jump to if WHEN is false */
Parse sSubParse; /* Parse context for sub-vdbe */
assert( pTrigger->zName==0 || pTab==tableOfTrigger(pTrigger) );
assert( pTop->pVdbe );
@@ -1133,19 +1135,17 @@ static TriggerPrg *codeRowTrigger(
/* Allocate and populate a new Parse context to use for coding the
** trigger sub-program. */
pSubParse = sqlite3StackAllocZero(db, sizeof(Parse));
if( !pSubParse ) return 0;
sqlite3ParseObjectInit(&sSubParse, db);
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pSubParse;
pSubParse->db = db;
pSubParse->pTriggerTab = pTab;
pSubParse->pToplevel = pTop;
pSubParse->zAuthContext = pTrigger->zName;
pSubParse->eTriggerOp = pTrigger->op;
pSubParse->nQueryLoop = pParse->nQueryLoop;
pSubParse->disableVtab = pParse->disableVtab;
sNC.pParse = &sSubParse;
sSubParse.pTriggerTab = pTab;
sSubParse.pToplevel = pTop;
sSubParse.zAuthContext = pTrigger->zName;
sSubParse.eTriggerOp = pTrigger->op;
sSubParse.nQueryLoop = pParse->nQueryLoop;
sSubParse.disableVtab = pParse->disableVtab;
v = sqlite3GetVdbe(pSubParse);
v = sqlite3GetVdbe(&sSubParse);
if( v ){
VdbeComment((v, "Start: %s.%s (%s %s%s%s ON %s)",
pTrigger->zName, onErrorText(orconf),
@@ -1171,14 +1171,14 @@ static TriggerPrg *codeRowTrigger(
if( db->mallocFailed==0
&& SQLITE_OK==sqlite3ResolveExprNames(&sNC, pWhen)
){
iEndTrigger = sqlite3VdbeMakeLabel(pSubParse);
sqlite3ExprIfFalse(pSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
iEndTrigger = sqlite3VdbeMakeLabel(&sSubParse);
sqlite3ExprIfFalse(&sSubParse, pWhen, iEndTrigger, SQLITE_JUMPIFNULL);
}
sqlite3ExprDelete(db, pWhen);
}
/* Code the trigger program into the sub-vdbe. */
codeTriggerProgram(pSubParse, pTrigger->step_list, orconf);
codeTriggerProgram(&sSubParse, pTrigger->step_list, orconf);
/* Insert an OP_Halt at the end of the sub-program. */
if( iEndTrigger ){
@@ -1186,23 +1186,24 @@ static TriggerPrg *codeRowTrigger(
}
sqlite3VdbeAddOp0(v, OP_Halt);
VdbeComment((v, "End: %s.%s", pTrigger->zName, onErrorText(orconf)));
transferParseError(pParse, &sSubParse);
transferParseError(pParse, pSubParse);
if( db->mallocFailed==0 && pParse->nErr==0 ){
if( pParse->nErr==0 ){
assert( db->mallocFailed==0 );
pProgram->aOp = sqlite3VdbeTakeOpArray(v, &pProgram->nOp, &pTop->nMaxArg);
}
pProgram->nMem = pSubParse->nMem;
pProgram->nCsr = pSubParse->nTab;
pProgram->nMem = sSubParse.nMem;
pProgram->nCsr = sSubParse.nTab;
pProgram->token = (void *)pTrigger;
pPrg->aColmask[0] = pSubParse->oldmask;
pPrg->aColmask[1] = pSubParse->newmask;
pPrg->aColmask[0] = sSubParse.oldmask;
pPrg->aColmask[1] = sSubParse.newmask;
sqlite3VdbeDelete(v);
}else{
transferParseError(pParse, &sSubParse);
}
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
assert( !sSubParse.pTriggerPrg && !sSubParse.nMaxArg );
sqlite3ParseObjectReset(&sSubParse);
return pPrg;
}
@@ -1257,7 +1258,7 @@ void sqlite3CodeRowTriggerDirect(
Vdbe *v = sqlite3GetVdbe(pParse); /* Main VM */
TriggerPrg *pPrg;
pPrg = getRowTrigger(pParse, p, pTab, orconf);
assert( pPrg || pParse->nErr || pParse->db->mallocFailed );
assert( pPrg || pParse->nErr );
/* Code the OP_Program opcode in the parent VDBE. P4 of the OP_Program
** is a pointer to the sub-vdbe containing the trigger program. */
+7 -3
View File
@@ -347,9 +347,11 @@ void sqlite3Update(
memset(&sContext, 0, sizeof(sContext));
db = pParse->db;
if( pParse->nErr || db->mallocFailed ){
assert( db->pParse==pParse );
if( pParse->nErr ){
goto update_cleanup;
}
assert( db->mallocFailed==0 );
/* Locate the table which we want to update.
*/
@@ -721,7 +723,7 @@ void sqlite3Update(
if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){
flags |= WHERE_ONEPASS_MULTIROW;
}
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0, flags,iIdxCur);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur);
if( pWInfo==0 ) goto update_cleanup;
/* A one-pass strategy that might update more than one row may not
@@ -1243,7 +1245,9 @@ static void updateVirtualTable(
regRowid = ++pParse->nMem;
/* Start scanning the virtual table */
pWInfo = sqlite3WhereBegin(pParse, pSrc,pWhere,0,0,WHERE_ONEPASS_DESIRED,0);
pWInfo = sqlite3WhereBegin(
pParse, pSrc, pWhere, 0, 0, 0, WHERE_ONEPASS_DESIRED, 0
);
if( pWInfo==0 ) return;
/* Populate the argument registers. */
+6
View File
@@ -189,6 +189,8 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
char *zMsg;
va_list ap;
sqlite3 *db = pParse->db;
assert( db!=0 );
assert( db->pParse==pParse );
db->errByteOffset = -2;
va_start(ap, zFormat);
zMsg = sqlite3VMPrintf(db, zFormat, ap);
@@ -196,6 +198,10 @@ void sqlite3ErrorMsg(Parse *pParse, const char *zFormat, ...){
if( db->errByteOffset<-1 ) db->errByteOffset = -1;
if( db->suppressErr ){
sqlite3DbFree(db, zMsg);
if( db->mallocFailed ){
pParse->nErr++;
pParse->rc = SQLITE_NOMEM;
}
}else{
pParse->nErr++;
sqlite3DbFree(db, pParse->zErrMsg);
+1 -2
View File
@@ -1378,8 +1378,7 @@ void sqlite3VdbeSetP4KeyInfo(Parse *pParse, Index *pIdx){
*/
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
assert( p->nOp>0 || p->aOp==0 );
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
|| p->pParse->nErr>0 );
assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->pParse->nErr>0 );
if( p->nOp ){
assert( p->aOp );
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
+6 -5
View File
@@ -152,10 +152,9 @@ int sqlite3_blob_open(
sqlite3_mutex_enter(db->mutex);
pBlob = (Incrblob *)sqlite3DbMallocZero(db, sizeof(Incrblob));
do {
memset(&sParse, 0, sizeof(Parse));
while(1){
sqlite3ParseObjectInit(&sParse,db);
if( !pBlob ) goto blob_open_out;
sParse.db = db;
sqlite3DbFree(db, zErr);
zErr = 0;
@@ -332,7 +331,9 @@ int sqlite3_blob_open(
goto blob_open_out;
}
rc = blobSeekToRow(pBlob, iRow, &zErr);
} while( (++nAttempt)<SQLITE_MAX_SCHEMA_RETRY && rc==SQLITE_SCHEMA );
if( (++nAttempt)>=SQLITE_MAX_SCHEMA_RETRY || rc!=SQLITE_SCHEMA ) break;
sqlite3ParseObjectReset(&sParse);
}
blob_open_out:
if( rc==SQLITE_OK && db->mallocFailed==0 ){
@@ -343,7 +344,7 @@ blob_open_out:
}
sqlite3ErrorWithMsg(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
sqlite3ParserReset(&sParse);
sqlite3ParseObjectReset(&sParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);
return rc;
-4
View File
@@ -1530,11 +1530,7 @@ static int valueFromExpr(
assert( pExpr!=0 );
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
#if defined(SQLITE_ENABLE_STAT4)
if( op==TK_REGISTER ) op = pExpr->op2;
#else
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
#endif
/* Compressed expressions only appear when parsing the DEFAULT clause
** on a table column definition, and hence only when pCtx==0. This
+2 -3
View File
@@ -825,9 +825,8 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
pTab = pCtx->pTab;
assert( IsVirtual(pTab) );
memset(&sParse, 0, sizeof(sParse));
sqlite3ParseObjectInit(&sParse, db);
sParse.eParseMode = PARSE_MODE_DECLARE_VTAB;
sParse.db = db;
/* We should never be able to reach this point while loading the
** schema. Nevertheless, defend against that (turn off db->init.busy)
** in case a bug arises. */
@@ -881,7 +880,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3VdbeFinalize(sParse.pVdbe);
}
sqlite3DeleteTable(db, sParse.pNewTable);
sqlite3ParserReset(&sParse);
sqlite3ParseObjectReset(&sParse);
db->init.busy = initBusy;
assert( (rc&0xff)==rc );
+77 -17
View File
@@ -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;
@@ -3452,6 +3459,15 @@ static int whereLoopAddBtree(
#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Return true if pTerm is a virtual table LIMIT or OFFSET term.
*/
static int isLimitTerm(WhereTerm *pTerm){
assert( pTerm->eOperator==WO_AUX || pTerm->eMatchOp==0 );
return pTerm->eMatchOp>=SQLITE_INDEX_CONSTRAINT_LIMIT
&& pTerm->eMatchOp<=SQLITE_INDEX_CONSTRAINT_OFFSET;
}
/*
** Argument pIdxInfo is already populated with all constraints that may
** be used by the virtual table identified by pBuilder->pNew->iTab. This
@@ -3479,7 +3495,8 @@ static int whereLoopAddVirtualOne(
u16 mExclude, /* Exclude terms using these operators */
sqlite3_index_info *pIdxInfo, /* Populated object for xBestIndex */
u16 mNoOmit, /* Do not omit these constraints */
int *pbIn /* OUT: True if plan uses an IN(...) op */
int *pbIn, /* OUT: True if plan uses an IN(...) op */
int *pbRetryLimit /* OUT: Retry without LIMIT/OFFSET */
){
WhereClause *pWC = pBuilder->pWC;
struct sqlite3_index_constraint *pIdxCons;
@@ -3504,6 +3521,7 @@ static int whereLoopAddVirtualOne(
pIdxCons->usable = 0;
if( (pTerm->prereqRight & mUsable)==pTerm->prereqRight
&& (pTerm->eOperator & mExclude)==0
&& (pbRetryLimit || !isLimitTerm(pTerm))
){
pIdxCons->usable = 1;
}
@@ -3536,8 +3554,8 @@ static int whereLoopAddVirtualOne(
mxTerm = -1;
assert( pNew->nLSlot>=nConstraint );
for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0;
pNew->u.vtab.omitMask = 0;
memset(pNew->aLTerm, 0, sizeof(pNew->aLTerm[0])*nConstraint );
memset(&pNew->u.vtab, 0, sizeof(pNew->u.vtab));
pIdxCons = *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint;
for(i=0; i<nConstraint; i++, pIdxCons++){
int iTerm;
@@ -3571,6 +3589,9 @@ static int whereLoopAddVirtualOne(
}else{
testcase( i!=iTerm );
}
if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET ){
pNew->u.vtab.bOmitOffset = 1;
}
}
if( (pTerm->eOperator & WO_IN)!=0 ){
/* A virtual table that is constrained by an IN clause may not
@@ -3582,6 +3603,21 @@ static int whereLoopAddVirtualOne(
pIdxInfo->idxFlags &= ~SQLITE_INDEX_SCAN_UNIQUE;
*pbIn = 1; assert( (mExclude & WO_IN)==0 );
}
if( isLimitTerm(pTerm) && *pbIn ){
/* If there is an IN(...) term handled as an == (separate call to
** xFilter for each value on the RHS of the IN) and a LIMIT or
** OFFSET term handled as well, the plan is unusable. Set output
** variable *pbRetryLimit to true to tell the caller to retry with
** LIMIT and OFFSET disabled. */
if( pIdxInfo->needToFreeIdxStr ){
sqlite3_free(pIdxInfo->idxStr);
pIdxInfo->idxStr = 0;
pIdxInfo->needToFreeIdxStr = 0;
}
*pbRetryLimit = 1;
return SQLITE_OK;
}
}
}
@@ -3684,13 +3720,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.
@@ -3732,6 +3780,7 @@ static int whereLoopAddVirtual(
WhereLoop *pNew;
Bitmask mBest; /* Tables used by best possible plan */
u16 mNoOmit;
int bRetry = 0; /* True to retry with LIMIT/OFFSET disabled */
assert( (mPrereq & mUnusable)==0 );
pWInfo = pBuilder->pWInfo;
@@ -3740,8 +3789,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;
@@ -3756,7 +3804,15 @@ static int whereLoopAddVirtual(
/* First call xBestIndex() with all constraints usable. */
WHERETRACE(0x800, ("BEGIN %s.addVirtual()\n", pSrc->pTab->zName));
WHERETRACE(0x40, (" VirtualOne: all usable\n"));
rc = whereLoopAddVirtualOne(pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn);
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, &bRetry
);
if( bRetry ){
assert( rc==SQLITE_OK );
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, ALLBITS, 0, p, mNoOmit, &bIn, 0
);
}
/* If the call to xBestIndex() with all terms enabled produced a plan
** that does not require any source tables (IOW: a plan with mBest==0)
@@ -3774,7 +3830,7 @@ static int whereLoopAddVirtual(
if( bIn ){
WHERETRACE(0x40, (" VirtualOne: all usable w/o IN\n"));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn);
pBuilder, mPrereq, ALLBITS, WO_IN, p, mNoOmit, &bIn, 0);
assert( bIn==0 );
mBestNoIn = pNew->prereq & ~mPrereq;
if( mBestNoIn==0 ){
@@ -3801,7 +3857,7 @@ static int whereLoopAddVirtual(
WHERETRACE(0x40, (" VirtualOne: mPrev=%04llx mNext=%04llx\n",
(sqlite3_uint64)mPrev, (sqlite3_uint64)mNext));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn);
pBuilder, mPrereq, mNext|mPrereq, 0, p, mNoOmit, &bIn, 0);
if( pNew->prereq==mPrereq ){
seenZero = 1;
if( bIn==0 ) seenZeroNoIN = 1;
@@ -3814,7 +3870,7 @@ static int whereLoopAddVirtual(
if( rc==SQLITE_OK && seenZero==0 ){
WHERETRACE(0x40, (" VirtualOne: all disabled\n"));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn);
pBuilder, mPrereq, mPrereq, 0, p, mNoOmit, &bIn, 0);
if( bIn==0 ) seenZeroNoIN = 1;
}
@@ -3824,7 +3880,7 @@ static int whereLoopAddVirtual(
if( rc==SQLITE_OK && seenZeroNoIN==0 ){
WHERETRACE(0x40, (" VirtualOne: all disabled and w/o IN\n"));
rc = whereLoopAddVirtualOne(
pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn);
pBuilder, mPrereq, mPrereq, WO_IN, p, mNoOmit, &bIn, 0);
}
}
@@ -3873,7 +3929,6 @@ static int whereLoopAddOr(
int i, j;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
WHERETRACE(0x200, ("Begin processing OR-clause %p\n", pTerm));
@@ -5231,6 +5286,7 @@ WhereInfo *sqlite3WhereBegin(
Expr *pWhere, /* The WHERE clause */
ExprList *pOrderBy, /* An ORDER BY (or GROUP BY) clause, or NULL */
ExprList *pResultSet, /* Query result set. Req'd for DISTINCT */
Select *pLimit, /* Use this LIMIT/OFFSET clause, if any */
u16 wctrlFlags, /* The WHERE_* flags defined in sqliteInt.h */
int iAuxArg /* If WHERE_OR_SUBCLAUSE is set, index cursor number
** If WHERE_USE_LIMIT, then the limit amount */
@@ -5265,7 +5321,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
@@ -5308,6 +5363,9 @@ WhereInfo *sqlite3WhereBegin(
pWInfo->wctrlFlags = wctrlFlags;
pWInfo->iLimit = iAuxArg;
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
#ifndef SQLITE_OMIT_VIRTUALTABLE
pWInfo->pLimit = pLimit;
#endif
memset(&pWInfo->nOBSat, 0,
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
@@ -5376,6 +5434,7 @@ WhereInfo *sqlite3WhereBegin(
/* Analyze all of the subexpressions. */
sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC);
sqlite3WhereAddLimit(&pWInfo->sWC, pLimit);
if( db->mallocFailed ) goto whereBeginError;
/* Special case: WHERE terms that do not refer to any tables in the join
@@ -5475,9 +5534,10 @@ WhereInfo *sqlite3WhereBegin(
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
pWInfo->revMask = ALLBITS;
}
if( pParse->nErr || db->mallocFailed ){
if( pParse->nErr ){
goto whereBeginError;
}
assert( db->mallocFailed==0 );
#ifdef WHERETRACE_ENABLED
if( sqlite3WhereTrace ){
sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
+7 -2
View File
@@ -123,7 +123,8 @@ struct WhereLoop {
} btree;
struct { /* Information for virtual tables */
int idxNum; /* Index number */
u8 needFree; /* True if sqlite3_free(idxStr) is needed */
u8 needFree : 1; /* True if sqlite3_free(idxStr) is needed */
u8 bOmitOffset : 1; /* True to let virtual table handle offset */
i8 isOrdered; /* True if satisfies ORDER BY */
u16 omitMask; /* Terms that may be omitted */
char *idxStr; /* Index identifier string */
@@ -386,7 +387,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
@@ -454,6 +454,9 @@ struct WhereInfo {
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
ExprList *pResultSet; /* Result set of the query */
Expr *pWhere; /* The complete WHERE clause */
#ifndef SQLITE_OMIT_VIRTUALTABLE
Select *pLimit; /* Used to access LIMIT expr/registers for vtabs */
#endif
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
int iContinue; /* Jump here to continue with next record */
int iBreak; /* Jump here to break out of the loop */
@@ -539,6 +542,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
void sqlite3WhereClauseInit(WhereClause*,WhereInfo*);
void sqlite3WhereClauseClear(WhereClause*);
void sqlite3WhereSplit(WhereClause*,Expr*,u8);
void sqlite3WhereAddLimit(WhereClause*, Select*);
Bitmask sqlite3WhereExprUsage(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprUsageNN(WhereMaskSet*, Expr*);
Bitmask sqlite3WhereExprListUsage(WhereMaskSet*, ExprList*);
@@ -609,5 +613,6 @@ void sqlite3WhereTabFuncArgs(Parse*, SrcItem*, WhereClause*);
#define WHERE_TRANSCONS 0x00200000 /* Uses a transitive constraint */
#define WHERE_BLOOMFILTER 0x00400000 /* Consider using a Bloom-filter */
#define WHERE_SELFCULL 0x00800000 /* nOut reduced by extra WHERE terms */
#define WHERE_OMIT_OFFSET 0x01000000 /* Set offset counter to zero */
#endif /* !defined(SQLITE_WHEREINT_H) */
+16 -3
View File
@@ -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
@@ -838,7 +841,8 @@ static int codeAllEqualityTerms(
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
if( pParse->db->mallocFailed==0 && pParse->nErr==0 ){
if( pParse->nErr==0 ){
assert( pParse->db->mallocFailed==0 );
if( sqlite3CompareAffinity(pRight, zAff[j])==SQLITE_AFF_BLOB ){
zAff[j] = SQLITE_AFF_BLOB;
}
@@ -1533,6 +1537,15 @@ Bitmask sqlite3WhereCodeOneLoopStart(
}else{
Expr *pRight = pTerm->pExpr->pRight;
codeExprOrVector(pParse, pRight, iTarget, 1);
if( pTerm->eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET
&& pLoop->u.vtab.bOmitOffset
){
assert( pTerm->eOperator==WO_AUX );
assert( pWInfo->pLimit!=0 );
assert( pWInfo->pLimit->iOffset>0 );
sqlite3VdbeAddOp2(v, OP_Integer, 0, pWInfo->pLimit->iOffset);
VdbeComment((v,"Zero OFFSET counter"));
}
}
}
sqlite3VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg);
@@ -2354,9 +2367,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
/* Loop through table entries that match term pOrTerm. */
ExplainQueryPlan((pParse, 1, "INDEX %d", ii+1));
WHERETRACE(0xffff, ("Subplan for OR-clause:\n"));
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, 0,
WHERE_OR_SUBCLAUSE, iCovCur);
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
assert( pSubWInfo || pParse->nErr );
if( pSubWInfo ){
WhereLoop *pSubLoop;
int addrExplain = sqlite3WhereExplainOneScan(
+113 -1
View File
@@ -1379,7 +1379,10 @@ static void exprAnalyze(
** no longer used.
**
** This is only required if at least one side of the comparison operation
** is not a sub-select. */
** is not a sub-select.
**
** tag-20220128a
*/
if( (pExpr->op==TK_EQ || pExpr->op==TK_IS)
&& (nLeft = sqlite3ExprVectorSize(pExpr->pLeft))>1
&& sqlite3ExprVectorSize(pExpr->pRight)==nLeft
@@ -1522,6 +1525,113 @@ void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
}
}
/*
** Add either a LIMIT (if eMatchOp==SQLITE_INDEX_CONSTRAINT_LIMIT) or
** OFFSET (if eMatchOp==SQLITE_INDEX_CONSTRAINT_OFFSET) term to the
** where-clause passed as the first argument. The value for the term
** is found in register iReg.
**
** In the common case where the value is a simple integer
** (example: "LIMIT 5 OFFSET 10") then the expression codes as a
** TK_INTEGER so that it will be available to sqlite3_vtab_rhs_value().
** If not, then it codes as a TK_REGISTER expression.
*/
void whereAddLimitExpr(
WhereClause *pWC, /* Add the constraint to this WHERE clause */
int iReg, /* Register that will hold value of the limit/offset */
Expr *pExpr, /* Expression that defines the limit/offset */
int iCsr, /* Cursor to which the constraint applies */
int eMatchOp /* SQLITE_INDEX_CONSTRAINT_LIMIT or _OFFSET */
){
Parse *pParse = pWC->pWInfo->pParse;
sqlite3 *db = pParse->db;
Expr *pNew;
int iVal = 0;
if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
if( pVal==0 ) return;
ExprSetProperty(pVal, EP_IntValue);
pVal->u.iValue = iVal;
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
}else{
Expr *pVal = sqlite3Expr(db, TK_REGISTER, 0);
if( pVal==0 ) return;
pVal->iTable = iReg;
pNew = sqlite3PExpr(pParse, TK_MATCH, 0, pVal);
}
if( pNew ){
WhereTerm *pTerm;
int idx;
idx = whereClauseInsert(pWC, pNew, TERM_DYNAMIC|TERM_VIRTUAL);
pTerm = &pWC->a[idx];
pTerm->leftCursor = iCsr;
pTerm->eOperator = WO_AUX;
pTerm->eMatchOp = eMatchOp;
}
}
/*
** Possibly add terms corresponding to the LIMIT and OFFSET clauses of the
** SELECT statement passed as the second argument. These terms are only
** added if:
**
** 1. The SELECT statement has a LIMIT clause, and
** 2. The SELECT statement is not an aggregate or DISTINCT query, and
** 3. The SELECT statement has exactly one object in its from clause, and
** that object is a virtual table, and
** 4. There are no terms in the WHERE clause that will not be passed
** to the virtual table xBestIndex method.
** 5. The ORDER BY clause, if any, will be made available to the xBestIndex
** method.
**
** LIMIT and OFFSET terms are ignored by most of the planner code. They
** exist only so that they may be passed to the xBestIndex method of the
** single virtual table in the FROM clause of the SELECT.
*/
void sqlite3WhereAddLimit(WhereClause *pWC, Select *p){
assert( p==0 || (p->pGroupBy==0 && (p->selFlags & SF_Aggregate)==0) );
if( (p && p->pLimit) /* 1 */
&& (p->selFlags & (SF_Distinct|SF_Aggregate))==0 /* 2 */
&& (p->pSrc->nSrc==1 && IsVirtual(p->pSrc->a[0].pTab)) /* 3 */
){
ExprList *pOrderBy = p->pOrderBy;
int iCsr = p->pSrc->a[0].iCursor;
int ii;
/* Check condition (4). Return early if it is not met. */
for(ii=0; ii<pWC->nTerm; ii++){
if( pWC->a[ii].wtFlags & TERM_CODED ){
/* This term is a vector operation that has been decomposed into
** other, subsequent terms. It can be ignored. See tag-20220128a */
assert( pWC->a[ii].wtFlags & TERM_VIRTUAL );
assert( pWC->a[ii].eOperator==0 );
continue;
}
if( pWC->a[ii].leftCursor!=iCsr ) return;
}
/* Check condition (5). Return early if it is not met. */
if( pOrderBy ){
for(ii=0; ii<pOrderBy->nExpr; ii++){
Expr *pExpr = pOrderBy->a[ii].pExpr;
if( pExpr->op!=TK_COLUMN ) return;
if( NEVER(pExpr->iTable!=iCsr) ) return;
if( pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_BIGNULL ) return;
}
}
/* All conditions are met. Add the terms to the where-clause object. */
assert( p->pLimit->op==TK_LIMIT );
whereAddLimitExpr(pWC, p->iLimit, p->pLimit->pLeft,
iCsr, SQLITE_INDEX_CONSTRAINT_LIMIT);
if( p->iOffset>0 ){
whereAddLimitExpr(pWC, p->iOffset, p->pLimit->pRight,
iCsr, SQLITE_INDEX_CONSTRAINT_OFFSET);
}
}
}
/*
** Initialize a preallocated WhereClause structure.
*/
@@ -1557,6 +1667,7 @@ void sqlite3WhereClauseClear(WhereClause *pWC){
}
#endif
while(1){
assert( a->eMatchOp==0 || a->eOperator==WO_AUX );
if( a->wtFlags & TERM_DYNAMIC ){
sqlite3ExprDelete(db, a->pExpr);
}
@@ -1714,6 +1825,7 @@ void sqlite3WhereTabFuncArgs(
pColRef->iColumn = k++;
assert( ExprUseYTab(pColRef) );
pColRef->y.pTab = pTab;
pItem->colUsed |= sqlite3ExprColUsed(pColRef);
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
+1 -6
View File
@@ -1106,12 +1106,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
sqlite3ParserAddCleanup(pParse, sqlite3DbFree, pTab);
}
if( rc ){
if( pParse->nErr==0 ){
assert( pParse->db->mallocFailed );
sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
}
}
assert( rc==SQLITE_OK || pParse->nErr!=0 );
return rc;
}
+149
View File
@@ -0,0 +1,149 @@
# 2022-01-27
#
# 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 testing date and time functions.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# Skip this whole file if date and time functions are omitted
# at compile-time
#
ifcapable {!datetime} {
finish_test
return
}
proc datetest {tnum expr result} {
do_test date3-$tnum [subst {
execsql "SELECT coalesce($expr,'NULL')"
}] [list $result]
}
set tcl_precision 15
# EVIDENCE-OF: R-45708-63005 unixepoch(time-value, modifier, modifier,
# ...)
#
datetest 1.1 {unixepoch('1970-01-01')} {0}
datetest 1.2 {unixepoch('1969-12-31 23:59:59')} {-1}
datetest 1.3 {unixepoch('2106-02-07 06:28:15')} {4294967295}
datetest 1.4 {unixepoch('2106-02-07 06:28:16')} {4294967296}
datetest 1.5 {unixepoch('9999-12-31 23:59:59')} {253402300799}
datetest 1.6 {unixepoch('0000-01-01 00:00:00')} {-62167219200}
# EVIDENCE-OF: R-30877-63179 The unixepoch() function returns a unix
# timestamp - the number of seconds since 1970-01-01 00:00:00 UTC.
#
for {set i 1} {$i<=100} {incr i} {
set x [expr {int(rand()*0xfffffffff)-0xffffffff}]
datetest 1.7.$i "unixepoch($x,'unixepoch')==$x" {1}
}
# EVIDENCE-OF: R-62992-54137 The unixepoch() always returns an integer,
# even if the input time-value has millisecond precision.
#
datetest 1.8 {unixepoch('2022-01-27 12:59:28.052')} {1643288368}
# EVIDENCE-OF: R-05412-24332 If the time-value is numeric (the
# DDDDDDDDDD format) then the 'auto' modifier causes the time-value to
# interpreted as either a julian day number or a unix timestamp,
# depending on its magnitude.
#
# EVIDENCE-OF: R-56763-40111 If the value is between 0.0 and
# 5373484.499999, then it is interpreted as a julian day number
# (corresponding to dates between -4713-11-24 12:00:00 and 9999-12-31
# 23:59:59, inclusive).
#
# EVIDENCE-OF: R-07289-49223 For numeric values outside of the range of
# valid julian day numbers, but within the range of -210866760000 to
# 253402300799, the 'auto' modifier causes the value to be interpreted
# as a unix timestamp.
#
# EVIDENCE-OF: R-20795-34947 Other numeric values are out of range and
# cause a NULL return.
#
foreach {tn jd date} {
2.1 0.0 {-4713-11-24 12:00:00}
2.2 5373484.4999999 {9999-12-31 23:59:59}
2.3 2440587.5 {1970-01-01 00:00:00}
2.4 2440587.49998843 {1969-12-31 23:59:59}
2.5 2440615.7475463 {1970-01-29 05:56:28}
2.10 -1 {1969-12-31 23:59:59}
2.11 5373485 {1970-03-04 04:38:05}
2.12 -210866760000 {-4713-11-24 12:00:00}
2.13 253402300799 {9999-12-31 23:59:59}
2.20 -210866760001 {NULL}
2.21 253402300800 {NULL}
} {
datetest $tn "datetime($jd,'auto')" $date
}
# EVIDENCE-OF: R-38886-35357 The 'auto' modifier is a no-op for text
# time-values.
#
datetest 2.30 {date('2022-01-29','auto')==date('2022-01-29')} {1}
# EVIDENCE-OF: R-53132-26856 The 'auto' modifier can be used to work
# with date/time values even in cases where it is not known if the
# julian day number or unix timestamp formats are in use.
#
do_execsql_test date3-2.40 {
WITH tx(timeval,datetime) AS (
VALUES('2022-01-27 13:15:44','2022-01-27 13:15:44'),
(2459607.05260275,'2022-01-27 13:15:44'),
(1643289344,'2022-01-27 13:15:44')
)
SELECT datetime(timeval,'auto') == datetime FROM tx;
} {1 1 1}
# EVIDENCE-OF: R-49255-55373 The "unixepoch" modifier (11) only works if
# it immediately follows a time value in the DDDDDDDDDD format.
#
# EVIDENCE-OF: R-23075-39245 This modifier causes the DDDDDDDDDD to be
# interpreted not as a Julian day number as it normally would be, but as
# Unix Time - the number of seconds since 1970.
#
datetest 3.1 {datetime(2459607.05,'+1 hour','unixepoch')} {NULL}
datetest 3.2 {datetime(2459607.05,'unixepoch','+1 hour')} {1970-01-29 12:13:27}
# EVIDENCE-OF: R-21150-52363 The "julianday" modifier must immediately
# follow the initial time-value which must be of the form DDDDDDDDD.
#
# EVIDENCE-OF: R-31176-64601 Any other use of the 'julianday' modifier
# is an error and causes the function to return NULL.
#
# EVIDENCE-OF: R-32483-36353 The 'julianday' modifier forces the
# time-value number to be interpreted as a julian-day number.
#
# EVIDENCE-OF: R-25859-20124 The only difference is that adding
# 'julianday' forces the DDDDDDDDD time-value format, and causes a NULL
# to be returned if any other time-value format is used.
#
datetest 4.1 {datetime(2459607,'julianday')} {2022-01-27 12:00:00}
datetest 4.2 {datetime(2459607,'+1 hour','julianday')} {NULL}
datetest 4.3 {datetime('2022-01-27','julianday')} {NULL}
# EVIDENCE-OF: R-33431-18865 Unix timestamps for the first 63 days of
# 1970 will be interpreted as julian day numbers.
#
do_execsql_test date3-5.0 {
WITH inc(x) AS (VALUES(-10) UNION ALL SELECT x+1 FROM inc WHERE x<100)
SELECT count(*) FROM inc
WHERE datetime('1970-01-01',format('%+d days',x))
<> datetime(unixepoch('1970-01-01',format('%+d days',x)),'auto');
} {63}
finish_test
+4 -7
View File
@@ -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
View File
@@ -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 {
BIN
View File
Binary file not shown.
+11 -8
View File
@@ -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');
+15
View File
@@ -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
+8
View File
@@ -19,6 +19,7 @@
# shell4-1.*: Basic tests specific to the "stats" command.
# shell4-2.*: Basic tests for ".trace"
# shell4-3.*: The ".read" command takes the shell out of interactive mode
# shell4-4.*: Input redirects cannot recurse too much
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -138,4 +139,11 @@ do_test shell4-3.2 {
exec $::CLI :memory: --interactive ".read t1.txt"
} {pound: £}
do_test shell4-4.1 {
set fd [open t1.txt wb]
puts $fd ".read t1.txt"
close $fd
catchcmd ":memory:" ".read t1.txt"
} {1 {Input nesting limit (25) reached at line 1. Check recursion.}}
finish_test
+41
View File
@@ -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