diff options
Diffstat (limited to 'src/sqlite.c')
| -rw-r--r-- | src/sqlite.c | 753 |
1 files changed, 753 insertions, 0 deletions
diff --git a/src/sqlite.c b/src/sqlite.c new file mode 100644 index 00000000000..649cb382948 --- /dev/null +++ b/src/sqlite.c | |||
| @@ -0,0 +1,753 @@ | |||
| 1 | /* | ||
| 2 | Copyright (C) 2021-2022 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software: you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation, either version 3 of the License, or (at | ||
| 9 | your option) any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | This file is based on the emacs-sqlite3 package written by Syohei | ||
| 20 | YOSHIDA <syohex@gmail.com>, which can be found at: | ||
| 21 | |||
| 22 | https://github.com/syohex/emacs-sqlite3 | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <config.h> | ||
| 26 | #include "lisp.h" | ||
| 27 | #include "coding.h" | ||
| 28 | |||
| 29 | #ifdef HAVE_SQLITE3 | ||
| 30 | |||
| 31 | #include <sqlite3.h> | ||
| 32 | |||
| 33 | #ifdef WINDOWSNT | ||
| 34 | |||
| 35 | # include <windows.h> | ||
| 36 | # include "w32common.h" | ||
| 37 | # include "w32.h" | ||
| 38 | |||
| 39 | DEF_DLL_FN (SQLITE_API int, sqlite3_finalize, (sqlite3_stmt*)); | ||
| 40 | DEF_DLL_FN (SQLITE_API int, sqlite3_close, (sqlite3*)); | ||
| 41 | DEF_DLL_FN (SQLITE_API int, sqlite3_open_v2, | ||
| 42 | (const char*, sqlite3**, int, const char*)); | ||
| 43 | DEF_DLL_FN (SQLITE_API int, sqlite3_reset, (sqlite3_stmt*)); | ||
| 44 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_text, | ||
| 45 | (sqlite3_stmt*, int, const char*, int, void(*)(void*))); | ||
| 46 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int64, | ||
| 47 | (sqlite3_stmt*, int, sqlite3_int64)); | ||
| 48 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_double, (sqlite3_stmt*, int, double)); | ||
| 49 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_null, (sqlite3_stmt*, int)); | ||
| 50 | DEF_DLL_FN (SQLITE_API int, sqlite3_bind_int, (sqlite3_stmt*, int, int)); | ||
| 51 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_errmsg, (sqlite3*)); | ||
| 52 | DEF_DLL_FN (SQLITE_API int, sqlite3_step, (sqlite3_stmt*)); | ||
| 53 | DEF_DLL_FN (SQLITE_API int, sqlite3_changes, (sqlite3*)); | ||
| 54 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_count, (sqlite3_stmt*)); | ||
| 55 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_type, (sqlite3_stmt*, int)); | ||
| 56 | DEF_DLL_FN (SQLITE_API sqlite3_int64, sqlite3_column_int64, | ||
| 57 | (sqlite3_stmt*, int)); | ||
| 58 | DEF_DLL_FN (SQLITE_API double, sqlite3_column_double, (sqlite3_stmt*, int)); | ||
| 59 | DEF_DLL_FN (SQLITE_API const void*, sqlite3_column_blob, | ||
| 60 | (sqlite3_stmt*, int)); | ||
| 61 | DEF_DLL_FN (SQLITE_API int, sqlite3_column_bytes, (sqlite3_stmt*, int)); | ||
| 62 | DEF_DLL_FN (SQLITE_API const unsigned char*, sqlite3_column_text, | ||
| 63 | (sqlite3_stmt*, int)); | ||
| 64 | DEF_DLL_FN (SQLITE_API const char*, sqlite3_column_name, (sqlite3_stmt*, int)); | ||
| 65 | DEF_DLL_FN (SQLITE_API int, sqlite3_exec, | ||
| 66 | (sqlite3*, const char*, int (*callback)(void*,int,char**,char**), | ||
| 67 | void*, char**)); | ||
| 68 | DEF_DLL_FN (SQLITE_API int, sqlite3_prepare_v2, | ||
| 69 | (sqlite3*, const char*, int, sqlite3_stmt**, const char**)); | ||
| 70 | |||
| 71 | # ifdef HAVE_SQLITE3_LOAD_EXTENSION | ||
| 72 | DEF_DLL_FN (SQLITE_API int, sqlite3_load_extension, | ||
| 73 | (sqlite3*, const char*, const char*, char**)); | ||
| 74 | # undef sqlite3_load_extension | ||
| 75 | # define sqlite3_load_extension fn_sqlite3_load_extension | ||
| 76 | # endif | ||
| 77 | |||
| 78 | # undef sqlite3_finalize | ||
| 79 | # undef sqlite3_close | ||
| 80 | # undef sqlite3_open_v2 | ||
| 81 | # undef sqlite3_reset | ||
| 82 | # undef sqlite3_bind_text | ||
| 83 | # undef sqlite3_bind_int64 | ||
| 84 | # undef sqlite3_bind_double | ||
| 85 | # undef sqlite3_bind_null | ||
| 86 | # undef sqlite3_bind_int | ||
| 87 | # undef sqlite3_errmsg | ||
| 88 | # undef sqlite3_step | ||
| 89 | # undef sqlite3_changes | ||
| 90 | # undef sqlite3_column_count | ||
| 91 | # undef sqlite3_column_type | ||
| 92 | # undef sqlite3_column_int64 | ||
| 93 | # undef sqlite3_column_double | ||
| 94 | # undef sqlite3_column_blob | ||
| 95 | # undef sqlite3_column_bytes | ||
| 96 | # undef sqlite3_column_text | ||
| 97 | # undef sqlite3_column_name | ||
| 98 | # undef sqlite3_exec | ||
| 99 | # undef sqlite3_prepare_v2 | ||
| 100 | |||
| 101 | # define sqlite3_finalize fn_sqlite3_finalize | ||
| 102 | # define sqlite3_close fn_sqlite3_close | ||
| 103 | # define sqlite3_open_v2 fn_sqlite3_open_v2 | ||
| 104 | # define sqlite3_reset fn_sqlite3_reset | ||
| 105 | # define sqlite3_bind_text fn_sqlite3_bind_text | ||
| 106 | # define sqlite3_bind_int64 fn_sqlite3_bind_int64 | ||
| 107 | # define sqlite3_bind_double fn_sqlite3_bind_double | ||
| 108 | # define sqlite3_bind_null fn_sqlite3_bind_null | ||
| 109 | # define sqlite3_bind_int fn_sqlite3_bind_int | ||
| 110 | # define sqlite3_errmsg fn_sqlite3_errmsg | ||
| 111 | # define sqlite3_step fn_sqlite3_step | ||
| 112 | # define sqlite3_changes fn_sqlite3_changes | ||
| 113 | # define sqlite3_column_count fn_sqlite3_column_count | ||
| 114 | # define sqlite3_column_type fn_sqlite3_column_type | ||
| 115 | # define sqlite3_column_int64 fn_sqlite3_column_int64 | ||
| 116 | # define sqlite3_column_double fn_sqlite3_column_double | ||
| 117 | # define sqlite3_column_blob fn_sqlite3_column_blob | ||
| 118 | # define sqlite3_column_bytes fn_sqlite3_column_bytes | ||
| 119 | # define sqlite3_column_text fn_sqlite3_column_text | ||
| 120 | # define sqlite3_column_name fn_sqlite3_column_name | ||
| 121 | # define sqlite3_exec fn_sqlite3_exec | ||
| 122 | # define sqlite3_prepare_v2 fn_sqlite3_prepare_v2 | ||
| 123 | |||
| 124 | static bool | ||
| 125 | load_dll_functions (HMODULE library) | ||
| 126 | { | ||
| 127 | LOAD_DLL_FN (library, sqlite3_finalize); | ||
| 128 | LOAD_DLL_FN (library, sqlite3_close); | ||
| 129 | LOAD_DLL_FN (library, sqlite3_open_v2); | ||
| 130 | LOAD_DLL_FN (library, sqlite3_reset); | ||
| 131 | LOAD_DLL_FN (library, sqlite3_bind_text); | ||
| 132 | LOAD_DLL_FN (library, sqlite3_bind_int64); | ||
| 133 | LOAD_DLL_FN (library, sqlite3_bind_double); | ||
| 134 | LOAD_DLL_FN (library, sqlite3_bind_null); | ||
| 135 | LOAD_DLL_FN (library, sqlite3_bind_int); | ||
| 136 | LOAD_DLL_FN (library, sqlite3_errmsg); | ||
| 137 | LOAD_DLL_FN (library, sqlite3_step); | ||
| 138 | LOAD_DLL_FN (library, sqlite3_changes); | ||
| 139 | LOAD_DLL_FN (library, sqlite3_column_count); | ||
| 140 | LOAD_DLL_FN (library, sqlite3_column_type); | ||
| 141 | LOAD_DLL_FN (library, sqlite3_column_int64); | ||
| 142 | LOAD_DLL_FN (library, sqlite3_column_double); | ||
| 143 | LOAD_DLL_FN (library, sqlite3_column_blob); | ||
| 144 | LOAD_DLL_FN (library, sqlite3_column_bytes); | ||
| 145 | LOAD_DLL_FN (library, sqlite3_column_text); | ||
| 146 | LOAD_DLL_FN (library, sqlite3_column_name); | ||
| 147 | LOAD_DLL_FN (library, sqlite3_exec); | ||
| 148 | # ifdef HAVE_SQLITE3_LOAD_EXTENSION | ||
| 149 | LOAD_DLL_FN (library, sqlite3_load_extension); | ||
| 150 | # endif | ||
| 151 | LOAD_DLL_FN (library, sqlite3_prepare_v2); | ||
| 152 | return true; | ||
| 153 | } | ||
| 154 | #endif /* WINDOWSNT */ | ||
| 155 | |||
| 156 | static bool | ||
| 157 | init_sqlite_functions (void) | ||
| 158 | { | ||
| 159 | #ifdef WINDOWSNT | ||
| 160 | static bool sqlite3_initialized; | ||
| 161 | |||
| 162 | if (!sqlite3_initialized) | ||
| 163 | { | ||
| 164 | HMODULE library = w32_delayed_load (Qsqlite3); | ||
| 165 | |||
| 166 | if (!library) | ||
| 167 | message1 ("sqlite3 library was not found"); | ||
| 168 | else if (load_dll_functions (library)) | ||
| 169 | { | ||
| 170 | sqlite3_initialized = true; | ||
| 171 | Vlibrary_cache = Fcons (Fcons (Qsqlite3, Qt), Vlibrary_cache); | ||
| 172 | } | ||
| 173 | else | ||
| 174 | { | ||
| 175 | message1 ("sqlite3 library was found, but could not be loaded successfully"); | ||
| 176 | Vlibrary_cache = Fcons (Fcons (Qsqlite3, Qnil), Vlibrary_cache); | ||
| 177 | } | ||
| 178 | } | ||
| 179 | return sqlite3_initialized; | ||
| 180 | #else /* !WINDOWSNT */ | ||
| 181 | return true; | ||
| 182 | #endif /* !WINDOWSNT */ | ||
| 183 | } | ||
| 184 | |||
| 185 | |||
| 186 | static void | ||
| 187 | sqlite_free (void *arg) | ||
| 188 | { | ||
| 189 | struct Lisp_Sqlite *ptr = (struct Lisp_Sqlite *)arg; | ||
| 190 | if (ptr->is_statement) | ||
| 191 | sqlite3_finalize (ptr->stmt); | ||
| 192 | else if (ptr->db) | ||
| 193 | sqlite3_close (ptr->db); | ||
| 194 | xfree (ptr->name); | ||
| 195 | xfree (ptr); | ||
| 196 | } | ||
| 197 | |||
| 198 | static Lisp_Object | ||
| 199 | encode_string (Lisp_Object string) | ||
| 200 | { | ||
| 201 | if (STRING_MULTIBYTE (string)) | ||
| 202 | return encode_string_utf_8 (string, Qnil, 0, Qt, Qt); | ||
| 203 | else | ||
| 204 | return string; | ||
| 205 | } | ||
| 206 | |||
| 207 | static Lisp_Object | ||
| 208 | make_sqlite (bool is_statement, void *db, void *stmt, char *name) | ||
| 209 | { | ||
| 210 | struct Lisp_Sqlite *ptr | ||
| 211 | = ALLOCATE_PLAIN_PSEUDOVECTOR (struct Lisp_Sqlite, PVEC_SQLITE); | ||
| 212 | ptr->is_statement = is_statement; | ||
| 213 | ptr->finalizer = sqlite_free; | ||
| 214 | ptr->db = db; | ||
| 215 | ptr->name = name; | ||
| 216 | ptr->stmt = stmt; | ||
| 217 | ptr->eof = false; | ||
| 218 | return make_lisp_ptr (ptr, Lisp_Vectorlike); | ||
| 219 | } | ||
| 220 | |||
| 221 | static void | ||
| 222 | check_sqlite (Lisp_Object db, bool is_statement) | ||
| 223 | { | ||
| 224 | init_sqlite_functions (); | ||
| 225 | CHECK_SQLITE (db); | ||
| 226 | if (is_statement && !XSQLITE (db)->is_statement) | ||
| 227 | xsignal1 (Qerror, build_string ("Invalid set object")); | ||
| 228 | else if (!is_statement && XSQLITE (db)->is_statement) | ||
| 229 | xsignal1 (Qerror, build_string ("Invalid database object")); | ||
| 230 | if (!is_statement && !XSQLITE (db)->db) | ||
| 231 | xsignal1 (Qerror, build_string ("Database closed")); | ||
| 232 | else if (is_statement && !XSQLITE (db)->db) | ||
| 233 | xsignal1 (Qerror, build_string ("Statement closed")); | ||
| 234 | } | ||
| 235 | |||
| 236 | static int db_count = 0; | ||
| 237 | |||
| 238 | DEFUN ("sqlite-open", Fsqlite_open, Ssqlite_open, 0, 1, 0, | ||
| 239 | doc: /* Open FILE as an sqlite database. | ||
| 240 | If FILE is nil, an in-memory database will be opened instead. */) | ||
| 241 | (Lisp_Object file) | ||
| 242 | { | ||
| 243 | char *name; | ||
| 244 | if (!init_sqlite_functions ()) | ||
| 245 | xsignal1 (Qerror, build_string ("sqlite support is not available")); | ||
| 246 | |||
| 247 | if (!NILP (file)) | ||
| 248 | { | ||
| 249 | CHECK_STRING (file); | ||
| 250 | file = ENCODE_FILE (Fexpand_file_name (file, Qnil)); | ||
| 251 | name = xstrdup (SSDATA (file)); | ||
| 252 | } | ||
| 253 | else | ||
| 254 | /* In-memory database. These have to have different names to | ||
| 255 | refer to different databases. */ | ||
| 256 | name = xstrdup (SSDATA (CALLN (Fformat, build_string (":memory:%d"), | ||
| 257 | make_int (++db_count)))); | ||
| 258 | |||
| 259 | sqlite3 *sdb; | ||
| 260 | int ret = sqlite3_open_v2 (name, | ||
| 261 | &sdb, | ||
| 262 | SQLITE_OPEN_FULLMUTEX | ||
| 263 | | SQLITE_OPEN_READWRITE | ||
| 264 | | SQLITE_OPEN_CREATE | ||
| 265 | | (NILP (file) ? SQLITE_OPEN_MEMORY : 0) | ||
| 266 | #ifdef SQLITE_OPEN_URI | ||
| 267 | | SQLITE_OPEN_URI | ||
| 268 | #endif | ||
| 269 | | 0, NULL); | ||
| 270 | |||
| 271 | if (ret != SQLITE_OK) | ||
| 272 | return Qnil; | ||
| 273 | |||
| 274 | return make_sqlite (false, sdb, NULL, name); | ||
| 275 | } | ||
| 276 | |||
| 277 | DEFUN ("sqlite-close", Fsqlite_close, Ssqlite_close, 1, 1, 0, | ||
| 278 | doc: /* Close the sqlite database DB. */) | ||
| 279 | (Lisp_Object db) | ||
| 280 | { | ||
| 281 | check_sqlite (db, false); | ||
| 282 | sqlite3_close (XSQLITE (db)->db); | ||
| 283 | XSQLITE (db)->db = NULL; | ||
| 284 | return Qt; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* Bind values in a statement like | ||
| 288 | "insert into foo values (?, ?, ?)". */ | ||
| 289 | static const char * | ||
| 290 | bind_values (sqlite3 *db, sqlite3_stmt *stmt, Lisp_Object values) | ||
| 291 | { | ||
| 292 | sqlite3_reset (stmt); | ||
| 293 | int len; | ||
| 294 | if (VECTORP (values)) | ||
| 295 | len = ASIZE (values); | ||
| 296 | else | ||
| 297 | len = list_length (values); | ||
| 298 | |||
| 299 | for (int i = 0; i < len; ++i) | ||
| 300 | { | ||
| 301 | int ret = SQLITE_MISMATCH; | ||
| 302 | Lisp_Object value; | ||
| 303 | if (VECTORP (values)) | ||
| 304 | value = AREF (values, i); | ||
| 305 | else | ||
| 306 | { | ||
| 307 | value = XCAR (values); | ||
| 308 | values = XCDR (values); | ||
| 309 | } | ||
| 310 | Lisp_Object type = Ftype_of (value); | ||
| 311 | |||
| 312 | if (EQ (type, Qstring)) | ||
| 313 | { | ||
| 314 | Lisp_Object encoded = encode_string (value); | ||
| 315 | ret = sqlite3_bind_text (stmt, i + 1, | ||
| 316 | SSDATA (encoded), SBYTES (encoded), | ||
| 317 | NULL); | ||
| 318 | } | ||
| 319 | else if (EQ (type, Qinteger)) | ||
| 320 | { | ||
| 321 | if (BIGNUMP (value)) | ||
| 322 | ret = sqlite3_bind_int64 (stmt, i + 1, bignum_to_intmax (value)); | ||
| 323 | else | ||
| 324 | ret = sqlite3_bind_int64 (stmt, i + 1, XFIXNUM (value)); | ||
| 325 | } | ||
| 326 | else if (EQ (type, Qfloat)) | ||
| 327 | ret = sqlite3_bind_double (stmt, i + 1, XFLOAT_DATA (value)); | ||
| 328 | else if (NILP (value)) | ||
| 329 | ret = sqlite3_bind_null (stmt, i + 1); | ||
| 330 | else if (EQ (value, Qt)) | ||
| 331 | ret = sqlite3_bind_int (stmt, i + 1, 1); | ||
| 332 | else if (EQ (value, Qfalse)) | ||
| 333 | ret = sqlite3_bind_int (stmt, i + 1, 0); | ||
| 334 | else | ||
| 335 | return "invalid argument"; | ||
| 336 | |||
| 337 | if (ret != SQLITE_OK) | ||
| 338 | return sqlite3_errmsg (db); | ||
| 339 | } | ||
| 340 | |||
| 341 | return NULL; | ||
| 342 | } | ||
| 343 | |||
| 344 | DEFUN ("sqlite-execute", Fsqlite_execute, Ssqlite_execute, 2, 3, 0, | ||
| 345 | doc: /* Execute a non-select SQL statement. | ||
| 346 | If VALUES is non-nil, it should be a vector or a list of values | ||
| 347 | to bind when executing a statement like | ||
| 348 | |||
| 349 | insert into foo values (?, ?, ...) | ||
| 350 | |||
| 351 | Value is the number of affected rows. */) | ||
| 352 | (Lisp_Object db, Lisp_Object query, Lisp_Object values) | ||
| 353 | { | ||
| 354 | check_sqlite (db, false); | ||
| 355 | CHECK_STRING (query); | ||
| 356 | if (!(NILP (values) || CONSP (values) || VECTORP (values))) | ||
| 357 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | ||
| 358 | |||
| 359 | sqlite3 *sdb = XSQLITE (db)->db; | ||
| 360 | Lisp_Object retval = Qnil; | ||
| 361 | const char *errmsg = NULL; | ||
| 362 | Lisp_Object encoded = encode_string (query); | ||
| 363 | sqlite3_stmt *stmt = NULL; | ||
| 364 | |||
| 365 | /* We only execute the first statement -- if there's several | ||
| 366 | (separated by a semicolon), the subsequent statements won't be | ||
| 367 | done. */ | ||
| 368 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), -1, &stmt, NULL); | ||
| 369 | if (ret != SQLITE_OK) | ||
| 370 | { | ||
| 371 | if (stmt != NULL) | ||
| 372 | { | ||
| 373 | sqlite3_finalize (stmt); | ||
| 374 | sqlite3_reset (stmt); | ||
| 375 | } | ||
| 376 | |||
| 377 | errmsg = sqlite3_errmsg (sdb); | ||
| 378 | goto exit; | ||
| 379 | } | ||
| 380 | |||
| 381 | /* Bind ? values. */ | ||
| 382 | if (!NILP (values)) { | ||
| 383 | const char *err = bind_values (sdb, stmt, values); | ||
| 384 | if (err != NULL) | ||
| 385 | { | ||
| 386 | errmsg = err; | ||
| 387 | goto exit; | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | ret = sqlite3_step (stmt); | ||
| 392 | sqlite3_finalize (stmt); | ||
| 393 | if (ret != SQLITE_OK && ret != SQLITE_DONE) | ||
| 394 | { | ||
| 395 | errmsg = sqlite3_errmsg (sdb); | ||
| 396 | goto exit; | ||
| 397 | } | ||
| 398 | |||
| 399 | retval = make_fixnum (sqlite3_changes (sdb)); | ||
| 400 | |||
| 401 | exit: | ||
| 402 | if (errmsg != NULL) | ||
| 403 | xsignal1 (ret == SQLITE_LOCKED || ret == SQLITE_BUSY? | ||
| 404 | Qsqlite_locked_error: Qerror, | ||
| 405 | build_string (errmsg)); | ||
| 406 | |||
| 407 | return retval; | ||
| 408 | } | ||
| 409 | |||
| 410 | static Lisp_Object | ||
| 411 | row_to_value (sqlite3_stmt *stmt) | ||
| 412 | { | ||
| 413 | int len = sqlite3_column_count (stmt); | ||
| 414 | Lisp_Object values = Qnil; | ||
| 415 | |||
| 416 | for (int i = 0; i < len; ++i) | ||
| 417 | { | ||
| 418 | Lisp_Object v = Qnil; | ||
| 419 | |||
| 420 | switch (sqlite3_column_type (stmt, i)) | ||
| 421 | { | ||
| 422 | case SQLITE_INTEGER: | ||
| 423 | v = make_int (sqlite3_column_int64 (stmt, i)); | ||
| 424 | break; | ||
| 425 | |||
| 426 | case SQLITE_FLOAT: | ||
| 427 | v = make_float (sqlite3_column_double (stmt, i)); | ||
| 428 | break; | ||
| 429 | |||
| 430 | case SQLITE_BLOB: | ||
| 431 | v = | ||
| 432 | code_convert_string_norecord | ||
| 433 | (make_unibyte_string (sqlite3_column_blob (stmt, i), | ||
| 434 | sqlite3_column_bytes (stmt, i)), | ||
| 435 | Qutf_8, false); | ||
| 436 | break; | ||
| 437 | |||
| 438 | case SQLITE_NULL: | ||
| 439 | v = Qnil; | ||
| 440 | break; | ||
| 441 | |||
| 442 | case SQLITE_TEXT: | ||
| 443 | v = | ||
| 444 | code_convert_string_norecord | ||
| 445 | (make_unibyte_string ((const char *)sqlite3_column_text (stmt, i), | ||
| 446 | sqlite3_column_bytes (stmt, i)), | ||
| 447 | Qutf_8, false); | ||
| 448 | break; | ||
| 449 | } | ||
| 450 | |||
| 451 | values = Fcons (v, values); | ||
| 452 | } | ||
| 453 | |||
| 454 | return Fnreverse (values); | ||
| 455 | } | ||
| 456 | |||
| 457 | static Lisp_Object | ||
| 458 | column_names (sqlite3_stmt *stmt) | ||
| 459 | { | ||
| 460 | Lisp_Object columns = Qnil; | ||
| 461 | int count = sqlite3_column_count (stmt); | ||
| 462 | for (int i = 0; i < count; ++i) | ||
| 463 | columns = Fcons (build_string (sqlite3_column_name (stmt, i)), columns); | ||
| 464 | |||
| 465 | return Fnreverse (columns); | ||
| 466 | } | ||
| 467 | |||
| 468 | DEFUN ("sqlite-select", Fsqlite_select, Ssqlite_select, 2, 4, 0, | ||
| 469 | doc: /* Select data from the database DB that matches QUERY. | ||
| 470 | If VALUES is non-nil, it should be a list or a vector specifying the | ||
| 471 | values that will be interpolated into a parameterized statement. | ||
| 472 | |||
| 473 | By default, the return value is a list where the first element is a | ||
| 474 | list of column names, and the rest of the elements are the matching data. | ||
| 475 | |||
| 476 | RETURN-TYPE can be either nil (which means that the matching data | ||
| 477 | should be returned as a list of rows), or `full' (the same, but the | ||
| 478 | first element in the return list will be the column names), or `set', | ||
| 479 | which means that we return a set object that can be queried with | ||
| 480 | `sqlite-next' and other functions to get the data. */) | ||
| 481 | (Lisp_Object db, Lisp_Object query, Lisp_Object values, | ||
| 482 | Lisp_Object return_type) | ||
| 483 | { | ||
| 484 | check_sqlite (db, false); | ||
| 485 | CHECK_STRING (query); | ||
| 486 | |||
| 487 | if (!(NILP (values) || CONSP (values) || VECTORP (values))) | ||
| 488 | xsignal1 (Qerror, build_string ("VALUES must be a list or a vector")); | ||
| 489 | |||
| 490 | sqlite3 *sdb = XSQLITE (db)->db; | ||
| 491 | Lisp_Object retval = Qnil; | ||
| 492 | const char *errmsg = NULL; | ||
| 493 | Lisp_Object encoded = encode_string (query); | ||
| 494 | |||
| 495 | sqlite3_stmt *stmt = NULL; | ||
| 496 | int ret = sqlite3_prepare_v2 (sdb, SSDATA (encoded), SBYTES (encoded), | ||
| 497 | &stmt, NULL); | ||
| 498 | if (ret != SQLITE_OK) | ||
| 499 | { | ||
| 500 | if (stmt) | ||
| 501 | sqlite3_finalize (stmt); | ||
| 502 | |||
| 503 | goto exit; | ||
| 504 | } | ||
| 505 | |||
| 506 | /* Query with parameters. */ | ||
| 507 | if (!NILP (values)) | ||
| 508 | { | ||
| 509 | const char *err = bind_values (sdb, stmt, values); | ||
| 510 | if (err != NULL) | ||
| 511 | { | ||
| 512 | sqlite3_finalize (stmt); | ||
| 513 | errmsg = err; | ||
| 514 | goto exit; | ||
| 515 | } | ||
| 516 | } | ||
| 517 | |||
| 518 | /* Return a handle to get the data. */ | ||
| 519 | if (EQ (return_type, Qset)) | ||
| 520 | { | ||
| 521 | retval = make_sqlite (true, sdb, stmt, XSQLITE (db)->name); | ||
| 522 | goto exit; | ||
| 523 | } | ||
| 524 | |||
| 525 | /* Return the data directly. */ | ||
| 526 | Lisp_Object data = Qnil; | ||
| 527 | while ((ret = sqlite3_step (stmt)) == SQLITE_ROW) | ||
| 528 | data = Fcons (row_to_value (stmt), data); | ||
| 529 | |||
| 530 | if (EQ (return_type, Qfull)) | ||
| 531 | retval = Fcons (column_names (stmt), Fnreverse (data)); | ||
| 532 | else | ||
| 533 | retval = Fnreverse (data); | ||
| 534 | sqlite3_finalize (stmt); | ||
| 535 | |||
| 536 | exit: | ||
| 537 | if (errmsg != NULL) | ||
| 538 | xsignal1 (Qerror, build_string (errmsg)); | ||
| 539 | |||
| 540 | return retval; | ||
| 541 | } | ||
| 542 | |||
| 543 | static Lisp_Object | ||
| 544 | sqlite_exec (sqlite3 *sdb, const char *query) | ||
| 545 | { | ||
| 546 | int ret = sqlite3_exec (sdb, query, NULL, NULL, NULL); | ||
| 547 | if (ret != SQLITE_OK) | ||
| 548 | return Qnil; | ||
| 549 | |||
| 550 | return Qt; | ||
| 551 | } | ||
| 552 | |||
| 553 | DEFUN ("sqlite-transaction", Fsqlite_transaction, Ssqlite_transaction, 1, 1, 0, | ||
| 554 | doc: /* Start a transaction in DB. */) | ||
| 555 | (Lisp_Object db) | ||
| 556 | { | ||
| 557 | check_sqlite (db, false); | ||
| 558 | return sqlite_exec (XSQLITE (db)->db, "begin"); | ||
| 559 | } | ||
| 560 | |||
| 561 | DEFUN ("sqlite-commit", Fsqlite_commit, Ssqlite_commit, 1, 1, 0, | ||
| 562 | doc: /* Commit a transaction in DB. */) | ||
| 563 | (Lisp_Object db) | ||
| 564 | { | ||
| 565 | check_sqlite (db, false); | ||
| 566 | return sqlite_exec (XSQLITE (db)->db, "commit"); | ||
| 567 | } | ||
| 568 | |||
| 569 | DEFUN ("sqlite-rollback", Fsqlite_rollback, Ssqlite_rollback, 1, 1, 0, | ||
| 570 | doc: /* Roll back a transaction in DB. */) | ||
| 571 | (Lisp_Object db) | ||
| 572 | { | ||
| 573 | check_sqlite (db, false); | ||
| 574 | return sqlite_exec (XSQLITE (db)->db, "rollback"); | ||
| 575 | } | ||
| 576 | |||
| 577 | DEFUN ("sqlite-pragma", Fsqlite_pragma, Ssqlite_pragma, 2, 2, 0, | ||
| 578 | doc: /* Execute PRAGMA in DB. */) | ||
| 579 | (Lisp_Object db, Lisp_Object pragma) | ||
| 580 | { | ||
| 581 | check_sqlite (db, false); | ||
| 582 | CHECK_STRING (pragma); | ||
| 583 | |||
| 584 | return sqlite_exec (XSQLITE (db)->db, | ||
| 585 | SSDATA (concat2 (build_string ("PRAGMA "), pragma))); | ||
| 586 | } | ||
| 587 | |||
| 588 | #ifdef HAVE_SQLITE3_LOAD_EXTENSION | ||
| 589 | DEFUN ("sqlite-load-extension", Fsqlite_load_extension, | ||
| 590 | Ssqlite_load_extension, 2, 2, 0, | ||
| 591 | doc: /* Load an SQlite MODULE into DB. | ||
| 592 | MODULE should be the name of an SQlite module's file, a | ||
| 593 | shared library in the system-dependent format and having a | ||
| 594 | system-dependent file-name extension. | ||
| 595 | |||
| 596 | Only modules on Emacs' list of allowed modules can be loaded. */) | ||
| 597 | (Lisp_Object db, Lisp_Object module) | ||
| 598 | { | ||
| 599 | check_sqlite (db, false); | ||
| 600 | CHECK_STRING (module); | ||
| 601 | |||
| 602 | /* Add names of useful and free modules here. */ | ||
| 603 | const char *allowlist[3] = { "pcre", "csvtable", NULL }; | ||
| 604 | char *name = SSDATA (Ffile_name_nondirectory (module)); | ||
| 605 | /* Possibly skip past a common prefix. */ | ||
| 606 | const char *prefix = "libsqlite3_mod_"; | ||
| 607 | if (!strncmp (name, prefix, strlen (prefix))) | ||
| 608 | name += strlen (prefix); | ||
| 609 | |||
| 610 | bool do_allow = false; | ||
| 611 | for (const char **allow = allowlist; *allow; allow++) | ||
| 612 | { | ||
| 613 | if (strlen (*allow) < strlen (name) | ||
| 614 | && !strncmp (*allow, name, strlen (*allow)) | ||
| 615 | && (!strcmp (name + strlen (*allow), ".so") | ||
| 616 | || !strcmp (name + strlen (*allow), ".DLL"))) | ||
| 617 | { | ||
| 618 | do_allow = true; | ||
| 619 | break; | ||
| 620 | } | ||
| 621 | } | ||
| 622 | |||
| 623 | if (!do_allow) | ||
| 624 | xsignal (Qerror, build_string ("Module name not on allowlist")); | ||
| 625 | |||
| 626 | int result = sqlite3_load_extension | ||
| 627 | (XSQLITE (db)->db, | ||
| 628 | SSDATA (ENCODE_FILE (Fexpand_file_name (module, Qnil))), | ||
| 629 | NULL, NULL); | ||
| 630 | if (result == SQLITE_OK) | ||
| 631 | return Qt; | ||
| 632 | return Qnil; | ||
| 633 | } | ||
| 634 | #endif /* HAVE_SQLITE3_LOAD_EXTENSION */ | ||
| 635 | |||
| 636 | DEFUN ("sqlite-next", Fsqlite_next, Ssqlite_next, 1, 1, 0, | ||
| 637 | doc: /* Return the next result set from SET. */) | ||
| 638 | (Lisp_Object set) | ||
| 639 | { | ||
| 640 | check_sqlite (set, true); | ||
| 641 | |||
| 642 | int ret = sqlite3_step (XSQLITE (set)->stmt); | ||
| 643 | if (ret != SQLITE_ROW && ret != SQLITE_OK && ret != SQLITE_DONE) | ||
| 644 | xsignal1 (Qerror, build_string (sqlite3_errmsg (XSQLITE (set)->db))); | ||
| 645 | |||
| 646 | if (ret == SQLITE_DONE) | ||
| 647 | { | ||
| 648 | XSQLITE (set)->eof = true; | ||
| 649 | return Qnil; | ||
| 650 | } | ||
| 651 | |||
| 652 | return row_to_value (XSQLITE (set)->stmt); | ||
| 653 | } | ||
| 654 | |||
| 655 | DEFUN ("sqlite-columns", Fsqlite_columns, Ssqlite_columns, 1, 1, 0, | ||
| 656 | doc: /* Return the column names of SET. */) | ||
| 657 | (Lisp_Object set) | ||
| 658 | { | ||
| 659 | check_sqlite (set, true); | ||
| 660 | return column_names (XSQLITE (set)->stmt); | ||
| 661 | } | ||
| 662 | |||
| 663 | DEFUN ("sqlite-more-p", Fsqlite_more_p, Ssqlite_more_p, 1, 1, 0, | ||
| 664 | doc: /* Say whether there are any further results in SET. */) | ||
| 665 | (Lisp_Object set) | ||
| 666 | { | ||
| 667 | check_sqlite (set, true); | ||
| 668 | |||
| 669 | if (XSQLITE (set)->eof) | ||
| 670 | return Qnil; | ||
| 671 | else | ||
| 672 | return Qt; | ||
| 673 | } | ||
| 674 | |||
| 675 | DEFUN ("sqlite-finalize", Fsqlite_finalize, Ssqlite_finalize, 1, 1, 0, | ||
| 676 | doc: /* Mark this SET as being finished. | ||
| 677 | This will free the resources held by SET. */) | ||
| 678 | (Lisp_Object set) | ||
| 679 | { | ||
| 680 | check_sqlite (set, true); | ||
| 681 | sqlite3_finalize (XSQLITE (set)->stmt); | ||
| 682 | XSQLITE (set)->db = NULL; | ||
| 683 | return Qt; | ||
| 684 | } | ||
| 685 | |||
| 686 | #endif /* HAVE_SQLITE3 */ | ||
| 687 | |||
| 688 | DEFUN ("sqlitep", Fsqlitep, Ssqlitep, 1, 1, 0, | ||
| 689 | doc: /* Say whether OBJECT is an SQlite object. */) | ||
| 690 | (Lisp_Object object) | ||
| 691 | { | ||
| 692 | #ifdef HAVE_SQLITE3 | ||
| 693 | return SQLITE (object)? Qt: Qnil; | ||
| 694 | #else | ||
| 695 | return Qnil; | ||
| 696 | #endif | ||
| 697 | } | ||
| 698 | |||
| 699 | DEFUN ("sqlite-available-p", Fsqlite_available_p, Ssqlite_available_p, 0, 0, 0, | ||
| 700 | doc: /* Return t if sqlite3 support is available in this instance of Emacs.*/) | ||
| 701 | (void) | ||
| 702 | { | ||
| 703 | #ifdef HAVE_SQLITE3 | ||
| 704 | # ifdef WINDOWSNT | ||
| 705 | Lisp_Object found = Fassq (Qsqlite3, Vlibrary_cache); | ||
| 706 | if (CONSP (found)) | ||
| 707 | return XCDR (found); | ||
| 708 | else | ||
| 709 | return init_sqlite_functions () ? Qt : Qnil; | ||
| 710 | # else | ||
| 711 | return Qt; | ||
| 712 | #endif | ||
| 713 | #else | ||
| 714 | return Qnil; | ||
| 715 | #endif | ||
| 716 | } | ||
| 717 | |||
| 718 | void | ||
| 719 | syms_of_sqlite (void) | ||
| 720 | { | ||
| 721 | #ifdef HAVE_SQLITE3 | ||
| 722 | defsubr (&Ssqlite_open); | ||
| 723 | defsubr (&Ssqlite_close); | ||
| 724 | defsubr (&Ssqlite_execute); | ||
| 725 | defsubr (&Ssqlite_select); | ||
| 726 | defsubr (&Ssqlite_transaction); | ||
| 727 | defsubr (&Ssqlite_commit); | ||
| 728 | defsubr (&Ssqlite_rollback); | ||
| 729 | defsubr (&Ssqlite_pragma); | ||
| 730 | #ifdef HAVE_SQLITE3_LOAD_EXTENSION | ||
| 731 | defsubr (&Ssqlite_load_extension); | ||
| 732 | #endif | ||
| 733 | defsubr (&Ssqlite_next); | ||
| 734 | defsubr (&Ssqlite_columns); | ||
| 735 | defsubr (&Ssqlite_more_p); | ||
| 736 | defsubr (&Ssqlite_finalize); | ||
| 737 | DEFSYM (Qset, "set"); | ||
| 738 | DEFSYM (Qfull, "full"); | ||
| 739 | #endif | ||
| 740 | defsubr (&Ssqlitep); | ||
| 741 | defsubr (&Ssqlite_available_p); | ||
| 742 | |||
| 743 | DEFSYM (Qsqlite_locked_error, "sqlite-locked-error"); | ||
| 744 | Fput (Qsqlite_locked_error, Qerror_conditions, | ||
| 745 | Fpurecopy (list2 (Qsqlite_locked_error, Qerror))); | ||
| 746 | Fput (Qsqlite_locked_error, Qerror_message, | ||
| 747 | build_pure_c_string ("Database locked")); | ||
| 748 | |||
| 749 | DEFSYM (Qsqlitep, "sqlitep"); | ||
| 750 | DEFSYM (Qfalse, "false"); | ||
| 751 | DEFSYM (Qsqlite, "sqlite"); | ||
| 752 | DEFSYM (Qsqlite3, "sqlite3"); | ||
| 753 | } | ||