/ Check-in [b8e53608]
Login

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

Overview
Comment:Disable the feature on this branch in non-SQLITE_ENABLE_SHARED_SCHEMA builds.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | reuse-schema
Files: files | file ages | folders
SHA3-256:b8e536089b0e6dec500a28556f826c99b78d979615ba3bc01ed31ead1b2112df
User & Date: dan 2019-03-21 17:13:55
Wiki:reuse-schema
Context
2019-03-21
17:22
Merge latest trunk changes with this branch. check-in: 3196f5f4 user: dan tags: reuse-schema
17:13
Disable the feature on this branch in non-SQLITE_ENABLE_SHARED_SCHEMA builds. check-in: b8e53608 user: dan tags: reuse-schema
2019-03-20
20:02
Use the IsReuseSchema() macro more consistently. Also, rename it to IsSharedSchema(). check-in: c1be211c user: dan tags: reuse-schema
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

282
283
284
285
286
287
288

289
290
291
292
293
294
295
...
312
313
314
315
316
317
318

319
320
321
322
323
324
325
** list of users and their access credentials.
*/
int sqlite3UserAuthTable(const char *zTable){
  return sqlite3_stricmp(zTable, "sqlite_user")==0;
}
#endif


/*
** If this database connection was opened with the SQLITE_OPEN_SHARED_SCHEMA
** flag specified, then ensure that the database schema for database iDb
** is loaded. Either by obtaining a Schema object from the schema-pool, or
** by reading the contents of the sqlite_master table. Unless it is NULL, 
** the location indicated by parameter pbUnload is set to 1 if a shared-schema 
** is loaded.
................................................................................
    memset(&db->init, 0, sizeof(struct sqlite3InitInfo));
    rc = sqlite3InitOne(db, iDb, pzErr, 0);
    db->init = sv;
    if( pbUnload && rc==SQLITE_OK && iDb!=1 ) *pbUnload = 1;
  }
  return rc;
}


/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.
**
** If zDatabase is 0, all databases are searched for the table and the







>







 







>







282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
** list of users and their access credentials.
*/
int sqlite3UserAuthTable(const char *zTable){
  return sqlite3_stricmp(zTable, "sqlite_user")==0;
}
#endif

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** If this database connection was opened with the SQLITE_OPEN_SHARED_SCHEMA
** flag specified, then ensure that the database schema for database iDb
** is loaded. Either by obtaining a Schema object from the schema-pool, or
** by reading the contents of the sqlite_master table. Unless it is NULL, 
** the location indicated by parameter pbUnload is set to 1 if a shared-schema 
** is loaded.
................................................................................
    memset(&db->init, 0, sizeof(struct sqlite3InitInfo));
    rc = sqlite3InitOne(db, iDb, pzErr, 0);
    db->init = sv;
    if( pbUnload && rc==SQLITE_OK && iDb!=1 ) *pbUnload = 1;
  }
  return rc;
}
#endif

/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
** database containing the table.  Return NULL if not found.
**
** If zDatabase is 0, all databases are searched for the table and the

Changes to src/callback.c.

36
37
38
39
40
41
42

43
44
45
46
47
48
49
..
65
66
67
68
69
70
71

72
73
74
75
76
77
78
...
525
526
527
528
529
530
531

532
533
534


535
536
537
538

539
540
541
542
543
544
545
...
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
838
839
  int nDelete;                    /* Schema objects deleted by ReleaseAll() */
  u64 cksum;                      /* Checksum for this Schema contents */
  Schema *pSchema;                /* Linked list of Schema objects */
  Schema sSchema;                 /* The single dummy schema object */
  SchemaPool *pNext;              /* Next element in schemaPoolList */
};


#ifdef SQLITE_DEBUG
static void assert_schema_state_ok(sqlite3 *db){
  if( IsSharedSchema(db) && db->magic!=SQLITE_MAGIC_ZOMBIE ){
    int i;
    for(i=0; i<db->nDb; i++){
      if( i!=1 ){
        Db *pDb = &db->aDb[i];
................................................................................
      }
    }
  }
}
#else
# define assert_schema_state_ok(x)
#endif


/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the encoding enc of name zName, length nName.
*/
static void callCollNeeded(sqlite3 *db, int enc, const char *zName){
  assert( !db->xCollNeeded || !db->xCollNeeded16 );
................................................................................
** database iDb. 
**
** If an OOM error occurs while disconnecting from a schema-pool, 
** the db->mallocFailed flag is set.
*/
void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
  Db *pDb = &db->aDb[iDb];

  if( IsSharedSchema(db) && iDb!=1 && pDb->pSPool ){
    sqlite3SchemaDisconnect(db, iDb, 1);
  }else{


    sqlite3SchemaClear(pDb->pSchema);
  }
}


/*
** Global linked list of SchemaPool objects. Read and write access must
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
*/
static SchemaPool *SQLITE_WSD schemaPoolList = 0;

#ifdef SQLITE_TEST
................................................................................
  assert( iDb!=1 );
  assert_schema_state_ok(db);
  sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
  schemaRelease(db, pDb);
  sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}



/*
** In most cases, this function finds and returns the schema associated 
** with BTree handle pBt, creating a new one if necessary. However, if
** the database handle was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** specified, a new, empty, Schema object in memory obtained by 
** sqlite3_malloc() is always returned.
*/
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
  Schema *p;
  if( pBt && IsSharedSchema(db)==0 ){
    p = (Schema*)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
  }else{
    db->lookaside.bDisable++;
    p = (Schema*)sqlite3DbMallocZero(db, sizeof(Schema));
    db->lookaside.bDisable--;
  }
  if( !p ){
    sqlite3OomFault(db);
  }else if ( 0==p->file_format ){
    sqlite3HashInit(&p->tblHash);
    sqlite3HashInit(&p->idxHash);
    sqlite3HashInit(&p->trigHash);
    sqlite3HashInit(&p->fkeyHash);
    p->enc = SQLITE_UTF8;
  }
  return p;
}







>







 







>







 







>


|
>
>




>







 







>
>












<
|
<












36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
..
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
...
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
...
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
838
839
840
841
842
843
844
845
  int nDelete;                    /* Schema objects deleted by ReleaseAll() */
  u64 cksum;                      /* Checksum for this Schema contents */
  Schema *pSchema;                /* Linked list of Schema objects */
  Schema sSchema;                 /* The single dummy schema object */
  SchemaPool *pNext;              /* Next element in schemaPoolList */
};

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
#ifdef SQLITE_DEBUG
static void assert_schema_state_ok(sqlite3 *db){
  if( IsSharedSchema(db) && db->magic!=SQLITE_MAGIC_ZOMBIE ){
    int i;
    for(i=0; i<db->nDb; i++){
      if( i!=1 ){
        Db *pDb = &db->aDb[i];
................................................................................
      }
    }
  }
}
#else
# define assert_schema_state_ok(x)
#endif
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */

/*
** Invoke the 'collation needed' callback to request a collation sequence
** in the encoding enc of name zName, length nName.
*/
static void callCollNeeded(sqlite3 *db, int enc, const char *zName){
  assert( !db->xCollNeeded || !db->xCollNeeded16 );
................................................................................
** database iDb. 
**
** If an OOM error occurs while disconnecting from a schema-pool, 
** the db->mallocFailed flag is set.
*/
void sqlite3SchemaClearOrDisconnect(sqlite3 *db, int iDb){
  Db *pDb = &db->aDb[iDb];
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  if( IsSharedSchema(db) && iDb!=1 && pDb->pSPool ){
    sqlite3SchemaDisconnect(db, iDb, 1);
  }else
#endif
  {
    sqlite3SchemaClear(pDb->pSchema);
  }
}

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** Global linked list of SchemaPool objects. Read and write access must
** be protected by the SQLITE_MUTEX_STATIC_MASTER mutex.
*/
static SchemaPool *SQLITE_WSD schemaPoolList = 0;

#ifdef SQLITE_TEST
................................................................................
  assert( iDb!=1 );
  assert_schema_state_ok(db);
  sqlite3_mutex_enter( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
  schemaRelease(db, pDb);
  sqlite3_mutex_leave( sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER) );
}

