diff options
Diffstat (limited to 'src/sqlite.c')
| -rw-r--r-- | src/sqlite.c | 173 |
1 files changed, 99 insertions, 74 deletions
diff --git a/src/sqlite.c b/src/sqlite.c index 54bfb7b6c61..1526e344e53 100644 --- a/src/sqlite.c +++ b/src/sqlite.c | |||
| @@ -51,6 +51,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double)); | |||
| 51 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); | 51 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); |
| 52 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); | 52 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); |
| 53 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); | 53 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); |
| 54 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errstr, (int)); | ||
| 54 | DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); | 55 | DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); |
| 55 | DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); | 56 | DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); |
| 56 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); | 57 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); |
| @@ -88,6 +89,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, | |||
| 88 | # undef sqlite3_bind_null | 89 | # undef sqlite3_bind_null |
| 89 | # undef sqlite3_bind_int | 90 | # undef sqlite3_bind_int |
| 90 | # undef sqlite3_errmsg | 91 | # undef sqlite3_errmsg |
| 92 | # undef sqlite3_errstr | ||
| 91 | # undef sqlite3_step | 93 | # undef sqlite3_step |
| 92 | # undef sqlite3_changes | 94 | # undef sqlite3_changes |
| 93 | # undef sqlite3_column_count | 95 | # undef sqlite3_column_count |
| @@ -112,6 +114,7 @@ DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, | |||
| 112 | # define sqlite3_bind_null fn_sqlite3_bind_null | 114 | # define sqlite3_bind_null fn_sqlite3_bind_null |
| 113 | # define sqlite3_bind_int fn_sqlite3_bind_int | 115 | # define sqlite3_bind_int fn_sqlite3_bind_int |
| 114 | # define sqlite3_errmsg fn_sqlite3_errmsg | 116 | # define sqlite3_errmsg fn_sqlite3_errmsg |
| 117 | # define sqlite3_errstr fn_sqlite3_errstr | ||
| 115 | # define sqlite3_step fn_sqlite3_step | 118 | # define sqlite3_step fn_sqlite3_step |
| 116 | # define sqlite3_changes fn_sqlite3_changes | 119 | # define sqlite3_changes fn_sqlite3_changes |
| 117 | # define sqlite3_column_count fn_sqlite3_column_count | 120 | # define sqlite3_column_count fn_sqlite3_column_count |
| @@ -139,6 +142,7 @@ load_dll_functions (HMODULE library) | |||
| 139 | LOAD_DLL_FN (library, sqlite3_bind_null); | 142 | LOAD_DLL_FN (library, sqlite3_bind_null); |
| 140 | LOAD_DLL_FN (library, sqlite3_bind_int); | 143 | LOAD_DLL_FN (library, sqlite3_bind_int); |
| 141 | LOAD_DLL_FN (library, sqlite3_errmsg); | 144 | LOAD_DLL_FN (library, sqlite3_errmsg); |
| 145 | LOAD_DLL_FN (library, sqlite3_errstr); | ||
| 142 | LOAD_DLL_FN (library, sqlite3_step); | 146 | LOAD_DLL_FN (library, sqlite3_step); |
| 143 | LOAD_DLL_FN (library, sqlite3_changes); | 147 | LOAD_DLL_FN (library, sqlite3_changes); |
| 144 | LOAD_DLL_FN (library, sqlite3_column_count); | 148 | LOAD_DLL_FN (library, sqlite3_column_count); |
| @@ -373,72 +377,6 @@ bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values) | |||
| 373 | return NULL; | 377 | return NULL; |
| 374 | } | 378 | } |
| 375 | 379 | ||
| 376 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, | ||
| 377 | doc: /* Execute a non-select SQL statement. | ||
| 378 | If VALUES is non-nil, it should be a vector or a list of values | ||
| 379 | to bind when executing a statement like | ||
| 380 | |||
| 381 | insert into foo values (?, ?, ...) | ||
| 382 | |||
| 383 | Value is the number of affected rows. */) | ||
| 384 | (Lisp_Object db, Lisp_Object query, Lisp_Object values) | ||
| 385 | { | ||
| 386 | check_sqlite (db, false); | ||
| 387 | CHECK_STRING (query); | ||
| 388 | if (!(NILP (values) || CONSP (values) || VECTORP (values))) | ||
| 389 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | ||
| 390 | |||
| 391 | sqlite3 *sdb = XSQLITE (db)->db; | ||
| 392 | Lisp_Object retval = Qnil; | ||
| 393 | const char *errmsg = NULL; | ||
| 394 | Lisp_Object encoded = encode_string (query); | ||
| 395 | sqlite3_stmt *stmt = NULL; | ||
| 396 | |||
| 397 | /* We only execute the first statement -- if there's several | ||
| 398 | (separated by a semicolon), the subsequent statements won't be | ||
| 399 | done. */ | ||
| 400 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); | ||
| 401 | if (ret != SQLITE_OK) | ||
| 402 | { | ||
| 403 | if (stmt != NULL) | ||
| 404 | { | ||
| 405 | sqlite3_finalize (stmt); | ||
| 406 | sqlite3_reset (stmt); | ||
| 407 | } | ||
| 408 | |||
| 409 | errmsg = sqlite3_errmsg (sdb); | ||
| 410 | goto exit; | ||
| 411 | } | ||
| 412 | |||
| 413 | /* Bind ? values. */ | ||
| 414 | if (!NILP (values)) { | ||
| 415 | const char *err = bind_values (sdb, stmt, values); | ||
| 416 | if (err != NULL) | ||
| 417 | { | ||
| 418 | errmsg = err; | ||
| 419 | goto exit; | ||
| 420 | } | ||
| 421 | } | ||
| 422 | |||
| 423 | ret = sqlite3_step (stmt); | ||
| 424 | sqlite3_finalize (stmt); | ||
| 425 | if (ret != SQLITE_OK && ret != SQLITE_DONE) | ||
| 426 | { | ||
| 427 | errmsg = sqlite3_errmsg (sdb); | ||
| 428 | goto exit; | ||
| 429 | } | ||
| 430 | |||
| 431 | retval = make_fixnum (sqlite3_changes (sdb)); | ||
| 432 | |||
| 433 | exit: | ||
| 434 | if (errmsg != NULL) | ||
| 435 | xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? | ||
| 436 | Qsqlite_locked_error: Qerror, | ||
| 437 | build_string (errmsg)); | ||
| 438 | |||
| 439 | return retval; | ||
| 440 | } | ||
| 441 | |||
| 442 | static Lisp_Object | 380 | static Lisp_Object |
| 443 | row_to_value (sqlite3_stmt *stmt) | 381 | row_to_value (sqlite3_stmt *stmt) |
| 444 | { | 382 | { |
| @@ -484,6 +422,94 @@ row_to_value (sqlite3_stmt *stmt) | |||
| 484 | } | 422 | } |
| 485 | 423 | ||
| 486 | static Lisp_Object | 424 | static Lisp_Object |
| 425 | sqlite_prepare_errmsg (int code, sqlite3 *sdb) | ||
| 426 | { | ||
| 427 | Lisp_Object errmsg = build_string (sqlite3_errstr (code)); | ||
| 428 | /* More details about what went wrong. */ | ||
| 429 | const char *sql_error = sqlite3_errmsg (sdb); | ||
| 430 | if (sql_error) | ||
| 431 | return CALLN (Fformat, build_string ("%s (%s)"), | ||
| 432 | errmsg, build_string (sql_error)); | ||
| 433 | else | ||
| 434 | return errmsg; | ||
| 435 | } | ||
| 436 | |||
| 437 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, | ||
| 438 | doc: /* Execute a non-select SQL statement. | ||
| 439 | If VALUES is non-nil, it should be a vector or a list of values | ||
| 440 | to bind when executing a statement like | ||
| 441 | |||
| 442 | insert into foo values (?, ?, ...) | ||
| 443 | |||
| 444 | Value is the number of affected rows. */) | ||
| 445 | (Lisp_Object db, Lisp_Object query, Lisp_Object values) | ||
| 446 | { | ||
| 447 | check_sqlite (db, false); | ||
| 448 | CHECK_STRING (query); | ||
| 449 | if (!(NILP (values) || CONSP (values) || VECTORP (values))) | ||
| 450 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | ||
| 451 | |||
| 452 | sqlite3 *sdb = XSQLITE (db)->db; | ||
| 453 | Lisp_Object errmsg = Qnil, | ||
| 454 | encoded = encode_string (query); | ||
| 455 | sqlite3_stmt *stmt = NULL; | ||
| 456 | |||
| 457 | /* We only execute the first statement -- if there's several | ||
| 458 | (separated by a semicolon), the subsequent statements won't be | ||
| 459 | done. */ | ||
| 460 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); | ||
| 461 | if (ret != SQLITE_OK) | ||
| 462 | { | ||
| 463 | if (stmt != NULL) | ||
| 464 | { | ||
| 465 | sqlite3_finalize (stmt); | ||
| 466 | sqlite3_reset (stmt); | ||
| 467 | } | ||
| 468 | |||
| 469 | errmsg = sqlite_prepare_errmsg (ret, sdb); | ||
| 470 | goto exit; | ||
| 471 | } | ||
| 472 | |||
| 473 | /* Bind ? values. */ | ||
| 474 | if (!NILP (values)) | ||
| 475 | { | ||
| 476 | const char *err = bind_values (sdb, stmt, values); | ||
| 477 | if (err != NULL) | ||
| 478 | { | ||
| 479 | errmsg = build_string (err); | ||
| 480 | goto exit; | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 484 | ret = sqlite3_step (stmt); | ||
| 485 | |||
| 486 | if (ret == SQLITE_ROW) | ||
| 487 | { | ||
| 488 | Lisp_Object data = Qnil; | ||
| 489 | do | ||
| 490 | data = Fcons (row_to_value (stmt), data); | ||
| 491 | while (sqlite3_step (stmt) == SQLITE_ROW); | ||
| 492 | |||
| 493 | sqlite3_finalize (stmt); | ||
| 494 | return Fnreverse (data); | ||
| 495 | } | ||
| 496 | else if (ret == SQLITE_OK || ret == SQLITE_DONE) | ||
| 497 | { | ||
| 498 | Lisp_Object rows = make_fixnum (sqlite3_changes (sdb)); | ||
| 499 | sqlite3_finalize (stmt); | ||
| 500 | return rows; | ||
| 501 | } | ||
| 502 | else | ||
| 503 | errmsg = build_string (sqlite3_errmsg (sdb)); | ||
| 504 | |||
| 505 | exit: | ||
| 506 | sqlite3_finalize (stmt); | ||
| 507 | xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? | ||
| 508 | Qsqlite_locked_error: Qerror, | ||
| 509 | errmsg); | ||
| 510 | } | ||
| 511 | |||
| 512 | static Lisp_Object | ||
| 487 | column_names (sqlite3_stmt *stmt) | 513 | column_names (sqlite3_stmt *stmt) |
| 488 | { | 514 | { |
| 489 | Lisp_Object columns = Qnil; | 515 | Lisp_Object columns = Qnil; |
| @@ -517,9 +543,8 @@ which means that we return a set object that can be queried with | |||
| 517 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | 543 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); |
| 518 | 544 | ||
| 519 | sqlite3 *sdb = XSQLITE (db)->db; | 545 | sqlite3 *sdb = XSQLITE (db)->db; |
| 520 | Lisp_Object retval = Qnil; | 546 | Lisp_Object retval = Qnil, errmsg = Qnil, |
| 521 | const char *errmsg = NULL; | 547 | encoded = encode_string (query); |
| 522 | Lisp_Object encoded = encode_string (query); | ||
| 523 | 548 | ||
| 524 | sqlite3_stmt *stmt = NULL; | 549 | sqlite3_stmt *stmt = NULL; |
| 525 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), SBYTES (encoded), | 550 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), SBYTES (encoded), |
| @@ -528,7 +553,7 @@ which means that we return a set object that can be queried with | |||
| 528 | { | 553 | { |
| 529 | if (stmt) | 554 | if (stmt) |
| 530 | sqlite3_finalize (stmt); | 555 | sqlite3_finalize (stmt); |
| 531 | 556 | errmsg = sqlite_prepare_errmsg (ret, sdb); | |
| 532 | goto exit; | 557 | goto exit; |
| 533 | } | 558 | } |
| 534 | 559 | ||
| @@ -539,7 +564,7 @@ which means that we return a set object that can be queried with | |||
| 539 | if (err != NULL) | 564 | if (err != NULL) |
| 540 | { | 565 | { |
| 541 | sqlite3_finalize (stmt); | 566 | sqlite3_finalize (stmt); |
| 542 | errmsg = err; | 567 | errmsg = build_string (err); |
| 543 | goto exit; | 568 | goto exit; |
| 544 | } | 569 | } |
| 545 | } | 570 | } |
| @@ -553,7 +578,7 @@ which means that we return a set object that can be queried with | |||
| 553 | 578 | ||
| 554 | /* Return the data directly. */ | 579 | /* Return the data directly. */ |
| 555 | Lisp_Object data = Qnil; | 580 | Lisp_Object data = Qnil; |
| 556 | while ((ret = sqlite3_step (stmt)) == SQLITE_ROW) | 581 | while (sqlite3_step (stmt) == SQLITE_ROW) |
| 557 | data = Fcons (row_to_value (stmt), data); | 582 | data = Fcons (row_to_value (stmt), data); |
| 558 | 583 | ||
| 559 | if (EQ (return_type, Qfull)) | 584 | if (EQ (return_type, Qfull)) |
| @@ -563,8 +588,8 @@ which means that we return a set object that can be queried with | |||
| 563 | sqlite3_finalize (stmt); | 588 | sqlite3_finalize (stmt); |
| 564 | 589 | ||
| 565 | exit: | 590 | exit: |
| 566 | if (errmsg != NULL) | 591 | if (! NILP (errmsg)) |
| 567 | xsignal1 (Qerror, build_string (errmsg)); | 592 | xsignal1 (Qerror, errmsg); |
| 568 | 593 | ||
| 569 | return retval; | 594 | return retval; |
| 570 | } | 595 | } |