diff options
| author | Lars Ingebrigtsen | 2022-10-10 10:58:33 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-10-10 10:58:33 +0200 |
| commit | 7e7dc74ffbab5eac863657ef719e9f47165708b3 (patch) | |
| tree | 8445727c13f2ffb2c3ff52a840eb9986649da78c /src/sqlite.c | |
| parent | 7ab6ec364d56c292de2d6294e9424824866691b3 (diff) | |
| download | emacs-7e7dc74ffbab5eac863657ef719e9f47165708b3.tar.gz emacs-7e7dc74ffbab5eac863657ef719e9f47165708b3.zip | |
Support "insert into ... returning ..." in sqlite-execute
* doc/lispref/text.texi (Database): Mention it.
* src/sqlite.c (Fsqlite_execute): Support syntax like "insert into
... returning ..." (bug#58390).
Diffstat (limited to 'src/sqlite.c')
| -rw-r--r-- | src/sqlite.c | 120 |
1 files changed, 64 insertions, 56 deletions
diff --git a/src/sqlite.c b/src/sqlite.c index 7af3760eb4c..65b1dc492f6 100644 --- a/src/sqlite.c +++ b/src/sqlite.c | |||
| @@ -377,6 +377,50 @@ bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values) | |||
| 377 | return NULL; | 377 | return NULL; |
| 378 | } | 378 | } |
| 379 | 379 | ||
| 380 | static Lisp_Object | ||
| 381 | row_to_value (sqlite3_stmt *stmt) | ||
| 382 | { | ||
| 383 | int len = sqlite3_column_count (stmt); | ||
| 384 | Lisp_Object values = Qnil; | ||
| 385 | |||
| 386 | for (int i = 0; i < len; ++i) | ||
| 387 | { | ||
| 388 | Lisp_Object v = Qnil; | ||
| 389 | |||
| 390 | switch (sqlite3_column_type (stmt, i)) | ||
| 391 | { | ||
| 392 | case SQLITE_INTEGER: | ||
| 393 | v = make_int (sqlite3_column_int64 (stmt, i)); | ||
| 394 | break; | ||
| 395 | |||
| 396 | case SQLITE_FLOAT: | ||
| 397 | v = make_float (sqlite3_column_double (stmt, i)); | ||
| 398 | break; | ||
| 399 | |||
| 400 | case SQLITE_BLOB: | ||
| 401 | v = make_unibyte_string (sqlite3_column_blob (stmt, i), | ||
| 402 | sqlite3_column_bytes (stmt, i)); | ||
| 403 | break; | ||
| 404 | |||
| 405 | case SQLITE_NULL: | ||
| 406 | v = Qnil; | ||
| 407 | break; | ||
| 408 | |||
| 409 | case SQLITE_TEXT: | ||
| 410 | v = | ||
| 411 | code_convert_string_norecord | ||
| 412 | (make_unibyte_string ((const char *)sqlite3_column_text (stmt, i), | ||
| 413 | sqlite3_column_bytes (stmt, i)), | ||
| 414 | Qutf_8, false); | ||
| 415 | break; | ||
| 416 | } | ||
| 417 | |||
| 418 | values = Fcons (v, values); | ||
| 419 | } | ||
| 420 | |||
| 421 | return Fnreverse (values); | ||
| 422 | } | ||
| 423 | |||
| 380 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, | 424 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, |
| 381 | doc: /* Execute a non-select SQL statement. | 425 | doc: /* Execute a non-select SQL statement. |
| 382 | If VALUES is non-nil, it should be a vector or a list of values | 426 | If VALUES is non-nil, it should be a vector or a list of values |
| @@ -393,7 +437,6 @@ Value is the number of affected rows. */) | |||
| 393 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | 437 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); |
| 394 | 438 | ||
| 395 | sqlite3 *sdb = XSQLITE (db)->db; | 439 | sqlite3 *sdb = XSQLITE (db)->db; |
| 396 | Lisp_Object retval = Qnil; | ||
| 397 | const char *errmsg = NULL; | 440 | const char *errmsg = NULL; |
| 398 | Lisp_Object encoded = encode_string (query); | 441 | Lisp_Object encoded = encode_string (query); |
| 399 | sqlite3_stmt *stmt = NULL; | 442 | sqlite3_stmt *stmt = NULL; |
| @@ -426,66 +469,31 @@ Value is the number of affected rows. */) | |||
| 426 | } | 469 | } |
| 427 | 470 | ||
| 428 | ret = sqlite3_step (stmt); | 471 | ret = sqlite3_step (stmt); |
| 429 | sqlite3_finalize (stmt); | ||
| 430 | if (ret != SQLITE_OK && ret != SQLITE_DONE) | ||
| 431 | { | ||
| 432 | errmsg = sqlite3_errmsg (sdb); | ||
| 433 | goto exit; | ||
| 434 | } | ||
| 435 | 472 | ||
| 436 | retval = make_fixnum (sqlite3_changes (sdb)); | 473 | if (ret == SQLITE_ROW) |
| 437 | |||
| 438 | exit: | ||
| 439 | if (errmsg != NULL) | ||
| 440 | xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? | ||
| 441 | Qsqlite_locked_error: Qerror, | ||
| 442 | build_string (errmsg)); | ||
| 443 | |||
| 444 | return retval; | ||
| 445 | } | ||
| 446 | |||
| 447 | static Lisp_Object | ||
| 448 | row_to_value (sqlite3_stmt *stmt) | ||
| 449 | { | ||
| 450 | int len = sqlite3_column_count (stmt); | ||
| 451 | Lisp_Object values = Qnil; | ||
| 452 | |||
| 453 | for (int i = 0; i < len; ++i) | ||
| 454 | { | 474 | { |
| 455 | Lisp_Object v = Qnil; | 475 | Lisp_Object data = Qnil; |
| 456 | 476 | do | |
| 457 | switch (sqlite3_column_type (stmt, i)) | 477 | data = Fcons (row_to_value (stmt), data); |
| 458 | { | 478 | while (sqlite3_step (stmt) == SQLITE_ROW); |
| 459 | case SQLITE_INTEGER: | ||
| 460 | v = make_int (sqlite3_column_int64 (stmt, i)); | ||
| 461 | break; | ||
| 462 | |||
| 463 | case SQLITE_FLOAT: | ||
| 464 | v = make_float (sqlite3_column_double (stmt, i)); | ||
| 465 | break; | ||
| 466 | 479 | ||
| 467 | case SQLITE_BLOB: | 480 | sqlite3_finalize (stmt); |
| 468 | v = make_unibyte_string (sqlite3_column_blob (stmt, i), | 481 | return Fnreverse (data); |
| 469 | sqlite3_column_bytes (stmt, i)); | ||
| 470 | break; | ||
| 471 | |||
| 472 | case SQLITE_NULL: | ||
| 473 | v = Qnil; | ||
| 474 | break; | ||
| 475 | |||
| 476 | case SQLITE_TEXT: | ||
| 477 | v = | ||
| 478 | code_convert_string_norecord | ||
| 479 | (make_unibyte_string ((const char *)sqlite3_column_text (stmt, i), | ||
| 480 | sqlite3_column_bytes (stmt, i)), | ||
| 481 | Qutf_8, false); | ||
| 482 | break; | ||
| 483 | } | ||
| 484 | |||
| 485 | values = Fcons (v, values); | ||
| 486 | } | 482 | } |
| 483 | else if (ret == SQLITE_OK || ret == SQLITE_DONE) | ||
| 484 | { | ||
| 485 | Lisp_Object rows = make_fixnum (sqlite3_changes (sdb)); | ||
| 486 | sqlite3_finalize (stmt); | ||
| 487 | return rows; | ||
| 488 | } | ||
| 489 | else | ||
| 490 | errmsg = sqlite3_errmsg (sdb); | ||
| 487 | 491 | ||
| 488 | return Fnreverse (values); | 492 | exit: |
| 493 | sqlite3_finalize (stmt); | ||
| 494 | xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? | ||
| 495 | Qsqlite_locked_error: Qerror, | ||
| 496 | build_string (errmsg)); | ||
| 489 | } | 497 | } |
| 490 | 498 | ||
| 491 | static Lisp_Object | 499 | static Lisp_Object |