#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */

/*
** In most cases, this function finds and returns the schema associated 
** with BTree handle pBt, creating a new one if necessary. However, if
** the database handle was opened with the SQLITE_OPEN_SHARED_SCHEMA flag
** specified, a new, empty, Schema object in memory obtained by 
** sqlite3_malloc() is always returned.
*/
Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){
  Schema *p;
  if( pBt && IsSharedSchema(db)==0 ){
    p = (Schema*)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaClear);
  }else{

    p = (Schema*)sqlite3DbMallocZero(0, sizeof(Schema));

  }
  if( !p ){
    sqlite3OomFault(db);
  }else if ( 0==p->file_format ){
    sqlite3HashInit(&p->tblHash);
    sqlite3HashInit(&p->idxHash);
    sqlite3HashInit(&p->trigHash);
    sqlite3HashInit(&p->fkeyHash);
    p->enc = SQLITE_UTF8;
  }
  return p;
}

Changes to src/main.c.

1050
1051
1052
1053
1054
1055
1056

1057
1058
1059
1060
1061
1062
1063
1064
1065

1066
1067
1068
1069
1070
1071
1072
....
3628
3629
3630
3631
3632
3633
3634

3635
3636
3637
3638

3639

3640
3641
3642

3643
3644
3645
3646
3647
3648
3649
    Schema *pSchema = db->aDb[i].pSchema;
    if( pSchema ){
      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
        Table *pTab = (Table *)sqliteHashData(p);
        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
      }
    }

    if( i!=1 && IsSharedSchema(db) ){
      VTable *pVTable;
      VTable *pNext;
      for(pVTable=db->aDb[i].pVTable; pVTable; pVTable=pNext){
        pNext = pVTable->pNext;
        sqlite3VtabUnlock(pVTable);
      }
      db->aDb[i].pVTable = 0;
    }

  }
  for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
    Module *pMod = (Module *)sqliteHashData(p);
    if( pMod->pEpoTab ){
      sqlite3VtabDisconnect(db, pMod->pEpoTab);
    }
  }
................................................................................
  sqlite3BtreeEnterAll(db);
  if( IsSharedSchema(db)==0 ){
    rc = sqlite3Init(db, &zErrMsg);
  }

  /* Locate the table in question */
  if( rc==SQLITE_OK ){

    Parse sParse;                   /* Fake Parse object for FindTable */
    Parse *pSaved = db->pParse;
    memset(&sParse, 0, sizeof(sParse));
    db->pParse = &sParse;

    pTab = sqlite3FindTable(db, zTableName, zDbName);

    sqlite3_free(sParse.zErrMsg);
    rc = sParse.rc;
    db->pParse = pSaved;

  }
  if( SQLITE_OK!=rc ) goto error_out;

  if( !pTab || pTab->pSelect ){
    pTab = 0;
    goto error_out;
  }







>
|








>







 







>




>

>



>







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
....
3630
3631
3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
    Schema *pSchema = db->aDb[i].pSchema;
    if( pSchema ){
      for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
        Table *pTab = (Table *)sqliteHashData(p);
        if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
      }
    }
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    if( IsSharedSchema(db) && i!=1 ){
      VTable *pVTable;
      VTable *pNext;
      for(pVTable=db->aDb[i].pVTable; pVTable; pVTable=pNext){
        pNext = pVTable->pNext;
        sqlite3VtabUnlock(pVTable);
      }
      db->aDb[i].pVTable = 0;
    }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
  }
  for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
    Module *pMod = (Module *)sqliteHashData(p);
    if( pMod->pEpoTab ){
      sqlite3VtabDisconnect(db, pMod->pEpoTab);
    }
  }
................................................................................
  sqlite3BtreeEnterAll(db);
  if( IsSharedSchema(db)==0 ){
    rc = sqlite3Init(db, &zErrMsg);
  }

  /* Locate the table in question */
  if( rc==SQLITE_OK ){
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    Parse sParse;                   /* Fake Parse object for FindTable */
    Parse *pSaved = db->pParse;
    memset(&sParse, 0, sizeof(sParse));
    db->pParse = &sParse;
#endif
    pTab = sqlite3FindTable(db, zTableName, zDbName);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    sqlite3_free(sParse.zErrMsg);
    rc = sParse.rc;
    db->pParse = pSaved;
#endif
  }
  if( SQLITE_OK!=rc ) goto error_out;

  if( !pTab || pTab->pSelect ){
    pTab = 0;
    goto error_out;
  }

Changes to src/prepare.c.

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
...
137
138
139
140
141
142
143

144
145

146
147
148
149
150
151
152
...
165
166
167
168
169
170
171

172
173
174

175
176
177
178
179
180
181
...
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
...
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
    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    *pData->pzErrMsg = z;
    pData->rc = SQLITE_CORRUPT_BKPT;
  }
}


/*
** Update the Schema.cksum checksum to account for the database object
** specified by the three arguments following the first.
*/
void schemaUpdateChecksum(
  InitData *pData,                /* Schema parse context */
  const char *zName,              /* Name of new database object */
  const char *zRoot,              /* Root page of new database object */
  const char *zSql                /* SQL used to create new database object */
){
  int i;
  u64 cksum = pData->cksum;
................................................................................
  if( zName ){
    for(i=0; zName[i]; i++) cksum += (cksum<<3) + zName[i];
  }
  if( zRoot ) for(i=0; zRoot[i]; i++) cksum += (cksum<<3) + zRoot[i];
  if( zSql ) for(i=0; zSql[i]; i++) cksum += (cksum<<3) + zSql[i];
  pData->cksum = cksum;
}


/*
** Check to see if any sibling index (another index on the same table)
** of pIndex has the same root page number, and if it does, return true.
** This would indicate a corrupt schema.
*/
int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
................................................................................
      if( db->init.orphanTrigger ){
        assert( iDb==1 );
      }else{
        pData->rc = rc;
        if( rc==SQLITE_NOMEM ){
          sqlite3OomFault(db);
        }else if( rc!=SQLITE_INTERRUPT 

               && (rc&0xFF)!=SQLITE_LOCKED 
               && (rc&0xFF)!=SQLITE_IOERR

        ){
          corruptSchema(pData, argv[0], sqlite3_errmsg(db));
        }
      }
    }
    sqlite3_finalize(pStmt);
  }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
................................................................................
     || pIndex->tnum<2
     || sqlite3IndexHasDuplicateRootPage(pIndex)
    ){
      corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
    }
  }


  if( iDb!=1 && IsSharedSchema(db) ){
    schemaUpdateChecksum(pData, argv[0], argv[1], argv[2]);
  }

  return 0;
}

