static void *sqlite_open_conn(const DBConf *db_conf) { sqlite *db = NULL; SQLiteConf *conf = db_conf->sqlite; /* make compiler happy */ char *errmsg = 0; /* sanity check */ if (conf == NULL) return NULL; if ((db = sqlite_open(octstr_get_cstr(conf->file), 0, &errmsg)) == NULL) { error(0, "SQLite: can not open database file `%s'!", octstr_get_cstr(conf->file)); error(0, "SQLite: %s", errmsg); goto failed; } if (conf->lock_timeout > 0) { info(0, "SQLite: Setting lock timeout to %ld", conf->lock_timeout); sqlite_busy_timeout(db, conf->lock_timeout); } info(0, "SQLite: Opened database file `%s'.", octstr_get_cstr(conf->file)); info(0, "SQLite: library version %s.", sqlite_version); return db; failed: return NULL; }
IoObject *IoSQLite_open(IoSQLite *self, IoObject *locals, IoMessage *m) { /*doc SQLite open(optionalPathString) Opens the database.Returns self on success or nil upon failure. If the databse is locked, "yield" will be called until it is accessable or timeoutSeconds has expired. */ char *zErrMsg; if (DATA(self)->debugOn) { IoState_print_(IOSTATE, "IoSQLite opening '%s'\n", CSTRING(DATA(self)->path)); } DATA(self)->db = sqlite_open(CSTRING(DATA(self)->path), 0, &zErrMsg); if (!DATA(self)->db) { IoSQLite_error_(self, zErrMsg); } else { IoSQLite_error_(self, ""); } sqlite_busy_handler(DATA(self)->db, IoSQLite_busyHandler, self); sqlite_busy_timeout(DATA(self)->db, DATA(self)->timeoutSeconds*1000); return self; }
/* * smb_nic_dbcreate * * Creates the host database based on the defined SQL statement. * It also initializes db_info table. */ static int smb_nic_dbcreate(void) { sqlite *db = NULL; char *errmsg = NULL; int rc, err = SMB_NIC_SUCCESS; (void) unlink(SMB_NIC_DB_NAME); db = sqlite_open(SMB_NIC_DB_NAME, 0600, &errmsg); if (db == NULL) { syslog(LOG_ERR, "Failed to create host database (%s).", NULL_MSGCHK(errmsg)); sqlite_freemem(errmsg); return (SMB_NIC_DBOPEN_FAILED); } sqlite_busy_timeout(db, SMB_NIC_DB_TIMEOUT); rc = sqlite_exec(db, "BEGIN TRANSACTION", NULL, NULL, &errmsg); if (rc != SQLITE_OK) { syslog(LOG_ERR, "Failed to create host database. Unable to " \ "begin database transaction (%s).", NULL_MSGCHK(errmsg)); sqlite_freemem(errmsg); sqlite_close(db); return (SMB_NIC_DBEXEC_FAILED); } if (sqlite_exec(db, SMB_NIC_DB_SQL, NULL, NULL, &errmsg) == SQLITE_OK) { rc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, &errmsg); if (rc == SQLITE_OK) err = smb_nic_dbsetinfo(db); if (err != SMB_NIC_SUCCESS) rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg); } else { syslog(LOG_ERR, "Failed to create host database. Unable to " \ "initialize host database (%s).", NULL_MSGCHK(errmsg)); sqlite_freemem(errmsg); rc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, &errmsg); } if (rc != SQLITE_OK) { /* this is bad - database may be left in a locked state */ syslog(LOG_ERR, "Failed to create host database. Unable to " \ "close a transaction (%s).", NULL_MSGCHK(errmsg)); sqlite_freemem(errmsg); err = SMB_NIC_DBINIT_FAILED; } (void) sqlite_close(db); return (err); }
/* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked ** whenever one of those connection-specific commands is executed ** in Tcl. For example, if you run Tcl code like this: ** ** sqlite db1 "my_database" ** db1 close ** ** The first command opens a connection to the "my_database" database ** and calls that connection "db1". The second command causes this ** subroutine to be invoked. */ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; int rc = TCL_OK; static const char *DB_strs[] = { "authorizer", "busy", "changes", "close", "commit_hook", "complete", "errorcode", "eval", "function", "last_insert_rowid", "last_statement_changes", "onecolumn", "progress", "rekey", "timeout", "trace", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CHANGES, DB_CLOSE, DB_COMMIT_HOOK, DB_COMPLETE, DB_ERRORCODE, DB_EVAL, DB_FUNCTION, DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN, DB_PROGRESS, DB_REKEY, DB_TIMEOUT, DB_TRACE }; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){ return TCL_ERROR; } switch( (enum DB_enum)choice ){ /* $db authorizer ?CALLBACK? ** ** Invoke the given callback to authorize each SQL operation as it is ** compiled. 5 arguments are appended to the callback before it is ** invoked: ** ** (1) The authorization type (ex: SQLITE_CREATE_TABLE, SQLITE_INSERT, ...) ** (2) First descriptive name (depends on authorization type) ** (3) Second descriptive name ** (4) Name of the database (ex: "main", "temp") ** (5) Name of trigger that is doing the access ** ** The callback should return on of the following strings: SQLITE_OK, ** SQLITE_IGNORE, or SQLITE_DENY. Any other return value is an error. ** ** If this method is invoked with no arguments, the current authorization ** callback string is returned. */ case DB_AUTHORIZER: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?"); }else if( objc==2 ){ if( pDb->zAuth ){ Tcl_AppendResult(interp, pDb->zAuth, 0); } }else{ char *zAuth; int len; if( pDb->zAuth ){ Tcl_Free(pDb->zAuth); } zAuth = Tcl_GetStringFromObj(objv[2], &len); if( zAuth && len>0 ){ pDb->zAuth = Tcl_Alloc( len + 1 ); strcpy(pDb->zAuth, zAuth); }else{ pDb->zAuth = 0; } #ifndef SQLITE_OMIT_AUTHORIZATION if( pDb->zAuth ){ pDb->interp = interp; sqlite_set_authorizer(pDb->db, auth_callback, pDb); }else{ sqlite_set_authorizer(pDb->db, 0, 0); } #endif } break; } /* $db busy ?CALLBACK? ** ** Invoke the given callback if an SQL statement attempts to open ** a locked database file. */ case DB_BUSY: { if( objc>3 ){ Tcl_WrongNumArgs(interp, 2, objv, "CALLBACK"); return TCL_ERROR; }else if( objc==2 ){ if( pDb->zBusy ){ Tcl_AppendResult(interp, pDb->zBusy, 0); } }else{ char *zBusy; int len; if( pDb->zBusy ){ Tcl_Free(pDb->zBusy); } zBusy = Tcl_GetStringFromObj(objv[2], &len); if( zBusy && len>0 ){ pDb->zBusy = Tcl_Alloc( len + 1 ); strcpy(pDb->zBusy, zBusy); }else{ pDb->zBusy = 0; } if( pDb->zBusy ){ pDb->interp = interp; sqlite_busy_handler(pDb->db, DbBusyHandler, pDb); }else{ sqlite_busy_handler(pDb->db, 0, 0); } } break; } /* $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; sqlite_progress_handler(pDb->db, N, DbProgressHandler, pDb); }else{ sqlite_progress_handler(pDb->db, 0, 0, 0); } #endif }else{ Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK"); return TCL_ERROR; } break; } /* ** $db changes ** ** Return the number of rows that were modified, inserted, or deleted by ** the most recent "eval". */ case DB_CHANGES: { Tcl_Obj *pResult; int nChange; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } nChange = sqlite_changes(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, nChange); break; } /* ** $db last_statement_changes ** ** Return the number of rows that were modified, inserted, or deleted by ** the last statment to complete execution (excluding changes due to ** triggers) */ case DB_LAST_STATEMENT_CHANGES: { Tcl_Obj *pResult; int lsChange; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } lsChange = sqlite_last_statement_changes(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, lsChange); break; } /* $db close ** ** Shutdown the database */ case DB_CLOSE: { Tcl_DeleteCommand(interp, Tcl_GetStringFromObj(objv[0], 0)); 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?"); }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; sqlite_commit_hook(pDb->db, DbCommitHandler, pDb); }else{ sqlite_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: { Tcl_Obj *pResult; int isComplete; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } isComplete = sqlite_complete( Tcl_GetStringFromObj(objv[2], 0) ); pResult = Tcl_GetObjResult(interp); Tcl_SetBooleanObj(pResult, isComplete); break; } /* ** $db errorcode ** ** Return the numeric error code that was returned by the most recent ** call to sqlite_exec(). */ case DB_ERRORCODE: { Tcl_SetObjResult(interp, Tcl_NewIntObj(pDb->rc)); break; } /* ** $db eval $sql ?array { ...code... }? ** ** 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. */ case DB_EVAL: { CallbackData cbData; char *zErrMsg; char *zSql; #ifdef UTF_TRANSLATION_NEEDED Tcl_DString dSql; int i; #endif if( objc!=5 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?"); return TCL_ERROR; } pDb->interp = interp; zSql = Tcl_GetStringFromObj(objv[2], 0); #ifdef UTF_TRANSLATION_NEEDED Tcl_DStringInit(&dSql); Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql); zSql = Tcl_DStringValue(&dSql); #endif Tcl_IncrRefCount(objv[2]); if( objc==5 ){ cbData.interp = interp; cbData.once = 1; cbData.zArray = Tcl_GetStringFromObj(objv[3], 0); cbData.pCode = objv[4]; cbData.tcl_rc = TCL_OK; cbData.nColName = 0; cbData.azColName = 0; zErrMsg = 0; Tcl_IncrRefCount(objv[3]); Tcl_IncrRefCount(objv[4]); rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg); Tcl_DecrRefCount(objv[4]); Tcl_DecrRefCount(objv[3]); if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; } }else{ Tcl_Obj *pList = Tcl_NewObj(); cbData.tcl_rc = TCL_OK; rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg); Tcl_SetObjResult(interp, pList); } pDb->rc = rc; if( rc==SQLITE_ABORT ){ if( zErrMsg ) free(zErrMsg); rc = cbData.tcl_rc; }else if( zErrMsg ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); free(zErrMsg); rc = TCL_ERROR; }else if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = TCL_ERROR; }else{ } Tcl_DecrRefCount(objv[2]); #ifdef UTF_TRANSLATION_NEEDED Tcl_DStringFree(&dSql); if( objc==5 && cbData.azColName ){ for(i=0; i<cbData.nColName; i++){ if( cbData.azColName[i] ) free(cbData.azColName[i]); } free(cbData.azColName); cbData.azColName = 0; } #endif return rc; } /* ** $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]; strcpy(pFunc->zScript, zScript); sqlite_create_function(pDb->db, zName, -1, tclSqlFunc, pFunc); sqlite_function_type(pDb->db, zName, SQLITE_NUMERIC); 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 = sqlite_last_insert_rowid(pDb->db); pResult = Tcl_GetObjResult(interp); Tcl_SetIntObj(pResult, rowid); break; } /* ** $db onecolumn SQL ** ** Return a single column from a single row of the given SQL query. */ case DB_ONECOLUMN: { char *zSql; char *zErrMsg = 0; if( objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL"); return TCL_ERROR; } zSql = Tcl_GetStringFromObj(objv[2], 0); rc = sqlite_exec(pDb->db, zSql, DbEvalCallback3, interp, &zErrMsg); if( rc==SQLITE_ABORT ){ rc = SQLITE_OK; }else if( zErrMsg ){ Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); free(zErrMsg); rc = TCL_ERROR; }else if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, sqlite_error_string(rc), 0); rc = 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 = sqlite_rekey(pDb->db, pKey, nKey); if( rc ){ Tcl_AppendResult(interp, sqlite_error_string(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; sqlite_busy_timeout(pDb->db, ms); 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?"); }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; sqlite_trace(pDb->db, DbTraceHandler, pDb); }else{ sqlite_trace(pDb->db, 0, 0); } } break; } } /* End of the SWITCH statement */ return rc; }
/* ** If an input line begins with "." then invoke this routine to ** process that line. ** ** Return 1 to exit and 0 to continue. */ static int do_meta_command(char *zLine, struct callback_data *p){ int i = 1; int nArg = 0; int n, c; int rc = 0; char *azArg[50]; /* Parse the input line into tokens. */ while( zLine[i] && nArg<ArraySize(azArg) ){ while( isspace(zLine[i]) ){ i++; } if( zLine[i]==0 ) break; if( zLine[i]=='\'' || zLine[i]=='"' ){ int delim = zLine[i++]; azArg[nArg++] = &zLine[i]; while( zLine[i] && zLine[i]!=delim ){ i++; } if( zLine[i]==delim ){ zLine[i++] = 0; } }else{ azArg[nArg++] = &zLine[i]; while( zLine[i] && !isspace(zLine[i]) ){ i++; } if( zLine[i] ) zLine[i++] = 0; } } /* Process the input line. */ if( nArg==0 ) return rc; n = strlen(azArg[0]); c = azArg[0][0]; if( c=='d' && n>1 && strncmp(azArg[0], "databases", n)==0 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 1; data.mode = MODE_Column; data.colWidth[0] = 3; data.colWidth[1] = 15; data.colWidth[2] = 58; sqlite_exec(p->db, "PRAGMA database_list; ", callback, &data, &zErrMsg); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite_freemem(zErrMsg); } }else if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){ char *zErrMsg = 0; open_db(p); fprintf(p->out, "BEGIN TRANSACTION;\n"); if( nArg==1 ){ sqlite_exec(p->db, "SELECT name, type, sql FROM sqlite_master " "WHERE type!='meta' AND sql NOT NULL " "ORDER BY substr(type,2,1), name", dump_callback, p, &zErrMsg ); }else{ int i; for(i=1; i<nArg && zErrMsg==0; i++){ sqlite_exec_printf(p->db, "SELECT name, type, sql FROM sqlite_master " "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOT NULL " "ORDER BY substr(type,2,1), name", dump_callback, p, &zErrMsg, azArg[i] ); } } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite_freemem(zErrMsg); }else{ fprintf(p->out, "COMMIT;\n"); } }else if( c=='e' && strncmp(azArg[0], "echo", n)==0 && nArg>1 ){ int j; char *z = azArg[1]; int val = atoi(azArg[1]); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } p->echoOn = val; }else if( c=='e' && strncmp(azArg[0], "exit", n)==0 ){ rc = 1; }else if( c=='e' && strncmp(azArg[0], "explain", n)==0 ){ int j; char *z = nArg>=2 ? azArg[1] : "1"; int val = atoi(z); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } if(val == 1) { if(!p->explainPrev.valid) { p->explainPrev.valid = 1; p->explainPrev.mode = p->mode; p->explainPrev.showHeader = p->showHeader; memcpy(p->explainPrev.colWidth,p->colWidth,sizeof(p->colWidth)); } /* We could put this code under the !p->explainValid ** condition so that it does not execute if we are already in ** explain mode. However, always executing it allows us an easy ** was to reset to explain mode in case the user previously ** did an .explain followed by a .width, .mode or .header ** command. */ p->mode = MODE_Column; p->showHeader = 1; memset(p->colWidth,0,ArraySize(p->colWidth)); p->colWidth[0] = 4; p->colWidth[1] = 12; p->colWidth[2] = 10; p->colWidth[3] = 10; p->colWidth[4] = 35; }else if (p->explainPrev.valid) { p->explainPrev.valid = 0; p->mode = p->explainPrev.mode; p->showHeader = p->explainPrev.showHeader; memcpy(p->colWidth,p->explainPrev.colWidth,sizeof(p->colWidth)); } }else if( c=='h' && (strncmp(azArg[0], "header", n)==0 || strncmp(azArg[0], "headers", n)==0 )&& nArg>1 ){ int j; char *z = azArg[1]; int val = atoi(azArg[1]); for(j=0; z[j]; j++){ if( isupper(z[j]) ) z[j] = tolower(z[j]); } if( strcmp(z,"on")==0 ){ val = 1; }else if( strcmp(z,"yes")==0 ){ val = 1; } p->showHeader = val; }else if( c=='h' && strncmp(azArg[0], "help", n)==0 ){ fprintf(stderr,zHelp); }else if( c=='i' && strncmp(azArg[0], "indices", n)==0 && nArg>1 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_List; sqlite_exec_printf(p->db, "SELECT name FROM sqlite_master " "WHERE type='index' AND tbl_name LIKE '%q' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type='index' AND tbl_name LIKE '%q' " "ORDER BY 1", callback, &data, &zErrMsg, azArg[1], azArg[1] ); if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite_freemem(zErrMsg); } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 && nArg>=2 ){ int n2 = strlen(azArg[1]); if( strncmp(azArg[1],"line",n2)==0 || strncmp(azArg[1],"lines",n2)==0 ){ p->mode = MODE_Line; }else if( strncmp(azArg[1],"column",n2)==0 || strncmp(azArg[1],"columns",n2)==0 ){ p->mode = MODE_Column; }else if( strncmp(azArg[1],"list",n2)==0 ){ p->mode = MODE_List; }else if( strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( strncmp(azArg[1],"insert",n2)==0 ){ p->mode = MODE_Insert; if( nArg>=3 ){ set_table_name(p, azArg[2]); }else{ set_table_name(p, "table"); } }else { fprintf(stderr,"mode should be on of: column html insert line list\n"); } }else if( c=='n' && strncmp(azArg[0], "nullvalue", n)==0 && nArg==2 ) { sprintf(p->nullvalue, "%.*s", (int)ArraySize(p->nullvalue)-1, azArg[1]); }else if( c=='o' && strncmp(azArg[0], "output", n)==0 && nArg==2 ){ if( p->out!=stdout ){ fclose(p->out); } if( strcmp(azArg[1],"stdout")==0 ){ p->out = stdout; strcpy(p->outfile,"stdout"); }else{ p->out = fopen(azArg[1], "wb"); if( p->out==0 ){ fprintf(stderr,"can't write to \"%s\"\n", azArg[1]); p->out = stdout; } else { strcpy(p->outfile,azArg[1]); } } }else if( c=='p' && strncmp(azArg[0], "prompt", n)==0 && (nArg==2 || nArg==3)){ if( nArg >= 2) { strncpy(mainPrompt,azArg[1],(int)ArraySize(mainPrompt)-1); } if( nArg >= 3) { strncpy(continuePrompt,azArg[2],(int)ArraySize(continuePrompt)-1); } }else if( c=='q' && strncmp(azArg[0], "quit", n)==0 ){ rc = 1; }else if( c=='r' && strncmp(azArg[0], "read", n)==0 && nArg==2 ){ FILE *alt = fopen(azArg[1], "rb"); if( alt==0 ){ fprintf(stderr,"can't open \"%s\"\n", azArg[1]); }else{ process_input(p, alt); fclose(alt); } }else #ifdef SQLITE_HAS_CODEC if( c=='r' && strncmp(azArg[0],"rekey", n)==0 && nArg==4 ){ char *zOld = p->zKey; if( zOld==0 ) zOld = ""; if( strcmp(azArg[1],zOld) ){ fprintf(stderr,"old key is incorrect\n"); }else if( strcmp(azArg[2], azArg[3]) ){ fprintf(stderr,"2nd copy of new key does not match the 1st\n"); }else{ sqlite_freemem(p->zKey); p->zKey = sqlite_mprintf("%s", azArg[2]); sqlite_rekey(p->db, p->zKey, strlen(p->zKey)); } }else #endif if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){ struct callback_data data; char *zErrMsg = 0; open_db(p); memcpy(&data, p, sizeof(data)); data.showHeader = 0; data.mode = MODE_Semi; if( nArg>1 ){ extern int sqliteStrICmp(const char*,const char*); if( sqliteStrICmp(azArg[1],"sqlite_master")==0 ){ char *new_argv[2], *new_colv[2]; new_argv[0] = "CREATE TABLE sqlite_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); }else if( sqliteStrICmp(azArg[1],"sqlite_temp_master")==0 ){ char *new_argv[2], *new_colv[2]; new_argv[0] = "CREATE TEMP TABLE sqlite_temp_master (\n" " type text,\n" " name text,\n" " tbl_name text,\n" " rootpage integer,\n" " sql text\n" ")"; new_argv[1] = 0; new_colv[0] = "sql"; new_colv[1] = 0; callback(&data, 1, new_argv, new_colv); }else{ sqlite_exec_printf(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " "WHERE tbl_name LIKE '%q' AND type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg, azArg[1]); } }else{ sqlite_exec(p->db, "SELECT sql FROM " " (SELECT * FROM sqlite_master UNION ALL" " SELECT * FROM sqlite_temp_master) " "WHERE type!='meta' AND sql NOTNULL " "ORDER BY substr(type,2,1), name", callback, &data, &zErrMsg ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite_freemem(zErrMsg); } }else if( c=='s' && strncmp(azArg[0], "separator", n)==0 && nArg==2 ){ sprintf(p->separator, "%.*s", (int)ArraySize(p->separator)-1, azArg[1]); }else if( c=='s' && strncmp(azArg[0], "show", n)==0){ int i; fprintf(p->out,"%9.9s: %s\n","echo", p->echoOn ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","explain", p->explainPrev.valid ? "on" :"off"); fprintf(p->out,"%9.9s: %s\n","headers", p->showHeader ? "on" : "off"); fprintf(p->out,"%9.9s: %s\n","mode", modeDescr[p->mode]); fprintf(p->out,"%9.9s: %s\n","nullvalue", p->nullvalue); fprintf(p->out,"%9.9s: %s\n","output", strlen(p->outfile) ? p->outfile : "stdout"); fprintf(p->out,"%9.9s: %s\n","separator", p->separator); fprintf(p->out,"%9.9s: ","width"); for (i=0;i<(int)ArraySize(p->colWidth) && p->colWidth[i] != 0;i++) { fprintf(p->out,"%d ",p->colWidth[i]); } fprintf(p->out,"\n\n"); }else if( c=='t' && n>1 && strncmp(azArg[0], "tables", n)==0 ){ char **azResult; int nRow, rc; char *zErrMsg; open_db(p); if( nArg==1 ){ rc = sqlite_get_table(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg ); }else{ rc = sqlite_get_table_printf(p->db, "SELECT name FROM sqlite_master " "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "UNION ALL " "SELECT name FROM sqlite_temp_master " "WHERE type IN ('table','view') AND name LIKE '%%%q%%' " "ORDER BY 1", &azResult, &nRow, 0, &zErrMsg, azArg[1], azArg[1] ); } if( zErrMsg ){ fprintf(stderr,"Error: %s\n", zErrMsg); sqlite_freemem(zErrMsg); } if( rc==SQLITE_OK ){ int len, maxlen = 0; int i, j; int nPrintCol, nPrintRow; for(i=1; i<=nRow; i++){ if( azResult[i]==0 ) continue; len = strlen(azResult[i]); if( len>maxlen ) maxlen = len; } nPrintCol = 80/(maxlen+2); if( nPrintCol<1 ) nPrintCol = 1; nPrintRow = (nRow + nPrintCol - 1)/nPrintCol; for(i=0; i<nPrintRow; i++){ for(j=i+1; j<=nRow; j+=nPrintRow){ char *zSp = j<=nPrintRow ? "" : " "; printf("%s%-*s", zSp, maxlen, azResult[j] ? azResult[j] : ""); } printf("\n"); } } sqlite_free_table(azResult); }else if( c=='t' && n>1 && strncmp(azArg[0], "timeout", n)==0 && nArg>=2 ){ open_db(p); sqlite_busy_timeout(p->db, atoi(azArg[1])); }else if( c=='w' && strncmp(azArg[0], "width", n)==0 ){ int j; for(j=1; j<nArg && j<ArraySize(p->colWidth); j++){ p->colWidth[j-1] = atoi(azArg[j]); } }else { fprintf(stderr, "unknown command or invalid arguments: " " \"%s\". Enter \".help\" for help\n", azArg[0]); } return rc; }
int _ds_init_storage (DSPAM_CTX * CTX, void *dbh) { struct _sqlite_drv_storage *s; FILE *file; char buff[1024]; char filename[MAX_FILENAME_LENGTH]; char *err=NULL; struct stat st; int noexist; buff[0] = 0; if (CTX == NULL) return EINVAL; if (!CTX->home) { LOG(LOG_ERR, ERR_AGENT_DSPAM_HOME); return EINVAL; } if (CTX->flags & DSF_MERGED) { LOG(LOG_ERR, ERR_DRV_NO_MERGED); return EINVAL; } /* don't init if we're already initted */ if (CTX->storage != NULL) { LOGDEBUG ("_ds_init_storage: storage already initialized"); return EINVAL; } s = malloc (sizeof (struct _sqlite_drv_storage)); if (s == NULL) { LOG (LOG_CRIT, ERR_MEM_ALLOC); return EUNKNOWN; } s->dbh = NULL; s->control_token = 0; s->iter_token = NULL; s->iter_sig = NULL; s->control_token = 0; s->control_sh = 0; s->control_ih = 0; s->dbh_attached = (dbh) ? 1 : 0; if (CTX->group == NULL || CTX->group[0] == 0) _ds_userdir_path (filename, CTX->home, CTX->username, "sdb"); else _ds_userdir_path (filename, CTX->home, CTX->group, "sdb"); _ds_prepare_path_for (filename); noexist = stat(filename, &st); if (dbh) s->dbh = dbh; else s->dbh = sqlite_open(filename, 0660, &err); if (s->dbh == NULL) { LOGDEBUG ("_ds_init_storage: sqlite_open: unable to initialize database: %s", err); return EUNKNOWN; } /* Commit timeout of 20 minutes */ sqlite_busy_timeout(s->dbh, 1000 * 60 * 20); /* Create database objects */ if (noexist) { sqlite_exec(s->dbh, "create table dspam_token_data (token char(20) primary key, " "spam_hits int, innocent_hits int, last_hit date)", NULL, NULL, &err); sqlite_exec(s->dbh, "create index id_token_data_02 on dspam_token_data" "(innocent_hits)", NULL, NULL, &err); sqlite_exec(s->dbh, "create table dspam_signature_data (" "signature char(128) primary key, data blob, created_on date)", NULL, NULL, &err); sqlite_exec(s->dbh, "create table dspam_stats (dspam_stat_id int primary key, " "spam_learned int, innocent_learned int, " "spam_misclassified int, innocent_misclassified int, " "spam_corpusfed int, innocent_corpusfed int, " "spam_classified int, innocent_classified int)", NULL, NULL, &err); } if (_ds_read_attribute(CTX->config->attributes, "SQLitePragma")) { char pragma[1024]; attribute_t t = _ds_find_attribute(CTX->config->attributes, "SQLitePragma"); while(t != NULL) { snprintf(pragma, sizeof(pragma), "PRAGMA %s", t->value); if ((sqlite_exec(s->dbh, pragma, NULL, NULL, &err))!=SQLITE_OK) { LOG(LOG_WARNING, "sqlite.pragma function error: %s: %s", err, pragma); _sqlite_drv_query_error (err, pragma); } t = t->next; } } else if (CTX->home) { snprintf(filename, MAX_FILENAME_LENGTH, "%s/sqlite.pragma", CTX->home); file = fopen(filename, "r"); if (file != NULL) { while((fgets(buff, sizeof(buff), file))!=NULL) { chomp(buff); if ((sqlite_exec(s->dbh, buff, NULL, NULL, &err))!=SQLITE_OK) { LOG(LOG_WARNING, "sqlite.pragma function error: %s: %s", err, buff); _sqlite_drv_query_error (err, buff); } } fclose(file); } } CTX->storage = s; s->dir_handles = nt_create (NT_INDEX); s->control_token = 0; s->control_ih = 0; s->control_sh = 0; /* get spam totals on successful init */ if (CTX->username != NULL) { if (_sqlite_drv_get_spamtotals (CTX)) { LOGDEBUG ("unable to load totals. using zero values."); } } else { memset (&CTX->totals, 0, sizeof (struct _ds_spam_totals)); memset (&s->control_totals, 0, sizeof (struct _ds_spam_totals)); } return 0; }
static int sqlite_odbx_result( odbx_t* handle, odbx_result_t** result, struct timeval* timeout, unsigned long chunk ) { char** res; long ms = 0; int err, nrow, ncolumn; struct sres* sres; struct sconn* aux = (struct sconn*) handle->aux; if( handle->generic == NULL || aux == NULL ) { return -ODBX_ERR_PARAM; } aux->errmsg = NULL; if( aux->stmt == NULL ) { return ODBX_RES_DONE; /* no more results */ } if( timeout != NULL ) { ms = timeout->tv_sec * 1000 + timeout->tv_usec / 1000; } while( ( err = sqlite_get_table( (sqlite*) handle->generic, aux->stmt, &res, &nrow, &ncolumn, NULL ) ) == SQLITE_BUSY ) { if( ms <= 0 ) { return ODBX_RES_TIMEOUT; } /* Timeout */ sqlite_busy_timeout( (sqlite*) handle->generic, 100 ); ms -= 100; } free( aux->stmt ); aux->stmt = NULL; if( err != SQLITE_OK ) { aux->errno = err; aux->errmsg = (char*) sqlite_error_string( err ); return -ODBX_ERR_BACKEND; } if( ( *result = (odbx_result_t*) malloc( sizeof( struct odbx_result_t ) ) ) == NULL ) { return -ODBX_ERR_NOMEM; } if( ( sres = (struct sres*) malloc( sizeof( struct sres ) ) ) == NULL ) { free( *result ); *result = NULL; return -ODBX_ERR_NOMEM; } (*result)->generic = (void*) res; (*result)->aux = (void*) sres; sres->ncolumn = ncolumn; sres->nrow = nrow; sres->cur = -1; if( !ncolumn ) { return ODBX_RES_NOROWS; } /* empty or not SELECT like query */ return ODBX_RES_ROWS; /* result is available */ }