/ Check-in [c7c5e927]
Login

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

Overview
Comment:The ATTACH and DETACH statements are now coded but are still mostly untested. (CVS 890)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c7c5e927a54f0fbc2ca625754787aff4d9c4eff1
User & Date: drh 2003-03-31 00:30:48
Context
2003-03-31
02:12
Add the sqliteErrorMsg() function and use it to generate error message text during parsing and code generation. This simplifies the code somewhat and makes it easier to handle names with a database prefix. (CVS 891) check-in: 1d3fc977 user: drh tags: trunk
00:30
The ATTACH and DETACH statements are now coded but are still mostly untested. (CVS 890) check-in: c7c5e927 user: drh tags: trunk
2003-03-30
19:17
Remove the experimental sqlite_open_aux_file() API. It will soon be replaced by ATTACH and DETACH SQL commands. (CVS 1732) check-in: 0a358844 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
182
183
184
185
186
187
188




189
190
191
192
193
194
195


196
197
198
199
200
201
202
203
...
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
...
362
363
364
365
366
367
368

369
370
371
372
373
374
375
...
426
427
428
429
430
431
432

433
434
435
436
437
438
439
440
...
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
....
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
....
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
....
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
....
2637
2638
2639
2640
2641
2642
2643


































































































**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.136 2003/03/30 00:19:50 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
................................................................................
}

/*
** 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;
  int i;



  for(i=0; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    temp1 = pDb->tblHash;
    temp2 = pDb->trigHash;
    sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
    sqliteHashClear(&pDb->aFKey);
    sqliteHashClear(&pDb->idxHash);
    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
................................................................................
    sqliteHashClear(&temp2);
    sqliteHashInit(&pDb->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){
................................................................................
  int isView       /* True if this is a VIEW */
){
  Table *pTable;
  Index *pIdx;
  char *zName;
  sqlite *db = pParse->db;
  Vdbe *v;


  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  if( pParse->iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( (isTemp & 1)==isTemp );
................................................................................
  ** index or table name.  Issue an error message if it does.
  **
  ** If we are re-reading the sqlite_master table because of a schema
  ** change and a new permanent table is found whose name collides with
  ** an existing temporary table, that is not an error.
  */
  pTable = sqliteFindTable(db, zName, 0);

  if( pTable!=0 && (pTable->iDb==isTemp || !pParse->initFlag) ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
................................................................................
    return;
  }
  pTable->zName = zName;
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->iDb = isTemp ? 1 : pParse->iDb;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;

  /* Begin generating the code that will insert the table record into
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
................................................................................
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
      " may not be indexed", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( !isTemp && pTab->iDb>=2 ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
      " may not have non-temporary indices added", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0);
................................................................................
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->iDb==1 ){
    isTemp = 1;
  }


#if 0
  /* 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->iDb ){
    goto exit_create_index;
  }
#endif

  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
  ** Exception:  If we are reading the names of permanent indices from the
  ** sqlite_master table (because some other process changed the schema) and
  ** one of the index names collides with the name of a temporary table or
................................................................................
*/
void sqliteCodeVerifySchema(Parse *pParse){
  int i;
  sqlite *db = pParse->db;
  Vdbe *v = sqliteGetVdbe(pParse);
  for(i=0; i<db->nDb; i++){
    if( i==1 || db->aDb[i].pBt==0 ) continue;
    sqliteVdbeAddOp(v, OP_VerifyCookie, 0, db->aDb[i].schema_cookie);
  }
  pParse->schemaVerified = 1;
}

/*
** Generate VDBE code that prepares for doing an operation that
** might change the database.
................................................................................
    sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
  }else

  {}
  sqliteFree(zLeft);
  sqliteFree(zRight);
}









































































































|







 







>
>
>
>

|



|

>
>
|







 







>
>

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









|







 







>







 







>
|







 







|







 







|







 







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







 







|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
...
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
...
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
...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
...
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
...
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
....
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
....
1504
1505
1506
1507
1508
1509
1510














1511
1512
1513
1514
1515
1516
1517
....
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
....
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.137 2003/03/31 00:30:48 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
................................................................................
}

/*
** 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.
**
** If iDb<=0 then reset the internal schema tables for all database
** files.  If iDb>=2 then reset the internal schema for only the
** single file indicates.
*/
void sqliteResetInternalSchema(sqlite *db, int iDb){
  HashElem *pElem;
  Hash temp1;
  Hash temp2;
  int i, j;

  assert( iDb>=0 && iDb<db->nDb );
  db->flags &= ~SQLITE_Initialized;
  for(i=iDb; i<db->nDb; i++){
    Db *pDb = &db->aDb[i];
    temp1 = pDb->tblHash;
    temp2 = pDb->trigHash;
    sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0);
    sqliteHashClear(&pDb->aFKey);
    sqliteHashClear(&pDb->idxHash);
    for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){
................................................................................
    sqliteHashClear(&temp2);
    sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0);
    for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){
      Table *pTab = sqliteHashData(pElem);
      sqliteDeleteTable(db, pTab);
    }
    sqliteHashClear(&temp1);
    db->aDb[i].flags &= ~SQLITE_Initialized;
    if( iDb>0 ) return;
  }
  assert( iDb==0 );
  db->flags &= ~SQLITE_InternChanges;

  /* If one or more of the auxiliary database files has been closed,
  ** then remove then from the auxiliary database list.  We take the
  ** opportunity to do this here since we have just deleted all of the
  ** schema hash tables and therefore do not have to make any changes
  ** to any of those tables.
  */
  for(i=j=2; i<db->nDb; i++){
    if( db->aDb[i].pBt==0 ){
      sqliteFree(db->aDb[i].zName);
      db->aDb[i].zName = 0;
      continue;
    }
    if( j<i ){
      db->aDb[j++] = db->aDb[i];
    }
  }
  memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j]));
  db->nDb = j;
  if( db->nDb<=2 && db->aDb!=db->aDbStatic ){
    memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0]));
    sqliteFree(db->aDb);
    db->aDb = db->aDbStatic;
  }
}

