aboutsummaryrefslogtreecommitdiffstats
path: root/src/sqlite.c
diff options
context:
space:
mode:
authorLars Ingebrigtsen2022-10-10 10:58:33 +0200
committerLars Ingebrigtsen2022-10-10 10:58:33 +0200
commit7e7dc74ffbab5eac863657ef719e9f47165708b3 (patch)
tree8445727c13f2ffb2c3ff52a840eb9986649da78c /src/sqlite.c
parent7ab6ec364d56c292de2d6294e9424824866691b3 (diff)
downloademacs-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.c120
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
380static Lisp_Object
381row_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
380DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, 424DEFUN ("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.
382If VALUES is non-nil, it should be a vector or a list of values 426If 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
447static Lisp_Object
448row_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
491static Lisp_Object 499static Lisp_Object