Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Fix an infinite recursion on db_err() that might occur if SQLite is unable to create the WAL file for a database due to lack of write permission on the containing directory. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
421fe24138cd443b0059bb51baec08f4 |
| User & Date: | drh 2017-12-13 19:16:52.254 |
Context
|
2017-12-13
| ||
| 20:36 | Improved error reporting when trying to write to a repository that is in a read-only directory. check-in: 500b0a2ae8 user: drh tags: trunk | |
| 19:16 | Fix an infinite recursion on db_err() that might occur if SQLite is unable to create the WAL file for a database due to lack of write permission on the containing directory. check-in: 421fe24138 user: drh tags: trunk | |
| 17:17 | Always generate timeline-data for a timeline even if the table has no check-ins and thus no graph. This causes the timeline-data scanner to continue looking for subsequent timelines. check-in: 3f31676492 user: drh tags: trunk | |
Changes
Changes to src/db.c.
| ︙ | ︙ | |||
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
** structure.
*/
struct Stmt {
Blob sql; /* The SQL for this statement */
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
Stmt *pNext, *pPrev; /* List of all unfinalized statements */
int nStep; /* Number of sqlite3_step() calls */
};
/*
** Copy this to initialize a Stmt object to a clean/empty state. This
** is useful to help avoid assertions when performing cleanup in some
** error handling cases.
*/
#define empty_Stmt_m {BLOB_INITIALIZER,NULL, NULL, NULL, 0}
#endif /* INTERFACE */
const struct Stmt empty_Stmt = empty_Stmt_m;
/*
** Call this routine when a database error occurs.
*/
static void db_err(const char *zFormat, ...){
va_list ap;
char *z;
int rc = 1;
va_start(ap, zFormat);
z = vmprintf(zFormat, ap);
va_end(ap);
#ifdef FOSSIL_ENABLE_JSON
if( g.json.isJsonMode ){
json_err( 0, z, 1 );
if( g.isHTTP ){
| > > > | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
** structure.
*/
struct Stmt {
Blob sql; /* The SQL for this statement */
sqlite3_stmt *pStmt; /* The results of sqlite3_prepare_v2() */
Stmt *pNext, *pPrev; /* List of all unfinalized statements */
int nStep; /* Number of sqlite3_step() calls */
int rc; /* Error from db_vprepare() */
};
/*
** Copy this to initialize a Stmt object to a clean/empty state. This
** is useful to help avoid assertions when performing cleanup in some
** error handling cases.
*/
#define empty_Stmt_m {BLOB_INITIALIZER,NULL, NULL, NULL, 0}
#endif /* INTERFACE */
const struct Stmt empty_Stmt = empty_Stmt_m;
/*
** Call this routine when a database error occurs.
*/
static void db_err(const char *zFormat, ...){
static int rcLooping = 0;
va_list ap;
char *z;
int rc = 1;
if( rcLooping ) exit(rcLooping);
va_start(ap, zFormat);
z = vmprintf(zFormat, ap);
va_end(ap);
#ifdef FOSSIL_ENABLE_JSON
if( g.json.isJsonMode ){
json_err( 0, z, 1 );
if( g.isHTTP ){
|
| ︙ | ︙ | |||
95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
g.cgiOutput = 0;
cgi_printf("<h1>Database Error</h1>\n<p>%h</p>\n", z);
cgi_reply();
}else{
fprintf(stderr, "%s: %s\n", g.argv[0], z);
}
free(z);
db_force_rollback();
fossil_exit(rc);
}
/*
** All static variable that a used by only this file are gathered into
** the following structure.
| > | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
g.cgiOutput = 0;
cgi_printf("<h1>Database Error</h1>\n<p>%h</p>\n", z);
cgi_reply();
}else{
fprintf(stderr, "%s: %s\n", g.argv[0], z);
}
free(z);
rcLooping = rc;
db_force_rollback();
fossil_exit(rc);
}
/*
** All static variable that a used by only this file are gathered into
** the following structure.
|
| ︙ | ︙ | |||
271 272 273 274 275 276 277 278 279 280 281 282 283 284 |
}
rc = sqlite3_prepare_v3(g.db, zSql, -1, prepFlags, &pStmt->pStmt, 0);
if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
}
pStmt->pNext = pStmt->pPrev = 0;
pStmt->nStep = 0;
return rc;
}
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
int rc;
va_list ap;
va_start(ap, zFormat);
rc = db_vprepare(pStmt, 0, zFormat, ap);
| > | 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
}
rc = sqlite3_prepare_v3(g.db, zSql, -1, prepFlags, &pStmt->pStmt, 0);
if( rc!=0 && (flags & DB_PREPARE_IGNORE_ERROR)!=0 ){
db_err("%s\n%s", sqlite3_errmsg(g.db), zSql);
}
pStmt->pNext = pStmt->pPrev = 0;
pStmt->nStep = 0;
pStmt->rc = rc;
return rc;
}
int db_prepare(Stmt *pStmt, const char *zFormat, ...){
int rc;
va_list ap;
va_start(ap, zFormat);
rc = db_vprepare(pStmt, 0, zFormat, ap);
|
| ︙ | ︙ | |||
357 358 359 360 361 362 363 364 365 366 367 368 369 370 |
/*
** Step the SQL statement. Return either SQLITE_ROW or an error code
** or SQLITE_OK if the statement finishes successfully.
*/
int db_step(Stmt *pStmt){
int rc;
rc = sqlite3_step(pStmt->pStmt);
pStmt->nStep++;
return rc;
}
/*
** Print warnings if a query is inefficient.
| > | 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
/*
** Step the SQL statement. Return either SQLITE_ROW or an error code
** or SQLITE_OK if the statement finishes successfully.
*/
int db_step(Stmt *pStmt){
int rc;
if( pStmt->pStmt==0 ) return pStmt->rc;
rc = sqlite3_step(pStmt->pStmt);
pStmt->nStep++;
return rc;
}
/*
** Print warnings if a query is inefficient.
|
| ︙ | ︙ |