mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-07 02:42:48 +03:00
Fix for ticket #813. (CVS 1818)
FossilOrigin-Name: 88e4bfa154e33c627ff2abb15cc55a100359d370
This commit is contained in:
13
manifest
13
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Store\sschema\scookies\son\sthe\sTEMP\sdatabase.\s\sTicket\s#807.\s(CVS\s1817)
|
C Fix\sfor\sticket\s#813.\s(CVS\s1818)
|
||||||
D 2004-07-19T17:25:25
|
D 2004-07-19T19:14:01
|
||||||
F Makefile.in 77d1219b6563476711a7a962e865979a6f314eb0
|
F Makefile.in 77d1219b6563476711a7a962e865979a6f314eb0
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -80,7 +80,7 @@ F src/vdbeInt.h 7160653a006b6d2c4a00d204112a095bdf842ab6
|
|||||||
F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355
|
F src/vdbeapi.c c5c6d8f162a9581dde497b1a4034f9a0bf54c355
|
||||||
F src/vdbeaux.c 4de85e30ca4a83ea0a45eceb7e88ac7a48f4c237
|
F src/vdbeaux.c 4de85e30ca4a83ea0a45eceb7e88ac7a48f4c237
|
||||||
F src/vdbemem.c bbf621377343bee046547712a144a94f387bb1eb
|
F src/vdbemem.c bbf621377343bee046547712a144a94f387bb1eb
|
||||||
F src/where.c 504e1df3d7d9eb74175088e532d1d7ee17f50ac7
|
F src/where.c 9009033f311281934d946ecaba759cd65b9dbea8
|
||||||
F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016
|
F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016
|
||||||
F test/attach.test 3acdffccbf5f78b07746771b9490758718e28856
|
F test/attach.test 3acdffccbf5f78b07746771b9490758718e28856
|
||||||
F test/attach2.test b175333059e86c82dbf593fc922522ecb0f8aff8
|
F test/attach2.test b175333059e86c82dbf593fc922522ecb0f8aff8
|
||||||
@@ -126,6 +126,7 @@ F test/ioerr.test 7d087bfd1a1a53442940e000df936e0df0c5b886
|
|||||||
F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd
|
F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd
|
||||||
F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
|
F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8
|
||||||
F test/join3.test 8d989e52413199065bd630b3d0a6b2329d173099
|
F test/join3.test 8d989e52413199065bd630b3d0a6b2329d173099
|
||||||
|
F test/join4.test 9e8754291d412e68dbb04e460b9255fcb17d09a4
|
||||||
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
|
F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718
|
||||||
F test/laststmtchanges.test 417aa27eb2b5cdfafb46e390e2c9ddd0a20eba43
|
F test/laststmtchanges.test 417aa27eb2b5cdfafb46e390e2c9ddd0a20eba43
|
||||||
F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d
|
F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d
|
||||||
@@ -236,7 +237,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
|||||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P b36e6e4907716e048fb21903e234578596c7333d
|
P c6c13dc460094e6adea2b14849edf9f485238b99
|
||||||
R 27d8d1ff5e4a09c10df4c3b7ad31e5bc
|
R 1efcd7bc4407c0074ce67844f3b21f8a
|
||||||
U drh
|
U drh
|
||||||
Z 9bdf2c5059de01392d40fdc6b41ce812
|
Z c2f019b3c66ef29f590cae938431831e
|
||||||
|
@@ -1 +1 @@
|
|||||||
c6c13dc460094e6adea2b14849edf9f485238b99
|
88e4bfa154e33c627ff2abb15cc55a100359d370
|
55
src/where.c
55
src/where.c
@@ -12,7 +12,7 @@
|
|||||||
** This module contains C code that generates VDBE code used to process
|
** This module contains C code that generates VDBE code used to process
|
||||||
** the WHERE clause of SQL statements.
|
** the WHERE clause of SQL statements.
|
||||||
**
|
**
|
||||||
** $Id: where.c,v 1.109 2004/07/19 17:25:25 drh Exp $
|
** $Id: where.c,v 1.110 2004/07/19 19:14:01 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -280,6 +280,35 @@ static Index *findSortingIndex(
|
|||||||
return pMatch;
|
return pMatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Disable a term in the WHERE clause. Except, do not disable the term
|
||||||
|
** if it controls a LEFT OUTER JOIN and it did not originate in the ON
|
||||||
|
** or USING clause of that join.
|
||||||
|
**
|
||||||
|
** Consider the term t2.z='ok' in the following queries:
|
||||||
|
**
|
||||||
|
** (1) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x WHERE t2.z='ok'
|
||||||
|
** (2) SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.x AND t2.z='ok'
|
||||||
|
** (3) SELECT * FROM t1, t2 WHERE t1.a=t2.x AND t2.z='ok'
|
||||||
|
**
|
||||||
|
** The t2.z='ok' is disabled in the in (2) because it did not originate
|
||||||
|
** in the ON clause. The term is disabled in (3) because it is not part
|
||||||
|
** of a LEFT OUTER JOIN. In (1), the term is not disabled.
|
||||||
|
**
|
||||||
|
** Disabling a term causes that term to not be tested in the inner loop
|
||||||
|
** of the join. Disabling is an optimization. We would get the correct
|
||||||
|
** results if nothing were ever disabled, but joins might run a little
|
||||||
|
** slower. The trick is to disable as much as we can without disabling
|
||||||
|
** too much. If we disabled in (1), we'd get the wrong answer.
|
||||||
|
** See ticket #813.
|
||||||
|
*/
|
||||||
|
static void disableTerm(WhereLevel *pLevel, Expr **ppExpr){
|
||||||
|
Expr *pExpr = *ppExpr;
|
||||||
|
if( pLevel->iLeftJoin==0 || ExprHasProperty(pExpr, EP_FromJoin) ){
|
||||||
|
*ppExpr = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate the beginning of the loop used for WHERE clause processing.
|
** Generate the beginning of the loop used for WHERE clause processing.
|
||||||
** The return value is a pointer to an (opaque) structure that contains
|
** The return value is a pointer to an (opaque) structure that contains
|
||||||
@@ -760,7 +789,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
}else{
|
}else{
|
||||||
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
||||||
}
|
}
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
|
cont = pLevel->cont = sqlite3VdbeMakeLabel(v);
|
||||||
sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
|
sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);
|
||||||
haveKey = 0;
|
haveKey = 0;
|
||||||
@@ -789,7 +818,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
|
if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
|
||||||
if( pX->op==TK_EQ ){
|
if( pX->op==TK_EQ ){
|
||||||
sqlite3ExprCode(pParse, pX->pRight);
|
sqlite3ExprCode(pParse, pX->pRight);
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( pX->op==TK_IN && nColumn==1 ){
|
if( pX->op==TK_IN && nColumn==1 ){
|
||||||
@@ -798,7 +827,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0);
|
pLevel->inP2 = sqlite3VdbeAddOp(v, OP_IdxColumn, pX->iTable, 0);
|
||||||
pLevel->inOp = OP_Next;
|
pLevel->inOp = OP_Next;
|
||||||
pLevel->inP1 = pX->iTable;
|
pLevel->inP1 = pX->iTable;
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,7 +840,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
char idxaff = pIdx->pTable->aCol[pX->pRight->iColumn].affinity;
|
char idxaff = pIdx->pTable->aCol[pX->pRight->iColumn].affinity;
|
||||||
if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
|
if( sqlite3IndexAffinityOk(aExpr[k].p, idxaff) ){
|
||||||
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -883,7 +912,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
sqlite3VdbeAddOp(v, OP_ForceInt,
|
sqlite3VdbeAddOp(v, OP_ForceInt,
|
||||||
aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
|
aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);
|
||||||
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
|
sqlite3VdbeAddOp(v, OP_MoveGe, iCur, brk);
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
}else{
|
}else{
|
||||||
sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
|
sqlite3VdbeAddOp(v, OP_Rewind, iCur, brk);
|
||||||
}
|
}
|
||||||
@@ -905,7 +934,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
}else{
|
}else{
|
||||||
testOp = OP_Gt;
|
testOp = OP_Gt;
|
||||||
}
|
}
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
}
|
}
|
||||||
start = sqlite3VdbeCurrentAddr(v);
|
start = sqlite3VdbeCurrentAddr(v);
|
||||||
pLevel->op = OP_Next;
|
pLevel->op = OP_Next;
|
||||||
@@ -960,7 +989,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
|
&& aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]
|
||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, aExpr[k].p->pRight);
|
sqlite3ExprCode(pParse, aExpr[k].p->pRight);
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( aExpr[k].idxRight==iCur
|
if( aExpr[k].idxRight==iCur
|
||||||
@@ -969,7 +998,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
&& aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]
|
||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
sqlite3ExprCode(pParse, aExpr[k].p->pLeft);
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1006,7 +1035,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||||
leFlag = pExpr->op==TK_LE;
|
leFlag = pExpr->op==TK_LE;
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( aExpr[k].idxRight==iCur
|
if( aExpr[k].idxRight==iCur
|
||||||
@@ -1016,7 +1045,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||||
leFlag = pExpr->op==TK_GE;
|
leFlag = pExpr->op==TK_GE;
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1063,7 +1092,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, pExpr->pRight);
|
sqlite3ExprCode(pParse, pExpr->pRight);
|
||||||
geFlag = pExpr->op==TK_GE;
|
geFlag = pExpr->op==TK_GE;
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( aExpr[k].idxRight==iCur
|
if( aExpr[k].idxRight==iCur
|
||||||
@@ -1073,7 +1102,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
){
|
){
|
||||||
sqlite3ExprCode(pParse, pExpr->pLeft);
|
sqlite3ExprCode(pParse, pExpr->pLeft);
|
||||||
geFlag = pExpr->op==TK_LE;
|
geFlag = pExpr->op==TK_LE;
|
||||||
aExpr[k].p = 0;
|
disableTerm(pLevel, &aExpr[k].p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
78
test/join4.test
Normal file
78
test/join4.test
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# 2002 May 24
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
# This file implements tests for left outer joins containing WHERE
|
||||||
|
# clauses that restrict the scope of the left term of the join.
|
||||||
|
#
|
||||||
|
# $Id: join4.test,v 1.1 2004/07/19 19:14:01 drh Exp $
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
do_test join4-1.1 {
|
||||||
|
execsql {
|
||||||
|
create temp table t1(a integer, b varchar(10));
|
||||||
|
insert into t1 values(1,'one');
|
||||||
|
insert into t1 values(2,'two');
|
||||||
|
insert into t1 values(3,'three');
|
||||||
|
insert into t1 values(4,'four');
|
||||||
|
|
||||||
|
create temp table t2(x integer, y varchar(10), z varchar(10));
|
||||||
|
insert into t2 values(2,'niban','ok');
|
||||||
|
insert into t2 values(4,'yonban','err');
|
||||||
|
}
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
|
||||||
|
}
|
||||||
|
} {2 two 2 niban ok}
|
||||||
|
do_test join4-1.2 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
|
||||||
|
}
|
||||||
|
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||||
|
do_test join4-1.3 {
|
||||||
|
execsql {
|
||||||
|
create index i2 on t2(z);
|
||||||
|
}
|
||||||
|
btree_breakpoint
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x where t2.z='ok'
|
||||||
|
}
|
||||||
|
} {2 two 2 niban ok}
|
||||||
|
do_test join4-1.4 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x and t2.z='ok'
|
||||||
|
}
|
||||||
|
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||||
|
do_test join4-1.5 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x where t2.z>='ok'
|
||||||
|
}
|
||||||
|
} {2 two 2 niban ok}
|
||||||
|
do_test join4-1.4 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x and t2.z>='ok'
|
||||||
|
}
|
||||||
|
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||||
|
do_test join4-1.6 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x where t2.z IN ('ok')
|
||||||
|
}
|
||||||
|
} {2 two 2 niban ok}
|
||||||
|
do_test join4-1.7 {
|
||||||
|
execsql {
|
||||||
|
select * from t1 left outer join t2 on t1.a=t2.x and t2.z IN ('ok')
|
||||||
|
}
|
||||||
|
} {1 one {} {} {} 2 two 2 niban ok 3 three {} {} {} 4 four {} {} {}}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
Reference in New Issue
Block a user