Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | The ATTACH and DETACH statements are now coded but are still mostly untested. (CVS 890) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
c7c5e927a54f0fbc2ca625754787aff4 |
User & Date: | drh 2003-03-31 00:30:48 |
Context
2003-03-31
| ||
02:12 | Add the sqliteErrorMsg() function and use it to generate error message text during parsing and code generation. This simplifies the code somewhat and makes it easier to handle names with a database prefix. (CVS 891) check-in: 1d3fc977 user: drh tags: trunk | |
00:30 | The ATTACH and DETACH statements are now coded but are still mostly untested. (CVS 890) check-in: c7c5e927 user: drh tags: trunk | |
2003-03-30
| ||
19:17 | Remove the experimental sqlite_open_aux_file() API. It will soon be replaced by ATTACH and DETACH SQL commands. (CVS 1732) check-in: 0a358844 user: drh tags: trunk | |
Changes
Changes to src/build.c.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ... 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 ... 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 ... 362 363 364 365 366 367 368 369 370 371 372 373 374 375 ... 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 ... 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 .... 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 .... 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 .... 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 .... 2637 2638 2639 2640 2641 2642 2643 |
** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.136 2003/03/30 00:19:50 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs ................................................................................ } /* ** Erase all schema information from the in-memory hash tables of ** database connection. This routine is called to reclaim memory ** before the connection closes. It is also called during a rollback ** if there were schema changes during the transaction. */ void sqliteResetInternalSchema(sqlite *db){ HashElem *pElem; Hash temp1; Hash temp2; int i; for(i=0; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; temp1 = pDb->tblHash; temp2 = pDb->trigHash; sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&pDb->aFKey); sqliteHashClear(&pDb->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ ................................................................................ sqliteHashClear(&temp2); sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); sqliteDeleteTable(db, pTab); } sqliteHashClear(&temp1); } db->flags &= ~(SQLITE_Initialized|SQLITE_InternChanges); } /* ** This routine is called whenever a rollback occurs. If there were ** schema changes during the transaction, then we have to reset the ** internal hash tables and reload them from disk. */ void sqliteRollbackInternalChanges(sqlite *db){ if( db->flags & SQLITE_InternChanges ){ sqliteResetInternalSchema(db); } } /* ** This routine is called when a commit occurs. */ void sqliteCommitInternalChanges(sqlite *db){ ................................................................................ int isView /* True if this is a VIEW */ ){ Table *pTable; Index *pIdx; char *zName; sqlite *db = pParse->db; Vdbe *v; pParse->sFirstToken = *pStart; zName = sqliteTableNameFromToken(pName); if( zName==0 ) return; if( pParse->iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( (isTemp & 1)==isTemp ); ................................................................................ ** index or table name. Issue an error message if it does. ** ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** an existing temporary table, that is not an error. */ pTable = sqliteFindTable(db, zName, 0); if( pTable!=0 && (pTable->iDb==isTemp || !pParse->initFlag) ){ sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n, " already exists", 0, 0); sqliteFree(zName); pParse->nErr++; return; } if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 && ................................................................................ return; } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = isTemp ? 1 : pParse->iDb; if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* Begin generating the code that will insert the table record into ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ................................................................................ if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not be indexed", 0); pParse->nErr++; goto exit_create_index; } if( !isTemp && pTab->iDb>=2 ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not have non-temporary indices added", 0); pParse->nErr++; goto exit_create_index; } if( pTab->pSelect ){ sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0); ................................................................................ pParse->nErr++; goto exit_create_index; } if( pTab->iDb==1 ){ isTemp = 1; } #if 0 /* If this index is created while re-reading the schema from sqlite_master ** but the table associated with this index is a temporary table, it can ** only mean that the table that this index is really associated with is ** one whose name is hidden behind a temporary table with the same name. ** Since its table has been suppressed, we need to also suppress the ** index. */ if( pParse->initFlag && !pParse->isTemp && pTab->iDb ){ goto exit_create_index; } #endif /* ** Find the name of the index. Make sure there is not already another ** index or table with the same name. ** ** Exception: If we are reading the names of permanent indices from the ** sqlite_master table (because some other process changed the schema) and ** one of the index names collides with the name of a temporary table or ................................................................................ */ void sqliteCodeVerifySchema(Parse *pParse){ int i; sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); for(i=0; i<db->nDb; i++){ if( i==1 || db->aDb[i].pBt==0 ) continue; sqliteVdbeAddOp(v, OP_VerifyCookie, 0, db->aDb[i].schema_cookie); } pParse->schemaVerified = 1; } /* ** Generate VDBE code that prepares for doing an operation that ** might change the database. ................................................................................ sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); }else {} sqliteFree(zLeft); sqliteFree(zRight); } |
| > > > > | | > > | > > > | > > > > > > > > > > > > > > > > > > > > > > > > | > > | | | < < < < < < < < < < < < < < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > |
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 ... 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 ... 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 ... 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 ... 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 ... 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 .... 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 .... 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 .... 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 .... 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 |
** COPY ** VACUUM ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.137 2003/03/31 00:30:48 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs ................................................................................ } /* ** Erase all schema information from the in-memory hash tables of ** database connection. This routine is called to reclaim memory ** before the connection closes. It is also called during a rollback ** if there were schema changes during the transaction. ** ** If iDb<=0 then reset the internal schema tables for all database ** files. If iDb>=2 then reset the internal schema for only the ** single file indicates. */ void sqliteResetInternalSchema(sqlite *db, int iDb){ HashElem *pElem; Hash temp1; Hash temp2; int i, j; assert( iDb>=0 && iDb<db->nDb ); db->flags &= ~SQLITE_Initialized; for(i=iDb; i<db->nDb; i++){ Db *pDb = &db->aDb[i]; temp1 = pDb->tblHash; temp2 = pDb->trigHash; sqliteHashInit(&pDb->trigHash, SQLITE_HASH_STRING, 0); sqliteHashClear(&pDb->aFKey); sqliteHashClear(&pDb->idxHash); for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ ................................................................................ sqliteHashClear(&temp2); sqliteHashInit(&pDb->tblHash, SQLITE_HASH_STRING, 0); for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ Table *pTab = sqliteHashData(pElem); sqliteDeleteTable(db, pTab); } sqliteHashClear(&temp1); db->aDb[i].flags &= ~SQLITE_Initialized; if( iDb>0 ) return; } assert( iDb==0 ); db->flags &= ~SQLITE_InternChanges; /* If one or more of the auxiliary database files has been closed, ** then remove then from the auxiliary database list. We take the ** opportunity to do this here since we have just deleted all of the ** schema hash tables and therefore do not have to make any changes ** to any of those tables. */ for(i=j=2; i<db->nDb; i++){ if( db->aDb[i].pBt==0 ){ sqliteFree(db->aDb[i].zName); db->aDb[i].zName = 0; continue; } if( j<i ){ db->aDb[j++] = db->aDb[i]; } } memset(&db->aDb[j], 0, (db->nDb-j)*sizeof(db->aDb[j])); db->nDb = j; if( db->nDb<=2 && db->aDb!=db->aDbStatic ){ memcpy(db->aDbStatic, db->aDb, 2*sizeof(db->aDb[0])); sqliteFree(db->aDb); db->aDb = db->aDbStatic; } } /* ** This routine is called whenever a rollback occurs. If there were ** schema changes during the transaction, then we have to reset the ** internal hash tables and reload them from disk. */ void sqliteRollbackInternalChanges(sqlite *db){ if( db->flags & SQLITE_InternChanges ){ sqliteResetInternalSchema(db, 0); } } /* ** This routine is called when a commit occurs. */ void sqliteCommitInternalChanges(sqlite *db){ ................................................................................ int isView /* True if this is a VIEW */ ){ Table *pTable; Index *pIdx; char *zName; sqlite *db = pParse->db; Vdbe *v; int iDb; pParse->sFirstToken = *pStart; zName = sqliteTableNameFromToken(pName); if( zName==0 ) return; if( pParse->iDb==1 ) isTemp = 1; #ifndef SQLITE_OMIT_AUTHORIZATION assert( (isTemp & 1)==isTemp ); ................................................................................ ** index or table name. Issue an error message if it does. ** ** If we are re-reading the sqlite_master table because of a schema ** change and a new permanent table is found whose name collides with ** an existing temporary table, that is not an error. */ pTable = sqliteFindTable(db, zName, 0); iDb = isTemp ? 1 : pParse->iDb; if( pTable!=0 && (pTable->iDb==iDb || !pParse->initFlag) ){ sqliteSetNString(&pParse->zErrMsg, "table ", 0, pName->z, pName->n, " already exists", 0, 0); sqliteFree(zName); pParse->nErr++; return; } if( (pIdx = sqliteFindIndex(db, zName, 0))!=0 && ................................................................................ return; } pTable->zName = zName; pTable->nCol = 0; pTable->aCol = 0; pTable->iPKey = -1; pTable->pIndex = 0; pTable->iDb = iDb; if( pParse->pNewTable ) sqliteDeleteTable(db, pParse->pNewTable); pParse->pNewTable = pTable; /* Begin generating the code that will insert the table record into ** the SQLITE_MASTER table. Note in particular that we must go ahead ** and allocate the record number for the table entry now. Before any ** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause ................................................................................ if( pTab==0 || pParse->nErr ) goto exit_create_index; if( pTab->readOnly ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not be indexed", 0); pParse->nErr++; goto exit_create_index; } if( !isTemp && pTab->iDb>=2 && pParse->initFlag==0 ){ sqliteSetString(&pParse->zErrMsg, "table ", pTab->zName, " may not have non-temporary indices added", 0); pParse->nErr++; goto exit_create_index; } if( pTab->pSelect ){ sqliteSetString(&pParse->zErrMsg, "views may not be indexed", 0); ................................................................................ pParse->nErr++; goto exit_create_index; } if( pTab->iDb==1 ){ isTemp = 1; } /* ** Find the name of the index. Make sure there is not already another ** index or table with the same name. ** ** Exception: If we are reading the names of permanent indices from the ** sqlite_master table (because some other process changed the schema) and ** one of the index names collides with the name of a temporary table or ................................................................................ */ void sqliteCodeVerifySchema(Parse *pParse){ int i; sqlite *db = pParse->db; Vdbe *v = sqliteGetVdbe(pParse); for(i=0; i<db->nDb; i++){ if( i==1 || db->aDb[i].pBt==0 ) continue; sqliteVdbeAddOp(v, OP_VerifyCookie, i, db->aDb[i].schema_cookie); } pParse->schemaVerified = 1; } /* ** Generate VDBE code that prepares for doing an operation that ** might change the database. ................................................................................ sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb); }else {} sqliteFree(zLeft); sqliteFree(zRight); } /* ** This routine is called by the parser to process an ATTACH statement: ** ** ATTACH DATABASE filename AS dbname ** ** The pFilename and pDbname arguments are the tokens that define the ** filename and dbname in the ATTACH statement. */ void sqliteAttach(Parse *pParse, Token *pFilename, Token *pDbname){ Db *aNew; int rc, i; char *zFile, *zName; sqlite *db; if( pParse->explain ) return; db = pParse->db; if( db->aDb==db->aDbStatic ){ aNew = sqliteMalloc( sizeof(db->aDb[0])*3 ); if( aNew==0 ) return; memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2); }else{ aNew = sqliteRealloc(db->aDb, sizeof(db->aDb[0])*(db->nDb+1) ); if( aNew==0 ) return; } db->aDb = aNew; aNew = &db->aDb[db->nDb++]; memset(aNew, 0, sizeof(*aNew)); sqliteHashInit(&aNew->tblHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&aNew->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&aNew->trigHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&aNew->aFKey, SQLITE_HASH_STRING, 1); zName = 0; sqliteSetNString(&zName, pDbname->z, pDbname->n, 0); if( zName==0 ) return; sqliteDequote(zName); for(i=0; i<db->nDb; i++){ if( db->aDb[i].zName && sqliteStrICmp(db->aDb[i].zName, zName)==0 ){ sqliteSetString(&pParse->zErrMsg, "database \"", zName, "\" already in use", 0); sqliteFree(zName); pParse->nErr++; return; } } aNew->zName = zName; zFile = 0; sqliteSetNString(&zFile, pFilename->z, pFilename->n, 0); if( zFile==0 ) return; sqliteDequote(zFile); rc = sqliteBtreeOpen(zFile, 0, MAX_PAGES, &aNew->pBt); if( rc ){ sqliteSetString(&pParse->zErrMsg, "unable to open database: ", zFile, 0); pParse->nErr++; } sqliteFree(zFile); db->flags &= ~SQLITE_Initialized; if( pParse->nErr ) return; rc = sqliteInit(pParse->db, &pParse->zErrMsg); if( rc ){ pParse->nErr++; } } /* ** This routine is called by the parser to process a DETACH statement: ** ** DETACH DATABASE dbname ** ** The pDbname argument is the name of the database in the DETACH statement. */ void sqliteDetach(Parse *pParse, Token *pDbname){ int i; sqlite *db; if( pParse->explain ) return; db = pParse->db; for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt==0 || db->aDb[i].zName==0 ) continue; if( strlen(db->aDb[i].zName)!=pDbname->n ) continue; if( sqliteStrNICmp(db->aDb[i].zName, pDbname->z, pDbname->n)==0 ) break; } if( i>=db->nDb ){ sqliteSetNString(&pParse->zErrMsg, "no such database: ", -1, pDbname->z, pDbname->n, 0); pParse->nErr++; return; } if( i<2 ){ sqliteSetString(&pParse->zErrMsg, "cannot detached \"main\" or \"temp\"",0); pParse->nErr++; return; } sqliteBtreeClose(db->aDb[i].pBt); db->aDb[i].pBt = 0; sqliteResetInternalSchema(db, 0); } |
Changes to src/main.c.
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 ... 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 ... 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 ... 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 ... 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 |
** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.118 2003/03/30 19:17:02 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information ................................................................................ ** ** Each callback contains the following information: ** ** argv[0] = "file-format" or "schema-cookie" or "table" or "index" ** argv[1] = table or index name or meta statement type. ** argv[2] = root page number for table or index. NULL for meta. ** argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement. ** argv[4] = "1" for temporary files, "0" for main database ** */ static int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; Parse sParse; int nErr = 0; ................................................................................ return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal ** data structures. Return one of the SQLITE_ error codes to ** indicate success or failure. ** ** After the database is initialized, the SQLITE_Initialized ** bit is set in the flags field of the sqlite structure. An ** attempt is made to initialize the database as soon as it ** is opened. If that fails (perhaps because another process ** has the sqlite_master table locked) than another attempt ** is made the first time the database is accessed. */ int sqliteInit(sqlite *db, char **pzErrMsg){ int rc; BtCursor *curMain; int size; Table *pTab; char *azArg[6]; int meta[SQLITE_N_BTREE_META]; Parse sParse; InitData initData; /* ** The master database table has a structure like this */ ................................................................................ "UNION ALL " "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " "WHERE type='table' " "UNION ALL " "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " "WHERE type='index'"; /* Construct the schema tables: sqlite_master and sqlite_temp_master */ azArg[0] = "table"; azArg[1] = MASTER_NAME; azArg[2] = "2"; azArg[3] = master_schema; azArg[4] = "0"; azArg[5] = 0; initData.db = db; initData.pzErrMsg = pzErrMsg; sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, MASTER_NAME, "main"); if( pTab ){ pTab->readOnly = 1; } azArg[1] = TEMP_MASTER_NAME; azArg[3] = temp_master_schema; azArg[4] = "1"; sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp"); if( pTab ){ pTab->readOnly = 1; } /* Create a cursor to hold the database open */ if( db->aDb[0].pBt==0 ) return SQLITE_OK; rc = sqliteBtreeCursor(db->aDb[0].pBt, 2, 0, &curMain); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); sqliteResetInternalSchema(db); return rc; } /* Get the database meta information */ rc = sqliteBtreeGetMeta(db->aDb[0].pBt, meta); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); sqliteResetInternalSchema(db); sqliteBtreeCloseCursor(curMain); return rc; } db->next_cookie = db->aDb[0].schema_cookie = meta[1]; db->file_format = meta[2]; size = meta[3]; if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; sqliteBtreeSetCacheSize(db->aDb[0].pBt, size); db->safety_level = meta[4]; if( db->safety_level==0 ) db->safety_level = 2; sqliteBtreeSetSafetyLevel(db->aDb[0].pBt, db->safety_level); /* ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. ** file_format==3 Version 2.6.0. Fix empty-string index bug. ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 4; }else if( db->file_format>4 ){ sqliteBtreeCloseCursor(curMain); sqliteSetString(pzErrMsg, "unsupported file format", 0); return SQLITE_ERROR; } /* Read the schema information out of the schema tables */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.xCallback = sqliteInitCallback; sParse.pArg = (void*)&initData; sParse.initFlag = 1; sParse.useCallback = 1; sqliteRunParser(&sParse, db->file_format>=2 ? init_script : older_init_script, pzErrMsg); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", 0); sParse.rc = SQLITE_NOMEM; sqliteBtreeRollback(db->aDb[0].pBt); sqliteResetInternalSchema(db); } if( sParse.rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqliteCommitInternalChanges(db); }else{ db->flags &= ~SQLITE_Initialized; sqliteResetInternalSchema(db); } sqliteBtreeCloseCursor(curMain); return sParse.rc; } /* ** The version of the library */ const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite_version[] = SQLITE_VERSION; ................................................................................ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return; } db->magic = SQLITE_MAGIC_CLOSED; for(j=0; j<db->nDb; j++){ if( db->aDb[j].pBt ){ sqliteBtreeClose(db->aDb[j].pBt); } if( j>=2 ){ sqliteFree(db->aDb[j].zName); } } if( db->aDb!=db->aDbStatic ){ sqliteFree(db->aDb); } sqliteResetInternalSchema(db); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqliteFree(pFunc); } } ................................................................................ if( db->xTrace ) db->xTrace(db->pTraceArg, zSql); #endif sqliteRunParser(&sParse, zSql, pzErrMsg); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", 0); sParse.rc = SQLITE_NOMEM; sqliteRollbackAll(db); sqliteResetInternalSchema(db); db->flags &= ~SQLITE_InTrans; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){ sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ sqliteResetInternalSchema(db); } if( sParse.useCallback==0 ){ assert( ppVm ); *ppVm = (sqlite_vm*)sParse.pVdbe; *pzTail = sParse.zTail; } if( sqliteSafetyOff(db) ) goto exec_misuse; |
| | > > > > | < < < < < < < < > > > > > | > | | | | | | | > | | < | < | > > | | | | < | | < | | | | | | | | | | | | | | | > > > > > > | > > > > | | | > > > > > > > > > < | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < | > > < < < | > > | | |
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 .. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 ... 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 ... 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 ... 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 ... 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 |
** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.119 2003/03/31 00:30:48 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information ................................................................................ ** ** Each callback contains the following information: ** ** argv[0] = "file-format" or "schema-cookie" or "table" or "index" ** argv[1] = table or index name or meta statement type. ** argv[2] = root page number for table or index. NULL for meta. ** argv[3] = SQL text for a CREATE TABLE or CREATE INDEX statement. ** argv[4] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. ** */ static int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; Parse sParse; int nErr = 0; ................................................................................ return rc!=SQLITE_OK; } /* ** Attempt to read the database schema and initialize internal ** data structures for a single database file. The index of the ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqliteInitOne(sqlite *db, int iDb, char **pzErrMsg){ int rc; BtCursor *curMain; int size; Table *pTab; char *azArg[6]; char zDbNum[30]; int meta[SQLITE_N_BTREE_META]; Parse sParse; InitData initData; /* ** The master database table has a structure like this */ ................................................................................ "UNION ALL " "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " "WHERE type='table' " "UNION ALL " "SELECT type, name, rootpage, sql, 0 FROM sqlite_master " "WHERE type='index'"; assert( iDb>=0 && iDb!=1 && iDb<db->nDb ); /* Construct the schema tables: sqlite_master and sqlite_temp_master */ azArg[0] = "table"; azArg[1] = MASTER_NAME; azArg[2] = "2"; azArg[3] = master_schema; sprintf(zDbNum, "%d", iDb); azArg[4] = zDbNum; azArg[5] = 0; initData.db = db; initData.pzErrMsg = pzErrMsg; sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, MASTER_NAME, "main"); if( pTab ){ pTab->readOnly = 1; } if( iDb==0 ){ azArg[1] = TEMP_MASTER_NAME; azArg[3] = temp_master_schema; azArg[4] = "1"; sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, TEMP_MASTER_NAME, "temp"); if( pTab ){ pTab->readOnly = 1; } } /* Create a cursor to hold the database open */ if( db->aDb[iDb].pBt==0 ) return SQLITE_OK; rc = sqliteBtreeCursor(db->aDb[iDb].pBt, 2, 0, &curMain); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); return rc; } /* Get the database meta information */ rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta); if( rc ){ sqliteSetString(pzErrMsg, sqlite_error_string(rc), 0); sqliteBtreeCloseCursor(curMain); return rc; } db->aDb[iDb].schema_cookie = meta[1]; if( iDb==0 ){ db->next_cookie = meta[1]; db->file_format = meta[2]; size = meta[3]; if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; db->safety_level = meta[4]; if( db->safety_level==0 ) db->safety_level = 2; /* ** file_format==1 Version 2.1.0. ** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY. ** file_format==3 Version 2.6.0. Fix empty-string index bug. ** file_format==4 Version 2.7.0. Add support for separate numeric and ** text datatypes. */ if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 4; }else if( db->file_format>4 ){ sqliteBtreeCloseCursor(curMain); sqliteSetString(pzErrMsg, "unsupported file format", 0); return SQLITE_ERROR; } }else if( db->file_format<4 || db->file_format!=meta[2] ){ sqliteSetString(pzErrMsg, "incompatible file format in auxiliary " "database \"", db->aDb[iDb].zName, "\"", 0); sqliteBtreeClose(db->aDb[iDb].pBt); db->aDb[iDb].pBt = 0; return SQLITE_FORMAT; } sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, size); sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]); /* Read the schema information out of the schema tables */ memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sParse.xCallback = sqliteInitCallback; sParse.pArg = (void*)&initData; sParse.initFlag = 1; sParse.useCallback = 1; if( iDb==0 ){ sqliteRunParser(&sParse, db->file_format>=2 ? init_script : older_init_script, pzErrMsg); }else{ char *zSql = 0; sqliteSetString(&zSql, "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"", db->aDb[iDb].zName, "\".sqlite_master", 0); sqliteRunParser(&sParse, zSql, pzErrMsg); sqliteFree(zSql); } sqliteBtreeCloseCursor(curMain); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", 0); sParse.rc = SQLITE_NOMEM; sqliteResetInternalSchema(db, 0); } if( sParse.rc==SQLITE_OK ){ db->aDb[iDb].flags |= SQLITE_Initialized; }else{ sqliteResetInternalSchema(db, iDb); } return sParse.rc; } /* ** Initialize all database files - the main database file, the file ** used to store temporary tables, and any additional database files ** created using ATTACH statements. Return a success code. If an ** error occurs, write an error message into *pzErrMsg. ** ** After the database is initialized, the SQLITE_Initialized ** bit is set in the flags field of the sqlite structure. An ** attempt is made to initialize the database as soon as it ** is opened. If that fails (perhaps because another process ** has the sqlite_master table locked) than another attempt ** is made the first time the database is accessed. */ int sqliteInit(sqlite *db, char **pzErrMsg){ int i, rc; assert( (db->flags & SQLITE_Initialized)==0 ); rc = SQLITE_OK; for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ if( db->aDb[i].flags & SQLITE_Initialized ) continue; if( i==1 ) continue; /* Skip the temp database - initialized with 0 */ rc = sqliteInitOne(db, i, pzErrMsg); } if( rc==SQLITE_OK ){ db->flags |= SQLITE_Initialized; sqliteCommitInternalChanges(db); }else{ db->flags &= ~SQLITE_Initialized; } return rc; } /* ** The version of the library */ const char rcsid[] = "@(#) \044Id: SQLite version " SQLITE_VERSION " $"; const char sqlite_version[] = SQLITE_VERSION; ................................................................................ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ return; } db->magic = SQLITE_MAGIC_CLOSED; for(j=0; j<db->nDb; j++){ if( db->aDb[j].pBt ){ sqliteBtreeClose(db->aDb[j].pBt); db->aDb[j].pBt = 0; } if( j>=2 ){ sqliteFree(db->aDb[j].zName); db->aDb[j].zName = 0; } } sqliteResetInternalSchema(db, 0); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqliteFree(pFunc); } } ................................................................................ if( db->xTrace ) db->xTrace(db->pTraceArg, zSql); #endif sqliteRunParser(&sParse, zSql, pzErrMsg); if( sqlite_malloc_failed ){ sqliteSetString(pzErrMsg, "out of memory", 0); sParse.rc = SQLITE_NOMEM; sqliteRollbackAll(db); sqliteResetInternalSchema(db, 0); db->flags &= ~SQLITE_InTrans; } if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK; if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){ sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0); } sqliteStrRealloc(pzErrMsg); if( sParse.rc==SQLITE_SCHEMA ){ sqliteResetInternalSchema(db, 0); } if( sParse.useCallback==0 ){ assert( ppVm ); *ppVm = (sqlite_vm*)sParse.pVdbe; *pzTail = sParse.zTail; } if( sqliteSafetyOff(db) ) goto exec_misuse; |
Changes to src/parse.y.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
|
** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.93 2003/03/27 12:51:25 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ ................................................................................ A = sqliteExpr(TK_RAISE, 0, 0, &Z); A->iColumn = OE_Fail; sqliteExprSpan(A, &X, &Y); } //////////////////////// DROP TRIGGER statement ////////////////////////////// cmd ::= DROP TRIGGER nm(X) dbnm(D). { sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0); } //////////////////////// ATTACH DATABASE file AS name ///////////////////////// cmd ::= ATTACH database_kw_opt ids AS nm. database_kw_opt ::= DATABASE. database_kw_opt ::= . //////////////////////// DETACH DATABASE name ///////////////////////////////// cmd ::= DETACH database_kw_opt nm. |
|
|
|
>
>
|
>
>
|
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
|
** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.94 2003/03/31 00:30:48 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ ................................................................................ A = sqliteExpr(TK_RAISE, 0, 0, &Z); A->iColumn = OE_Fail; sqliteExprSpan(A, &X, &Y); } //////////////////////// DROP TRIGGER statement ////////////////////////////// cmd ::= DROP TRIGGER nm(X) dbnm(D). { sqliteDropTrigger(pParse,sqliteSrcListAppend(0,&X,&D),0); } //////////////////////// ATTACH DATABASE file AS name ///////////////////////// cmd ::= ATTACH database_kw_opt ids(F) AS nm(D). { sqliteAttach(pParse, &F, &D); } database_kw_opt ::= DATABASE. database_kw_opt ::= . //////////////////////// DETACH DATABASE name ///////////////////////////////// cmd ::= DETACH database_kw_opt nm(D). { sqliteDetach(pParse, &D); } |
Changes to src/sqlite.h.in.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.42 2003/03/30 19:17:03 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. ................................................................................ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */ /* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, ** otherwise the key is generated at random. The unique key is always |
|
>
|
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
|
** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.43 2003/03/31 00:30:49 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** Make sure we can call this stuff from C++. ................................................................................ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ #define SQLITE_MISUSE 21 /* Library used incorrectly */ #define SQLITE_NOLFS 22 /* Uses OS features not supported on host */ #define SQLITE_AUTH 23 /* Authorization denied */ #define SQLITE_FORMAT 24 /* Auxiliary database format error */ #define SQLITE_ROW 100 /* sqlite_step() has another row ready */ #define SQLITE_DONE 101 /* sqlite_step() has finished executing */ /* ** Each entry in an SQLite table has a unique integer key. (The key is ** the value of the INTEGER PRIMARY KEY column if there is such a column, ** otherwise the key is generated at random. The unique key is always |
Changes to src/sqliteInt.h.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 .... 1078 1079 1080 1081 1082 1083 1084 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.166 2003/03/27 13:50:00 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" ................................................................................ void sqliteExec(Parse*); Expr *sqliteExpr(int, Expr*, Expr*, Token*); void sqliteExprSpan(Expr*,Token*,Token*); Expr *sqliteExprFunction(ExprList*, Token*); void sqliteExprDelete(Expr*); ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*); void sqliteExprListDelete(ExprList*); void sqlitePragma(Parse*,Token*,Token*,int); void sqliteResetInternalSchema(sqlite*); int sqliteInit(sqlite*, char**); void sqliteBeginParse(Parse*,int); void sqliteRollbackInternalChanges(sqlite*); void sqliteCommitInternalChanges(sqlite*); Table *sqliteResultSetOfSelect(Parse*,char*,Select*); void sqliteOpenMasterTable(Vdbe *v, int); void sqliteStartTable(Parse*,Token*,Token*,int,int); void sqliteAddColumn(Parse*,Token*); ................................................................................ #ifndef SQLITE_OMIT_AUTHORIZATION void sqliteAuthRead(Parse*,Expr*,SrcList*,int); int sqliteAuthCheck(Parse*,int, const char*, const char*); #else # define sqliteAuthRead(a,b,c,d) # define sqliteAuthCheck(a,b,c,d) SQLITE_OK #endif |
| > | < > > |
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ... 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 .... 1078 1079 1080 1081 1082 1083 1084 1085 1086 |
** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.167 2003/03/31 00:30:49 drh Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" ................................................................................ void sqliteExec(Parse*); Expr *sqliteExpr(int, Expr*, Expr*, Token*); void sqliteExprSpan(Expr*,Token*,Token*); Expr *sqliteExprFunction(ExprList*, Token*); void sqliteExprDelete(Expr*); ExprList *sqliteExprListAppend(ExprList*,Expr*,Token*); void sqliteExprListDelete(ExprList*); int sqliteInit(sqlite*, char**); void sqlitePragma(Parse*,Token*,Token*,int); void sqliteResetInternalSchema(sqlite*, int); void sqliteBeginParse(Parse*,int); void sqliteRollbackInternalChanges(sqlite*); void sqliteCommitInternalChanges(sqlite*); Table *sqliteResultSetOfSelect(Parse*,char*,Select*); void sqliteOpenMasterTable(Vdbe *v, int); void sqliteStartTable(Parse*,Token*,Token*,int,int); void sqliteAddColumn(Parse*,Token*); ................................................................................ #ifndef SQLITE_OMIT_AUTHORIZATION void sqliteAuthRead(Parse*,Expr*,SrcList*,int); int sqliteAuthCheck(Parse*,int, const char*, const char*); #else # define sqliteAuthRead(a,b,c,d) # define sqliteAuthCheck(a,b,c,d) SQLITE_OK #endif void sqliteAttach(Parse*, Token*, Token*); void sqliteDetach(Parse*, Token*); |