SQLite

Changes On Branch multi-arg-pragma
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Changes In Branch multi-arg-pragma Excluding Merge-Ins

This is equivalent to a diff from 56474ebc to fd81d8a4

2016-10-20
22:02
Experimental est_count pragma. (check-in: 340822af user: drh tags: est_count_pragma)
18:20
Add the ability for the PRAGMA statement to accept multiple arguments. Currently all arguments other than the first are ignored. (Leaf check-in: fd81d8a4 user: drh tags: multi-arg-pragma)
11:48
Add test case to incrblob4.test. No changes to code. (check-in: fd9c6ff0 user: dan tags: trunk)
2016-10-18
16:36
Minor simplification of the comparison opcodes. (check-in: 56474ebc user: drh tags: trunk)
15:29
Fix harmless uninitialized variable warnings in speedtest1.c. (check-in: 2aa7a03b user: drh tags: trunk)

Changes to src/build.c.

3568
3569
3570
3571
3572
3573
3574




3575
3576





3577

3578
3579
3580

3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591

3592
3593

3594




3595
3596
3597
3598
3599
3600
3601
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579

3580
3581
3582
3583
3584
3585
3586
3587
3588

3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599

3600
3601

3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614







+
+
+
+

-
+
+
+
+
+

+


-
+










-
+

-
+

+
+
+
+







}

/*
** Append a new element to the given IdList.  Create a new IdList if
** 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,
      pList->a,
      sizeof(pList->a[0]),
      &pList->nId,
      &i
  );
  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;
}

/*
** Delete an IdList.
*/
void sqlite3IdListDelete(sqlite3 *db, IdList *pList){
  int i;

Changes to src/parse.y.

200
201
202
203
204
205
206
207

208
209
210




211
212
213
214
215
216
217
200
201
202
203
204
205
206

207
208
209
210
211
212
213
214
215
216
217
218
219
220
221







-
+



+
+
+
+







%left BITAND BITOR LSHIFT RSHIFT.
%left PLUS MINUS.
%left STAR SLASH REM.
%left CONCAT.
%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.
//
%fallback ID
  ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
250
251
252
253
254
255
256
257
258


259
260
261
262
263
264
265
254
255
256
257
258
259
260


261
262
263
264
265
266
267
268
269







-
-
+
+







}
typetoken(A) ::= typename(A) LP signed COMMA signed RP(Y). {
  A.n = (int)(&Y.z[Y.n] - A.z);
}
%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.
//
carglist ::= carglist ccons.
carglist ::= .
ccons ::= CONSTRAINT nm(X).           {pParse->constraintName = X;}
803
804
805
806
807
808
809
810

811
812
813

814

815

816
817
818
819
820
821
822
807
808
809
810
811
812
813

814
815
816

817
818
819

820
821
822
823
824
825
826
827







-
+


-
+

+
-
+







insert_cmd(A) ::= REPLACE.            {A = OE_Replace;}

%type idlist_opt {IdList*}
%destructor idlist_opt {sqlite3IdListDelete(pParse->db, $$);}
%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,0,sqlite3NameFromToken(pParse->db,&Y));
    {A = sqlite3IdListAppend(pParse->db,0,&Y); /*A-overwrites-Y*/}
     /*A-overwrites-Y*/}

/////////////////////////// Expression Processing /////////////////////////////
//

%type expr {ExprSpan}
%destructor expr {sqlite3ExprDelete(pParse->db, $$.pExpr);}
%type term {ExprSpan}
1320
1321
1322
1323
1324
1325
1326
1327

1328
1329
1330
1331
1332
1333




1334


1335
1336
1337
1338
1339

















1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1325
1326
1327
1328
1329
1330
1331

1332






1333
1334
1335
1336
1337
1338
1339





1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357




1358
1359
1360
1361
1362
1363
1364







-
+
-
-
-
-
-
-
+
+
+
+

+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

-
-
-
-







cmd ::= VACUUM nm(X).          {sqlite3Vacuum(pParse,&X);}
%endif  SQLITE_OMIT_ATTACH
%endif  SQLITE_OMIT_VACUUM

///////////////////////////// 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).                {sqlite3Pragma(pParse,&X,&Z,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);}
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,$$);}
nmnum(A) ::= plus_num(A).
nmnum(A) ::= nm(A).
nmnum(A) ::= ON(A).
nmnum(A) ::= DELETE(A).
nmnum(A) ::= DEFAULT(A).
  
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

