class Amalgalite::SQLite3::Database
The ruby extension wrapper around the core sqlite3 database object.
Public Class Methods
Create a new SQLite2 database with a UTF-8 encoding.
VALUE am_sqlite3_database_open(int argc, VALUE *argv, VALUE class) { VALUE self = am_sqlite3_database_alloc(class); VALUE rFlags; VALUE rFilename; int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE; char* filename; int rc; am_sqlite3* am_db; /* at least a filename argument is required */ rb_scan_args( argc, argv, "11", &rFilename, &rFlags ); /* convert flags to the sqlite version */ flags = ( Qnil == rFlags ) ? flags : FIX2INT(rFlags); filename = StringValuePtr(rFilename); /* extract the sqlite3 wrapper struct */ Data_Get_Struct(self, am_sqlite3, am_db); /* open the sqlite3 database */ rc = sqlite3_open_v2( filename, &(am_db->db), flags, 0); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure to open database %s : [SQLITE_ERROR %d] : %s\n", filename, rc, sqlite3_errmsg(am_db->db)); } /* by default turn on the extended result codes */ rc = sqlite3_extended_result_codes( am_db->db, 1); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure to set extended result codes %s : [SQLITE_ERROR %d] : %s\n", filename, rc, sqlite3_errmsg(am_db->db)); } return self; }
Create a new SQLite3 database with a UTF-16 encoding
VALUE am_sqlite3_database_open16(VALUE class, VALUE rFilename) { VALUE self = am_sqlite3_database_alloc(class); char* filename = StringValuePtr(rFilename); am_sqlite3* am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_open16( filename, &(am_db->db) ); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure to open UTF-16 database %s : [SQLITE_ERROR %d] : %s\n", filename, rc, sqlite3_errmsg( am_db->db )); } /* by default turn on the extended result codes */ rc = sqlite3_extended_result_codes( am_db->db, 1); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure to set extended result codes on UTF-16 database %s : [SQLITE_ERROR %d] : %s\n", filename, rc, (char*)sqlite3_errmsg16(am_db->db)); } return self; }
Public Instance Methods
return true if the database is in autocommit mode, otherwise return false
VALUE am_sqlite3_database_is_autocommit(VALUE self) { am_sqlite3 *am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_get_autocommit( am_db->db ); return ( 0 == rc ) ? Qfalse : Qtrue ; }
register a busy handler. If the argument is nil, then an existing busy handler is removed. Otherwise the argument is registered as the busy handler.
VALUE am_sqlite3_database_busy_handler( VALUE self, VALUE handler ) { am_sqlite3 *am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); /* Removing a busy handler case, remove it from sqlite and then remove it * from the garbage collector if it existed */ if ( Qnil == handler ) { rc = sqlite3_busy_handler( am_db->db, NULL, NULL ); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure removing busy handler : [SQLITE_ERROR %d] : %s\n", rc, sqlite3_errmsg( am_db->db )); } if ( Qnil != am_db->busy_handler_obj ) { rb_gc_unregister_address( &(am_db->busy_handler_obj) ); } } else { /* installing a busy handler * - register it with sqlite * - keep a reference for ourselves with our database handle * - registere the handler reference with the garbage collector */ rc = sqlite3_busy_handler( am_db->db, amalgalite_xBusy, (void*)handler ); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure setting busy handler : [SQLITE_ERROR %d] : %s\n", rc, sqlite3_errmsg( am_db->db )); } am_db->busy_handler_obj = handler; rb_gc_register_address( &(am_db->busy_handler_obj) ); } return Qnil; }
Close the database
VALUE am_sqlite3_database_close(VALUE self) { am_sqlite3 *am_db; int rc = 0; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_close( am_db->db ); am_db->db = NULL; if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure to close database : [SQLITE_ERROR %d] : %s\n", rc, sqlite3_errmsg( am_db->db )); } return self; }
register the given klass to be invoked as an sql aggregate.
VALUE am_sqlite3_database_define_aggregate( VALUE self, VALUE name, VALUE arity, VALUE klass ) { am_sqlite3 *am_db; int rc; char* zFunctionName = RSTRING_PTR(name); int nArg = FIX2INT( arity ); Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_create_function( am_db->db, zFunctionName, nArg, SQLITE_UTF8, (void *)klass, NULL, /* for scalar functions, not used here */ amalgalite_xStep, amalgalite_xFinal); if ( SQLITE_OK != rc ) { /* in the case of SQLITE_MISUSE the error message in the database may * not be set. In this case, hardcode the error. * http://sqlite.org/c3ref/errcode.html * * This is a result of 3.6.15 which has sqlite3_create_function return * SQLITE_MISUSE intead of SQLITE_ERROR if called with incorrect * parameters. */ if ( SQLITE_MISUSE == rc ) { rb_raise(eAS_Error, "Failure defining SQL function '%s' with arity '%d' : [SQLITE_ERROR %d] : Library used incorrectly\n", zFunctionName, nArg, rc); } else { rb_raise(eAS_Error, "Failure defining SQL function '%s' with arity '%d' : [SQLITE_ERROR %d] : %s\n", zFunctionName, nArg, rc, sqlite3_errmsg( am_db->db )); } } rb_gc_register_address( &klass ); return Qnil; }
register the given function to be invoked as an sql function.
VALUE am_sqlite3_database_define_function( VALUE self, VALUE name, VALUE proc_like ) { am_sqlite3 *am_db; int rc; VALUE arity = rb_funcall( proc_like, rb_intern( "arity" ), 0 ); char* zFunctionName = RSTRING_PTR(name); int nArg = FIX2INT( arity ); Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_create_function( am_db->db, zFunctionName, nArg, SQLITE_UTF8, (void *)proc_like, amalgalite_xFunc, NULL, NULL); if ( SQLITE_OK != rc ) { /* in the case of SQLITE_MISUSE the error message in the database may * not be set. In this case, hardcode the error. * http://sqlite.org/c3ref/errcode.html * * This is a result of 3.6.15 which has sqlite3_create_function return * SQLITE_MISUSE intead of SQLITE_ERROR if called with incorrect * parameters. */ if ( SQLITE_MISUSE == rc ) { rb_raise(eAS_Error, "Failure defining SQL function '%s' with arity '%d' : [SQLITE_ERROR %d] : Library used incorrectly\n", zFunctionName, nArg, rc); } else { rb_raise(eAS_Error, "Failure defining SQL function '%s' with arity '%d' : [SQLITE_ERROR %d] : %s\n", zFunctionName, nArg, rc, sqlite3_errmsg( am_db->db )); } } rb_gc_register_address( &proc_like ); return Qnil; }
call-seqL
database.execute_batch( sqls ) -> Boolean
Execute the statements in a batch.
VALUE am_sqlite3_database_exec(VALUE self, VALUE rSQL) { VALUE sql = StringValue( rSQL ); am_sqlite3 *am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_exec( am_db->db, RSTRING_PTR(sql), NULL, NULL, NULL ); if ( SQLITE_OK != rc ){ rb_raise( eAS_Error, "Failed to execute bulk statements: [SQLITE_ERROR %d] : %s\n", rc, sqlite3_errmsg(am_db->db)); } /* Presume that nobody will want to batch execute more than a Fixnum's worth of statements */ return Qtrue; }
Cause another thread with a handle on this database to be interrupted and return at the earliest opportunity as interrupted.
VALUE am_sqlite3_database_interrupt_bang( VALUE self ) { am_sqlite3 *am_db; Data_Get_Struct(self, am_sqlite3, am_db); sqlite3_interrupt( am_db->db ); return Qnil; }
return the last error code that happened in the database
VALUE am_sqlite3_database_last_error_code(VALUE self) { am_sqlite3 *am_db; int code; Data_Get_Struct(self, am_sqlite3, am_db); code = sqlite3_errcode( am_db->db ); return INT2FIX( code ); }
return the last error message that happened in the database
VALUE am_sqlite3_database_last_error_message(VALUE self) { am_sqlite3 *am_db; const char *message; Data_Get_Struct(self, am_sqlite3, am_db); message = sqlite3_errmsg( am_db->db ); return rb_str_new2( message ); }
Return the rowid of the last row inserted into the database from this database connection.
VALUE am_sqlite3_database_last_insert_rowid(VALUE self) { am_sqlite3 *am_db; sqlite3_int64 last_id; Data_Get_Struct(self, am_sqlite3, am_db); last_id = sqlite3_last_insert_rowid( am_db->db ); return SQLINT64_2NUM( last_id ); }
Create a new SQLite3 statement.
VALUE am_sqlite3_database_prepare(VALUE self, VALUE rSQL) { VALUE sql = StringValue( rSQL ); VALUE stmt = am_sqlite3_statement_alloc(cAS_Statement); am_sqlite3 *am_db; am_sqlite3_stmt *am_stmt; const char *tail; int rc; Data_Get_Struct(self, am_sqlite3, am_db); Data_Get_Struct(stmt, am_sqlite3_stmt, am_stmt); rc = sqlite3_prepare_v2( am_db->db, RSTRING_PTR(sql), (int)RSTRING_LEN(sql), &(am_stmt->stmt), &tail); if ( SQLITE_OK != rc) { rb_raise(eAS_Error, "Failure to prepare statement %s : [SQLITE_ERROR %d] : %s\n", RSTRING_PTR(sql), rc, sqlite3_errmsg(am_db->db)); am_sqlite3_statement_free( am_stmt ); } if ( tail != NULL ) { am_stmt->remaining_sql = rb_str_new2( tail ); rb_gc_register_address( &(am_stmt->remaining_sql) ); } else { am_stmt->remaining_sql = Qnil; } return stmt; }
register a progress handler. If the argument is nil, then an existing progress handler is removed. Otherwise the argument is registered as the progress handler.
VALUE am_sqlite3_database_progress_handler( VALUE self, VALUE op_count, VALUE handler ) { am_sqlite3 *am_db; Data_Get_Struct(self, am_sqlite3, am_db); /* Removing a progress handler, remove it from sqlite and then remove it * from the garbage collector if it existed */ if ( Qnil == handler ) { sqlite3_progress_handler( am_db->db, -1, NULL, (void*)NULL ); if ( Qnil != am_db->progress_handler_obj ) { rb_gc_unregister_address( &(am_db->progress_handler_obj) ); } } else { int op_codes = FIX2INT( op_count ); /* installing a progress handler * - register it with sqlite * - keep a reference for ourselves with our database handle * - register the handler reference with the garbage collector */ sqlite3_progress_handler( am_db->db, op_codes, amalgalite_xProgress, (void*)handler ); am_db->progress_handler_obj = handler; rb_gc_register_address( &(am_db->progress_handler_obj) ); } return Qnil; }
This registers an object to be called with every profile event in SQLite.
This is an experimental api and is subject to change or removal.
VALUE am_sqlite3_database_register_profile_tap(VALUE self, VALUE tap) { am_sqlite3 *am_db; Data_Get_Struct(self, am_sqlite3, am_db); /* Qnil, unregister the item and tell the garbage collector we are done with * it. */ if ( tap == Qnil ) { sqlite3_profile( am_db->db, NULL, NULL ); rb_gc_unregister_address( &(am_db->profile_obj) ); am_db->profile_obj = Qnil; /* register the item and store the reference to the object in the am_db * structure. We also have to tell the Ruby garbage collector that we * point to the Ruby object from C. */ } else { am_db->profile_obj = tap; rb_gc_register_address( &(am_db->profile_obj) ); sqlite3_profile( am_db->db, amalgalite_xProfile, (void *)am_db->profile_obj ); } return Qnil; }
This registers an object to be called with every trace event in SQLite.
This is an experimental api and is subject to change, or removal.
VALUE am_sqlite3_database_register_trace_tap(VALUE self, VALUE tap) { am_sqlite3 *am_db; Data_Get_Struct(self, am_sqlite3, am_db); /* Qnil, unregister the item and tell the garbage collector we are done with * it. */ if ( Qnil == tap ) { sqlite3_trace( am_db->db, NULL, NULL ); rb_gc_unregister_address( &(am_db->trace_obj) ); am_db->trace_obj = Qnil; /* register the item and store the reference to the object in the am_db * structure. We also have to tell the Ruby garbage collector that we * point to the Ruby object from C. */ } else { am_db->trace_obj = tap; rb_gc_register_address( &(am_db->trace_obj) ); sqlite3_trace( am_db->db, amalgalite_xTrace, (void *)am_db->trace_obj ); } return Qnil; }
remove the given klass from availability in SQL as an aggregate.
VALUE am_sqlite3_database_remove_aggregate( VALUE self, VALUE name, VALUE arity, VALUE klass ) { am_sqlite3 *am_db; int rc; char* zFunctionName = RSTRING_PTR(name); int nArg = FIX2INT( arity ); Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_create_function( am_db->db, zFunctionName, nArg, SQLITE_UTF8, NULL, NULL, NULL, NULL); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure removing SQL aggregate '%s' with arity '%d' : [SQLITE_ERROR %d] : %s\n", zFunctionName, nArg, rc, sqlite3_errmsg( am_db->db )); } rb_gc_unregister_address( &klass ); return Qnil; }
remove the given function from availability in SQL.
VALUE am_sqlite3_database_remove_function( VALUE self, VALUE name, VALUE proc_like ) { am_sqlite3 *am_db; int rc; VALUE arity = rb_funcall( proc_like, rb_intern( "arity" ), 0 ); char* zFunctionName = RSTRING_PTR(name); int nArg = FIX2INT( arity ); Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_create_function( am_db->db, zFunctionName, nArg, SQLITE_UTF8, NULL, NULL, NULL, NULL); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure removing SQL function '%s' with arity '%d' : [SQLITE_ERROR %d] : %s\n", zFunctionName, nArg, rc, sqlite3_errmsg( am_db->db )); } rb_gc_unregister_address( &proc_like ); return Qnil; }
Replicates the current database to the database passed in using the sqlite3_backup api
VALUE am_sqlite3_database_replicate_to( VALUE self, VALUE other ) { am_sqlite3 *am_src_db; am_sqlite3 *am_dest_db; sqlite3_backup *backup; sqlite3 *src; sqlite3 *dest; int rc_s; int rc_f; /* source database */ Data_Get_Struct(self, am_sqlite3, am_src_db); src = am_src_db->db; /* destination database */ Data_Get_Struct(other, am_sqlite3, am_dest_db); dest = am_dest_db->db; backup = sqlite3_backup_init( dest, "main", src, "main" ); if ( NULL == backup ) { rb_raise(eAS_Error, "Failure to initialize replication: [SQLITE_ERROR %d] : %s\n", sqlite3_errcode( dest ), sqlite3_errmsg( dest )); } rc_s = sqlite3_backup_step( backup, -1 ); /* copy the whole thing at once */ rc_f = sqlite3_backup_finish( backup ); /* report the rc_s error if that one is bad, * else raise the rc_f error, or nothing */ if ( SQLITE_DONE != rc_s ) { rb_raise(eAS_Error, "Failure in replication : [SQLITE_ERROR %d] : %s\n", sqlite3_errcode( dest ), sqlite3_errmsg( dest ) ); } else if ( SQLITE_OK != rc_f ) { rb_raise(eAS_Error, "Failure in finishing replication: [SQLITE_ERROR %d] : %s\n", sqlite3_errcode( dest ), sqlite3_errmsg( dest ) ); } return other; }
return the number of rows changed with the most recent INSERT, UPDATE or DELETE statement.
VALUE am_sqlite3_database_row_changes(VALUE self) { am_sqlite3 *am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_changes( am_db->db ); return INT2FIX(rc); }
return the DBstatus object for the sqlite database
# File lib/amalgalite/sqlite3/database/status.rb, line 64 def status @status ||= DBStatus.new( self ) end
Returns a hash containing the meta information about the column. The available keys are:
- declared_data_type
-
the declared data type of the column
- collation_sequence_name
-
the name of the collation sequence for the column
- not_null_constraint
-
True if the column has a NOT NULL constraint
- primary_key
-
True if the column is part of a primary key
- auto_increment
-
True if the column is AUTO INCREMENT
VALUE am_sqlite3_database_table_column_metadata(VALUE self, VALUE db_name, VALUE tbl_name, VALUE col_name) { am_sqlite3 *am_db; int rc; /* input */ const char *zDbName = StringValuePtr( db_name ); const char *zTableName = StringValuePtr( tbl_name ); const char *zColumnName = StringValuePtr( col_name ); /* output */ const char *pzDataType = NULL; const char *pzCollSeq = NULL; int pNotNull, pPrimaryKey, pAutoinc; VALUE rHash = rb_hash_new(); VALUE rStr = Qnil; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_table_column_metadata( am_db->db, zDbName, zTableName, zColumnName, &pzDataType, &pzCollSeq, &pNotNull, &pPrimaryKey, &pAutoinc); if ( SQLITE_OK != rc ) { rb_raise(eAS_Error, "Failure retrieveing column meta data for table '%s' column '%s' : [SQLITE_ERROR %d] : %s\n", zTableName, zColumnName, rc, sqlite3_errmsg( am_db-> db )); } rStr = ( NULL == pzDataType) ? Qnil : rb_str_new2( pzDataType ); rb_hash_aset( rHash, rb_str_new2("declared_data_type"), rStr ); rStr = ( NULL == pzCollSeq) ? Qnil : rb_str_new2( pzCollSeq ); rb_hash_aset( rHash, rb_str_new2("collation_sequence_name"), rStr ); rb_hash_aset( rHash, rb_str_new2("not_null_constraint"), ( pNotNull ? Qtrue : Qfalse )); rb_hash_aset( rHash, rb_str_new2("primary_key"), ( pPrimaryKey ? Qtrue : Qfalse )); rb_hash_aset( rHash, rb_str_new2("auto_increment"), ( pAutoinc ? Qtrue : Qfalse )); return rHash; }
return the number of rows changed by INSERT, UPDATE or DELETE statements in the database connection since the connection was opened.
VALUE am_sqlite3_database_total_changes(VALUE self) { am_sqlite3 *am_db; int rc; Data_Get_Struct(self, am_sqlite3, am_db); rc = sqlite3_total_changes( am_db->db ); return INT2FIX(rc); }