/ Check-in [9c1432bf]
Login

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

Overview
Comment:Added support for the "sqlite_temp_master" table. Increased the version number to 2.5.2. (CVS 640)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:9c1432bf7485258e485bd652e3acdaeabbfe8850
User & Date: drh 2002-06-25 01:09:11
Context
2002-06-25
01:09
Version 2.5.2 (CVS 641) check-in: 756310ca user: drh tags: trunk
01:09
Added support for the "sqlite_temp_master" table. Increased the version number to 2.5.2. (CVS 640) check-in: 9c1432bf user: drh tags: trunk
2002-06-24
22:01
Partial fix for a problem with LEFT OUTER JOIN. It used to be that the test for the right-hand table not matching the left table occurred after all ON, USING, WHERE clause processing. The test should occur after ON and USING clauses are checked but before the WHERE clause is check. This fix works as long as the total number of "AND" separated terms in the ON, USING, and WHERE clause does not exceed 32. To do: make this work for any number of terms and add test cases. that (CVS 639) check-in: 8b6574cf user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to VERSION.

1
2.5.1
|
1
2.5.2

Changes to src/build.c.

21
22
23
24
25
26
27
28
29
30
31


















32
33
34
35
36
37
38
..
44
45
46
47
48
49
50

51
52
53
54
55
56
57
..
66
67
68
69
70
71
72

73
74
75
76
77
78
79
80
81
82

83
84
85
86
87
88
89
90
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132



133
134

135
136
137
138
139
140

141
142
143




144





















145
146
147
148
149
150
151
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
















378
379
380
381
382
383
384


385
386
387
388
389
390
391
392
...
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
...
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
...
721
722
723
724
725
726
727
728
729
730
731


732
733
734
735
736
737
738
...
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
...
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
...
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
...
920
921
922
923
924
925
926

927
928
929
930
931

932
933
934
935
936
937
938
....
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167

1168

1169
1170

1171
1172
1173
1174




1175
1176

1177
1178

1179
1180
1181

1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
....
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
....
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449

1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
....
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488

1489
1490
1491
1492
1493
1494
1495
....
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546

1547
1548
1549

1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.97 2002/06/20 11:36:49 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>



















/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
** that statement.  Prior action routines should have already
** constructed VDBE code to do the work of the SQL statement.
** This routine just has to execute the VDBE code.
................................................................................
  int rc = SQLITE_OK;
  sqlite *db = pParse->db;
  if( sqlite_malloc_failed ) return;
  if( pParse->pVdbe && pParse->nErr==0 ){
    if( pParse->explain ){
      rc = sqliteVdbeList(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg);

    }else{
      FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
      sqliteVdbeTrace(pParse->pVdbe, trace);
      rc = sqliteVdbeExec(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg, db->pBusyArg,
                          db->xBusyCallback);
      if( rc ) pParse->nErr++;
................................................................................

/*
** Locate the in-memory structure that describes 
** a particular database table given the name
** of that table.  Return NULL if not found.
*/
Table *sqliteFindTable(sqlite *db, const char *zName){

  Table *p = sqliteHashFind(&db->tblHash, zName, strlen(zName)+1);
  return p;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index.
** Return NULL if not found.
*/
Index *sqliteFindIndex(sqlite *db, const char *zName){

  Index *p = sqliteHashFind(&db->idxHash, zName, strlen(zName)+1);
  return p;
}

/*
** Remove the given index from the index hash table, and free
** its memory structures.
**
................................................................................
static void sqliteDeleteIndex(sqlite *db, Index *p){
  Index *pOld;
  assert( db!=0 && p->zName!=0 );
  pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0);
  if( pOld!=0 && pOld!=p ){
    sqliteHashInsert(&db->idxHash, pOld->zName, strlen(pOld->zName)+1, pOld);
  }
  sqliteHashInsert(&db->idxDrop, p, 0, 0);
  sqliteFree(p);
}

/*
** Unlink the given index from its table, then remove
** the index from the index hash table and free its memory
** structures.
................................................................................
      p->pNext = pIndex->pNext;
    }
  }
  sqliteDeleteIndex(db, pIndex);
}

/*
** Move the given index to the pending DROP INDEX queue if it has
** been committed.  If this index was never committed, then just
** delete it.
**
** Indices on the pending drop queue are deleted when a COMMIT is
** executed.  If a ROLLBACK occurs, the indices are moved back into
** the main index hash table.
*/



static void sqlitePendingDropIndex(sqlite *db, Index *p){
  if( !p->isCommit ){

    sqliteUnlinkAndDeleteIndex(db, p);
  }else{
    Index *pOld;
    pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0);
    if( pOld!=0 && pOld!=p ){
      sqliteHashInsert(&db->idxHash, pOld->zName, strlen(pOld->zName)+1, pOld);

    }
    sqliteHashInsert(&db->idxDrop, p, 0, p);
    p->isDropped = 1;




  }





















}

/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
................................................................................
** table structure with all its indices.
*/
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
  Table *pOld;
  assert( db!=0 );
  pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
  assert( pOld==0 || pOld==p );
  sqliteHashInsert(&db->tblDrop, p, 0, 0);
  sqliteDeleteTable(db, p);
}

/*
** Move the given table to the pending DROP TABLE queue if it has
** been committed.  If this table was never committed, then just
** delete it.  Do the same for all its indices.
**
** Table on the drop queue are not actually deleted until a COMMIT
** statement is executed.  If a ROLLBACK occurs instead of a COMMIT,
** then the tables on the drop queue are moved back into the main
** hash table.
*/
static void sqlitePendingDropTable(sqlite *db, Table *pTbl){
  if( !pTbl->isCommit ){
    sqliteUnlinkAndDeleteTable(db, pTbl);
  }else{
    Table *pOld;
    Index *pIndex, *pNext;
    pOld = sqliteHashInsert(&db->tblHash, pTbl->zName, strlen(pTbl->zName)+1,0);
    assert( pOld==pTbl );
    sqliteHashInsert(&db->tblDrop, pTbl, 0, pTbl);
    for(pIndex = pTbl->pIndex; pIndex; pIndex=pNext){
      pNext = pIndex->pNext;
      sqlitePendingDropIndex(db, pIndex);
    }
  }
}

/*
** Check all Tables and Indexes in the internal hash table and commit
** any additions or deletions to those hash tables.
**
** When executing CREATE TABLE and CREATE INDEX statements, the Table
** and Index structures are created and added to the hash tables, but
** the "isCommit" field is not set.  This routine sets those fields.
** When executing DROP TABLE and DROP INDEX, the table or index structures
** are moved out of tblHash and idxHash into tblDrop and idxDrop.  This
** routine deletes the structure in tblDrop and idxDrop.
**
** See also: sqliteRollbackInternalChanges()
*/
void sqliteCommitInternalChanges(sqlite *db){
  HashElem *pElem;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;
  db->schema_cookie = db->next_cookie;
  for(pElem=sqliteHashFirst(&db->tblHash); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTable = sqliteHashData(pElem);
    pTable->isCommit = 1;
  }
  for(pElem=sqliteHashFirst(&db->tblDrop); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTable = sqliteHashData(pElem);
    sqliteDeleteTable(db, pTable);
  }
  sqliteHashClear(&db->tblDrop);
  for(pElem=sqliteHashFirst(&db->idxHash); pElem; pElem=sqliteHashNext(pElem)){
    Index *pIndex = sqliteHashData(pElem);
    pIndex->isCommit = 1;
  }
  while( (pElem=sqliteHashFirst(&db->idxDrop))!=0 ){
    Index *pIndex = sqliteHashData(pElem);
    sqliteUnlinkAndDeleteIndex(db, pIndex);
  }
  sqliteHashClear(&db->idxDrop);

  /* Set the commit flag on all triggers added this transaction */
  for(pElem=sqliteHashFirst(&db->trigHash); pElem; pElem=sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    pTrigger->isCommit = 1;
  }

  /* Delete the structures for triggers removed this transaction */
  pElem = sqliteHashFirst(&db->trigDrop);
  while( pElem ){
    Trigger *pTrigger = sqliteHashData(pElem);
    sqliteDeleteTrigger(pTrigger);
    pElem = sqliteHashNext(pElem);
  }
  sqliteHashClear(&db->trigDrop);

  db->flags &= ~SQLITE_InternChanges;
}

/*
** This routine runs when one or more CREATE TABLE, CREATE INDEX,
** DROP TABLE, or DROP INDEX statements gets rolled back.  The
** additions or deletions of Table and Index structures in the
** internal hash tables are undone.
**
** See also: sqliteCommitInternalChanges()
*/
void sqliteRollbackInternalChanges(sqlite *db){
  Hash toDelete;
  HashElem *pElem;
  if( (db->flags & SQLITE_InternChanges)==0 ) return;
  sqliteHashInit(&toDelete, SQLITE_HASH_POINTER, 0);
  db->next_cookie = db->schema_cookie;
  for(pElem=sqliteHashFirst(&db->tblHash); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTable = sqliteHashData(pElem);
    if( !pTable->isCommit ){
      sqliteHashInsert(&toDelete, pTable, 0, pTable);
    }
  }
  for(pElem=sqliteHashFirst(&toDelete); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTable = sqliteHashData(pElem);
    sqliteUnlinkAndDeleteTable(db, pTable);
  }
  sqliteHashClear(&toDelete);
  for(pElem=sqliteHashFirst(&db->tblDrop); pElem; pElem=sqliteHashNext(pElem)){
    Table *pOld, *p = sqliteHashData(pElem);
    assert( p->isCommit );
    pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, p);
    assert( pOld==0 || pOld==p );
  }
  sqliteHashClear(&db->tblDrop);
  for(pElem=sqliteHashFirst(&db->idxHash); pElem; pElem=sqliteHashNext(pElem)){
    Index *pIndex = sqliteHashData(pElem);
    if( !pIndex->isCommit ){
      sqliteHashInsert(&toDelete, pIndex, 0, pIndex);
    }
  }
  for(pElem=sqliteHashFirst(&toDelete); pElem; pElem=sqliteHashNext(pElem)){
    Index *pIndex = sqliteHashData(pElem);
    sqliteUnlinkAndDeleteIndex(db, pIndex);
  }
  sqliteHashClear(&toDelete);
  for(pElem=sqliteHashFirst(&db->idxDrop); pElem; pElem=sqliteHashNext(pElem)){
    Index *pOld, *p = sqliteHashData(pElem);
    assert( p->isCommit );
    p->isDropped = 0;
    pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, p);
    assert( pOld==0 || pOld==p );
  }
  sqliteHashClear(&db->idxDrop);

  /* Remove any triggers that haven't been commited yet */
  for(pElem = sqliteHashFirst(&db->trigHash); pElem; 
      pElem = (pElem?sqliteHashNext(pElem):0)){
    Trigger *pTrigger = sqliteHashData(pElem);
    if( !pTrigger->isCommit ){
      Table *pTbl = sqliteFindTable(db, pTrigger->table);
      if( pTbl ){
        if( pTbl->pTrigger == pTrigger ){
          pTbl->pTrigger = pTrigger->pNext;
        }else{
          Trigger *cc = pTbl->pTrigger;
          while( cc ){
            if( cc->pNext == pTrigger ){
              cc->pNext = cc->pNext->pNext;
              break;
            }
            cc = cc->pNext;
          }
          assert(cc);
        }
      }
      sqliteHashInsert(&db->trigHash, pTrigger->name,
              1 + strlen(pTrigger->name), 0);
      sqliteDeleteTrigger(pTrigger);
      pElem = sqliteHashFirst(&db->trigHash);
    }
  }

  /* Any triggers that were dropped - put 'em back in place */
  for(pElem = sqliteHashFirst(&db->trigDrop); pElem; 
      pElem = sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    Table *pTbl = sqliteFindTable(db, pTrigger->table);
    sqliteHashInsert(&db->trigHash, pTrigger->name, 
        strlen(pTrigger->name) + 1, pTrigger);
    pTrigger->pNext = pTbl->pTrigger;
    pTbl->pTrigger = pTrigger;
  }

  sqliteHashClear(&db->trigDrop);
  db->flags &= ~SQLITE_InternChanges;
}

/*
** Construct the name of a user table or index from a token.
**
** Space to hold the name is obtained from sqliteMalloc() and must
** be freed by the calling function.
*/
char *sqliteTableNameFromToken(Token *pName){
  char *zName = sqliteStrNDup(pName->z, pName->n);
  sqliteDequote(zName);
  return zName;
}

















/*
** Begin constructing a new table representation in memory.  This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement.  In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name.  The
** pStart token is the CREATE and pName is the table name.  The isTemp


** flag is true if the "TEMP" or "TEMPORARY" keyword occurs in between
** CREATE and TABLE.
**
** The new table record is initialized and put in pParse->pNewTable.
** As more of the CREATE TABLE statement is parsed, additional action
** routines will be called to add more information to this record.
** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
** is called to complete the construction of the new table record.
................................................................................

  /* Before trying to create a temporary table, make sure the Btree for
  ** holding temporary tables is open.
  */
  if( isTemp && db->pBeTemp==0 ){
    int rc = sqliteBtreeOpen(0, 0, MAX_PAGES, &db->pBeTemp);
    if( rc!=SQLITE_OK ){
      sqliteSetNString(&pParse->zErrMsg, "unable to open a temporary database "
        "file for storing temporary tables", 0);
      pParse->nErr++;
      return;
    }
    if( db->flags & SQLITE_InTrans ){
      rc = sqliteBtreeBeginTrans(db->pBeTemp);
      if( rc!=SQLITE_OK ){
................................................................................
  ** now.
  */
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse, 0);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
      sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
      sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    }
  }
}

/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
** in a CREATE TABLE statement.  sqliteStartTable() gets called
** first to get things going.  Then this routine is called for each
................................................................................
**
** This plan is not completely bullet-proof.  It is possible for
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
void sqliteChangeCookie(sqlite *db){
  if( db->next_cookie==db->schema_cookie ){
    db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
    db->flags |= SQLITE_InternChanges;


  }
}