/*
** 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, 0);
  }
}

/*
** This routine is called when a commit occurs.
*/
void sqliteCommitInternalChanges(sqlite *db){
................................................................................
  int isView       /* True if this is a VIEW */
){
  Table *pTable;
  Index *pIdx;
  char *zName;
  sqlite *db = pParse->db;
  Vdbe *v;
  int iDb;

  pParse->sFirstToken = *pStart;
  zName = sqliteTableNameFromToken(pName);
  if( zName==0 ) return;
  if( pParse->iDb==1 ) isTemp = 1;
#ifndef SQLITE_OMIT_AUTHORIZATION
  assert( (isTemp & 1)==isTemp );
................................................................................
  ** index or table name.  Issue an error message if it does.
  **
  ** If we are re-reading the sqlite_master table because of a schema
  ** change and a new permanent table is found whose name collides with
  ** an existing temporary table, that is not an error.
  */
  pTable = sqliteFindTable(db, zName, 0);
  iDb = isTemp ? 1 : pParse->iDb;
  if( pTable!=0 && (pTable->iDb==iDb || !pParse->initFlag) ){
    sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n,
        " already exists", 0, 0);
    sqliteFree(zName);
    pParse->nErr++;
    return;
  }
  if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 &&
................................................................................
    return;
  }
  pTable->zName = zName;
  pTable->nCol = 0;
  pTable->aCol = 0;
  pTable->iPKey = -1;
  pTable->pIndex = 0;
  pTable->iDb = iDb;
  if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable);
  pParse->pNewTable = pTable;

  /* Begin generating the code that will insert the table record into
  ** the SQLITE_MASTER table.  Note in particular that we must go ahead
  ** and allocate the record number for the table entry now.  Before any
  ** PRIMARY KEY or UNIQUE keywords are parsed.  Those keywords will cause
................................................................................
  if( pTab==0 || pParse->nErr ) goto exit_create_index;
  if( pTab->readOnly ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName,
      " may not be indexed", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( !isTemp && pTab->iDb>=2 && pParse->initFlag==0 ){
    sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, 
      " may not have non-temporary indices added", 0);
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->pSelect ){
    sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0);
................................................................................
    pParse->nErr++;
    goto exit_create_index;
  }
  if( pTab->iDb==1 ){
    isTemp = 1;
  }















  /*
  ** Find the name of the index.  Make sure there is not already another
  ** index or table with the same name.  
  **
  ** Exception:  If we are reading the names of permanent indices from the
  ** sqlite_master table (because some other process changed the schema) and
  ** one of the index names collides with the name of a temporary table or
................................................................................
*/
void sqliteCodeVerifySchema(Parse *pParse){
  int i;
  sqlite *db = pParse->db;
  Vdbe *v = sqliteGetVdbe(pParse);
  for(i=0; i<db->nDb; i++){
    if( i==1 || db->aDb[i].pBt==0 ) continue;
    sqliteVdbeAddOp(v, OP_VerifyCookie, i, db->aDb[i].schema_cookie);
  }
  pParse->schemaVerified = 1;
}