/*
** 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
................................................................................
  assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema || (IsSharedSchema(db) && iDb!=1) );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );

  pDb = &db->aDb[iDb];

  assert( pDb->pSPool==0 || IsSharedSchema(db) );
  if( pDb->pSPool ){
    /* See if there is a free schema object in the schema-pool. If not,
    ** disconnect from said schema pool and continue. This function will
    ** connect to a (possibly different) schema-pool before returning. */
    Schema *pNew = sqlite3SchemaExtract(pDb->pSPool);
    if( pNew ){
................................................................................
      pDb->pSchema = pNew;
      return SQLITE_OK;
    }
    rc = sqlite3SchemaDisconnect(db, iDb, 1);
    if( rc!=SQLITE_OK ) goto error_out;
    assert( pDb->pSchema && pDb->pSPool==0 );
  }


  db->init.busy = 1;

  /* Construct the in-memory representation schema tables (sqlite_master or
  ** sqlite_temp_master) by invoking the parser directly.  The appropriate
  ** table name will be inserted automatically by the parser so we can just
  ** use the abbreviation "x" here.  The parser will also automatically tag
................................................................................
    }
    sqlite3ResetOneSchema(db, iDb);
  }
  db->init.busy = 0;
  return rc;
}







int sqlite3LockReusableSchema(sqlite3 *db){
  if( IsSharedSchema(db) && (db->mDbFlags & DBFLAG_SchemaInuse)==0 ){
    db->mDbFlags |= DBFLAG_SchemaInuse;
    return 1;
  }
  return 0;
}








void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease){
  if( bRelease ){
    db->mDbFlags &= ~DBFLAG_SchemaInuse;
    sqlite3SchemaReleaseAll(db);
  }
}


/*
** 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.
**







>




|







 







>







 







>


>







 







>
|


>







 







>







 







>







 







>
>
>
>
>
>







>
>
>
>
>
>
>
>






>







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
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
...
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
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
...
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
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
    z = sqlite3MPrintf(db, "malformed database schema (%s)", zObj);
    if( zExtra && zExtra[0] ) z = sqlite3MPrintf(db, "%z - %s", z, zExtra);
    *pData->pzErrMsg = z;
    pData->rc = SQLITE_CORRUPT_BKPT;
  }
}

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** Update the Schema.cksum checksum to account for the database object
** specified by the three arguments following the first.
*/
static void schemaUpdateChecksum(
  InitData *pData,                /* Schema parse context */
  const char *zName,              /* Name of new database object */
  const char *zRoot,              /* Root page of new database object */
  const char *zSql                /* SQL used to create new database object */
){
  int i;
  u64 cksum = pData->cksum;
................................................................................
  if( zName ){
    for(i=0; zName[i]; i++) cksum += (cksum<<3) + zName[i];
  }
  if( zRoot ) for(i=0; zRoot[i]; i++) cksum += (cksum<<3) + zRoot[i];
  if( zSql ) for(i=0; zSql[i]; i++) cksum += (cksum<<3) + zSql[i];
  pData->cksum = cksum;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */

/*
** Check to see if any sibling index (another index on the same table)
** of pIndex has the same root page number, and if it does, return true.
** This would indicate a corrupt schema.
*/
int sqlite3IndexHasDuplicateRootPage(Index *pIndex){
................................................................................
      if( db->init.orphanTrigger ){
        assert( iDb==1 );
      }else{
        pData->rc = rc;
        if( rc==SQLITE_NOMEM ){
          sqlite3OomFault(db);
        }else if( rc!=SQLITE_INTERRUPT 
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
               && (rc&0xFF)!=SQLITE_LOCKED 
               && (rc&0xFF)!=SQLITE_IOERR
#endif
        ){
          corruptSchema(pData, argv[0], sqlite3_errmsg(db));
        }
      }
    }
    sqlite3_finalize(pStmt);
  }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
................................................................................
     || pIndex->tnum<2
     || sqlite3IndexHasDuplicateRootPage(pIndex)
    ){
      corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
    }
  }

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  if( IsSharedSchema(db) && iDb!=1 ){
    schemaUpdateChecksum(pData, argv[0], argv[1], argv[2]);
  }
#endif
  return 0;
}

/*
** 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
................................................................................
  assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
  assert( iDb>=0 && iDb<db->nDb );
  assert( db->aDb[iDb].pSchema || (IsSharedSchema(db) && iDb!=1) );
  assert( sqlite3_mutex_held(db->mutex) );
  assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );

  pDb = &db->aDb[iDb];
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  assert( pDb->pSPool==0 || IsSharedSchema(db) );
  if( pDb->pSPool ){
    /* See if there is a free schema object in the schema-pool. If not,
    ** disconnect from said schema pool and continue. This function will
    ** connect to a (possibly different) schema-pool before returning. */
    Schema *pNew = sqlite3SchemaExtract(pDb->pSPool);
    if( pNew ){
................................................................................
      pDb->pSchema = pNew;
      return SQLITE_OK;
    }
    rc = sqlite3SchemaDisconnect(db, iDb, 1);
    if( rc!=SQLITE_OK ) goto error_out;
    assert( pDb->pSchema && pDb->pSPool==0 );
  }
#endif

  db->init.busy = 1;

  /* Construct the in-memory representation schema tables (sqlite_master or
  ** sqlite_temp_master) by invoking the parser directly.  The appropriate
  ** table name will be inserted automatically by the parser so we can just
  ** use the abbreviation "x" here.  The parser will also automatically tag
................................................................................
    }
    sqlite3ResetOneSchema(db, iDb);
  }
  db->init.busy = 0;
  return rc;
}


#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** If this is a SHARED_SCHEMA connection and the DBFLAG_SchemaInUse flag
** is not currently set, set it and return non-zero. Otherwise, return 0.
*/
int sqlite3LockReusableSchema(sqlite3 *db){
  if( IsSharedSchema(db) && (db->mDbFlags & DBFLAG_SchemaInuse)==0 ){
    db->mDbFlags |= DBFLAG_SchemaInuse;
    return 1;
  }
  return 0;
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
/*
** This function is a no-op for non-SHARED_SCHEMA connections, or if bRelease
** is zero. Otherwise, clear the DBFLAG_SchemaInuse flag and release all
** schema references currently held.
*/
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease){
  if( bRelease ){
    db->mDbFlags &= ~DBFLAG_SchemaInuse;
    sqlite3SchemaReleaseAll(db);
  }
}
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */

/*
** 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.
**

Changes to src/shell.c.in.

1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
....
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
....
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
....
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
....
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
#define AUTOEQP_on       1           /* Automatic EQP is on */
#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
#define AUTOEQP_full     3           /* Show full EXPLAIN */

/* Allowed values for ShellState.openMode
*/
#define SHELL_OPEN_UNSPEC      0      /* No open-mode specified */
#define SHELL_OPEN_NORMAL      1      /* Normal database file */
#define SHELL_OPEN_APPENDVFS   2      /* Use appendvfs */
#define SHELL_OPEN_ZIPFILE     3      /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY    4      /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5      /* Open using sqlite3_deserialize() */
#define SHELL_OPEN_HEXDB       6      /* Use "dbtotxt" output as data source */
#define SHELL_OPEN_REUSESCHEMA 7      /* Open for schema reuse */

/* Allowed values for ShellState.eTraceType
*/
#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */

................................................................................
        sqlite3_open(":memory:", &p->db);
        break;
      }
      case SHELL_OPEN_READONLY: {
        sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
        break;
      }
      case SHELL_OPEN_REUSESCHEMA: {
        sqlite3_open_v2(p->zDbFilename, &p->db,
          SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SHARED_SCHEMA,0);
        break;
      }
      case SHELL_OPEN_UNSPEC:
      case SHELL_OPEN_NORMAL: {
        sqlite3_open(p->zDbFilename, &p->db);
................................................................................
      }else if( optionMatch(z, "zip") ){
        p->openMode = SHELL_OPEN_ZIPFILE;
#endif
      }else if( optionMatch(z, "append") ){
        p->openMode = SHELL_OPEN_APPENDVFS;
      }else if( optionMatch(z, "readonly") ){
        p->openMode = SHELL_OPEN_READONLY;
      }else if( optionMatch(z, "reuseschema") ){
        p->openMode = SHELL_OPEN_REUSESCHEMA;
      }else if( z[0]=='-' ){
#ifdef SQLITE_ENABLE_DESERIALIZE
      }else if( optionMatch(z, "deserialize") ){
        p->openMode = SHELL_OPEN_DESERIALIZE;
      }else if( optionMatch(z, "hexdb") ){
        p->openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
................................................................................
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( strcmp(z,"-reuseschema")==0 ){
      data.openMode = SHELL_OPEN_REUSESCHEMA;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( strncmp(z, "-A",2)==0 ){
      /* All remaining command-line arguments are passed to the ".archive"
      ** command, so ignore them */
      break;
#endif
    }else if( strcmp(z, "-memtrace")==0 ){
................................................................................
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( strcmp(z,"-reuseschema")==0 ){
      data.openMode = SHELL_OPEN_REUSESCHEMA;
    }else if( strcmp(z,"-ascii")==0 ){
      data.mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
                       SEP_Unit);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
                       SEP_Record);
    }else if( strcmp(z,"-separator")==0 ){







|
|
|
|
|
|
|
|







 







|







 







|
|







 







|
|







 







|
|







1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
....
4297
4298
4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
....
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
....
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
....
9536
9537
9538
9539
9540
9541
9542
9543
9544
9545
9546
9547
9548
9549
9550
9551
#define AUTOEQP_off      0           /* Automatic EXPLAIN QUERY PLAN is off */
#define AUTOEQP_on       1           /* Automatic EQP is on */
#define AUTOEQP_trigger  2           /* On and also show plans for triggers */
#define AUTOEQP_full     3           /* Show full EXPLAIN */

/* Allowed values for ShellState.openMode
*/
#define SHELL_OPEN_UNSPEC       0    /* No open-mode specified */
#define SHELL_OPEN_NORMAL       1    /* Normal database file */
#define SHELL_OPEN_APPENDVFS    2    /* Use appendvfs */
#define SHELL_OPEN_ZIPFILE      3    /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY     4    /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE  5    /* Open using sqlite3_deserialize() */
#define SHELL_OPEN_HEXDB        6    /* Use "dbtotxt" output as data source */
#define SHELL_OPEN_SHAREDSCHEMA 7    /* Open for schema reuse */

/* Allowed values for ShellState.eTraceType
*/
#define SHELL_TRACE_PLAIN      0      /* Show input SQL text */
#define SHELL_TRACE_EXPANDED   1      /* Show expanded SQL text */
#define SHELL_TRACE_NORMALIZED 2      /* Show normalized SQL text */

................................................................................
        sqlite3_open(":memory:", &p->db);
        break;
      }
      case SHELL_OPEN_READONLY: {
        sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
        break;
      }
      case SHELL_OPEN_SHAREDSCHEMA: {
        sqlite3_open_v2(p->zDbFilename, &p->db,
          SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SHARED_SCHEMA,0);
        break;
      }
      case SHELL_OPEN_UNSPEC:
      case SHELL_OPEN_NORMAL: {
        sqlite3_open(p->zDbFilename, &p->db);
................................................................................
      }else if( optionMatch(z, "zip") ){
        p->openMode = SHELL_OPEN_ZIPFILE;
#endif
      }else if( optionMatch(z, "append") ){
        p->openMode = SHELL_OPEN_APPENDVFS;
      }else if( optionMatch(z, "readonly") ){
        p->openMode = SHELL_OPEN_READONLY;
      }else if( optionMatch(z, "sharedschema") ){
        p->openMode = SHELL_OPEN_SHAREDSCHEMA;
      }else if( z[0]=='-' ){
#ifdef SQLITE_ENABLE_DESERIALIZE
      }else if( optionMatch(z, "deserialize") ){
        p->openMode = SHELL_OPEN_DESERIALIZE;
      }else if( optionMatch(z, "hexdb") ){
        p->openMode = SHELL_OPEN_HEXDB;
      }else if( optionMatch(z, "maxsize") && iName+1<nArg ){
................................................................................
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( strcmp(z,"-sharedschema")==0 ){
      data.openMode = SHELL_OPEN_SHAREDSCHEMA;
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
    }else if( strncmp(z, "-A",2)==0 ){
      /* All remaining command-line arguments are passed to the ".archive"
      ** command, so ignore them */
      break;
#endif
    }else if( strcmp(z, "-memtrace")==0 ){
................................................................................
    }else if( strcmp(z,"-deserialize")==0 ){
      data.openMode = SHELL_OPEN_DESERIALIZE;
    }else if( strcmp(z,"-maxsize")==0 && i+1<argc ){
      data.szMax = integerValue(argv[++i]);
#endif
    }else if( strcmp(z,"-readonly")==0 ){
      data.openMode = SHELL_OPEN_READONLY;
    }else if( strcmp(z,"-sharedschema")==0 ){
      data.openMode = SHELL_OPEN_SHAREDSCHEMA;
    }else if( strcmp(z,"-ascii")==0 ){
      data.mode = MODE_Ascii;
      sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
                       SEP_Unit);
      sqlite3_snprintf(sizeof(data.rowSeparator), data.rowSeparator,
                       SEP_Record);
    }else if( strcmp(z,"-separator")==0 ){

Changes to src/sqliteInt.h.

1199
1200
1201
1202
1203
1204
1205

1206
1207

1208
1209
1210
1211
1212
1213
1214
....
1232
1233
1234
1235
1236
1237
1238

1239

1240
1241
1242
1243
1244
1245
1246
....
1501
1502
1503
1504
1505
1506
1507

1508



1509
1510
1511
1512
1513
1514
1515
....
1955
1956
1957
1958
1959
1960
1961

1962

1963
1964
1965
1966
1967
1968
1969
....
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272



3273
3274
3275
3276
3277
3278
3279
....
4318
4319
4320
4321
4322
4323
4324



4325
4326
4327
4328
4329
4330
4331
4332
4333












4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
*/
struct Db {
  char *zDbSName;      /* Name of this database. (schema name, not filename) */
  Btree *pBt;          /* The B*Tree structure for this database file */
  u8 safety_level;     /* How aggressive at syncing data to disk */
  u8 bSyncSet;         /* True if "PRAGMA synchronous=N" has been run */
  Schema *pSchema;     /* Pointer to database schema (possibly shared) */

  SchemaPool *pSPool;  /* For REUSE_SCHEMA mode */
  VTable *pVTable;     /* List of all VTable objects (REUSE_SCHEMA mode only) */

};

/*
** An instance of the following structure stores a database schema.
**
** Most Schema objects are associated with a Btree.  The exception is
** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
................................................................................
  Hash trigHash;       /* All triggers indexed by name */
  Hash fkeyHash;       /* All foreign keys by referenced table name */
  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
  u8 file_format;      /* Schema format version for this file */
  u8 enc;              /* Text encoding used by this database */
  u16 schemaFlags;     /* Flags associated with this schema */
  int cache_size;      /* Number of pages to use in the cache */

  Schema *pNext;       /* Next Schema object SchemaPool (REUSE_SCHEMA) */

};

/*
** These macros can be used to test, set, or clear bits in the
** Db.pSchema->flags field.
*/
#define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
................................................................................
  sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
  sqlite3_userauth auth;        /* User authentication information */
#endif
};


#define IsSharedSchema(db) (((db)->openFlags & SQLITE_OPEN_SHARED_SCHEMA)!=0)




/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db)        ((db)->enc)

................................................................................
  sqlite3 *db;              /* Database connection associated with this table */
  Module *pMod;             /* Pointer to module implementation */
  sqlite3_vtab *pVtab;      /* Pointer to vtab instance */
  int nRef;                 /* Number of pointers to this structure */
  u8 bConstraint;           /* True if constraints are supported */
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */

  char *zName;              /* Table name (REUSE_SCHEMA mode) */

};

/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
*/
struct Table {
................................................................................
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
  Expr *pWhen;            /* The WHEN clause of the expression (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  Schema *pSchema;        /* Schema containing the trigger */
  Schema *pTabSchema;     /* Schema containing the table */
  char *zTabSchema;       /* Temp triggers in IsSharedSchema() dbs only */
  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */



};

