SQLite
Check-in [cd501bbccf]
Not logged in
Overview
SHA1 Hash:cd501bbccf3e62b002317592cc331770b32c129a
Date: 2012-11-26 19:50:41
User: dan
Comment:Add an option to register global hooks used for logging all SQL executed by an application.
Tags And Properties
Changes
hide diffs unified diffs patch

Changes to main.mk

253 $(TOP)/src/test_osinst.c \ 253 $(TOP)/src/test_osinst.c \ 254 $(TOP)/src/test_pcache.c \ 254 $(TOP)/src/test_pcache.c \ 255 $(TOP)/src/test_quota.c \ 255 $(TOP)/src/test_quota.c \ 256 $(TOP)/src/test_rtree.c \ 256 $(TOP)/src/test_rtree.c \ 257 $(TOP)/src/test_schema.c \ 257 $(TOP)/src/test_schema.c \ 258 $(TOP)/src/test_server.c \ 258 $(TOP)/src/test_server.c \ 259 $(TOP)/src/test_stat.c \ 259 $(TOP)/src/test_stat.c \ > 260 $(TOP)/src/test_sqllog.c \ 260 $(TOP)/src/test_superlock.c \ 261 $(TOP)/src/test_superlock.c \ 261 $(TOP)/src/test_syscall.c \ 262 $(TOP)/src/test_syscall.c \ 262 $(TOP)/src/test_tclvar.c \ 263 $(TOP)/src/test_tclvar.c \ 263 $(TOP)/src/test_thread.c \ 264 $(TOP)/src/test_thread.c \ 264 $(TOP)/src/test_vfs.c \ 265 $(TOP)/src/test_vfs.c \ 265 $(TOP)/src/test_wholenumber.c \ 266 $(TOP)/src/test_wholenumber.c \ 266 $(TOP)/src/test_wsd.c 267 $(TOP)/src/test_wsd.c

Changes to src/global.c

171 0, /* isMallocInit */ 171 0, /* isMallocInit */ 172 0, /* isPCacheInit */ 172 0, /* isPCacheInit */ 173 0, /* pInitMutex */ 173 0, /* pInitMutex */ 174 0, /* nRefInitMutex */ 174 0, /* nRefInitMutex */ 175 0, /* xLog */ 175 0, /* xLog */ 176 0, /* pLogArg */ 176 0, /* pLogArg */ 177 0, /* bLocaltimeFault */ 177 0, /* bLocaltimeFault */ > 178 #ifdef SQLITE_ENABLE_SQLLOG > 179 0, /* xSqllog */ > 180 0 /* pSqllogArg */ > 181 #endif 178 }; 182 }; 179 183 180 184 181 /* 185 /* 182 ** Hash table for global functions - functions common to all 186 ** Hash table for global functions - functions common to all 183 ** database connections. After initialization, this table is 187 ** database connections. After initialization, this table is 184 ** read-only. 188 ** read-only.

Changes to src/main.c