/*
** Generate VDBE code that prepares for doing an operation that
** might change the database.
................................................................................
    sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
  }else

  {}
  sqliteFree(zLeft);
  sqliteFree(zRight);
}

/*
** This routine is called by the parser to process an ATTACH statement:
**
**     ATTACH DATABASE filename AS dbname
**
** The pFilename and pDbname arguments are the tokens that define the
** filename and dbname in the ATTACH statement.
*/
void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){
  Db *aNew;
  int rc, i;
  char *zFile, *zName;
  sqlite *db;

  if( pParse->explain ) return;
  db = pParse->db;
  if( db->aDb==db->aDbStatic ){
    aNew = sqliteMalloc( sizeof(db->aDb[0])*3 );
    if( aNew==0 ) return;
    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);
  }else{
    aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) );
    if( aNew==0 ) return;
  }
  db->aDb = aNew;
  aNew = &db->aDb[db->nDb++];
  memset(aNew, 0, sizeof(*aNew));
  sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0);
  sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1);
  
  zName = 0;
  sqliteSetNString(&zName, pDbname->z, pDbname->n, 0);
  if( zName==0 ) return;
  sqliteDequote(zName);
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){
      sqliteSetString(&pParse->zErrMsg, "database \"", zName, 
         "\" already in use", 0);
      sqliteFree(zName);
      pParse->nErr++;
      return;
    }
  }
  aNew->zName = zName;
  zFile = 0;
  sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0);
  if( zFile==0 ) return;
  sqliteDequote(zFile);
  rc = sqliteBtreeOpen(zFile, 0, MAX_PAGES, &aNew->pBt);
  if( rc ){
    sqliteSetString(&pParse->zErrMsg, "unable to open database: ", zFile, 0);
    pParse->nErr++;
  }
  sqliteFree(zFile);
  db->flags &= ~SQLITE_Initialized;
  if( pParse->nErr ) return;
  rc = sqliteInit(pParse->db, &pParse->zErrMsg);
  if( rc ){
    pParse->nErr++;
  }
}

/*
** This routine is called by the parser to process a DETACH statement:
**
**    DETACH DATABASE dbname
**
** The pDbname argument is the name of the database in the DETACH statement.
*/
void sqliteDetach(Parse *pParse, Token *pDbname){
  int i;
  sqlite *db;

  if( pParse->explain ) return;
  db = pParse->db;
  for(i=0; i<db->nDb; i++){
    if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue;
    if( strlen(db->aDb[i].zName)!=pDbname->n ) continue;
    if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break;
  }
  if( i>=db->nDb ){
    sqliteSetNString(&pParse->zErrMsg, "no such database: ", -1,
        pDbname->z, pDbname->n, 0);
    pParse->nErr++;
    return;
  }
  if( i<2 ){
    sqliteSetString(&pParse->zErrMsg, "cannot detached \"main\" or \"temp\"",0);
    pParse->nErr++;
    return;
  }
  sqliteBtreeClose(db->aDb[i].pBt);
  db->aDb[i].pBt = 0;
  sqliteResetInternalSchema(db, 0);
}

Changes to src/main.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
36
37
38
39
40
41
42
43

44
45
46
47
48
49
50
...
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
...
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
...
472
473
474
475
476
477
478

479
480
481

482
483
484
485
486
487