/*
** A trigger is either a BEFORE or an AFTER trigger.  The following constants
** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
................................................................................
int sqlite3FindDbName(sqlite3 *, const char *);
int sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DeleteIndexSamples(sqlite3*,Index*);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
void sqlite3SchemaClear(void *);



int sqlite3SchemaConnect(sqlite3*, int, u64);
int sqlite3SchemaDisconnect(sqlite3 *, int, int);
void sqlite3SchemaClearOrDisconnect(sqlite3*, int);
Schema *sqlite3SchemaExtract(SchemaPool*);
int sqlite3SchemaLoad(sqlite3*, int, int*, char**);
void sqlite3SchemaReleaseAll(sqlite3*);
void sqlite3SchemaRelease(sqlite3*, int);
void sqlite3SchemaAdjustUsed(sqlite3*, int, int, int*);
void sqlite3SchemaWritable(Parse*, int);












Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
void sqlite3KeyInfoUnref(KeyInfo*);
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);

void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease);
int sqlite3LockReusableSchema(sqlite3 *db);

#ifdef SQLITE_DEBUG
int sqlite3KeyInfoIsWriteable(KeyInfo*);
#endif
int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
  void (*)(sqlite3_context*,int,sqlite3_value **),
  void (*)(sqlite3_context*,int,sqlite3_value **), 







>


>







 







>

>







 







>
|
>
>
>







 







>

>







 







<


>
>
>







 







>
>
>


<






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








<
<







1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
....
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
....
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
....
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
....
3273
3274
3275
3276
3277
3278
3279

3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
....
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341

4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367


4368
4369
4370
4371
4372
4373
4374
*/
struct Db {
  char *zDbSName;      /* Name of this database. (schema name, not filename) */
  Btree *pBt;          /* The B*Tree structure for this database file */
  u8 safety_level;     /* How aggressive at syncing data to disk */
  u8 bSyncSet;         /* True if "PRAGMA synchronous=N" has been run */
  Schema *pSchema;     /* Pointer to database schema (possibly shared) */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  SchemaPool *pSPool;  /* For REUSE_SCHEMA mode */
  VTable *pVTable;     /* List of all VTable objects (REUSE_SCHEMA mode only) */
#endif
};

/*
** An instance of the following structure stores a database schema.
**
** Most Schema objects are associated with a Btree.  The exception is
** the Schema for the TEMP databaes (sqlite3.aDb[1]) which is free-standing.
................................................................................
  Hash trigHash;       /* All triggers indexed by name */
  Hash fkeyHash;       /* All foreign keys by referenced table name */
  Table *pSeqTab;      /* The sqlite_sequence table used by AUTOINCREMENT */
  u8 file_format;      /* Schema format version for this file */
  u8 enc;              /* Text encoding used by this database */
  u16 schemaFlags;     /* Flags associated with this schema */
  int cache_size;      /* Number of pages to use in the cache */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  Schema *pNext;       /* Next Schema object SchemaPool (REUSE_SCHEMA) */
#endif
};

/*
** These macros can be used to test, set, or clear bits in the
** Db.pSchema->flags field.
*/
#define DbHasProperty(D,I,P)     (((D)->aDb[I].pSchema->schemaFlags&(P))==(P))
................................................................................
  sqlite3 *pNextBlocked;        /* Next in list of all blocked connections */
#endif
#ifdef SQLITE_USER_AUTHENTICATION
  sqlite3_userauth auth;        /* User authentication information */
#endif
};

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
# define IsSharedSchema(db) (((db)->openFlags & SQLITE_OPEN_SHARED_SCHEMA)!=0)
#else
# define IsSharedSchema(db) 0
#endif

/*
** A macro to discover the encoding of a database.
*/
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
#define ENC(db)        ((db)->enc)

................................................................................
  sqlite3 *db;              /* Database connection associated with this table */
  Module *pMod;             /* Pointer to module implementation */
  sqlite3_vtab *pVtab;      /* Pointer to vtab instance */
  int nRef;                 /* Number of pointers to this structure */
  u8 bConstraint;           /* True if constraints are supported */
  int iSavepoint;           /* Depth of the SAVEPOINT stack */
  VTable *pNext;            /* Next in linked list (see above) */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  char *zName;              /* Table name (REUSE_SCHEMA mode) */
#endif
};

/*
** The schema for each SQL table and view is represented in memory
** by an instance of the following structure.
*/
struct Table {
................................................................................
  u8 op;                  /* One of TK_DELETE, TK_UPDATE, TK_INSERT         */
  u8 tr_tm;               /* One of TRIGGER_BEFORE, TRIGGER_AFTER */
  Expr *pWhen;            /* The WHEN clause of the expression (may be NULL) */
  IdList *pColumns;       /* If this is an UPDATE OF <column-list> trigger,
                             the <column-list> is stored here */
  Schema *pSchema;        /* Schema containing the trigger */
  Schema *pTabSchema;     /* Schema containing the table */

  TriggerStep *step_list; /* Link list of trigger program steps             */
  Trigger *pNext;         /* Next trigger associated with the table */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  char *zTabSchema;       /* Temp triggers in IsSharedSchema() dbs only */
#endif
};

/*
** A trigger is either a BEFORE or an AFTER trigger.  The following constants
** determine which.
**
** If there are multiple triggers, you might of some BEFORE and some AFTER.
................................................................................
int sqlite3FindDbName(sqlite3 *, const char *);
int sqlite3AnalysisLoad(sqlite3*,int iDB);
void sqlite3DeleteIndexSamples(sqlite3*,Index*);
void sqlite3DefaultRowEst(Index*);
void sqlite3RegisterLikeFunctions(sqlite3*, int);
int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
void sqlite3SchemaClear(void *);
void sqlite3SchemaClearOrDisconnect(sqlite3*, int);

#ifdef SQLITE_ENABLE_SHARED_SCHEMA 
int sqlite3SchemaConnect(sqlite3*, int, u64);
int sqlite3SchemaDisconnect(sqlite3 *, int, int);

Schema *sqlite3SchemaExtract(SchemaPool*);
int sqlite3SchemaLoad(sqlite3*, int, int*, char**);
void sqlite3SchemaReleaseAll(sqlite3*);
void sqlite3SchemaRelease(sqlite3*, int);
void sqlite3SchemaAdjustUsed(sqlite3*, int, int, int*);
void sqlite3SchemaWritable(Parse*, int);
void sqlite3UnlockReusableSchema(sqlite3 *db, int bRelease);
int sqlite3LockReusableSchema(sqlite3 *db);
#else
# define sqlite3SchemaWritable(x,y)
# define sqlite3UnlockReusableSchema(x,y)
# define sqlite3LockReusableSchema(x) 0
# define sqlite3SchemaDisconnect(x,y,z) SQLITE_OK
# define sqlite3SchemaLoad(w,x,y,z) SQLITE_OK
# define sqlite3SchemaRelease(y,z)
# define sqlite3SchemaConnect(x,y,z) SQLITE_OK
#endif

Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
int sqlite3SchemaToIndex(sqlite3 *db, Schema *);
KeyInfo *sqlite3KeyInfoAlloc(sqlite3*,int,int);
void sqlite3KeyInfoUnref(KeyInfo*);
KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);




#ifdef SQLITE_DEBUG
int sqlite3KeyInfoIsWriteable(KeyInfo*);
#endif
int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
  void (*)(sqlite3_context*,int,sqlite3_value **),
  void (*)(sqlite3_context*,int,sqlite3_value **), 

Changes to src/status.c.

277
278
279
280
281
282
283


284
285
286
287
288
289
290
291
292

293
294
295
296
297
298
299
...
308
309
310
311
312
313
314

315
316
317
318

319
320
321
322
323
324
325
      int nByte = 0;              /* Used to accumulate return value */
      int bReleaseSchema;

      sqlite3BtreeEnterAll(db);
      bReleaseSchema = sqlite3LockReusableSchema(db);
      db->pnBytesFreed = &nByte;
      for(i=0; i<db->nDb; i++){


        int bUnload = 0;
        int nUsed = nByte;
        Schema *pSchema;
        if( db->aDb[i].pSPool ){
          char *zDummy = 0;
          rc = sqlite3SchemaLoad(db, i, &bUnload, &zDummy);
          sqlite3_free(zDummy);
          if( rc ) break;
        }

        pSchema = db->aDb[i].pSchema;
        if( ALWAYS(pSchema!=0) ){
          HashElem *p;

          nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
              pSchema->tblHash.count 
            + pSchema->trigHash.count
................................................................................
          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
            sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
          }
          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
          }
        }

        if( db->aDb[i].pSPool ){
          if( bUnload ) sqlite3SchemaRelease(db, i);
          sqlite3SchemaAdjustUsed(db, i, nUsed, &nByte);
        }

      }
      sqlite3UnlockReusableSchema(db, bReleaseSchema);
      db->pnBytesFreed = 0;
      sqlite3BtreeLeaveAll(db);

      *pHighwater = 0;
      *pCurrent = nByte;