127 127 128 /* If SQLite is already completely initialized, then this call 128 /* If SQLite is already completely initialized, then this call 129 ** to sqlite3_initialize() should be a no-op. But the initialization 129 ** to sqlite3_initialize() should be a no-op. But the initialization 130 ** must be complete. So isInit must not be set until the very end 130 ** must be complete. So isInit must not be set until the very end 131 ** of this routine. 131 ** of this routine. 132 */ 132 */ 133 if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; 133 if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; > 134 > 135 #ifdef SQLITE_ENABLE_SQLLOG > 136 { > 137 extern sqlite3_init_sqllog(void); > 138 sqlite3_init_sqllog(); > 139 } > 140 #endif 134 141 135 /* Make sure the mutex subsystem is initialized. If unable to 142 /* Make sure the mutex subsystem is initialized. If unable to 136 ** initialize the mutex subsystem, return early with the error. 143 ** initialize the mutex subsystem, return early with the error. 137 ** If the system is so sick that we are unable to allocate a mutex, 144 ** If the system is so sick that we are unable to allocate a mutex, 138 ** there is not much SQLite is going to be able to do. 145 ** there is not much SQLite is going to be able to do. 139 ** 146 ** 140 ** The mutex subsystem must take care of serializing its own 147 ** The mutex subsystem must take care of serializing its own ................................................................................................................................................................................ 475 break; 482 break; 476 } 483 } 477 484 478 case SQLITE_CONFIG_COVERING_INDEX_SCAN: { 485 case SQLITE_CONFIG_COVERING_INDEX_SCAN: { 479 sqlite3GlobalConfig.bUseCis = va_arg(ap, int); 486 sqlite3GlobalConfig.bUseCis = va_arg(ap, int); 480 break; 487 break; 481 } 488 } > 489 > 490 #ifdef SQLITE_ENABLE_SQLLOG > 491 case SQLITE_CONFIG_SQLLOG: { > 492 typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); > 493 sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); > 494 sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); > 495 break; > 496 } > 497 #endif 482 498 483 default: { 499 default: { 484 rc = SQLITE_ERROR; 500 rc = SQLITE_ERROR; 485 break; 501 break; 486 } 502 } 487 } 503 } 488 va_end(ap); 504 va_end(ap); ................................................................................................................................................................................ 814 */ 830 */ 815 if( !forceZombie && connectionIsBusy(db) ){ 831 if( !forceZombie && connectionIsBusy(db) ){ 816 sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " 832 sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " 817 "statements or unfinished backups"); 833 "statements or unfinished backups"); 818 sqlite3_mutex_leave(db->mutex); 834 sqlite3_mutex_leave(db->mutex); 819 return SQLITE_BUSY; 835 return SQLITE_BUSY; 820 } 836 } > 837 > 838 #ifdef SQLITE_ENABLE_SQLLOG > 839 if( sqlite3GlobalConfig.xSqllog ){ > 840 sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 0); > 841 } > 842 #endif 821 843 822 /* Convert the connection into a zombie and then close it. 844 /* Convert the connection into a zombie and then close it. 823 */ 845 */ 824 db->magic = SQLITE_MAGIC_ZOMBIE; 846 db->magic = SQLITE_MAGIC_ZOMBIE; 825 sqlite3LeaveMutexAndCloseZombie(db); 847 sqlite3LeaveMutexAndCloseZombie(db); 826 return SQLITE_OK; 848 return SQLITE_OK; 827 } 849 } ................................................................................................................................................................................ 2447 if( rc==SQLITE_NOMEM ){ 2469 if( rc==SQLITE_NOMEM ){ 2448 sqlite3_close(db); 2470 sqlite3_close(db); 2449 db = 0; 2471 db = 0; 2450 }else if( rc!=SQLITE_OK ){ 2472 }else if( rc!=SQLITE_OK ){ 2451 db->magic = SQLITE_MAGIC_SICK; 2473 db->magic = SQLITE_MAGIC_SICK; 2452 } 2474 } 2453 *ppDb = db; 2475 *ppDb = db; > 2476 #ifdef SQLITE_ENABLE_SQLLOG > 2477 if( sqlite3GlobalConfig.xSqllog ){ > 2478 sqlite3GlobalConfig.xSqllog( > 2479 sqlite3GlobalConfig.pSqllogArg, db, zFilename, -1 > 2480 ); > 2481 } > 2482 #endif 2454 return sqlite3ApiExit(0, rc); 2483 return sqlite3ApiExit(0, rc); 2455 } 2484 } 2456 2485 2457 /* 2486 /* 2458 ** Open a new database handle. 2487 ** Open a new database handle. 2459 */ 2488 */ 2460 int sqlite3_open( 2489 int sqlite3_open(

Changes to src/sqlite.h.in