488
489
490
491
492
493
494
...
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
**
*************************************************************************
** 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.118 2003/03/30 19:17:02 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
**
** 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 text for a CREATE TABLE or CREATE INDEX statement.
**     argv[4] = "1" for temporary files, "0" for main database

**
*/
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
  InitData *pData = (InitData*)pInit;
  Parse sParse;
  int nErr = 0;
................................................................................
  return rc!=SQLITE_OK;
}



/*
** Attempt to read the database schema and initialize internal



** data structures.  Return one of the SQLITE_ error codes to
** indicate success or failure.
**
** 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;
  InitData initData;

  /*
  ** The master database table has a structure like this
  */
................................................................................
     "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;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  sqliteInitCallback(&initData, 5, azArg, 0);
  pTab = sqliteFindTable(db, MASTER_NAME, "main");
  if( pTab ){
    pTab->readOnly = 1;
  }

  azArg[1] = TEMP_MASTER_NAME;
  azArg[3] = temp_master_schema;
  azArg[4] = "1";
  sqliteInitCallback(&initData, 5, azArg, 0);
  pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
  if( pTab ){
    pTab->readOnly = 1;

  }

  /* Create a cursor to hold the database open
  */
  if( db->aDb[0].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[0].pBt, 2, 0, &curMain);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
    sqliteResetInternalSchema(db);
    return rc;
  }

  /* Get the database meta information
  */
  rc = sqliteBtreeGetMeta(db->aDb[0].pBt, meta);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);
    sqliteResetInternalSchema(db);
    sqliteBtreeCloseCursor(curMain);
    return rc;
  }
  db->next_cookie = db->aDb[0].schema_cookie = meta[1];


  db->file_format = meta[2];
  size = meta[3];
  if( size==0 ){ size = MAX_PAGES; }
  db->cache_size = size;
  sqliteBtreeSetCacheSize(db->aDb[0].pBt, size);
  db->safety_level = meta[4];
  if( db->safety_level==0 ) db->safety_level = 2;
  sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level);

  /*
  **     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. Fix empty-string index bug.
  **     file_format==4    Version 2.7.0. Add support for separate numeric and
  **                       text datatypes.
  */
  if( db->file_format==0 ){
    /* This happens if the database was initially empty */
    db->file_format = 4;
  }else if( db->file_format>4 ){
    sqliteBtreeCloseCursor(curMain);
    sqliteSetString(pzErrMsg, "unsupported file format", 0);
    return SQLITE_ERROR;
  }










  /* Read the schema information out of the schema tables
  */
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.xCallback = sqliteInitCallback;
  sParse.pArg = (void*)&initData;
  sParse.initFlag = 1;
  sParse.useCallback = 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->aDb[0].pBt);
    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 rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
const char sqlite_version[] = SQLITE_VERSION;
................................................................................
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return;
  }
  db->magic = SQLITE_MAGIC_CLOSED;
  for(j=0; j<db->nDb; j++){
    if( db->aDb[j].pBt ){
      sqliteBtreeClose(db->aDb[j].pBt);

    }
    if( j>=2 ){
      sqliteFree(db->aDb[j].zName);

    }
  }
  if( db->aDb!=db->aDbStatic ){
    sqliteFree(db->aDb);
  }
  sqliteResetInternalSchema(db);


  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }
................................................................................
  if( db->xTrace ) db->xTrace(db->pTraceArg, zSql);
#endif
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
    sqliteRollbackAll(db);
    sqliteResetInternalSchema(db);
    db->flags &= ~SQLITE_InTrans;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
    sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0);
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    sqliteResetInternalSchema(db);
  }
  if( sParse.useCallback==0 ){
    assert( ppVm );
    *ppVm = (sqlite_vm*)sParse.pVdbe;
    *pzTail = sParse.zTail;
  }
  if( sqliteSafetyOff(db) ) goto exec_misuse;







|







 







|
>







 







>
>
>
|

<
<
<
<
<
<
<

<
>





>







 







>
>







>
|








>
|
|
|
|
|
|
|
>




|
|


<





|


<



|
>
>
|
|
|
|
<
|
|
<

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








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



<
|


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




<

<
|







 







>



>


<
<
<
|
>
>







 







|








