Fossil SCM
Attempt to improve error messages resulting from SQL errors.
Commit
b94e15cff72b105e9fa6ecbf404baeb4036827bd1b6fb75ed7459574fba2c361
Parent
10a57cece17e70f…
1 file changed
+28
-13
M
src/db.c
+28
-13
| --- src/db.c | ||
| +++ src/db.c | ||
| @@ -88,10 +88,22 @@ | ||
| 88 | 88 | @ error Database\serror:\s%F(z) |
| 89 | 89 | cgi_reply(); |
| 90 | 90 | } |
| 91 | 91 | fossil_fatal("Database error: %s", z); |
| 92 | 92 | } |
| 93 | + | |
| 94 | +/* | |
| 95 | +** Check a result code. If it is not SQLITE_OK, print the | |
| 96 | +** corresponding error message and exit. | |
| 97 | +*/ | |
| 98 | +static void db_check_result(int rc, Stmt *pStmt){ | |
| 99 | + if( rc!=SQLITE_OK ){ | |
| 100 | + db_err("SQL error (%d,%d: %s) while running [%s]", | |
| 101 | + rc, sqlite3_extended_errcode(g.db), | |
| 102 | + sqlite3_errmsg(g.db), blob_str(&pStmt->sql)); | |
| 103 | + } | |
| 104 | +} | |
| 93 | 105 | |
| 94 | 106 | /* |
| 95 | 107 | ** All static variable that a used by only this file are gathered into |
| 96 | 108 | ** the following structure. |
| 97 | 109 | */ |
| @@ -478,11 +490,11 @@ | ||
| 478 | 490 | */ |
| 479 | 491 | int db_reset(Stmt *pStmt){ |
| 480 | 492 | int rc; |
| 481 | 493 | db_stats(pStmt); |
| 482 | 494 | rc = sqlite3_reset(pStmt->pStmt); |
| 483 | - db_check_result(rc); | |
| 495 | + db_check_result(rc, pStmt); | |
| 484 | 496 | return rc; |
| 485 | 497 | } |
| 486 | 498 | int db_finalize(Stmt *pStmt){ |
| 487 | 499 | int rc; |
| 488 | 500 | if( pStmt->pNext ){ |
| @@ -496,11 +508,11 @@ | ||
| 496 | 508 | pStmt->pNext = 0; |
| 497 | 509 | pStmt->pPrev = 0; |
| 498 | 510 | db_stats(pStmt); |
| 499 | 511 | blob_reset(&pStmt->sql); |
| 500 | 512 | rc = sqlite3_finalize(pStmt->pStmt); |
| 501 | - db_check_result(rc); | |
| 513 | + db_check_result(rc, pStmt); | |
| 502 | 514 | pStmt->pStmt = 0; |
| 503 | 515 | return rc; |
| 504 | 516 | } |
| 505 | 517 | |
| 506 | 518 | /* |
| @@ -576,30 +588,33 @@ | ||
| 576 | 588 | void db_ephemeral_blob(Stmt *pStmt, int N, Blob *pBlob){ |
| 577 | 589 | blob_init(pBlob, sqlite3_column_blob(pStmt->pStmt, N), |
| 578 | 590 | sqlite3_column_bytes(pStmt->pStmt, N)); |
| 579 | 591 | } |
| 580 | 592 | |
| 581 | -/* | |
| 582 | -** Check a result code. If it is not SQLITE_OK, print the | |
| 583 | -** corresponding error message and exit. | |
| 584 | -*/ | |
| 585 | -void db_check_result(int rc){ | |
| 586 | - if( rc!=SQLITE_OK ){ | |
| 587 | - db_err("SQL error: %s", sqlite3_errmsg(g.db)); | |
| 588 | - } | |
| 589 | -} | |
| 590 | - | |
| 591 | 593 | /* |
| 592 | 594 | ** Execute a single prepared statement until it finishes. |
| 593 | 595 | */ |
| 594 | 596 | int db_exec(Stmt *pStmt){ |
| 595 | 597 | int rc; |
| 596 | 598 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 597 | 599 | rc = db_reset(pStmt); |
| 598 | - db_check_result(rc); | |
| 600 | + db_check_result(rc, pStmt); | |
| 599 | 601 | return rc; |
| 600 | 602 | } |
| 603 | + | |
| 604 | +/* | |
| 605 | +** COMMAND: test-db-exec-error | |
| 606 | +** | |
| 607 | +** Invoke the db_exec() interface with an erroneous SQL statement | |
| 608 | +** in order to verify the error handling logic. | |
| 609 | +*/ | |
| 610 | +void db_test_db_exec_cmd(void){ | |
| 611 | + Stmt err; | |
| 612 | + db_find_and_open_repository(0,0); | |
| 613 | + db_prepare(&err, "INSERT INTO repository.config(name) VALUES(NULL);"); | |
| 614 | + db_exec(&err); | |
| 615 | +} | |
| 601 | 616 | |
| 602 | 617 | /* |
| 603 | 618 | ** Print the output of one or more SQL queries on standard output. |
| 604 | 619 | ** This routine is used for debugging purposes only. |
| 605 | 620 | */ |
| 606 | 621 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -88,10 +88,22 @@ | |
| 88 | @ error Database\serror:\s%F(z) |
| 89 | cgi_reply(); |
| 90 | } |
| 91 | fossil_fatal("Database error: %s", z); |
| 92 | } |
| 93 | |
| 94 | /* |
| 95 | ** All static variable that a used by only this file are gathered into |
| 96 | ** the following structure. |
| 97 | */ |
| @@ -478,11 +490,11 @@ | |
| 478 | */ |
| 479 | int db_reset(Stmt *pStmt){ |
| 480 | int rc; |
| 481 | db_stats(pStmt); |
| 482 | rc = sqlite3_reset(pStmt->pStmt); |
| 483 | db_check_result(rc); |
| 484 | return rc; |
| 485 | } |
| 486 | int db_finalize(Stmt *pStmt){ |
| 487 | int rc; |
| 488 | if( pStmt->pNext ){ |
| @@ -496,11 +508,11 @@ | |
| 496 | pStmt->pNext = 0; |
| 497 | pStmt->pPrev = 0; |
| 498 | db_stats(pStmt); |
| 499 | blob_reset(&pStmt->sql); |
| 500 | rc = sqlite3_finalize(pStmt->pStmt); |
| 501 | db_check_result(rc); |
| 502 | pStmt->pStmt = 0; |
| 503 | return rc; |
| 504 | } |
| 505 | |
| 506 | /* |
| @@ -576,30 +588,33 @@ | |
| 576 | void db_ephemeral_blob(Stmt *pStmt, int N, Blob *pBlob){ |
| 577 | blob_init(pBlob, sqlite3_column_blob(pStmt->pStmt, N), |
| 578 | sqlite3_column_bytes(pStmt->pStmt, N)); |
| 579 | } |
| 580 | |
| 581 | /* |
| 582 | ** Check a result code. If it is not SQLITE_OK, print the |
| 583 | ** corresponding error message and exit. |
| 584 | */ |
| 585 | void db_check_result(int rc){ |
| 586 | if( rc!=SQLITE_OK ){ |
| 587 | db_err("SQL error: %s", sqlite3_errmsg(g.db)); |
| 588 | } |
| 589 | } |
| 590 | |
| 591 | /* |
| 592 | ** Execute a single prepared statement until it finishes. |
| 593 | */ |
| 594 | int db_exec(Stmt *pStmt){ |
| 595 | int rc; |
| 596 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 597 | rc = db_reset(pStmt); |
| 598 | db_check_result(rc); |
| 599 | return rc; |
| 600 | } |
| 601 | |
| 602 | /* |
| 603 | ** Print the output of one or more SQL queries on standard output. |
| 604 | ** This routine is used for debugging purposes only. |
| 605 | */ |
| 606 |
| --- src/db.c | |
| +++ src/db.c | |
| @@ -88,10 +88,22 @@ | |
| 88 | @ error Database\serror:\s%F(z) |
| 89 | cgi_reply(); |
| 90 | } |
| 91 | fossil_fatal("Database error: %s", z); |
| 92 | } |
| 93 | |
| 94 | /* |
| 95 | ** Check a result code. If it is not SQLITE_OK, print the |
| 96 | ** corresponding error message and exit. |
| 97 | */ |
| 98 | static void db_check_result(int rc, Stmt *pStmt){ |
| 99 | if( rc!=SQLITE_OK ){ |
| 100 | db_err("SQL error (%d,%d: %s) while running [%s]", |
| 101 | rc, sqlite3_extended_errcode(g.db), |
| 102 | sqlite3_errmsg(g.db), blob_str(&pStmt->sql)); |
| 103 | } |
| 104 | } |
| 105 | |
| 106 | /* |
| 107 | ** All static variable that a used by only this file are gathered into |
| 108 | ** the following structure. |
| 109 | */ |
| @@ -478,11 +490,11 @@ | |
| 490 | */ |
| 491 | int db_reset(Stmt *pStmt){ |
| 492 | int rc; |
| 493 | db_stats(pStmt); |
| 494 | rc = sqlite3_reset(pStmt->pStmt); |
| 495 | db_check_result(rc, pStmt); |
| 496 | return rc; |
| 497 | } |
| 498 | int db_finalize(Stmt *pStmt){ |
| 499 | int rc; |
| 500 | if( pStmt->pNext ){ |
| @@ -496,11 +508,11 @@ | |
| 508 | pStmt->pNext = 0; |
| 509 | pStmt->pPrev = 0; |
| 510 | db_stats(pStmt); |
| 511 | blob_reset(&pStmt->sql); |
| 512 | rc = sqlite3_finalize(pStmt->pStmt); |
| 513 | db_check_result(rc, pStmt); |
| 514 | pStmt->pStmt = 0; |
| 515 | return rc; |
| 516 | } |
| 517 | |
| 518 | /* |
| @@ -576,30 +588,33 @@ | |
| 588 | void db_ephemeral_blob(Stmt *pStmt, int N, Blob *pBlob){ |
| 589 | blob_init(pBlob, sqlite3_column_blob(pStmt->pStmt, N), |
| 590 | sqlite3_column_bytes(pStmt->pStmt, N)); |
| 591 | } |
| 592 | |
| 593 | /* |
| 594 | ** Execute a single prepared statement until it finishes. |
| 595 | */ |
| 596 | int db_exec(Stmt *pStmt){ |
| 597 | int rc; |
| 598 | while( (rc = db_step(pStmt))==SQLITE_ROW ){} |
| 599 | rc = db_reset(pStmt); |
| 600 | db_check_result(rc, pStmt); |
| 601 | return rc; |
| 602 | } |
| 603 | |
| 604 | /* |
| 605 | ** COMMAND: test-db-exec-error |
| 606 | ** |
| 607 | ** Invoke the db_exec() interface with an erroneous SQL statement |
| 608 | ** in order to verify the error handling logic. |
| 609 | */ |
| 610 | void db_test_db_exec_cmd(void){ |
| 611 | Stmt err; |
| 612 | db_find_and_open_repository(0,0); |
| 613 | db_prepare(&err, "INSERT INTO repository.config(name) VALUES(NULL);"); |
| 614 | db_exec(&err); |
| 615 | } |
| 616 | |
| 617 | /* |
| 618 | ** Print the output of one or more SQL queries on standard output. |
| 619 | ** This routine is used for debugging purposes only. |
| 620 | */ |
| 621 |