1589 ** without change even with newer versions of SQLite. 1589 ** without change even with newer versions of SQLite. 1590 ** 1590 ** 1591 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] 1591 ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] 1592 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE 1592 ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE 1593 ** <dd> These options are obsolete and should not be used by new code. 1593 ** <dd> These options are obsolete and should not be used by new code. 1594 ** They are retained for backwards compatibility but are now no-ops. 1594 ** They are retained for backwards compatibility but are now no-ops. 1595 ** </dl> 1595 ** </dl> > 1596 ** > 1597 ** [[SQLITE_CONFIG_SQLLOG]] > 1598 ** <dt>SQLITE_CONFIG_SQLLOG > 1599 ** <dd>This option is only available if sqlite is compiled with the > 1600 ** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should > 1601 ** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). > 1602 ** The second should be of type (void*). > 1603 ** </dl> 1596 */ 1604 */ 1597 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ 1605 #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ 1598 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ 1606 #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ 1599 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ 1607 #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ 1600 #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ 1608 #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ 1601 #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ 1609 #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ 1602 #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ 1610 #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ ................................................................................................................................................................................ 1610 #define SQLITE_CONFIG_PCACHE 14 /* no-op */ 1618 #define SQLITE_CONFIG_PCACHE 14 /* no-op */ 1611 #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ 1619 #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ 1612 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ 1620 #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ 1613 #define SQLITE_CONFIG_URI 17 /* int */ 1621 #define SQLITE_CONFIG_URI 17 /* int */ 1614 #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ 1622 #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ 1615 #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ 1623 #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ 1616 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ 1624 #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ > 1625 #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ 1617 1626 1618 /* 1627 /* 1619 ** CAPI3REF: Database Connection Configuration Options 1628 ** CAPI3REF: Database Connection Configuration Options 1620 ** 1629 ** 1621 ** These constants are the available integer configuration options that 1630 ** These constants are the available integer configuration options that 1622 ** can be passed as the second argument to the [sqlite3_db_config()] interface. 1631 ** can be passed as the second argument to the [sqlite3_db_config()] interface. 1623 ** 1632 **

Changes to src/sqliteInt.h

2511 int isMallocInit; /* True after malloc is initialized */ 2511 int isMallocInit; /* True after malloc is initialized */ 2512 int isPCacheInit; /* True after malloc is initialized */ 2512 int isPCacheInit; /* True after malloc is initialized */ 2513 sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ 2513 sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ 2514 int nRefInitMutex; /* Number of users of pInitMutex */ 2514 int nRefInitMutex; /* Number of users of pInitMutex */ 2515 void (*xLog)(void*,int,const char*); /* Function for logging */ 2515 void (*xLog)(void*,int,const char*); /* Function for logging */ 2516 void *pLogArg; /* First argument to xLog() */ 2516 void *pLogArg; /* First argument to xLog() */ 2517 int bLocaltimeFault; /* True to fail localtime() calls */ 2517 int bLocaltimeFault; /* True to fail localtime() calls */ > 2518 #ifdef SQLITE_ENABLE_SQLLOG > 2519 void(*xSqllog)(void*,sqlite3*,const char*, int); > 2520 void *pSqllogArg; > 2521 #endif 2518 }; 2522 }; 2519 2523 2520 /* 2524 /* 2521 ** Context pointer passed down through the tree-walk. 2525 ** Context pointer passed down through the tree-walk. 2522 */ 2526 */ 2523 struct Walker { 2527 struct Walker { 2524 int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ 2528 int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */

Added src/test_sqllog.c