/*
** Measure the number of characters needed to output the given
** identifier.  The number returned includes any quotes used
** but does not include the null terminator.
................................................................................
    zSep2 = ",";
    zEnd = ")";
  }else{
    zSep = "\n  ";
    zSep2 = ",\n  ";
    zEnd = "\n)";
  }
  n += 25 + 6*p->nCol;
  zStmt = sqliteMalloc( n );
  if( zStmt==0 ) return 0;
  assert( !p->isTemp );
  strcpy(zStmt, "CREATE TABLE ");
  k = strlen(zStmt);
  identPut(zStmt, &k, p->zName);
  zStmt[k++] = '(';
  for(i=0; i<p->nCol; i++){
    strcpy(&zStmt[k], zSep);
    k += strlen(&zStmt[k]);
    zSep = zSep2;
................................................................................
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" table on the disk.  So do not write to the disk
  ** again.  Extract the root page number for the table from the 
  ** pParse->newTnum field.  (The page number should have been put
  ** there by the sqliteOpenCb routine.)
  */
  if( pParse->initFlag ){
    p->tnum = pParse->newTnum;
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, then just create the table.  Do not
  ** make an entry in SQLITE_MASTER.
  */
  if( !pParse->initFlag ){
    int n;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
................................................................................
      sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
      sqliteVdbeChangeP3(v, -1, (char *)&p->tnum, P3_POINTER);
    }else{
      /* A view */
      sqliteVdbeAddOp(v, OP_Integer, 0, 0);
    }
    p->tnum = 0;
    if( !p->isTemp ){
      sqliteVdbeAddOp(v, OP_Pull, 1, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      if( p->pSelect==0 ){
        sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
      }else{
        sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
      }
................................................................................
      }else{
        assert( pEnd!=0 );
        n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
        sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
      }
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);

      sqliteChangeCookie(db);
      sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
    }

    if( pSelect ){
      int op = p->isTemp ? OP_OpenWrAux : OP_OpenWrite;
      sqliteVdbeAddOp(v, op, 1, 0);
      pParse->nTab = 2;
      sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
    }
    sqliteEndWriteOperation(pParse);
................................................................................

  /* Generate code to remove the table from the master table
  ** on disk.
  */
  v = sqliteGetVdbe(pParse);
  if( v ){
    static VdbeOp dropTable[] = {
      { OP_OpenWrite,  0, 2,        MASTER_NAME},
      { OP_Rewind,     0, ADDR(9),  0},
      { OP_String,     0, 0,        0}, /* 2 */
      { OP_MemStore,   1, 1,        0},
      { OP_MemLoad,    1, 0,        0}, /* 4 */
      { OP_Column,     0, 2,        0},
      { OP_Ne,         0, ADDR(8),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(4),  0}, /* 8 */
      { OP_Integer,    0, 0,        0}, /* 9 */
      { OP_SetCookie,  0, 0,        0},
      { OP_Close,      0, 0,        0},
    };
    Index *pIdx;

    sqliteBeginWriteOperation(pParse, 0);

    /* Drop all triggers associated with the table being dropped */
    while( pTable->pTrigger ){

      Token tt;
      tt.z = pTable->pTrigger->name;
      tt.n = strlen(pTable->pTrigger->name);
      sqliteDropTrigger(pParse, &tt, 1);




    }
    if( !pTable->isTemp ){

      base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
      sqliteVdbeChangeP3(v, base+2, pTable->zName, 0);

      sqliteChangeCookie(db);
      sqliteVdbeChangeP1(v, base+9, db->next_cookie);
    }

    if( !isView ){
      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
      for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
      }
    }
    sqliteEndWriteOperation(pParse);
  }

  /* Move the table (and all its indices) to the pending DROP queue.
  ** Or, if the table was never committed, just delete it.  If the table
  ** has been committed and is placed on the pending DROP queue, then the
  ** delete will occur when sqliteCommitInternalChanges() executes.
  **
  ** Exception: if the SQL statement began with the EXPLAIN keyword,
  ** then no changes should be made.
  */
  if( !pParse->explain ){
    sqlitePendingDropTable(db, pTable);
    db->flags |= SQLITE_InternChanges;
  }
  sqliteViewResetAll(db);
}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
................................................................................
  /* If this index is created while re-reading the schema from sqlite_master
  ** but the table associated with this index is a temporary table, it can
  ** only mean that the table that this index is really associated with is
  ** one whose name is hidden behind a temporary table with the same name.
  ** Since its table has been suppressed, we need to also suppress the
  ** index.
  */
  if( pParse->initFlag && pTab->isTemp ){
    goto exit_create_index;
  }

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
................................................................................
    int addr;
    int isTemp = pTab->isTemp;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      sqliteBeginWriteOperation(pParse, 0);
      if( !isTemp ){
        sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
        sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
      }
    }
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, "index", P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, pIndex->zName, P3_STATIC);
      sqliteVdbeAddOp(v, OP_String, 0, 0);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
    }
    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
    pIndex->tnum = 0;
    if( pTable ){

      if( isTemp ){
        sqliteVdbeAddOp(v, OP_OpenWrAux, 1, 0);
      }else{
        sqliteVdbeAddOp(v, OP_Dup, 0, 0);
        sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
      }
    }
    if( !isTemp ){
      addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
      if( pStart && pEnd ){
        n = Addr(pEnd->z) - Addr(pStart->z) + 1;
        sqliteVdbeChangeP3(v, addr, pStart->z, n);
      }
      sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
      sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    }
    if( pTable ){
      sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
      for(i=0; i<pIndex->nColumn; i++){
................................................................................
      sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
      sqliteVdbeResolveLabel(v, lbl2);
      sqliteVdbeAddOp(v, OP_Close, 2, 0);
      sqliteVdbeAddOp(v, OP_Close, 1, 0);
    }
    if( pTable!=0 ){
      if( !isTemp ){
        sqliteChangeCookie(db);
        sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
        sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
        sqliteVdbeAddOp(v, OP_Close, 0, 0);
      }

      sqliteEndWriteOperation(pParse);
    }
  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
................................................................................
    return;
  }

  /* Generate code to remove the index and from the master table */
  v = sqliteGetVdbe(pParse);
  if( v ){
    static VdbeOp dropIndex[] = {
      { OP_OpenWrite,  0, 2,       MASTER_NAME},
      { OP_Rewind,     0, ADDR(10),0}, 
      { OP_String,     0, 0,       0}, /* 2 */
      { OP_MemStore,   1, 1,       0},
      { OP_MemLoad,    1, 0,       0}, /* 4 */
      { OP_Column,     0, 1,       0},
      { OP_Eq,         0, ADDR(9), 0},
      { OP_Next,       0, ADDR(4), 0},
      { OP_Goto,       0, ADDR(10),0},
      { OP_Delete,     0, 0,       0}, /* 9 */
      { OP_Integer,    0, 0,       0}, /* 10 */
      { OP_SetCookie,  0, 0,       0},
      { OP_Close,      0, 0,       0},
    };
    int base;
    Table *pTab = pIndex->pTable;

    sqliteBeginWriteOperation(pParse, 0);
    if( !pTab->isTemp ){
      base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
      sqliteVdbeChangeP3(v, base+2, pIndex->zName, P3_STATIC);

      sqliteChangeCookie(db);
      sqliteVdbeChangeP1(v, base+10, db->next_cookie);
    }

    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
    sqliteEndWriteOperation(pParse);
  }

  /* Move the index onto the pending DROP queue.  Or, if the index was
  ** never committed, just delete it.  Indices on the pending DROP queue
  ** get deleted by sqliteCommitInternalChanges() when the user executes
  ** a COMMIT.  Or if a rollback occurs, the elements of the DROP queue
  ** are moved back into the main hash table.
  */
  if( !pParse->explain ){
    sqlitePendingDropIndex(db, pIndex);
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.







|



>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>







 







>
|









>
|







 







<







 







|
|
|
|
<
<
<

>
>
>
|
<
>
|
|
|
|
|
|
>
|
<
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<




<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<










>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







>
>
|







 







|







 







|
|






<







 







|



>
>







 







|


|
<







 







|
|
|
|









|
|







 







<







 







>
|
<
<
<

>







 







<
|
|

|

|

|
<
<
<


>

>

|
>




>
>
>
>
|
<
>
|
|
>
|
<

>









|
<
<
<





|







 







|







 







|
<
<
|
<
<







<




>



<



<







<







 







|
<
<
<

>







 







<
|
|

|

|
|
|
|
<
<
<





|
|
|
>
|
<

>




|
<
<
<
<


|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
...
116
117
118
119
120
121
122

123
124
125
126
127
128
129
...
138
139
140
141
142
143
144
145
146
147
148



149
150
151
152
153

154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
...
226
227
228
229
230
231
232

233
234
235
236















































































































































































237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
...
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
...
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379

380
381
382
383
384
385
386
...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
675
676
677
678
679
680
681
682
683
684
685

686
687
688
689
690
691
692
...
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
...
781
782
783
784
785
786
787

788
789
790
791
792
793
794
...
806
807
808
809
810
811
812
813
814



815
816
817
818
819
820
821
822
823
....
1032
1033
1034
1035
1036
1037
1038

1039
1040
1041
1042
1043
1044
1045
1046



1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063

1064
1065
1066
1067
1068

1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080



1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
....
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
....
1311
1312
1313
1314
1315
1316
1317
1318


1319


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
....
1356
1357
1358
1359
1360
1361
1362
1363



1364
1365
1366
1367
1368
1369
1370
1371
1372
....
1396
1397
1398
1399
1400
1401
1402

1403
1404
1405
1406
1407
1408
1409
1410
1411



1412
1413
1414
1415
1416
1417
1418
1419
1420
1421

1422
1423
1424
1425
1426
1427
1428




1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.98 2002/06/25 01:09:11 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Check to see if the schema for the database needs
** to be read from the SQLITE_MASTER and SQLITE_TEMP_MASTER tables.
** If it does, then read it.
*/
void sqliteBeginParse(Parse *pParse, int explainFlag){
  sqlite *db = pParse->db;
  pParse->explain = explainFlag;
  if((db->flags & SQLITE_Initialized)==0 && pParse->initFlag==0 ){
    int rc = sqliteInit(db, &pParse->zErrMsg);
    if( rc!=SQLITE_OK ){
      pParse->rc = rc;
      pParse->nErr++;
    }
  }
}

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
** that statement.  Prior action routines should have already
** constructed VDBE code to do the work of the SQL statement.
** This routine just has to execute the VDBE code.
................................................................................
  int rc = SQLITE_OK;
  sqlite *db = pParse->db;
  if( sqlite_malloc_failed ) return;
  if( pParse->pVdbe && pParse->nErr==0 ){
    if( pParse->explain ){
      rc = sqliteVdbeList(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg);
      db->next_cookie = db->schema_cookie;
    }else{
      FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
      sqliteVdbeTrace(pParse->pVdbe, trace);
      rc = sqliteVdbeExec(pParse->pVdbe, pParse->xCallback, pParse->pArg, 
                          &pParse->zErrMsg, db->pBusyArg,
                          db->xBusyCallback);
      if( rc ) pParse->nErr++;
................................................................................

/*
** Locate the in-memory structure that describes 
** a particular database table given the name
** of that table.  Return NULL if not found.
*/
Table *sqliteFindTable(sqlite *db, const char *zName){
  Table *p;
  p = sqliteHashFind(&db->tblHash, zName, strlen(zName)+1);
  return p;
}

/*
** Locate the in-memory structure that describes 
** a particular index given the name of that index.
** Return NULL if not found.
*/
Index *sqliteFindIndex(sqlite *db, const char *zName){
  Index *p;
  p = sqliteHashFind(&db->idxHash, zName, strlen(zName)+1);
  return p;
}

/*
** Remove the given index from the index hash table, and free
** its memory structures.
**
................................................................................
static void sqliteDeleteIndex(sqlite *db, Index *p){
  Index *pOld;
  assert( db!=0 && p->zName!=0 );
  pOld = sqliteHashInsert(&db->idxHash, p->zName, strlen(p->zName)+1, 0);
  if( pOld!=0 && pOld!=p ){
    sqliteHashInsert(&db->idxHash, pOld->zName, strlen(pOld->zName)+1, pOld);
  }

  sqliteFree(p);
}

/*
** Unlink the given index from its table, then remove
** the index from the index hash table and free its memory
** structures.
................................................................................
      p->pNext = pIndex->pNext;
    }
  }
  sqliteDeleteIndex(db, pIndex);
}

/*
** Erase all schema information from the in-memory hash tables of
** database connection.  This routine is called to reclaim memory
** before the connection closes.  It is also called during a rollback
** if there were schema changes during the transaction.



*/
void sqliteResetInternalSchema(sqlite *db){
  HashElem *pElem;
  Hash temp1;
  Hash temp2;


  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);
  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger *pTrigger = sqliteHashData(pElem);
    sqliteDeleteTrigger(pTrigger);
  }

  sqliteHashClear(&temp2);
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    sqliteDeleteTable(db, pTab);
  }
  sqliteHashClear(&temp1);
  db->flags &= ~(SQLITE_Initialized|SQLITE_InternChanges);
}

/*
** This routine is called whenever a rollback occurs.  If there were
** schema changes during the transaction, then we have to reset the
** internal hash tables and reload them from disk.
*/
void sqliteRollbackInternalChanges(sqlite *db){
  if( db->flags & SQLITE_InternChanges ){
    sqliteResetInternalSchema(db);
  }
}

/*
** This routine is called when a commit occurs.
*/
void sqliteCommitInternalChanges(sqlite *db){
  db->schema_cookie = db->next_cookie;
  db->flags &= ~SQLITE_InternChanges;
}

/*
** Remove the memory data structures associated with the given
** Table.  No changes are made to disk by this routine.
**
** This routine just deletes the data structure.  It does not unlink
................................................................................
** table structure with all its indices.
*/
static void sqliteUnlinkAndDeleteTable(sqlite *db, Table *p){
  Table *pOld;
  assert( db!=0 );
  pOld = sqliteHashInsert(&db->tblHash, p->zName, strlen(p->zName)+1, 0);
  assert( pOld==0 || pOld==p );

  sqliteDeleteTable(db, p);
}

/*















































































































































































** Construct the name of a user table or index from a token.
**
** Space to hold the name is obtained from sqliteMalloc() and must
** be freed by the calling function.
*/
char *sqliteTableNameFromToken(Token *pName){
  char *zName = sqliteStrNDup(pName->z, pName->n);
  sqliteDequote(zName);
  return zName;
}

