From 19dbfa8adc898005920bf8452a8816e3d296ff09 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 20 Oct 2016 18:20:10 +0000 Subject: [PATCH] Add the ability for the PRAGMA statement to accept multiple arguments. Currently all arguments other than the first are ignored. FossilOrigin-Name: fd81d8a4300c36d02f07371b722124ccf619654c --- manifest | 21 ++++++++++-------- manifest.uuid | 2 +- src/build.c | 21 ++++++++++++++---- src/parse.y | 59 ++++++++++++++++++++++++++++++------------------- src/pragma.c | 23 ++++++------------- src/sqliteInt.h | 4 ++-- 6 files changed, 75 insertions(+), 55 deletions(-) diff --git a/manifest b/manifest index 48536b0043..335c3844f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Minor\ssimplification\sof\sthe\scomparison\sopcodes. -D 2016-10-18T16:36:15.935 +C Add\sthe\sability\sfor\sthe\sPRAGMA\sstatement\sto\saccept\smultiple\sarguments.\nCurrently\sall\sarguments\sother\sthan\sthe\sfirst\sare\signored. +D 2016-10-20T18:20:10.293 F Makefile.in 6fd48ffcf7c2deea7499062d1f3747f986c19678 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc 5151cc64c4c05f3455f4f692ad11410a810d937f @@ -332,7 +332,7 @@ F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73 F src/btree.c 4d035fb52b0ef9658d43dfe604413185dff7a5d1 F src/btree.h d05b2fcc290991a8a3d9ea1816ddd55a4359dcde F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5 -F src/build.c 59dcfdc1ee55439d069af301ef7f2e84421b5102 +F src/build.c e22e66fb34e1e50bb7869a510923bfe58db3071a F src/callback.c 2e76147783386374bf01b227f752c81ec872d730 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7 @@ -375,11 +375,11 @@ F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9 F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/pager.c 49b6c163832498838c92d0c4c90721576ae707b7 F src/pager.h 0a19b1e212d0f5d0507f186ae1cca4e523d09d1a -F src/parse.y 0338f906b61e311c2b7e11a3f89b0092c780b664 +F src/parse.y 07f68096c97093793ed04d69db8bb75e55c3e00e F src/pcache.c 5ff2a08f76a9c1b22f43eb063b7068fb085465ac F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490 F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953 -F src/pragma.c d932ba278654617cdd281f88a790a3185fca7c44 +F src/pragma.c 3ad504c61bcddacc231662f83ac41aceea639ff2 F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1 @@ -391,7 +391,7 @@ F src/shell.c b80396d2fadce4681397707e30078bf416e1dec2 F src/sqlite.h.in 7ef021d74ac7d4004c784a16ad015508f171c4bf F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae -F src/sqliteInt.h 8d241c2c0a1a7b6611d3e9398f41d69426da850d +F src/sqliteInt.h cf6393ad581d692b886e5281f7bb03b02c2a5f26 F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1 F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@ -1526,7 +1526,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 2aa7a03b8632dbfd9741018b5b19c372dcfd3647 -R 4e106c87e784e92bad6650fe8613fe88 +P 56474ebca3fdddb8f3c5156f06dc42dc0a65256c +R 7df9a33a3d365e65a71615f92b26cc61 +T *branch * multi-arg-pragma +T *sym-multi-arg-pragma * +T -sym-trunk * U drh -Z 84c64fba90e2b1da59a52306d789b152 +Z 4afce9abc23c76c5686e4f8a5162325b diff --git a/manifest.uuid b/manifest.uuid index 091e1f1005..4f7a6dca15 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -56474ebca3fdddb8f3c5156f06dc42dc0a65256c \ No newline at end of file +fd81d8a4300c36d02f07371b722124ccf619654c \ No newline at end of file diff --git a/src/build.c b/src/build.c index 508e747ea6..432b832836 100644 --- a/src/build.c +++ b/src/build.c @@ -3572,12 +3572,21 @@ void *sqlite3ArrayAllocate( ** need be. ** ** A new IdList is returned, or NULL if malloc() fails. +** +** The zName must have been obtained from sqlite3DbMalloc(). This routine +** accepts ownership of the zName string and will ensure that it is freed +** when no longer in use. */ -IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ +IdList *sqlite3IdListAppend( + Parse *pParse, /* Parsing context */ + IdList *pList, /* ID list to append to */ + char *zName /* Token to append */ +){ int i; + sqlite3 *db = pParse->db; if( pList==0 ){ pList = sqlite3DbMallocZero(db, sizeof(IdList) ); - if( pList==0 ) return 0; + if( pList==0 ) goto id_list_append_fail; } pList->a = sqlite3ArrayAllocate( db, @@ -3588,10 +3597,14 @@ IdList *sqlite3IdListAppend(sqlite3 *db, IdList *pList, Token *pToken){ ); if( i<0 ){ sqlite3IdListDelete(db, pList); - return 0; + goto id_list_append_fail; } - pList->a[i].zName = sqlite3NameFromToken(db, pToken); + pList->a[i].zName = zName; return pList; + +id_list_append_fail: + sqlite3DbFree(db, zName); + return 0; } /* diff --git a/src/parse.y b/src/parse.y index 1eff123d18..57b7db0408 100644 --- a/src/parse.y +++ b/src/parse.y @@ -204,11 +204,15 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);} %left COLLATE. %right BITNOT. -// An IDENTIFIER can be a generic identifier, or one of several +// An "id" can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. +// A "number" can be either an integer or a floating point value +%token_class number INTEGER|FLOAT. + + // The following directive causes tokens ABORT, AFTER, ASC, etc. to // fallback to ID if they will not parse as their original value. // This obviates the need for the "id" nonterminal. @@ -254,8 +258,8 @@ typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). { %type typename {Token} typename(A) ::= ids(A). typename(A) ::= typename(A) ids(Y). {A.n=Y.n+(int)(Y.z-A.z);} -signed ::= plus_num. -signed ::= minus_num. +signed ::= PLUS|MINUS number. +signed ::= number. // "carglist" is a list of additional constraints that come after the // column name and column type in a CREATE TABLE statement. @@ -807,12 +811,13 @@ insert_cmd(A) ::= REPLACE. {A = OE_Replace;} %type idlist {IdList*} %destructor idlist {sqlite3IdListDelete(pParse->db, $$);} -idlist_opt(A) ::= . {A = 0;} +idlist_opt(A) ::= . {A = 0;} idlist_opt(A) ::= LP idlist(X) RP. {A = X;} idlist(A) ::= idlist(A) COMMA nm(Y). - {A = sqlite3IdListAppend(pParse->db,A,&Y);} + {A = sqlite3IdListAppend(pParse,A,sqlite3NameFromToken(pParse->db,&Y));} idlist(A) ::= nm(Y). - {A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/} + {A = sqlite3IdListAppend(pParse,0,sqlite3NameFromToken(pParse->db,&Y)); + /*A-overwrites-Y*/} /////////////////////////// Expression Processing ///////////////////////////// // @@ -1324,24 +1329,32 @@ cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);} ///////////////////////////// The PRAGMA command ///////////////////////////// // %ifndef SQLITE_OMIT_PRAGMA -cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0,0);} -cmd ::= PRAGMA nm(X) dbnm(Z) EQ nmnum(Y). {sqlite3Pragma(pParse,&X,&Z,&Y,0);} -cmd ::= PRAGMA nm(X) dbnm(Z) LP nmnum(Y) RP. {sqlite3Pragma(pParse,&X,&Z,&Y,0);} -cmd ::= PRAGMA nm(X) dbnm(Z) EQ minus_num(Y). - {sqlite3Pragma(pParse,&X,&Z,&Y,1);} -cmd ::= PRAGMA nm(X) dbnm(Z) LP minus_num(Y) RP. - {sqlite3Pragma(pParse,&X,&Z,&Y,1);} - -nmnum(A) ::= plus_num(A). -nmnum(A) ::= nm(A). -nmnum(A) ::= ON(A). -nmnum(A) ::= DELETE(A). -nmnum(A) ::= DEFAULT(A). +cmd ::= PRAGMA nm(X) dbnm(Z). {sqlite3Pragma(pParse,&X,&Z,0);} +cmd ::= PRAGMA nm(X) dbnm(Z) EQ pragma_arglist(Y). + {sqlite3Pragma(pParse,&X,&Z,Y);} +cmd ::= PRAGMA nm(X) dbnm(Z) LP pragma_arglist(Y) RP. + {sqlite3Pragma(pParse,&X,&Z,Y);} + +%type pragma_arglist {IdList*} +%destructor pragma_arglist {sqlite3IdListDelete(pParse->db,$$);} + +pragma_arglist(A) ::= pragma_arg(X). + { A = sqlite3IdListAppend(pParse,0,X)/*A-overwrites-X*/; } +pragma_arglist(A) ::= pragma_arglist(A) COMMA pragma_arg(Y). + { A = sqlite3IdListAppend(pParse,A,Y); } + +%type pragma_arg {char*} +%destructor pragma_arg {sqlite3DbFree(pParse->db,$$);} +pragma_arg(A) ::= number(X). + {A = sqlite3NameFromToken(pParse->db,&X);/*A-overwrites-X*/} +pragma_arg(A) ::= nm(X). + {A = sqlite3NameFromToken(pParse->db,&X);/*A-overwrites-X*/} +pragma_arg(A) ::= ON|DELETE|DEFAULT(X). + {A = sqlite3NameFromToken(pParse->db,&X);/*A-overwrites-X*/} +pragma_arg(A) ::= PLUS number(X). {A = sqlite3NameFromToken(pParse->db,&X);} +pragma_arg(A) ::= MINUS number(X). {A = sqlite3MPrintf(pParse->db,"-%T",&X);} + %endif SQLITE_OMIT_PRAGMA -%token_class number INTEGER|FLOAT. -plus_num(A) ::= PLUS number(X). {A = X;} -plus_num(A) ::= number(A). -minus_num(A) ::= MINUS number(X). {A = X;} //////////////////////////// The CREATE TRIGGER command ///////////////////// %ifndef SQLITE_OMIT_TRIGGER diff --git a/src/pragma.c b/src/pragma.c index e774de3421..fef044d7d6 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -282,11 +282,7 @@ const char *sqlite3JournalModename(int eMode){ ** ** Pragmas are of this form: ** -** PRAGMA [schema.]id [= value] -** -** The identifier might also be a string. The value is a string, and -** identifier, or a number. If minusFlag is true, then the value is -** a number that was preceded by a minus sign. +** PRAGMA [schema.]id [= value-list] ** ** If the left side is "database.id" then pId1 is the database name ** and pId2 is the id. If the left side is just "id" then pId1 is the @@ -296,8 +292,7 @@ void sqlite3Pragma( Parse *pParse, Token *pId1, /* First part of [schema.]id field */ Token *pId2, /* Second part of [schema.]id field, or NULL */ - Token *pValue, /* Token for , or NULL */ - int minusFlag /* True if a '-' sign preceded */ + IdList *pValues /* The value-list arguments. NULL if omitted */ ){ char *zLeft = 0; /* Nul-terminated UTF-8 string */ char *zRight = 0; /* Nul-terminated UTF-8 string , or NULL */ @@ -312,14 +307,14 @@ void sqlite3Pragma( Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */ const struct sPragmaNames *pPragma; - if( v==0 ) return; + if( v==0 ) goto pragma_out; sqlite3VdbeRunOnlyOnce(v); pParse->nMem = 2; /* Interpret the [schema.] part of the pragma statement. iDb is the ** index of the database this pragma is being applied to in db.aDb[]. */ iDb = sqlite3TwoPartName(pParse, pId1, pId2, &pId); - if( iDb<0 ) return; + if( iDb<0 ) goto pragma_out; pDb = &db->aDb[iDb]; /* If the temp database has been explicitly named as part of the @@ -330,12 +325,8 @@ void sqlite3Pragma( } zLeft = sqlite3NameFromToken(db, pId); - if( !zLeft ) return; - if( minusFlag ){ - zRight = sqlite3MPrintf(db, "-%T", pValue); - }else{ - zRight = sqlite3NameFromToken(db, pValue); - } + if( !zLeft ) goto pragma_out; + if( pValues ) zRight = pValues->a[0].zName; assert( pId2 ); zDb = pId2->n>0 ? pDb->zDbSName : 0; @@ -1984,7 +1975,7 @@ void sqlite3Pragma( pragma_out: sqlite3DbFree(db, zLeft); - sqlite3DbFree(db, zRight); + sqlite3IdListDelete(db, pValues); } #endif /* SQLITE_OMIT_PRAGMA */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 2d13f2635d..7b620b93e9 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3566,7 +3566,7 @@ void sqlite3ExprListDelete(sqlite3*, ExprList*); u32 sqlite3ExprListFlags(const ExprList*); int sqlite3Init(sqlite3*, char**); int sqlite3InitCallback(void*, int, char**, char**); -void sqlite3Pragma(Parse*,Token*,Token*,Token*,int); +void sqlite3Pragma(Parse*,Token*,Token*,IdList*); void sqlite3ResetAllSchemasOfConnection(sqlite3*); void sqlite3ResetOneSchema(sqlite3*,int); void sqlite3CollapseDatabaseArray(sqlite3*); @@ -3641,7 +3641,7 @@ void sqlite3DeleteTable(sqlite3*, Table*); #endif void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int); void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*); -IdList *sqlite3IdListAppend(sqlite3*, IdList*, Token*); +IdList *sqlite3IdListAppend(Parse*, IdList*, char*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListEnlarge(sqlite3*, SrcList*, int, int); SrcList *sqlite3SrcListAppend(sqlite3*, SrcList*, Token*, Token*); -- 2.39.5