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 |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c7c5e927a54f0fbc2ca625754787aff4 |
User & Date: | drh 2003-03-31 00:30:48.000 |
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: 1d3fc97721 user: drh tags: trunk) | |
00:30 | The ATTACH and DETACH statements are now coded but are still mostly untested. (CVS 890) (check-in: c7c5e927a5 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: 0a358844e4 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** 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 |
︙ | ︙ | |||
182 183 184 185 186 187 188 189 | } /* ** 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. */ | > > > > | | > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > | | 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 | } /* ** 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)){ Trigger *pTrigger = sqliteHashData(pElem); sqliteDeleteTrigger(pTrigger); } 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){ |
︙ | ︙ | |||
362 363 364 365 366 367 368 369 370 371 372 373 374 375 | 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 ); | > | 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | 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 ); |
︙ | ︙ | |||
426 427 428 429 430 431 432 | ** 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); | > | | 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 | ** 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 && |
︙ | ︙ | |||
451 452 453 454 455 456 457 | return; } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; | | | 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 | 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 |
︙ | ︙ | |||
1454 1455 1456 1457 1458 1459 1460 | 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; } | | < < < < < < < < < < < < < < | 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 | 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 |
︙ | ︙ | |||
2147 2148 2149 2150 2151 2152 2153 | */ 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; | | | 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 | */ 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. |
︙ | ︙ | |||
2637 2638 2639 2640 2641 2642 2643 | sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); }else {} sqliteFree(zLeft); sqliteFree(zRight); } | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | 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 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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 |
︙ | ︙ | |||
36 37 38 39 40 41 42 | ** ** 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. | | > | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** ** 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; |
︙ | ︙ | |||
154 155 156 157 158 159 160 | return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal | > > > | < < < < < < < | > | 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 | 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 */ |
︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 232 233 234 235 236 | "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; | > > > | > | | | | | | | > | | < | < > > | | | | | < | | < | | | | | | | | | | | | | | | > > > > > > > > > > | | | > > > > > > > > > < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | | 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 | "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; |
︙ | ︙ | |||
472 473 474 475 476 477 478 479 480 481 482 483 | /* 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); } } | > > < < < | > > | 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 | /* 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); } } |
︙ | ︙ | |||
669 670 671 672 673 674 675 | 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); | | | | 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 | 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 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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 ){ |
︙ | ︙ | |||
837 838 839 840 841 842 843 | 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). { | | | > > | > > | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 | 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 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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++. |
︙ | ︙ | |||
161 162 163 164 165 166 167 168 169 170 171 172 173 174 | #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 | > | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | #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.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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" |
︙ | ︙ | |||
967 968 969 970 971 972 973 974 | 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); | > | < | 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | 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*); |
︙ | ︙ | |||
1078 1079 1080 1081 1082 1083 1084 | #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 | > > | 1078 1079 1080 1081 1082 1083 1084 1085 1086 | #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*); |