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
886 887 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 |
# File 'ext/extralite/database.c', line 886
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 })
527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'ext/extralite/database.c', line 527
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}]
*
565 566 567 568 569 570 571 572 573 574 575 576 |
# File 'ext/extralite/database.c', line 565
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]]
*
599 600 601 602 603 604 605 606 607 608 609 610 |
# File 'ext/extralite/database.c', line 599
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}]
*
565 566 567 568 569 570 571 572 573 574 575 576 |
# File 'ext/extralite/database.c', line 565
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]
*
633 634 635 636 637 638 639 640 641 642 643 644 |
# File 'ext/extralite/database.c', line 633
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
.
1025 1026 1027 1028 1029 1030 1031 1032 1033 |
# File 'ext/extralite/database.c', line 1025
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.
668 669 670 671 672 |
# File 'ext/extralite/database.c', line 668
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.
650 651 652 |
# File 'ext/extralite/database.c', line 650
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.
1324 1325 1326 1327 1328 |
# File 'ext/extralite/database.c', line 1324
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.
1334 1335 1336 1337 1338 |
# File 'ext/extralite/database.c', line 1334
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.
1346 1347 1348 1349 1350 |
# File 'ext/extralite/database.c', line 1346
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)
495 496 497 |
# File 'ext/extralite/database.c', line 495
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.
683 684 685 686 687 688 689 690 691 692 |
# File 'ext/extralite/database.c', line 683
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.
1375 1376 1377 1378 |
# File 'ext/extralite/database.c', line 1375
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.
1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 |
# File 'ext/extralite/database.c', line 1399
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.
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 |
# File 'ext/extralite/database.c', line 1358
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.
796 797 798 799 800 801 |
# File 'ext/extralite/database.c', line 796
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.
658 659 660 661 662 |
# File 'ext/extralite/database.c', line 658
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.
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 |
# File 'ext/extralite/database.c', line 998
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.
710 711 712 713 714 715 716 717 718 719 720 721 722 |
# File 'ext/extralite/database.c', line 710
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.
1219 1220 1221 1222 1223 1224 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 |
# File 'ext/extralite/database.c', line 1219
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 iterating 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.
748 749 750 |
# File 'ext/extralite/database.c', line 748
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.
782 783 784 |
# File 'ext/extralite/database.c', line 782
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.
748 749 750 |
# File 'ext/extralite/database.c', line 748
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.
765 766 767 |
# File 'ext/extralite/database.c', line 765
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)
338 339 340 |
# File 'ext/extralite/database.c', line 338
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)
391 392 393 |
# File 'ext/extralite/database.c', line 391
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)
338 339 340 |
# File 'ext/extralite/database.c', line 338
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)
417 418 419 |
# File 'ext/extralite/database.c', line 417
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)
469 470 471 |
# File 'ext/extralite/database.c', line 469
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)
417 418 419 |
# File 'ext/extralite/database.c', line 417
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)
443 444 445 |
# File 'ext/extralite/database.c', line 443
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)
361 362 363 |
# File 'ext/extralite/database.c', line 361
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.
973 974 975 976 977 978 979 980 981 982 983 984 985 |
# File 'ext/extralite/database.c', line 973
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.
1039 1040 1041 1042 1043 1044 |
# File 'ext/extralite/database.c', line 1039
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.
1051 1052 1053 1054 1055 1056 |
# File 'ext/extralite/database.c', line 1051
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 }
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 |
# File 'ext/extralite/database.c', line 1076
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.
698 699 700 701 702 |
# File 'ext/extralite/database.c', line 698
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
1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 |
# File 'ext/extralite/database.c', line 1448
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));
}
|