/*
** Generate code to open the appropriate master table.  The table
** opened will be SQLITE_MASTER for persistent tables and 
** SQLITE_TEMP_MASTER for temporary tables.  The table is opened
** on cursor 0.
*/
void sqliteOpenMasterTable(Vdbe *v, int isTemp){
  if( isTemp ){
    sqliteVdbeAddOp(v, OP_OpenWrAux, 0, 2);
    sqliteVdbeChangeP3(v, -1, TEMP_MASTER_NAME, P3_STATIC);
  }else{
    sqliteVdbeAddOp(v, OP_OpenWrite, 0, 2);
    sqliteVdbeChangeP3(v, -1, MASTER_NAME, P3_STATIC);
  }
}

/*
** Begin constructing a new table representation in memory.  This is
** the first of several action routines that get called in response
** to a CREATE TABLE statement.  In particular, this routine is called
** after seeing tokens "CREATE" and "TABLE" and the table name.  The
** pStart token is the CREATE and pName is the table name.  The isTemp
** flag is true if the table should be stored in the auxiliary database
** file instead of in the main database file.  This is normally the case
** when the "TEMP" or "TEMPORARY" keyword occurs in between
** CREATE and TABLE.
**
** The new table record is initialized and put in pParse->pNewTable.
** As more of the CREATE TABLE statement is parsed, additional action
** routines will be called to add more information to this record.
** At the end of the CREATE TABLE statement, the sqliteEndTable() routine
** is called to complete the construction of the new table record.
................................................................................

  /* Before trying to create a temporary table, make sure the Btree for
  ** holding temporary tables is open.
  */
  if( isTemp && db->pBeTemp==0 ){
    int rc = sqliteBtreeOpen(0, 0, MAX_PAGES, &db->pBeTemp);
    if( rc!=SQLITE_OK ){
      sqliteSetString(&pParse->zErrMsg, "unable to open a temporary database "
        "file for storing temporary tables", 0);
      pParse->nErr++;
      return;
    }
    if( db->flags & SQLITE_InTrans ){
      rc = sqliteBtreeBeginTrans(db->pBeTemp);
      if( rc!=SQLITE_OK ){
................................................................................
  ** now.
  */
  if( !pParse->initFlag && (v = sqliteGetVdbe(pParse))!=0 ){
    sqliteBeginWriteOperation(pParse, 0);
    if( !isTemp ){
      sqliteVdbeAddOp(v, OP_Integer, db->file_format, 0);
      sqliteVdbeAddOp(v, OP_SetCookie, 0, 1);
    }
    sqliteOpenMasterTable(v, isTemp);
    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
    sqliteVdbeAddOp(v, OP_Dup, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
  }
}


/*
** Add a new column to the table currently being constructed.
**
** The parser calls this routine once for each column declaration
** in a CREATE TABLE statement.  sqliteStartTable() gets called
** first to get things going.  Then this routine is called for each
................................................................................
**
** This plan is not completely bullet-proof.  It is possible for
** the schema to change multiple times and for the cookie to be
** set back to prior value.  But schema changes are infrequent
** and the probability of hitting the same cookie value is only
** 1 chance in 2^32.  So we're safe enough.
*/
void sqliteChangeCookie(sqlite *db, Vdbe *v){
  if( db->next_cookie==db->schema_cookie ){
    db->next_cookie = db->schema_cookie + sqliteRandomByte() + 1;
    db->flags |= SQLITE_InternChanges;
    sqliteVdbeAddOp(v, OP_Integer, db->next_cookie, 0);
    sqliteVdbeAddOp(v, OP_SetCookie, 0, 0);
  }
}

/*
** Measure the number of characters needed to output the given
** identifier.  The number returned includes any quotes used
** but does not include the null terminator.
................................................................................
    zSep2 = ",";
    zEnd = ")";
  }else{
    zSep = "\n  ";
    zSep2 = ",\n  ";
    zEnd = "\n)";
  }
  n += 35 + 6*p->nCol;
  zStmt = sqliteMalloc( n );
  if( zStmt==0 ) return 0;
  strcpy(zStmt, p->isTemp ? "CREATE TEMP TABLE " : "CREATE TABLE ");

  k = strlen(zStmt);
  identPut(zStmt, &k, p->zName);
  zStmt[k++] = '(';
  for(i=0; i<p->nCol; i++){
    strcpy(&zStmt[k], zSep);
    k += strlen(&zStmt[k]);
    zSep = zSep2;
................................................................................
    p->aCol = pSelTab->aCol;
    pSelTab->nCol = 0;
    pSelTab->aCol = 0;
    sqliteDeleteTable(0, pSelTab);
  }

  /* If the initFlag is 1 it means we are reading the SQL off the
  ** "sqlite_master" or "sqlite_temp_master" table on the disk.
  ** So do not write to the disk again.  Extract the root page number
  ** for the table from the pParse->newTnum field.  (The page number
  ** should have been put there by the sqliteOpenCb routine.)
  */
  if( pParse->initFlag ){
    p->tnum = pParse->newTnum;
  }

  /* If not initializing, then create a record for the new table
  ** in the SQLITE_MASTER table of the database.  The record number
  ** for the new table entry should already be on the stack.
  **
  ** If this is a TEMPORARY table, write the entry into the auxiliary
  ** file instead of into the main database file.
  */
  if( !pParse->initFlag ){
    int n;
    Vdbe *v;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) return;
................................................................................
      sqliteVdbeAddOp(v, OP_CreateTable, 0, p->isTemp);
      sqliteVdbeChangeP3(v, -1, (char *)&p->tnum, P3_POINTER);
    }else{
      /* A view */
      sqliteVdbeAddOp(v, OP_Integer, 0, 0);
    }
    p->tnum = 0;

    sqliteVdbeAddOp(v, OP_Pull, 1, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( p->pSelect==0 ){
      sqliteVdbeChangeP3(v, -1, "table", P3_STATIC);
    }else{
      sqliteVdbeChangeP3(v, -1, "view", P3_STATIC);
    }
................................................................................
    }else{
      assert( pEnd!=0 );
      n = Addr(pEnd->z) - Addr(pParse->sFirstToken.z) + 1;
      sqliteVdbeChangeP3(v, -1, pParse->sFirstToken.z, n);
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);
    if( !p->isTemp ){
      sqliteChangeCookie(db, v);



    }
    sqliteVdbeAddOp(v, OP_Close, 0, 0);
    if( pSelect ){
      int op = p->isTemp ? OP_OpenWrAux : OP_OpenWrite;
      sqliteVdbeAddOp(v, op, 1, 0);
      pParse->nTab = 2;
      sqliteSelect(pParse, pSelect, SRT_Table, 1, 0, 0, 0);
    }
    sqliteEndWriteOperation(pParse);
................................................................................

  /* Generate code to remove the table from the master table
  ** on disk.
  */
  v = sqliteGetVdbe(pParse);
  if( v ){
    static VdbeOp dropTable[] = {

      { OP_Rewind,     0, ADDR(8),  0},
      { OP_String,     0, 0,        0}, /* 1 */
      { OP_MemStore,   1, 1,        0},
      { OP_MemLoad,    1, 0,        0}, /* 3 */
      { OP_Column,     0, 2,        0},
      { OP_Ne,         0, ADDR(7),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(3),  0}, /* 7 */



    };
    Index *pIdx;
    Trigger *pTrigger;
    sqliteBeginWriteOperation(pParse, 0);
    sqliteOpenMasterTable(v, pTable->isTemp);
    /* Drop all triggers associated with the table being dropped */
    pTrigger = pTable->pTrigger;
    while( pTrigger ){
      Token tt;
      tt.z = pTable->pTrigger->name;
      tt.n = strlen(pTable->pTrigger->name);
      sqliteDropTrigger(pParse, &tt, 1);
      if( pParse->explain ){
        pTrigger = pTrigger->pNext;
      }else{
        pTrigger = pTable->pTrigger;
      }

    }
    base = sqliteVdbeAddOpList(v, ArraySize(dropTable), dropTable);
    sqliteVdbeChangeP3(v, base+1, pTable->zName, 0);
    if( !pTable->isTemp ){
      sqliteChangeCookie(db, v);

    }
    sqliteVdbeAddOp(v, OP_Close, 0, 0);
    if( !isView ){
      sqliteVdbeAddOp(v, OP_Destroy, pTable->tnum, pTable->isTemp);
      for(pIdx=pTable->pIndex; pIdx; pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Destroy, pIdx->tnum, pTable->isTemp);
      }
    }
    sqliteEndWriteOperation(pParse);
  }

  /* Delete the in-memory description of the table.



  **
  ** Exception: if the SQL statement began with the EXPLAIN keyword,
  ** then no changes should be made.
  */
  if( !pParse->explain ){
    sqliteUnlinkAndDeleteTable(db, pTable);
    db->flags |= SQLITE_InternChanges;
  }
  sqliteViewResetAll(db);
}

/*
** Create a new index for an SQL table.  pIndex is the name of the index 
................................................................................
  /* If this index is created while re-reading the schema from sqlite_master
  ** but the table associated with this index is a temporary table, it can
  ** only mean that the table that this index is really associated with is
  ** one whose name is hidden behind a temporary table with the same name.
  ** Since its table has been suppressed, we need to also suppress the
  ** index.
  */
  if( pParse->initFlag && !pParse->isTemp && pTab->isTemp ){
    goto exit_create_index;
  }

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
................................................................................
    int addr;
    int isTemp = pTab->isTemp;

    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto exit_create_index;
    if( pTable!=0 ){
      sqliteBeginWriteOperation(pParse, 0);
      sqliteOpenMasterTable(v, isTemp);


    }


    sqliteVdbeAddOp(v, OP_NewRecno, 0, 0);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, "index", P3_STATIC);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pIndex->zName, P3_STATIC);
    sqliteVdbeAddOp(v, OP_String, 0, 0);
    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);

    addr = sqliteVdbeAddOp(v, OP_CreateIndex, 0, isTemp);
    sqliteVdbeChangeP3(v, addr, (char*)&pIndex->tnum, P3_POINTER);
    pIndex->tnum = 0;
    if( pTable ){
      sqliteVdbeAddOp(v, OP_Dup, 0, 0);
      if( isTemp ){
        sqliteVdbeAddOp(v, OP_OpenWrAux, 1, 0);
      }else{

        sqliteVdbeAddOp(v, OP_OpenWrite, 1, 0);
      }
    }

    addr = sqliteVdbeAddOp(v, OP_String, 0, 0);
    if( pStart && pEnd ){
      n = Addr(pEnd->z) - Addr(pStart->z) + 1;
      sqliteVdbeChangeP3(v, addr, pStart->z, n);
    }
    sqliteVdbeAddOp(v, OP_MakeRecord, 5, 0);
    sqliteVdbeAddOp(v, OP_PutIntKey, 0, 0);

    if( pTable ){
      sqliteVdbeAddOp(v, isTemp ? OP_OpenAux : OP_Open, 2, pTab->tnum);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      lbl2 = sqliteVdbeMakeLabel(v);
      sqliteVdbeAddOp(v, OP_Rewind, 2, lbl2);
      lbl1 = sqliteVdbeAddOp(v, OP_Recno, 2, 0);
      for(i=0; i<pIndex->nColumn; i++){
................................................................................
      sqliteVdbeAddOp(v, OP_Next, 2, lbl1);
      sqliteVdbeResolveLabel(v, lbl2);
      sqliteVdbeAddOp(v, OP_Close, 2, 0);
      sqliteVdbeAddOp(v, OP_Close, 1, 0);
    }
    if( pTable!=0 ){
      if( !isTemp ){
        sqliteChangeCookie(db, v);



      }
      sqliteVdbeAddOp(v, OP_Close, 0, 0);
      sqliteEndWriteOperation(pParse);
    }
  }

  /* Clean up before exiting */
exit_create_index:
  sqliteIdListDelete(pList);
................................................................................
    return;
  }

  /* Generate code to remove the index and from the master table */
  v = sqliteGetVdbe(pParse);
  if( v ){
    static VdbeOp dropIndex[] = {

      { OP_Rewind,     0, ADDR(9), 0}, 
      { OP_String,     0, 0,       0}, /* 1 */
      { OP_MemStore,   1, 1,       0},
      { OP_MemLoad,    1, 0,       0}, /* 3 */
      { OP_Column,     0, 1,       0},
      { OP_Eq,         0, ADDR(8), 0},
      { OP_Next,       0, ADDR(3), 0},
      { OP_Goto,       0, ADDR(9), 0},
      { OP_Delete,     0, 0,       0}, /* 8 */



    };
    int base;
    Table *pTab = pIndex->pTable;

    sqliteBeginWriteOperation(pParse, 0);
    sqliteOpenMasterTable(v, pTab->isTemp);
    base = sqliteVdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
    sqliteVdbeChangeP3(v, base+1, pIndex->zName, 0);
    if( !pTab->isTemp ){
      sqliteChangeCookie(db, v);

    }
    sqliteVdbeAddOp(v, OP_Close, 0, 0);
    sqliteVdbeAddOp(v, OP_Destroy, pIndex->tnum, pTab->isTemp);
    sqliteEndWriteOperation(pParse);
  }

  /* Delete the in-memory description of this index.




  */
  if( !pParse->explain ){
    sqliteUnlinkAndDeleteIndex(db, pIndex);
    db->flags |= SQLITE_InternChanges;
  }
}

