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

📄 tclsqlite.c

📁 sqlite嵌入式数据库源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    break;  }  /*    $db close  **  ** Shutdown the database  */  case DB_CLOSE: {    Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0));    break;  }  /*  **     $db collate NAME SCRIPT  **  ** Create a new SQL collation function called NAME.  Whenever  ** that function is called, invoke SCRIPT to evaluate the function.  */  case DB_COLLATE: {    SqlCollate *pCollate;    char *zName;    char *zScript;    int nScript;    if( objc!=4 ){      Tcl_WrongNumArgs(interp, 2, objv, "NAME SCRIPT");      return TCL_ERROR;    }    zName = Tcl_GetStringFromObj(objv[2], 0);    zScript = Tcl_GetStringFromObj(objv[3], &nScript);    pCollate = (SqlCollate*)Tcl_Alloc( sizeof(*pCollate) + nScript + 1 );    if( pCollate==0 ) return TCL_ERROR;    pCollate->interp = interp;    pCollate->pNext = pDb->pCollate;    pCollate->zScript = (char*)&pCollate[1];    pDb->pCollate = pCollate;    strcpy(pCollate->zScript, zScript);    if( sqlite3_create_collation(pDb->db, zName, SQLITE_UTF8,         pCollate, tclSqlCollate) ){      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);      return TCL_ERROR;    }    break;  }  /*  **     $db collation_needed SCRIPT  **  ** Create a new SQL collation function called NAME.  Whenever  ** that function is called, invoke SCRIPT to evaluate the function.  */  case DB_COLLATION_NEEDED: {    if( objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "SCRIPT");      return TCL_ERROR;    }    if( pDb->pCollateNeeded ){      Tcl_DecrRefCount(pDb->pCollateNeeded);    }    pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);    Tcl_IncrRefCount(pDb->pCollateNeeded);    sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);    break;  }  /*    $db commit_hook ?CALLBACK?  **  ** Invoke the given callback just before committing every SQL transaction.  ** If the callback throws an exception or returns non-zero, then the  ** transaction is aborted.  If CALLBACK is an empty string, the callback  ** is disabled.  */  case DB_COMMIT_HOOK: {    if( objc>3 ){      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");      return TCL_ERROR;    }else if( objc==2 ){      if( pDb->zCommit ){        Tcl_AppendResult(interp, pDb->zCommit, 0);      }    }else{      char *zCommit;      int len;      if( pDb->zCommit ){        Tcl_Free(pDb->zCommit);      }      zCommit = Tcl_GetStringFromObj(objv[2], &len);      if( zCommit && len>0 ){        pDb->zCommit = Tcl_Alloc( len + 1 );        strcpy(pDb->zCommit, zCommit);      }else{        pDb->zCommit = 0;      }      if( pDb->zCommit ){        pDb->interp = interp;        sqlite3_commit_hook(pDb->db, DbCommitHandler, pDb);      }else{        sqlite3_commit_hook(pDb->db, 0, 0);      }    }    break;  }  /*    $db complete SQL  **  ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if  ** additional lines of input are needed.  This is similar to the  ** built-in "info complete" command of Tcl.  */  case DB_COMPLETE: {#ifndef SQLITE_OMIT_COMPLETE    Tcl_Obj *pResult;    int isComplete;    if( objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "SQL");      return TCL_ERROR;    }    isComplete = sqlite3_complete( Tcl_GetStringFromObj(objv[2], 0) );    pResult = Tcl_GetObjResult(interp);    Tcl_SetBooleanObj(pResult, isComplete);#endif    break;  }  /*    $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?  **  ** Copy data into table from filename, optionally using SEPARATOR  ** as column separators.  If a column contains a null string, or the  ** value of NULLINDICATOR, a NULL is inserted for the column.  ** conflict-algorithm is one of the sqlite conflict algorithms:  **    rollback, abort, fail, ignore, replace  ** On success, return the number of lines processed, not necessarily same  ** as 'db changes' due to conflict-algorithm selected.  **  ** 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);      fclose(in);      return TCL_ERROR;    }    (void)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));        if( zErr ){          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);    (void)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 enable_load_extension BOOLEAN  **  ** Turn the extension loading feature on or off.  It if off by  ** default.  */  case DB_ENABLE_LOAD_EXTENSION: {    int onoff;    if( objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "BOOLEAN");      return TCL_ERROR;    }    if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){      return TCL_ERROR;    }    sqlite3_enable_load_extension(pDb->db, onoff);    break;  }  /*  **    $db errorcode  **  ** Return the numeric error code that was returned by the most recent  ** call to sqlite3_exec().  */  case DB_ERRORCODE: {    Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_errcode(pDb->db)));    break;  }     /*  **    $db eval $sql ?array? ?{  ...code... }?  **    $db onecolumn $sql  **  ** The SQL statement in $sql is evaluated.  For each row, the values are  ** placed in elements of the array named "array" and ...code... is executed.  ** If "array" and "code" are omitted, then no callback is every invoked.  ** If "array" is an empty string, then the values are placed in variables  ** that have the same name as the fields extracted by the query.  **  ** The onecolumn method is the equivalent of:  **     lindex [$db eval $sql] 0  */  case DB_ONECOLUMN:  case DB_EVAL:  case DB_EXISTS: {    char const *zSql;      /* Next SQL statement to execute */    char const *zLeft;     /* What is left after first stmt in zSql */    sqlite3_stmt *pStmt;   /* Compiled SQL statment */    Tcl_Obj *pArray;       /* Name of array into which results are written */    Tcl_Obj *pScript;      /* Script to run for each result set */    Tcl_Obj **apParm;      /* Parameters that need a Tcl_DecrRefCount() */    int nParm;             /* Number of entries used in apParm[] */    Tcl_Obj *aParm[10];    /* Static space for apParm[] in the common case */    Tcl_Obj *pRet;         /* Value to be returned */    SqlPreparedStmt *pPreStmt;  /* Pointer to a prepared statement */    int rc2;    if( choice==DB_EVAL ){      if( objc<3 || objc>5 ){        Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME? ?SCRIPT?");        return TCL_ERROR;      }      pRet = Tcl_NewObj();      Tcl_IncrRefCount(pRet);    }else{      if( objc!=3 ){        Tcl_WrongNumArgs(interp, 2, objv, "SQL");        return TCL_ERROR;      }      if( choice==DB_EXISTS ){        pRet = Tcl_NewBooleanObj(0);        Tcl_IncrRefCount(pRet);      }else{        pRet = 0;      }    }    if( objc==3 ){      pArray = pScript = 0;    }else if( objc==4 ){      pArray = 0;      pScript = objv[3];    }else{      pArray = objv[3];      if( Tcl_GetString(pArray)[0]==0 ) pArray = 0;      pScript = objv[4];    }    Tcl_IncrRefCount(objv[2]);    zSql = Tcl_GetStringFromObj(objv[2], 0);    while( rc==TCL_OK && zSql[0] ){      int i;                     /* Loop counter */      int nVar;                  /* Number of bind parameters in the pStmt */      int nCol;                  /* Number of columns in the result set */      Tcl_Obj **apColName = 0;   /* Array of column names */      int len;                   /* String length of zSql */        /* Try to find a SQL statement that has already been compiled and      ** which matches the next sequence of SQL.      */      pStmt = 0;      pPreStmt = pDb->stmtList;      len = strlen(zSql);      if( pPreStmt && sqlite3_expired(pPreStmt->pStmt) ){        flushStmtCache(pDb);        pPreStmt = 0;      }      for(; pPreStmt; pPreStmt=pPreStmt->pNext){        int n = pPreStmt->nSql;        if( len>=n             && memcmp(pPreStmt->zSql, zSql, n)==0            && (zSql[n]==0 || zSql[n-1]==';')        ){          pStmt = pPreStmt->pStmt;

⌨️ 快捷键说明

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