|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
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
...
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
...
520
521
522
523
524
525
526
527
528
529
530
531
532
533



534
535
536
537
538
539
540
541
542
543
...
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
**
*************************************************************************
** 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.119 2003/03/31 00:30:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>

/*
** A pointer to this structure is used to communicate information
................................................................................
**
** 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 text for a CREATE TABLE or CREATE INDEX statement.
**     argv[4] = "1" for temporary files, "0" for main database, "2" or more
**               for auxiliary database files.
**
*/
static
int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){
  InitData *pData = (InitData*)pInit;
  Parse sParse;
  int nErr = 0;
................................................................................
  return rc!=SQLITE_OK;
}



/*
** Attempt to read the database schema and initialize internal
** data structures for a single database file.  The index of the
** database file is given by iDb.  iDb==0 is used for the main
** database.  iDb==1 should never be used.  iDb>=2 is used for
** auxiliary databases.  Return one of the SQLITE_ error codes to
** indicate success or failure.







*/

static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){
  int rc;
  BtCursor *curMain;
  int size;
  Table *pTab;
  char *azArg[6];
  char zDbNum[30];
  int meta[SQLITE_N_BTREE_META];
  Parse sParse;
  InitData initData;

  /*
  ** The master database table has a structure like this
  */
................................................................................
     "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'";


  assert( iDb>=0 && iDb!=1 && iDb<db->nDb );

  /* Construct the schema tables: sqlite_master and sqlite_temp_master
  */
  azArg[0] = "table";
  azArg[1] = MASTER_NAME;
  azArg[2] = "2";
  azArg[3] = master_schema;
  sprintf(zDbNum, "%d", iDb);
  azArg[4] = zDbNum;
  azArg[5] = 0;
  initData.db = db;
  initData.pzErrMsg = pzErrMsg;
  sqliteInitCallback(&initData, 5, azArg, 0);
  pTab = sqliteFindTable(db, MASTER_NAME, "main");
  if( pTab ){
    pTab->readOnly = 1;
  }
  if( iDb==0 ){
    azArg[1] = TEMP_MASTER_NAME;
    azArg[3] = temp_master_schema;
    azArg[4] = "1";
    sqliteInitCallback(&initData, 5, azArg, 0);
    pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp");
    if( pTab ){
      pTab->readOnly = 1;
    }
  }

  /* Create a cursor to hold the database open
  */
  if( db->aDb[iDb].pBt==0 ) return SQLITE_OK;
  rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);

    return rc;
  }

  /* Get the database meta information
  */
  rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);
  if( rc ){
    sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0);

    sqliteBtreeCloseCursor(curMain);
    return rc;
  }
  db->aDb[iDb].schema_cookie = meta[1];
  if( iDb==0 ){
    db->next_cookie = meta[1];
    db->file_format = meta[2];
    size = meta[3];
    if( size==0 ){ size = MAX_PAGES; }
    db->cache_size = size;

    db->safety_level = meta[4];
    if( db->safety_level==0 ) db->safety_level = 2;


    /*
    **  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. Fix empty-string index bug.
    **  file_format==4    Version 2.7.0. Add support for separate numeric and
    **                    text datatypes.
    */
    if( db->file_format==0 ){
      /* This happens if the database was initially empty */
      db->file_format = 4;
    }else if( db->file_format>4 ){
      sqliteBtreeCloseCursor(curMain);
      sqliteSetString(pzErrMsg, "unsupported file format", 0);
      return SQLITE_ERROR;
    }
  }else if( db->file_format<4 || db->file_format!=meta[2] ){
    sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "
       "database \"", db->aDb[iDb].zName, "\"", 0);
    sqliteBtreeClose(db->aDb[iDb].pBt);
    db->aDb[iDb].pBt = 0;
    return SQLITE_FORMAT;
  }
  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, size);
  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);

  /* Read the schema information out of the schema tables
  */
  memset(&sParse, 0, sizeof(sParse));
  sParse.db = db;
  sParse.xCallback = sqliteInitCallback;
  sParse.pArg = (void*)&initData;
  sParse.initFlag = 1;
  sParse.useCallback = 1;
  if( iDb==0 ){
    sqliteRunParser(&sParse,
        db->file_format>=2 ? init_script : older_init_script,
        pzErrMsg);
  }else{
    char *zSql = 0;
    sqliteSetString(&zSql, 
       "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",
       db->aDb[iDb].zName, "\".sqlite_master", 0);
    sqliteRunParser(&sParse, zSql, pzErrMsg);
    sqliteFree(zSql);
  }
  sqliteBtreeCloseCursor(curMain);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;

    sqliteResetInternalSchema(db, 0);
  }
  if( sParse.rc==SQLITE_OK ){
    db->aDb[iDb].flags |= SQLITE_Initialized;
  }else{
    sqliteResetInternalSchema(db, iDb);
  }
  return sParse.rc;
}

