extralite 1.27 → 2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,13 +6,17 @@ VALUE cError;
6
6
  VALUE cSQLError;
7
7
  VALUE cBusyError;
8
8
  VALUE cInterruptError;
9
+ VALUE eArgumentError;
9
10
 
11
+ ID ID_bind;
10
12
  ID ID_call;
11
13
  ID ID_keys;
12
14
  ID ID_new;
13
15
  ID ID_strip;
14
16
  ID ID_to_s;
15
17
 
18
+ VALUE SYM_read_only;
19
+
16
20
  static size_t Database_size(const void *ptr) {
17
21
  return sizeof(Database_t);
18
22
  }
@@ -35,27 +39,21 @@ static VALUE Database_allocate(VALUE klass) {
35
39
  return TypedData_Wrap_Struct(klass, &Database_type, db);
36
40
  }
37
41
 
38
- #define GetDatabase(obj, database) \
39
- TypedData_Get_Struct((obj), Database_t, &Database_type, (database))
40
-
41
- // make sure the database is open
42
- #define GetOpenDatabase(obj, database) { \
43
- TypedData_Get_Struct((obj), Database_t, &Database_type, (database)); \
44
- if (!(database)->sqlite3_db) { \
45
- rb_raise(cError, "Database is closed"); \
46
- } \
42
+ inline Database_t *self_to_database(VALUE self) {
43
+ Database_t *db;
44
+ TypedData_Get_Struct(self, Database_t, &Database_type, db);
45
+ return db;
47
46
  }
48
47
 
