From: drh Date: Mon, 24 Aug 2015 20:21:20 +0000 (+0000) Subject: Enhances the parser so that it accepts arbitrary expressions for the arguments X-Git-Tag: version-3.9.0~192 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=108aa00a87e19312fa04b9cbaf98c8587128ab86;p=thirdparty%2Fsqlite.git Enhances the parser so that it accepts arbitrary expressions for the arguments of an index, though the code generator still rejects everything other than simple column names. The sqlite3RestrictColumnListSyntax() routine is removed since that feature is now handled by the parser. FossilOrigin-Name: bed42116addabcf3dfdc2e2d51ae183965704988 --- diff --git a/manifest b/manifest index ac41156aae..bc354b2e92 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sCREATE\sVIEW\ssyntax\sso\sthat\sthe\snames\sof\scolumns\sof\sthe\sview\scan\nbe\sspecified\safter\sthe\sview\sname. -D 2015-08-24T17:42:49.622 +C Enhances\sthe\sparser\sso\sthat\sit\saccepts\sarbitrary\sexpressions\sfor\sthe\sarguments\nof\san\sindex,\sthough\sthe\scode\sgenerator\sstill\srejects\severything\sother\sthan\nsimple\scolumn\snames.\s\sThe\ssqlite3RestrictColumnListSyntax()\sroutine\sis\sremoved\nsince\sthat\sfeature\sis\snow\shandled\sby\sthe\sparser. +D 2015-08-24T20:21:20.985 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in e2218eb228374422969de7b1680eda6864affcef F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -282,14 +282,14 @@ F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btree.c f48b3ef91676c06a90a8832987ecef6b94c931ee F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1 F src/btreeInt.h 8177c9ab90d772d6d2c6c517e05bed774b7c92c0 -F src/build.c a4e2669bc59729589b7e3867c58eae5a4f2419ff +F src/build.c 789e75f3478ac63c0f398a131c49a0802c356c2b F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/complete.c addcd8160b081131005d5bc2d34adf20c1c5c92f F src/ctime.c 5a0b735dc95604766f5dac73973658eef782ee8b F src/date.c 8ec787fed4929d8ccdf6b1bc360fccc3e1d2ca58 F src/dbstat.c f402e77e25089c6003d0c60b3233b9b3947d599a F src/delete.c 8857a6f27560718f65d43bdbec86c967ae1f8dfa -F src/expr.c c05d67f1a03c097d5c29839d5a538cfde9c472ce +F src/expr.c 650ac7c4f659980a3315e2aaa02a0d71e87f14a5 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c c9b63a217d86582c22121699a47f22f524608869 F src/func.c 824bea430d3a2b7dbc62806ad54da8fdb8ed9e3f @@ -326,7 +326,7 @@ F src/os_win.c 40b3af7a47eb1107d0d69e592bec345a3b7b798a F src/os_win.h eb7a47aa17b26b77eb97e4823f20a00b8bda12ca F src/pager.c aa916ca28606ccf4b6877dfc2b643ccbca86589f F src/pager.h 6d435f563b3f7fcae4b84433b76a6ac2730036e2 -F src/parse.y 07f2084f9ec157b108f1bf12466277d6f17b59d1 +F src/parse.y f599aa5e871a493330d567ced93de696f61f48f7 F src/pcache.c cde06aa50962595e412d497e22fd2e07878ba1f0 F src/pcache.h 9968603796240cdf83da7e7bef76edf90619cea9 F src/pcache1.c a3fe31b17e841ec70beee72a2c960e9c787a8857 @@ -342,7 +342,7 @@ F src/shell.c b1f91e60918df3a68efad1e3a11696b9a7e23d23 F src/sqlite.h.in 378bebc8fe6a88bade25e5f23b7e6123fdc64b00 F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3ext.h f700e6a9dd1fdcccc9951ab022b366fb66b9e413 -F src/sqliteInt.h 79a8e76bcbe67170d371ae2a08c85cc2d7cd0caf +F src/sqliteInt.h edbcd0c0787541a636a25ab1d1eaf847dbd043f1 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/status.c f266ad8a2892d659b74f0f50cb6a88b6e7c12179 F src/table.c 51b46b2a62d1b3a959633d593b89bab5e2c9155e @@ -910,7 +910,7 @@ F test/pagerfault2.test caf4c7facb914fd3b03a17b31ae2b180c8d6ca1f F test/pagerfault3.test 1003fcda009bf48a8e22a516e193b6ef0dd1bbd8 F test/pageropt.test 6b8f6a123a5572c195ad4ae40f2987007923bbd6 F test/pagesize.test 5769fc62d8c890a83a503f67d47508dfdc543305 -F test/parser1.test 23867b6f2c4758c7774108826d9f17e9cd17bcde +F test/parser1.test 222b5cbf3e2e659fec1bf7d723488c8b9c94f1d0 F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442 F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff @@ -1312,7 +1312,7 @@ F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972 F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d F test/with1.test a1e8660be88e2eb4648f8860f831d1e38b5b5443 -F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775 +F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87 F test/withM.test e97f2a8c506ab3ea9eab94e6f6072f6cc924c991 F test/without_rowid1.test 1a7b9bd51b899928d327052df9741d2fe8dbe701 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 @@ -1379,7 +1379,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 48bd54594752d5be3337f12c72f28d2080cb630b F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P a1ae20cd97456a1126cfa1a9bedce0bac0940ad6 -R 7c6b5f2ebead0dd2f6f395aca9a96d64 +P d794b34da6f9c77dfe17773b0b17b22de72cce7f +R 551ba7ed9667cd3021493a6e99ba80fb U drh -Z 9176898b8b319f8964514d527c2d8cd5 +Z 12005a1b68dc81ba8d64d2d3b63a147c diff --git a/manifest.uuid b/manifest.uuid index 358a0a2590..defc8a5329 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d794b34da6f9c77dfe17773b0b17b22de72cce7f \ No newline at end of file +bed42116addabcf3dfdc2e2d51ae183965704988 \ No newline at end of file diff --git a/src/build.c b/src/build.c index 815b17deb8..8a7dda89c1 100644 --- a/src/build.c +++ b/src/build.c @@ -1310,11 +1310,15 @@ void sqlite3AddPrimaryKey( }else{ nTerm = pList->nExpr; for(i=0; inCol; iCol++){ - if( sqlite3StrICmp(pList->a[i].zName, pTab->aCol[iCol].zName)==0 ){ - pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; - zType = pTab->aCol[iCol].zType; - break; + Expr *pCExpr = sqlite3ExprSkipCollate(pList->a[i].pExpr); + if( pCExpr && pCExpr->op==TK_ID ){ + const char *zCName = pCExpr->u.zToken; + for(iCol=0; iColnCol; iCol++){ + if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){ + pTab->aCol[iCol].colFlags |= COLFLAG_PRIMKEY; + zType = pTab->aCol[iCol].zType; + break; + } } } } @@ -1696,10 +1700,12 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){ */ if( pTab->iPKey>=0 ){ ExprList *pList; - pList = sqlite3ExprListAppend(pParse, 0, 0); + Token ipkToken; + ipkToken.z = pTab->aCol[pTab->iPKey].zName; + ipkToken.n = sqlite3Strlen30(ipkToken.z); + pList = sqlite3ExprListAppend(pParse, 0, + sqlite3ExprAlloc(db, TK_ID, &ipkToken, 0)); if( pList==0 ) return; - pList->a[0].zName = sqlite3DbStrDup(pParse->db, - pTab->aCol[pTab->iPKey].zName); pList->a[0].sortOrder = pParse->iPkSortOrder; assert( pParse->pNewTable==pTab ); pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0); @@ -2076,7 +2082,6 @@ void sqlite3CreateView( return; } sqlite3StartTable(pParse, pName1, pName2, isTemp, 1, 0, noErr); - sqlite3RestrictColumnListSyntax(pParse, pCNames); p = pParse->pNewTable; if( p==0 || pParse->nErr ) goto create_view_fail; sqlite3TwoPartName(pParse, pName1, pName2, &pName); @@ -2607,8 +2612,6 @@ void sqlite3CreateForeignKey( assert( pTo!=0 ); if( p==0 || IN_DECLARE_VTAB ) goto fk_end; - sqlite3RestrictColumnListSyntax(pParse, pFromCol); - sqlite3RestrictColumnListSyntax(pParse, pToCol); if( pFromCol==0 ){ int iCol = p->nCol-1; if( NEVER(iCol<0) ) goto fk_end; @@ -3043,12 +3046,16 @@ Index *sqlite3CreateIndex( ** So create a fake list to simulate this. */ if( pList==0 ){ - pList = sqlite3ExprListAppend(pParse, 0, 0); + Token prevCol; + prevCol.z = pTab->aCol[pTab->nCol-1].zName; + prevCol.n = sqlite3Strlen30(prevCol.z); + pList = sqlite3ExprListAppend(pParse, 0, + sqlite3ExprAlloc(db, TK_ID, &prevCol, 0)); if( pList==0 ) goto exit_create_index; - pList->a[0].zName = sqlite3DbStrDup(pParse->db, - pTab->aCol[pTab->nCol-1].zName); assert( pList->nExpr==1 ); sqlite3ExprListSetSortOrder(pList, sortOrder); + }else{ + sqlite3ExprListCheckLength(pParse, pList, "index"); } /* Figure out how many bytes of space are required to store explicitly @@ -3056,8 +3063,7 @@ Index *sqlite3CreateIndex( */ for(i=0; inExpr; i++){ Expr *pExpr = pList->a[i].pExpr; - if( pExpr ){ - assert( pExpr->op==TK_COLLATE ); + if( pExpr && pExpr->op==TK_COLLATE ){ nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken)); } } @@ -3109,10 +3115,17 @@ Index *sqlite3CreateIndex( ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; inExpr; i++, pListItem++){ - const char *zColName = pListItem->zName; + const char *zColName; + Expr *pCExpr; int requestedSortOrder; char *zColl; /* Collation sequence name */ + pCExpr = sqlite3ExprSkipCollate(pListItem->pExpr); + if( pCExpr->op!=TK_ID ){ + sqlite3ErrorMsg(pParse, "indexes on expressions not yet supported"); + continue; + } + zColName = pCExpr->u.zToken; for(j=0, pTabCol=pTab->aCol; jnCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } @@ -3124,9 +3137,8 @@ Index *sqlite3CreateIndex( } assert( j<=0x7fff ); pIndex->aiColumn[i] = (i16)j; - if( pListItem->pExpr ){ + if( pListItem->pExpr->op==TK_COLLATE ){ int nColl; - assert( pListItem->pExpr->op==TK_COLLATE ); zColl = pListItem->pExpr->u.zToken; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); @@ -4293,32 +4305,6 @@ KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){ return pKey; } -/* -** Generate a syntax error if the expression list provided contains -** any COLLATE or ASC or DESC keywords. -** -** Some legacy versions of SQLite allowed constructs like: -** -** CREATE TABLE x(..., FOREIGN KEY(x COLLATE binary DESC) REFERENCES...); -** ^^^^^^^^^^^^^^^^^^^ -** -** The COLLATE and sort order terms were ignored. To prevent compatibility -** problems in case something like this appears in a legacy sqlite_master -** table, only enforce the restriction on new SQL statements, not when -** parsing the schema out of the sqlite_master table. -*/ -void sqlite3RestrictColumnListSyntax(Parse *pParse, ExprList *p){ - int i; - if( p==0 || pParse->db->init.busy ) return; - for(i=0; inExpr; i++){ - if( p->a[i].pExpr!=0 || p->a[i].bDefinedSO ){ - sqlite3ErrorMsg(pParse, "syntax error after column name \"%w\"", - p->a[i].zName); - return; - } - } -} - #ifndef SQLITE_OMIT_CTE /* ** This routine is invoked once per CTE by the parser while parsing a @@ -4335,8 +4321,6 @@ With *sqlite3WithAdd( With *pNew; char *zName; - sqlite3RestrictColumnListSyntax(pParse, pArglist); - /* Check that the CTE name is unique within this WITH clause. If ** not, store an error in the Parse structure. */ zName = sqlite3NameFromToken(pParse->db, pName); diff --git a/src/expr.c b/src/expr.c index 1c57ecc6fd..1aebef6b16 100644 --- a/src/expr.c +++ b/src/expr.c @@ -1172,7 +1172,6 @@ void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){ return; } p->a[p->nExpr-1].sortOrder = (u8)iSortOrder; - p->a[p->nExpr-1].bDefinedSO = 1; } /* diff --git a/src/parse.y b/src/parse.y index acd899449e..e99feeefc1 100644 --- a/src/parse.y +++ b/src/parse.y @@ -301,7 +301,7 @@ ccons ::= PRIMARY KEY sortorder(Z) onconf(R) autoinc(I). {sqlite3AddPrimaryKey(pParse,0,R,I,Z);} ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0,0,0);} ccons ::= CHECK LP expr(X) RP. {sqlite3AddCheckConstraint(pParse,X.pExpr);} -ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R). +ccons ::= REFERENCES nm(T) eidlist_opt(TA) refargs(R). {sqlite3CreateForeignKey(pParse,0,&T,TA,R);} ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);} ccons ::= COLLATE ids(C). {sqlite3AddCollateType(pParse, &C);} @@ -345,14 +345,14 @@ conslist ::= tcons. tconscomma ::= COMMA. {pParse->constraintName.n = 0;} tconscomma ::= . tcons ::= CONSTRAINT nm(X). {pParse->constraintName = X;} -tcons ::= PRIMARY KEY LP idxlist(X) autoinc(I) RP onconf(R). +tcons ::= PRIMARY KEY LP sortlist(X) autoinc(I) RP onconf(R). {sqlite3AddPrimaryKey(pParse,X,R,I,0);} -tcons ::= UNIQUE LP idxlist(X) RP onconf(R). +tcons ::= UNIQUE LP sortlist(X) RP onconf(R). {sqlite3CreateIndex(pParse,0,0,0,X,R,0,0,0,0);} tcons ::= CHECK LP expr(E) RP onconf. {sqlite3AddCheckConstraint(pParse,E.pExpr);} -tcons ::= FOREIGN KEY LP idxlist(FA) RP - REFERENCES nm(T) idxlist_opt(TA) refargs(R) defer_subclause_opt(D). { +tcons ::= FOREIGN KEY LP eidlist(FA) RP + REFERENCES nm(T) eidlist_opt(TA) refargs(R) defer_subclause_opt(D). { sqlite3CreateForeignKey(pParse, FA, &T, TA, R); sqlite3DeferForeignKey(pParse, D); } @@ -386,7 +386,7 @@ ifexists(A) ::= . {A = 0;} ///////////////////// The CREATE VIEW statement ///////////////////////////// // %ifndef SQLITE_OMIT_VIEW -cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) idxlist_opt(C) +cmd ::= createkw(X) temp(T) VIEW ifnotexists(E) nm(Y) dbnm(Z) eidlist_opt(C) AS select(S). { sqlite3CreateView(pParse, &X, &Y, &Z, C, S, T, E); } @@ -674,6 +674,11 @@ using_opt(U) ::= . {U = 0;} %type orderby_opt {ExprList*} %destructor orderby_opt {sqlite3ExprListDelete(pParse->db, $$);} + +// the sortlist non-terminal stores a list of expression where each +// expression is optionally followed by ASC or DESC to indicate the +// sort order. +// %type sortlist {ExprList*} %destructor sortlist {sqlite3ExprListDelete(pParse->db, $$);} @@ -1208,7 +1213,7 @@ nexprlist(A) ::= expr(Y). ///////////////////////////// The CREATE INDEX command /////////////////////// // cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) - ON nm(Y) LP idxlist(Z) RP where_opt(W). { + ON nm(Y) LP sortlist(Z) RP where_opt(W). { sqlite3CreateIndex(pParse, &X, &D, sqlite3SrcListAppend(pParse->db,0,&Y,0), Z, U, &S, W, SQLITE_SO_ASC, NE); @@ -1218,31 +1223,64 @@ cmd ::= createkw(S) uniqueflag(U) INDEX ifnotexists(NE) nm(X) dbnm(D) uniqueflag(A) ::= UNIQUE. {A = OE_Abort;} uniqueflag(A) ::= . {A = OE_None;} -%type idxlist {ExprList*} -%destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);} -%type idxlist_opt {ExprList*} -%destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);} - -idxlist_opt(A) ::= . {A = 0;} -idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} -idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); - A = sqlite3ExprListAppend(pParse,X, p); - sqlite3ExprListSetName(pParse,A,&Y,1); - sqlite3ExprListCheckLength(pParse, A, "index"); - sqlite3ExprListSetSortOrder(A,Z); + +// The eidlist non-terminal (Expression Id List) generates an ExprList +// from a list of identifiers. The identifier names are in ExprList.a[].zName. +// This list is stored in an ExprList rather than an IdList so that it +// can be easily sent to sqlite3ColumnsExprList(). +// +// eidlist is grouped with CREATE INDEX because it used to be the non-terminal +// used for the arguments to an index. That is just an historical accident. +// +// IMPORTANT COMPATIBILITY NOTE: Some prior versions of SQLite accepted +// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate +// places - places that might have been stored in the sqlite_master schema. +// Those extra features were ignored. But because they might be in some +// (busted) old databases, we need to continue parsing them when loading +// historical schemas. +// +%type eidlist {ExprList*} +%destructor eidlist {sqlite3ExprListDelete(pParse->db, $$);} +%type eidlist_opt {ExprList*} +%destructor eidlist_opt {sqlite3ExprListDelete(pParse->db, $$);} + +%include { + /* Add a single new term to an ExprList that is used to store a + ** list of identifiers. Report an error if the ID list contains + ** a COLLATE clause or an ASC or DESC keyword, except ignore the + ** error while parsing a legacy schema. + */ + static ExprList *parserAddExprIdListTerm( + Parse *pParse, + ExprList *pPrior, + Token *pIdToken, + int hasCollate, + int sortOrder + ){ + ExprList *p = sqlite3ExprListAppend(pParse, pPrior, 0); + if( (hasCollate || sortOrder!=SQLITE_SO_UNDEFINED) + && pParse->db->init.busy==0 + ){ + sqlite3ErrorMsg(pParse, "syntax error after column name \"%.*s\"", + pIdToken->n, pIdToken->z); + } + sqlite3ExprListSetName(pParse, p, pIdToken, 1); + return p; + } +} // end %include + +eidlist_opt(A) ::= . {A = 0;} +eidlist_opt(A) ::= LP eidlist(X) RP. {A = X;} +eidlist(A) ::= eidlist(X) COMMA nm(Y) collate(C) sortorder(Z). { + A = parserAddExprIdListTerm(pParse, X, &Y, C, Z); } -idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { - Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C, 1); - A = sqlite3ExprListAppend(pParse,0, p); - sqlite3ExprListSetName(pParse, A, &Y, 1); - sqlite3ExprListCheckLength(pParse, A, "index"); - sqlite3ExprListSetSortOrder(A,Z); +eidlist(A) ::= nm(Y) collate(C) sortorder(Z). { + A = parserAddExprIdListTerm(pParse, 0, &Y, C, Z); } -%type collate {Token} -collate(C) ::= . {C.z = 0; C.n = 0;} -collate(C) ::= COLLATE ids(X). {C = X;} +%type collate {int} +collate(C) ::= . {C = 0;} +collate(C) ::= COLLATE ids. {C = 1;} ///////////////////////////// The DROP INDEX command ///////////////////////// @@ -1490,10 +1528,10 @@ with(A) ::= . {A = 0;} with(A) ::= WITH wqlist(W). { A = W; } with(A) ::= WITH RECURSIVE wqlist(W). { A = W; } -wqlist(A) ::= nm(X) idxlist_opt(Y) AS LP select(Z) RP. { +wqlist(A) ::= nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, 0, &X, Y, Z); } -wqlist(A) ::= wqlist(W) COMMA nm(X) idxlist_opt(Y) AS LP select(Z) RP. { +wqlist(A) ::= wqlist(W) COMMA nm(X) eidlist_opt(Y) AS LP select(Z) RP. { A = sqlite3WithAdd(pParse, W, &X, Y, Z); } %endif SQLITE_OMIT_CTE diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 5f12350538..4c17904ff8 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2189,7 +2189,6 @@ struct ExprList { unsigned done :1; /* A flag to indicate when processing is finished */ unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */ unsigned reusable :1; /* Constant expression is reusable */ - unsigned bDefinedSO :1; /* True if either DESC or ASC keywords present */ union { struct { u16 iOrderByCol; /* For ORDER BY, column number in result set */ @@ -3758,7 +3757,6 @@ const char *sqlite3JournalModename(int); int sqlite3Checkpoint(sqlite3*, int, int, int*, int*); int sqlite3WalDefaultHook(void*,sqlite3*,const char*,int); #endif -void sqlite3RestrictColumnListSyntax(Parse*,ExprList*); #ifndef SQLITE_OMIT_CTE With *sqlite3WithAdd(Parse*,With*,Token*,ExprList*,Select*); void sqlite3WithDelete(sqlite3*,With*); diff --git a/test/parser1.test b/test/parser1.test index f4c3227f87..78c1a40c63 100644 --- a/test/parser1.test +++ b/test/parser1.test @@ -21,7 +21,13 @@ do_catchsql_test parser1-1.1 { b TEXT, FOREIGN KEY(b COLLATE nocase DESC) REFERENCES t1(a COLLATE binary ASC) ); -} {1 {syntax error after column name "a"}} +} {1 {syntax error after column name "b"}} + + +# Verify that a legacy schema in the sqlite_master file is allowed to have +# COLLATE, ASC, and DESC keywords on the id list of a FK constraint, and that +# those keywords are silently ignored. +# do_execsql_test parser1-1.2 { CREATE TABLE t1( a TEXT PRIMARY KEY, @@ -42,7 +48,22 @@ do_test parser1-1.3 { sqlite3 db2 test.db db2 eval {SELECT * FROM t1 ORDER BY 1} } {abc {} xyz abc} +db2 close +do_execsql_test parser1-1.4 { + UPDATE sqlite_master SET sql='CREATE TABLE t1( + a TEXT PRIMARY KEY, + b TEXT, + FOREIGN KEY(b ASC) REFERENCES t1(a) + )' WHERE name='t1'; + SELECT name FROM sqlite_master WHERE sql LIKE '%ASC%'; +} {t1} +sqlite3 db2 test.db +do_test parser1-1.5 { + sqlite3 db2 test.db + db2 eval {SELECT * FROM t1 ORDER BY 1} +} {abc {} xyz abc} +db2 close do_catchsql_test parser1-2.1 { WITH RECURSIVE diff --git a/test/with2.test b/test/with2.test index eb0614729b..02d10b5112 100644 --- a/test/with2.test +++ b/test/with2.test @@ -250,7 +250,8 @@ do_execsql_test 4.4 [genstmt 255] 1 set nLimit [sqlite3_limit db SQLITE_LIMIT_COLUMN -1] do_execsql_test 4.5 [genstmt [expr $nLimit-1]] 1 do_execsql_test 4.6 [genstmt $nLimit] 1 -do_catchsql_test 4.7 [genstmt [expr $nLimit+1]] {1 {too many columns in index}} +do_catchsql_test 4.7 [genstmt [expr $nLimit+1]] \ + {1 {too many columns in result set}} #--------------------------------------------------------------------------- # Check that adding a WITH clause to an INSERT disables the xfer @@ -415,4 +416,3 @@ do_execsql_test 8.3 { finish_test -