>
>


<






>







 







>




>







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
...
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
      int nByte = 0;              /* Used to accumulate return value */
      int bReleaseSchema;

      sqlite3BtreeEnterAll(db);
      bReleaseSchema = sqlite3LockReusableSchema(db);
      db->pnBytesFreed = &nByte;
      for(i=0; i<db->nDb; i++){
        Schema *pSchema;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
        int bUnload = 0;
        int nUsed = nByte;

        if( db->aDb[i].pSPool ){
          char *zDummy = 0;
          rc = sqlite3SchemaLoad(db, i, &bUnload, &zDummy);
          sqlite3_free(zDummy);
          if( rc ) break;
        }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
        pSchema = db->aDb[i].pSchema;
        if( ALWAYS(pSchema!=0) ){
          HashElem *p;

          nByte += sqlite3GlobalConfig.m.xRoundup(sizeof(HashElem)) * (
              pSchema->tblHash.count 
            + pSchema->trigHash.count
................................................................................
          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
            sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
          }
          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
          }
        }
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
        if( db->aDb[i].pSPool ){
          if( bUnload ) sqlite3SchemaRelease(db, i);
          sqlite3SchemaAdjustUsed(db, i, nUsed, &nByte);
        }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
      }
      sqlite3UnlockReusableSchema(db, bReleaseSchema);
      db->pnBytesFreed = 0;
      sqlite3BtreeLeaveAll(db);

      *pHighwater = 0;
      *pCurrent = nByte;

Changes to src/tclsqlite.c.

3589
3590
3591
3592
3593
3594
3595

3596

3597
3598
3599
3600
3601
3602
3603
....
3724
3725
3726
3727
3728
3729
3730

3731
3732
3733
3734
3735
3736
3737
3738

3739
3740
3741
3742
3743
3744
3745
static int sqliteCmdUsage(
  Tcl_Interp *interp,
  Tcl_Obj *const*objv
){
  Tcl_WrongNumArgs(interp, 1, objv,
    "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
    " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"

    " ?-shared-schema BOOLEAN?"

#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    " ?-key CODECKEY?"
#endif
  );
  return TCL_ERROR;
}

................................................................................
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_URI;
      }else{
        flags &= ~SQLITE_OPEN_URI;
      }

    }else if( strcmp(zArg, "-shared-schema")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_SHARED_SCHEMA;
      }else{
        flags &= ~SQLITE_OPEN_SHARED_SCHEMA;
      }

    }else{
      Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
      return TCL_ERROR;
    }
  }
  zErrMsg = 0;
  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );







>

>







 







>








>







3589
3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
....
3726
3727
3728
3729
3730
3731
3732
3733
3734
3735
3736
3737
3738
3739
3740
3741
3742
3743
3744
3745
3746
3747
3748
3749
static int sqliteCmdUsage(
  Tcl_Interp *interp,
  Tcl_Obj *const*objv
){
  Tcl_WrongNumArgs(interp, 1, objv,
    "HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
    " ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    " ?-shared-schema BOOLEAN?"
#endif
#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
    " ?-key CODECKEY?"
#endif
  );
  return TCL_ERROR;
}

................................................................................
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_URI;
      }else{
        flags &= ~SQLITE_OPEN_URI;
      }
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    }else if( strcmp(zArg, "-shared-schema")==0 ){
      int b;
      if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
      if( b ){
        flags |= SQLITE_OPEN_SHARED_SCHEMA;
      }else{
        flags &= ~SQLITE_OPEN_SHARED_SCHEMA;
      }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
    }else{
      Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
      return TCL_ERROR;
    }
  }
  zErrMsg = 0;
  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );

Changes to src/test_config.c.

769
770
771
772
773
774
775






776
777
778
779
780
781
782
#endif

#ifdef SQLITE_OMIT_WINDOWFUNC
  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
#endif







#define LINKVAR(x) { \
    static const int cv_ ## x = SQLITE_ ## x; \
    Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
                TCL_LINK_INT | TCL_LINK_READ_ONLY); }

  LINKVAR( MAX_LENGTH );







>
>
>
>
>
>







769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
#endif

#ifdef SQLITE_OMIT_WINDOWFUNC
  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "windowfunc", "1", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "sharedschema", "0", TCL_GLOBAL_ONLY);
#endif

#define LINKVAR(x) { \
    static const int cv_ ## x = SQLITE_ ## x; \
    Tcl_LinkVar(interp, "SQLITE_" #x, (char *)&(cv_ ## x), \
                TCL_LINK_INT | TCL_LINK_READ_ONLY); }

  LINKVAR( MAX_LENGTH );

Changes to src/test_schemapool.c.

15
16
17
18
19
20
21
22
23




24
25
26
27
28
29
30
...
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
*/

/*
** None of this works unless we have virtual tables.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST)

#include "sqliteInt.h"
#include <tcl.h>





/* The code in this file defines a sqlite3 virtual-table module with
** the following schema.
*/
#define SCHEMAPOOL_SCHEMA \
"CREATE TABLE x("         \
"  cksum   INTEGER, "     \
................................................................................
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_create_module(db, "schemapool", &schemaPoolModule, 0);
#endif
  return TCL_OK;
}

#endif


/*
** Register commands with the TCL interpreter.
*/
int Sqlitetestschemapool_Init(Tcl_Interp *interp){

  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
     void *clientData;
  } aObjCmd[] = {
     { "register_schemapool_module", register_schemapool_module, 0 },
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
  }

  return TCL_OK;
}








<

>
>
>
>







 







|
>





>












>



15
16
17
18
19
20
21

22
23
24
25
26
27
28
29
30
31
32
33
...
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
*/

/*
** None of this works unless we have virtual tables.
*/
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST)


#include <tcl.h>

#ifdef SQLITE_ENABLE_SHARED_SCHEMA

#include "sqliteInt.h"

/* The code in this file defines a sqlite3 virtual-table module with
** the following schema.
*/
#define SCHEMAPOOL_SCHEMA \
"CREATE TABLE x("         \
"  cksum   INTEGER, "     \
................................................................................
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
#ifndef SQLITE_OMIT_VIRTUALTABLE
  sqlite3_create_module(db, "schemapool", &schemaPoolModule, 0);
#endif
  return TCL_OK;
}

#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_TEST) */