> 1 /* > 2 ** 2012 November 26 > 3 ** > 4 ** The author disclaims copyright to this source code. In place of > 5 ** a legal notice, here is a blessing: > 6 ** > 7 ** May you do good and not evil. > 8 ** May you find forgiveness for yourself and forgive others. > 9 ** May you share freely, never taking more than you give. > 10 ** > 11 ************************************************************************* > 12 ** > 13 ** OVERVIEW > 14 ** > 15 ** This file contains experimental code used to record data from live > 16 ** SQLite applications that may be useful for offline analysis. Specifically: > 17 ** > 18 ** 1) The initial contents of all database files opened by the > 19 ** application, and > 20 ** > 21 ** 2) All SQL statements executed by the application. > 22 ** > 23 ** USAGE > 24 ** > 25 ** To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG > 26 ** pre-processor symbol defined and this file linked into the application > 27 ** somehow. > 28 ** > 29 ** At runtime, logging is enabled by setting environment variable > 30 ** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged > 31 ** data. The directory must already exist. > 32 ** > 33 ** Usually, if the application opens the same database file more than once > 34 ** (either by attaching it or by using more than one database handle), only > 35 ** a single copy is made. This behaviour may be overridden (so that a > 36 ** separate copy is taken each time the database file is opened or attached) > 37 ** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0. > 38 ** > 39 ** OUTPUT: > 40 ** > 41 ** The SQLITE_SQLLOG_DIR is populated with three types of files: > 42 ** > 43 ** sqllog_N.db - Copies of database files. N may be any integer. > 44 ** > 45 ** sqllog_N.sql - A list of SQL statements executed by a single > 46 ** connection. N may be any integer. > 47 ** > 48 ** sqllog.idx - An index mapping from integer N to a database > 49 ** file name - indicating the full path of the > 50 ** database from which sqllog_N.db was copied. > 51 */ > 52 > 53 #include "sqlite3.h" > 54 #include "stdio.h" > 55 #include "stdlib.h" > 56 #include "string.h" > 57 #include "assert.h" > 58 > 59 #define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR" > 60 #define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES" > 61 > 62 /* Assume that all database and database file names are shorted than this. */ > 63 #define SQLLOG_NAMESZ 512 > 64 > 65 /* Maximum number of simultaneous database connections the process may > 66 ** open (if any more are opened an error is logged using sqlite3_log() > 67 ** and processing is halted). > 68 */ > 69 #define MAX_CONNECTIONS 256 > 70 > 71 struct SLConn { > 72 int isErr; /* True if an error has occurred */ > 73 sqlite3 *db; /* Connection handle */ > 74 int iLog; /* First integer value used in file names */ > 75 FILE *fd; /* File descriptor for log file */ > 76 }; > 77 > 78 struct SLGlobal { > 79 /* Protected by MUTEX_STATIC_MASTER */ > 80 sqlite3_mutex *mutex; /* Recursive mutex */ > 81 int nConn; /* Size of aConn[] array */ > 82 > 83 /* Protected by SLGlobal.mutex */ > 84 int bReuse; /* True to avoid extra copies of db files */ > 85 char zDir[SQLLOG_NAMESZ]; /* Directory to create files in */ > 86 char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */ > 87 int iNextLog; /* Used to allocate file names */ > 88 int iNextDb; /* Used to allocate database file names */ > 89 int bRec; /* True if testSqllog() is called rec. */ > 90 int iClock; /* Clock value */ > 91 struct SLConn aConn[MAX_CONNECTIONS]; > 92 } sqllogglobal; > 93 > 94 /* > 95 ** Return true if c is an ASCII whitespace character. > 96 */ > 97 static int sqllog_isspace(char c){ > 98 return (c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r'); > 99 } > 100 > 101 /* > 102 ** The first argument points to a nul-terminated string containing an SQL > 103 ** command. Before returning, this function sets *pz to point to the start > 104 ** of the first token in this command, and *pn to the number of bytes in > 105 ** the token. This is used to check if the SQL command is an "ATTACH" or > 106 ** not. > 107 */ > 108 static void sqllogTokenize(const char *z, const char **pz, int *pn){ > 109 const char *p = z; > 110 int n; > 111 > 112 /* Skip past any whitespace */ > 113 while( sqllog_isspace(*p) ){ > 114 p++; > 115 } > 116 > 117 /* Figure out how long the first token is */ > 118 *pz = p; > 119 n = 0; > 120 while( (p[n]>='a' && p[n]<='z') || (p[n]>='A' && p[n]<='Z') ) n++; > 121 *pn = n; > 122 } > 123 > 124 /* > 125 ** Check if the logs directory already contains a copy of database file > 126 ** zFile. If so, return a pointer to the full path of the copy. Otherwise, > 127 ** return NULL. > 128 ** > 129 ** If a non-NULL value is returned, then the caller must arrange to > 130 ** eventually free it using sqlite3_free(). > 131 */ > 132 static char *sqllogFindFile(const char *zFile){ > 133 char *zRet = 0; > 134 FILE *fd = 0; > 135 > 136 /* Open the index file for reading */ > 137 fd = fopen(sqllogglobal.zIdx, "r"); > 138 > 139 while( feof(fd)==0 ){ > 140 char *z; > 141 int n; > 142 char zLine[SQLLOG_NAMESZ*2+5]; > 143 > 144 fgets(zLine, sizeof(zLine), fd); > 145 z = zLine; > 146 while( *z>='0' && *z<='9' ) z++; > 147 while( *z==' ' ) z++; > 148 > 149 n = strlen(z); > 150 while( n>0 && sqllog_isspace(z[n-1]) ) n--; > 151 if( n==strlen(zFile) && 0==memcmp(zFile, z, n) ){ > 152 char zBuf[16]; > 153 z = zLine; > 154 while( *z>='0' && *z<='9' ){ > 155 zBuf[z-zLine] = *z; > 156 z++; > 157 } > 158 zRet = sqlite3_mprintf("%s/sqllog_%s.db", sqllogglobal.zDir, zBuf); > 159 break; > 160 } > 161 } > 162 > 163 fclose(fd); > 164 return zRet; > 165 } > 166 > 167 static void sqllogFindAttached( > 168 struct SLConn *p, /* Database connection */ > 169 const char *zSearch, /* Name to search for (or NULL) */ > 170 char *zName, /* OUT: Name of attached database */ > 171 char *zFile /* OUT: Name of attached file */ > 172 ){ > 173 sqlite3_stmt *pStmt; > 174 int rc; > 175 > 176 /* The "PRAGMA database_list" command returns a list of databases in the > 177 ** order that they were attached. So a newly attached database is > 178 ** described by the last row returned. */ > 179 assert( sqllogglobal.bRec==0 ); > 180 sqllogglobal.bRec = 1; > 181 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); > 182 if( rc==SQLITE_OK ){ > 183 while( SQLITE_ROW==sqlite3_step(pStmt) ){ > 184 char *zVal1; int nVal1; > 185 char *zVal2; int nVal2; > 186 > 187 zVal1 = sqlite3_column_text(pStmt, 1); > 188 nVal1 = sqlite3_column_bytes(pStmt, 1); > 189 memcpy(zName, zVal1, nVal1+1); > 190 > 191 zVal2 = sqlite3_column_text(pStmt, 2); > 192 nVal2 = sqlite3_column_bytes(pStmt, 2); > 193 memcpy(zFile, zVal2, nVal2+1); > 194 > 195 if( zSearch && strlen(zSearch)==nVal1 > 196 && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1) > 197 ){ > 198 break; > 199 } > 200 } > 201 rc = sqlite3_finalize(pStmt); > 202 } > 203 sqllogglobal.bRec = 0; > 204 } > 205 > 206 > 207 /* > 208 ** Parameter zSearch is the name of a database attached to the database > 209 ** connection associated with the first argument. This function creates > 210 ** a backup of this database in the logs directory. > 211 ** > 212 ** The name used for the backup file is automatically generated. Call > 213 ** it zFile. > 214 ** > 215 ** If the bLog parameter is true, then a statement of the following form > 216 ** is written to the log file associated with *p: > 217 ** > 218 ** ATTACH 'zFile' AS 'zName'; > 219 ** > 220 ** Otherwise, if bLog is false, a comment is added to the log file: > 221 ** > 222 ** -- Main database file is 'zFile' > 223 ** > 224 ** The SLGlobal.mutex mutex is always held when this function is called. > 225 */ > 226 static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){ > 227 char zName[SQLLOG_NAMESZ]; /* Attached database name */ > 228 char zFile[SQLLOG_NAMESZ]; /* Database file name */ > 229 char *zFree; > 230 char *zInit = 0; > 231 > 232 sqllogFindAttached(p, zSearch, zName, zFile); > 233 if( zFile[0]=='\0' ){ > 234 zInit = sqlite3_mprintf(""); > 235 }else{ > 236 if( sqllogglobal.bReuse ){ > 237 zInit = sqllogFindFile(zFile); > 238 }else{ > 239 zInit = 0; > 240 } > 241 if( zInit==0 ){ > 242 int rc; > 243 sqlite3 *copy = 0; > 244 FILE *fd; > 245 int iDb; > 246 > 247 /* Generate a file-name to use for the copy of this database */ > 248 iDb = sqllogglobal.iNextDb++; > 249 zInit = sqlite3_mprintf("%s/sqllog_%d.db", sqllogglobal.zDir, iDb); > 250 > 251 /* Create the backup */ > 252 assert( sqllogglobal.bRec==0 ); > 253 sqllogglobal.bRec = 1; > 254 rc = sqlite3_open(zInit, &copy); > 255 if( rc==SQLITE_OK ){ > 256 sqlite3_backup *pBak; > 257 sqlite3_exec(copy, "PRAGMA synchronous = 0", 0, 0, 0); > 258 pBak = sqlite3_backup_init(copy, "main", p->db, zName); > 259 if( pBak ){ > 260 sqlite3_backup_step(pBak, -1); > 261 sqlite3_backup_finish(pBak); > 262 } > 263 sqlite3_close(copy); > 264 } > 265 sqllogglobal.bRec = 0; > 266 > 267 /* Write an entry into the database index file */ > 268 fd = fopen(sqllogglobal.zIdx, "a"); > 269 fprintf(fd, "%d %s\n", iDb, zFile); > 270 fclose(fd); > 271 } > 272 } > 273 > 274 if( bLog ){ > 275 zFree = sqlite3_mprintf("ATTACH '%q' AS '%q'; -- clock=%d steps=1\n", > 276 zInit, zName, sqllogglobal.iClock++ > 277 ); > 278 }else{ > 279 zFree = sqlite3_mprintf("-- Main database is '%q'\n", zInit); > 280 } > 281 fprintf(p->fd, "%s", zFree); > 282 sqlite3_free(zFree); > 283 > 284 sqlite3_free(zInit); > 285 } > 286 > 287 /* > 288 ** If it is not already open, open the log file for connection *p. > 289 ** > 290 ** The SLGlobal.mutex mutex is always held when this function is called. > 291 */ > 292 static void sqllogOpenlog(struct SLConn *p){ > 293 /* If the log file has not yet been opened, open it now. */ > 294 if( p->fd==0 ){ > 295 char *zLog; > 296 > 297 /* If it is still NULL, have global.zDir point to a copy of environment > 298 ** variable $ENVIRONMENT_VARIABLE1_NAME. */ > 299 if( sqllogglobal.zDir[0]==0 ){ > 300 FILE *fd; > 301 char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); > 302 if( zVar==0 || strlen(zVar)>=(sizeof(sqllogglobal.zDir)) ) return; > 303 memcpy(sqllogglobal.zDir, zVar, strlen(zVar)+1); > 304 sprintf(sqllogglobal.zIdx, "%s/sqllog.idx", sqllogglobal.zDir); > 305 if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ > 306 sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); > 307 } > 308 fd = fopen(sqllogglobal.zIdx, "w"); > 309 close(fd); > 310 } > 311 > 312 /* Open the log file */ > 313 zLog = sqlite3_mprintf("%s/sqllog_%d.sql", sqllogglobal.zDir, p->iLog); > 314 p->fd = fopen(zLog, "w"); > 315 assert( p->fd ); > 316 sqlite3_free(zLog); > 317 } > 318 } > 319 > 320 /* > 321 ** This function is called if the SQLLOG callback is invoked to report > 322 ** execution of an SQL statement. Parameter p is the connection the statement > 323 ** was executed by, parameter zSql is the text of the statement itself and > 324 ** parameter nStep is the number of times sqlite3_step() was called. > 325 */ > 326 static void testSqllogStmt(struct SLConn *p, const char *zSql, int nStep){ > 327 const char *zFirst; /* Pointer to first token in zSql */ > 328 int nFirst; /* Size of token zFirst in bytes */ > 329 > 330 assert( nStep>0 ); > 331 > 332 sqllogTokenize(zSql, &zFirst, &nFirst); > 333 if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){ > 334 /* Not an ATTACH statement. Write this directly to the log. */ > 335 fprintf(p->fd, "%s; -- clock=%d steps=%d\n", > 336 zSql, sqllogglobal.iClock++, nStep > 337 ); > 338 }else{ > 339 /* This is an ATTACH statement. Copy the database. */ > 340 sqllogCopydb(p, 0, 1); > 341 } > 342 } > 343 > 344 /* > 345 ** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog(). > 346 */ > 347 static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int nStep){ > 348 struct SLConn *p; > 349 sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); > 350 > 351 #if 0 > 352 if( sqllogglobal.isErr && zSql ){ > 353 /* If an error has already occurred, ignore all callbacks except > 354 ** those reporting calls to sqlite3_close(). */ > 355 return; > 356 } > 357 #endif > 358 > 359 /* This is a database open command. */ > 360 if( zSql && nStep<0 ){ > 361 sqlite3_mutex_enter(master); > 362 if( sqllogglobal.mutex==0 ){ > 363 sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); > 364 } > 365 p = &sqllogglobal.aConn[sqllogglobal.nConn++]; > 366 p->fd = 0; > 367 p->db = db; > 368 p->iLog = sqllogglobal.iNextLog++; > 369 sqlite3_mutex_leave(master); > 370 > 371 /* Open the log and take a copy of the main database file */ > 372 sqlite3_mutex_enter(sqllogglobal.mutex); > 373 if( sqllogglobal.bRec==0 ){ > 374 sqllogOpenlog(p); > 375 sqllogCopydb(p, "main", 0); > 376 } > 377 sqlite3_mutex_leave(sqllogglobal.mutex); > 378 } > 379 > 380 else{ > 381 > 382 int i; > 383 for(i=0; i<sqllogglobal.nConn; i++){ > 384 p = &sqllogglobal.aConn[i]; > 385 if( p->db==db ) break; > 386 } > 387 if( i==sqllogglobal.nConn ) return; > 388 > 389 /* A database handle close command */ > 390 if( zSql==0 ){ > 391 sqlite3_mutex_enter(master); > 392 if( p->fd ) fclose(p->fd); > 393 p->db = 0; > 394 p->fd = 0; > 395 > 396 sqllogglobal.nConn--; > 397 if( sqllogglobal.nConn==0 ){ > 398 sqlite3_mutex_free(sqllogglobal.mutex); > 399 sqllogglobal.mutex = 0; > 400 }else{ > 401 int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p; > 402 if( nShift>0 ){ > 403 memmove(p, &p[1], nShift*sizeof(struct SLConn)); > 404 } > 405 } > 406 sqlite3_mutex_leave(master); > 407 > 408 /* An ordinary SQL command. */ > 409 }else{ > 410 sqlite3_mutex_enter(sqllogglobal.mutex); > 411 if( sqllogglobal.bRec==0 ){ > 412 testSqllogStmt(p, zSql, nStep); > 413 } > 414 sqlite3_mutex_leave(sqllogglobal.mutex); > 415 } > 416 } > 417 } > 418 > 419 /* > 420 ** This function is called either before sqlite3_initialized() or by it. > 421 ** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so > 422 ** registers an SQLITE_CONFIG_SQLLOG callback to record the applications > 423 ** database activity. > 424 */ > 425 void sqlite3_init_sqllog(void){ > 426 if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){ > 427 if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){ > 428 memset(&sqllogglobal, 0, sizeof(sqllogglobal)); > 429 sqllogglobal.bReuse = 1; > 430 } > 431 } > 432 } > 433

