OLD | NEW |
1 /* | 1 /* |
2 ** 2012 November 26 | 2 ** 2012 November 26 |
3 ** | 3 ** |
4 ** The author disclaims copyright to this source code. In place of | 4 ** The author disclaims copyright to this source code. In place of |
5 ** a legal notice, here is a blessing: | 5 ** a legal notice, here is a blessing: |
6 ** | 6 ** |
7 ** May you do good and not evil. | 7 ** May you do good and not evil. |
8 ** May you find forgiveness for yourself and forgive others. | 8 ** May you find forgiveness for yourself and forgive others. |
9 ** May you share freely, never taking more than you give. | 9 ** May you share freely, never taking more than you give. |
10 ** | 10 ** |
(...skipping 28 matching lines...) Expand all Loading... |
39 ** At runtime, logging is enabled by setting environment variable | 39 ** At runtime, logging is enabled by setting environment variable |
40 ** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged | 40 ** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged |
41 ** data. The logging directory must already exist. | 41 ** data. The logging directory must already exist. |
42 ** | 42 ** |
43 ** Usually, if the application opens the same database file more than once | 43 ** Usually, if the application opens the same database file more than once |
44 ** (either by attaching it or by using more than one database handle), only | 44 ** (either by attaching it or by using more than one database handle), only |
45 ** a single copy is made. This behavior may be overridden (so that a | 45 ** a single copy is made. This behavior may be overridden (so that a |
46 ** separate copy is taken each time the database file is opened or attached) | 46 ** separate copy is taken each time the database file is opened or attached) |
47 ** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0. | 47 ** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0. |
48 ** | 48 ** |
| 49 ** If the environment variable SQLITE_SQLLOG_CONDITIONAL is defined, then |
| 50 ** logging is only done for database connections if a file named |
| 51 ** "<database>-sqllog" exists in the same directly as the main database |
| 52 ** file when it is first opened ("<database>" is replaced by the actual |
| 53 ** name of the main database file). |
| 54 ** |
49 ** OUTPUT: | 55 ** OUTPUT: |
50 ** | 56 ** |
51 ** The SQLITE_SQLLOG_DIR is populated with three types of files: | 57 ** The SQLITE_SQLLOG_DIR is populated with three types of files: |
52 ** | 58 ** |
53 ** sqllog_N.db - Copies of database files. N may be any integer. | 59 ** sqllog_N.db - Copies of database files. N may be any integer. |
54 ** | 60 ** |
55 ** sqllog_N.sql - A list of SQL statements executed by a single | 61 ** sqllog_N.sql - A list of SQL statements executed by a single |
56 ** connection. N may be any integer. | 62 ** connection. N may be any integer. |
57 ** | 63 ** |
58 ** sqllog.idx - An index mapping from integer N to a database | 64 ** sqllog.idx - An index mapping from integer N to a database |
(...skipping 22 matching lines...) Expand all Loading... |
81 #if SQLITE_OS_WIN | 87 #if SQLITE_OS_WIN |
82 return (int)_getpid(); | 88 return (int)_getpid(); |
83 #else | 89 #else |
84 return (int)getpid(); | 90 return (int)getpid(); |
85 #endif | 91 #endif |
86 } | 92 } |
87 | 93 |
88 /* Names of environment variables to be used */ | 94 /* Names of environment variables to be used */ |
89 #define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR" | 95 #define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR" |
90 #define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES" | 96 #define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES" |
| 97 #define ENVIRONMENT_VARIABLE3_NAME "SQLITE_SQLLOG_CONDITIONAL" |
91 | 98 |
92 /* Assume that all database and database file names are shorted than this. */ | 99 /* Assume that all database and database file names are shorted than this. */ |
93 #define SQLLOG_NAMESZ 512 | 100 #define SQLLOG_NAMESZ 512 |
94 | 101 |
95 /* Maximum number of simultaneous database connections the process may | 102 /* Maximum number of simultaneous database connections the process may |
96 ** open (if any more are opened an error is logged using sqlite3_log() | 103 ** open (if any more are opened an error is logged using sqlite3_log() |
97 ** and processing is halted). | 104 ** and processing is halted). |
98 */ | 105 */ |
99 #define MAX_CONNECTIONS 256 | 106 #define MAX_CONNECTIONS 256 |
100 | 107 |
101 /* There is one instance of this object for each SQLite database connection | 108 /* There is one instance of this object for each SQLite database connection |
102 ** that is being logged. | 109 ** that is being logged. |
103 */ | 110 */ |
104 struct SLConn { | 111 struct SLConn { |
105 int isErr; /* True if an error has occurred */ | 112 int isErr; /* True if an error has occurred */ |
106 sqlite3 *db; /* Connection handle */ | 113 sqlite3 *db; /* Connection handle */ |
107 int iLog; /* First integer value used in file names */ | 114 int iLog; /* First integer value used in file names */ |
108 FILE *fd; /* File descriptor for log file */ | 115 FILE *fd; /* File descriptor for log file */ |
109 }; | 116 }; |
110 | 117 |
111 /* This object is a singleton that keeps track of all data loggers. | 118 /* This object is a singleton that keeps track of all data loggers. |
112 */ | 119 */ |
113 static struct SLGlobal { | 120 static struct SLGlobal { |
114 /* Protected by MUTEX_STATIC_MASTER */ | 121 /* Protected by MUTEX_STATIC_MASTER */ |
115 sqlite3_mutex *mutex; /* Recursive mutex */ | 122 sqlite3_mutex *mutex; /* Recursive mutex */ |
116 int nConn; /* Size of aConn[] array */ | 123 int nConn; /* Size of aConn[] array */ |
117 | 124 |
118 /* Protected by SLGlobal.mutex */ | 125 /* Protected by SLGlobal.mutex */ |
| 126 int bConditional; /* Only trace if *-sqllog file is present */ |
119 int bReuse; /* True to avoid extra copies of db files */ | 127 int bReuse; /* True to avoid extra copies of db files */ |
120 char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */ | 128 char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */ |
121 char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */ | 129 char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */ |
122 int iNextLog; /* Used to allocate file names */ | 130 int iNextLog; /* Used to allocate file names */ |
123 int iNextDb; /* Used to allocate database file names */ | 131 int iNextDb; /* Used to allocate database file names */ |
124 int bRec; /* True if testSqllog() is called rec. */ | 132 int bRec; /* True if testSqllog() is called rec. */ |
125 int iClock; /* Clock value */ | 133 int iClock; /* Clock value */ |
126 struct SLConn aConn[MAX_CONNECTIONS]; | 134 struct SLConn aConn[MAX_CONNECTIONS]; |
127 } sqllogglobal; | 135 } sqllogglobal; |
128 | 136 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 | 216 |
209 if( ferror(fd) ){ | 217 if( ferror(fd) ){ |
210 sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error reading index file"); | 218 sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error reading index file"); |
211 } | 219 } |
212 | 220 |
213 fclose(fd); | 221 fclose(fd); |
214 return zRet; | 222 return zRet; |
215 } | 223 } |
216 | 224 |
217 static int sqllogFindAttached( | 225 static int sqllogFindAttached( |
218 struct SLConn *p, /* Database connection */ | 226 sqlite3 *db, /* Database connection */ |
219 const char *zSearch, /* Name to search for (or NULL) */ | 227 const char *zSearch, /* Name to search for (or NULL) */ |
220 char *zName, /* OUT: Name of attached database */ | 228 char *zName, /* OUT: Name of attached database */ |
221 char *zFile /* OUT: Name of attached file */ | 229 char *zFile /* OUT: Name of attached file */ |
222 ){ | 230 ){ |
223 sqlite3_stmt *pStmt; | 231 sqlite3_stmt *pStmt; |
224 int rc; | 232 int rc; |
225 | 233 |
226 /* The "PRAGMA database_list" command returns a list of databases in the | 234 /* The "PRAGMA database_list" command returns a list of databases in the |
227 ** order that they were attached. So a newly attached database is | 235 ** order that they were attached. So a newly attached database is |
228 ** described by the last row returned. */ | 236 ** described by the last row returned. */ |
229 assert( sqllogglobal.bRec==0 ); | 237 assert( sqllogglobal.bRec==0 ); |
230 sqllogglobal.bRec = 1; | 238 sqllogglobal.bRec = 1; |
231 rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); | 239 rc = sqlite3_prepare_v2(db, "PRAGMA database_list", -1, &pStmt, 0); |
232 if( rc==SQLITE_OK ){ | 240 if( rc==SQLITE_OK ){ |
233 while( SQLITE_ROW==sqlite3_step(pStmt) ){ | 241 while( SQLITE_ROW==sqlite3_step(pStmt) ){ |
234 const char *zVal1; int nVal1; | 242 const char *zVal1; int nVal1; |
235 const char *zVal2; int nVal2; | 243 const char *zVal2; int nVal2; |
236 | 244 |
237 zVal1 = (const char*)sqlite3_column_text(pStmt, 1); | 245 zVal1 = (const char*)sqlite3_column_text(pStmt, 1); |
238 nVal1 = sqlite3_column_bytes(pStmt, 1); | 246 nVal1 = sqlite3_column_bytes(pStmt, 1); |
239 memcpy(zName, zVal1, nVal1+1); | 247 if( zName ){ |
| 248 memcpy(zName, zVal1, nVal1+1); |
| 249 } |
240 | 250 |
241 zVal2 = (const char*)sqlite3_column_text(pStmt, 2); | 251 zVal2 = (const char*)sqlite3_column_text(pStmt, 2); |
242 nVal2 = sqlite3_column_bytes(pStmt, 2); | 252 nVal2 = sqlite3_column_bytes(pStmt, 2); |
243 memcpy(zFile, zVal2, nVal2+1); | 253 memcpy(zFile, zVal2, nVal2+1); |
244 | 254 |
245 if( zSearch && strlen(zSearch)==nVal1 | 255 if( zSearch && strlen(zSearch)==nVal1 |
246 && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1) | 256 && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1) |
247 ){ | 257 ){ |
248 break; | 258 break; |
249 } | 259 } |
(...skipping 28 matching lines...) Expand all Loading... |
278 ** | 288 ** |
279 ** The SLGlobal.mutex mutex is always held when this function is called. | 289 ** The SLGlobal.mutex mutex is always held when this function is called. |
280 */ | 290 */ |
281 static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){ | 291 static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){ |
282 char zName[SQLLOG_NAMESZ]; /* Attached database name */ | 292 char zName[SQLLOG_NAMESZ]; /* Attached database name */ |
283 char zFile[SQLLOG_NAMESZ]; /* Database file name */ | 293 char zFile[SQLLOG_NAMESZ]; /* Database file name */ |
284 char *zFree; | 294 char *zFree; |
285 char *zInit = 0; | 295 char *zInit = 0; |
286 int rc; | 296 int rc; |
287 | 297 |
288 rc = sqllogFindAttached(p, zSearch, zName, zFile); | 298 rc = sqllogFindAttached(p->db, zSearch, zName, zFile); |
289 if( rc!=SQLITE_OK ) return; | 299 if( rc!=SQLITE_OK ) return; |
290 | 300 |
291 if( zFile[0]=='\0' ){ | 301 if( zFile[0]=='\0' ){ |
292 zInit = sqlite3_mprintf(""); | 302 zInit = sqlite3_mprintf(""); |
293 }else{ | 303 }else{ |
294 if( sqllogglobal.bReuse ){ | 304 if( sqllogglobal.bReuse ){ |
295 zInit = sqllogFindFile(zFile); | 305 zInit = sqllogFindFile(zFile); |
296 }else{ | 306 }else{ |
297 zInit = 0; | 307 zInit = 0; |
298 } | 308 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 /* If the log file has not yet been opened, open it now. */ | 368 /* If the log file has not yet been opened, open it now. */ |
359 if( p->fd==0 ){ | 369 if( p->fd==0 ){ |
360 char *zLog; | 370 char *zLog; |
361 | 371 |
362 /* If it is still NULL, have global.zPrefix point to a copy of | 372 /* If it is still NULL, have global.zPrefix point to a copy of |
363 ** environment variable $ENVIRONMENT_VARIABLE1_NAME. */ | 373 ** environment variable $ENVIRONMENT_VARIABLE1_NAME. */ |
364 if( sqllogglobal.zPrefix[0]==0 ){ | 374 if( sqllogglobal.zPrefix[0]==0 ){ |
365 FILE *fd; | 375 FILE *fd; |
366 char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); | 376 char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); |
367 if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return; | 377 if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return; |
368 sprintf(sqllogglobal.zPrefix, "%s/sqllog_%d", zVar, getProcessId()); | 378 sqlite3_snprintf(sizeof(sqllogglobal.zPrefix), sqllogglobal.zPrefix, |
369 sprintf(sqllogglobal.zIdx, "%s.idx", sqllogglobal.zPrefix); | 379 "%s/sqllog_%d", zVar, getProcessId()); |
| 380 sqlite3_snprintf(sizeof(sqllogglobal.zIdx), sqllogglobal.zIdx, |
| 381 "%s.idx", sqllogglobal.zPrefix); |
370 if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ | 382 if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ |
371 sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); | 383 sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); |
372 } | 384 } |
373 fd = fopen(sqllogglobal.zIdx, "w"); | 385 fd = fopen(sqllogglobal.zIdx, "w"); |
374 if( fd ) fclose(fd); | 386 if( fd ) fclose(fd); |
375 } | 387 } |
376 | 388 |
377 /* Open the log file */ | 389 /* Open the log file */ |
378 zLog = sqlite3_mprintf("%s_%d.sql", sqllogglobal.zPrefix, p->iLog); | 390 zLog = sqlite3_mprintf("%s_%d.sql", sqllogglobal.zPrefix, p->iLog); |
379 p->fd = fopen(zLog, "w"); | 391 p->fd = fopen(zLog, "w"); |
(...skipping 17 matching lines...) Expand all Loading... |
397 if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){ | 409 if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){ |
398 /* Not an ATTACH statement. Write this directly to the log. */ | 410 /* Not an ATTACH statement. Write this directly to the log. */ |
399 fprintf(p->fd, "%s; -- clock=%d\n", zSql, sqllogglobal.iClock++); | 411 fprintf(p->fd, "%s; -- clock=%d\n", zSql, sqllogglobal.iClock++); |
400 }else{ | 412 }else{ |
401 /* This is an ATTACH statement. Copy the database. */ | 413 /* This is an ATTACH statement. Copy the database. */ |
402 sqllogCopydb(p, 0, 1); | 414 sqllogCopydb(p, 0, 1); |
403 } | 415 } |
404 } | 416 } |
405 | 417 |
406 /* | 418 /* |
| 419 ** The database handle passed as the only argument has just been opened. |
| 420 ** Return true if this module should log initial databases and SQL |
| 421 ** statements for this connection, or false otherwise. |
| 422 ** |
| 423 ** If an error occurs, sqlite3_log() is invoked to report it to the user |
| 424 ** and zero returned. |
| 425 */ |
| 426 static int sqllogTraceDb(sqlite3 *db){ |
| 427 int bRet = 1; |
| 428 if( sqllogglobal.bConditional ){ |
| 429 char zFile[SQLLOG_NAMESZ]; /* Attached database name */ |
| 430 int rc = sqllogFindAttached(db, "main", 0, zFile); |
| 431 if( rc==SQLITE_OK ){ |
| 432 int nFile = strlen(zFile); |
| 433 if( (SQLLOG_NAMESZ-nFile)<8 ){ |
| 434 sqlite3_log(SQLITE_IOERR, |
| 435 "sqllogTraceDb(): database name too long (%d bytes)", nFile |
| 436 ); |
| 437 bRet = 0; |
| 438 }else{ |
| 439 memcpy(&zFile[nFile], "-sqllog", 8); |
| 440 bRet = !access(zFile, F_OK); |
| 441 } |
| 442 } |
| 443 } |
| 444 return bRet; |
| 445 } |
| 446 |
| 447 /* |
407 ** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog(). | 448 ** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog(). |
408 ** | 449 ** |
409 ** The eType parameter has the following values: | 450 ** The eType parameter has the following values: |
410 ** | 451 ** |
411 ** 0: Opening a new database connection. zSql is the name of the | 452 ** 0: Opening a new database connection. zSql is the name of the |
412 ** file being opened. db is a pointer to the newly created database | 453 ** file being opened. db is a pointer to the newly created database |
413 ** connection. | 454 ** connection. |
414 ** | 455 ** |
415 ** 1: An SQL statement has run to completion. zSql is the text of the | 456 ** 1: An SQL statement has run to completion. zSql is the text of the |
416 ** SQL statement with all parameters expanded to their actual values. | 457 ** SQL statement with all parameters expanded to their actual values. |
(...skipping 13 matching lines...) Expand all Loading... |
430 | 471 |
431 assert( eType==0 || eType==1 || eType==2 ); | 472 assert( eType==0 || eType==1 || eType==2 ); |
432 assert( (eType==2)==(zSql==0) ); | 473 assert( (eType==2)==(zSql==0) ); |
433 | 474 |
434 /* This is a database open command. */ | 475 /* This is a database open command. */ |
435 if( eType==0 ){ | 476 if( eType==0 ){ |
436 sqlite3_mutex_enter(master); | 477 sqlite3_mutex_enter(master); |
437 if( sqllogglobal.mutex==0 ){ | 478 if( sqllogglobal.mutex==0 ){ |
438 sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); | 479 sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); |
439 } | 480 } |
440 p = &sqllogglobal.aConn[sqllogglobal.nConn++]; | |
441 p->fd = 0; | |
442 p->db = db; | |
443 p->iLog = sqllogglobal.iNextLog++; | |
444 sqlite3_mutex_leave(master); | 481 sqlite3_mutex_leave(master); |
445 | 482 |
446 /* Open the log and take a copy of the main database file */ | |
447 sqlite3_mutex_enter(sqllogglobal.mutex); | 483 sqlite3_mutex_enter(sqllogglobal.mutex); |
448 if( sqllogglobal.bRec==0 ){ | 484 if( sqllogglobal.bRec==0 && sqllogTraceDb(db) ){ |
| 485 |
| 486 sqlite3_mutex_enter(master); |
| 487 p = &sqllogglobal.aConn[sqllogglobal.nConn++]; |
| 488 p->fd = 0; |
| 489 p->db = db; |
| 490 p->iLog = sqllogglobal.iNextLog++; |
| 491 sqlite3_mutex_leave(master); |
| 492 |
| 493 /* Open the log and take a copy of the main database file */ |
449 sqllogOpenlog(p); | 494 sqllogOpenlog(p); |
450 if( p->fd ) sqllogCopydb(p, "main", 0); | 495 if( p->fd ) sqllogCopydb(p, "main", 0); |
451 } | 496 } |
452 sqlite3_mutex_leave(sqllogglobal.mutex); | 497 sqlite3_mutex_leave(sqllogglobal.mutex); |
453 } | 498 } |
454 | 499 |
455 else{ | 500 else{ |
456 | 501 |
457 int i; | 502 int i; |
458 for(i=0; i<sqllogglobal.nConn; i++){ | 503 for(i=0; i<sqllogglobal.nConn; i++){ |
459 p = &sqllogglobal.aConn[i]; | 504 p = &sqllogglobal.aConn[i]; |
460 if( p->db==db ) break; | 505 if( p->db==db ) break; |
461 } | 506 } |
462 if( i==sqllogglobal.nConn ) return; | |
463 | 507 |
464 /* A database handle close command */ | 508 /* A database handle close command */ |
465 if( eType==2 ){ | 509 if( eType==2 ){ |
466 sqlite3_mutex_enter(master); | 510 sqlite3_mutex_enter(master); |
467 if( p->fd ) fclose(p->fd); | 511 if( i<sqllogglobal.nConn ){ |
468 p->db = 0; | 512 if( p->fd ) fclose(p->fd); |
469 p->fd = 0; | 513 p->db = 0; |
| 514 p->fd = 0; |
| 515 sqllogglobal.nConn--; |
| 516 } |
470 | 517 |
471 sqllogglobal.nConn--; | |
472 if( sqllogglobal.nConn==0 ){ | 518 if( sqllogglobal.nConn==0 ){ |
473 sqlite3_mutex_free(sqllogglobal.mutex); | 519 sqlite3_mutex_free(sqllogglobal.mutex); |
474 sqllogglobal.mutex = 0; | 520 sqllogglobal.mutex = 0; |
475 }else{ | 521 }else if( i<sqllogglobal.nConn ){ |
476 int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p; | 522 int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p; |
477 if( nShift>0 ){ | 523 if( nShift>0 ){ |
478 memmove(p, &p[1], nShift*sizeof(struct SLConn)); | 524 memmove(p, &p[1], nShift*sizeof(struct SLConn)); |
479 } | 525 } |
480 } | 526 } |
481 sqlite3_mutex_leave(master); | 527 sqlite3_mutex_leave(master); |
482 | 528 |
483 /* An ordinary SQL command. */ | 529 /* An ordinary SQL command. */ |
484 }else if( p->fd ){ | 530 }else if( i<sqllogglobal.nConn && p->fd ){ |
485 sqlite3_mutex_enter(sqllogglobal.mutex); | 531 sqlite3_mutex_enter(sqllogglobal.mutex); |
486 if( sqllogglobal.bRec==0 ){ | 532 if( sqllogglobal.bRec==0 ){ |
487 testSqllogStmt(p, zSql); | 533 testSqllogStmt(p, zSql); |
488 } | 534 } |
489 sqlite3_mutex_leave(sqllogglobal.mutex); | 535 sqlite3_mutex_leave(sqllogglobal.mutex); |
490 } | 536 } |
491 } | 537 } |
492 } | 538 } |
493 | 539 |
494 /* | 540 /* |
495 ** This function is called either before sqlite3_initialized() or by it. | 541 ** This function is called either before sqlite3_initialized() or by it. |
496 ** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so | 542 ** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so |
497 ** registers an SQLITE_CONFIG_SQLLOG callback to record the applications | 543 ** registers an SQLITE_CONFIG_SQLLOG callback to record the applications |
498 ** database activity. | 544 ** database activity. |
499 */ | 545 */ |
500 void sqlite3_init_sqllog(void){ | 546 void sqlite3_init_sqllog(void){ |
501 if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){ | 547 if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){ |
502 if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){ | 548 if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){ |
503 memset(&sqllogglobal, 0, sizeof(sqllogglobal)); | 549 memset(&sqllogglobal, 0, sizeof(sqllogglobal)); |
504 sqllogglobal.bReuse = 1; | 550 sqllogglobal.bReuse = 1; |
| 551 if( getenv(ENVIRONMENT_VARIABLE3_NAME) ){ |
| 552 sqllogglobal.bConditional = 1; |
| 553 } |
505 } | 554 } |
506 } | 555 } |
507 } | 556 } |
OLD | NEW |