/*
** Register commands with the TCL interpreter.
*/
int Sqlitetestschemapool_Init(Tcl_Interp *interp){
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  static struct {
     char *zName;
     Tcl_ObjCmdProc *xProc;
     void *clientData;
  } aObjCmd[] = {
     { "register_schemapool_module", register_schemapool_module, 0 },
  };
  int i;
  for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
    Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
        aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
  }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
  return TCL_OK;
}

Changes to src/trigger.c.

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
...
249
250
251
252
253
254
255

256
257
258
259

260
261
262
263
264
265
266
...
550
551
552
553
554
555
556

557

558
559
560
561
562
563
564
  if( pParse->disableTriggers ){
    return 0;
  }

  if( pTmpSchema!=pTab->pSchema ){
    sqlite3 *db = pParse->db;
    HashElem *p;

    char *zSchema = 0;
    if( IsSharedSchema(db) ){
      zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
    }

    assert( sqlite3SchemaMutexHeld(db, 0, pTmpSchema) );
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);


      if( (zSchema==0 && pTrig->pTabSchema==pTab->pSchema)
       || (zSchema!=0 && 0==sqlite3StrICmp(pTrig->zTabSchema, zSchema))
      ){




        if( 0==sqlite3StrICmp(pTrig->table, pTab->zName) 
        ){
          pTrig->pTabSchema = pTab->pSchema;
          pTrig->pNext = (pList ? pList : pTab->pTrigger);
          pList = pTrig;
        }
      }
    }
  }
................................................................................

  /* Build the Trigger object */
  pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
  if( pTrigger==0 ) goto trigger_cleanup;
  pTrigger->zName = zName;
  zName = 0;
  pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);

  if( IsSharedSchema(db) && iDb==1 ){
    int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    pTrigger->zTabSchema = sqlite3DbStrDup(db, db->aDb[iTabDb].zDbSName);
  }

  pTrigger->pSchema = db->aDb[iDb].pSchema;
  pTrigger->pTabSchema = pTab->pSchema;
  pTrigger->op = (u8)op;
  pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
  if( IN_RENAME_OBJECT ){
    sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName);
    pTrigger->pWhen = pWhen;
................................................................................
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqlite3DeleteTriggerStep(db, pTrigger->step_list);
  sqlite3DbFree(db, pTrigger->zName);
  sqlite3DbFree(db, pTrigger->table);

  sqlite3DbFree(db, pTrigger->zTabSchema);

  sqlite3ExprDelete(db, pTrigger->pWhen);
  sqlite3IdListDelete(db, pTrigger->pColumns);
  sqlite3DbFree(db, pTrigger);
}

/*
** This function is called to drop a trigger from the database schema. 







>




>



>
>

|
<
>
>
>
>
|
<







 







>




>







 







>

>







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
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
  if( pParse->disableTriggers ){
    return 0;
  }

  if( pTmpSchema!=pTab->pSchema ){
    sqlite3 *db = pParse->db;
    HashElem *p;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
    char *zSchema = 0;
    if( IsSharedSchema(db) ){
      zSchema = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
    }
#endif
    assert( sqlite3SchemaMutexHeld(db, 0, pTmpSchema) );
    for(p=sqliteHashFirst(&pTmpSchema->trigHash); p; p=sqliteHashNext(p)){
      Trigger *pTrig = (Trigger *)sqliteHashData(p);

#ifdef SQLITE_ENABLE_SHARED_SCHEMA
      if( (zSchema==0 && pTrig->pTabSchema==pTab->pSchema)
       || (zSchema!=0 && 0==sqlite3StrICmp(pTrig->zTabSchema, zSchema)) )

#else 
      if( pTrig->pTabSchema==pTab->pSchema )
#endif
      {
        if( 0==sqlite3StrICmp(pTrig->table, pTab->zName) ){

          pTrig->pTabSchema = pTab->pSchema;
          pTrig->pNext = (pList ? pList : pTab->pTrigger);
          pList = pTrig;
        }
      }
    }
  }
................................................................................

  /* Build the Trigger object */
  pTrigger = (Trigger*)sqlite3DbMallocZero(db, sizeof(Trigger));
  if( pTrigger==0 ) goto trigger_cleanup;
  pTrigger->zName = zName;
  zName = 0;
  pTrigger->table = sqlite3DbStrDup(db, pTableName->a[0].zName);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  if( IsSharedSchema(db) && iDb==1 ){
    int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    pTrigger->zTabSchema = sqlite3DbStrDup(db, db->aDb[iTabDb].zDbSName);
  }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
  pTrigger->pSchema = db->aDb[iDb].pSchema;
  pTrigger->pTabSchema = pTab->pSchema;
  pTrigger->op = (u8)op;
  pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
  if( IN_RENAME_OBJECT ){
    sqlite3RenameTokenRemap(pParse, pTrigger->table, pTableName->a[0].zName);
    pTrigger->pWhen = pWhen;
................................................................................
** Recursively delete a Trigger structure
*/
void sqlite3DeleteTrigger(sqlite3 *db, Trigger *pTrigger){
  if( pTrigger==0 ) return;
  sqlite3DeleteTriggerStep(db, pTrigger->step_list);
  sqlite3DbFree(db, pTrigger->zName);
  sqlite3DbFree(db, pTrigger->table);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  sqlite3DbFree(db, pTrigger->zTabSchema);
#endif
  sqlite3ExprDelete(db, pTrigger->pWhen);
  sqlite3IdListDelete(db, pTrigger->pColumns);
  sqlite3DbFree(db, pTrigger);
}

/*
** This function is called to drop a trigger from the database schema. 

Changes to src/vtab.c.

140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
...
530
531
532
533
534
535
536


537

538
539
540
541
542
543
544
545

546
547

548
549
550
551
552
553
554
...
587
588
589
590
591
592
593

594
595
596
597


598
599
600
601
602
603
604
** pTab is a pointer to a Table structure representing a virtual-table.
** Return a pointer to the VTable object used by connection db to access 
** this virtual-table, if one has been created, or NULL otherwise.
*/
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
  VTable *pVtab;
  assert( IsVirtual(pTab) );

  if( IsSharedSchema(db) ){
    int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    if( iDb!=1 ){
      for(pVtab=db->aDb[iDb].pVTable; pVtab; pVtab=pVtab->pNext){
        if( sqlite3StrICmp(pTab->zName, pVtab->zName)==0 ) break;
      }
      return pVtab;
    }
  }

  for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
  return pVtab;
}

/*
** Decrement the ref-count on a virtual table object. When the ref-count
** reaches zero, call the xDisconnect() method to delete the object.
................................................................................
  }

  zModuleName = sqlite3DbStrDup(db, pTab->zName);
  if( !zModuleName ){
    return SQLITE_NOMEM_BKPT;
  }



  nByte = sizeof(VTable) + sqlite3Strlen30(pTab->zName) + 1;

  pVTable = (VTable*)sqlite3MallocZero(nByte);
  if( !pVTable ){
    sqlite3OomFault(db);
    sqlite3DbFree(db, zModuleName);
    return SQLITE_NOMEM_BKPT;
  }
  pVTable->db = db;
  pVTable->pMod = pMod;

  pVTable->zName = (char*)&pVTable[1];
  memcpy(pVTable->zName, pTab->zName, nByte-sizeof(VTable));


  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;

  /* Invoke the virtual table constructor */
  assert( &db->pVtabCtx );
  assert( xConstruct );
