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

📄 attach.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*** 2003 April 6**** 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.***************************************************************************** This file contains code used to implement the ATTACH and DETACH commands.**** $Id: attach.c,v 1.78 2008/08/20 16:35:10 drh Exp $*/#include "sqliteInt.h"#ifndef SQLITE_OMIT_ATTACH/*** Resolve an expression that was part of an ATTACH or DETACH statement. This** is slightly different from resolving a normal SQL expression, because simple** identifiers are treated as strings, not possible column names or aliases.**** i.e. if the parser sees:****     ATTACH DATABASE abc AS def**** it treats the two expressions as literal strings 'abc' and 'def' instead of** looking for columns of the same name.**** This only applies to the root node of pExpr, so the statement:****     ATTACH DATABASE abc||def AS 'db2'**** will fail because neither abc or def can be resolved.*/static int resolveAttachExpr(NameContext *pName, Expr *pExpr){  int rc = SQLITE_OK;  if( pExpr ){    if( pExpr->op!=TK_ID ){      rc = sqlite3ResolveExprNames(pName, pExpr);      if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){        sqlite3ErrorMsg(pName->pParse, "invalid name: \"%T\"", &pExpr->span);        return SQLITE_ERROR;      }    }else{      pExpr->op = TK_STRING;    }  }  return rc;}/*** An SQL user-function registered to do the work of an ATTACH statement. The** three arguments to the function come directly from an attach statement:****     ATTACH DATABASE x AS y KEY z****     SELECT sqlite_attach(x, y, z)**** If the optional "KEY z" syntax is omitted, an SQL NULL is passed as the** third argument.*/static void attachFunc(  sqlite3_context *context,  int argc,  sqlite3_value **argv){  int i;  int rc = 0;  sqlite3 *db = sqlite3_context_db_handle(context);  const char *zName;  const char *zFile;  Db *aNew;  char *zErrDyn = 0;  char zErr[128];  zFile = (const char *)sqlite3_value_text(argv[0]);  zName = (const char *)sqlite3_value_text(argv[1]);  if( zFile==0 ) zFile = "";  if( zName==0 ) zName = "";  /* Check for the following errors:  **  **     * Too many attached databases,  **     * Transaction currently open  **     * Specified database name already being used.  */  if( db->nDb>=db->aLimit[SQLITE_LIMIT_ATTACHED]+2 ){    sqlite3_snprintf(      sizeof(zErr), zErr, "too many attached databases - max %d",       db->aLimit[SQLITE_LIMIT_ATTACHED]    );    goto attach_error;  }  if( !db->autoCommit ){    sqlite3_snprintf(sizeof(zErr), zErr,                     "cannot ATTACH database within transaction");    goto attach_error;  }  for(i=0; i<db->nDb; i++){    char *z = db->aDb[i].zName;    if( z && zName && sqlite3StrICmp(z, zName)==0 ){      sqlite3_snprintf(sizeof(zErr), zErr,                        "database %s is already in use", zName);      goto attach_error;    }  }  /* Allocate the new entry in the db->aDb[] array and initialise the schema  ** hash tables.  */  if( db->aDb==db->aDbStatic ){    aNew = sqlite3DbMallocRaw(db, sizeof(db->aDb[0])*3 );    if( aNew==0 ) return;    memcpy(aNew, db->aDb, sizeof(db->aDb[0])*2);  }else{    aNew = sqlite3DbRealloc(db, 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));  /* Open the database file. If the btree is successfully opened, use  ** it to obtain the database schema. At this point the schema may  ** or may not be initialised.  */  rc = sqlite3BtreeFactory(db, zFile, 0, SQLITE_DEFAULT_CACHE_SIZE,                           db->openFlags | SQLITE_OPEN_MAIN_DB,                           &aNew->pBt);  if( rc==SQLITE_OK ){    Pager *pPager;    aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);    if( !aNew->pSchema ){      rc = SQLITE_NOMEM;    }else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){      sqlite3_snprintf(sizeof(zErr), zErr,         "attached databases must use the same text encoding as main database");      goto attach_error;    }    pPager = sqlite3BtreePager(aNew->pBt);    sqlite3PagerLockingMode(pPager, db->dfltLockMode);    sqlite3PagerJournalMode(pPager, db->dfltJournalMode);  }  aNew->zName = sqlite3DbStrDup(db, zName);  aNew->safety_level = 3;#if SQLITE_HAS_CODEC  {    extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);    extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);    int nKey;    char *zKey;    int t = sqlite3_value_type(argv[2]);    switch( t ){      case SQLITE_INTEGER:      case SQLITE_FLOAT:        zErrDyn = sqlite3DbStrDup(db, "Invalid key value");        rc = SQLITE_ERROR;        break;              case SQLITE_TEXT:      case SQLITE_BLOB:        nKey = sqlite3_value_bytes(argv[2]);        zKey = (char *)sqlite3_value_blob(argv[2]);        sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);        break;      case SQLITE_NULL:        /* No key specified.  Use the key from the main database */        sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);        sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);        break;    }  }#endif  /* If the file was opened successfully, read the schema for the new database.  ** If this fails, or if opening the file failed, then close the file and   ** remove the entry from the db->aDb[] array. i.e. put everything back the way  ** we found it.  */  if( rc==SQLITE_OK ){    (void)sqlite3SafetyOn(db);    sqlite3BtreeEnterAll(db);    rc = sqlite3Init(db, &zErrDyn);    sqlite3BtreeLeaveAll(db);    (void)sqlite3SafetyOff(db);  }  if( rc ){    int iDb = db->nDb - 1;    assert( iDb>=2 );    if( db->aDb[iDb].pBt ){      sqlite3BtreeClose(db->aDb[iDb].pBt);      db->aDb[iDb].pBt = 0;      db->aDb[iDb].pSchema = 0;    }    sqlite3ResetInternalSchema(db, 0);    db->nDb = iDb;    if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){      db->mallocFailed = 1;      sqlite3_snprintf(sizeof(zErr),zErr, "out of memory");    }else{      sqlite3_snprintf(sizeof(zErr),zErr, "unable to open database: %s", zFile);    }    goto attach_error;  }    return;attach_error:  /* Return an error if we get here */  if( zErrDyn ){    sqlite3_result_error(context, zErrDyn, -1);    sqlite3DbFree(db, zErrDyn);  }else{    zErr[sizeof(zErr)-1] = 0;    sqlite3_result_error(context, zErr, -1);  }  if( rc ) sqlite3_result_error_code(context, rc);}/*** An SQL user-function registered to do the work of an DETACH statement. The** three arguments to the function come directly from a detach statement:****     DETACH DATABASE x****     SELECT sqlite_detach(x)*/static void detachFunc(  sqlite3_context *context,  int argc,  sqlite3_value **argv){  const char *zName = (const char *)sqlite3_value_text(argv[0]);  sqlite3 *db = sqlite3_context_db_handle(context);  int i;  Db *pDb = 0;  char zErr[128];  if( zName==0 ) zName = "";  for(i=0; i<db->nDb; i++){    pDb = &db->aDb[i];    if( pDb->pBt==0 ) continue;    if( sqlite3StrICmp(pDb->zName, zName)==0 ) break;  }  if( i>=db->nDb ){    sqlite3_snprintf(sizeof(zErr),zErr, "no such database: %s", zName);    goto detach_error;  }  if( i<2 ){    sqlite3_snprintf(sizeof(zErr),zErr, "cannot detach database %s", zName);    goto detach_error;  }  if( !db->autoCommit ){    sqlite3_snprintf(sizeof(zErr), zErr,                     "cannot DETACH database within transaction");    goto detach_error;  }

⌨️ 快捷键说明

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