Changes to src/vdbeaux.c

49 49 50 /* 50 /* 51 ** Remember the SQL string for a prepared statement. 51 ** Remember the SQL string for a prepared statement. 52 */ 52 */ 53 void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ 53 void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ 54 assert( isPrepareV2==1 || isPrepareV2==0 ); 54 assert( isPrepareV2==1 || isPrepareV2==0 ); 55 if( p==0 ) return; 55 if( p==0 ) return; 56 #ifdef SQLITE_OMIT_TRACE | 56 #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) 57 if( !isPrepareV2 ) return; 57 if( !isPrepareV2 ) return; 58 #endif 58 #endif 59 assert( p->zSql==0 ); 59 assert( p->zSql==0 ); 60 p->zSql = sqlite3DbStrNDup(p->db, z, n); 60 p->zSql = sqlite3DbStrNDup(p->db, z, n); 61 p->isPrepareV2 = (u8)isPrepareV2; 61 p->isPrepareV2 = (u8)isPrepareV2; 62 } 62 } 63 63 ................................................................................................................................................................................ 2322 db->errCode = rc; 2322 db->errCode = rc; 2323 }else{ 2323 }else{ 2324 sqlite3Error(db, rc, 0); 2324 sqlite3Error(db, rc, 0); 2325 } 2325 } 2326 return rc; 2326 return rc; 2327 } 2327 } 2328 2328 > 2329 #ifdef SQLITE_ENABLE_SQLLOG > 2330 /* > 2331 ** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, > 2332 ** invoke it. > 2333 */ > 2334 static void vdbeInvokeSqllog(Vdbe *v){ > 2335 if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ > 2336 char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); > 2337 assert( v->db->init.busy==0 ); > 2338 if( zExpanded ){ > 2339 sqlite3GlobalConfig.xSqllog( > 2340 sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1 > 2341 ); > 2342 sqlite3DbFree(v->db, zExpanded); > 2343 } > 2344 } > 2345 } > 2346 #else > 2347 # define vdbeInvokeSqllog(x) > 2348 #endif > 2349 2329 /* 2350 /* 2330 ** Clean up a VDBE after execution but do not delete the VDBE just yet. 2351 ** Clean up a VDBE after execution but do not delete the VDBE just yet. 2331 ** Write any error messages into *pzErrMsg. Return the result code. 2352 ** Write any error messages into *pzErrMsg. Return the result code. 2332 ** 2353 ** 2333 ** After this routine is run, the VDBE should be ready to be executed 2354 ** After this routine is run, the VDBE should be ready to be executed 2334 ** again. 2355 ** again. 2335 ** 2356 ** ................................................................................................................................................................................ 2349 2370 2350 /* If the VDBE has be run even partially, then transfer the error code 2371 /* If the VDBE has be run even partially, then transfer the error code 2351 ** and error message from the VDBE into the main database structure. But 2372 ** and error message from the VDBE into the main database structure. But 2352 ** if the VDBE has just been set to run but has not actually executed any 2373 ** if the VDBE has just been set to run but has not actually executed any 2353 ** instructions yet, leave the main database error information unchanged. 2374 ** instructions yet, leave the main database error information unchanged. 2354 */ 2375 */ 2355 if( p->pc>=0 ){ 2376 if( p->pc>=0 ){ > 2377 vdbeInvokeSqllog(p); 2356 sqlite3VdbeTransferError(p); 2378 sqlite3VdbeTransferError(p); 2357 sqlite3DbFree(db, p->zErrMsg); 2379 sqlite3DbFree(db, p->zErrMsg); 2358 p->zErrMsg = 0; 2380 p->zErrMsg = 0; 2359 if( p->runOnlyOnce ) p->expired = 1; 2381 if( p->runOnlyOnce ) p->expired = 1; 2360 }else if( p->rc && p->expired ){ 2382 }else if( p->rc && p->expired ){ 2361 /* The expired flag was set on the VDBE before the first call 2383 /* The expired flag was set on the VDBE before the first call 2362 ** to sqlite3_step(). For consistency (since sqlite3_step() was 2384 ** to sqlite3_step(). For consistency (since sqlite3_step() was