................................................................................
      /* If everything went according to plan, link the new VTable structure
      ** into the linked list headed by pTab->pVTable. Or, if this is a
      ** reusable schema, into the linked list headed by Db.pVTable.
      **
      ** Then loop through the columns of the table to see if any of them
      ** contain the token "hidden". If so, set the Column COLFLAG_HIDDEN flag
      ** and remove the token from the type string.  */

      if( IsSharedSchema(db) && iDb!=1 ){
        pVTable->pNext = db->aDb[iDb].pVTable;
        db->aDb[iDb].pVTable = pVTable;
      }else{


        pVTable->pNext = pTab->pVTable;
        pTab->pVTable = pVTable;
      }

      for(iCol=0; iCol<pTab->nCol; iCol++){
        char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
        int nType;







>









>







 







>
>
|
>








>


>







 







>



|
>
>







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
...
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
...
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
** pTab is a pointer to a Table structure representing a virtual-table.
** Return a pointer to the VTable object used by connection db to access 
** this virtual-table, if one has been created, or NULL otherwise.
*/
VTable *sqlite3GetVTable(sqlite3 *db, Table *pTab){
  VTable *pVtab;
  assert( IsVirtual(pTab) );
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  if( IsSharedSchema(db) ){
    int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
    if( iDb!=1 ){
      for(pVtab=db->aDb[iDb].pVTable; pVtab; pVtab=pVtab->pNext){
        if( sqlite3StrICmp(pTab->zName, pVtab->zName)==0 ) break;
      }
      return pVtab;
    }
  }
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
  for(pVtab=pTab->pVTable; pVtab && pVtab->db!=db; pVtab=pVtab->pNext);
  return pVtab;
}

/*
** Decrement the ref-count on a virtual table object. When the ref-count
** reaches zero, call the xDisconnect() method to delete the object.
................................................................................
  }

  zModuleName = sqlite3DbStrDup(db, pTab->zName);
  if( !zModuleName ){
    return SQLITE_NOMEM_BKPT;
  }

  nByte = sizeof(VTable);
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  nByte += sqlite3Strlen30(pTab->zName) + 1;
#endif
  pVTable = (VTable*)sqlite3MallocZero(nByte);
  if( !pVTable ){
    sqlite3OomFault(db);
    sqlite3DbFree(db, zModuleName);
    return SQLITE_NOMEM_BKPT;
  }
  pVTable->db = db;
  pVTable->pMod = pMod;
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
  pVTable->zName = (char*)&pVTable[1];
  memcpy(pVTable->zName, pTab->zName, nByte-sizeof(VTable));
#endif

  iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
  pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;

  /* Invoke the virtual table constructor */
  assert( &db->pVtabCtx );
  assert( xConstruct );
................................................................................
      /* If everything went according to plan, link the new VTable structure
      ** into the linked list headed by pTab->pVTable. Or, if this is a
      ** reusable schema, into the linked list headed by Db.pVTable.
      **
      ** Then loop through the columns of the table to see if any of them
      ** contain the token "hidden". If so, set the Column COLFLAG_HIDDEN flag
      ** and remove the token from the type string.  */
#ifdef SQLITE_ENABLE_SHARED_SCHEMA
      if( IsSharedSchema(db) && iDb!=1 ){
        pVTable->pNext = db->aDb[iDb].pVTable;
        db->aDb[iDb].pVTable = pVTable;
      }else
#endif /* ifdef SQLITE_ENABLE_SHARED_SCHEMA */
      {
        pVTable->pNext = pTab->pVTable;
        pTab->pVTable = pVTable;
      }

      for(iCol=0; iCol<pTab->nCol; iCol++){
        char *zType = sqlite3ColumnType(&pTab->aCol[iCol], "");
        int nType;

Changes to test/reuse1.test.

12
13
14
15
16
17
18
19



20
21
22
23
24
25
26
...
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#


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

if 1 {




forcedelete test.db2
sqlite3 db2 test.db2

do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
................................................................................
  do_execsql_test 2.2 {
    SELECT * FROM aux.ft;
  } {aux1 aux2 aux3}

  do_execsql_test 2.2 {
    SELECT * FROM aux.ft_content;
  } {1 aux1 2 aux2 3 aux3}
}

}

#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 3.0 {







|
>
>
>







 







<
<







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
121
122
123
124
125
126
127


128
129
130
131
132
133
134
#


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

ifcapable !sharedschema {
  finish_test
  return
}

forcedelete test.db2
sqlite3 db2 test.db2

do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
................................................................................
  do_execsql_test 2.2 {
    SELECT * FROM aux.ft;
  } {aux1 aux2 aux3}

  do_execsql_test 2.2 {
    SELECT * FROM aux.ft_content;
  } {1 aux1 2 aux2 3 aux3}


}

#-------------------------------------------------------------------------
#
reset_db
forcedelete test.db2
do_execsql_test 3.0 {

Changes to test/reuse2.test.

11
12
13
14
15
16
17





18
19
20
21
22
23
24
#
#


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






do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
  PRAGMA schema_version;
} {2}








>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
#


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

ifcapable !sharedschema {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
  PRAGMA schema_version;
} {2}

Changes to test/reuse3.test.

11
12
13
14
15
16
17





18
19
20
21
22
23
24
#
#


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






do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
  CREATE TABLE t2(a);
} {}








>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
#


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

ifcapable !sharedschema {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x INTEGER PRIMARY KEY, y UNIQUE, z);
  CREATE INDEX i1 ON t1(z);
  CREATE TABLE t2(a);
} {}

Changes to test/reuse4.test.

10
11
12
13
14
15
16





17
18
19
20
21
22
23
#***********************************************************************
#
#

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






foreach {tn sharedschema} {
  1 0  
  2 1  
} {
  reset_db








>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#***********************************************************************
#
#

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

ifcapable !sharedschema {
  finish_test
  return
}

foreach {tn sharedschema} {
  1 0  
  2 1  
} {
  reset_db

Changes to test/reuse5.test.

11
12
13
14
15
16
17





18
19
20
21
22
23
24
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse5
set CLI [test_find_cli]






do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  CREATE TABLE t2(a, b, c);
  CREATE INDEX t1x ON t1(x);
  CREATE INDEX t1y ON t1(y);
  CREATE VIEW v1 AS SELECT * FROM t2;







>
>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix reuse5
set CLI [test_find_cli]

ifcapable !sharedschema {
  finish_test
  return
}

do_execsql_test 1.0 {
  CREATE TABLE t1(x, y);
  CREATE TABLE t2(a, b, c);
  CREATE INDEX t1x ON t1(x);
  CREATE INDEX t1y ON t1(y);
  CREATE VIEW v1 AS SELECT * FROM t2;

Changes to test/reusefault.test.

10
11
12
13
14
15
16





17
18
19
20
21
22
23
#***********************************************************************
#
#

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






do_execsql_test 1.0 {
  PRAGMA cache_size = 10;
  CREATE TABLE t1(a UNIQUE, b UNIQUE);
  INSERT INTO t1 VALUES(1, 2), (3, 4);
}
faultsim_save_and_close







>
>
>
>
>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#***********************************************************************
#
#

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

ifcapable !sharedschema {
  finish_test
  return
}

do_execsql_test 1.0 {
  PRAGMA cache_size = 10;
  CREATE TABLE t1(a UNIQUE, b UNIQUE);
  INSERT INTO t1 VALUES(1, 2), (3, 4);
}
faultsim_save_and_close

Changes to test/tclsqlite.test.

21
22
23
24
25
26
27
28



29
30
31
32
33
34
35

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

# Check the error messages generated by tclsqlite
#
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN? ?-shared-schema BOOLEAN?"



if {[sqlite3 -has-codec]} {
  append r " ?-key CODECKEY?"
}
do_test tcl-1.1 {
  set v [catch {sqlite3 -bogus} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg







|
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

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

# Check the error messages generated by tclsqlite
#
set r "sqlite_orig HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN? ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
ifcapable sharedschema {
  append r " ?-shared-schema BOOLEAN?"
}
if {[sqlite3 -has-codec]} {
  append r " ?-key CODECKEY?"
}
do_test tcl-1.1 {
  set v [catch {sqlite3 -bogus} msg]
  regsub {really_sqlite3} $msg {sqlite3} msg
  lappend v $msg