mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
Generalize the IS and IS NOT operators so that their right-hand side can be
an arbitrary expression and not simple the constant NULL. They work like = and <> except that NULL values compare equal to one another an unequal to everything else. FossilOrigin-Name: 98853f6104076c50ea92175e17a3254bfbbd4619
This commit is contained in:
@@ -19,6 +19,7 @@ END {
|
|||||||
printf "#define TK_%-29s %4d\n", "TO_NUMERIC", ++max
|
printf "#define TK_%-29s %4d\n", "TO_NUMERIC", ++max
|
||||||
printf "#define TK_%-29s %4d\n", "TO_INT", ++max
|
printf "#define TK_%-29s %4d\n", "TO_INT", ++max
|
||||||
printf "#define TK_%-29s %4d\n", "TO_REAL", ++max
|
printf "#define TK_%-29s %4d\n", "TO_REAL", ++max
|
||||||
|
printf "#define TK_%-29s %4d\n", "ISNOT", ++max
|
||||||
printf "#define TK_%-29s %4d\n", "END_OF_FILE", ++max
|
printf "#define TK_%-29s %4d\n", "END_OF_FILE", ++max
|
||||||
printf "#define TK_%-29s %4d\n", "ILLEGAL", ++max
|
printf "#define TK_%-29s %4d\n", "ILLEGAL", ++max
|
||||||
printf "#define TK_%-29s %4d\n", "SPACE", ++max
|
printf "#define TK_%-29s %4d\n", "SPACE", ++max
|
||||||
|
|||||||
26
manifest
26
manifest
@@ -1,8 +1,8 @@
|
|||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
-----BEGIN PGP SIGNED MESSAGE-----
|
||||||
Hash: SHA1
|
Hash: SHA1
|
||||||
|
|
||||||
C Factor\sthe\sUMINUS\sand\sUPLUS\stokens\sout\sof\sthe\sparser\sso\sthat\sthe\sparser\ntables\scan\sgo\sback\sto\susing\s8-bit\svalues\sinstead\sof\s16-bit\svalues.
|
C Generalize\sthe\sIS\sand\sIS\sNOT\soperators\sso\sthat\stheir\sright-hand\sside\scan\sbe\nan\sarbitrary\sexpression\sand\snot\ssimple\sthe\sconstant\sNULL.\s\sThey\swork\slike\n=\sand\s<>\sexcept\sthat\sNULL\svalues\scompare\sequal\sto\sone\sanother\san\sunequal\sto\neverything\selse.
|
||||||
D 2009-09-22T20:08:35
|
D 2009-09-23T02:29:37
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
|
F Makefile.in 4ca3f1dd6efa2075bcb27f4dc43eef749877740d
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -10,7 +10,7 @@ F Makefile.vxworks 10010ddbf52e2503c7c49c7c0b7c7a096f8638a6
|
|||||||
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
|
||||||
F VERSION 7260e7baf934051dee42458206e915b75570f41d
|
F VERSION 7260e7baf934051dee42458206e915b75570f41d
|
||||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||||
F addopcodes.awk 08eb3bdfef10a131530e3ad7fa1a6902a52dad15
|
F addopcodes.awk 17dc593f791f874d2c23a0f9360850ded0286531
|
||||||
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
|
F art/2005osaward.gif 0d1851b2a7c1c9d0ccce545f3e14bca42d7fd248
|
||||||
F art/SQLite.eps 9b43cc99cfd2be687d386faea6862ea68d6a72b2
|
F art/SQLite.eps 9b43cc99cfd2be687d386faea6862ea68d6a72b2
|
||||||
F art/SQLite.gif 1bbb94484963f1382e27e1c5e86dd0c1061eba2b
|
F art/SQLite.gif 1bbb94484963f1382e27e1c5e86dd0c1061eba2b
|
||||||
@@ -117,7 +117,7 @@ F src/callback.c 10d237171472865f58fb07d515737238c9e06688
|
|||||||
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
||||||
F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
|
F src/date.c 657ff12ca0f1195b531561afacbb38b772d16638
|
||||||
F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931
|
F src/delete.c 15499f5d10047d38e68ce991b3f88cbddb6e0931
|
||||||
F src/expr.c 638b599adad562d41c3bf90f542f9419664aa7b8
|
F src/expr.c 8a663240f374a5326ee157df3d27751f58b7676a
|
||||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||||
F src/fkey.c fa1ad144926a8536e23cbbf64c0e51b8f2fdd4bf
|
F src/fkey.c fa1ad144926a8536e23cbbf64c0e51b8f2fdd4bf
|
||||||
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
|
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
|
||||||
@@ -153,7 +153,7 @@ F src/os_unix.c 5369272992c14dd198c02ddfc2fd7a1516906c40
|
|||||||
F src/os_win.c 49a360be4f42d5a63d00be9aa44449ed4d6717e0
|
F src/os_win.c 49a360be4f42d5a63d00be9aa44449ed4d6717e0
|
||||||
F src/pager.c ebd0a8f2421e8f0ad5b78201440004bf3e1c96d8
|
F src/pager.c ebd0a8f2421e8f0ad5b78201440004bf3e1c96d8
|
||||||
F src/pager.h 11852d044c86cf5a9d6e34171fb0c4fcf1f6265f
|
F src/pager.h 11852d044c86cf5a9d6e34171fb0c4fcf1f6265f
|
||||||
F src/parse.y 749f39fa218418a19c46970336c2343214e2fe05
|
F src/parse.y 563ecc9e633bbb465383667380aff1646ecd96f7
|
||||||
F src/pcache.c c92ffd4f3e1279b3766854c6d18b5bf4aac0d1fa
|
F src/pcache.c c92ffd4f3e1279b3766854c6d18b5bf4aac0d1fa
|
||||||
F src/pcache.h 435ef324197f79391f9c92b71d7f92b548ad7a36
|
F src/pcache.h 435ef324197f79391f9c92b71d7f92b548ad7a36
|
||||||
F src/pcache1.c 211295a9ff6a5b30f1ca50516731a5cf3e9bf82c
|
F src/pcache1.c 211295a9ff6a5b30f1ca50516731a5cf3e9bf82c
|
||||||
@@ -167,7 +167,7 @@ F src/select.c 1d0a13137532321b4364f964e46f057d271691e3
|
|||||||
F src/shell.c d0171721c7402b368e257ddfc09ed54d0c74070c
|
F src/shell.c d0171721c7402b368e257ddfc09ed54d0c74070c
|
||||||
F src/sqlite.h.in 5af8181f815831a8672c3834c60e6b4418448bcc
|
F src/sqlite.h.in 5af8181f815831a8672c3834c60e6b4418448bcc
|
||||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||||
F src/sqliteInt.h 6a949ccf79ae441ac37f0d3033204895aa2a9e6a
|
F src/sqliteInt.h 35f0d4203924272b5ae849c88b7b857eda3bb272
|
||||||
F src/sqliteLimit.h 504a3161886d2938cbd163054ad620b8356df758
|
F src/sqliteLimit.h 504a3161886d2938cbd163054ad620b8356df758
|
||||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||||
@@ -209,7 +209,7 @@ F src/update.c 4fac66ecaea13c9c13e7d3de8da66aae3cce90e2
|
|||||||
F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30
|
F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30
|
||||||
F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
|
F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
|
||||||
F src/vacuum.c 869d08eaab64e2a4eaf4ef9ea34b851892b65a75
|
F src/vacuum.c 869d08eaab64e2a4eaf4ef9ea34b851892b65a75
|
||||||
F src/vdbe.c 03857c07b8d159eb86ff559138d2eb5317cbfe32
|
F src/vdbe.c 4946e2ac1124b0cb0ee882ed7628d2d8b339b8ef
|
||||||
F src/vdbe.h 7d5075e3fa4e5587a9be8d5e503857c825490cef
|
F src/vdbe.h 7d5075e3fa4e5587a9be8d5e503857c825490cef
|
||||||
F src/vdbeInt.h 546ed25cad488c053819e19d09751d71d3ce3601
|
F src/vdbeInt.h 546ed25cad488c053819e19d09751d71d3ce3601
|
||||||
F src/vdbeapi.c 524d79eb17bbcbe31c37c908b8e01edc5c684a90
|
F src/vdbeapi.c 524d79eb17bbcbe31c37c908b8e01edc5c684a90
|
||||||
@@ -756,14 +756,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
|
||||||
P 55b263fa2b2fed8c721154e3c48f4226be95065c
|
P 3fc938c961fd7810594224b91a2d6e1ac9e48084
|
||||||
R eef40f23e9c60a6f8dbfd20ac239494a
|
R d99ab25244fa05bd56d10d71bb3bee44
|
||||||
U drh
|
U drh
|
||||||
Z a26ff37b38b185f4ba103e5a00635dcb
|
Z 4608482892179163853473e1fbf42a31
|
||||||
-----BEGIN PGP SIGNATURE-----
|
-----BEGIN PGP SIGNATURE-----
|
||||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
Version: GnuPG v1.4.6 (GNU/Linux)
|
||||||
|
|
||||||
iD8DBQFKuS7GoxKgR168RlERArmIAJ9Zh9EPcETkJ903DGxflMeqs+sSrQCfRsQh
|
iD8DBQFKuYgUoxKgR168RlERApeHAJ48L4oeCXw8ZV6ov3G5+bjNMfQIewCfX/Rc
|
||||||
N09u5KCVOpvUNYJvUIHJJug=
|
qXj8iamFDJ6JXwF0VP/iAOI=
|
||||||
=Nr38
|
=lSDQ
|
||||||
-----END PGP SIGNATURE-----
|
-----END PGP SIGNATURE-----
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
3fc938c961fd7810594224b91a2d6e1ac9e48084
|
98853f6104076c50ea92175e17a3254bfbbd4619
|
||||||
41
src/expr.c
41
src/expr.c
@@ -152,7 +152,7 @@ static char comparisonAffinity(Expr *pExpr){
|
|||||||
char aff;
|
char aff;
|
||||||
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
|
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
|
||||||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
|
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
|
||||||
pExpr->op==TK_NE );
|
pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
|
||||||
assert( pExpr->pLeft );
|
assert( pExpr->pLeft );
|
||||||
aff = sqlite3ExprAffinity(pExpr->pLeft);
|
aff = sqlite3ExprAffinity(pExpr->pLeft);
|
||||||
if( pExpr->pRight ){
|
if( pExpr->pRight ){
|
||||||
@@ -2244,6 +2244,19 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TK_IS:
|
||||||
|
case TK_ISNOT: {
|
||||||
|
testcase( op==TK_IS );
|
||||||
|
testcase( op==TK_ISNOT );
|
||||||
|
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||||
|
pExpr->pRight, &r2, ®Free2);
|
||||||
|
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||||
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
|
r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
|
||||||
|
testcase( regFree1==0 );
|
||||||
|
testcase( regFree2==0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TK_AND:
|
case TK_AND:
|
||||||
case TK_OR:
|
case TK_OR:
|
||||||
case TK_PLUS:
|
case TK_PLUS:
|
||||||
@@ -3018,6 +3031,19 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TK_IS:
|
||||||
|
case TK_ISNOT: {
|
||||||
|
testcase( op==TK_IS );
|
||||||
|
testcase( op==TK_ISNOT );
|
||||||
|
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||||
|
pExpr->pRight, &r2, ®Free2);
|
||||||
|
op = (op==TK_IS) ? TK_EQ : TK_NE;
|
||||||
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
|
r1, r2, dest, SQLITE_NULLEQ);
|
||||||
|
testcase( regFree1==0 );
|
||||||
|
testcase( regFree2==0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
case TK_NOTNULL: {
|
case TK_NOTNULL: {
|
||||||
assert( TK_ISNULL==OP_IsNull );
|
assert( TK_ISNULL==OP_IsNull );
|
||||||
@@ -3167,6 +3193,19 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
|
|||||||
testcase( regFree2==0 );
|
testcase( regFree2==0 );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TK_IS:
|
||||||
|
case TK_ISNOT: {
|
||||||
|
testcase( op==TK_IS );
|
||||||
|
testcase( op==TK_ISNOT );
|
||||||
|
codeCompareOperands(pParse, pExpr->pLeft, &r1, ®Free1,
|
||||||
|
pExpr->pRight, &r2, ®Free2);
|
||||||
|
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
|
||||||
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
||||||
|
r1, r2, dest, SQLITE_NULLEQ);
|
||||||
|
testcase( regFree1==0 );
|
||||||
|
testcase( regFree2==0 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
case TK_ISNULL:
|
case TK_ISNULL:
|
||||||
case TK_NOTNULL: {
|
case TK_NOTNULL: {
|
||||||
testcase( op==TK_ISNULL );
|
testcase( op==TK_ISNULL );
|
||||||
|
|||||||
22
src/parse.y
22
src/parse.y
@@ -884,10 +884,26 @@ expr(A) ::= expr(X) likeop(OP) expr(Y) escape(E). [LIKE_KW] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
|
expr(A) ::= expr(X) ISNULL|NOTNULL(E). {spanUnaryPostfix(&A,pParse,@E,&X,&E);}
|
||||||
expr(A) ::= expr(X) IS NULL(E). {spanUnaryPostfix(&A,pParse,TK_ISNULL,&X,&E);}
|
|
||||||
expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
expr(A) ::= expr(X) NOT NULL(E). {spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
||||||
expr(A) ::= expr(X) IS NOT NULL(E).
|
|
||||||
{spanUnaryPostfix(&A,pParse,TK_NOTNULL,&X,&E);}
|
// expr1 IS expr2
|
||||||
|
// expr1 IS NOT expr2
|
||||||
|
//
|
||||||
|
// If expr2 is NULL then code as TK_ISNULL or TK_NOTNULL. If expr2
|
||||||
|
// is any other expression, code as TK_IS or TK_ISNOT.
|
||||||
|
//
|
||||||
|
expr(A) ::= expr(X) IS expr(Y). {
|
||||||
|
spanBinaryExpr(&A,pParse,TK_IS,&X,&Y);
|
||||||
|
if( pParse->db->mallocFailed==0 && Y.pExpr->op==TK_NULL ){
|
||||||
|
A.pExpr->op = TK_ISNULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr(A) ::= expr(X) IS NOT expr(Y). {
|
||||||
|
spanBinaryExpr(&A,pParse,TK_ISNOT,&X,&Y);
|
||||||
|
if( pParse->db->mallocFailed==0 && Y.pExpr->op==TK_NULL ){
|
||||||
|
A.pExpr->op = TK_NOTNULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
%include {
|
%include {
|
||||||
/* Construct an expression node for a unary prefix operator
|
/* Construct an expression node for a unary prefix operator
|
||||||
|
|||||||
@@ -1126,6 +1126,7 @@ struct CollSeq {
|
|||||||
*/
|
*/
|
||||||
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
|
#define SQLITE_JUMPIFNULL 0x08 /* jumps if either operand is NULL */
|
||||||
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
|
#define SQLITE_STOREP2 0x10 /* Store result in reg[P2] rather than jump */
|
||||||
|
#define SQLITE_NULLEQ 0x80 /* NULL=NULL */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An object of this type is created for each virtual table present in
|
** An object of this type is created for each virtual table present in
|
||||||
|
|||||||
88
src/vdbe.c
88
src/vdbe.c
@@ -1680,12 +1680,24 @@ case OP_ToReal: { /* same as TK_TO_REAL, in1 */
|
|||||||
** This works just like the Lt opcode except that the jump is taken if
|
** This works just like the Lt opcode except that the jump is taken if
|
||||||
** the operands in registers P1 and P3 are not equal. See the Lt opcode for
|
** the operands in registers P1 and P3 are not equal. See the Lt opcode for
|
||||||
** additional information.
|
** additional information.
|
||||||
|
**
|
||||||
|
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
|
||||||
|
** true or false and is never NULL. If both operands are NULL then the result
|
||||||
|
** of comparison is false. If either operand is NULL then the result is true.
|
||||||
|
** If neither operand is NULL the the result is the same as it would be if
|
||||||
|
** the SQLITE_NULLEQ flag were omitted from P5.
|
||||||
*/
|
*/
|
||||||
/* Opcode: Eq P1 P2 P3 P4 P5
|
/* Opcode: Eq P1 P2 P3 P4 P5
|
||||||
**
|
**
|
||||||
** This works just like the Lt opcode except that the jump is taken if
|
** This works just like the Lt opcode except that the jump is taken if
|
||||||
** the operands in registers P1 and P3 are equal.
|
** the operands in registers P1 and P3 are equal.
|
||||||
** See the Lt opcode for additional information.
|
** See the Lt opcode for additional information.
|
||||||
|
**
|
||||||
|
** If SQLITE_NULLEQ is set in P5 then the result of comparison is always either
|
||||||
|
** true or false and is never NULL. If both operands are NULL then the result
|
||||||
|
** of comparison is true. If either operand is NULL then the result is false.
|
||||||
|
** If neither operand is NULL the the result is the same as it would be if
|
||||||
|
** the SQLITE_NULLEQ flag were omitted from P5.
|
||||||
*/
|
*/
|
||||||
/* Opcode: Le P1 P2 P3 P4 P5
|
/* Opcode: Le P1 P2 P3 P4 P5
|
||||||
**
|
**
|
||||||
@@ -1711,37 +1723,46 @@ case OP_Lt: /* same as TK_LT, jump, in1, in3 */
|
|||||||
case OP_Le: /* same as TK_LE, jump, in1, in3 */
|
case OP_Le: /* same as TK_LE, jump, in1, in3 */
|
||||||
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
|
case OP_Gt: /* same as TK_GT, jump, in1, in3 */
|
||||||
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||||
int flags;
|
int res; /* Result of the comparison of pIn1 against pIn3 */
|
||||||
int res;
|
char affinity; /* Affinity to use for comparison */
|
||||||
char affinity;
|
|
||||||
|
|
||||||
flags = pIn1->flags|pIn3->flags;
|
if( (pIn1->flags | pIn3->flags)&MEM_Null ){
|
||||||
|
/* One or both operands are NULL */
|
||||||
if( flags&MEM_Null ){
|
if( pOp->p5 & SQLITE_NULLEQ ){
|
||||||
/* If either operand is NULL then the result is always NULL.
|
/* If SQLITE_NULLEQ is set (which will only happen if the operator is
|
||||||
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
|
** OP_Eq or OP_Ne) then take the jump or not depending on whether
|
||||||
*/
|
** or not both operands are null.
|
||||||
if( pOp->p5 & SQLITE_STOREP2 ){
|
*/
|
||||||
pOut = &p->aMem[pOp->p2];
|
assert( pOp->opcode==OP_Eq || pOp->opcode==OP_Ne );
|
||||||
MemSetTypeFlag(pOut, MEM_Null);
|
res = (pIn1->flags & pIn3->flags & MEM_Null)==0;
|
||||||
REGISTER_TRACE(pOp->p2, pOut);
|
}else{
|
||||||
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
/* SQLITE_NULLEQ is clear and at least one operand is NULL,
|
||||||
pc = pOp->p2-1;
|
** then the result is always NULL.
|
||||||
|
** The jump is taken if the SQLITE_JUMPIFNULL bit is set.
|
||||||
|
*/
|
||||||
|
if( pOp->p5 & SQLITE_STOREP2 ){
|
||||||
|
pOut = &p->aMem[pOp->p2];
|
||||||
|
MemSetTypeFlag(pOut, MEM_Null);
|
||||||
|
REGISTER_TRACE(pOp->p2, pOut);
|
||||||
|
}else if( pOp->p5 & SQLITE_JUMPIFNULL ){
|
||||||
|
pc = pOp->p2-1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* Neither operand is NULL. Do a comparison. */
|
||||||
|
affinity = pOp->p5 & SQLITE_AFF_MASK;
|
||||||
|
if( affinity ){
|
||||||
|
applyAffinity(pIn1, affinity, encoding);
|
||||||
|
applyAffinity(pIn3, affinity, encoding);
|
||||||
|
if( db->mallocFailed ) goto no_mem;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
affinity = pOp->p5 & SQLITE_AFF_MASK;
|
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
|
||||||
if( affinity ){
|
ExpandBlob(pIn1);
|
||||||
applyAffinity(pIn1, affinity, encoding);
|
ExpandBlob(pIn3);
|
||||||
applyAffinity(pIn3, affinity, encoding);
|
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
|
||||||
if( db->mallocFailed ) goto no_mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
|
|
||||||
ExpandBlob(pIn1);
|
|
||||||
ExpandBlob(pIn3);
|
|
||||||
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
|
|
||||||
switch( pOp->opcode ){
|
switch( pOp->opcode ){
|
||||||
case OP_Eq: res = res==0; break;
|
case OP_Eq: res = res==0; break;
|
||||||
case OP_Ne: res = res!=0; break;
|
case OP_Ne: res = res!=0; break;
|
||||||
@@ -1807,9 +1828,18 @@ case OP_Compare: {
|
|||||||
assert( n>0 );
|
assert( n>0 );
|
||||||
assert( pKeyInfo!=0 );
|
assert( pKeyInfo!=0 );
|
||||||
p1 = pOp->p1;
|
p1 = pOp->p1;
|
||||||
assert( p1>0 && p1+n<=p->nMem+1 );
|
|
||||||
p2 = pOp->p2;
|
p2 = pOp->p2;
|
||||||
assert( p2>0 && p2+n<=p->nMem+1 );
|
#if SQLITE_DEBUG
|
||||||
|
if( aPermute ){
|
||||||
|
int k, mx = 0;
|
||||||
|
for(k=0; k<n; k++) if( aPermute[k]>mx ) mx = aPermute[k];
|
||||||
|
assert( p1>0 && p1+mx<=p->nMem+1 );
|
||||||
|
assert( p2>0 && p2+mx<=p->nMem+1 );
|
||||||
|
}else{
|
||||||
|
assert( p1>0 && p1+n<=p->nMem+1 );
|
||||||
|
assert( p2>0 && p2+n<=p->nMem+1 );
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_DEBUG */
|
||||||
for(i=0; i<n; i++){
|
for(i=0; i<n; i++){
|
||||||
idx = aPermute ? aPermute[i] : i;
|
idx = aPermute ? aPermute[i] : i;
|
||||||
REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]);
|
REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]);
|
||||||
|
|||||||
Reference in New Issue
Block a user