/*
** Append a new element to the given IdList.  Create a new IdList if
** need be.

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
26
27
28
29
30
31
32

33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
...
116
117
118
119
120
121
122
123
124
125






126
127
128
129
130
131









132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
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
...
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
...
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
...
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
...
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.83 2002/06/22 02:33:38 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the
................................................................................
**
** Each callback contains the following information:
**
**     argv[0] = "file-format" or "schema-cookie" or "table" or "index"
**     argv[1] = table or index name or meta statement type.
**     argv[2] = root page number for table or index.  NULL for meta.
**     argv[3] = SQL create statement for the table or index

**
*/
int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

  /* TODO: Do some validity checks on all fields.  In particular,
  ** make sure fields do not contain NULLs. Otherwise we might core
  ** when attempting to initialize from a corrupt database file. */

  assert( argc==4 );
  switch( argv[0][0] ){
    case 'c': {  /* Recommended pager cache size */
      int size = atoi(argv[3]);
      if( size==0 ){ size = MAX_PAGES; }
      db->cache_size = size;
      sqliteBtreeSetCacheSize(db->pBe, size);
      break;
    }
    case 'f': {  /* File format */
      /*
      ** file_format==1  Version 2.1.0.
      ** file_format==2  Version 2.2.0.  Integer primary key.
      ** file_format==3  Version 2.6.0.  Separate text and numeric datatypes.
      */
      db->file_format = atoi(argv[3]);
      break;
    }
    case 's': { /* Schema cookie */
      db->schema_cookie = atoi(argv[3]);
      db->next_cookie = db->schema_cookie;
      break;
    }
    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because sParse.initFlag is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = db;
        sParse.initFlag = 1;

        sParse.newTnum = atoi(argv[2]);
        sqliteRunParser(&sParse, argv[3], 0);
      }else{
        /* If the SQL column is blank it means this is an index that
        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
        ** constraint for a CREATE TABLE.  The index should have already
        ** been created when we processed the CREATE TABLE.  All we have
................................................................................
** After the database is initialized, the SQLITE_Initialized
** bit is set in the flags field of the sqlite structure.  An
** attempt is made to initialize the database as soon as it
** is opened.  If that fails (perhaps because another process
** has the sqlite_master table locked) than another attempt
** is made the first time the database is accessed.
*/
static int sqliteInit(sqlite *db, char **pzErrMsg){
  Vdbe *vdbe;
  int rc;







  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE " MASTER_NAME " (\n"









     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;

  /* The following VDBE program is used to initialize the internal
  ** structure holding the tables and indexes of the database.
  ** The database contains a special table named "sqlite_master"
  ** defined as follows:
  **
  **    CREATE TABLE sqlite_master (
  **        type       text,    --  Either "table" or "index" or "meta"
  **        name       text,    --  Name of table or index
  **        tbl_name   text,    --  Associated table 
  **        rootpage   integer, --  The integer page number of root page
  **        sql        text     --  The CREATE statement for this object
  **    );
  **
  ** The sqlite_master table contains a single entry for each table
  ** and each index.  The "type" column tells whether the entry is
  ** a table or index.  The "name" column is the name of the object.
  ** The "tbl_name" is the name of the associated table.  For tables,
  ** the tbl_name column is always the same as name.  For indices, the
  ** tbl_name column contains the name of the table that the index
  ** indexes.  The "rootpage" column holds the number of the root page
  ** for the b-tree for the table or index.  Finally, the "sql" column
  ** contains the complete text of the CREATE TABLE or CREATE INDEX
  ** statement that originally created the table or index.  If an index
  ** was created to fulfill a PRIMARY KEY or UNIQUE constraint on a table,
  ** then the "sql" column is NULL.
  **
  ** In format 1, entries in the sqlite_master table are in a random
  ** order.  Two passes must be made through the table to initialize
  ** internal data structures.  The first pass reads table definitions
  ** and the second pass read index definitions.  Having two passes
  ** insures that indices appear after their tables.
  **
  ** In format 2, entries appear in chronological order.  Only a single
  ** pass needs to be made through the table since everything will be
  ** in the write order.  VIEWs may only occur in format 2.
  **
  ** The following program invokes its callback on the SQL for each
  ** table then goes back and invokes the callback on the
  ** SQL for each index.  The callback will invoke the
  ** parser to build the internal representation of the
  ** database scheme.
  */
  static VdbeOp initProg[] = {
    /* Send the file format to the callback routine
    */
    { OP_Open,       0, 2,  0},
    { OP_String,     0, 0,  "file-format"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 1,  0},
    { OP_Callback,   4, 0,  0},

    /* Send the recommended pager cache size to the callback routine
    */
    { OP_String,     0, 0,  "cache-size"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 2,  0},
    { OP_Callback,   4, 0,  0},

    /* Send the initial schema cookie to the callback
    */
    { OP_String,     0, 0,  "schema_cookie"},
    { OP_String,     0, 0,  0},
    { OP_String,     0, 0,  0},
    { OP_ReadCookie, 0, 0,  0},
    { OP_Callback,   4, 0,  0},

    /* Check the file format.  If the format number is 2 or more,
    ** then do a single pass through the SQLITE_MASTER table.  For
    ** a format number of less than 2, jump forward to a different
    ** algorithm that makes two passes through the SQLITE_MASTER table,
    ** once for tables and a second time for indices.
    */
    { OP_ReadCookie, 0, 1,  0},
    { OP_Integer,    2, 0,  0},
    { OP_Lt,         0, 28, 0},

    /* This is the code for doing a single scan through the SQLITE_MASTER
    ** table.  This code runs for format 2 and greater.
    */
    { OP_Rewind,     0, 26, 0},
    { OP_Column,     0, 0,  0},           /* 20 */
    { OP_Column,     0, 1,  0},
    { OP_Column,     0, 3,  0},
    { OP_Column,     0, 4,  0},
    { OP_Callback,   4, 0,  0},
    { OP_Next,       0, 20, 0},
    { OP_Close,      0, 0,  0},           /* 26 */
    { OP_Halt,       0, 0,  0},

    /* This is the code for doing two passes through SQLITE_MASTER.  This
    ** code runs for file format 1.
    */
    { OP_Rewind,     0, 48, 0},           /* 28 */
    { OP_Column,     0, 0,  0},           /* 29 */
    { OP_String,     0, 0,  "table"},
    { OP_Ne,         0, 37, 0},
    { OP_Column,     0, 0,  0},
    { OP_Column,     0, 1,  0},
    { OP_Column,     0, 3,  0},
    { OP_Column,     0, 4,  0},
    { OP_Callback,   4, 0,  0},
    { OP_Next,       0, 29, 0},           /* 37 */
    { OP_Rewind,     0, 48, 0},           /* 38 */
    { OP_Column,     0, 0,  0},           /* 39 */
    { OP_String,     0, 0,  "index"},
    { OP_Ne,         0, 47, 0},
    { OP_Column,     0, 0,  0},
    { OP_Column,     0, 1,  0},
    { OP_Column,     0, 3,  0},
    { OP_Column,     0, 4,  0},
    { OP_Callback,   4, 0,  0},
    { OP_Next,       0, 39, 0},           /* 47 */
    { OP_Close,      0, 0,  0},           /* 48 */
    { OP_Halt,       0, 0,  0},
  };

  /* Create a virtual machine to run the initialization program.  Run
  ** the program.  Then delete the virtual machine.
  */
  vdbe = sqliteVdbeCreate(db);
  if( vdbe==0 ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    return SQLITE_NOMEM;
  }
  sqliteVdbeAddOpList(vdbe, sizeof(initProg)/sizeof(initProg[0]), initProg);
  rc = sqliteVdbeExec(vdbe, sqliteInitCallback, db, pzErrMsg, 
                      db->pBusyArg, db->xBusyCallback);
  sqliteVdbeDelete(vdbe);
  if( rc==SQLITE_OK && db->nTable==0 ){
    db->file_format = 2;
  }
  if( rc==SQLITE_OK && db->file_format>2 ){
    sqliteSetString(pzErrMsg, "unsupported file format", 0);
    rc = SQLITE_ERROR;
  }

  /* The schema for the SQLITE_MASTER table is not stored in the
  ** database itself.  We have to invoke the callback one extra
  ** time to get it to process the SQLITE_MASTER table defintion.
  */


  if( rc==SQLITE_OK ){
    Table *pTab;
    char *azArg[6];
    azArg[0] = "table";
    azArg[1] = MASTER_NAME;
    azArg[2] = "2";
    azArg[3] = master_schema;
    azArg[4] = 0;
    sqliteInitCallback(db, 4, azArg, 0);
    pTab = sqliteFindTable(db, MASTER_NAME);
    if( pTab ){
      pTab->readOnly = 1;
    }

    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);



  }

  return rc;
}

/*
** The version of the library
*/
const char sqlite_version[] = SQLITE_VERSION;

................................................................................
  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->trigDrop, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0);
  sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0);
  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
  sqliteRegisterBuiltinFunctions(db);
  db->onError = OE_Default;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  
  /* Open the backend database driver */
................................................................................

no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", 0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}

/*
** Erase all schema information from the schema hash table.  Except
** tables that are created using CREATE TEMPORARY TABLE are preserved
** if the preserveTemps flag is true.
**
** The database schema is normally read in once when the database
** is first opened and stored in a hash table in the sqlite structure.
** This routine erases the stored schema.  This erasure occurs because
** either the database is being closed or because some other process
** changed the schema and this process needs to reread it.
*/
static void clearHashTable(sqlite *db, int preserveTemps){
  HashElem *pElem;
  Hash temp1;
  Hash temp2;

  /* Make sure there are no uncommited DROPs */
  assert( sqliteHashFirst(&db->tblDrop)==0 || sqlite_malloc_failed );
  assert( sqliteHashFirst(&db->idxDrop)==0 || sqlite_malloc_failed );
  assert( sqliteHashFirst(&db->trigDrop)==0 || sqlite_malloc_failed );
  temp1 = db->tblHash;
  temp2 = db->trigHash;
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashClear(&db->idxHash);

  for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
    Trigger * pTrigger = sqliteHashData(pElem);
    Table *pTab = sqliteFindTable(db, pTrigger->table);
    assert(pTab);
    if( pTab->isTemp && preserveTemps ){ 
      sqliteHashInsert(&db->trigHash, pTrigger->name, strlen(pTrigger->name), 
          pTrigger);
    }else{
      sqliteDeleteTrigger(pTrigger);
    }
  }
  sqliteHashClear(&temp2);

  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);

  for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
    Table *pTab = sqliteHashData(pElem);
    if( preserveTemps && pTab->isTemp ){
      Index *pIdx;
      int nName = strlen(pTab->zName);
      Table *pOld = sqliteHashInsert(&db->tblHash, pTab->zName, nName+1, pTab);
      if( pOld!=0 ){
        assert( pOld==pTab );   /* Malloc failed on the HashInsert */
        sqliteDeleteTable(db, pOld);
        continue;
      }
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        int n = strlen(pIdx->zName)+1;
        Index *pOldIdx;
        pOldIdx = sqliteHashInsert(&db->idxHash, pIdx->zName, n, pIdx);
        if( pOld ){
          assert( pOldIdx==pIdx );
          sqliteUnlinkAndDeleteIndex(db, pOldIdx);
        }
      }
    }else{
      sqliteDeleteTable(db, pTab);
    }
  }
  sqliteHashClear(&temp1);
  db->flags &= ~SQLITE_Initialized;
}

/*
** Return the ROWID of the most recent insert
*/
int sqlite_last_insert_rowid(sqlite *db){
  return db->lastRowid;
}

................................................................................
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
  HashElem *i;
  if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ return; }
  db->magic = SQLITE_MAGIC_CLOSED;
  sqliteBtreeClose(db->pBe);
  sqliteRollbackInternalChanges(db);
  clearHashTable(db, 0);
  if( db->pBeTemp ){
    sqliteBtreeClose(db->pBeTemp);
  }
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
................................................................................
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
    sqliteBtreeRollback(db->pBe);
    if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
    db->flags &= ~SQLITE_InTrans;
    clearHashTable(db, 0);
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    clearHashTable(db, 1);
  }
  db->recursionDepth--;
  if( sqliteSafetyOff(db) ) goto exec_misuse;
  return sParse.rc;

