mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-20 07:41:32 +03:00
Allow INDEXED BY and NOT INDEXED to be used in UPDATE and DELETE statements. (CVS 5772)
FossilOrigin-Name: 83a7e446b2d4846a6f92bd831a2adaa265f5a786
This commit is contained in:
24
manifest
24
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Add\sa\stest\sscript\sto\sverify\sthat\sticket\s#3419\sstays\sfixed.\s(CVS\s5771)
|
C Allow\sINDEXED\sBY\sand\sNOT\sINDEXED\sto\sbe\sused\sin\sUPDATE\sand\sDELETE\sstatements.\s(CVS\s5772)
|
||||||
D 2008-10-06T15:31:13
|
D 2008-10-06T16:18:40
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in e4ab842f9a64ef61d57093539a8aab76b12810db
|
F Makefile.in e4ab842f9a64ef61d57093539a8aab76b12810db
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -102,11 +102,11 @@ F src/btmutex.c 709cad2cdca0afd013f0f612363810e53f59ec53
|
|||||||
F src/btree.c 64a38df6f0a9997563418ed194984b81e4ab3694
|
F src/btree.c 64a38df6f0a9997563418ed194984b81e4ab3694
|
||||||
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
|
F src/btree.h 6371c5e599fab391a150c96afbc10062b276d107
|
||||||
F src/btreeInt.h e38e9b2b285f40f5bc0a6664f630d4a141622f16
|
F src/btreeInt.h e38e9b2b285f40f5bc0a6664f630d4a141622f16
|
||||||
F src/build.c 5097bb7978bfdae4ae052abc16aa00c1054b7956
|
F src/build.c 8714bd809583bbe07bf22d0e1808a3fc31abe330
|
||||||
F src/callback.c 7a40fd44da3eb89e7f6eff30aa6f940c45d73a97
|
F src/callback.c 7a40fd44da3eb89e7f6eff30aa6f940c45d73a97
|
||||||
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
|
F src/complete.c cb14e06dbe79dee031031f0d9e686ff306afe07c
|
||||||
F src/date.c 5c092296c03d658e84884121a694150964d6861d
|
F src/date.c 5c092296c03d658e84884121a694150964d6861d
|
||||||
F src/delete.c 52c3614b1dc815f54d64a98dc65a393737f68b91
|
F src/delete.c 924c43df7533479d0aa93dc0eed32c9b8cf64c9f
|
||||||
F src/expr.c 30973b017bf95ca767f5eec64918c8afc425488d
|
F src/expr.c 30973b017bf95ca767f5eec64918c8afc425488d
|
||||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||||
F src/func.c 8431b40a7843d1024145684d303c55b4ee087bbe
|
F src/func.c 8431b40a7843d1024145684d303c55b4ee087bbe
|
||||||
@@ -139,7 +139,7 @@ F src/os_unix.c f33b69d8a85372b270fe37ee664a4c2140a5217d
|
|||||||
F src/os_win.c 04033a86a39f49cb8e348f515eb0116aa9d36678
|
F src/os_win.c 04033a86a39f49cb8e348f515eb0116aa9d36678
|
||||||
F src/pager.c 44eba010e81dcc9b772401b90d6a1c61ec24345b
|
F src/pager.c 44eba010e81dcc9b772401b90d6a1c61ec24345b
|
||||||
F src/pager.h 9c1917be28fff58118e1fe0ddbc7adfb8dd4f44d
|
F src/pager.h 9c1917be28fff58118e1fe0ddbc7adfb8dd4f44d
|
||||||
F src/parse.y c69312dff9285f6638b209189d4166dd3a985c81
|
F src/parse.y d8edf095cd9f1a0083e6ff6b964396870523dc0d
|
||||||
F src/pcache.c f8d7beceba164a34441ac37e88abb3a404f968a7
|
F src/pcache.c f8d7beceba164a34441ac37e88abb3a404f968a7
|
||||||
F src/pcache.h 28d9ce2d66909db1f01652586450b62b64793093
|
F src/pcache.h 28d9ce2d66909db1f01652586450b62b64793093
|
||||||
F src/pragma.c 0b1c2d2a241dd79a7361bbeb8ff575a9e9d7cd71
|
F src/pragma.c 0b1c2d2a241dd79a7361bbeb8ff575a9e9d7cd71
|
||||||
@@ -147,11 +147,11 @@ F src/prepare.c c7e00ed1b0bdcf699b1aad651247d4dc3d281b0b
|
|||||||
F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
|
F src/printf.c 785f87120589c1db672e37c6eb1087c456e6f84d
|
||||||
F src/random.c 11bbdf7def3746a762fbdb56c9d04648135ad6d8
|
F src/random.c 11bbdf7def3746a762fbdb56c9d04648135ad6d8
|
||||||
F src/resolve.c 1971ff6996f1a73303339acf7f1de8497546045d
|
F src/resolve.c 1971ff6996f1a73303339acf7f1de8497546045d
|
||||||
F src/select.c 75d4ffe971e25831125ea165c0c580df00f4c403
|
F src/select.c 34f32ee034289d72aa459fef40565bb74c76af24
|
||||||
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
|
F src/shell.c d83b578a8ccdd3e0e7fef4388a0887ce9f810967
|
||||||
F src/sqlite.h.in ea235b37a691b32e7941baa70fb0afaf6377dbb4
|
F src/sqlite.h.in ea235b37a691b32e7941baa70fb0afaf6377dbb4
|
||||||
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
|
F src/sqlite3ext.h 1e3887c9bd3ae66cb599e922824b04cd0d0f2c3e
|
||||||
F src/sqliteInt.h 1806947aac72ba3ea6de3b9de5c66e3d257e8fe7
|
F src/sqliteInt.h 6c08ddc70e1c9b0581778543af6985342c5516f0
|
||||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||||
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
|
F src/table.c 22744786199c9195720c15a7a42cb97b2e2728d8
|
||||||
@@ -372,7 +372,7 @@ F test/incrvacuum_ioerr.test 57d2f5777ab13fa03b87b262a4ea1bad5cfc0291
|
|||||||
F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
|
F test/index.test cbf301cdb2da43e4eac636c3400c2439af1834ad
|
||||||
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
|
||||||
F test/index3.test 727d55dceb9a4ec36675057bb5becfc265e28ca6
|
F test/index3.test 727d55dceb9a4ec36675057bb5becfc265e28ca6
|
||||||
F test/indexedby.test 5e54a6b25ac619502a4960c1bf7ca93bb23da5df
|
F test/indexedby.test 03af52375e50d146e78f56442b6677d2932c4963
|
||||||
F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
|
F test/insert.test aef273dd1cee84cc92407469e6bd1b3cdcb76908
|
||||||
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
|
||||||
F test/insert3.test 9a4ef3526fd3cca8b05278020ec3100448b4c677
|
F test/insert3.test 9a4ef3526fd3cca8b05278020ec3100448b4c677
|
||||||
@@ -640,7 +640,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
|||||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||||
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
F tool/speedtest8.c 1dbced29de5f59ba2ebf877edcadf171540374d1
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
P 24891902fa625445aa47ae930f0cb340cc73d25d
|
P c3cf54a1b6bbaaeab4cab701c6cbbed02695facc
|
||||||
R 078d46958e9975c6cde4a1174680baa8
|
R ca83b644149fe533cdd795f52e48a148
|
||||||
U drh
|
U danielk1977
|
||||||
Z 32ce6a1b9f1606eebd07bae951617e0e
|
Z c3b964ea90e3130652cb73cc4202d059
|
||||||
|
@@ -1 +1 @@
|
|||||||
c3cf54a1b6bbaaeab4cab701c6cbbed02695facc
|
83a7e446b2d4846a6f92bd831a2adaa265f5a786
|
28
src/build.c
28
src/build.c
@@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.497 2008/10/06 05:32:19 danielk1977 Exp $
|
** $Id: build.c,v 1.498 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -3116,7 +3116,6 @@ SrcList *sqlite3SrcListAppendFromTerm(
|
|||||||
Token *pTable, /* Name of the table to add to the FROM clause */
|
Token *pTable, /* Name of the table to add to the FROM clause */
|
||||||
Token *pDatabase, /* Name of the database containing pTable */
|
Token *pDatabase, /* Name of the database containing pTable */
|
||||||
Token *pAlias, /* The right-hand side of the AS subexpression */
|
Token *pAlias, /* The right-hand side of the AS subexpression */
|
||||||
Token *pIndexedBy, /* Token from INDEXED BY clause, if any */
|
|
||||||
Select *pSubquery, /* A subquery used in place of a table name */
|
Select *pSubquery, /* A subquery used in place of a table name */
|
||||||
Expr *pOn, /* The ON clause of a join */
|
Expr *pOn, /* The ON clause of a join */
|
||||||
IdList *pUsing /* The USING clause of a join */
|
IdList *pUsing /* The USING clause of a join */
|
||||||
@@ -3134,19 +3133,30 @@ SrcList *sqlite3SrcListAppendFromTerm(
|
|||||||
if( pAlias && pAlias->n ){
|
if( pAlias && pAlias->n ){
|
||||||
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
|
pItem->zAlias = sqlite3NameFromToken(db, pAlias);
|
||||||
}
|
}
|
||||||
if( pIndexedBy && pIndexedBy->n==1 && !pIndexedBy->z ){
|
|
||||||
/* A "NOT INDEXED" clause was supplied. See parse.y
|
|
||||||
** construct "indexed_opt" for details. */
|
|
||||||
pItem->notIndexed = 1;
|
|
||||||
}else{
|
|
||||||
pItem->zIndex = sqlite3NameFromToken(db, pIndexedBy);
|
|
||||||
}
|
|
||||||
pItem->pSelect = pSubquery;
|
pItem->pSelect = pSubquery;
|
||||||
pItem->pOn = pOn;
|
pItem->pOn = pOn;
|
||||||
pItem->pUsing = pUsing;
|
pItem->pUsing = pUsing;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Add an INDEXED BY or NOT INDEXED clause to the most recently added
|
||||||
|
** element of the source-list passed as the second argument.
|
||||||
|
*/
|
||||||
|
void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
|
||||||
|
if( pIndexedBy && p && p->nSrc>0 ){
|
||||||
|
struct SrcList_item *pItem = &p->a[p->nSrc-1];
|
||||||
|
assert( pItem->notIndexed==0 && pItem->zIndex==0 );
|
||||||
|
if( pIndexedBy->n==1 && !pIndexedBy->z ){
|
||||||
|
/* A "NOT INDEXED" clause was supplied. See parse.y
|
||||||
|
** construct "indexed_opt" for details. */
|
||||||
|
pItem->notIndexed = 1;
|
||||||
|
}else{
|
||||||
|
pItem->zIndex = sqlite3NameFromToken(pParse->db, pIndexedBy);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** When building up a FROM clause in the parser, the join operator
|
** When building up a FROM clause in the parser, the join operator
|
||||||
** is initially attached to the left operand. But the code generator
|
** is initially attached to the left operand. But the code generator
|
||||||
|
13
src/delete.c
13
src/delete.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** in order to generate code for DELETE FROM statements.
|
** in order to generate code for DELETE FROM statements.
|
||||||
**
|
**
|
||||||
** $Id: delete.c,v 1.176 2008/10/06 05:32:19 danielk1977 Exp $
|
** $Id: delete.c,v 1.177 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -22,16 +22,17 @@
|
|||||||
** are found, return a pointer to the last table.
|
** are found, return a pointer to the last table.
|
||||||
*/
|
*/
|
||||||
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
|
||||||
Table *pTab = 0;
|
struct SrcList_item *pItem = pSrc->a;
|
||||||
int i;
|
Table *pTab;
|
||||||
struct SrcList_item *pItem;
|
assert( pItem && pSrc->nSrc==1 );
|
||||||
for(i=0, pItem=pSrc->a; i<pSrc->nSrc; i++, pItem++){
|
|
||||||
pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
|
pTab = sqlite3LocateTable(pParse, 0, pItem->zName, pItem->zDatabase);
|
||||||
sqlite3DeleteTable(pItem->pTab);
|
sqlite3DeleteTable(pItem->pTab);
|
||||||
pItem->pTab = pTab;
|
pItem->pTab = pTab;
|
||||||
if( pTab ){
|
if( pTab ){
|
||||||
pTab->nRef++;
|
pTab->nRef++;
|
||||||
}
|
}
|
||||||
|
if( sqlite3IndexedByLookup(pParse, pItem) ){
|
||||||
|
pTab = 0;
|
||||||
}
|
}
|
||||||
return pTab;
|
return pTab;
|
||||||
}
|
}
|
||||||
@@ -106,7 +107,7 @@ void sqlite3MaterializeView(
|
|||||||
pWhere = sqlite3ExprDup(db, pWhere);
|
pWhere = sqlite3ExprDup(db, pWhere);
|
||||||
viewName.z = (u8*)pView->zName;
|
viewName.z = (u8*)pView->zName;
|
||||||
viewName.n = (unsigned int)strlen((const char*)viewName.z);
|
viewName.n = (unsigned int)strlen((const char*)viewName.z);
|
||||||
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName,0,pDup,0,0);
|
pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
|
||||||
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
|
||||||
|
17
src/parse.y
17
src/parse.y
@@ -14,7 +14,7 @@
|
|||||||
** the parser. Lemon will also generate a header file containing
|
** the parser. Lemon will also generate a header file containing
|
||||||
** numeric codes for all of the tokens.
|
** numeric codes for all of the tokens.
|
||||||
**
|
**
|
||||||
** @(#) $Id: parse.y,v 1.253 2008/10/06 05:32:19 danielk1977 Exp $
|
** @(#) $Id: parse.y,v 1.254 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// All token codes are small integers with #defines that begin with "TK_"
|
// All token codes are small integers with #defines that begin with "TK_"
|
||||||
@@ -457,12 +457,13 @@ stl_prefix(A) ::= seltablist(X) joinop(Y). {
|
|||||||
}
|
}
|
||||||
stl_prefix(A) ::= . {A = 0;}
|
stl_prefix(A) ::= . {A = 0;}
|
||||||
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I) on_opt(N) using_opt(U). {
|
seltablist(A) ::= stl_prefix(X) nm(Y) dbnm(D) as(Z) indexed_opt(I) on_opt(N) using_opt(U). {
|
||||||
A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,&I,0,N,U);
|
A = sqlite3SrcListAppendFromTerm(pParse,X,&Y,&D,&Z,0,N,U);
|
||||||
|
sqlite3SrcListIndexedBy(pParse, A, &I);
|
||||||
}
|
}
|
||||||
%ifndef SQLITE_OMIT_SUBQUERY
|
%ifndef SQLITE_OMIT_SUBQUERY
|
||||||
seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
|
seltablist(A) ::= stl_prefix(X) LP seltablist_paren(S) RP
|
||||||
as(Z) on_opt(N) using_opt(U). {
|
as(Z) on_opt(N) using_opt(U). {
|
||||||
A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,0,S,N,U);
|
A = sqlite3SrcListAppendFromTerm(pParse,X,0,0,&Z,S,N,U);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A seltablist_paren nonterminal represents anything in a FROM that
|
// A seltablist_paren nonterminal represents anything in a FROM that
|
||||||
@@ -506,7 +507,7 @@ on_opt(N) ::= . {N = 0;}
|
|||||||
// in the token.
|
// in the token.
|
||||||
//
|
//
|
||||||
// If there is a "NOT INDEXED" clause, then (z==0 && n==1), which is
|
// If there is a "NOT INDEXED" clause, then (z==0 && n==1), which is
|
||||||
// normally illegal. The sqlite3SrcListAppendFromTerm() function
|
// normally illegal. The sqlite3SrcListIndexedBy() function
|
||||||
// recognizes and interprets this as a special case.
|
// recognizes and interprets this as a special case.
|
||||||
//
|
//
|
||||||
%type indexed_opt {Token}
|
%type indexed_opt {Token}
|
||||||
@@ -577,7 +578,10 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
|
|||||||
|
|
||||||
/////////////////////////// The DELETE statement /////////////////////////////
|
/////////////////////////// The DELETE statement /////////////////////////////
|
||||||
//
|
//
|
||||||
cmd ::= DELETE FROM fullname(X) where_opt(Y). {sqlite3DeleteFrom(pParse,X,Y);}
|
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(Y). {
|
||||||
|
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||||
|
sqlite3DeleteFrom(pParse,X,Y);
|
||||||
|
}
|
||||||
|
|
||||||
%type where_opt {Expr*}
|
%type where_opt {Expr*}
|
||||||
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
|
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}
|
||||||
@@ -587,7 +591,8 @@ where_opt(A) ::= WHERE expr(X). {A = X;}
|
|||||||
|
|
||||||
////////////////////////// The UPDATE command ////////////////////////////////
|
////////////////////////// The UPDATE command ////////////////////////////////
|
||||||
//
|
//
|
||||||
cmd ::= UPDATE orconf(R) fullname(X) SET setlist(Y) where_opt(Z). {
|
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(Z). {
|
||||||
|
sqlite3SrcListIndexedBy(pParse, X, &I);
|
||||||
sqlite3ExprListCheckLength(pParse,Y,"set list");
|
sqlite3ExprListCheckLength(pParse,Y,"set list");
|
||||||
sqlite3Update(pParse,X,Y,Z,R);
|
sqlite3Update(pParse,X,Y,Z,R);
|
||||||
}
|
}
|
||||||
|
39
src/select.c
39
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.477 2008/10/06 05:32:19 danielk1977 Exp $
|
** $Id: select.c,v 1.478 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -2882,6 +2882,31 @@ static int minMaxQuery(Parse *pParse, Select *p){
|
|||||||
return WHERE_ORDERBY_NORMAL;
|
return WHERE_ORDERBY_NORMAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If the source-list item passed as an argument was augmented with an
|
||||||
|
** INDEXED BY clause, then try to locate the specified index. If there
|
||||||
|
** was such a clause and the named index cannot be found, return
|
||||||
|
** SQLITE_ERROR and leave an error in pParse. Otherwise, populate
|
||||||
|
** pFrom->pIndex and return SQLITE_OK.
|
||||||
|
*/
|
||||||
|
int sqlite3IndexedByLookup(Parse *pParse, struct SrcList_item *pFrom){
|
||||||
|
if( pFrom->pTab && pFrom->zIndex ){
|
||||||
|
Table *pTab = pFrom->pTab;
|
||||||
|
char *zIndex = pFrom->zIndex;
|
||||||
|
Index *pIdx;
|
||||||
|
for(pIdx=pTab->pIndex;
|
||||||
|
pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
|
||||||
|
pIdx=pIdx->pNext
|
||||||
|
);
|
||||||
|
if( !pIdx ){
|
||||||
|
sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
|
||||||
|
return SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
pFrom->pIndex = pIdx;
|
||||||
|
}
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine is a Walker callback for "expanding" a SELECT statement.
|
** This routine is a Walker callback for "expanding" a SELECT statement.
|
||||||
** "Expanding" means to do the following:
|
** "Expanding" means to do the following:
|
||||||
@@ -2984,19 +3009,9 @@ static int selectExpander(Walker *pWalker, Select *p){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Locate the index named by the INDEXED BY clause, if any. */
|
/* Locate the index named by the INDEXED BY clause, if any. */
|
||||||
if( pFrom->zIndex ){
|
if( sqlite3IndexedByLookup(pParse, pFrom) ){
|
||||||
char *zIndex = pFrom->zIndex;
|
|
||||||
Index *pIdx;
|
|
||||||
for(pIdx=pTab->pIndex;
|
|
||||||
pIdx && sqlite3StrICmp(pIdx->zName, zIndex);
|
|
||||||
pIdx=pIdx->pNext
|
|
||||||
);
|
|
||||||
if( !pIdx ){
|
|
||||||
sqlite3ErrorMsg(pParse, "no such index: %s", zIndex, 0);
|
|
||||||
return WRC_Abort;
|
return WRC_Abort;
|
||||||
}
|
}
|
||||||
pFrom->pIndex = pIdx;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process NATURAL keywords, and ON and USING clauses of joins.
|
/* Process NATURAL keywords, and ON and USING clauses of joins.
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.774 2008/10/06 05:32:19 danielk1977 Exp $
|
** @(#) $Id: sqliteInt.h,v 1.775 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -2141,8 +2141,10 @@ void *sqlite3ArrayAllocate(sqlite3*,void*,int,int,int*,int*,int*);
|
|||||||
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
|
IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*);
|
||||||
int sqlite3IdListIndex(IdList*,const char*);
|
int sqlite3IdListIndex(IdList*,const char*);
|
||||||
SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
|
SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*);
|
||||||
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*, Token*,
|
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
|
||||||
Token*, Select*, Expr*, IdList*);
|
Token*, Select*, Expr*, IdList*);
|
||||||
|
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
|
||||||
|
int sqlite3IndexedByLookup(Parse *, struct SrcList_item *);
|
||||||
void sqlite3SrcListShiftJoinType(SrcList*);
|
void sqlite3SrcListShiftJoinType(SrcList*);
|
||||||
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
|
void sqlite3SrcListAssignCursors(Parse*, SrcList*);
|
||||||
void sqlite3IdListDelete(sqlite3*, IdList*);
|
void sqlite3IdListDelete(sqlite3*, IdList*);
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
#
|
#
|
||||||
#***********************************************************************
|
#***********************************************************************
|
||||||
#
|
#
|
||||||
# $Id: indexedby.test,v 1.2 2008/10/06 11:29:49 danielk1977 Exp $
|
# $Id: indexedby.test,v 1.3 2008/10/06 16:18:40 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -162,5 +162,47 @@ do_test indexedby-6.2 {
|
|||||||
EQP { SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid }
|
EQP { SELECT * FROM t1 NOT INDEXED WHERE b = 10 ORDER BY rowid }
|
||||||
} {0 0 {TABLE t1 USING PRIMARY KEY ORDER BY}}
|
} {0 0 {TABLE t1 USING PRIMARY KEY ORDER BY}}
|
||||||
|
|
||||||
|
# Test that "INDEXED BY" can be used in a DELETE statement.
|
||||||
|
#
|
||||||
|
do_test indexedby-7.1 {
|
||||||
|
EQP { DELETE FROM t1 WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-7.2 {
|
||||||
|
EQP { DELETE FROM t1 NOT INDEXED WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1}}
|
||||||
|
do_test indexedby-7.3 {
|
||||||
|
EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-7.4 {
|
||||||
|
EQP { DELETE FROM t1 INDEXED BY i1 WHERE a = 5 AND b = 10}
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-7.5 {
|
||||||
|
EQP { DELETE FROM t1 INDEXED BY i2 WHERE a = 5 AND b = 10}
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i2}}
|
||||||
|
do_test indexedby-7.6 {
|
||||||
|
catchsql { DELETE FROM t1 INDEXED BY i2 WHERE a = 5}
|
||||||
|
} {1 {cannot use index: i2}}
|
||||||
|
|
||||||
|
# Test that "INDEXED BY" can be used in an UPDATE statement.
|
||||||
|
#
|
||||||
|
do_test indexedby-8.1 {
|
||||||
|
EQP { UPDATE t1 SET rowid=rowid+1 WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-8.2 {
|
||||||
|
EQP { UPDATE t1 NOT INDEXED SET rowid=rowid+1 WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1}}
|
||||||
|
do_test indexedby-8.3 {
|
||||||
|
EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 }
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-8.4 {
|
||||||
|
EQP { UPDATE t1 INDEXED BY i1 SET rowid=rowid+1 WHERE a = 5 AND b = 10}
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i1}}
|
||||||
|
do_test indexedby-8.5 {
|
||||||
|
EQP { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5 AND b = 10}
|
||||||
|
} {0 0 {TABLE t1 WITH INDEX i2}}
|
||||||
|
do_test indexedby-8.6 {
|
||||||
|
catchsql { UPDATE t1 INDEXED BY i2 SET rowid=rowid+1 WHERE a = 5}
|
||||||
|
} {1 {cannot use index: i2}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user