Class: Extralite::Database
- Inherits:
-
Object
- Object
- Extralite::Database
- Defined in:
- lib/extralite.rb,
ext/extralite/database.c
Defined Under Namespace
Classes: Rollback
Instance Method Summary collapse
-
#backup(*args) {|remaining, total| ... } ⇒ Extralite::Database
Creates a backup of the database to the given destination, which can be either a filename or a database instance.
-
#batch_execute(sql, params_source) ⇒ Integer
(also: #execute_multi)
Executes the given query for each list of parameters in the paramter source.
-
#batch_query(sql, parameters) ⇒ Array<Hash>, Integer
Executes the given query for each list of parameters in the given paramter source.
-
#batch_query_array(sql, parameters) ⇒ Array<Array>, Integer
Executes the given query for each list of parameters in the given paramter source.
-
#batch_query_hash(sql, parameters) ⇒ Array<Hash>, Integer
Executes the given query for each list of parameters in the given paramter source.
-
#batch_query_splat(sql, parameters) ⇒ Array<any>, Integer
Executes the given query for each list of parameters in the given paramter source.
-
#busy_timeout=(sec) ⇒ Extralite::Database
Sets the busy timeout for the database, in seconds or fractions thereof.
-
#changes ⇒ Integer
Returns the number of changes made to the database by the last operation.
-
#close ⇒ Extralite::Database
Closes the database.
-
#closed? ⇒ Boolean
Returns true if the database is closed.
-
#columns(sql) ⇒ Array<String>
Returns the column names for the given query, without running it.
-
#errcode ⇒ Integer
Returns the last error code for the database.
-
#errmsg ⇒ String
Returns the last error message for the database.
-
#error_offset ⇒ Integer
Returns the offset for the last error.
-
#execute(sql, *parameters) ⇒ Integer?
Runs a query returning the total changes effected.
-
#filename(*args) ⇒ Object
Returns the database filename.
-
#gvl_release_threshold ⇒ Integer
Returns the database's GVL release threshold.
-
#gvl_release_threshold=(value) ⇒ Integer
Sets the database's GVL release threshold.
-
#initialize(*args) ⇒ Object
constructor
Initializes a new SQLite database with the given path and options:.
-
#inspect ⇒ String
Returns a short string representation of the database instance, including the database filename.
-
#interrupt ⇒ Extralite::Database
Interrupts a long running query.
-
#last_insert_rowid ⇒ Integer
Returns the rowid of the last inserted row.
-
#limit(*args) ⇒ Object
Returns the current limit for the given category.
-
#load_extension(path) ⇒ Extralite::Database
Loads an extension with the given path.
-
#on_progress(*args) ⇒ Extralite::Database
Installs or removes a progress handler that will be executed periodically while a query is running.
-
#pragma(value) ⇒ Hash
Gets or sets one or more database pragmas.
-
#prepare(*args) ⇒ Extralite::Query
Creates a prepared query with the given SQL query in hash mode.
-
#prepare_array(*args) ⇒ Extralite::Query
Creates a prepared query with the given SQL query in array mode.
-
#prepare_hash(*args) ⇒ Extralite::Query
Creates a prepared query with the given SQL query in hash mode.
-
#prepare_splat(*args) ⇒ Extralite::Query
Creates a prepared query with the given SQL query in argv mode.
-
#query(*args) ⇒ Object
Runs a query returning rows as hashes (with symbol keys).
-
#query_array(*args) ⇒ Object
Runs a query returning rows as arrays.
-
#query_hash(*args) ⇒ Object
Runs a query returning rows as hashes (with symbol keys).
-
#query_single(*args) ⇒ Object
Runs a query returning a single row as a hash.
-
#query_single_array(*args) ⇒ Object
Runs a query returning a single row as an array.
-
#query_single_hash(*args) ⇒ Object
Runs a query returning a single row as a hash.
-
#query_single_splat(*args) ⇒ Object
Runs a query returning a single row as an array or a single value.
-
#query_splat(*args) ⇒ Object
Runs a query and transforms rows through the given transform poc.
-
#read_only? ⇒ boolean
Returns true if the database was open for read only access.
-
#release(name) ⇒ Extralite::Database
Release a savepoint with the given name.
-
#rollback! ⇒ Extralite::Database
Rolls back the currently active transaction.
-
#rollback_to(name) ⇒ Extralite::Database
Rolls back changes to a savepoint with the given name.
-
#savepoint(name) ⇒ Extralite::Database
Creates a savepoint with the given name.
-
#status(*args) ⇒ Object
Returns database status values for the given op as an array containing the current value and the high water mark value.
-
#tables(db = 'main') ⇒ Array
Returns the list of currently defined tables.
-
#total_changes ⇒ Integer
Returns the total number of changes made to the database since opening it.
-
#trace ⇒ Extralite::Database
Installs or removes a block that will be invoked for every SQL statement executed.
-
#track_changes(*tables) { ... } ⇒ Extralite::Changeset
Tracks changes to the database and returns a changeset.
-
#transaction(mode = :immediate) ⇒ Any
Starts a transaction and runs the given block.
-
#transaction_active? ⇒ bool
Returns true if a transaction is currently in progress.
-
#wal_checkpoint(*args) ⇒ Object
Runs a WAL checkpoint operation with the given mode.
Constructor Details
#initialize(path) ⇒ void #initialize(path, gvl_release_threshold: , on_progress: , read_only: , wal: ) ⇒ void
Initializes a new SQLite database with the given path and options:
:gvl_release_threshold
(Integer
): sets the GVL release threshold (see#gvl_release_threshold=
).:pragma
(Hash
): one or more pragmas to set upon opening the database.:read_only
(true
/false
): opens the database in read-only mode if true.:wal
(true
/false
): sets up the database for WAL journaling mode by settingPRAGMA journal_mode=wal
andPRAGMA synchronous=1
.
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'ext/extralite/database.c', line 182 VALUE Database_initialize(int argc, VALUE *argv, VALUE self) { Database_t *db = self_to_database(self); VALUE path; VALUE opts = Qnil; rb_scan_args(argc, argv, "11", &path, &opts); int flags = db_open_flags_from_opts(opts); int rc = sqlite3_open_v2(StringValueCStr(path), &db->sqlite3_db, flags, NULL); if (rc) { sqlite3_close_v2(db->sqlite3_db); db->sqlite3_db = NULL; rb_raise(cError, "%s", sqlite3_errstr(rc)); } // Enable extended result codes rc = sqlite3_extended_result_codes(db->sqlite3_db, 1); if (rc) { sqlite3_close_v2(db->sqlite3_db); rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db)); } #ifdef HAVE_SQLITE3_ENABLE_LOAD_EXTENSION rc = sqlite3_enable_load_extension(db->sqlite3_db, 1); if (rc) { sqlite3_close_v2(db->sqlite3_db); rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db)); } #endif db->trace_proc = Qnil; db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD; db->progress_handler = global_progress_handler; db->progress_handler.tick_count = 0; db->progress_handler.call_count = 0; if (db->progress_handler.mode != PROGRESS_NONE) { db->gvl_release_threshold = -1; if (db->progress_handler.mode != PROGRESS_ONCE) sqlite3_progress_handler(db->sqlite3_db, db->progress_handler.tick, &Database_progress_handler, db); sqlite3_busy_handler(db->sqlite3_db, &Database_busy_handler, db); } if (!NIL_P(opts)) Database_apply_opts(self, db, opts); return Qnil; } |
Instance Method Details
#backup(*args) {|remaining, total| ... } ⇒ Extralite::Database
Creates a backup of the database to the given destination, which can be either a filename or a database instance. In order to monitor the backup progress you can pass a block that will be called periodically by the backup method with two arguments: the remaining page count, and the total page count, which can be used to display the progress to the user or to collect statistics.
db_src.backup(db_dest) do |remaining, total|
puts "Backing up #{remaining}/#{total}"
end
888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 |
# File 'ext/extralite/database.c', line 888 VALUE Database_backup(int argc, VALUE *argv, VALUE self) { VALUE dst; VALUE src_name; VALUE dst_name; rb_scan_args(argc, argv, "12", &dst, &src_name, &dst_name); if (src_name == Qnil) src_name = rb_str_new_literal("main"); if (dst_name == Qnil) dst_name = rb_str_new_literal("main"); int dst_is_fn = TYPE(dst) == T_STRING; Database_t *src = self_to_open_database(self); sqlite3 *dst_db; if (dst_is_fn) { int rc = sqlite3_open(StringValueCStr(dst), &dst_db); if (rc) { sqlite3_close_v2(dst_db); rb_raise(cError, "%s", sqlite3_errmsg(dst_db)); } } else { Database_t *dst_struct = self_to_open_database(dst); dst_db = dst_struct->sqlite3_db; } // TODO: add possibility to use different src and dest db names (main, tmp, or // attached db's). sqlite3_backup *backup; backup = sqlite3_backup_init(dst_db, StringValueCStr(dst_name), src->sqlite3_db, StringValueCStr(src_name)); if (!backup) { if (dst_is_fn) sqlite3_close_v2(dst_db); rb_raise(cError, "%s", sqlite3_errmsg(dst_db)); } backup_ctx ctx = { dst_db, dst_is_fn, backup, rb_block_given_p(), 0 }; rb_ensure(SAFE(backup_safe_iterate), (VALUE)&ctx, SAFE(backup_cleanup), (VALUE)&ctx); RB_GC_GUARD(src_name); RB_GC_GUARD(dst_name); return self; } |
#batch_execute(sql, params_source) ⇒ Integer Also known as: execute_multi
Executes the given query for each list of parameters in the paramter source. If an enumerable is given, it is iterated and each of its values is used as the parameters for running the query. If a callable is given, it is called repeatedly and each of its return values is used as the parameters, until nil is returned.
Returns the number of changes effected. This method is designed for inserting multiple records or performing other mass operations.
records = [
[1, 2, 3],
[4, 5, 6]
]
db.batch_execute('insert into foo values (?, ?, ?)', records)
source = [
[1, 2, 3],
[4, 5, 6]
]
db.batch_execute('insert into foo values (?, ?, ?)', -> { records.shift })
529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
# File 'ext/extralite/database.c', line 529 VALUE Database_batch_execute(VALUE self, VALUE sql, VALUE parameters) { Database_t *db = self_to_open_database(self); sqlite3_stmt *stmt; if (RSTRING_LEN(sql) == 0) return Qnil; prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql); query_ctx ctx = QUERY_CTX( self, sql, db, stmt, parameters, Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS ); return rb_ensure(SAFE(safe_batch_execute), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx); } |
#batch_query(sql, params_source) ⇒ Array<Hash>, Integer #batch_query(sql, params_source) {|rows| ... } ⇒ Array<Hash>, Integer #batch_query_hash(sql, params_source) ⇒ Array<Hash>, Integer #batch_query_hash(sql, params_source) {|rows| ... } ⇒ Array<Hash>, Integer
Executes the given query for each list of parameters in the given paramter source. If a block is given, it is called with the resulting rows for each invocation of the query, and the total number of changes is returned. Otherwise, an array containing the resulting rows for each invocation is returned.
records = [
[1, 2],
[3, 4]
]
db.batch_query('insert into foo values (?, ?) returning bar, baz', records)
#=> [{ bar: 1, baz: 2 }, { bar: 3, baz: 4}]
*
567 568 569 570 571 572 573 574 575 576 577 578 |
# File 'ext/extralite/database.c', line 567 VALUE Database_batch_query(VALUE self, VALUE sql, VALUE parameters) { Database_t *db = self_to_open_database(self); sqlite3_stmt *stmt; prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql); query_ctx ctx = QUERY_CTX( self, sql, db, stmt, parameters, Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS ); return rb_ensure(SAFE(safe_batch_query), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx); } |
#batch_query_array(sql, params_source) ⇒ Array<Array>, Integer #batch_query_array(sql, params_source) {|rows| ... } ⇒ Array<Array>, Integer
Executes the given query for each list of parameters in the given paramter source. If a block is given, it is called with the resulting rows for each invocation of the query, and the total number of changes is returned. Otherwise, an array containing the resulting rows for each invocation is returned. Rows are represented as arrays.
records = [
[1, 2],
[3, 4]
]
db.batch_query_array('insert into foo values (?, ?) returning bar, baz', records)
#=> [[1, 2], [3, 4]]
*
601 602 603 604 605 606 607 608 609 610 611 612 |
# File 'ext/extralite/database.c', line 601 VALUE Database_batch_query_array(VALUE self, VALUE sql, VALUE parameters) { Database_t *db = self_to_open_database(self); sqlite3_stmt *stmt; prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql); query_ctx ctx = QUERY_CTX( self, sql, db, stmt, parameters, Qnil, QUERY_ARRAY, ROW_MULTI, ALL_ROWS ); return rb_ensure(SAFE(safe_batch_query_array), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx); } |
#batch_query(sql, params_source) ⇒ Array<Hash>, Integer #batch_query(sql, params_source) {|rows| ... } ⇒ Array<Hash>, Integer #batch_query_hash(sql, params_source) ⇒ Array<Hash>, Integer #batch_query_hash(sql, params_source) {|rows| ... } ⇒ Array<Hash>, Integer
Executes the given query for each list of parameters in the given paramter source. If a block is given, it is called with the resulting rows for each invocation of the query, and the total number of changes is returned. Otherwise, an array containing the resulting rows for each invocation is returned.
records = [
[1, 2],
[3, 4]
]
db.batch_query('insert into foo values (?, ?) returning bar, baz', records)
#=> [{ bar: 1, baz: 2 }, { bar: 3, baz: 4}]
*
567 568 569 570 571 572 573 574 575 576 577 578 |
# File 'ext/extralite/database.c', line 567 VALUE Database_batch_query(VALUE self, VALUE sql, VALUE parameters) { Database_t *db = self_to_open_database(self); sqlite3_stmt *stmt; prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql); query_ctx ctx = QUERY_CTX( self, sql, db, stmt, parameters, Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS ); return rb_ensure(SAFE(safe_batch_query), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx); } |
#batch_query_splat(sql, params_source) ⇒ Array<any>, Integer #batch_query_splat(sql, params_source) {|rows| ... } ⇒ Array<any>, Integer
Executes the given query for each list of parameters in the given paramter source. If a block is given, it is called with the resulting rows for each invocation of the query, and the total number of changes is returned. Otherwise, an array containing the resulting rows for each invocation is returned. Rows are single values.
records = [
[1, 2],
[3, 4]
]
db.batch_query_splat('insert into foo values (?, ?) returning baz', records)
#=> [2, 4]
*
635 636 637 638 639 640 641 642 643 644 645 646 |
# File 'ext/extralite/database.c', line 635 VALUE Database_batch_query_splat(VALUE self, VALUE sql, VALUE parameters) { Database_t *db = self_to_open_database(self); sqlite3_stmt *stmt; prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql); query_ctx ctx = QUERY_CTX( self, sql, db, stmt, parameters, Qnil, QUERY_SPLAT, ROW_MULTI, ALL_ROWS ); return rb_ensure(SAFE(safe_batch_query_splat), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx); } |
#busy_timeout=(sec) ⇒ Extralite::Database
Sets the busy timeout for the database, in seconds or fractions thereof. To
disable the busy timeout, set it to 0 or nil. When the busy timeout is set to
a value larger than zero, running a query when the database is locked will
cause the program to wait for the database to become available. If the
database is still locked when the timeout period has elapsed, the query will
fail with a Extralite::BusyError
exception.
Setting the busy timeout allows other threads to run while waiting for the
database to become available. See also #on_progress
.
1027 1028 1029 1030 1031 1032 1033 1034 1035 |
# File 'ext/extralite/database.c', line 1027 VALUE Database_busy_timeout_set(VALUE self, VALUE sec) { Database_t *db = self_to_open_database(self); int ms = (sec == Qnil) ? 0 : (int)(NUM2DBL(sec) * 1000); int rc = sqlite3_busy_timeout(db->sqlite3_db, ms); if (rc != SQLITE_OK) rb_raise(cError, "Failed to set busy timeout"); return self; } |
#changes ⇒ Integer
Returns the number of changes made to the database by the last operation.
670 671 672 673 674 |
# File 'ext/extralite/database.c', line 670 VALUE Database_changes(VALUE self) { Database_t *db = self_to_open_database(self); return INT2FIX(sqlite3_changes(db->sqlite3_db)); } |
#close ⇒ Extralite::Database
Closes the database.
243 244 245 246 247 248 249 250 251 252 253 254 |
# File 'ext/extralite/database.c', line 243 VALUE Database_close(VALUE self) { int rc; Database_t *db = self_to_database(self); rc = sqlite3_close_v2(db->sqlite3_db); if (rc) { rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db)); } db->sqlite3_db = NULL; return self; } |
#closed? ⇒ Boolean
Returns true if the database is closed.
263 264 265 266 |
# File 'ext/extralite/database.c', line 263 VALUE Database_closed_p(VALUE self) { Database_t *db = self_to_database(self); return db->sqlite3_db ? Qfalse : Qtrue; } |
#columns(sql) ⇒ Array<String>
Returns the column names for the given query, without running it.
652 653 654 |
# File 'ext/extralite/database.c', line 652 VALUE Database_columns(VALUE self, VALUE sql) { return Database_perform_query(1, &sql, self, safe_query_columns, QUERY_HASH); } |
#errcode ⇒ Integer
Returns the last error code for the database.
1330 1331 1332 1333 1334 |
# File 'ext/extralite/database.c', line 1330 VALUE Database_errcode(VALUE self) { Database_t *db = self_to_open_database(self); return INT2NUM(sqlite3_errcode(db->sqlite3_db)); } |
#errmsg ⇒ String
Returns the last error message for the database.
1340 1341 1342 1343 1344 |
# File 'ext/extralite/database.c', line 1340 VALUE Database_errmsg(VALUE self) { Database_t *db = self_to_open_database(self); return rb_str_new2(sqlite3_errmsg(db->sqlite3_db)); } |
#error_offset ⇒ Integer
Returns the offset for the last error. This is useful for indicating where in the SQL string an error was encountered.
1352 1353 1354 1355 1356 |
# File 'ext/extralite/database.c', line 1352 VALUE Database_error_offset(VALUE self) { Database_t *db = self_to_open_database(self); return INT2NUM(sqlite3_error_offset(db->sqlite3_db)); } |
#execute(sql, *parameters) ⇒ Integer?
Runs a query returning the total changes effected. This method should be used for data- or schema-manipulation queries.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.execute('update foo set x = ? where y = ?', 42, 43)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.execute('update foo set x = :bar', bar: 42)
497 498 499 |
# File 'ext/extralite/database.c', line 497 VALUE Database_execute(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_changes, QUERY_HASH); } |
#filename ⇒ String #filename(db_name) ⇒ String
Returns the database filename. If db_name is given, returns the filename for the respective attached database.
685 686 687 688 689 690 691 692 693 694 |
# File 'ext/extralite/database.c', line 685 VALUE Database_filename(int argc, VALUE *argv, VALUE self) { const char *db_name; const char *filename; Database_t *db = self_to_open_database(self); rb_check_arity(argc, 0, 1); db_name = (argc == 1) ? StringValueCStr(argv[0]) : "main"; filename = sqlite3_db_filename(db->sqlite3_db, db_name); return filename ? rb_str_new_cstr(filename) : Qnil; } |
#gvl_release_threshold ⇒ Integer
Returns the database's GVL release threshold.
1381 1382 1383 1384 |
# File 'ext/extralite/database.c', line 1381 VALUE Database_gvl_release_threshold_get(VALUE self) { Database_t *db = self_to_open_database(self); return INT2NUM(db->gvl_release_threshold); } |
#gvl_release_threshold=(value) ⇒ Integer
Sets the database's GVL release threshold. The release policy changes according to the given value:
- Less than 0: the GVL is never released while running queries. This is the
policy used when a progress handler is set. For more information see
#on_progress
. - 0: The GVL is released while preparing queries, but held when iterating through records.
- Greater than 0: the GVL is released while preparing queries, and released periodically while iterating through records, according to the given period. A value of 1 will release the GVL on every iterated record. A value of 100 will release the GVL once for every 100 records.
A value of nil sets the threshold to the default value, which is currently 1000.
1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 |
# File 'ext/extralite/database.c', line 1405 VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) { Database_t *db = self_to_open_database(self); switch (TYPE(value)) { case T_FIXNUM: { int value_int = NUM2INT(value); if (value_int < -1) rb_raise(eArgumentError, "Invalid GVL release threshold value (expect integer >= -1)"); if (value_int > -1 && db->progress_handler.mode != PROGRESS_NONE) Database_reset_progress_handler(self, db); db->gvl_release_threshold = value_int; break; } case T_NIL: db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD; break; default: rb_raise(eArgumentError, "Invalid GVL release threshold value (expect integer or nil)"); } return INT2NUM(db->gvl_release_threshold); } |
#inspect ⇒ String
Returns a short string representation of the database instance, including the database filename.
1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 |
# File 'ext/extralite/database.c', line 1364 VALUE Database_inspect(VALUE self) { Database_t *db = self_to_database(self); VALUE cname = rb_class_name(CLASS_OF(self)); if (!(db)->sqlite3_db) return rb_sprintf("#<%"PRIsVALUE":%p (closed)>", cname, (void*)self); else { VALUE filename = Database_filename(0, NULL, self); if (RSTRING_LEN(filename) == 0) filename = rb_str_new_literal(":memory:"); return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, filename); } } |
#interrupt ⇒ Extralite::Database
Interrupts a long running query. This method is to be called from a different
thread than the one running the query. Upon calling #interrupt
the running
query will stop and raise an Extralite::InterruptError
exception.
It is not safe to call #interrupt
on a database that is about to be closed.
For more information, consult the sqlite3 API
docs.
798 799 800 801 802 803 |
# File 'ext/extralite/database.c', line 798 VALUE Database_interrupt(VALUE self) { Database_t *db = self_to_open_database(self); sqlite3_interrupt(db->sqlite3_db); return self; } |
#last_insert_rowid ⇒ Integer
Returns the rowid of the last inserted row.
660 661 662 663 664 |
# File 'ext/extralite/database.c', line 660 VALUE Database_last_insert_rowid(VALUE self) { Database_t *db = self_to_open_database(self); return INT2FIX(sqlite3_last_insert_rowid(db->sqlite3_db)); } |
#limit(category) ⇒ Integer #limit(category, new_value) ⇒ Integer
Returns the current limit for the given category. If a new value is given, sets the limit to the new value and returns the previous value.
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 |
# File 'ext/extralite/database.c', line 1000 VALUE Database_limit(int argc, VALUE *argv, VALUE self) { VALUE category, new_value; rb_scan_args(argc, argv, "11", &category, &new_value); Database_t *db = self_to_open_database(self); int value = sqlite3_limit(db->sqlite3_db, NUM2INT(category), RTEST(new_value) ? NUM2INT(new_value) : -1); if (value == -1) rb_raise(cError, "Invalid limit category"); return INT2NUM(value); } |
#load_extension(path) ⇒ Extralite::Database
Loads an extension with the given path.
712 713 714 715 716 717 718 719 720 721 722 723 724 |
# File 'ext/extralite/database.c', line 712 VALUE Database_load_extension(VALUE self, VALUE path) { Database_t *db = self_to_open_database(self); char *err_msg; int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg); if (rc != SQLITE_OK) { VALUE error = rb_exc_new2(cError, err_msg); sqlite3_free(err_msg); rb_exc_raise(error); } return self; } |
#on_progress(*args) ⇒ Extralite::Database
Installs or removes a progress handler that will be executed periodically while a query is running. This method can be used to support switching between fibers and threads or implementing timeouts for running queries.
The period
parameter specifies the approximate number of SQLite
virtual machine instructions that are evaluated between successive
invocations of the progress handler. A period of less than 1 removes the
progress handler. The default period value is 1000.
The optional tick
parameter specifies the granularity of how often the
progress handler is called. The default tick value is 10, which means that
Extralite's underlying progress callback will be called every 10 SQLite VM
instructions. The given progress proc, however, will be only called every
period
(cumulative) VM instructions. This allows the progress handler to
work correctly also when running simple queries that don't include many
VM instructions. If the tick
value is greater than the period value it is
automatically capped to the period value.
The mode
parameter controls the progress handler mode, which is one of the
following:
:normal
(default): the progress handler proc is invoked on query progress.:once
: the progress handler proc is invoked only once, when preparing the query.:at_least_once
: the progress handler proc is invoked when prearing the query, and on query progress.
The progress handler is called also when the database is busy. This lets the
application perform work while waiting for the database to become unlocked,
or implement a timeout. Note that setting the database's busy_timeout after
setting a progress handler may lead to undefined behaviour in a concurrent
application. When busy, the progress handler proc is passed true
as the
first argument.
When the progress handler is set, the gvl release threshold value is set to -1, which means that the GVL will not be released at all when preparing or running queries. It is the application's responsibility to let other threads or fibers run by calling e.g. Thread.pass:
db.on_progress do
do_something_interesting
Thread.pass # let other threads run
end
Note that the progress handler is set globally for the database and that Extralite does provide any hooks for telling which queries are currently running or at what time they were started. This means that you'll need to wrap the stock #query_xxx and #execute methods with your own code that calculates timeouts, for example:
def setup_progress_handler
@db.on_progress do
raise TimeoutError if Time.now - @t0 >= @timeout
Thread.pass
end
end
def query(sql, *)
@t0 = Time.now
@db.query(sql, *)
end
If the gvl release threshold is set to a value equal to or larger than 0 after setting the progress handler, the progress handler will be reset.
1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 |
# File 'ext/extralite/database.c', line 1225 VALUE Database_on_progress(int argc, VALUE *argv, VALUE self) { Database_t *db = self_to_open_database(self); VALUE opts; struct progress_handler prog; rb_scan_args(argc, argv, "00:", &opts); prog = parse_progress_handler_opts(opts); if (prog.mode == PROGRESS_NONE) { Database_reset_progress_handler(self, db); db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD; return self; } db->gvl_release_threshold = -1; db->progress_handler.mode = prog.mode; RB_OBJ_WRITE(self, &db->progress_handler.proc, prog.proc); db->progress_handler.period = prog.period; db->progress_handler.tick = prog.tick; db->progress_handler.tick_count = 0; db->progress_handler.call_count = 0; // The PROGRESS_ONCE mode works by invoking the progress handler proc exactly // once, before over the result set, so in that mode we don't // actually need to set the progress handler at the sqlite level. if (prog.mode != PROGRESS_ONCE) sqlite3_progress_handler(db->sqlite3_db, prog.tick, &Database_progress_handler, db); if (prog.mode != PROGRESS_NONE) sqlite3_busy_handler(db->sqlite3_db, &Database_busy_handler, db); return self; } |
#pragma(value) ⇒ Hash
Gets or sets one or more database pragmas. For a list of available pragmas see: https://sqlite.org/pragma.html#toc
db.pragma(:cache_size) # get
db.pragma(cache_size: -2000) # set
214 215 216 |
# File 'lib/extralite.rb', line 214 def pragma(value) value.is_a?(Hash) ? pragma_set(value) : pragma_get(value) end |
#prepare(sql) ⇒ Extralite::Query #prepare(sql, *params) ⇒ Extralite::Query #prepare(sql, *params) { ... } ⇒ Extralite::Query
Creates a prepared query with the given SQL query in hash mode. If query parameters are given, they are bound to the query. If a block is given, it is used as a transform proc.
750 751 752 |
# File 'ext/extralite/database.c', line 750 VALUE Database_prepare_hash(int argc, VALUE *argv, VALUE self) { return Database_prepare(argc, argv, self, SYM_hash); } |
#prepare_array(sql) ⇒ Extralite::Query #prepare_array(sql, *params) ⇒ Extralite::Query #prepare_array(sql, *params) { ... } ⇒ Extralite::Query
Creates a prepared query with the given SQL query in array mode. If query parameters are given, they are bound to the query. If a block is given, it is used as a transform proc.
784 785 786 |
# File 'ext/extralite/database.c', line 784 VALUE Database_prepare_array(int argc, VALUE *argv, VALUE self) { return Database_prepare(argc, argv, self, SYM_array); } |
#prepare(sql) ⇒ Extralite::Query #prepare(sql, *params) ⇒ Extralite::Query #prepare(sql, *params) { ... } ⇒ Extralite::Query
Creates a prepared query with the given SQL query in hash mode. If query parameters are given, they are bound to the query. If a block is given, it is used as a transform proc.
750 751 752 |
# File 'ext/extralite/database.c', line 750 VALUE Database_prepare_hash(int argc, VALUE *argv, VALUE self) { return Database_prepare(argc, argv, self, SYM_hash); } |
#prepare_splat(sql) ⇒ Extralite::Query #prepare_splat(sql, *params) ⇒ Extralite::Query #prepare_splat(sql, *params) { ... } ⇒ Extralite::Query
Creates a prepared query with the given SQL query in argv mode. If query parameters are given, they are bound to the query. If a block is given, it is used as a transform proc.
767 768 769 |
# File 'ext/extralite/database.c', line 767 VALUE Database_prepare_splat(int argc, VALUE *argv, VALUE self) { return Database_prepare(argc, argv, self, SYM_splat); } |
#query(sql, ...) ⇒ Array<Hash>, Integer #query(transform, sql, ...) ⇒ Array<Hash>, Integer #query(sql, *parameters, &block) ⇒ Array #query_hash(sql, *parameters, &block) ⇒ Array
Runs a query returning rows as hashes (with symbol keys). If a block is given, it will be called for each row. Otherwise, an array containing all rows is returned.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query('select * from foo where x = :bar', bar: 42)
340 341 342 |
# File 'ext/extralite/database.c', line 340 VALUE Database_query(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_hash, QUERY_HASH); } |
#query_array(sql, ...) ⇒ Array<Array>, Integer #query_array(transform, sql, ...) ⇒ Array<Array>, Integer
Runs a query returning rows as arrays. If a block is given, it will be called for each row. Otherwise, an array containing all rows is returned.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query_array('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using a hash, where keys are either strings are symbols. String
keys can include or omit the :
prefix. The following are equivalent:
db.query_array('select * from foo where x = :bar', bar: 42)
db.query_array('select * from foo where x = :bar', 'bar' => 42)
db.query_array('select * from foo where x = :bar', ':bar' => 42)
393 394 395 |
# File 'ext/extralite/database.c', line 393 VALUE Database_query_array(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_array, QUERY_ARRAY); } |
#query(sql, ...) ⇒ Array<Hash>, Integer #query(transform, sql, ...) ⇒ Array<Hash>, Integer #query(sql, *parameters, &block) ⇒ Array #query_hash(sql, *parameters, &block) ⇒ Array
Runs a query returning rows as hashes (with symbol keys). If a block is given, it will be called for each row. Otherwise, an array containing all rows is returned.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query('select * from foo where x = :bar', bar: 42)
340 341 342 |
# File 'ext/extralite/database.c', line 340 VALUE Database_query(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_hash, QUERY_HASH); } |
#query_single(sql, ...) ⇒ Array, any #query_single(transform, sql, ...) ⇒ Array, any
Runs a query returning a single row as a hash.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query_single('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query_single('select * from foo where x = :bar', bar: 42)
419 420 421 |
# File 'ext/extralite/database.c', line 419 VALUE Database_query_single(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_single_row_hash, QUERY_HASH); } |
#query_single_array(sql, ...) ⇒ Array, any #query_single_array(transform, sql, ...) ⇒ Array, any
Runs a query returning a single row as an array.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query_single_array('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query_single_array('select * from foo where x = :bar', bar: 42)
471 472 473 |
# File 'ext/extralite/database.c', line 471 VALUE Database_query_single_array(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_single_row_array, QUERY_ARRAY); } |
#query_single(sql, ...) ⇒ Array, any #query_single(transform, sql, ...) ⇒ Array, any
Runs a query returning a single row as a hash.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query_single('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query_single('select * from foo where x = :bar', bar: 42)
419 420 421 |
# File 'ext/extralite/database.c', line 419 VALUE Database_query_single(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_single_row_hash, QUERY_HASH); } |
#query_single_splat(sql, ...) ⇒ Array, any #query_single_splat(transform, sql, ...) ⇒ Array, any
Runs a query returning a single row as an array or a single value.
Query parameters to be bound to placeholders in the query can be specified as
a list of values or as a hash mapping parameter names to values. When
parameters are given as an array, the query should specify parameters using
?
:
db.query_single_splat('select * from foo where x = ?', 42)
Named placeholders are specified using :
. The placeholder values are
specified using keyword arguments:
db.query_single_splat('select * from foo where x = :bar', bar: 42)
445 446 447 |
# File 'ext/extralite/database.c', line 445 VALUE Database_query_single_splat(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_single_row_splat, QUERY_SPLAT); } |
#query_splat(sql, ...) ⇒ Array<Array, any>, Integer #query_splat(transform, sql, ...) ⇒ Array<Array, any>, Integer
Runs a query and transforms rows through the given transform poc. Each row is provided to the transform proc as a list of values. If a block is given, it will be called for each row. Otherwise, an array containing all rows is returned.
If a transform block is given, it is called for each row, with the row values splatted:
transform = ->(a, b, c) { a * 100 + b * 10 + c }
db.query_splat(transform, 'select a, b, c from foo where c = ?', 42)
363 364 365 |
# File 'ext/extralite/database.c', line 363 VALUE Database_query_splat(int argc, VALUE *argv, VALUE self) { return Database_perform_query(argc, argv, self, safe_query_splat, QUERY_SPLAT); } |
#read_only? ⇒ boolean
Returns true if the database was open for read only access.
233 234 235 236 237 |
# File 'ext/extralite/database.c', line 233 VALUE Database_read_only_p(VALUE self) { Database_t *db = self_to_database(self); int open = sqlite3_db_readonly(db->sqlite3_db, "main"); return (open == 1) ? Qtrue : Qfalse; } |
#release(name) ⇒ Extralite::Database
Release a savepoint with the given name. For more information on savepoints see: https://sqlite.org/lang_savepoint.html
268 269 270 271 |
# File 'lib/extralite.rb', line 268 def release(name) execute "release #{name}" self end |
#rollback! ⇒ Extralite::Database
Rolls back the currently active transaction. This method should only be
called from within a block passed to Database#transaction
. This method
raises a Extralite::Rollback exception, which will stop execution of the
transaction block without propagating the exception.
db.transaction do
db.execute('insert into foo (42)')
db.rollback!
end
295 296 297 |
# File 'lib/extralite.rb', line 295 def rollback! raise Rollback end |
#rollback_to(name) ⇒ Extralite::Database
Rolls back changes to a savepoint with the given name. For more information on savepoints see: https://sqlite.org/lang_savepoint.html
278 279 280 281 |
# File 'lib/extralite.rb', line 278 def rollback_to(name) execute "rollback to #{name}" self end |
#savepoint(name) ⇒ Extralite::Database
Creates a savepoint with the given name. For more information on savepoints see: https://sqlite.org/lang_savepoint.html
db.savepoint(:savepoint1)
db.execute('insert into foo values (42)')
db.rollback_to(:savepoint1)
db.release(:savepoint1)
258 259 260 261 |
# File 'lib/extralite.rb', line 258 def savepoint(name) execute "savepoint #{name}" self end |
#status(op) ⇒ Array<Integer> #status(op, reset) ⇒ Array<Integer>
Returns database status values for the given op as an array containing the current value and the high water mark value. To reset the high water mark, pass true as reset.
975 976 977 978 979 980 981 982 983 984 985 986 987 |
# File 'ext/extralite/database.c', line 975 VALUE Database_status(int argc, VALUE *argv, VALUE self) { VALUE op, reset; int cur, hwm; rb_scan_args(argc, argv, "11", &op, &reset); Database_t *db = self_to_open_database(self); int rc = sqlite3_db_status(db->sqlite3_db, NUM2INT(op), &cur, &hwm, RTEST(reset) ? 1 : 0); if (rc != SQLITE_OK) rb_raise(cError, "%s", sqlite3_errstr(rc)); return rb_ary_new3(2, INT2NUM(cur), INT2NUM(hwm)); } |
#tables(db = 'main') ⇒ Array
Returns the list of currently defined tables. If a database name is given, returns the list of tables for the relevant attached database.
202 203 204 |
# File 'lib/extralite.rb', line 202 def tables(db = 'main') query_splat(format(TABLES_SQL, db: db)) end |
#total_changes ⇒ Integer
Returns the total number of changes made to the database since opening it.
1041 1042 1043 1044 1045 1046 |
# File 'ext/extralite/database.c', line 1041 VALUE Database_total_changes(VALUE self) { Database_t *db = self_to_open_database(self); int value = sqlite3_total_changes(db->sqlite3_db); return INT2NUM(value); } |
#trace ⇒ Extralite::Database
Installs or removes a block that will be invoked for every SQL statement
executed. To stop tracing, call #trace
without a block.
1053 1054 1055 1056 1057 1058 |
# File 'ext/extralite/database.c', line 1053 VALUE Database_trace(VALUE self) { Database_t *db = self_to_open_database(self); RB_OBJ_WRITE(self, &db->trace_proc, rb_block_given_p() ? rb_block_proc() : Qnil); return self; } |
#track_changes(*tables) { ... } ⇒ Extralite::Changeset
Tracks changes to the database and returns a changeset. The changeset can then be used to store the changes to a file, apply them to another database, or undo the changes. The given table names specify which tables should be tracked for changes. Passing a value of nil causes all tables to be tracked.
changeset = db.track_changes(:foo, :bar) do
perform_a_bunch_of_queries
end
File.open('my.changes', 'w+') { |f| f << changeset.to_blob }
1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 |
# File 'ext/extralite/database.c', line 1078 VALUE Database_track_changes(int argc, VALUE *argv, VALUE self) { self_to_open_database(self); VALUE changeset = rb_funcall(cChangeset, ID_new, 0); VALUE tables = rb_ary_new_from_values(argc, argv); rb_funcall(changeset, ID_track, 2, self, tables); RB_GC_GUARD(changeset); RB_GC_GUARD(tables); return changeset; } |
#transaction(mode = :immediate) ⇒ Any
Starts a transaction and runs the given block. If an exception is raised in the block, the transaction is rolled back. Otherwise, the transaction is commited after running the block.
db.transaction do
db.execute('insert into foo values (1, 2, 3)')
raise if db.query_single_value('select x from bar') > 42
end
For more information on transactions see: https://sqlite.org/lang_transaction.html
237 238 239 240 241 242 243 244 245 246 |
# File 'lib/extralite.rb', line 237 def transaction(mode = :immediate) abort = false execute "begin #{mode} transaction" yield self rescue => e abort = true e.is_a?(Rollback) ? nil : raise ensure execute(abort ? 'rollback' : 'commit') end |
#transaction_active? ⇒ bool
Returns true if a transaction is currently in progress.
700 701 702 703 704 |
# File 'ext/extralite/database.c', line 700 VALUE Database_transaction_active_p(VALUE self) { Database_t *db = self_to_open_database(self); return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue; } |
#wal_checkpoint(mode) ⇒ Array<int> #wal_checkpoint(mode, db_name) ⇒ Array<int>
Runs a WAL checkpoint operation with the given mode. If a database name is given, the checkpoint operation is ran on the corresponding attached database, otherwise it is run on the main database. Returns an array containing the total number of frames in the WAL file, and the number of frames checkpointed. For more information see: https://sqlite.org/c3ref/wal_checkpoint_v2.html
1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 |
# File 'ext/extralite/database.c', line 1454 VALUE Database_wal_checkpoint(int argc, VALUE *argv, VALUE self) { Database_t *db = self_to_open_database(self); VALUE mode = Qnil; VALUE db_name = Qnil; int total_frames; int checkpointed_frames; rb_scan_args(argc, argv, "11", &mode, &db_name); int mode_int = checkpoint_mode_symbol_to_int(mode); int rc = sqlite3_wal_checkpoint_v2( db->sqlite3_db, NIL_P(db_name) ? NULL : StringValueCStr(db_name), mode_int, &total_frames, &checkpointed_frames ); if (rc != SQLITE_OK) rb_raise(cError, "Failed to perform WAL checkpoint: %s", sqlite3_errstr(rc)); return rb_ary_new3(2, INT2NUM(total_frames), INT2NUM(checkpointed_frames)); } |