exec_misuse:
  if( pzErrMsg ){







|







 







>











|

<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<












>







 







|
<

>
>
>
>
>
>





|
>
>
>
>
>
>
>
>
>








|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




|
<
<

>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
>


>
>
>

>
|







 







<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







|
<







 







|



|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46





















47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
97
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215





















































216
217
218
219
220


221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
...
276
277
278
279
280
281
282



283
284
285
286
287
288
289
...
317
318
319
320
321
322
323




































































324
325
326
327
328
329
330
...
339
340
341
342
343
344
345
346

347
348
349
350
351
352
353
...
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
**
*************************************************************************
** Main file for the SQLite library.  The routines in this file
** implement the programmer interface to the library.  Routines in
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.84 2002/06/25 01:09:11 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** This is the callback routine for the code that initializes the
................................................................................
**
** Each callback contains the following information:
**
**     argv[0] = "file-format" or "schema-cookie" or "table" or "index"
**     argv[1] = table or index name or meta statement type.
**     argv[2] = root page number for table or index.  NULL for meta.
**     argv[3] = SQL create statement for the table or index
**     argv[4] = "1" for temporary files, "0" for main database
**
*/
int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){
  sqlite *db = (sqlite*)pDb;
  Parse sParse;
  int nErr = 0;

  /* TODO: Do some validity checks on all fields.  In particular,
  ** make sure fields do not contain NULLs. Otherwise we might core
  ** when attempting to initialize from a corrupt database file. */

  assert( argc==5 );
  switch( argv[0][0] ){





















    case 'v':
    case 'i':
    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */
      if( argv[3] && argv[3][0] ){
        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.
        ** But because sParse.initFlag is set to 1, no VDBE code is generated
        ** or executed.  All the parser does is build the internal data
        ** structures that describe the table, index, or view.
        */
        memset(&sParse, 0, sizeof(sParse));
        sParse.db = db;
        sParse.initFlag = 1;
        sParse.isTemp = argv[4][0] - '0';
        sParse.newTnum = atoi(argv[2]);
        sqliteRunParser(&sParse, argv[3], 0);
      }else{
        /* If the SQL column is blank it means this is an index that
        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
        ** constraint for a CREATE TABLE.  The index should have already
        ** been created when we processed the CREATE TABLE.  All we have
................................................................................
** After the database is initialized, the SQLITE_Initialized
** bit is set in the flags field of the sqlite structure.  An
** attempt is made to initialize the database as soon as it
** is opened.  If that fails (perhaps because another process
** has the sqlite_master table locked) than another attempt
** is made the first time the database is accessed.
*/
int sqliteInit(sqlite *db, char **pzErrMsg){

  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char *azArg[6];
  int meta[SQLITE_N_BTREE_META];
  Parse sParse;

  /*
  ** The master database table has a structure like this
  */
  static char master_schema[] = 
     "CREATE TABLE sqlite_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;
  static char temp_master_schema[] = 
     "CREATE TEMP TABLE sqlite_temp_master(\n"
     "  type text,\n"
     "  name text,\n"
     "  tbl_name text,\n"
     "  rootpage integer,\n"
     "  sql text\n"
     ")"
  ;

  /* The following SQL will read the schema from the master tables.
  ** The first version works with SQLite file formats 2 or greater.
  ** The second version is for format 1 files.
  **
  ** Beginning with file format 2, the rowid for new table entries
  ** (including entries in sqlite_master) is an increasing integer.
  ** So for file format 2 and later, we can play back sqlite_master
  ** and all the CREATE statements will appear in the right order.
  ** But with file format 1, table entries were random and so we
  ** have to make sure the CREATE TABLEs occur before their corresponding
  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or
  ** CREATE TRIGGER in file format 1 because those constructs did
  ** not exist then.) 
  */
  static char init_script[] = 
     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
     "UNION ALL "
     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master";
  static char older_init_script[] = 
     "SELECT type, name, rootpage, sql, 1 FROM sqlite_temp_master "
     "UNION ALL "
     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
     "WHERE type='table' "
     "UNION ALL "
     "SELECT type, name, rootpage, sql, 0 FROM sqlite_master "
     "WHERE type='index'";


  /* Construct the schema tables: sqlite_master and sqlite_temp_master
  */
  azArg[0] = "table";
  azArg[1] = MASTER_NAME;
  azArg[2] = "2";
  azArg[3] = master_schema;
  azArg[4] = "0";
  azArg[5] = 0;
  sqliteInitCallback(db, 5, azArg, 0);
  pTab = sqliteFindTable(db, MASTER_NAME);
  if( pTab ){
    pTab->readOnly = 1;
  }
  azArg[1] = TEMP_MASTER_NAME;
  azArg[3] = temp_master_schema;
  azArg[4] = "1";
  sqliteInitCallback(db, 5, azArg, 0);
  pTab = sqliteFindTable(db, TEMP_MASTER_NAME);
  if( pTab ){
    pTab->readOnly = 1;
  }

  /* Create a cursor to hold the database open
  */
  if( db->pBe==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->pBe, 2, 0, &curMain);
  if( rc ) return rc;

  /* Get the database meta information
  */
  rc = sqliteBtreeGetMeta(db->pBe, meta);
  if( rc ){
    sqliteBtreeCloseCursor(curMain);
    return rc;
  }
  db->schema_cookie = meta[1];
  db->next_cookie = db->schema_cookie;
  db->file_format = meta[2];
  size = meta[3];
  if( size==0 ){ size = MAX_PAGES; }
  db->cache_size = size;
  sqliteBtreeSetCacheSize(db->pBe, size);

  /*
  **     file_format==1    Version 2.1.0.
  **     file_format==2    Version 2.2.0. Add support for INTEGER PRIMARY KEY.
  **     file_format==3    Version 2.6.0. Add support for separate numeric and
  **                       text datatypes.
  */
  if( db->file_format==0 ){
    db->file_format = 2;
  }else if( db->file_format>2 ){
    sqliteBtreeCloseCursor(curMain);





















































    sqliteSetString(pzErrMsg, "unsupported file format", 0);
    rc = SQLITE_ERROR;
  }

  /* Read the schema information out of the schema tables


  */
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.pBe = db->pBe;
  sParse.xCallback = sqliteInitCallback;
  sParse.pArg = (void*)db;
  sParse.initFlag = 1;
  sqliteRunParser(&sParse,
      db->file_format>=2 ? init_script : older_init_script,
      pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
    sqliteBtreeRollback(db->pBe);
    sqliteResetInternalSchema(db);
  }
  if( sParse.rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }else{
    db->flags &= ~SQLITE_Initialized;
    sqliteResetInternalSchema(db);
  }
  sqliteBtreeCloseCursor(curMain);
  return sParse.rc;
}

/*
** The version of the library
*/
const char sqlite_version[] = SQLITE_VERSION;

................................................................................
  /* Allocate the sqlite data structure */
  db = sqliteMalloc( sizeof(sqlite) );
  if( pzErrMsg ) *pzErrMsg = 0;
  if( db==0 ) goto no_mem_on_open;
  sqliteHashInit(&db->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&db->trigHash, SQLITE_HASH_STRING, 0);



  sqliteHashInit(&db->aFunc, SQLITE_HASH_STRING, 1);
  sqliteRegisterBuiltinFunctions(db);
  db->onError = OE_Default;
  db->priorNewRowid = 0;
  db->magic = SQLITE_MAGIC_BUSY;
  
  /* Open the backend database driver */
................................................................................

no_mem_on_open:
  sqliteSetString(pzErrMsg, "out of memory", 0);
  sqliteStrRealloc(pzErrMsg);
  return 0;
}





































































/*
** Return the ROWID of the most recent insert
*/
int sqlite_last_insert_rowid(sqlite *db){
  return db->lastRowid;
}

................................................................................
** Close an existing SQLite database
*/
void sqlite_close(sqlite *db){
  HashElem *i;
  if( sqliteSafetyCheck(db) || sqliteSafetyOn(db) ){ return; }
  db->magic = SQLITE_MAGIC_CLOSED;
  sqliteBtreeClose(db->pBe);
  sqliteResetInternalSchema(db);

  if( db->pBeTemp ){
    sqliteBtreeClose(db->pBeTemp);
  }
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
................................................................................
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
    sqliteBtreeRollback(db->pBe);
    if( db->pBeTemp ) sqliteBtreeRollback(db->pBeTemp);
    db->flags &= ~SQLITE_InTrans;
    sqliteResetInternalSchema(db);
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    sqliteResetInternalSchema(db);
  }
  db->recursionDepth--;
  if( sqliteSafetyOff(db) ) goto exec_misuse;
  return sParse.rc;

exec_misuse:
  if( pzErrMsg ){

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.74 2002/06/17 17:07:20 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
input ::= cmdlist.

// A list of commands is zero or more commands
//
cmdlist ::= ecmd.
cmdlist ::= cmdlist ecmd.
ecmd ::= explain cmd SEMI.  {sqliteExec(pParse);}
ecmd ::= cmd SEMI.          {sqliteExec(pParse);}
ecmd ::= SEMI.
explain ::= EXPLAIN.    {pParse->explain = 1;}

///////////////////// Begin and end transactions. ////////////////////////////
//

cmd ::= BEGIN trans_opt onconf(R).  {sqliteBeginTransaction(pParse,R);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
................................................................................
///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= CREATE(X) temp(T) TABLE ids(Y). {
   sqliteStartTable(pParse,&X,&Y,T);
}
%type temp {int}
temp(A) ::= TEMP.  {A = 1;}
temp(A) ::= .      {A = 0;}
create_table_args ::= LP columnlist conslist_opt RP(X). {
  sqliteEndTable(pParse,&X,0);
}
create_table_args ::= AS select(S). {
  sqliteEndTable(pParse,0,S);
  sqliteSelectDelete(S);
}







|







 







|
|
|







 







|
|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.75 2002/06/25 01:09:12 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
input ::= cmdlist.

// A list of commands is zero or more commands
//
cmdlist ::= ecmd.
cmdlist ::= cmdlist ecmd.
ecmd ::= explain cmd SEMI.  {sqliteExec(pParse);}
ecmd ::= SEMI.
explain ::= EXPLAIN.    { sqliteBeginParse(pParse, 1); }
explain ::= .           { sqliteBeginParse(pParse, 0); }

///////////////////// Begin and end transactions. ////////////////////////////
//

cmd ::= BEGIN trans_opt onconf(R).  {sqliteBeginTransaction(pParse,R);}
trans_opt ::= .
trans_opt ::= TRANSACTION.
................................................................................
///////////////////// The CREATE TABLE statement ////////////////////////////
//
cmd ::= create_table create_table_args.
create_table ::= CREATE(X) temp(T) TABLE ids(Y). {
   sqliteStartTable(pParse,&X,&Y,T);
}
%type temp {int}
temp(A) ::= TEMP.  {A = pParse->isTemp || !pParse->initFlag;}
temp(A) ::= .      {A = pParse->isTemp;}
create_table_args ::= LP columnlist conslist_opt RP(X). {
  sqliteEndTable(pParse,&X,0);
}
create_table_args ::= AS select(S). {
  sqliteEndTable(pParse,0,S);
  sqliteSelectDelete(S);
}

Changes to src/shell.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
656
657
658
659
660
661
662



663
664
665
666
667
668
669
670
671
...
792
793
794
795
796
797
798













799
800
801


802
803

804
805
806
807
808


809
810

811
812
813
814
815
816
817
...
842
843
844
845
846
847
848



849
850
851
852
853
854
855



856
857
858
859
860
861
862
863
864
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.57 2002/05/21 13:02:24 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <ctype.h>

................................................................................
    char *zErrMsg = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    sqlite_exec_printf(db,
      "SELECT name FROM sqlite_master "
      "WHERE type='index' AND tbl_name LIKE '%q' "



      "ORDER BY name",
      callback, &data, &zErrMsg, azArg[1]
    );
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else

................................................................................
                      "  rootpage integer,\n"
                      "  sql text\n"
                      ")";
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);













      }else{
        sqlite_exec_printf(db,
          "SELECT sql FROM sqlite_master "


          "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL "
          "ORDER BY type DESC, name",

          callback, &data, &zErrMsg, azArg[1]);
      }
    }else{
      sqlite_exec(db,
         "SELECT sql FROM sqlite_master "


         "WHERE type!='meta' AND sql NOTNULL "
         "ORDER BY tbl_name, type DESC, name",

         callback, &data, &zErrMsg
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
................................................................................
    char **azResult;
    int nRow, rc;
    char *zErrMsg;
    if( nArg==1 ){
      rc = sqlite_get_table(db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') "



        "ORDER BY name",
        &azResult, &nRow, 0, &zErrMsg
      );
    }else{
      rc = sqlite_get_table_printf(db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "



        "ORDER BY name",
        &azResult, &nRow, 0, &zErrMsg, azArg[1]
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
    if( rc==SQLITE_OK ){







|







 







>
>
>
|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>


|
>
>

<
>




|
>
>

<
>







 







>
>
>
|






>
>
>
|
|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
...
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820

821
822
823
824
825
826
827
828
829

830
831
832
833
834
835
836
837
...
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code to implement the "sqlite" command line
** utility for accessing SQLite databases.
**
** $Id: shell.c,v 1.58 2002/06/25 01:09:12 drh Exp $
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "sqlite.h"
#include <ctype.h>

................................................................................
    char *zErrMsg = 0;
    memcpy(&data, p, sizeof(data));
    data.showHeader = 0;
    data.mode = MODE_List;
    sqlite_exec_printf(db,
      "SELECT name FROM sqlite_master "
      "WHERE type='index' AND tbl_name LIKE '%q' "
      "UNION ALL "
      "SELECT name FROM sqlite_temp_master "
      "WHERE type='index' AND tbl_name LIKE '%q' "
      "ORDER BY 1",
      callback, &data, &zErrMsg, azArg[1], azArg[1]
    );
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
  }else

................................................................................
                      "  rootpage integer,\n"
                      "  sql text\n"
                      ")";
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
      }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){
        char *new_argv[2], *new_colv[2];
        new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n"
                      "  type text,\n"
                      "  name text,\n"
                      "  tbl_name text,\n"
                      "  rootpage integer,\n"
                      "  sql text\n"
                      ")";
        new_argv[1] = 0;
        new_colv[0] = "sql";
        new_colv[1] = 0;
        callback(&data, 1, new_argv, new_colv);
      }else{
        sqlite_exec_printf(db,
          "SELECT sql FROM "
          "  (SELECT * FROM sqlite_master UNION ALL"
          "   SELECT * FROM sqlite_temp_master) "
          "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL "

          "ORDER BY substr(type,2,1), name",
          callback, &data, &zErrMsg, azArg[1]);
      }
    }else{
      sqlite_exec(db,
         "SELECT sql FROM "
         "  (SELECT * FROM sqlite_master UNION ALL"
         "   SELECT * FROM sqlite_temp_master) "
         "WHERE type!='meta' AND sql NOTNULL "

         "ORDER BY substr(type,2,1), name",
         callback, &data, &zErrMsg
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
................................................................................
    char **azResult;
    int nRow, rc;
    char *zErrMsg;
    if( nArg==1 ){
      rc = sqlite_get_table(db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg
      );
    }else{
      rc = sqlite_get_table_printf(db,
        "SELECT name FROM sqlite_master "
        "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
        "UNION ALL "
        "SELECT name FROM sqlite_temp_master "
        "WHERE type IN ('table','view') AND name LIKE '%%%q%%' "
        "ORDER BY 1",
        &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1]
      );
    }
    if( zErrMsg ){
      fprintf(stderr,"Error: %s\n", zErrMsg);
      free(zErrMsg);
    }
    if( rc==SQLITE_OK ){

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
142
143
144
145
146
147
148

149
150
151
152
153
154
155
...
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
...
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
...
644
645
646
647
648
649
650
651
652
653
654





655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
...
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
...
843
844
845
846
847
848
849
850


851

852

853
854
855
856
857
858
859
...
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.130 2002/06/24 22:01:58 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................

/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
*/
#define MASTER_NAME   "sqlite_master"


/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    (sizeof(X)/sizeof(X[0]))

................................................................................
  int next_cookie;              /* Value of schema_cookie after commit */
  int cache_size;               /* Number of pages to use in the cache */
  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Hash tblHash;                 /* All tables indexed by name */
  Hash idxHash;                 /* All (named) indices indexed by name */
  Hash tblDrop;                 /* Uncommitted DROP TABLEs */
  Hash idxDrop;                 /* Uncommitted DROP INDEXs */
  Hash aFunc;                   /* All functions that can be in SQL exprs */
  int lastRowid;                /* ROWID of most recent insert */
  int priorNewRowid;            /* Last randomly generated ROWID */
  int onError;                  /* Default conflict algorithm */
  int magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Number of rows changed */
  int recursionDepth;           /* Number of nested calls to sqlite_exec() */

  Hash trigHash;                /* All triggers indexed by name */
  Hash trigDrop;                /* Uncommited dropped triggers */
};

/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
................................................................................
  int nCol;        /* Number of columns in this table */
  Column *aCol;    /* Information about each column */
  int iPKey;       /* If not less then 0, use aCol[iPKey] as the primary key */
  Index *pIndex;   /* List of SQL indexes on this table. */
  int tnum;        /* Root BTree node for this table (see note above) */
  Select *pSelect; /* NULL for tables.  Points to definition if a view. */
  u8 readOnly;     /* True if this table should not be written by the user */
  u8 isCommit;     /* True if creation of this table has been committed */
  u8 isTemp;       /* True if stored in db->pBeTemp instead of db->pBe */
  u8 isTransient;  /* True if automatically deleted when VDBE finishes */
  u8 hasPrimKey;   /* True if there exists a primary key */
  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */

  Trigger *pTrigger; /* List of SQL triggers on this table */
};

/*
** SQLite supports 5 different ways to resolve a contraint
** error.  ROLLBACK processing means that a constraint violation
** causes the operation in process to fail and for the current transaction
................................................................................
struct Index {
  char *zName;     /* Name of this index */
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 isUnique;     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  u8 isCommit;     /* True if creation of this index has been committed */
  u8 isDropped;    /* True if a DROP INDEX has executed on this index */
  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  Index *pNext;    /* The next index associated with the same table */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.
................................................................................
  void *pArg;          /* First argument to the callback function */
  char *zErrMsg;       /* An error message */
  Token sErrToken;     /* The token at which the error occurred */
  Token sFirstToken;   /* The first token parsed */
  Token sLastToken;    /* The last token parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  int colNamesSet;     /* TRUE after OP_ColumnCount has been issued to pVdbe */
  int explain;         /* True if the EXPLAIN flag is found on the query */
  int initFlag;        /* True if reparsing CREATE TABLEs */
  int nameClash;       /* A permanent table name clashes with temp table name */





  int newTnum;         /* Table number to use when reparsing CREATE TABLEs */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */
  int useAgg;          /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
  int schemaVerified;  /* True if an OP_VerifySchema has been coded someplace
                       ** other than after an OP_Transaction */
  TriggerStack *trigStack;
};

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *
................................................................................
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  int foreach;            /* One of TK_ROW or TK_STATEMENT */

  TriggerStep *step_list; /* Link list of trigger program steps             */
  char *strings;          /* pointer to allocation of Token strings */
  Trigger *pNext;         /* Next trigger associated with the table */
  int isCommit;           /* Set to TRUE once the trigger has been committed */
};