/*
** Initialize all database files - the main database file, the file
** used to store temporary tables, and any additional database files
** created using ATTACH statements.  Return a success code.  If an
** error occurs, write an error message into *pzErrMsg.
**
** 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 i, rc;
  
  assert( (db->flags & SQLITE_Initialized)==0 );
  rc = SQLITE_OK;
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
    if( db->aDb[i].flags & SQLITE_Initialized ) continue;
    if( i==1 ) continue;  /* Skip the temp database - initialized with 0 */
    rc = sqliteInitOne(db, i, pzErrMsg);
  }
  if( rc==SQLITE_OK ){
    db->flags |= SQLITE_Initialized;
    sqliteCommitInternalChanges(db);
  }else{
    db->flags &= ~SQLITE_Initialized;

  }

  return rc;
}

/*
** The version of the library
*/
const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $";
const char sqlite_version[] = SQLITE_VERSION;
................................................................................
    /* printf("DID NOT CLOSE\n"); fflush(stdout); */
    return;
  }
  db->magic = SQLITE_MAGIC_CLOSED;
  for(j=0; j<db->nDb; j++){
    if( db->aDb[j].pBt ){
      sqliteBtreeClose(db->aDb[j].pBt);
      db->aDb[j].pBt = 0;
    }
    if( j>=2 ){
      sqliteFree(db->aDb[j].zName);
      db->aDb[j].zName = 0;
    }
  }



  sqliteResetInternalSchema(db, 0);
  assert( db->nDb<=2 );
  assert( db->aDb==db->aDbStatic );
  for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){
    FuncDef *pFunc, *pNext;
    for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){
      pNext = pFunc->pNext;
      sqliteFree(pFunc);
    }
  }
................................................................................
  if( db->xTrace ) db->xTrace(db->pTraceArg, zSql);
#endif
  sqliteRunParser(&sParse, zSql, pzErrMsg);
  if( sqlite_malloc_failed ){
    sqliteSetString(pzErrMsg, "out of memory", 0);
    sParse.rc = SQLITE_NOMEM;
    sqliteRollbackAll(db);
    sqliteResetInternalSchema(db, 0);
    db->flags &= ~SQLITE_InTrans;
  }
  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
  if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
    sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0);
  }
  sqliteStrRealloc(pzErrMsg);
  if( sParse.rc==SQLITE_SCHEMA ){
    sqliteResetInternalSchema(db, 0);
  }
  if( sParse.useCallback==0 ){
    assert( ppVm );
    *ppVm = (sqlite_vm*)sParse.pVdbe;
    *pzTail = sParse.zTail;
  }
  if( sqliteSafetyOff(db) ) goto exec_misuse;

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
837
838
839
840
841
842
843
844
845
846
847
848


849
850
851
852
853
854


**
*************************************************************************
** 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.93 2003/03/27 12:51:25 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  A = sqliteExpr(TK_RAISE, 0, 0, &Z); 
  A->iColumn = OE_Fail;
  sqliteExprSpan(A, &X, &Y);
}

////////////////////////  DROP TRIGGER statement //////////////////////////////
cmd ::= DROP TRIGGER nm(X) dbnm(D). {
    sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0);
}

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids AS nm.



database_kw_opt ::= DATABASE.
database_kw_opt ::= .

//////////////////////// DETACH DATABASE name /////////////////////////////////
cmd ::= DETACH database_kw_opt nm.









|







 







|



|
>
>





