⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*** 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.***************************************************************************** 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.164.2.2 2004/06/26 14:40:05 drh Exp $*/#include "sqliteInt.h"#include "os.h"#include <ctype.h>/*** A pointer to this structure is used to communicate information** from sqliteInit into the sqliteInitCallback.*/typedef struct {  sqlite *db;         /* The database being initialized */  char **pzErrMsg;    /* Error message stored here */} InitData;/*** Fill the InitData structure with an error message that indicates** that the database is corrupt.*/static void corruptSchema(InitData *pData, const char *zExtra){  sqliteSetString(pData->pzErrMsg, "malformed database schema",     zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);}/*** This is the callback routine for the code that initializes the** database.  See sqliteInit() below for additional 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.***/staticint sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){  InitData *pData = (InitData*)pInit;  int nErr = 0;  assert( argc==5 );  if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */  if( argv[0]==0 ){    corruptSchema(pData, 0);    return 1;  }  switch( argv[0][0] ){    case 'v':    case 'i':    case 't': {  /* CREATE TABLE, CREATE INDEX, or CREATE VIEW statements */      sqlite *db = pData->db;      if( argv[2]==0 || argv[4]==0 ){        corruptSchema(pData, 0);        return 1;      }      if( argv[3] && argv[3][0] ){        /* Call the parser to process a CREATE TABLE, INDEX or VIEW.        ** But because db->init.busy is set to 1, no VDBE code is generated        ** or executed.  All the parser does is build the internal data        ** structures that describe the table, index, or view.        */        char *zErr;        assert( db->init.busy );        db->init.iDb = atoi(argv[4]);        assert( db->init.iDb>=0 && db->init.iDb<db->nDb );        db->init.newTnum = atoi(argv[2]);        if( sqlite_exec(db, argv[3], 0, 0, &zErr) ){          corruptSchema(pData, zErr);          sqlite_freemem(zErr);        }        db->init.iDb = 0;      }else{        /* If the SQL column is blank it means this is an index that        ** was created to be the PRIMARY KEY or to fulfill a UNIQUE        ** constraint for a CREATE TABLE.  The index should have already        ** been created when we processed the CREATE TABLE.  All we have        ** to do here is record the root page number for that index.        */        int iDb;        Index *pIndex;        iDb = atoi(argv[4]);        assert( iDb>=0 && iDb<db->nDb );        pIndex = sqliteFindIndex(db, argv[1], db->aDb[iDb].zName);        if( pIndex==0 || pIndex->tnum!=0 ){          /* This can occur if there exists an index on a TEMP table which          ** has the same name as another index on a permanent index.  Since          ** the permanent table is hidden by the TEMP table, we can also          ** safely ignore the index on the permanent table.          */          /* Do Nothing */;        }else{          pIndex->tnum = atoi(argv[2]);        }      }      break;    }    default: {      /* This can not happen! */      nErr = 1;      assert( nErr==0 );    }  }  return nErr;}/*** This is a callback procedure used to reconstruct a table.  The** name of the table to be reconstructed is passed in as argv[0].**** This routine is used to automatically upgrade a database from** format version 1 or 2 to version 3.  The correct operation of** this routine relys on the fact that no indices are used when** copying a table out to a temporary file.**** The change from version 2 to version 3 occurred between SQLite** version 2.5.6 and 2.6.0 on 2002-July-18.  */staticint upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){  InitData *pData = (InitData*)pInit;  int rc;  Table *pTab;  Trigger *pTrig;  char *zErr = 0;  pTab = sqliteFindTable(pData->db, argv[0], 0);  assert( pTab!=0 );  assert( sqliteStrICmp(pTab->zName, argv[0])==0 );  if( pTab ){    pTrig = pTab->pTrigger;    pTab->pTrigger = 0;  /* Disable all triggers before rebuilding the table */  }  rc = sqlite_exec_printf(pData->db,    "CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "    "DELETE FROM '%q'; "    "INSERT INTO '%q' SELECT * FROM sqlite_x; "    "DROP TABLE sqlite_x;",    0, 0, &zErr, argv[0], argv[0], argv[0]);  if( zErr ){    if( *pData->pzErrMsg ) sqlite_freemem(*pData->pzErrMsg);    *pData->pzErrMsg = zErr;  }  /* If an error occurred in the SQL above, then the transaction will  ** rollback which will delete the internal symbol tables.  This will  ** cause the structure that pTab points to be deleted.  In case that  ** happened, we need to refetch pTab.  */  pTab = sqliteFindTable(pData->db, argv[0], 0);  if( pTab ){    assert( sqliteStrICmp(pTab->zName, argv[0])==0 );    pTab->pTrigger = pTrig;  /* Re-enable triggers */  }  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 const *azArg[6];  char zDbNum[30];  int meta[SQLITE_N_BTREE_META];  InitData initData;  char const *zMasterSchema;  char const *zMasterName;  char *zSql = 0;  /*  ** The master database table has a structure like this  */  static char master_schema[] =      "CREATE TABLE sqlite_master(\n"     "  type text,\n"     "  name text,\n"     "  tbl_name text,\n"     "  rootpage integer,\n"     "  sql text\n"     ")"  ;  static char temp_master_schema[] =      "CREATE TEMP TABLE sqlite_temp_master(\n"     "  type text,\n"     "  name text,\n"     "  tbl_name text,\n"     "  rootpage integer,\n"     "  sql text\n"     ")"  ;  assert( iDb>=0 && iDb<db->nDb );  /* zMasterSchema and zInitScript are set to point at the master schema  ** and initialisation script appropriate for the database being  ** initialised. zMasterName is the name of the master table.  */  if( iDb==1 ){    zMasterSchema = temp_master_schema;    zMasterName = TEMP_MASTER_NAME;  }else{    zMasterSchema = master_schema;    zMasterName = MASTER_NAME;  }  /* Construct the schema table.  */  sqliteSafetyOff(db);  azArg[0] = "table";  azArg[1] = zMasterName;  azArg[2] = "2";  azArg[3] = zMasterSchema;  sprintf(zDbNum, "%d", iDb);  azArg[4] = zDbNum;  azArg[5] = 0;  initData.db = db;  initData.pzErrMsg = pzErrMsg;  sqliteInitCallback(&initData, 5, (char **)azArg, 0);  pTab = sqliteFindTable(db, zMasterName, db->aDb[iDb].zName);  if( pTab ){    pTab->readOnly = 1;  }else{    return SQLITE_NOMEM;  }  sqliteSafetyOn(db);  /* 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), (char*)0);    return rc;  }  /* Get the database meta information  */  rc = sqliteBtreeGetMeta(db->aDb[iDb].pBt, meta);  if( rc ){    sqliteSetString(pzErrMsg, sqlite_error_string(rc), (char*)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( meta[6]>0 && meta[6]<=2 && db->temp_store==0 ){      db->temp_store = meta[6];    }    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", (char*)0);      return SQLITE_ERROR;    }  }else if( iDb!=1 && (db->file_format!=meta[2] || db->file_format<4) ){    assert( db->file_format>=4 );    if( meta[2]==0 ){      sqliteSetString(pzErrMsg, "cannot attach empty database: ",         db->aDb[iDb].zName, (char*)0);    }else{      sqliteSetString(pzErrMsg, "incompatible file format in auxiliary "         "database: ", db->aDb[iDb].zName, (char*)0);    }    sqliteBtreeClose(db->aDb[iDb].pBt);    db->aDb[iDb].pBt = 0;    return SQLITE_FORMAT;  }  sqliteBtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size);  sqliteBtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[4]==0 ? 2 : meta[4]);  /* Read the schema information out of the schema tables  */  assert( db->init.busy );  sqliteSafetyOff(db);  /* The following SQL will read the schema from the master tables.  ** The first version works with SQLite file formats 2 or greater.  ** The second version is for format 1 files.  **  ** Beginning with file format 2, the rowid for new table entries  ** (including entries in sqlite_master) is an increasing integer.  ** So for file format 2 and later, we can play back sqlite_master  ** and all the CREATE statements will appear in the right order.  ** But with file format 1, table entries were random and so we  ** have to make sure the CREATE TABLEs occur before their corresponding  ** CREATE INDEXs.  (We don't have to deal with CREATE VIEW or  ** CREATE TRIGGER in file format 1 because those constructs did  ** not exist then.)   */  if( db->file_format>=2 ){    sqliteSetString(&zSql,         "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",       db->aDb[iDb].zName, "\".", zMasterName, (char*)0);  }else{    sqliteSetString(&zSql,         "SELECT type, name, rootpage, sql, ", zDbNum, " FROM \"",       db->aDb[iDb].zName, "\".", zMasterName,        " WHERE type IN ('table', 'index')"       " ORDER BY CASE type WHEN 'table' THEN 0 ELSE 1 END", (char*)0);  }  rc = sqlite_exec(db, zSql, sqliteInitCallback, &initData, 0);  sqliteFree(zSql);  sqliteSafetyOn(db);  sqliteBtreeCloseCursor(curMain);  if( sqlite_malloc_failed ){    sqliteSetString(pzErrMsg, "out of memory", (char*)0);    rc = SQLITE_NOMEM;    sqliteResetInternalSchema(db, 0);  }  if( rc==SQLITE_OK ){    DbSetProperty(db, iDb, DB_SchemaLoaded);  }else{    sqliteResetInternalSchema(db, iDb);  }  return 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;    if( db->init.busy ) return SQLITE_OK;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -