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

📄 tclsqlite.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
  ** This code is basically an implementation/enhancement of  ** the sqlite3 shell.c ".import" command.  **  ** This command usage is equivalent to the sqlite2.x COPY statement,  ** which imports file data into a table using the PostgreSQL COPY file format:  **   $db copy $conflit_algo $table_name $filename \t \\N  */  case DB_COPY: {    char *zTable;               /* Insert data into this table */    char *zFile;                /* The file from which to extract data */    char *zConflict;            /* The conflict algorithm to use */    sqlite3_stmt *pStmt;        /* A statement */    int rc;                     /* Result code */    int nCol;                   /* Number of columns in the table */    int nByte;                  /* Number of bytes in an SQL string */    int i, j;                   /* Loop counters */    int nSep;                   /* Number of bytes in zSep[] */    int nNull;                  /* Number of bytes in zNull[] */    char *zSql;                 /* An SQL statement */    char *zLine;                /* A single line of input from the file */    char **azCol;               /* zLine[] broken up into columns */    char *zCommit;              /* How to commit changes */    FILE *in;                   /* The input file */    int lineno = 0;             /* Line number of input file */    char zLineNum[80];          /* Line number print buffer */    Tcl_Obj *pResult;           /* interp result */    char *zSep;    char *zNull;    if( objc<5 || objc>7 ){      Tcl_WrongNumArgs(interp, 2, objv,          "CONFLICT-ALGORITHM TABLE FILENAME ?SEPARATOR? ?NULLINDICATOR?");      return TCL_ERROR;    }    if( objc>=6 ){      zSep = Tcl_GetStringFromObj(objv[5], 0);    }else{      zSep = "\t";    }    if( objc>=7 ){      zNull = Tcl_GetStringFromObj(objv[6], 0);    }else{      zNull = "";    }    zConflict = Tcl_GetStringFromObj(objv[2], 0);    zTable = Tcl_GetStringFromObj(objv[3], 0);    zFile = Tcl_GetStringFromObj(objv[4], 0);    nSep = strlen(zSep);    nNull = strlen(zNull);    if( nSep==0 ){      Tcl_AppendResult(interp, "Error: non-null separator required for copy", 0);      return TCL_ERROR;    }    if(sqlite3StrICmp(zConflict, "rollback") != 0 &&       sqlite3StrICmp(zConflict, "abort"   ) != 0 &&       sqlite3StrICmp(zConflict, "fail"    ) != 0 &&       sqlite3StrICmp(zConflict, "ignore"  ) != 0 &&       sqlite3StrICmp(zConflict, "replace" ) != 0 ) {      Tcl_AppendResult(interp, "Error: \"", zConflict,             "\", conflict-algorithm must be one of: rollback, "            "abort, fail, ignore, or replace", 0);      return TCL_ERROR;    }    zSql = sqlite3_mprintf("SELECT * FROM '%q'", zTable);    if( zSql==0 ){      Tcl_AppendResult(interp, "Error: no such table: ", zTable, 0);      return TCL_ERROR;    }    nByte = strlen(zSql);    rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);    sqlite3_free(zSql);    if( rc ){      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);      nCol = 0;    }else{      nCol = sqlite3_column_count(pStmt);    }    sqlite3_finalize(pStmt);    if( nCol==0 ) {      return TCL_ERROR;    }    zSql = malloc( nByte + 50 + nCol*2 );    if( zSql==0 ) {      Tcl_AppendResult(interp, "Error: can't malloc()", 0);      return TCL_ERROR;    }    sqlite3_snprintf(nByte+50, zSql, "INSERT OR %q INTO '%q' VALUES(?",         zConflict, zTable);    j = strlen(zSql);    for(i=1; i<nCol; i++){      zSql[j++] = ',';      zSql[j++] = '?';    }    zSql[j++] = ')';    zSql[j] = 0;    rc = sqlite3_prepare(pDb->db, zSql, 0, &pStmt, 0);    free(zSql);    if( rc ){      Tcl_AppendResult(interp, "Error: ", sqlite3_errmsg(pDb->db), 0);      sqlite3_finalize(pStmt);      return TCL_ERROR;    }    in = fopen(zFile, "rb");    if( in==0 ){      Tcl_AppendResult(interp, "Error: cannot open file: ", zFile, NULL);      sqlite3_finalize(pStmt);      return TCL_ERROR;    }    azCol = malloc( sizeof(azCol[0])*(nCol+1) );    if( azCol==0 ) {      Tcl_AppendResult(interp, "Error: can't malloc()", 0);      return TCL_ERROR;    }    sqlite3_exec(pDb->db, "BEGIN", 0, 0, 0);    zCommit = "COMMIT";    while( (zLine = local_getline(0, in))!=0 ){      char *z;      i = 0;      lineno++;      azCol[0] = zLine;      for(i=0, z=zLine; *z; z++){        if( *z==zSep[0] && strncmp(z, zSep, nSep)==0 ){          *z = 0;          i++;          if( i<nCol ){            azCol[i] = &z[nSep];            z += nSep-1;          }        }      }      if( i+1!=nCol ){        char *zErr;        zErr = malloc(200 + strlen(zFile));        sprintf(zErr,"Error: %s line %d: expected %d columns of data but found %d",           zFile, lineno, nCol, i+1);        Tcl_AppendResult(interp, zErr, 0);        free(zErr);        zCommit = "ROLLBACK";        break;      }      for(i=0; i<nCol; i++){        /* check for null data, if so, bind as null */        if ((nNull>0 && strcmp(azCol[i], zNull)==0) || strlen(azCol[i])==0) {          sqlite3_bind_null(pStmt, i+1);        }else{          sqlite3_bind_text(pStmt, i+1, azCol[i], -1, SQLITE_STATIC);        }      }      sqlite3_step(pStmt);      rc = sqlite3_reset(pStmt);      free(zLine);      if( rc!=SQLITE_OK ){        Tcl_AppendResult(interp,"Error: ", sqlite3_errmsg(pDb->db), 0);        zCommit = "ROLLBACK";        break;      }    }    free(azCol);    fclose(in);    sqlite3_finalize(pStmt);    sqlite3_exec(pDb->db, zCommit, 0, 0, 0);    if( zCommit[0] == 'C' ){      /* success, set result as number of lines processed */      pResult = Tcl_GetObjResult(interp);      Tcl_SetIntObj(pResult, lineno);      rc = TCL_OK;    }else{      /* failure, append lineno where failed */      sprintf(zLineNum,"%d",lineno);      Tcl_AppendResult(interp,", failed while processing line: ",zLineNum,0);      rc = TCL_ERROR;    }    break;  }  /*    $db version  **  ** Return the version string for this database.  */  case DB_VERSION: {    Tcl_SetResult(interp, (char *)sqlite3_libversion(), TCL_STATIC);    break;  }  } /* End of the SWITCH statement */  return rc;}/***   sqlite3 DBNAME FILENAME ?MODE? ?-key KEY?**** This is the main Tcl command.  When the "sqlite" Tcl command is** invoked, this routine runs to process that command.**** The first argument, DBNAME, is an arbitrary name for a new** database connection.  This command creates a new command named** DBNAME that is used to control that connection.  The database** connection is deleted when the DBNAME command is deleted.**** The second argument is the name of the directory that contains** the sqlite database that is to be accessed.**** For testing purposes, we also support the following:****  sqlite3 -encoding****       Return the encoding used by LIKE and GLOB operators.  Choices**       are UTF-8 and iso8859.****  sqlite3 -version****       Return the version number of the SQLite library.****  sqlite3 -tcl-uses-utf****       Return "1" if compiled with a Tcl uses UTF-8.  Return "0" if**       not.  Used by tests to make sure the library was compiled **       correctly.*/static int DbMain(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){  SqliteDb *p;  void *pKey = 0;  int nKey = 0;  const char *zArg;  char *zErrMsg;  const char *zFile;  char zBuf[80];  if( objc==2 ){    zArg = Tcl_GetStringFromObj(objv[1], 0);    if( strcmp(zArg,"-version")==0 ){      Tcl_AppendResult(interp,sqlite3_version,0);      return TCL_OK;    }    if( strcmp(zArg,"-has-codec")==0 ){#ifdef SQLITE_HAS_CODEC      Tcl_AppendResult(interp,"1",0);#else      Tcl_AppendResult(interp,"0",0);#endif      return TCL_OK;    }    if( strcmp(zArg,"-tcl-uses-utf")==0 ){#ifdef TCL_UTF_MAX      Tcl_AppendResult(interp,"1",0);#else      Tcl_AppendResult(interp,"0",0);#endif      return TCL_OK;    }  }  if( objc==5 || objc==6 ){    zArg = Tcl_GetStringFromObj(objv[objc-2], 0);    if( strcmp(zArg,"-key")==0 ){      pKey = Tcl_GetByteArrayFromObj(objv[objc-1], &nKey);      objc -= 2;    }  }  if( objc!=3 && objc!=4 ){    Tcl_WrongNumArgs(interp, 1, objv, #ifdef SQLITE_HAS_CODEC      "HANDLE FILENAME ?-key CODEC-KEY?"#else      "HANDLE FILENAME ?MODE?"#endif    );    return TCL_ERROR;  }  zErrMsg = 0;  p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );  if( p==0 ){    Tcl_SetResult(interp, "malloc failed", TCL_STATIC);    return TCL_ERROR;  }  memset(p, 0, sizeof(*p));  zFile = Tcl_GetStringFromObj(objv[2], 0);  sqlite3_open(zFile, &p->db);  if( SQLITE_OK!=sqlite3_errcode(p->db) ){    zErrMsg = strdup(sqlite3_errmsg(p->db));    sqlite3_close(p->db);    p->db = 0;  }#ifdef SQLITE_HAS_CODEC  sqlite3_key(p->db, pKey, nKey);#endif  if( p->db==0 ){    Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);    Tcl_Free((char*)p);    free(zErrMsg);    return TCL_ERROR;  }  p->maxStmt = NUM_PREPARED_STMTS;  zArg = Tcl_GetStringFromObj(objv[1], 0);  Tcl_CreateObjCommand(interp, zArg, DbObjCmd, (char*)p, DbDeleteCmd);  /* The return value is the value of the sqlite* pointer  */  sprintf(zBuf, "%p", p->db);  if( strncmp(zBuf,"0x",2) ){    sprintf(zBuf, "0x%p", p->db);  }  Tcl_AppendResult(interp, zBuf, 0);  /* If compiled with SQLITE_TEST turned on, then register the "md5sum"  ** SQL function.  */#ifdef SQLITE_TEST  {    extern void Md5_Register(sqlite3*);#ifdef SQLITE_MEMDEBUG    int mallocfail = sqlite3_iMallocFail;    sqlite3_iMallocFail = 0;#endif    Md5_Register(p->db);#ifdef SQLITE_MEMDEBUG    sqlite3_iMallocFail = mallocfail;#endif   }#endif    p->interp = interp;  return TCL_OK;}/*** Provide a dummy Tcl_InitStubs if we are using this as a static** library.*/#ifndef USE_TCL_STUBS# undef  Tcl_InitStubs# define Tcl_InitStubs(a,b,c)#endif/*** Initialize this module.**** This Tcl module contains only a single new Tcl command named "sqlite".** (Hence there is no namespace.  There is no point in using a namespace** if the extension only supplies one new name!)  The "sqlite" command is** used to open a new SQLite database.  See the DbMain() routine above** for additional information.*/int Sqlite3_Init(Tcl_Interp *interp){  Tcl_InitStubs(interp, "8.4", 0);  Tcl_CreateObjCommand(interp, "sqlite3", (Tcl_ObjCmdProc*)DbMain, 0, 0);  Tcl_PkgProvide(interp, "sqlite3", "3.0");  Tcl_CreateObjCommand(interp, "sqlite", (Tcl_ObjCmdProc*)DbMain, 0, 0);  Tcl_PkgProvide(interp, "sqlite", "3.0");  return TCL_OK;}int Tclsqlite3_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }int Sqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }int Tclsqlite3_SafeInit(Tcl_Interp *interp){ return TCL_OK; }#ifndef SQLITE_3_SUFFIX_ONLYint Sqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }int Tclsqlite_Init(Tcl_Interp *interp){ return Sqlite3_Init(interp); }int Sqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }int Tclsqlite_SafeInit(Tcl_Interp *interp){ return TCL_OK; }#endif#ifdef TCLSH/******************************************************************************* The code that follows is used to build standalone TCL interpreters*//*** If the macro TCLSH is one, then put in code this for the** "main" routine that will initialize Tcl and take input from** standard input.*/#if TCLSH==1static char zMainloop[] =  "set line {}\n"  "while {![eof stdin]} {\n"    "if {$line!=\"\"} {\n"      "puts -nonewline \"> \"\n"    "} else {\n"      "puts -nonewline \"% \"\n"    "}\n"    "flush stdout\n"    "append line [gets stdin]\n"    "if {[info complete $line]} {\n"      "if {[catch {uplevel #0 $line} result]} {\n"        "puts stderr \"Error: $result\"\n"      "} elseif {$result!=\"\"} {\n"        "puts $result\n"      "}\n"      "set line {}\n"    "} else {\n"      "append line \\n\n"    "}\n"  "}\n";#endif/*** If the macro TCLSH is two, then get the main loop code out of** the separate file "spaceanal_tcl.h".*/#if TCLSH==2static char zMainloop[] = #include "spaceanal_tcl.h";#endif#define TCLSH_MAIN main   /* Needed to fake out mktclapp */int TCLSH_MAIN(int argc, char **argv){  Tcl_Interp *interp;  Tcl_FindExecutable(argv[0]);  interp = Tcl_CreateInterp();  Sqlite3_Init(interp);#ifdef SQLITE_TEST  {    extern int Sqlitetest1_Init(Tcl_Interp*);    extern int Sqlitetest2_Init(Tcl_Interp*);    extern int Sqlitetest3_Init(Tcl_Interp*);    extern int Sqlitetest4_Init(Tcl_Interp*);    extern int Sqlitetest5_Init(Tcl_Interp*);    extern int Md5_Init(Tcl_Interp*);    extern int Sqlitetestsse_Init(Tcl_Interp*);    Sqlitetest1_Init(interp);    Sqlitetest2_Init(interp);    Sqlitetest3_Init(interp);    Sqlitetest4_Init(interp);    Sqlitetest5_Init(interp);    Md5_Init(interp);#ifdef SQLITE_SSE    Sqlitetestsse_Init(interp);#endif  }#endif  if( argc>=2 || TCLSH==2 ){    int i;    Tcl_SetVar(interp,"argv0",argv[1],TCL_GLOBAL_ONLY);    Tcl_SetVar(interp,"argv", "", TCL_GLOBAL_ONLY);    for(i=3-TCLSH; i<argc; i++){      Tcl_SetVar(interp, "argv", argv[i],          TCL_GLOBAL_ONLY | TCL_LIST_ELEMENT | TCL_APPEND_VALUE);    }    if( TCLSH==1 && Tcl_EvalFile(interp, argv[1])!=TCL_OK ){      const char *zInfo = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);      if( zInfo==0 ) zInfo = interp->result;      fprintf(stderr,"%s: %s\n", *argv, zInfo);      return 1;    }  }  if( argc<=1 || TCLSH==2 ){    Tcl_GlobalEval(interp, zMainloop);  }  return 0;}#endif /* TCLSH */#endif /* !defined(NO_TCL) */

⌨️ 快捷键说明

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