/*
 * An instance of struct TriggerStep is used to store a single SQL statement
 * that is a part of a trigger-program. 
 *
 * Instances of struct TriggerStep are stored in a singly linked list (linked
................................................................................
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
void sqliteExprSpan(Expr*,Token*,Token*);
Expr *sqliteExprFunction(ExprList*, Token*);
void sqliteExprDelete(Expr*);
ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*);
void sqliteExprListDelete(ExprList*);
void sqlitePragma(Parse*,Token*,Token*,int);
void sqliteCommitInternalChanges(sqlite*);


void sqliteRollbackInternalChanges(sqlite*);

Table *sqliteResultSetOfSelect(Parse*,char*,Select*);

void sqliteStartTable(Parse*,Token*,Token*,int);
void sqliteAddColumn(Parse*,Token*);
void sqliteAddNotNull(Parse*, int);
void sqliteAddPrimaryKey(Parse*, IdList*, int);
void sqliteAddColumnType(Parse*,Token*,Token*);
void sqliteAddDefaultValue(Parse*,Token*,int);
int sqliteCollateType(Parse*, Token*);
................................................................................
IdList *sqliteIdListDup(IdList*);
Select *sqliteSelectDup(Select*);
FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
void sqliteRegisterBuiltinFunctions(sqlite*);
int sqliteSafetyOn(sqlite*);
int sqliteSafetyOff(sqlite*);
int sqliteSafetyCheck(sqlite*);
void sqliteChangeCookie(sqlite *);
void sqliteCreateTrigger(Parse*, Token*, int, int, IdList*, Token*, 
                         int, Expr*, TriggerStep*, char const*,int);
void sqliteDropTrigger(Parse*, Token*, int);
int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
                         int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);







|







 







>







 







|
<







<
<
<







 







<




<







 







<
<







 







|
|
|
|
>
>
>
>
>







<
<
<
<







 







<







 







|
>
>

>

>







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
199
200
201
202
203
204
205
206

207
208
209
210
211
212
213



214
215
216
217
218
219
220
...
318
319
320
321
322
323
324

325
326
327
328

329
330
331
332
333
334
335
...
377
378
379
380
381
382
383


384
385
386
387
388
389
390
...
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659




660
661
662
663
664
665
666
...
701
702
703
704
705
706
707

708
709
710
711
712
713
714
...
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.131 2002/06/25 01:09:12 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
#include <stdio.h>
................................................................................

/*
** Name of the master database table.  The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
*/
#define MASTER_NAME       "sqlite_master"
#define TEMP_MASTER_NAME  "sqlite_temp_master"

/*
** A convenience macro that returns the number of elements in
** an array.
*/
#define ArraySize(X)    (sizeof(X)/sizeof(X[0]))

................................................................................
  int next_cookie;              /* Value of schema_cookie after commit */
  int cache_size;               /* Number of pages to use in the cache */
  int nTable;                   /* Number of tables in the database */
  void *pBusyArg;               /* 1st Argument to the busy callback */
  int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
  Hash tblHash;                 /* All tables indexed by name */
  Hash idxHash;                 /* All (named) indices indexed by name */
  Hash trigHash;                /* All triggers indexed by name */

  Hash aFunc;                   /* All functions that can be in SQL exprs */
  int lastRowid;                /* ROWID of most recent insert */
  int priorNewRowid;            /* Last randomly generated ROWID */
  int onError;                  /* Default conflict algorithm */
  int magic;                    /* Magic number for detect library misuse */
  int nChange;                  /* Number of rows changed */
  int recursionDepth;           /* Number of nested calls to sqlite_exec() */



};

/*
** Possible values for the sqlite.flags.
*/
#define SQLITE_VdbeTrace      0x00000001  /* True to trace VDBE execution */
#define SQLITE_Initialized    0x00000002  /* True after initialization */
................................................................................
  int nCol;        /* Number of columns in this table */
  Column *aCol;    /* Information about each column */
  int iPKey;       /* If not less then 0, use aCol[iPKey] as the primary key */
  Index *pIndex;   /* List of SQL indexes on this table. */
  int tnum;        /* Root BTree node for this table (see note above) */
  Select *pSelect; /* NULL for tables.  Points to definition if a view. */
  u8 readOnly;     /* True if this table should not be written by the user */

  u8 isTemp;       /* True if stored in db->pBeTemp instead of db->pBe */
  u8 isTransient;  /* True if automatically deleted when VDBE finishes */
  u8 hasPrimKey;   /* True if there exists a primary key */
  u8 keyConf;      /* What to do in case of uniqueness conflict on iPKey */

  Trigger *pTrigger; /* List of SQL triggers on this table */
};

/*
** SQLite supports 5 different ways to resolve a contraint
** error.  ROLLBACK processing means that a constraint violation
** causes the operation in process to fail and for the current transaction
................................................................................
struct Index {
  char *zName;     /* Name of this index */
  int nColumn;     /* Number of columns in the table used by this index */
  int *aiColumn;   /* Which columns are used by this index.  1st is 0 */
  Table *pTable;   /* The SQL table being indexed */
  int tnum;        /* Page containing root of this index in database file */
  u8 isUnique;     /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */


  u8 onError;      /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  Index *pNext;    /* The next index associated with the same table */
};

/*
** Each token coming out of the lexer is an instance of
** this structure.
................................................................................
  void *pArg;          /* First argument to the callback function */
  char *zErrMsg;       /* An error message */
  Token sErrToken;     /* The token at which the error occurred */
  Token sFirstToken;   /* The first token parsed */
  Token sLastToken;    /* The last token parsed */
  Table *pNewTable;    /* A table being constructed by CREATE TABLE */
  Vdbe *pVdbe;         /* An engine for executing database bytecode */
  u8 colNamesSet;      /* TRUE after OP_ColumnCount has been issued to pVdbe */
  u8 explain;          /* True if the EXPLAIN flag is found on the query */
  u8 initFlag;         /* True if reparsing CREATE TABLEs */
  u8 nameClash;        /* A permanent table name clashes with temp table name */
  u8 useAgg;           /* If true, extract field values from the aggregator
                       ** while generating expressions.  Normally false */
  u8 schemaVerified;   /* True if an OP_VerifySchema has been coded someplace
                       ** other than after an OP_Transaction */
  u8 isTemp;           /* True if parsing temporary tables */
  int newTnum;         /* Table number to use when reparsing CREATE TABLEs */
  int nErr;            /* Number of errors seen */
  int nTab;            /* Number of previously allocated VDBE cursors */
  int nMem;            /* Number of memory cells used so far */
  int nSet;            /* Number of sets used so far */
  int nAgg;            /* Number of aggregate expressions */
  AggExpr *aAgg;       /* An array of aggregate expressions */




  TriggerStack *trigStack;
};

/*
 * Each trigger present in the database schema is stored as an instance of
 * struct Trigger. 
 *
................................................................................
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  int foreach;            /* One of TK_ROW or TK_STATEMENT */

  TriggerStep *step_list; /* Link list of trigger program steps             */
  char *strings;          /* pointer to allocation of Token strings */
  Trigger *pNext;         /* Next trigger associated with the table */

};

/*
 * An instance of struct TriggerStep is used to store a single SQL statement
 * that is a part of a trigger-program. 
 *
 * Instances of struct TriggerStep are stored in a singly linked list (linked
................................................................................
Expr *sqliteExpr(int, Expr*, Expr*, Token*);
void sqliteExprSpan(Expr*,Token*,Token*);
Expr *sqliteExprFunction(ExprList*, Token*);
void sqliteExprDelete(Expr*);
ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*);
void sqliteExprListDelete(ExprList*);
void sqlitePragma(Parse*,Token*,Token*,int);
void sqliteResetInternalSchema(sqlite*);
int sqliteInit(sqlite*, char**);
void sqliteBeginParse(Parse*,int);
void sqliteRollbackInternalChanges(sqlite*);
void sqliteCommitInternalChanges(sqlite*);
Table *sqliteResultSetOfSelect(Parse*,char*,Select*);
void sqliteOpenMasterTable(Vdbe *v, int);
void sqliteStartTable(Parse*,Token*,Token*,int);
void sqliteAddColumn(Parse*,Token*);
void sqliteAddNotNull(Parse*, int);
void sqliteAddPrimaryKey(Parse*, IdList*, int);
void sqliteAddColumnType(Parse*,Token*,Token*);
void sqliteAddDefaultValue(Parse*,Token*,int);
int sqliteCollateType(Parse*, Token*);
................................................................................
IdList *sqliteIdListDup(IdList*);
Select *sqliteSelectDup(Select*);
FuncDef *sqliteFindFunction(sqlite*,const char*,int,int,int);
void sqliteRegisterBuiltinFunctions(sqlite*);
int sqliteSafetyOn(sqlite*);
int sqliteSafetyOff(sqlite*);
int sqliteSafetyCheck(sqlite*);
void sqliteChangeCookie(sqlite*, Vdbe*);
void sqliteCreateTrigger(Parse*, Token*, int, int, IdList*, Token*, 
                         int, Expr*, TriggerStep*, char const*,int);
void sqliteDropTrigger(Parse*, Token*, int);
int sqliteTriggersExist(Parse* , Trigger* , int , int , int, ExprList*);
int sqliteCodeRowTrigger(Parse*, int, ExprList*, int, Table *, int, int, 
                         int, int);
void sqliteViewTriggers(Parse*, Table*, Expr*, int, ExprList*);

Changes to src/trigger.c.

65
66
67
68
69
70
71






72
73
74
75
76
77
78
..
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144


145
146
147

148
149


150
151
152
153
154
155
156
...
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
...
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364


365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384

385
386
387

388
389
390
391

392
393
394
395
396
397
398
399
400
401
      goto trigger_cleanup;
    }
    if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
      sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
         "table: " MASTER_NAME, 0);
      pParse->nErr++;
      goto trigger_cleanup;






    }
    if( tab->pSelect && tr_tm != TK_INSTEAD ){
      sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
	  (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
          , pTableName->z, pTableName->n, 0);
      goto trigger_cleanup;
    }
................................................................................
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = pWhen;
  nt->pColumns = pColumns;
  nt->foreach = foreach;
  nt->step_list = pStepList;
  nt->isCommit = 0;
  offset = (int)(nt->strings - zData);
  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while( ss ){
    sqliteSelectMoveStrings(ss->pSelect, offset);
    if( ss->target.z ){
................................................................................

    ss = ss->pNext;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !pParse->initFlag && !tab->isTemp ){
    static VdbeOp insertTrig[] = {
      { OP_OpenWrite,  0, 2,  MASTER_NAME},
      { OP_NewRecno,   0, 0,  0          },
      { OP_String,     0, 0,  "trigger"  },
      { OP_String,     0, 0,  0          },  /* 3: trigger name */
      { OP_String,     0, 0,  0          },  /* 4: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String,     0, 0,  0          },  /* 6: SQL */
      { OP_MakeRecord, 5, 0,  0          },
      { OP_PutIntKey,  0, 0,  0          },
      { OP_Integer,    0, 0,  0          },  /* 9: Next cookie */
      { OP_SetCookie,  0, 0,  0          },
      { OP_Close,      0, 0,  0          },
    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto trigger_cleanup;
    sqliteBeginWriteOperation(pParse, 0);

    addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);


    sqliteVdbeChangeP3(v, addr+3, nt->name, 0); 
    sqliteVdbeChangeP3(v, addr+4, nt->table, 0); 
    sqliteVdbeChangeP3(v, addr+6, nt->strings, 0);

    sqliteChangeCookie(pParse->db);
    sqliteVdbeChangeP1(v, addr+9, pParse->db->next_cookie);


    sqliteEndWriteOperation(pParse);
  }

  if( !pParse->explain ){
    /* Stick it in the hash-table */
    sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);

................................................................................
 * sqliteDropTable(). In the latter case the "nested" argument is true.
 *
 * Note that this function does not delete the trigger entirely. Instead it
 * removes it from the internal schema and places it in the trigDrop hash 
 * table. This is so that the trigger can be restored into the database schema
 * if the transaction is rolled back.
 */
void sqliteDropTrigger(Parse *pParse, Token *pName, int nested)
{
  char *zName;
  Trigger *pTrigger;
  Table   *pTable;


  zName = sqliteStrNDup(pName->z, pName->n);

  /* ensure that the trigger being dropped exists */
  pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1); 
  if( !pTrigger ){
    sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
        zName, -1, 0);
    sqliteFree(zName);
    return;
  }

  /*
   * If this is not an "explain", do the following:
   * 1. Remove the trigger from its associated table structure
   * 2. Move the trigger from the trigHash hash to trigDrop
   */
  if( !pParse->explain ){
    /* 1 */
    pTable = sqliteFindTable(pParse->db, pTrigger->table);
    assert(pTable);
    if( pTable->pTrigger == pTrigger ){
      pTable->pTrigger = pTrigger->pNext;
    }else{
      Trigger *cc = pTable->pTrigger;
      while( cc ){ 
................................................................................
          cc->pNext = cc->pNext->pNext;
          break;
        }
        cc = cc->pNext;
      }
      assert(cc);
    }

    /* 2 */
    sqliteHashInsert(&(pParse->db->trigHash), zName, 
        pName->n + 1, NULL);
    sqliteHashInsert(&(pParse->db->trigDrop), pTrigger->name, 
        pName->n + 1, pTrigger);
  }

  /* Unless this is a trigger on a TEMP TABLE, generate code to destroy the
   * database record of the trigger */
  if( !pTable->isTemp ){


    int base;
    static VdbeOp dropTrigger[] = {
      { OP_OpenWrite,  0, 2,        MASTER_NAME},
      { OP_Rewind,     0, ADDR(9),  0},
      { OP_String,     0, 0,        0}, /* 2 */
      { OP_MemStore,   1, 1,        0},
      { OP_MemLoad,    1, 0,        0}, /* 4 */
      { OP_Column,     0, 1,        0},
      { OP_Ne,         0, ADDR(8),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(4),  0}, /* 8 */
      { OP_Integer,    0, 0,        0}, /* 9 */
      { OP_SetCookie,  0, 0,        0},
      { OP_Close,      0, 0,        0},
    };

    if( !nested ){
      sqliteBeginWriteOperation(pParse, 0);
    }
    base = sqliteVdbeAddOpList(pParse->pVdbe, 

        ArraySize(dropTrigger), dropTrigger);
    sqliteVdbeChangeP3(pParse->pVdbe, base+2, zName, 0);
    if( !nested ){

      sqliteChangeCookie(pParse->db);
    }
    sqliteVdbeChangeP1(pParse->pVdbe, base+9, pParse->db->next_cookie);
    if( !nested ){

      sqliteEndWriteOperation(pParse);
    }
  }

  sqliteFree(zName);
}

/*
** pEList is the SET clause of an UPDATE statement.  Each entry
** in pEList is of the format <id>=<expr>.  If any of the entries







>
>
>
>
>
>







 







<







 







|

<


|
|

|


<
<
<








>

>
>
|
|
|
>
|
<
>
>







 







|
<



>













|
<
<


<







 







<
<
|
<
<
|


<
|
<
>
>


<
|
|

|

|

|
<
<
<


<
|
<
<
>
|
|
<
>
|

<
<
>
|
|
<







65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
...
102
103
104
105
106
107
108

109
110
111
112
113
114
115
...
120
121
122
123
124
125
126
127
128

129
130
131
132
133
134
135
136



137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162
...
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
346
347
348
...
350
351
352
353
354
355
356


357


358
359
360

361

362
363
364
365

366
367
368
369
370
371
372
373



374
375

376


377
378
379

380
381
382


383
384
385

386
387
388
389
390
391
392
      goto trigger_cleanup;
    }
    if( sqliteStrICmp(tab->zName, MASTER_NAME)==0 ){
      sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
         "table: " MASTER_NAME, 0);
      pParse->nErr++;
      goto trigger_cleanup;
    }
    if( sqliteStrICmp(tab->zName, TEMP_MASTER_NAME)==0 ){
      sqliteSetString(&pParse->zErrMsg, "cannot create trigger on system "
         "table: " TEMP_MASTER_NAME, 0);
      pParse->nErr++;
      goto trigger_cleanup;
    }
    if( tab->pSelect && tr_tm != TK_INSTEAD ){
      sqliteSetNString(&pParse->zErrMsg, "cannot create ", -1,
	  (tr_tm == TK_BEFORE)?"BEFORE":"AFTER", -1, " trigger on view: ", -1
          , pTableName->z, pTableName->n, 0);
      goto trigger_cleanup;
    }
................................................................................
  if( sqlite_malloc_failed ) goto trigger_cleanup;
  nt->op = op;
  nt->tr_tm = tr_tm;
  nt->pWhen = pWhen;
  nt->pColumns = pColumns;
  nt->foreach = foreach;
  nt->step_list = pStepList;

  offset = (int)(nt->strings - zData);
  sqliteExprMoveStrings(nt->pWhen, offset);

  ss = nt->step_list;
  while( ss ){
    sqliteSelectMoveStrings(ss->pSelect, offset);
    if( ss->target.z ){
................................................................................

    ss = ss->pNext;
  }

  /* if we are not initializing, and this trigger is not on a TEMP table, 
  ** build the sqlite_master entry
  */
  if( !pParse->initFlag ){
    static VdbeOp insertTrig[] = {

      { OP_NewRecno,   0, 0,  0          },
      { OP_String,     0, 0,  "trigger"  },
      { OP_String,     0, 0,  0          },  /* 2: trigger name */
      { OP_String,     0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String,     0, 0,  0          },  /* 5: SQL */
      { OP_MakeRecord, 5, 0,  0          },
      { OP_PutIntKey,  0, 0,  0          },



    };
    int addr;
    Vdbe *v;

    /* Make an entry in the sqlite_master table */
    v = sqliteGetVdbe(pParse);
    if( v==0 ) goto trigger_cleanup;
    sqliteBeginWriteOperation(pParse, 0);
    sqliteOpenMasterTable(v, tab->isTemp);
    addr = sqliteVdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqliteVdbeChangeP3(v, addr, tab->isTemp ? TEMP_MASTER_NAME : MASTER_NAME,
                       P3_STATIC);
    sqliteVdbeChangeP3(v, addr+2, nt->name, 0); 
    sqliteVdbeChangeP3(v, addr+3, nt->table, 0); 
    sqliteVdbeChangeP3(v, addr+5, nt->strings, 0);
    if( !tab->isTemp ){
      sqliteChangeCookie(pParse->db, v);

    }
    sqliteVdbeAddOp(v, OP_Close, 0, 0);
    sqliteEndWriteOperation(pParse);
  }

  if( !pParse->explain ){
    /* Stick it in the hash-table */
    sqliteHashInsert(&(pParse->db->trigHash), nt->name, pName->n + 1, nt);

................................................................................
 * sqliteDropTable(). In the latter case the "nested" argument is true.
 *
 * Note that this function does not delete the trigger entirely. Instead it
 * removes it from the internal schema and places it in the trigDrop hash 
 * table. This is so that the trigger can be restored into the database schema
 * if the transaction is rolled back.
 */
void sqliteDropTrigger(Parse *pParse, Token *pName, int nested){

  char *zName;
  Trigger *pTrigger;
  Table   *pTable;
  Vdbe *v;

  zName = sqliteStrNDup(pName->z, pName->n);

  /* ensure that the trigger being dropped exists */
  pTrigger = sqliteHashFind(&(pParse->db->trigHash), zName, pName->n + 1); 
  if( !pTrigger ){
    sqliteSetNString(&pParse->zErrMsg, "no such trigger: ", -1,
        zName, -1, 0);
    sqliteFree(zName);
    return;
  }

  /*
   * If this is not an "explain", then delete the trigger structure.


   */
  if( !pParse->explain ){

    pTable = sqliteFindTable(pParse->db, pTrigger->table);
    assert(pTable);
    if( pTable->pTrigger == pTrigger ){
      pTable->pTrigger = pTrigger->pNext;
    }else{
      Trigger *cc = pTable->pTrigger;
      while( cc ){ 
................................................................................
          cc->pNext = cc->pNext->pNext;
          break;
        }
        cc = cc->pNext;
      }
      assert(cc);
    }


    sqliteHashInsert(&(pParse->db->trigHash), zName, pName->n + 1, NULL);


    sqliteDeleteTrigger(pTrigger);
  }


  /* Generate code to destroy the database record of the trigger.

  */
  if( pTable!=0 && !nested && (v = sqliteGetVdbe(pParse))!=0 ){
    int base;
    static VdbeOp dropTrigger[] = {

      { OP_Rewind,     0, ADDR(8),  0},
      { OP_String,     0, 0,        0}, /* 1 */
      { OP_MemStore,   1, 1,        0},
      { OP_MemLoad,    1, 0,        0}, /* 3 */
      { OP_Column,     0, 1,        0},
      { OP_Ne,         0, ADDR(7),  0},
      { OP_Delete,     0, 0,        0},
      { OP_Next,       0, ADDR(3),  0}, /* 7 */



    };


    sqliteBeginWriteOperation(pParse, 0);


    sqliteOpenMasterTable(v, pTable->isTemp);
    base = sqliteVdbeAddOpList(v,  ArraySize(dropTrigger), dropTrigger);
    sqliteVdbeChangeP3(v, base+1, zName, 0);

    if( !pTable->isTemp ){
      sqliteChangeCookie(pParse->db, v);
    }


    sqliteVdbeAddOp(v, OP_Close, 0, 0);
    sqliteEndWriteOperation(pParse);
  }


  sqliteFree(zName);
}

