extralite 3.0.1 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,7 @@ VALUE cParameterError;
19
19
  VALUE eArgumentError;
20
20
 
21
21
  ID ID_bind;
22
+ ID ID_inspect;
22
23
  ID ID_call;
23
24
  ID ID_each;
24
25
  ID ID_keys;
@@ -38,6 +39,7 @@ VALUE SYM_normal;
38
39
  VALUE SYM_passive;
39
40
  VALUE SYM_read_only;
40
41
  VALUE SYM_restart;
42
+ VALUE SYM_stmt_cache;
41
43
  VALUE SYM_truncate;
42
44
  VALUE SYM_wal;
43
45
 
@@ -58,12 +60,14 @@ static size_t Database_size(const void *ptr) {
58
60
 
59
61
  static void Database_mark(void *ptr) {
60
62
  Database_t *db = ptr;
63
+ rb_gc_mark_movable(db->stmt_cache);
61
64
  rb_gc_mark_movable(db->trace_proc);
62
65
  rb_gc_mark_movable(db->progress_handler.proc);
63
66
  }
64
67
 
65
68
  static void Database_compact(void *ptr) {
66
69
  Database_t *db = ptr;
70
+ db->stmt_cache = rb_gc_location(db->stmt_cache);
67
71
  db->trace_proc = rb_gc_location(db->trace_proc);
68
72
  db->progress_handler.proc = rb_gc_location(db->progress_handler.proc);
69
73
  }
@@ -83,6 +87,7 @@ static const rb_data_type_t Database_type = {
83
87
  static VALUE Database_allocate(VALUE klass) {
84
88
  Database_t *db = ALLOC(Database_t);
85
89
  db->sqlite3_db = NULL;
90
+ db->stmt_cache = Qnil;
86
91
  db->trace_proc = Qnil;
87
92
  db->progress_handler.proc = Qnil;
88
93
  db->progress_handler.mode = PROGRESS_NONE;
@@ -127,12 +132,17 @@ default_flags:
127
132
  }
128
133
 
129
134
  void Database_apply_opts(VALUE self, Database_t *db, VALUE opts) {
135
+ db->flags = DB_F_STMT_CACHE;
130
136
  if (NIL_P(opts)) goto modern_pragmas;
131
137
 
132
138
  // :gvl_release_threshold
133
139
  VALUE value = rb_hash_aref(opts, SYM_gvl_release_threshold);
134
140
  if (!NIL_P(value)) db->gvl_release_threshold = NUM2INT(value);
135
141
 
142
+ value = rb_hash_aref(opts, SYM_stmt_cache);
143
+ if (value == Qfalse)
144
+ db->flags &= !DB_F_STMT_CACHE;
145
+
136
146
  value = rb_hash_aref(opts, SYM_legacy);
137
147
  if (RTEST(value)) return;
138
148
 
@@ -175,9 +185,9 @@ int Database_busy_handler(void *ptr, int v) {
175
185
  * `#gvl_release_threshold=`).
176
186
  * - `:read_only` (`true`/`false`): opens the database in read-only mode if true.
177
187
  * - `:legacy` (`true`/`false`): By default the database is set up for
178
- * concurrent access with [WAL journaling
179
- * mode](https://www.sqlite.org/wal.html). To prevent Extralite from setting up
180
- * WAL journaling, set this option to true.
188
+ * concurrent access with [WAL journaling mode](https://www.sqlite.org/wal.html).
189
+ * To prevent Extralite from setting up WAL journaling, set this option to true.
190
+ * - `:stmt_cache`: true by default, set to false to disable stmt caching
181
191
  *
182
192
  * @overload initialize(path)
183
193
  * @param path [String] file path (or ':memory:' for memory database)
@@ -215,6 +225,7 @@ VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
215
225
  sqlite3_db_config(db->sqlite3_db ,SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, 1, NULL);
216
226
  #endif
217
227
 
228
+ db->stmt_cache = rb_hash_new();
218
229
  db->trace_proc = Qnil;
219
230
  db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
220
231
 
@@ -277,12 +288,13 @@ inline enum gvl_mode Database_prepare_gvl_mode(Database_t *db) {
277
288
 
278
289
  static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VALUE (*call)(query_ctx *), enum query_mode query_mode) {
279
290
  Database_t *db = self_to_open_database(self);
280
- sqlite3_stmt *stmt;
291
+ sqlite3_stmt *stmt = NULL;
281
292
  VALUE sql = Qnil;
282
293
  VALUE transform = Qnil;
283
294
  // transform mode is set and the first parameter is not a string, so we expect
284
295
  // a transform.,
285
296
  int got_transform = (TYPE(argv[0]) != T_STRING);
297
+ int execute_mode = query_mode == QUERY_VOID;
286
298
 
287
299
  // extract query from args
288
300
  rb_check_arity(argc, got_transform ? 2 : 1, UNLIMITED_ARGUMENTS);
@@ -293,26 +305,38 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
293
305
  argv++;
294
306
  }
295
307
 
296
- sql = rb_funcall(argv[0], ID_strip, 0);
297
- if (RSTRING_LEN(sql) == 0) return Qnil;
298
- // sql = argv[0];
308
+ sql = argv[0];
299
309
 
300
- prepare_multi_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
301
- RB_GC_GUARD(sql);
310
+ stmt_ctx stmt_ctx;
311
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, argc - 1, argv + 1);
302
312
 
303
- if (stmt == NULL) return Qnil;
304
-
305
- bind_all_parameters(stmt, argc - 1, argv + 1);
306
313
  Database_pre_query_hook(db, stmt, sql, argc - 1, argv + 1);
307
-
308
- query_ctx ctx = QUERY_CTX(
309
- self, sql, db, stmt, Qnil, transform,
310
- query_mode, ROW_YIELD_OR_MODE(ROW_MULTI), ALL_ROWS
311
- );
312
-
313
- VALUE result = rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
314
- RB_GC_GUARD(result);
315
- return result;
314
+ if (execute_mode) {
315
+ exec_multi_stmt(&stmt_ctx);
316
+
317
+ query_ctx ctx = QUERY_CTX(
318
+ self, sql, db, NULL, Qnil, transform,
319
+ query_mode, ROW_YIELD_OR_MODE(ROW_MULTI), ALL_ROWS
320
+ );
321
+ ctx.flags = stmt_ctx.flags;
322
+ ctx.total_changes = stmt_ctx.total_changes;
323
+ VALUE result = (VALUE)call(&ctx);
324
+ return result;
325
+ }
326
+ else {
327
+ prep_single_stmt(&stmt_ctx);
328
+ query_ctx ctx = QUERY_CTX(
329
+ self, sql, db, stmt, Qnil, transform,
330
+ query_mode, ROW_YIELD_OR_MODE(ROW_MULTI), ALL_ROWS
331
+ );
332
+ ctx.flags = stmt_ctx.flags;
333
+ if (!stmt) return Qnil;
334
+
335
+ bind_all_parameters(stmt, argc - 1, argv + 1);
336
+ VALUE result = rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
337
+ RB_GC_GUARD(result);
338
+ return result;
339
+ }
316
340
  }
317
341
 
318
342
  /* call-seq:
@@ -490,7 +514,9 @@ VALUE Database_query_single_array(int argc, VALUE *argv, VALUE self) {
490
514
  * db.execute(sql, *parameters) -> changes
491
515
  *
492
516
  * Runs a query returning the total changes effected. This method should be used
493
- * for data- or schema-manipulation queries.
517
+ * for data- or schema-manipulation queries. If the given SQL string contains
518
+ * multiple statements, they will be executed in the order given. If multiple
519
+ * statements are given along with query parameters, an error is raised.
494
520
  *
495
521
  * Query parameters to be bound to placeholders in the query can be specified as
496
522
  * a list of values or as a hash mapping parameter names to values. When
@@ -506,10 +532,10 @@ VALUE Database_query_single_array(int argc, VALUE *argv, VALUE self) {
506
532
  *
507
533
  * @param sql [String] query SQL
508
534
  * @param parameters [Array, Hash] parameters to run query with
509
- * @return [Integer, nil] Total number of changes effected or `nil` if the query ends with a comment.
535
+ * @return [Integer] Total number of changes effected
510
536
  */
511
537
  VALUE Database_execute(int argc, VALUE *argv, VALUE self) {
512
- return Database_perform_query(argc, argv, self, safe_query_changes, QUERY_HASH);
538
+ return Database_perform_query(argc, argv, self, safe_total_changes, QUERY_VOID);
513
539
  }
514
540
 
515
541
  /* call-seq:
@@ -546,7 +572,10 @@ VALUE Database_batch_execute(VALUE self, VALUE sql, VALUE parameters) {
546
572
 
547
573
  if (RSTRING_LEN(sql) == 0) return Qnil;
548
574
 
549
- prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
575
+ stmt_ctx stmt_ctx;
576
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, RARRAY_LEN(parameters), NULL);
577
+ prep_single_stmt(&stmt_ctx);
578
+ // prepare_xsingle_stmt(DB_GVL_MODE(db), db->stmt_cache, db->sqlite3_db, &stmt, sql, 0, NULL);
550
579
  query_ctx ctx = QUERY_CTX(
551
580
  self, sql, db, stmt, parameters,
552
581
  Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS
@@ -582,7 +611,10 @@ VALUE Database_batch_query(VALUE self, VALUE sql, VALUE parameters) {
582
611
  Database_t *db = self_to_open_database(self);
583
612
  sqlite3_stmt *stmt;
584
613
 
585
- prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
614
+ stmt_ctx stmt_ctx;
615
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, RARRAY_LEN(parameters), NULL);
616
+ prep_single_stmt(&stmt_ctx);
617
+ // prepare_xsingle_stmt(DB_GVL_MODE(db), db->stmt_cache, db->sqlite3_db, &stmt, sql, 0, NULL);
586
618
  query_ctx ctx = QUERY_CTX(
587
619
  self, sql, db, stmt, parameters,
588
620
  Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS
@@ -616,7 +648,10 @@ VALUE Database_batch_query_array(VALUE self, VALUE sql, VALUE parameters) {
616
648
  Database_t *db = self_to_open_database(self);
617
649
  sqlite3_stmt *stmt;
618
650
 
619
- prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
651
+ stmt_ctx stmt_ctx;
652
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, RARRAY_LEN(parameters), NULL);
653
+ prep_single_stmt(&stmt_ctx);
654
+ // prepare_xsingle_stmt(DB_GVL_MODE(db), db->stmt_cache, db->sqlite3_db, &stmt, sql, 0, NULL);
620
655
  query_ctx ctx = QUERY_CTX(
621
656
  self, sql, db, stmt, parameters,
622
657
  Qnil, QUERY_ARRAY, ROW_MULTI, ALL_ROWS
@@ -650,7 +685,10 @@ VALUE Database_batch_query_splat(VALUE self, VALUE sql, VALUE parameters) {
650
685
  Database_t *db = self_to_open_database(self);
651
686
  sqlite3_stmt *stmt;
652
687
 
653
- prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
688
+ stmt_ctx stmt_ctx;
689
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, RARRAY_LEN(parameters), NULL);
690
+ prep_single_stmt(&stmt_ctx);
691
+ // prepare_xsingle_stmt(DB_GVL_MODE(db), db->stmt_cache, db->sqlite3_db, &stmt, sql, 0, NULL);
654
692
  query_ctx ctx = QUERY_CTX(
655
693
  self, sql, db, stmt, parameters,
656
694
  Qnil, QUERY_SPLAT, ROW_MULTI, ALL_ROWS
@@ -1383,7 +1421,6 @@ VALUE Extralite_on_progress(int argc, VALUE *argv, VALUE self) {
1383
1421
  */
1384
1422
  VALUE Database_errcode(VALUE self) {
1385
1423
  Database_t *db = self_to_open_database(self);
1386
-
1387
1424
  return INT2NUM(sqlite3_errcode(db->sqlite3_db));
1388
1425
  }
1389
1426
 
@@ -1393,10 +1430,19 @@ VALUE Database_errcode(VALUE self) {
1393
1430
  */
1394
1431
  VALUE Database_errmsg(VALUE self) {
1395
1432
  Database_t *db = self_to_open_database(self);
1396
-
1397
1433
  return rb_str_new2(sqlite3_errmsg(db->sqlite3_db));
1398
1434
  }
1399
1435
 
1436
+ /* Returns the stmt cache for the database. If the database was setup with
1437
+ * stmt_cache set to false, returns nil.
1438
+ *
1439
+ * @return [Hash, nil] stmt cache or nil if disabled
1440
+ */
1441
+ VALUE Database_stmt_cache(VALUE self) {
1442
+ Database_t *db = self_to_open_database(self);
1443
+ return (db->flags & DB_F_STMT_CACHE) ? db->stmt_cache : Qnil;
1444
+ }
1445
+
1400
1446
  #ifdef HAVE_SQLITE3_ERROR_OFFSET
1401
1447
  /* Returns the offset for the last error. This is useful for indicating where in
1402
1448
  * the SQL string an error was encountered.
@@ -1581,6 +1627,7 @@ void Init_ExtraliteDatabase(void) {
1581
1627
  rb_define_method(cDatabase, "columns", Database_columns, 1);
1582
1628
  rb_define_method(cDatabase, "errcode", Database_errcode, 0);
1583
1629
  rb_define_method(cDatabase, "errmsg", Database_errmsg, 0);
1630
+ rb_define_method(cDatabase, "stmt_cache", Database_stmt_cache, 0);
1584
1631
 
1585
1632
  #ifdef HAVE_SQLITE3_ERROR_OFFSET
1586
1633
  rb_define_method(cDatabase, "error_offset", Database_error_offset, 0);
@@ -1644,6 +1691,8 @@ void Init_ExtraliteDatabase(void) {
1644
1691
  ID_to_s = rb_intern_const("to_s");
1645
1692
  ID_track = rb_intern_const("track");
1646
1693
 
1694
+ ID_inspect = rb_intern_const("inspect");
1695
+
1647
1696
  SYM_at_least_once = ID2SYM(rb_intern_const("at_least_once"));
1648
1697
  SYM_full = ID2SYM(rb_intern_const("full"));
1649
1698
  SYM_gvl_release_threshold = ID2SYM(rb_intern_const("gvl_release_threshold"));
@@ -1654,6 +1703,7 @@ void Init_ExtraliteDatabase(void) {
1654
1703
  SYM_passive = ID2SYM(rb_intern_const("passive"));
1655
1704
  SYM_read_only = ID2SYM(rb_intern_const("read_only"));
1656
1705
  SYM_restart = ID2SYM(rb_intern_const("restart"));
1706
+ SYM_stmt_cache = ID2SYM(rb_intern_const("stmt_cache"));
1657
1707
  SYM_truncate = ID2SYM(rb_intern_const("truncate"));
1658
1708
  SYM_wal = ID2SYM(rb_intern_const("wal"));
1659
1709
 
@@ -1667,6 +1717,7 @@ void Init_ExtraliteDatabase(void) {
1667
1717
  rb_gc_register_mark_object(SYM_passive);
1668
1718
  rb_gc_register_mark_object(SYM_read_only);
1669
1719
  rb_gc_register_mark_object(SYM_restart);
1720
+ rb_gc_register_mark_object(SYM_stmt_cache);
1670
1721
  rb_gc_register_mark_object(SYM_truncate);
1671
1722
  rb_gc_register_mark_object(SYM_wal);
1672
1723
 
@@ -31,6 +31,8 @@ extern VALUE cChangeset;
31
31
  extern VALUE cBlob;
32
32
  extern VALUE cTransform;
33
33
 
34
+ extern ID ID_inspect;
35
+
34
36
  extern VALUE mJSON;
35
37
 
36
38
  extern VALUE cError;
@@ -68,9 +70,13 @@ struct progress_handler {
68
70
  int call_count;
69
71
  };
70
72
 
73
+ #define DB_F_STMT_CACHE (1L << 0) // cache stmts
74
+
71
75
  typedef struct {
72
76
  sqlite3 *sqlite3_db;
77
+ VALUE stmt_cache;
73
78
  VALUE trace_proc;
79
+ int flags;
74
80
  int gvl_release_threshold;
75
81
  struct progress_handler progress_handler;
76
82
  } Database_t;
@@ -78,7 +84,8 @@ typedef struct {
78
84
  enum query_mode {
79
85
  QUERY_HASH,
80
86
  QUERY_SPLAT,
81
- QUERY_ARRAY
87
+ QUERY_ARRAY,
88
+ QUERY_VOID
82
89
  };
83
90
 
84
91
  typedef struct {
@@ -108,7 +115,6 @@ typedef struct {
108
115
  } Changeset_t;
109
116
  #endif
110
117
 
111
- // #define TRANSFORM_F_CONTAINER (1 << 0) // node is a container
112
118
  #define TRANSFORM_F_ARRAY (1 << 0) // node is an array container
113
119
  #define TRANSFORM_F_IDENTITY (1 << 1) // node is an identity column
114
120
  #define TRANSFORM_F_NAME (1 << 2) // node has a name VALUE
@@ -159,6 +165,7 @@ typedef struct {
159
165
  Database_t *db;
160
166
  sqlite3 *sqlite3_db;
161
167
  sqlite3_stmt *stmt;
168
+ unsigned int flags;
162
169
 
163
170
  int gvl_release_threshold;
164
171
  enum query_mode query_mode;
@@ -167,6 +174,7 @@ typedef struct {
167
174
 
168
175
  int eof;
169
176
  int step_count;
177
+ int total_changes;
170
178
  } query_ctx;
171
179
 
172
180
  enum gvl_mode {
@@ -174,24 +182,36 @@ enum gvl_mode {
174
182
  GVL_HOLD
175
183
  };
176
184
 
185
+ #define STMT_CTX_F_USE_CACHE (1L << 0)
186
+ #define STMT_CTX_F_CACHE_HIT (1L << 1)
187
+
188
+ typedef struct {
189
+ VALUE stmt_cache;
190
+ VALUE sql;
191
+
192
+ sqlite3 *db;
193
+ sqlite3_stmt **stmtptr;
194
+
195
+ const char *str;
196
+ size_t len;
197
+
198
+ enum gvl_mode gvl_mode;
199
+ unsigned int flags;
200
+ int rc;
201
+ int total_changes;
202
+ int argc;
203
+ VALUE *argv;
204
+ } stmt_ctx;
205
+
177
206
  #define ALL_ROWS -1
178
207
  #define SINGLE_ROW -2
179
208
  #define ROW_YIELD_OR_MODE(default) (rb_block_given_p() ? ROW_YIELD : default)
180
209
  #define ROW_MULTI_P(mode) (mode == ROW_MULTI)
181
210
  #define QUERY_CTX(self, sql, db, stmt, params, transform, query_mode, row_mode, max_rows) { \
182
- self, \
183
- sql, \
184
- params, \
185
- transform, \
186
- db, \
187
- db->sqlite3_db, \
188
- stmt, \
189
- db->gvl_release_threshold, \
190
- query_mode, \
191
- row_mode, \
192
- max_rows, \
193
- 0, \
194
- 0 \
211
+ self, sql, params, transform, \
212
+ db, db->sqlite3_db, stmt, 0, \
213
+ db->gvl_release_threshold, query_mode, row_mode, max_rows, \
214
+ 0, 0, 0 \
195
215
  }
196
216
 
197
217
  #define DEFAULT_GVL_RELEASE_THRESHOLD 1000
@@ -209,6 +229,7 @@ VALUE safe_batch_query_array(query_ctx *ctx);
209
229
  VALUE safe_query_splat(query_ctx *ctx);
210
230
  VALUE safe_query_array(query_ctx *ctx);
211
231
  VALUE safe_query_changes(query_ctx *ctx);
232
+ VALUE safe_total_changes(query_ctx *ctx);
212
233
  VALUE safe_query_columns(query_ctx *ctx);
213
234
  VALUE safe_query_hash(query_ctx *ctx);
214
235
  VALUE safe_query_transform(query_ctx *ctx);
@@ -222,8 +243,9 @@ VALUE Query_next(int argc, VALUE *argv, VALUE self);
222
243
  VALUE Query_to_a(VALUE self);
223
244
  VALUE Query_transform_set(VALUE self, VALUE transform);
224
245
 
225
- void prepare_single_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
226
- void prepare_multi_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql);
246
+ void make_stmt_ctx(stmt_ctx *ctx, Database_t *db, sqlite3_stmt **stmt, VALUE sql, int argc, VALUE *argv);
247
+ void prep_single_stmt(stmt_ctx *ctx);
248
+ int exec_multi_stmt(stmt_ctx *ctx);
227
249
  void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv);
228
250
  void bind_all_parameters_from_object(sqlite3_stmt *stmt, VALUE obj);
229
251
  int stmt_iterate(query_ctx *ctx);
@@ -25,7 +25,7 @@ static void Iterator_compact(void *ptr) {
25
25
 
26
26
  static const rb_data_type_t Iterator_type = {
27
27
  "Iterator",
28
- {Iterator_mark, free, Iterator_size, Iterator_compact},
28
+ {Iterator_mark, xfree, Iterator_size, Iterator_compact},
29
29
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
30
30
  };
31
31
 
@@ -11,7 +11,6 @@
11
11
 
12
12
  VALUE cQuery;
13
13
 
14
- ID ID_inspect;
15
14
  ID ID_slice;
16
15
 
17
16
  VALUE SYM_hash;
@@ -132,9 +131,15 @@ VALUE Query_initialize(VALUE self, VALUE db, VALUE sql, VALUE mode) {
132
131
  return Qnil;
133
132
  }
134
133
 
134
+ static inline void prep_query(Query_t *query) {
135
+ stmt_ctx stmt_ctx;
136
+ make_stmt_ctx(&stmt_ctx, query->db_struct, &(query->stmt), query->sql, 0, NULL);
137
+ prep_single_stmt(&stmt_ctx);
138
+ }
139
+
135
140
  static inline void query_reset(Query_t *query) {
136
141
  if (!query->stmt)
137
- prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
142
+ prep_query(query);
138
143
  else
139
144
  sqlite3_reset(query->stmt);
140
145
 
@@ -146,7 +151,7 @@ static inline void query_reset(Query_t *query) {
146
151
 
147
152
  static inline void query_bind(Query_t *query, int argc, VALUE * argv) {
148
153
  if (!query->stmt)
149
- prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
154
+ prep_query(query);
150
155
  else
151
156
  // we call sqlite3_reset because that's what the SQLite API expects before
152
157
  // changing the binding. See note at bottom of
@@ -406,8 +411,7 @@ VALUE Query_batch_execute(VALUE self, VALUE parameters) {
406
411
  Query_t *query = self_to_query_verify(self);
407
412
  if (query->closed) rb_raise(cError, "Query is closed");
408
413
 
409
- if (!query->stmt)
410
- prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
414
+ if (!query->stmt) prep_query(query);
411
415
 
412
416
  query_ctx ctx = QUERY_CTX(
413
417
  self,
@@ -455,8 +459,7 @@ VALUE Query_batch_query(VALUE self, VALUE parameters) {
455
459
  Query_t *query = self_to_query_verify(self);
456
460
  if (query->closed) rb_raise(cError, "Query is closed");
457
461
 
458
- if (!query->stmt)
459
- prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
462
+ if (!query->stmt) prep_query(query);
460
463
 
461
464
  query_ctx ctx = QUERY_CTX(
462
465
  self,
@@ -562,9 +565,7 @@ VALUE Query_status(int argc, VALUE* argv, VALUE self) {
562
565
  rb_scan_args(argc, argv, "11", &op, &reset);
563
566
 
564
567
  Query_t *query = self_to_query_verify(self);
565
-
566
- if (!query->stmt)
567
- prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
568
+ if (!query->stmt) prep_query(query);
568
569
 
569
570
  int value = sqlite3_stmt_status(query->stmt, NUM2INT(op), RTEST(reset) ? 1 : 0);
570
571
  return INT2NUM(value);
@@ -685,7 +686,6 @@ void Init_ExtraliteQuery(void) {
685
686
  rb_define_method(cQuery, "transform", Query_transform_get, 0);
686
687
  rb_define_method(cQuery, "transform=", Query_transform_set, 1);
687
688
 
688
- ID_inspect = rb_intern_const("inspect");
689
689
  ID_slice = rb_intern_const("slice");
690
690
 
691
691
  SYM_hash = ID2SYM(rb_intern_const("hash"));
@@ -1,4 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Extralite
2
- # Extralite version
3
- VERSION = '3.0.1'
4
+ VERSION = '3.1.0'
4
5
  end
data/lib/extralite.rb CHANGED
@@ -304,7 +304,8 @@ module Extralite
304
304
 
305
305
  def pragma_set(values)
306
306
  sql = values.inject(+'') { |s, (k, v)| s += "pragma #{k}=#{v}; " }
307
- query(sql)
307
+ execute(sql)
308
+ self
308
309
  end
309
310
 
310
311
  def pragma_get(key)
@@ -86,15 +86,15 @@ module Sequel
86
86
 
87
87
  class Database < Sequel::Database
88
88
  include ::Sequel::SQLite::DatabaseMethods
89
-
89
+
90
90
  set_adapter_scheme :extralite
91
-
91
+
92
92
  # Mimic the file:// uri, by having 2 preceding slashes specify a relative
93
93
  # path, and 3 preceding slashes specify an absolute path.
94
94
  def self.uri_to_options(uri) # :nodoc:
95
95
  { :database => (uri.host.nil? && uri.path == '/') ? nil : "#{uri.host}#{uri.path}" }
96
96
  end
97
-
97
+
98
98
  private_class_method :uri_to_options
99
99
 
100
100
  # The conversion procs to use for this database
@@ -129,12 +129,12 @@ module Sequel
129
129
  func.result = Regexp.new(regexp_str).match(string) ? 1 : 0
130
130
  end
131
131
  end
132
-
132
+
133
133
  class << db
134
134
  attr_reader :prepared_statements
135
135
  end
136
136
  db.instance_variable_set(:@prepared_statements, {})
137
-
137
+
138
138
  db
139
139
  end
140
140
 
@@ -148,7 +148,7 @@ module Sequel
148
148
  def disconnect_connection(c)
149
149
  c.close
150
150
  end
151
-
151
+
152
152
  # Run the given SQL with the given arguments and yield each row.
153
153
  def execute(sql, opts=OPTS, &block)
154
154
  _execute(:select, sql, opts, &block)
@@ -158,7 +158,7 @@ module Sequel
158
158
  def execute_dui(sql, opts=OPTS)
159
159
  _execute(:update, sql, opts)
160
160
  end
161
-
161
+
162
162
  # Drop any prepared statements on the connection when executing DDL. This is because
163
163
  # prepared statements lock the table in such a way that you can't drop or alter the
164
164
  # table while a prepared statement that references it still exists.
@@ -169,11 +169,11 @@ module Sequel
169
169
  super
170
170
  end
171
171
  end
172
-
172
+
173
173
  def execute_insert(sql, opts=OPTS)
174
174
  _execute(:insert, sql, opts)
175
175
  end
176
-
176
+
177
177
  def freeze
178
178
  @conversion_procs.freeze
179
179
  super
@@ -194,13 +194,13 @@ module Sequel
194
194
  end
195
195
 
196
196
  private
197
-
197
+
198
198
  def adapter_initialize
199
199
  @conversion_procs = SQLITE_TYPES.dup
200
200
  @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp)
201
201
  set_integer_booleans
202
202
  end
203
-
203
+
204
204
  # Yield an available connection. Rescue
205
205
  # any Extralite::Errors and turn them into DatabaseErrors.
206
206
  def _execute(type, sql, opts, &block)
@@ -228,7 +228,7 @@ module Sequel
228
228
  rescue ::Extralite::Error => e
229
229
  raise_error(e)
230
230
  end
231
-
231
+
232
232
  # The Extralite adapter does not need the pool to convert exceptions.
233
233
  # Also, force the max connections to 1 if a memory database is being
234
234
  # used, as otherwise each connection gets a separate database.
@@ -239,7 +239,7 @@ module Sequel
239
239
  o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
240
240
  o
241
241
  end
242
-
242
+
243
243
  def prepared_statement_argument(arg)
244
244
  case arg
245
245
  when Date, DateTime, Time
@@ -295,7 +295,7 @@ module Sequel
295
295
  end
296
296
  end
297
297
  end
298
-
298
+
299
299
  def database_error_classes
300
300
  [::Extralite::Error]
301
301
  end
@@ -308,15 +308,15 @@ module Sequel
308
308
  exception.code if exception.respond_to?(:code)
309
309
  end
310
310
  end
311
-
311
+
312
312
  class Dataset < Sequel::Dataset
313
313
  include ::Sequel::SQLite::DatasetMethods
314
314
 
315
315
  module ArgumentMapper
316
316
  include Sequel::Dataset::ArgumentMapper
317
-
317
+
318
318
  protected
319
-
319
+
320
320
  # Return a hash with the same values as the given hash,
321
321
  # but with the keys converted to strings.
322
322
  def map_to_prepared_args(hash)
@@ -324,16 +324,16 @@ module Sequel
324
324
  hash.each{|k,v| args[k.to_s.gsub('.', '__')] = v}
325
325
  args
326
326
  end
327
-
327
+
328
328
  private
329
-
329
+
330
330
  # Extralite uses a : before the name of the argument for named
331
331
  # arguments.
332
332
  def prepared_arg(k)
333
333
  LiteralString.new("#{prepared_arg_placeholder}#{k.to_s.gsub('.', '__')}")
334
334
  end
335
335
  end
336
-
336
+
337
337
  BindArgumentMethods = prepared_statements_module(:bind, ArgumentMapper)
338
338
  PreparedStatementMethods = prepared_statements_module(:prepare, BindArgumentMethods)
339
339
 
@@ -371,9 +371,9 @@ module Sequel
371
371
  def supports_regexp?
372
372
  db.allow_regexp?
373
373
  end
374
-
374
+
375
375
  private
376
-
376
+
377
377
  # The base type name for a given type, without any parenthetical part.
378
378
  def base_type_name(t)
379
379
  (t =~ /^(.*?)\(/ ? $1 : t).downcase if t