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

📄 tclsqlite.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
      }      for(i=1; i<=nVar; i++){        const char *zVar = sqlite3_bind_parameter_name(pStmt, i);        if( zVar!=0 && (zVar[0]=='$' || zVar[0]==':') ){          Tcl_Obj *pVar = Tcl_GetVar2Ex(interp, &zVar[1], 0, 0);          if( pVar ){            int n;            u8 *data;            char *zType = pVar->typePtr ? pVar->typePtr->name : "";            char c = zType[0];            if( c=='b' && strcmp(zType,"bytearray")==0 ){              data = Tcl_GetByteArrayFromObj(pVar, &n);              sqlite3_bind_blob(pStmt, i, data, n, SQLITE_STATIC);              Tcl_IncrRefCount(pVar);              apParm[nParm++] = pVar;            }else if( (c=='b' && strcmp(zType,"boolean")==0) ||                  (c=='i' && strcmp(zType,"int")==0) ){              Tcl_GetIntFromObj(interp, pVar, &n);              sqlite3_bind_int(pStmt, i, n);            }else if( c=='d' && strcmp(zType,"double")==0 ){              double r;              Tcl_GetDoubleFromObj(interp, pVar, &r);              sqlite3_bind_double(pStmt, i, r);            }else{              data = Tcl_GetStringFromObj(pVar, &n);              sqlite3_bind_text(pStmt, i, data, n, SQLITE_STATIC);              Tcl_IncrRefCount(pVar);              apParm[nParm++] = pVar;            }          }else{            sqlite3_bind_null( pStmt, i );          }        }      }      /* Compute column names */      nCol = sqlite3_column_count(pStmt);      if( pScript ){        apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );        if( apColName==0 ) break;        for(i=0; i<nCol; i++){          apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i));          Tcl_IncrRefCount(apColName[i]);        }      }      /* If results are being stored in an array variable, then create      ** the array(*) entry for that array      */      if( pArray ){        Tcl_Obj *pColList = Tcl_NewObj();        Tcl_Obj *pStar = Tcl_NewStringObj("*", -1);        Tcl_IncrRefCount(pColList);        for(i=0; i<nCol; i++){          Tcl_ListObjAppendElement(interp, pColList, apColName[i]);        }        Tcl_ObjSetVar2(interp, pArray, pStar, pColList,0);        Tcl_DecrRefCount(pColList);        Tcl_DecrRefCount(pStar);      }      /* Execute the SQL      */      while( rc==TCL_OK && pStmt && SQLITE_ROW==sqlite3_step(pStmt) ){        for(i=0; i<nCol; i++){          Tcl_Obj *pVal;                    /* Set pVal to contain the i'th column of this row. */          switch( sqlite3_column_type(pStmt, i) ){            case SQLITE_BLOB: {              int bytes = sqlite3_column_bytes(pStmt, i);              pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes);              break;            }            case SQLITE_INTEGER: {              sqlite_int64 v = sqlite3_column_int64(pStmt, i);              if( v>=-2147483647 && v<=2147483647 ){                pVal = Tcl_NewIntObj(v);              }else{                pVal = Tcl_NewWideIntObj(v);              }              break;            }            case SQLITE_FLOAT: {              double r = sqlite3_column_double(pStmt, i);              pVal = Tcl_NewDoubleObj(r);              break;            }            case SQLITE_NULL: {              pVal = dbTextToObj(pDb->zNull);              break;            }            default: {              pVal = dbTextToObj(sqlite3_column_text(pStmt, i));              break;            }          }            if( pScript ){            if( pArray==0 ){              Tcl_ObjSetVar2(interp, apColName[i], 0, pVal, 0);            }else{              Tcl_ObjSetVar2(interp, pArray, apColName[i], pVal, 0);            }          }else if( choice==DB_ONECOLUMN ){            if( pRet==0 ){              pRet = pVal;              Tcl_IncrRefCount(pRet);            }            rc = TCL_BREAK;          }else{            Tcl_ListObjAppendElement(interp, pRet, pVal);          }        }          if( pScript ){          rc = Tcl_EvalObjEx(interp, pScript, 0);          if( rc==TCL_CONTINUE ){            rc = TCL_OK;          }        }      }      if( rc==TCL_BREAK ){        rc = TCL_OK;      }      /* Free the column name objects */      if( pScript ){        for(i=0; i<nCol; i++){          Tcl_DecrRefCount(apColName[i]);        }        Tcl_Free((char*)apColName);      }      /* Free the bound string and blob parameters */      for(i=0; i<nParm; i++){        Tcl_DecrRefCount(apParm[i]);      }      if( apParm!=aParm ){        Tcl_Free((char*)apParm);      }      /* Reset the statement.  If the result code is SQLITE_SCHEMA, then      ** flush the statement cache and try the statement again.      */      rc2 = sqlite3_reset(pStmt);      if( SQLITE_SCHEMA==rc2 ){        /* After a schema change, flush the cache and try to run the        ** statement again        */        flushStmtCache( pDb );        sqlite3_finalize(pStmt);        if( pPreStmt ) Tcl_Free((char*)pPreStmt);        continue;      }else if( SQLITE_OK!=rc2 ){        /* If a run-time error occurs, report the error and stop reading        ** the SQL        */        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));        sqlite3_finalize(pStmt);        rc = TCL_ERROR;        if( pPreStmt ) Tcl_Free((char*)pPreStmt);        break;      }else if( pDb->maxStmt<=0 ){        /* If the cache is turned off, deallocated the statement */        if( pPreStmt ) Tcl_Free((char*)pPreStmt);        sqlite3_finalize(pStmt);      }else{        /* Everything worked and the cache is operational.        ** Create a new SqlPreparedStmt structure if we need one.        ** (If we already have one we can just reuse it.)        */        if( pPreStmt==0 ){          len = zLeft - zSql;          pPreStmt = (SqlPreparedStmt*)Tcl_Alloc( sizeof(*pPreStmt) + len );          if( pPreStmt==0 ) return TCL_ERROR;          pPreStmt->pStmt = pStmt;          pPreStmt->nSql = len;          memcpy(pPreStmt->zSql, zSql, len);          pPreStmt->zSql[len] = 0;        }        /* Add the prepared statement to the beginning of the cache list        */        pPreStmt->pNext = pDb->stmtList;        pPreStmt->pPrev = 0;        if( pDb->stmtList ){         pDb->stmtList->pPrev = pPreStmt;        }        pDb->stmtList = pPreStmt;        if( pDb->stmtLast==0 ){          assert( pDb->nStmt==0 );          pDb->stmtLast = pPreStmt;        }else{          assert( pDb->nStmt>0 );        }        pDb->nStmt++;           /* If we have too many statement in cache, remove the surplus from the        ** end of the cache list.        */        while( pDb->nStmt>pDb->maxStmt ){          sqlite3_finalize(pDb->stmtLast->pStmt);          pDb->stmtLast = pDb->stmtLast->pPrev;          Tcl_Free((char*)pDb->stmtLast->pNext);          pDb->stmtLast->pNext = 0;          pDb->nStmt--;        }      }      /* Proceed to the next statement */      zSql = zLeft;    }    Tcl_DecrRefCount(objv[2]);    if( pRet ){      if( rc==TCL_OK ){        Tcl_SetObjResult(interp, pRet);      }      Tcl_DecrRefCount(pRet);    }    break;  }  /*  **     $db function NAME SCRIPT  **  ** Create a new SQL function called NAME.  Whenever that function is  ** called, invoke SCRIPT to evaluate the function.  */  case DB_FUNCTION: {    SqlFunc *pFunc;    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);    pFunc = (SqlFunc*)Tcl_Alloc( sizeof(*pFunc) + nScript + 1 );    if( pFunc==0 ) return TCL_ERROR;    pFunc->interp = interp;    pFunc->pNext = pDb->pFunc;    pFunc->zScript = (char*)&pFunc[1];    pDb->pFunc = pFunc;    strcpy(pFunc->zScript, zScript);    rc = sqlite3_create_function(pDb->db, zName, -1, SQLITE_UTF8,        pFunc, tclSqlFunc, 0, 0);    if( rc!=SQLITE_OK ){      rc = TCL_ERROR;      Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_VOLATILE);    }else{      /* Must flush any cached statements */      flushStmtCache( pDb );    }    break;  }  /*  **     $db last_insert_rowid   **  ** Return an integer which is the ROWID for the most recent insert.  */  case DB_LAST_INSERT_ROWID: {    Tcl_Obj *pResult;    int rowid;    if( objc!=2 ){      Tcl_WrongNumArgs(interp, 2, objv, "");      return TCL_ERROR;    }    rowid = sqlite3_last_insert_rowid(pDb->db);    pResult = Tcl_GetObjResult(interp);    Tcl_SetIntObj(pResult, rowid);    break;  }  /*  ** The DB_ONECOLUMN method is implemented together with DB_EVAL.  */  /*    $db progress ?N CALLBACK?  **   ** Invoke the given callback every N virtual machine opcodes while executing  ** queries.  */  case DB_PROGRESS: {    if( objc==2 ){      if( pDb->zProgress ){        Tcl_AppendResult(interp, pDb->zProgress, 0);      }    }else if( objc==4 ){      char *zProgress;      int len;      int N;      if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &N) ){	return TCL_ERROR;      };      if( pDb->zProgress ){        Tcl_Free(pDb->zProgress);      }      zProgress = Tcl_GetStringFromObj(objv[3], &len);      if( zProgress && len>0 ){        pDb->zProgress = Tcl_Alloc( len + 1 );        strcpy(pDb->zProgress, zProgress);      }else{        pDb->zProgress = 0;      }#ifndef SQLITE_OMIT_PROGRESS_CALLBACK      if( pDb->zProgress ){        pDb->interp = interp;        sqlite3_progress_handler(pDb->db, N, DbProgressHandler, pDb);      }else{        sqlite3_progress_handler(pDb->db, 0, 0, 0);      }#endif    }else{      Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");      return TCL_ERROR;    }    break;  }  /*  **     $db rekey KEY  **  ** Change the encryption key on the currently open database.  */  case DB_REKEY: {    int nKey;    void *pKey;    if( objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "KEY");      return TCL_ERROR;    }    pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);#ifdef SQLITE_HAS_CODEC    rc = sqlite3_rekey(pDb->db, pKey, nKey);    if( rc ){      Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);      rc = TCL_ERROR;    }#endif    break;  }  /*  **     $db timeout MILLESECONDS  **  ** Delay for the number of milliseconds specified when a file is locked.  */  case DB_TIMEOUT: {    int ms;    if( objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "MILLISECONDS");      return TCL_ERROR;    }    if( Tcl_GetIntFromObj(interp, objv[2], &ms) ) return TCL_ERROR;    sqlite3_busy_timeout(pDb->db, ms);    break;  }  /*  **     $db nullvalue ?STRING?  **  ** Change text used when a NULL comes back from the database. If ?STRING?  ** is not present, then the current string used for NULL is returned.  ** If STRING is present, then STRING is returned.  **  */  case DB_NULLVALUE: {    if( objc!=2 && objc!=3 ){      Tcl_WrongNumArgs(interp, 2, objv, "NULLVALUE");      return TCL_ERROR;    }    if( objc==3 ){      int len;      char *zNull = Tcl_GetStringFromObj(objv[2], &len);      if( pDb->zNull ){        Tcl_Free(pDb->zNull);      }      if( zNull && len>0 ){        pDb->zNull = Tcl_Alloc( len + 1 );        strncpy(pDb->zNull, zNull, len);        pDb->zNull[len] = '\0';      }else{        pDb->zNull = 0;      }    }    Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));    break;  }    /*  **     $db total_changes  **  ** Return the number of rows that were modified, inserted, or deleted   ** since the database handle was created.  */  case DB_TOTAL_CHANGES: {    Tcl_Obj *pResult;    if( objc!=2 ){      Tcl_WrongNumArgs(interp, 2, objv, "");      return TCL_ERROR;    }    pResult = Tcl_GetObjResult(interp);    Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));    break;  }  /*    $db trace ?CALLBACK?  **  ** Make arrangements to invoke the CALLBACK routine for each SQL statement  ** that is executed.  The text of the SQL is appended to CALLBACK before  ** it is executed.  */  case DB_TRACE: {    if( objc>3 ){      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");      return TCL_ERROR;    }else if( objc==2 ){      if( pDb->zTrace ){        Tcl_AppendResult(interp, pDb->zTrace, 0);      }    }else{      char *zTrace;      int len;      if( pDb->zTrace ){        Tcl_Free(pDb->zTrace);      }      zTrace = Tcl_GetStringFromObj(objv[2], &len);      if( zTrace && len>0 ){        pDb->zTrace = Tcl_Alloc( len + 1 );        strcpy(pDb->zTrace, zTrace);      }else{        pDb->zTrace = 0;      }      if( pDb->zTrace ){        pDb->interp = interp;        sqlite3_trace(pDb->db, DbTraceHandler, pDb);      }else{        sqlite3_trace(pDb->db, 0, 0);      }    }    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.  **

⌨️ 快捷键说明

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