|
>
>
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
**
*************************************************************************
** 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.94 2003/03/31 00:30:48 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
%default_type {Token}
%extra_argument {Parse *pParse}
%syntax_error {
  if( pParse->zErrMsg==0 ){
................................................................................
  A = sqliteExpr(TK_RAISE, 0, 0, &Z); 
  A->iColumn = OE_Fail;
  sqliteExprSpan(A, &X, &Y);
}

////////////////////////  DROP TRIGGER statement //////////////////////////////
cmd ::= DROP TRIGGER nm(X) dbnm(D). {
  sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0);
}

//////////////////////// ATTACH DATABASE file AS name /////////////////////////
cmd ::= ATTACH database_kw_opt ids(F) AS nm(D). {
  sqliteAttach(pParse, &F, &D);
}

database_kw_opt ::= DATABASE.
database_kw_opt ::= .

//////////////////////// DETACH DATABASE name /////////////////////////////////
cmd ::= DETACH database_kw_opt nm(D). {
  sqliteDetach(pParse, &D);
}

Changes to src/sqlite.h.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
161
162
163
164
165
166
167

168
169
170
171
172
173
174
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.42 2003/03/30 19:17:03 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */

#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

/*
** Each entry in an SQLite table has a unique integer key.  (The key is
** the value of the INTEGER PRIMARY KEY column if there is such a column,
** otherwise the key is generated at random.  The unique key is always







|







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.43 2003/03/31 00:30:49 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
................................................................................
#define SQLITE_SCHEMA      17   /* The database schema changed */
#define SQLITE_TOOBIG      18   /* Too much data for one row of a table */
#define SQLITE_CONSTRAINT  19   /* Abort due to contraint violation */
#define SQLITE_MISMATCH    20   /* Data type mismatch */
#define SQLITE_MISUSE      21   /* Library used incorrectly */
#define SQLITE_NOLFS       22   /* Uses OS features not supported on host */
#define SQLITE_AUTH        23   /* Authorization denied */
#define SQLITE_FORMAT      24   /* Auxiliary database format error */
#define SQLITE_ROW         100  /* sqlite_step() has another row ready */
#define SQLITE_DONE        101  /* sqlite_step() has finished executing */

/*
** Each entry in an SQLite table has a unique integer key.  (The key is
** the value of the INTEGER PRIMARY KEY column if there is such a column,
** otherwise the key is generated at random.  The unique key is always

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
967
968
969
970
971
972
973

974
975
976
977
978
979
980
981
982
983
....
1078
1079
1080
1081
1082
1083
1084


**    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.166 2003/03/27 13:50:00 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
void sqliteExec(Parse*);
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,int);
void sqliteAddColumn(Parse*,Token*);
................................................................................
#ifndef SQLITE_OMIT_AUTHORIZATION
  void sqliteAuthRead(Parse*,Expr*,SrcList*,int);
  int sqliteAuthCheck(Parse*,int, const char*, const char*);
#else
# define sqliteAuthRead(a,b,c,d)
# define sqliteAuthCheck(a,b,c,d)    SQLITE_OK
#endif









|







 







>

|
<







 







>
>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
967
968
969
970
971
972
973
974
975
976

977
978
979
980
981
982
983
....
1078
1079
1080
1081
1082
1083
1084
1085
1086
**    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.167 2003/03/31 00:30:49 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
#include "hash.h"
#include "vdbe.h"
#include "parse.h"
#include "btree.h"
................................................................................
void sqliteExec(Parse*);
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*);
int sqliteInit(sqlite*, char**);
void sqlitePragma(Parse*,Token*,Token*,int);
void sqliteResetInternalSchema(sqlite*, int);

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,int);
void sqliteAddColumn(Parse*,Token*);
................................................................................
#ifndef SQLITE_OMIT_AUTHORIZATION
  void sqliteAuthRead(Parse*,Expr*,SrcList*,int);
  int sqliteAuthCheck(Parse*,int, const char*, const char*);
#else
# define sqliteAuthRead(a,b,c,d)
# define sqliteAuthCheck(a,b,c,d)    SQLITE_OK
#endif
void sqliteAttach(Parse*, Token*, Token*);
void sqliteDetach(Parse*, Token*);