/*
** pEList is the SET clause of an UPDATE statement.  Each entry
** in pEList is of the format <id>=<expr>.  If any of the entries

Changes to src/vdbe.c.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
....
3043
3044
3045
3046
3047
3048
3049

3050
3051
3052
3053
3054
3055
3056
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.158 2002/06/21 23:01:50 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  Btree *pX;
  switch( pOp->opcode ){
    case OP_Open:        wrFlag = 0;  pX = pBt;          break;
    case OP_OpenWrite:   wrFlag = 1;  pX = pBt;          break;
    case OP_OpenAux:     wrFlag = 0;  pX = db->pBeTemp;  break;
    case OP_OpenWrAux:   wrFlag = 1;  pX = db->pBeTemp;  break;
  }
  assert( pX!=0 );
  if( p2<=0 ){
    if( tos<0 ) goto not_enough_stack;
    Integerify(p, tos);
    p2 = p->aStack[tos].i;
    POPSTACK;
    if( p2<2 ){
      sqliteSetString(pzErrMsg, "root page number less than 2", 0);
................................................................................
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  cleanupCursor(&p->aCsr[i]);
  memset(&p->aCsr[i], 0, sizeof(Cursor));
  p->aCsr[i].nullRow = 1;

  do{
    rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
          busy = 0;







|







 







<







 







>







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
....
3017
3018
3019
3020
3021
3022
3023

3024
3025
3026
3027
3028
3029
3030
....
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.159 2002/06/25 01:09:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
................................................................................
  Btree *pX;
  switch( pOp->opcode ){
    case OP_Open:        wrFlag = 0;  pX = pBt;          break;
    case OP_OpenWrite:   wrFlag = 1;  pX = pBt;          break;
    case OP_OpenAux:     wrFlag = 0;  pX = db->pBeTemp;  break;
    case OP_OpenWrAux:   wrFlag = 1;  pX = db->pBeTemp;  break;
  }

  if( p2<=0 ){
    if( tos<0 ) goto not_enough_stack;
    Integerify(p, tos);
    p2 = p->aStack[tos].i;
    POPSTACK;
    if( p2<2 ){
      sqliteSetString(pzErrMsg, "root page number less than 2", 0);
................................................................................
      memset(&p->aCsr[j], 0, sizeof(Cursor));
    }
    p->nCursor = i+1;
  }
  cleanupCursor(&p->aCsr[i]);
  memset(&p->aCsr[i], 0, sizeof(Cursor));
  p->aCsr[i].nullRow = 1;
  if( pX==0 ) break;
  do{
    rc = sqliteBtreeCursor(pX, p2, wrFlag, &p->aCsr[i].pCursor);
    switch( rc ){
      case SQLITE_BUSY: {
        if( xBusy==0 || (*xBusy)(pBusyArg, pOp->p3, ++busy)==0 ){
          sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
          busy = 0;

Changes to src/where.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.55 2002/06/24 22:01:59 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int eqMask = 0;  /* Index columns covered by an x=... term */
      int ltMask = 0;  /* Index columns covered by an x<... term */
      int gtMask = 0;  /* Index columns covered by an x>... term */
      int inMask = 0;  /* Index columns covered by an x IN .. term */
      int nEq, m, score;

      if( pIdx->isDropped ) continue;   /* Ignore dropped indices */
      if( pIdx->nColumn>32 ) continue;  /* Ignore indices too many columns */
      for(j=0; j<nExpr; j++){
        if( aExpr[j].idxLeft==idx 
             && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
          int iColumn = aExpr[j].p->pLeft->iColumn;
          int k;
          for(k=0; k<pIdx->nColumn; k++){







|







 







<







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
475
476
477
478
479
480
481

482
483
484
485
486
487
488
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  Also found here are subroutines
** to generate VDBE code to evaluate expressions.
**
** $Id: where.c,v 1.56 2002/06/25 01:09:12 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
    for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
      int eqMask = 0;  /* Index columns covered by an x=... term */
      int ltMask = 0;  /* Index columns covered by an x<... term */
      int gtMask = 0;  /* Index columns covered by an x>... term */
      int inMask = 0;  /* Index columns covered by an x IN .. term */
      int nEq, m, score;


      if( pIdx->nColumn>32 ) continue;  /* Ignore indices too many columns */
      for(j=0; j<nExpr; j++){
        if( aExpr[j].idxLeft==idx 
             && (aExpr[j].prereqRight & loopMask)==aExpr[j].prereqRight ){
          int iColumn = aExpr[j].p->pLeft->iColumn;
          int k;
          for(k=0; k<pIdx->nColumn; k++){

Changes to test/temptable.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for temporary tables and indices.
#
# $Id: temptable.test,v 1.6 2002/06/06 23:16:06 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#
do_test temptable-1.0 {
................................................................................
  execsql {COMMIT}
  catchsql {SELECT * FROM t2}
} {0 {1 2}}
do_test temptable-2.5 {
  set r [catch {db2 eval {SELECT * FROM t2}} msg]
  lappend r $msg
} {1 {no such table: t2}}


# Make sure indices on temporary tables are also temporary.
#
do_test temptable-3.1 {
  execsql {
    CREATE INDEX i2 ON t2(x);
    SELECT name FROM sqlite_master WHERE type='index';







|







 







<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
110
111
112
113
114
115
116

117
118
119
120
121
122
123
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for temporary tables and indices.
#
# $Id: temptable.test,v 1.7 2002/06/25 01:09:12 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# Create an alternative connection to the database
#
do_test temptable-1.0 {
................................................................................
  execsql {COMMIT}
  catchsql {SELECT * FROM t2}
} {0 {1 2}}
do_test temptable-2.5 {
  set r [catch {db2 eval {SELECT * FROM t2}} msg]
  lappend r $msg
} {1 {no such table: t2}}


# Make sure indices on temporary tables are also temporary.
#
do_test temptable-3.1 {
  execsql {
    CREATE INDEX i2 ON t2(x);
    SELECT name FROM sqlite_master WHERE type='index';

Changes to test/trigger3.test.

156
157
158
159
160
161
162
163
    }
} {1 {View abort}}

catchsql { DROP TABLE tbl; } 
catchsql { DROP TABLE tbl2; } 
catchsql { DROP VIEW tbl_view; } 









|
156
157
158
159
160
161
162
163
    }
} {1 {View abort}}

catchsql { DROP TABLE tbl; } 
catchsql { DROP TABLE tbl2; } 
catchsql { DROP VIEW tbl_view; }

finish_test

Changes to www/changes.tcl.

20
21
22
23
24
25
26













27
28
29
30
31
32
33
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}














chng {2002 Jun 19 (2.5.1)} {
<li>The query optimizer now attempts to implement the ORDER BY clause
    using an index.  Sorting is still used if not suitable index is
    available.</li>
}








>
>
>
>
>
>
>
>
>
>
>
>
>







20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
}


proc chng {date desc} {
  puts "<DT><B>$date</B></DT>"
  puts "<DD><P><UL>$desc</UL></P></DD>"
}

chng {2002 Jun 24 (2.5.2)} {
<li>Added the new <b>SQLITE_TEMP_MASTER</b> table which records the schema
    for temporary tables in the same way that <b>SQLITE_MASTER</b> does for
    persistent tables.</li>
<li>Added an optimization to UNION ALL</li>
<li>Fixed a bug in the processing of LEFT OUTER JOIN</li>
<li>The LIMIT clause now works on subselects</li>
<li>ORDER BY works on subselects</li>
<li>There is a new TypeOf() function used to determine if an expression
    is numeric or text.</li>
<li>Autoincrement now works for INSERT from a SELECT.</li>
}

chng {2002 Jun 19 (2.5.1)} {
<li>The query optimizer now attempts to implement the ORDER BY clause
    using an index.  Sorting is still used if not suitable index is
    available.</li>
}

Changes to www/faq.tcl.

1
2
3
4
5
6
7
8
9
10
11
...
272
273
274
275
276
277
278
279
280











281
282
283
284
285
286
287
#
# Run this script to generated a faq.html output file
#
set rcsid {$Id: faq.tcl,v 1.10 2002/04/25 00:21:50 drh Exp $}

puts {<html>
<head>
  <title>SQLite Frequently Asked Questions</title>
</head>
<body bgcolor="white">
<h1 align="center">Frequently Asked Questions</h1>
................................................................................
  to implement the PRIMARY KEY or UNIQUE constraints) the <b>sql</b> field
  is NULL.</p>

  <p>The SQLITE_MASTER table is read-only.  You cannot change this table
  using UPDATE, INSERT, or DELETE.  The table is automatically updated by
  CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands.</p>

  <p>Temporary tables do not appear in the SQLITE_MASTER table.  At this time
  there is no way to get a listing of temporary tables and indices.</p>











}

faq {
  Are there any known size limits to SQLite databases?
} {
  <p>Internally, SQLite can handle databases up to 2^40 bytes (1 terabyte)
  in size.  But the backend interface to POSIX and Win32 limits files to



|







 







|
|
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
...
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#
# Run this script to generated a faq.html output file
#
set rcsid {$Id: faq.tcl,v 1.11 2002/06/25 01:09:13 drh Exp $}

puts {<html>
<head>
  <title>SQLite Frequently Asked Questions</title>
</head>
<body bgcolor="white">
<h1 align="center">Frequently Asked Questions</h1>
................................................................................
  to implement the PRIMARY KEY or UNIQUE constraints) the <b>sql</b> field
  is NULL.</p>

  <p>The SQLITE_MASTER table is read-only.  You cannot change this table
  using UPDATE, INSERT, or DELETE.  The table is automatically updated by
  CREATE TABLE, CREATE INDEX, DROP TABLE, and DROP INDEX commands.</p>

  <p>Temporary tables do not appear in the SQLITE_MASTER table.  Temporary
  tables and their indices and triggers occur in another special table
  named SQLITE_TEMP_MASTER.  SQLITE_TEMP_MASTER works just like SQLITE_MASTER
  except that it is only visible to the application that created the 
  temporary tables.  To get a list of all tables, both permanent and
  temporary, one can use a command similar to the following:
</blockquote><pre>
SELECT name FROM 
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type='table'
ORDER BY name
</pre></blockquote>
}

faq {
  Are there any known size limits to SQLite databases?
} {
  <p>Internally, SQLite can handle databases up to 2^40 bytes (1 terabyte)
  in size.  But the backend interface to POSIX and Win32 limits files to

Changes to www/lang.tcl.

1
2
3
4
5
6
7
8
9
10
11
...
232
233
234
235
236
237
238


239
240
241
242
243
244
245
246
...
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
...
339
340
341
342
343
344
345


346
347
348
349
350
351
352
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.40 2002/06/12 22:33:54 drh Exp $}

puts {<html>
<head>
  <title>Query Language Understood By SQLite</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
conflict resolution algorithm, that algorithm is used in place of
the default algorithm specified here.
See the section titled
<a href="#conflict">ON CONFLICT</a> for additional information.</p>

<p>The exact text
of each CREATE INDEX statement is stored in the <b>sqlite_master</b>


table.  Everytime the database is opened, all CREATE INDEX statements
are read from the <b>sqlite_master</b> table and used to regenerate
SQLite's internal representation of the index layout.</p>
}


Section {CREATE TABLE} {createtable}

................................................................................
ON CONFLICT <conflict-algorithm>
}

puts {
<p>A CREATE TABLE statement is basically the keywords "CREATE TABLE"
followed by the name of a new table and a parenthesized list of column
definitions and constraints.  The table name can be either an identifier
or a string.  The only reserved table name is "<b>sqlite_master</b>" which
is the name of the table that records the database schema.</p>

<p>Each column definition is the name of the column followed by the
datatype for that column, then one or more optional column constraints.
The datatype for the column is (usually) ignored and may be omitted.
All information is stored as null-terminated strings.
The UNIQUE constraint causes an index to be created on the specified
columns.  This index must contain unique keys.
................................................................................
of each CREATE TABLE statement is stored in the <b>sqlite_master</b>
table.  Everytime the database is opened, all CREATE TABLE statements
are read from the <b>sqlite_master</b> table and used to regenerate
SQLite's internal representation of the table layout.
If the original command was a CREATE TABLE AS then then an equivalent
CREATE TABLE statement is synthesized and store in <b>sqlite_master</b>
in place of the original command.


</p>
}
Section {CREATE TRIGGER} createtrigger

Syntax {sql-statement} {
CREATE TRIGGER <trigger-name> [ BEFORE | AFTER ]
<database-event> ON <table-name>



|







 







>
>
|







 







|
|







 







>
>







1
2
3
4
5
6
7
8
9
10
11
...
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
...
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: lang.tcl,v 1.41 2002/06/25 01:09:13 drh Exp $}

puts {<html>
<head>
  <title>Query Language Understood By SQLite</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
conflict resolution algorithm, that algorithm is used in place of
the default algorithm specified here.
See the section titled
<a href="#conflict">ON CONFLICT</a> for additional information.</p>

<p>The exact text
of each CREATE INDEX statement is stored in the <b>sqlite_master</b>
or <b>sqlite_temp_master</b> table, depending on whether the table
being indexed is temporary.  Everytime the database is opened,
all CREATE INDEX statements
are read from the <b>sqlite_master</b> table and used to regenerate
SQLite's internal representation of the index layout.</p>
}


Section {CREATE TABLE} {createtable}

................................................................................
ON CONFLICT <conflict-algorithm>
}

puts {
<p>A CREATE TABLE statement is basically the keywords "CREATE TABLE"
followed by the name of a new table and a parenthesized list of column
definitions and constraints.  The table name can be either an identifier
or a string.  Tables names that begin with "<b>sqlite_</b>" are reserved
for use by the engine.</p>

<p>Each column definition is the name of the column followed by the
datatype for that column, then one or more optional column constraints.
The datatype for the column is (usually) ignored and may be omitted.
All information is stored as null-terminated strings.
The UNIQUE constraint causes an index to be created on the specified
columns.  This index must contain unique keys.
................................................................................
of each CREATE TABLE statement is stored in the <b>sqlite_master</b>
table.  Everytime the database is opened, all CREATE TABLE statements
are read from the <b>sqlite_master</b> table and used to regenerate
SQLite's internal representation of the table layout.
If the original command was a CREATE TABLE AS then then an equivalent
CREATE TABLE statement is synthesized and store in <b>sqlite_master</b>
in place of the original command.
The text of CREATE TEMPORARY TABLE statements are stored in the
<b>sqlite_temp_master</b> table.
</p>
}
Section {CREATE TRIGGER} createtrigger

Syntax {sql-statement} {
CREATE TRIGGER <trigger-name> [ BEFORE | AFTER ]
<database-event> ON <table-name>

Changes to www/sqlite.tcl.

1
2
3
4
5
6
7
8
9
10
11
...
113
114
115
116
117
118
119








120
121
122
123
124
125
126
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
...
372
373
374
375
376
377
378
379


380
381
382
383
384
385
386
387
388


389
390
391
392
393
394
395
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: sqlite.tcl,v 1.16 2001/11/24 13:23:05 drh Exp $}

puts {<html>
<head>
  <title>sqlite: A program of interacting with SQLite databases</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
But you cannot execute DROP TABLE, UPDATE, INSERT or DELETE against
the sqlite_master table.  The sqlite_master
table is updated automatically as you create or drop tables and
indices from the database.  You can not make manual changes
to the sqlite_master table.
</p>









<h2>Special commands to sqlite</h2>

<p>
Most of the time, sqlite just reads lines of input and passes them
on to the SQLite library for execution.
But if an input line begins with a dot ("."), then
that line is intercepted and interpreted by the sqlite program itself.
................................................................................
}

puts {
<p>The ".tables" command is the same as setting list mode then
executing the following query:</p>

<blockquote><pre>
SELECT name FROM sqlite_master 
WHERE type='table' 
ORDER BY name;
</pre></blockquote>

<p>In fact, if you look at the source code to the sqlite program
(found in the source tree in the file src/shell.c) you'll find
exactly the above query.</p>

................................................................................
}

puts {
<p>The ".schema" command accomplishes the same thing as setting
list mode, then entering the following query:</p>

<blockquote><pre>
SELECT sql FROM sqlite_master


WHERE type!='meta'
ORDER BY tbl_name, type DESC, name
</pre></blockquote>

<p>Or, if you give an argument to ".schema" because you only
want the schema for a single table, the query looks like this:</p>

<blockquote><pre>
SELECT sql FROM sqlite_master


WHERE tbl_name LIKE '%s' AND type!='meta'
ORDER BY type DESC, name
</pre></blockquote>

<p>The <b>%s</b> in the query above is replaced by the argument
to ".schema", of course.  Notice that the argument to the ".schema"
command appears to the right of an SQL LIKE operator.  So you can



|







 







>
>
>
>
>
>
>
>







 







|
|







 







|
>
>








|
>
>







1
2
3
4
5
6
7
8
9
10
11
...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
...
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
...
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
#
# Run this Tcl script to generate the sqlite.html file.
#
set rcsid {$Id: sqlite.tcl,v 1.17 2002/06/25 01:09:13 drh Exp $}

puts {<html>
<head>
  <title>sqlite: A program of interacting with SQLite databases</title>
</head>
<body bgcolor=white>
<h1 align=center>
................................................................................
But you cannot execute DROP TABLE, UPDATE, INSERT or DELETE against
the sqlite_master table.  The sqlite_master
table is updated automatically as you create or drop tables and
indices from the database.  You can not make manual changes
to the sqlite_master table.
</p>

<p>
The schema for TEMPORARY tables is not stored in the "sqlite_master" table
since TEMPORARY tables are not visible to applications other than the
application that created the table.  The schema for TEMPORARY tables
is stored in another special table named "sqlite_temp_master".  The
"sqlite_temp_master" table is temporary itself.
</p>

<h2>Special commands to sqlite</h2>

<p>
Most of the time, sqlite just reads lines of input and passes them
on to the SQLite library for execution.
But if an input line begins with a dot ("."), then
that line is intercepted and interpreted by the sqlite program itself.
................................................................................
}

puts {
<p>The ".tables" command is the same as setting list mode then
executing the following query:</p>

<blockquote><pre>
SELECT name FROM sqlite_master WHERE type='table' 
UNION ALL SELECT name FROM sqlite_temp_master WHERE type='table'
ORDER BY name;
</pre></blockquote>

<p>In fact, if you look at the source code to the sqlite program
(found in the source tree in the file src/shell.c) you'll find
exactly the above query.</p>

................................................................................
}

puts {
<p>The ".schema" command accomplishes the same thing as setting
list mode, then entering the following query:</p>

<blockquote><pre>
SELECT sql FROM 
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE type!='meta'
ORDER BY tbl_name, type DESC, name
</pre></blockquote>

<p>Or, if you give an argument to ".schema" because you only
want the schema for a single table, the query looks like this:</p>

<blockquote><pre>
SELECT sql FROM
   (SELECT * FROM sqlite_master UNION ALL
    SELECT * FROM sqlite_temp_master)
WHERE tbl_name LIKE '%s' AND type!='meta'
ORDER BY type DESC, name
</pre></blockquote>

<p>The <b>%s</b> in the query above is replaced by the argument
to ".schema", of course.  Notice that the argument to the ".schema"
command appears to the right of an SQL LIKE operator.  So you can