cmd ::= createkw trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). {
  Token all;
  all.z = A.z;

Changes to src/pragma.c.

278
279
280
281
282
283
284
285

286
287
288
289
290
291
292
293
294
295
296
297
298
299

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315

316
317
318
319
320
321
322

323
324
325
326
327
328
329
330
331
332
333

334
335
336
337

338
339
340
341
342
343
344
345
278
279
280
281
282
283
284

285




286
287
288
289
290
291
292
293
294

295

296
297
298
299
300
301
302
303
304
305
306
307
308
309

310
311
312
313
314
315
316

317
318
319
320
321
322
323
324
325
326
327

328




329

330
331
332
333
334
335
336







-
+
-
-
-
-









-
+
-














-
+






-
+










-
+
-
-
-
-
+
-







}

/*
** Process a pragma statement.  
**
** Pragmas are of this form:
**
**      PRAGMA [schema.]id [= value]
**      PRAGMA [schema.]id [= value-list]
**
** 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.
**
** 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
** id and pId2 is any empty string.
*/
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 <value>, or NULL */
  IdList *pValues     /* The value-list arguments.  NULL if omitted */
  int minusFlag       /* True if a '-' sign preceded <value> */
){
  char *zLeft = 0;       /* Nul-terminated UTF-8 string <id> */
  char *zRight = 0;      /* Nul-terminated UTF-8 string <value>, or NULL */
  const char *zDb = 0;   /* The database name */
  Token *pId;            /* Pointer to <id> token */
  char *aFcntl[4];       /* Argument to SQLITE_FCNTL_PRAGMA */
  int iDb;               /* Database index for <database> */
  int lwr, upr, mid = 0;       /* Binary search bounds */
  int rc;                      /* return value form SQLITE_FCNTL_PRAGMA */
  sqlite3 *db = pParse->db;    /* The database connection */
  Db *pDb;                     /* The specific database being pragmaed */
  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 
  ** pragma, make sure it is open. 
  */
  if( iDb==1 && sqlite3OpenTempDatabase(pParse) ){
    return;
  }

  zLeft = sqlite3NameFromToken(db, pId);
  if( !zLeft ) return;
  if( !zLeft ) goto pragma_out;
  if( minusFlag ){
    zRight = sqlite3MPrintf(db, "-%T", pValue);
  }else{
    zRight = sqlite3NameFromToken(db, pValue);
  if( pValues ) zRight = pValues->a[0].zName;
  }

  assert( pId2 );
  zDb = pId2->n>0 ? pDb->zDbSName : 0;
  if( sqlite3AuthCheck(pParse, SQLITE_PRAGMA, zLeft, zRight, zDb) ){
    goto pragma_out;
  }

1980
1981
1982
1983
1984
1985
1986
1987

1988
1989
1990
1971
1972
1973
1974
1975
1976
1977

1978
1979
1980
1981







-
+



  break;
#endif

  } /* End of the PRAGMA switch */

pragma_out:
  sqlite3DbFree(db, zLeft);
  sqlite3DbFree(db, zRight);
  sqlite3IdListDelete(db, pValues);
}

#endif /* SQLITE_OMIT_PRAGMA */

Changes to src/sqliteInt.h.

3562
3563
3564
3565
3566
3567
3568
3569

3570
3571
3572
3573
3574
3575
3576
3562
3563
3564
3565
3566
3567
3568

3569
3570
3571
3572
3573
3574
3575
3576







-
+







void sqlite3ExprListSetSortOrder(ExprList*,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
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*);
void sqlite3CommitInternalChanges(sqlite3*);
void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
3637
3638
3639
3640
3641
3642
3643
3644

3645
3646
3647
3648
3649
3650
3651
3637
3638
3639
3640
3641
3642
3643

3644
3645
3646
3647
3648
3649
3650
3651







-
+







  void sqlite3AutoincrementEnd(Parse *pParse);
#else
# define sqlite3AutoincrementBegin(X)
# define sqlite3AutoincrementEnd(X)
#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*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
                                      Token*, Select*, Expr*, IdList*);
void sqlite3SrcListIndexedBy(Parse *, SrcList *, Token *);
void sqlite3SrcListFuncArgs(Parse*, SrcList*, ExprList*);