49
- Database_t *Database_struct(VALUE self) {
50
- Database_t *db;
51
- GetDatabase(self, db);
48
+ inline Database_t *self_to_open_database(VALUE self) {
49
+ Database_t *db = self_to_database(self);
50
+ if (!(db)->sqlite3_db) rb_raise(cError, "Database is closed");
51
+
52
52
  return db;
53
53
  }
54
54
 
55
- sqlite3 *Database_sqlite3_db(VALUE self) {
56
- Database_t *db;
57
- GetDatabase(self, db);
58
- return db->sqlite3_db;
55
+ inline sqlite3 *Database_sqlite3_db(VALUE self) {
56
+ return self_to_database(self)->sqlite3_db;
59
57
  }
60
58
 
61
59
  /* call-seq:
@@ -68,18 +66,37 @@ VALUE Extralite_sqlite3_version(VALUE self) {
68
66
  return rb_str_new_cstr(sqlite3_version);
69
67
  }
70
68
 
71
- /* call-seq:
72
- * db.initialize(path)
69
+ static inline int db_open_flags_from_opts(VALUE opts) {
70
+ if (opts == Qnil) goto default_flags;
71
+
72
+ if (TYPE(opts) != T_HASH)
73
+ rb_raise(eArgumentError, "Expected hash as database initialization options");
74
+
75
+ VALUE read_only = rb_hash_aref(opts, SYM_read_only);
76
+ if (RTEST(read_only)) return SQLITE_OPEN_READONLY;
77
+ default_flags:
78
+ return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
79
+ }
80
+
81
+ /* Initializes a new SQLite database with the given path and options.
73
82
  *
74
- * Initializes a new SQLite database with the given path.
83
+ * @overload initialize(path)
84
+ * @param path [String] file path (or ':memory:' for memory database)
85
+ * @return [void]
86
+ * @overload initialize(path, read_only: false)
87
+ * @param path [String] file path (or ':memory:' for memory database)
88
+ * @param read_only [boolean] true for opening the database for reading only
89
+ * @return [void]
75
90
  */
91
+ VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
92
+ Database_t *db = self_to_database(self);
93
+ VALUE path;
94
+ VALUE opts = Qnil;
76
95
 
77
- VALUE Database_initialize(VALUE self, VALUE path) {
78
- int rc;
79
- Database_t *db;
80
- GetDatabase(self, db);
96
+ rb_scan_args(argc, argv, "11", &path, &opts);
97
+ int flags = db_open_flags_from_opts(opts);
81
98
 
82
- rc = sqlite3_open(StringValueCStr(path), &db->sqlite3_db);
99
+ int rc = sqlite3_open_v2(StringValueCStr(path), &db->sqlite3_db, flags, NULL);
83
100
  if (rc) {
84
101
  sqlite3_close_v2(db->sqlite3_db);
85
102
  rb_raise(cError, "%s", sqlite3_errstr(rc));
@@ -105,6 +122,16 @@ VALUE Database_initialize(VALUE self, VALUE path) {
105
122
  return Qnil;
106
123
  }
107
124
 
125
+ /* Returns true if the database was open for read only access.
126
+ *
127
+ * @return [boolean] true if database is open for read only access
128
+ */
129
+ VALUE Database_read_only_p(VALUE self) {
130
+ Database_t *db = self_to_database(self);
131
+ int open = sqlite3_db_readonly(db->sqlite3_db, "main");
132
+ return (open == 1) ? Qtrue : Qfalse;
133
+ }
134
+
108
135
  /* call-seq:
109
136
  * db.close -> db
110
137
  *
@@ -112,8 +139,7 @@ VALUE Database_initialize(VALUE self, VALUE path) {
112
139
  */
113
140
  VALUE Database_close(VALUE self) {
114
141
  int rc;
115
- Database_t *db;
116
- GetDatabase(self, db);
142
+ Database_t *db = self_to_database(self);
117
143
 
118
144
  rc = sqlite3_close_v2(db->sqlite3_db);
119
145
  if (rc) {
@@ -132,14 +158,12 @@ VALUE Database_close(VALUE self) {
132
158
  * @return [bool] is database closed
133
159
  */
134
160
  VALUE Database_closed_p(VALUE self) {
135
- Database_t *db;
136
- GetDatabase(self, db);
137
-
161
+ Database_t *db = self_to_database(self);
138
162
  return db->sqlite3_db ? Qfalse : Qtrue;
139
163
  }
140
164
 
141
165
  static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VALUE (*call)(query_ctx *)) {
142
- Database_t *db;
166
+ Database_t *db = self_to_open_database(self);
143
167
  sqlite3_stmt *stmt;
144
168
  VALUE sql;
145
169
 
@@ -149,13 +173,12 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
149
173
  if (RSTRING_LEN(sql) == 0) return Qnil;
150
174
 
151
175
  // prepare query ctx
152
- GetOpenDatabase(self, db);
153
176
  if (db->trace_block != Qnil) rb_funcall(db->trace_block, ID_call, 1, sql);
154
177
  prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
155
178
  RB_GC_GUARD(sql);
156
179
 
157
180
  bind_all_parameters(stmt, argc - 1, argv + 1);
158
- query_ctx ctx = { self, db->sqlite3_db, stmt };
181
+ query_ctx ctx = { self, db->sqlite3_db, stmt, Qnil, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
159
182
 
160
183
  return rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
161
184
  }
@@ -170,7 +193,7 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
170
193
  *
171
194
  * Query parameters to be bound to placeholders in the query can be specified as
172
195
  * a list of values or as a hash mapping parameter names to values. When
173
- * parameters are given as a least, the query should specify parameters using
196
+ * parameters are given as an array, the query should specify parameters using
174
197
  * `?`:
175
198
  *
176
199
  * db.query('select * from foo where x = ?', 42)
@@ -195,7 +218,7 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
195
218
  *
196
219
  * Query parameters to be bound to placeholders in the query can be specified as
197
220
  * a list of values or as a hash mapping parameter names to values. When
198
- * parameters are given as a least, the query should specify parameters using
221
+ * parameters are given as an array, the query should specify parameters using
199
222
  * `?`:
200
223
  *
201
224
  * db.query_ary('select * from foo where x = ?', 42)
@@ -219,7 +242,7 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
219
242
  *
220
243
  * Query parameters to be bound to placeholders in the query can be specified as
221
244
  * a list of values or as a hash mapping parameter names to values. When
222
- * parameters are given as a least, the query should specify parameters using
245
+ * parameters are given as an array, the query should specify parameters using
223
246
  * `?`:
224
247
  *
225
248
  * db.query_single_row('select * from foo where x = ?', 42)
@@ -244,7 +267,7 @@ VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
244
267
  *
245
268
  * Query parameters to be bound to placeholders in the query can be specified as
246
269
  * a list of values or as a hash mapping parameter names to values. When
247
- * parameters are given as a least, the query should specify parameters using
270
+ * parameters are given as an array, the query should specify parameters using
248
271
  * `?`:
249
272
  *
250
273
  * db.query_single_column('select x from foo where x = ?', 42)
@@ -268,7 +291,7 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
268
291
  *
269
292
  * Query parameters to be bound to placeholders in the query can be specified as
270
293
  * a list of values or as a hash mapping parameter names to values. When
271
- * parameters are given as a least, the query should specify parameters using
294
+ * parameters are given as an array, the query should specify parameters using
272
295
  * `?`:
273
296
  *
274
297
  * db.query_single_value('select x from foo where x = ?', 42)
@@ -285,6 +308,31 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
285
308
  return Database_perform_query(argc, argv, self, safe_query_single_value);
286
309
  }
287
310
 
311
+ /* call-seq:
312
+ * db.execute(sql, *parameters) -> changes
313
+ *
314
+ * Runs a query returning the total changes effected. This method should be used
315
+ * for data- or schema-manipulation queries.
316
+ *
317
+ * Query parameters to be bound to placeholders in the query can be specified as
318
+ * a list of values or as a hash mapping parameter names to values. When
319
+ * parameters are given as an array, the query should specify parameters using
320
+ * `?`:
321
+ *
322
+ * db.execute('update foo set x = ? where y = ?', 42, 43)
323
+ *
324
+ * Named placeholders are specified using `:`. The placeholder values are
325
+ * specified using a hash, where keys are either strings are symbols. String
326
+ * keys can include or omit the `:` prefix. The following are equivalent:
327
+ *
328
+ * db.execute('update foo set x = :bar', bar: 42)
329
+ * db.execute('update foo set x = :bar', 'bar' => 42)
330
+ * db.execute('update foo set x = :bar', ':bar' => 42)
331
+ */
332
+ VALUE Database_execute(int argc, VALUE *argv, VALUE self) {
333
+ return Database_perform_query(argc, argv, self, safe_query_changes);
334
+ }
335
+
288
336
  /* call-seq:
289
337
  * db.execute_multi(sql, params_array) -> changes
290
338
  *
@@ -296,19 +344,18 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
296
344
  * [1, 2, 3],
297
345
  * [4, 5, 6]
298
346
  * ]
299
- * db.execute_multi_query('insert into foo values (?, ?, ?)', records)
347
+ * db.execute_multi('insert into foo values (?, ?, ?)', records)
300
348
  *
301
349
  */
302
350
  VALUE Database_execute_multi(VALUE self, VALUE sql, VALUE params_array) {
303
- Database_t *db;
351
+ Database_t *db = self_to_open_database(self);
304
352
  sqlite3_stmt *stmt;
305
353
 
306
354
  if (RSTRING_LEN(sql) == 0) return Qnil;
307
355
 
308
356
  // prepare query ctx
309
- GetOpenDatabase(self, db);
310
357
  prepare_single_stmt(db->sqlite3_db, &stmt, sql);
311
- query_ctx ctx = { self, db->sqlite3_db, stmt, params_array };
358
+ query_ctx ctx = { self, db->sqlite3_db, stmt, params_array, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
312
359
 
313
360
  return rb_ensure(SAFE(safe_execute_multi), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
314
361
  }
@@ -328,8 +375,7 @@ VALUE Database_columns(VALUE self, VALUE sql) {
328
375
  * Returns the rowid of the last inserted row.
329
376
  */
330
377
  VALUE Database_last_insert_rowid(VALUE self) {
331
- Database_t *db;
332
- GetOpenDatabase(self, db);
378
+ Database_t *db = self_to_open_database(self);
333
379
 
334
380
  return INT2FIX(sqlite3_last_insert_rowid(db->sqlite3_db));
335
381
  }
@@ -340,8 +386,7 @@ VALUE Database_last_insert_rowid(VALUE self) {
340
386
  * Returns the number of changes made to the database by the last operation.
341
387
  */
342
388
  VALUE Database_changes(VALUE self) {
343
- Database_t *db;
344
- GetOpenDatabase(self, db);
389
+ Database_t *db = self_to_open_database(self);
345
390
 
346
391
  return INT2FIX(sqlite3_changes(db->sqlite3_db));
347
392
  }
@@ -354,8 +399,7 @@ VALUE Database_changes(VALUE self) {
354
399
  VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
355
400
  const char *db_name;
356
401
  const char *filename;
357
- Database_t *db;
358
- GetOpenDatabase(self, db);
402
+ Database_t *db = self_to_open_database(self);
359
403
 
360
404
  rb_check_arity(argc, 0, 1);
361
405
  db_name = (argc == 1) ? StringValueCStr(argv[0]) : "main";
@@ -369,8 +413,7 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
369
413
  * Returns true if a transaction is currently in progress.
370
414
  */
371
415
  VALUE Database_transaction_active_p(VALUE self) {
372
- Database_t *db;
373
- GetOpenDatabase(self, db);
416
+ Database_t *db = self_to_open_database(self);
374
417
 
375
418
  return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
376
419
  }
@@ -382,8 +425,7 @@ VALUE Database_transaction_active_p(VALUE self) {
382
425
  * Loads an extension with the given path.
383
426
  */
384
427
  VALUE Database_load_extension(VALUE self, VALUE path) {
385
- Database_t *db;
386
- GetOpenDatabase(self, db);
428
+ Database_t *db = self_to_open_database(self);
387
429
  char *err_msg;
388
430
 
389
431
  int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg);
@@ -398,12 +440,16 @@ VALUE Database_load_extension(VALUE self, VALUE path) {
398
440
  #endif
399
441
 
400
442
  /* call-seq:
401
- * db.prepare(sql) -> Extralite::PreparedStatement
443
+ * db.prepare(sql) -> Extralite::Query
402
444
  *
403
445
  * Creates a prepared statement with the given SQL query.
404
446
  */
405
- VALUE Database_prepare(VALUE self, VALUE sql) {
406
- return rb_funcall(cPreparedStatement, ID_new, 2, self, sql);
447
+ VALUE Database_prepare(int argc, VALUE *argv, VALUE self) {
448
+ rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
449
+ VALUE query = rb_funcall(cQuery, ID_new, 2, self, argv[0]);
450
+ if (argc > 1) rb_funcallv(query, ID_bind, argc - 1, argv + 1);
451
+ RB_GC_GUARD(query);
452
+ return query;
407
453
  }
408
454
 
409
455
  /* call-seq:
@@ -417,8 +463,7 @@ VALUE Database_prepare(VALUE self, VALUE sql) {
417
463
  * For more information, consult the [sqlite3 API docs](https://sqlite.org/c3ref/interrupt.html).
418
464
  */
419
465
  VALUE Database_interrupt(VALUE self) {
420
- Database_t *db;
421
- GetOpenDatabase(self, db);
466
+ Database_t *db = self_to_open_database(self);
422
467
 
423
468
  sqlite3_interrupt(db->sqlite3_db);
424
469
  return self;
@@ -510,8 +555,7 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
510
555
 
511
556
  int dst_is_fn = TYPE(dst) == T_STRING;
512
557
 
513
- Database_t *src;
514
- GetOpenDatabase(self, src);
558
+ Database_t *src = self_to_open_database(self);
515
559
  sqlite3 *dst_db;
516
560
 
517
561
  if (dst_is_fn) {
@@ -522,8 +566,7 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
522
566
  }
523
567
  }
524
568
  else {
525
- Database_t *dst_struct;
526
- GetOpenDatabase(dst, dst_struct);
569
+ Database_t *dst_struct = self_to_open_database(dst);
527
570
  dst_db = dst_struct->sqlite3_db;
528
571
  }
529
572
 
@@ -540,6 +583,9 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
540
583
  backup_ctx ctx = { dst_db, dst_is_fn, backup, rb_block_given_p(), 0 };
541
584
  rb_ensure(SAFE(backup_safe_iterate), (VALUE)&ctx, SAFE(backup_cleanup), (VALUE)&ctx);
542
585
 
586
+ RB_GC_GUARD(src_name);
587
+ RB_GC_GUARD(dst_name);
588
+
543
589
  return self;
544
590
  }
545
591
 
@@ -575,8 +621,7 @@ VALUE Database_status(int argc, VALUE *argv, VALUE self) {
575
621
 
576
622
  rb_scan_args(argc, argv, "11", &op, &reset);
577
623
 
578
- Database_t *db;
579
- GetOpenDatabase(self, db);
624
+ Database_t *db = self_to_open_database(self);
580
625
 
581
626
  int rc = sqlite3_db_status(db->sqlite3_db, NUM2INT(op), &cur, &hwm, RTEST(reset) ? 1 : 0);
582
627
  if (rc != SQLITE_OK) rb_raise(cError, "%s", sqlite3_errstr(rc));
@@ -596,8 +641,7 @@ VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
596
641
 
597
642
  rb_scan_args(argc, argv, "11", &category, &new_value);
598
643
 
599
- Database_t *db;
600
- GetOpenDatabase(self, db);
644
+ Database_t *db = self_to_open_database(self);
601
645
 
602
646
  int value = sqlite3_limit(db->sqlite3_db, NUM2INT(category), RTEST(new_value) ? NUM2INT(new_value) : -1);
603
647
 
@@ -614,8 +658,7 @@ VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
614
658
  * disable the busy timeout, set it to 0 or nil.
615
659
  */
616
660
  VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
617
- Database_t *db;
618
- GetOpenDatabase(self, db);
661
+ Database_t *db = self_to_open_database(self);
619
662
 
620
663
  int ms = (sec == Qnil) ? 0 : (int)(NUM2DBL(sec) * 1000);
621
664
  int rc = sqlite3_busy_timeout(db->sqlite3_db, ms);
@@ -630,8 +673,7 @@ VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
630
673
  * Returns the total number of changes made to the database since opening it.
631
674
  */
632
675
  VALUE Database_total_changes(VALUE self) {
633
- Database_t *db;
634
- GetOpenDatabase(self, db);
676
+ Database_t *db = self_to_open_database(self);
635
677
 
636
678
  int value = sqlite3_total_changes(db->sqlite3_db);
637
679
  return INT2NUM(value);
@@ -645,8 +687,7 @@ VALUE Database_total_changes(VALUE self) {
645
687
  * executed.
646
688
  */
647
689
  VALUE Database_trace(VALUE self) {
648
- Database_t *db;
649
- GetOpenDatabase(self, db);
690
+ Database_t *db = self_to_open_database(self);
650
691
 
651
692
  db->trace_block = rb_block_given_p() ? rb_block_proc() : Qnil;
652
693
  return self;
@@ -658,8 +699,7 @@ VALUE Database_trace(VALUE self) {
658
699
  * Returns the last error code for the database.
659
700
  */
660
701
  VALUE Database_errcode(VALUE self) {
661
- Database_t *db;
662
- GetOpenDatabase(self, db);
702
+ Database_t *db = self_to_open_database(self);
663
703
 
664
704
  return INT2NUM(sqlite3_errcode(db->sqlite3_db));
665
705
  }
@@ -670,8 +710,7 @@ VALUE Database_errcode(VALUE self) {
670
710
  * Returns the last error message for the database.
671
711
  */
672
712
  VALUE Database_errmsg(VALUE self) {
673
- Database_t *db;
674
- GetOpenDatabase(self, db);
713
+ Database_t *db = self_to_open_database(self);
675
714
 
676
715
  return rb_str_new2(sqlite3_errmsg(db->sqlite3_db));
677
716
  }
@@ -683,13 +722,25 @@ VALUE Database_errmsg(VALUE self) {
683
722
  * Returns the offset for the last error
684
723
  */
685
724
  VALUE Database_error_offset(VALUE self) {
686
- Database_t *db;
687
- GetOpenDatabase(self, db);
725
+ Database_t *db = self_to_open_database(self);
688
726
 
689
727
  return INT2NUM(sqlite3_error_offset(db->sqlite3_db));
690
728
  }
691
729
  #endif
692
730
 
731
+ /* Returns a short string representation of the database instance, including the
732
+ * database filename.
733
+ *
734
+ * @return [String] string representation
735
+ */
736
+ VALUE Database_inspect(VALUE self) {
737
+ VALUE cname = rb_class_name(CLASS_OF(self));
738
+ VALUE filename = Database_filename(0, NULL, self);
739
+ if (RSTRING_LEN(filename) == 0) filename = rb_str_new_literal(":memory:");
740
+
741
+ return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, filename);
742
+ }
743
+
693
744
  void Init_ExtraliteDatabase(void) {
694
745
  VALUE mExtralite = rb_define_module("Extralite");
695
746
  rb_define_singleton_method(mExtralite, "runtime_status", Extralite_runtime_status, -1);
@@ -711,19 +762,22 @@ void Init_ExtraliteDatabase(void) {
711
762
  rb_define_method(cDatabase, "error_offset", Database_error_offset, 0);
712
763
  #endif
713
764
 
765
+ rb_define_method(cDatabase, "execute", Database_execute, -1);
714
766
  rb_define_method(cDatabase, "execute_multi", Database_execute_multi, 2);
715
767
  rb_define_method(cDatabase, "filename", Database_filename, -1);
716
- rb_define_method(cDatabase, "initialize", Database_initialize, 1);
768
+ rb_define_method(cDatabase, "initialize", Database_initialize, -1);
769
+ rb_define_method(cDatabase, "inspect", Database_inspect, 0);
717
770
  rb_define_method(cDatabase, "interrupt", Database_interrupt, 0);
718
771
  rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
719
772
  rb_define_method(cDatabase, "limit", Database_limit, -1);
720
- rb_define_method(cDatabase, "prepare", Database_prepare, 1);
773
+ rb_define_method(cDatabase, "prepare", Database_prepare, -1);
721
774
  rb_define_method(cDatabase, "query", Database_query_hash, -1);
722
775
  rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
723
776
  rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
724
777
  rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
725
778
  rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
726
779
  rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
780
+ rb_define_method(cDatabase, "read_only?", Database_read_only_p, 0);
727
781
  rb_define_method(cDatabase, "status", Database_status, -1);
728
782
  rb_define_method(cDatabase, "total_changes", Database_total_changes, 0);
729
783
  rb_define_method(cDatabase, "trace", Database_trace, 0);
@@ -742,9 +796,15 @@ void Init_ExtraliteDatabase(void) {
742
796
  rb_gc_register_mark_object(cBusyError);
743
797
  rb_gc_register_mark_object(cInterruptError);
744
798
 
799
+ eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
800
+
801
+ ID_bind = rb_intern("bind");
745
802
  ID_call = rb_intern("call");
746
803
  ID_keys = rb_intern("keys");
747
804
  ID_new = rb_intern("new");
748
805
  ID_strip = rb_intern("strip");
749
806
  ID_to_s = rb_intern("to_s");
807
+
808
+ SYM_read_only = ID2SYM(rb_intern("read_only"));
809
+ rb_gc_register_mark_object(SYM_read_only);
750
810
  }
@@ -4,13 +4,13 @@ if ENV['EXTRALITE_BUNDLE']
4
4
  require_relative('extconf-bundle')
5
5
  else
6
6
  ENV['RC_ARCHS'] = '' if RUBY_PLATFORM =~ /darwin/
7
-
7
+
8
8
  require 'mkmf'
9
-
9
+
10
10
  # :stopdoc:
11
-
11
+
12
12
  RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
13
-
13
+
14
14
  ldflags = cppflags = nil
15
15
  if RbConfig::CONFIG["host_os"] =~ /darwin/
16
16
  begin
@@ -25,7 +25,7 @@ else
25
25
  cppflags = "#{brew_prefix}/include"
26
26
  pkg_conf = "#{brew_prefix}/lib/pkgconfig"
27
27
  end
28
-
28
+
29
29
  # pkg_config should be less error prone than parsing compiler
30
30
  # commandline options, but we need to set default ldflags and cpp flags
31
31
  # in case the user doesn't have pkg-config installed
@@ -33,13 +33,13 @@ else
33
33
  rescue
34
34
  end
35
35
  end
36
-
36
+
37
37
  if with_config('sqlcipher')
38
38
  pkg_config("sqlcipher")
39
39
  else
40
40
  pkg_config("sqlite3")
41
41
  end
42
-
42
+
43
43
  # --with-sqlite3-{dir,include,lib}
44
44
  if with_config('sqlcipher')
45
45
  $CFLAGS << ' -DUSING_SQLCIPHER'
@@ -47,15 +47,15 @@ else
47
47
  else
48
48
  dir_config("sqlite3", cppflags, ldflags)
49
49
  end
50
-
50
+
51
51
  if RbConfig::CONFIG["host_os"] =~ /mswin/
52
52
  $CFLAGS << ' -W3'
53
53
  end
54
-
54
+
55
55
  if RUBY_VERSION < '2.7'
56
56
  $CFLAGS << ' -DTAINTING_SUPPORT'
57
57
  end
58
-
58
+
59
59
  # @!visibility private
60
60
  def asplode missing
61
61
  if RUBY_PLATFORM =~ /mingw|mswin/
@@ -70,25 +70,25 @@ else
70
70
  error
71
71
  end
72
72
  end
73
-
73
+
74
74
  asplode('sqlite3.h') unless find_header 'sqlite3.h'
75
75
  find_library 'pthread', 'pthread_create' # 1.8 support. *shrug*
76
-
76
+
77
77
  have_library 'dl' # for static builds
78
-
78
+
79
79
  if with_config('sqlcipher')
80
80
  asplode('sqlcipher') unless find_library 'sqlcipher', 'sqlite3_libversion_number'
81
81
  else
82
82
  asplode('sqlite3') unless find_library 'sqlite3', 'sqlite3_libversion_number'
83
83
  end
84
-
84
+
85
85
  have_func('sqlite3_enable_load_extension')
86
86
  have_func('sqlite3_load_extension')
87
87
  have_func('sqlite3_prepare_v2')
88
88
  have_func('sqlite3_error_offset')
89
-
89
+
90
90
  $defs << "-DEXTRALITE_NO_BUNDLE"
91
-
91
+
92
92
  dir_config('extralite_ext')
93
93
  create_makefile('extralite_ext')
94
94
  end