Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base: master
...
compare: master
Checking mergeability… Don't worry, you can still create the pull request.
  • 7 commits
  • 17 files changed
  • 2 commit comments
  • 2 contributors
View
8 .gitignore
@@ -13,6 +13,12 @@ tmtags
## VIM
*.swp
+## RubyMine
+.idea
+
+## NetBeans
+nbproject
+
## PROJECT::GENERAL
coverage
rdoc
@@ -20,3 +26,5 @@ pkg
## PROJECT::SPECIFIC
*.gem
+
+
View
2  Rakefile
@@ -16,7 +16,7 @@ begin
gem.add_development_dependency "test-unit", ">= 2.0"
gem.add_development_dependency "activerecord", ">= 2.3.5"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
- gem.post_install_message = <<-EOM
+ gem.post_install_message = <<EOM
==== WARNING ===================================================================
This is an early alpha version of SQLite3/Ruby FFI bindings!
Currently we support Ruby 1.9 ONLY.
View
2  lib/sqlite3.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
require "ffi"
require "sqlite3/api"
View
246 lib/sqlite3/api.rb
@@ -1,52 +1,214 @@
+# encoding: UTF-8
+
module SQLite3
module API
- extend FFI::Library
-
- lib_paths = Array(ENV["SQLITE3_LIB"] || Dir["/{opt,usr}/{,local/}lib{,64}/libsqlite3.{dylib,so*}"])
- fallback_names = ["libsqlite3", "sqlite3"]
- ffi_lib(lib_paths + fallback_names)
-
- attach_function :sqlite3_bind_blob, [:pointer, :int, :pointer, :int, :pointer], :int
- attach_function :sqlite3_bind_double, [:pointer, :int, :double], :int
- attach_function :sqlite3_bind_int, [:pointer, :int, :int], :int
- attach_function :sqlite3_bind_int64, [:pointer, :int, :int64], :int
- attach_function :sqlite3_bind_null, [:pointer, :int], :int
- attach_function :sqlite3_bind_parameter_index, [:pointer, :string], :int
- attach_function :sqlite3_bind_text, [:pointer, :int, :string, :int, :pointer], :int
- attach_function :sqlite3_bind_text16, [:pointer, :int, :pointer, :int, :pointer], :int
- attach_function :sqlite3_busy_timeout, [:pointer, :int], :int
- attach_function :sqlite3_changes, [:pointer], :int
- attach_function :sqlite3_close, [:pointer], :int
- attach_function :sqlite3_column_blob, [:pointer, :int], :pointer
- attach_function :sqlite3_column_bytes, [:pointer, :int], :int
- attach_function :sqlite3_column_bytes16, [:pointer, :int], :int
- attach_function :sqlite3_column_count, [:pointer], :int
- attach_function :sqlite3_column_decltype, [:pointer, :int], :string
- attach_function :sqlite3_column_double, [:pointer, :int], :double
- attach_function :sqlite3_column_int64, [:pointer, :int], :int64
- attach_function :sqlite3_column_name, [:pointer, :int], :string
- attach_function :sqlite3_column_text, [:pointer, :int], :string
- attach_function :sqlite3_column_text16, [:pointer, :int], :pointer
- attach_function :sqlite3_column_type, [:pointer, :int], :int
- attach_function :sqlite3_data_count, [:pointer], :int
- attach_function :sqlite3_errcode, [:pointer], :int
- attach_function :sqlite3_errmsg, [:pointer], :string
- attach_function :sqlite3_errmsg16, [:pointer], :pointer
- attach_function :sqlite3_finalize, [:pointer], :int
- attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
- attach_function :sqlite3_libversion, [], :string
- attach_function :sqlite3_open, [:string, :pointer], :int
- attach_function :sqlite3_open16, [:pointer, :pointer], :int
- attach_function :sqlite3_prepare, [:pointer, :string, :int, :pointer, :pointer], :int
- attach_function :sqlite3_reset, [:pointer], :int
- attach_function :sqlite3_step, [:pointer], :int
+ extend ::FFI::Library
+
+ # prefer spatialite, a version of sqlite extended to support spatial data conforming
+ # to OpenGis specifications. http://www.gaia-gis.it/spatialite/
+ $sqlite3_load_order ||= [
+ Dir['/{opt,usr}/{,local/}lib{,64}/libspatialite.{dylib,so*}'],
+ 'spatialite',
+ Dir['/{opt,usr}/{,local/}lib{,64}/libsqlite3.{dylib,so*}'],
+ 'sqlite3'
+ ].flatten
+
+ ffi_lib($sqlite3_load_order)
+
+ def sqlite3_callback
+ callback(:sqlite3_callback, [ :pointer, :int, :pointer, :pointer ], :int)
+ end
+
+ module_function :sqlite3_callback
+
+ def sqlite3_destructor_type
+ callback(:sqlite3_destructor_type, [ :pointer ], :void)
+ end
+
+ module_function :sqlite3_destructor_type
+
+ attach_function :sqlite3_aggregate_context, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_aggregate_count, [ :pointer ], :int
+ attach_function :sqlite3_auto_extension, [ callback([ ], :void) ], :int
+ attach_function :sqlite3_backup_finish, [ :pointer ], :int
+ attach_function :sqlite3_backup_init, [ :pointer, :string, :pointer, :string ], :pointer
+ attach_function :sqlite3_backup_pagecount, [ :pointer ], :int
+ attach_function :sqlite3_backup_remaining, [ :pointer ], :int
+ attach_function :sqlite3_backup_step, [ :pointer, :int ], :int
+ attach_function :sqlite3_bind_blob, [ :pointer, :int, :pointer, :int, callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_bind_double, [ :pointer, :int, :double ], :int
+ attach_function :sqlite3_bind_int, [ :pointer, :int, :int ], :int
+ attach_function :sqlite3_bind_int64, [ :pointer, :int, :int64 ], :int
+ attach_function :sqlite3_bind_null, [ :pointer, :int ], :int
+ attach_function :sqlite3_bind_parameter_count, [ :pointer ], :int
+ attach_function :sqlite3_bind_parameter_index, [ :pointer, :string ], :int
+ attach_function :sqlite3_bind_parameter_name, [ :pointer, :int ], :string
+ attach_function :sqlite3_bind_text, [ :pointer, :int, :string, :int, callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_bind_text16, [ :pointer, :int, :pointer, :int, callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_bind_value, [ :pointer, :int, :pointer ], :int
+ attach_function :sqlite3_bind_zeroblob, [ :pointer, :int, :int ], :int
+ attach_function :sqlite3_blob_bytes, [ :pointer ], :int
+ attach_function :sqlite3_blob_close, [ :pointer ], :int
+ attach_function :sqlite3_blob_open, [ :pointer, :string, :string, :string, :int64, :int, :pointer ], :int
+ attach_function :sqlite3_blob_read, [ :pointer, :pointer, :int, :int ], :int
+ attach_function :sqlite3_blob_write, [ :pointer, :pointer, :int, :int ], :int
+ attach_function :sqlite3_busy_handler, [ :pointer, callback([ :pointer, :int ], :int), :pointer ], :int
+ attach_function :sqlite3_busy_timeout, [ :pointer, :int ], :int
+ attach_function :sqlite3_changes, [ :pointer ], :int
+ attach_function :sqlite3_clear_bindings, [ :pointer ], :int
+ attach_function :sqlite3_close, [ :pointer ], :int
+ attach_function :sqlite3_collation_needed, [ :pointer, :pointer, callback([ :pointer, :pointer, :int, :string ], :void) ], :int
+ attach_function :sqlite3_collation_needed16, [ :pointer, :pointer, callback([ :pointer, :pointer, :int, :pointer ], :void) ], :int
+ attach_function :sqlite3_column_blob, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_column_bytes, [ :pointer, :int ], :int
+ attach_function :sqlite3_column_bytes16, [ :pointer, :int ], :int
+ attach_function :sqlite3_column_count, [ :pointer ], :int
+ attach_function :sqlite3_column_decltype, [ :pointer, :int ], :string
+ attach_function :sqlite3_column_decltype16, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_column_double, [ :pointer, :int ], :double
+ attach_function :sqlite3_column_int, [ :pointer, :int ], :int
+ attach_function :sqlite3_column_int64, [ :pointer, :int ], :int64
+ attach_function :sqlite3_column_name, [ :pointer, :int ], :string
+ attach_function :sqlite3_column_name16, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_column_text, [ :pointer, :int ], :string
+ attach_function :sqlite3_column_text16, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_column_type, [ :pointer, :int ], :int
+ attach_function :sqlite3_column_value, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_commit_hook, [ :pointer, callback([ :pointer ], :int), :pointer ], :pointer
+ attach_function :sqlite3_complete, [ :string ], :int
+ attach_function :sqlite3_complete16, [ :pointer ], :int
+ attach_function :sqlite3_config, [ :int, :varargs ], :int
+ attach_function :sqlite3_context_db_handle, [ :pointer ], :pointer
+ attach_function :sqlite3_create_collation, [ :pointer, :string, :int, :pointer, callback([ :pointer, :int, :pointer, :int, :pointer ], :int) ], :int
+ attach_function :sqlite3_create_collation16, [ :pointer, :pointer, :int, :pointer, callback([ :pointer, :int, :pointer, :int, :pointer ], :int) ], :int
+ attach_function :sqlite3_create_collation_v2, [ :pointer, :string, :int, :pointer, callback([ :pointer, :int, :pointer, :int, :pointer ], :int), callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_create_function, [ :pointer, :string, :int, :int, :pointer, callback([ :pointer, :int, :pointer ], :void), callback([ :pointer, :int, :pointer ], :void), callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_create_function16, [ :pointer, :pointer, :int, :int, :pointer, callback([ :pointer, :int, :pointer ], :void), callback([ :pointer, :int, :pointer ], :void), callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_create_module, [ :pointer, :string, :pointer, :pointer ], :int
+ attach_function :sqlite3_create_module_v2, [ :pointer, :string, :pointer, :pointer, callback([ :pointer ], :void) ], :int
+ attach_function :sqlite3_data_count, [ :pointer ], :int
+ attach_function :sqlite3_db_config, [ :pointer, :int, :varargs ], :int
+ attach_function :sqlite3_db_handle, [ :pointer ], :pointer
+ attach_function :sqlite3_db_mutex, [ :pointer ], :pointer
+ attach_function :sqlite3_db_status, [ :pointer, :int, :pointer, :pointer, :int ], :int
+ attach_function :sqlite3_declare_vtab, [ :pointer, :string ], :int
+ attach_function :sqlite3_enable_shared_cache, [ :int ], :int
+ attach_function :sqlite3_errcode, [ :pointer ], :int
+ attach_function :sqlite3_errmsg, [ :pointer ], :string
+ attach_function :sqlite3_errmsg16, [ :pointer ], :pointer
+ attach_function :sqlite3_exec, [ :pointer, :string, callback([ :pointer, :int, :pointer, :pointer ], :int), :pointer, :pointer ], :int
+ attach_function :sqlite3_expired, [ :pointer ], :int
+ attach_function :sqlite3_extended_errcode, [ :pointer ], :int
+ attach_function :sqlite3_extended_result_codes, [ :pointer, :int ], :int
+ attach_function :sqlite3_file_control, [ :pointer, :string, :int, :pointer ], :int
+ attach_function :sqlite3_finalize, [ :pointer ], :int
+ attach_function :sqlite3_free, [ :pointer ], :void
+ attach_function :sqlite3_free_table, [ :pointer ], :void
+ attach_function :sqlite3_get_autocommit, [ :pointer ], :int
+ attach_function :sqlite3_get_auxdata, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_get_table, [ :pointer, :string, :pointer, :pointer, :pointer, :pointer ], :int
+ attach_function :sqlite3_global_recover, [ ], :int
+ attach_function :sqlite3_initialize, [ ], :int
+ attach_function :sqlite3_interrupt, [ :pointer ], :void
+ attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
+ attach_function :sqlite3_libversion, [ ], :string
+ attach_function :sqlite3_libversion_number, [ ], :int
+ attach_function :sqlite3_limit, [ :pointer, :int, :int ], :int
+ attach_function :sqlite3_malloc, [ :int ], :pointer
+ attach_function :sqlite3_memory_alarm, [ callback([ :pointer, :int64, :int ], :void), :pointer, :int64 ], :int
+ attach_function :sqlite3_memory_highwater, [ :int ], :int64
+ attach_function :sqlite3_memory_used, [ ], :int64
+ attach_function :sqlite3_mprintf, [ :string, :varargs ], :string
+ attach_function :sqlite3_mutex_alloc, [ :int ], :pointer
+ attach_function :sqlite3_mutex_enter, [ :pointer ], :void
+ attach_function :sqlite3_mutex_free, [ :pointer ], :void
+ attach_function :sqlite3_mutex_leave, [ :pointer ], :void
+ attach_function :sqlite3_mutex_try, [ :pointer ], :int
+ attach_function :sqlite3_next_stmt, [ :pointer, :pointer ], :pointer
+ attach_function :sqlite3_open, [ :string, :pointer ], :int
+ attach_function :sqlite3_open16, [ :pointer, :pointer ], :int
+ attach_function :sqlite3_open_v2, [ :string, :pointer, :int, :string ], :int
+ attach_function :sqlite3_os_end, [ ], :int
+ attach_function :sqlite3_os_init, [ ], :int
+ attach_function :sqlite3_overload_function, [ :pointer, :string, :int ], :int
+ attach_function :sqlite3_prepare, [ :pointer, :string, :int, :pointer, :pointer ], :int
+ attach_function :sqlite3_prepare16, [ :pointer, :pointer, :int, :pointer, :pointer ], :int
+ attach_function :sqlite3_prepare16_v2, [ :pointer, :pointer, :int, :pointer, :pointer ], :int
+ attach_function :sqlite3_prepare_v2, [ :pointer, :string, :int, :pointer, :pointer ], :int
+ attach_function :sqlite3_profile, [ :pointer, callback([ :pointer, :string, :uint64 ], :void), :pointer ], :pointer
+ attach_function :sqlite3_progress_handler, [ :pointer, :int, callback([ :pointer ], :int), :pointer ], :void
+ attach_function :sqlite3_randomness, [ :int, :pointer ], :void
+ attach_function :sqlite3_realloc, [ :pointer, :int ], :pointer
+ attach_function :sqlite3_release_memory, [ :int ], :int
+ attach_function :sqlite3_reset, [ :pointer ], :int
+ attach_function :sqlite3_reset_auto_extension, [ ], :void
+ attach_function :sqlite3_result_blob, [ :pointer, :pointer, :int, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_result_double, [ :pointer, :double ], :void
+ attach_function :sqlite3_result_error, [ :pointer, :string, :int ], :void
+ attach_function :sqlite3_result_error16, [ :pointer, :pointer, :int ], :void
+ attach_function :sqlite3_result_error_code, [ :pointer, :int ], :void
+ attach_function :sqlite3_result_error_nomem, [ :pointer ], :void
+ attach_function :sqlite3_result_error_toobig, [ :pointer ], :void
+ attach_function :sqlite3_result_int, [ :pointer, :int ], :void
+ attach_function :sqlite3_result_int64, [ :pointer, :int64 ], :void
+ attach_function :sqlite3_result_null, [ :pointer ], :void
+ attach_function :sqlite3_result_text, [ :pointer, :string, :int, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_result_text16, [ :pointer, :pointer, :int, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_result_text16be, [ :pointer, :pointer, :int, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_result_text16le, [ :pointer, :pointer, :int, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_result_value, [ :pointer, :pointer ], :void
+ attach_function :sqlite3_result_zeroblob, [ :pointer, :int ], :void
+ attach_function :sqlite3_rollback_hook, [ :pointer, callback([ :pointer ], :void), :pointer ], :pointer
+ attach_function :sqlite3_set_authorizer, [ :pointer, callback([ :pointer, :int, :string, :string, :string, :string ], :int), :pointer ], :int
+ attach_function :sqlite3_set_auxdata, [ :pointer, :int, :pointer, callback([ :pointer ], :void) ], :void
+ attach_function :sqlite3_shutdown, [ ], :int
+ attach_function :sqlite3_sleep, [ :int ], :int
+ attach_function :sqlite3_snprintf, [ :int, :string, :string, :varargs ], :string
+ attach_function :sqlite3_soft_heap_limit, [ :int ], :void
+ attach_function :sqlite3_sql, [ :pointer ], :string
+ attach_function :sqlite3_status, [ :int, :pointer, :pointer, :int ], :int
+ attach_function :sqlite3_step, [ :pointer ], :int
+ attach_function :sqlite3_stmt_status, [ :pointer, :int, :int ], :int
+ attach_function :sqlite3_test_control, [ :int, :varargs ], :int
+ attach_function :sqlite3_thread_cleanup, [ ], :void
+ attach_function :sqlite3_threadsafe, [ ], :int
+ attach_function :sqlite3_total_changes, [ :pointer ], :int
+ attach_function :sqlite3_trace, [ :pointer, callback([ :pointer, :string ], :void), :pointer ], :pointer
+ attach_function :sqlite3_transfer_bindings, [ :pointer, :pointer ], :int
+ attach_function :sqlite3_update_hook, [ :pointer, callback([ :pointer, :int, :string, :string, :int64 ], :void), :pointer ], :pointer
+ attach_function :sqlite3_user_data, [ :pointer ], :pointer
+ attach_function :sqlite3_value_blob, [ :pointer ], :pointer
+ attach_function :sqlite3_value_bytes, [ :pointer ], :int
+ attach_function :sqlite3_value_bytes16, [ :pointer ], :int
+ attach_function :sqlite3_value_double, [ :pointer ], :double
+ attach_function :sqlite3_value_int, [ :pointer ], :int
+ attach_function :sqlite3_value_int64, [ :pointer ], :int64
+ attach_function :sqlite3_value_numeric_type, [ :pointer ], :int
+ attach_function :sqlite3_value_text, [ :pointer ], :pointer
+ attach_function :sqlite3_value_text16, [ :pointer ], :pointer
+ attach_function :sqlite3_value_text16be, [ :pointer ], :pointer
+ attach_function :sqlite3_value_text16le, [ :pointer ], :pointer
+ attach_function :sqlite3_value_type, [ :pointer ], :int
+ attach_function :sqlite3_vfs_find, [ :string ], :pointer
+ attach_function :sqlite3_vfs_register, [ :pointer, :int ], :int
+ attach_function :sqlite3_vfs_unregister, [ :pointer ], :int
begin
attach_function :sqlite3_enable_load_extension, [:pointer, :int], :int
- attach_function :sqlite3_load_extension, [:pointer, :string, :string, :string], :int
+ attach_function :sqlite3_load_extension, [ :pointer, :string, :string, :pointer ], :int
+
EXTENSION_SUPPORT = true
- rescue FFI::NotFoundError
+ rescue ::FFI::NotFoundError
EXTENSION_SUPPORT = false
end
+
+ begin
+ attach_function :spatialite_init, [:int], :int
+ self.spatialite_init(1)
+
+ SPATIALITE_SUPPORT = true
+ rescue ::FFI::NotFoundError
+ SPATIALITE_SUPPORT = false
+ end
end
end
View
2  lib/sqlite3/constants.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
module Constants
View
12 lib/sqlite3/database.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
# The Database class encapsulates a single connection to a SQLite3 database.
@@ -39,7 +41,7 @@ class << self
# It replaces all instances of the single-quote character with two
# single-quote characters. The modified string is returned.
def quote(string)
- string.gsub(/'/, "''")
+ "#{string}".gsub(/'/, "''")
end
end
@@ -63,7 +65,11 @@ def quote(string)
# By default, the new database will return result rows as arrays
# (#results_as_hash) and has type translation disabled (#type_translation=).
def initialize(file_name, options = {})
- @encoding = Encoding.find(options.fetch(:encoding, "utf-8"))
+ if RUBY_VERSION >= '1.9.1'
+ @encoding = Encoding.find(options.fetch(:encoding, "utf-8"))
+ else
+ @encoding = nil
+ end
@driver = Driver.new
@@ -168,7 +174,7 @@ def execute2(sql, *bind_vars)
yield result.columns
result.each { |row| yield row }
else
- return result.inject([result.columns]) { |arr,row| arr << row; arr }
+ return result.inject([result.columns]) { |arr, row| arr << row; arr }
end
end
end
View
44 lib/sqlite3/driver.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
class Driver
TRANSIENT = FFI::Pointer.new(-1)
@@ -8,7 +10,7 @@ def open(filename, utf_16 = false)
filename = filename.encode(Encoding.utf_16native)
result = API.sqlite3_open16(c_string(filename), handle)
else
- filename = filename.encode(Encoding.utf_8)
+ filename = filename.encode(Encoding.utf_8) if RUBY_VERSION >= '1.9.1'
result = API.sqlite3_open(filename, handle)
end
[result, handle.get_pointer(0)]
@@ -19,7 +21,11 @@ def errmsg(db, utf_16 = false)
ptr = API.sqlite3_errmsg16(db)
get_string_utf_16(ptr).force_encoding(Encoding.utf_16native)
else
- API.sqlite3_errmsg(db).force_encoding(Encoding.utf_8)
+ if RUBY_VERSION >= '1.9.1'
+ API.sqlite3_errmsg(db).force_encoding(Encoding.utf_8)
+ else
+ API.sqlite3_errmsg(db)
+ end
end
end
@@ -40,12 +46,16 @@ def prepare(db, sql)
end
def bind_string(stmt, index, value)
- case value.encoding
- when Encoding.utf_8, Encoding.us_ascii
- API.sqlite3_bind_text(stmt, index, value, value.bytesize, TRANSIENT)
- when Encoding.utf_16le, Encoding.utf_16be
- value = add_byte_order_mask(value)
- API.sqlite3_bind_text16(stmt, index, value, value.bytesize, TRANSIENT)
+ if RUBY_VERSION >= '1.9.1'
+ case value.encoding
+ when Encoding.utf_8, Encoding.us_ascii
+ API.sqlite3_bind_text(stmt, index, value, value.bytesize, TRANSIENT)
+ when Encoding.utf_16le, Encoding.utf_16be
+ value = add_byte_order_mask(value)
+ API.sqlite3_bind_text16(stmt, index, value, value.bytesize, TRANSIENT)
+ else
+ API.sqlite3_bind_blob(stmt, index, value, value.bytesize, TRANSIENT)
+ end
else
API.sqlite3_bind_blob(stmt, index, value, value.bytesize, TRANSIENT)
end
@@ -63,7 +73,11 @@ def column_text(stmt, column, utf_16 = false)
length = API.sqlite3_column_bytes16(stmt, column)
ptr.get_bytes(0, length).force_encoding(Encoding.utf_16native) # free?
else
- API.sqlite3_column_text(stmt, column).force_encoding(Encoding.utf_8)
+ if RUBY_VERSION >= '1.9.1'
+ API.sqlite3_column_text(stmt, column).force_encoding(Encoding.utf_8)
+ else
+ API.sqlite3_column_text(stmt, column)
+ end
end
end
@@ -118,11 +132,19 @@ def c_string(string)
end
def add_byte_order_mask(string)
- "\uFEFF".encode(string.encoding) + string
+ if RUBY_VERSION >= '1.9.1'
+ "\uFEFF".encode(string.encoding) + string
+ else
+ "\uFEFF" + string
+ end
end
def terminate_string!(string)
- string << "\0\0".force_encoding(string.encoding)
+ if RUBY_VERSION >= '1.9.1'
+ string << "\0\0".force_encoding(string.encoding)
+ else
+ string << "\0\0"
+ end
end
def get_string_utf_16(ptr)
View
10 lib/sqlite3/encoding.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
class Encoding
class << self
@@ -15,8 +17,12 @@ def find(encoding)
end
def utf_16?(str_or_enc)
- enc = str_or_enc.kind_of?(::Encoding) ? str_or_enc : str_or_enc.encoding
- [utf_16le, utf_16be].include?(enc)
+ if RUBY_VERSION >= '1.9.1'
+ enc = str_or_enc.kind_of?(::Encoding) ? str_or_enc : str_or_enc.encoding
+ [utf_16le, utf_16be].include?(enc)
+ else
+ false
+ end
end
def utf_16native
View
77 lib/sqlite3/errors.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
class Exception < ::StandardError
@@ -14,45 +16,45 @@ def code
end
end
- class SQLException < Exception; end
- class InternalException < Exception; end
- class PermissionException < Exception; end
- class AbortException < Exception; end
- class BusyException < Exception; end
- class LockedException < Exception; end
- class MemoryException < Exception; end
- class ReadOnlyException < Exception; end
- class InterruptException < Exception; end
- class IOException < Exception; end
- class CorruptException < Exception; end
- class NotFoundException < Exception; end
- class FullException < Exception; end
- class CantOpenException < Exception; end
- class ProtocolException < Exception; end
- class EmptyException < Exception; end
- class SchemaChangedException < Exception; end
- class TooBigException < Exception; end
- class ConstraintException < Exception; end
- class MismatchException < Exception; end
- class MisuseException < Exception; end
- class UnsupportedException < Exception; end
- class AuthorizationException < Exception; end
- class FormatException < Exception; end
- class RangeException < Exception; end
- class NotADatabaseException < Exception; end
+ SQLException = Class.new(Exception)
+ InternalException = Class.new(Exception)
+ PermissionException = Class.new(Exception)
+ AbortException = Class.new(Exception)
+ BusyException = Class.new(Exception)
+ LockedException = Class.new(Exception)
+ MemoryException = Class.new(Exception)
+ ReadOnlyException = Class.new(Exception)
+ InterruptException = Class.new(Exception)
+ IOException = Class.new(Exception)
+ CorruptException = Class.new(Exception)
+ NotFoundException = Class.new(Exception)
+ FullException = Class.new(Exception)
+ CantOpenException = Class.new(Exception)
+ ProtocolException = Class.new(Exception)
+ EmptyException = Class.new(Exception)
+ SchemaChangedException = Class.new(Exception)
+ TooBigException = Class.new(Exception)
+ ConstraintException = Class.new(Exception)
+ MismatchException = Class.new(Exception)
+ MisuseException = Class.new(Exception)
+ UnsupportedException = Class.new(Exception)
+ AuthorizationException = Class.new(Exception)
+ FormatException = Class.new(Exception)
+ RangeException = Class.new(Exception)
+ NotADatabaseException = Class.new(Exception)
EXCEPTIONS =
- [
- nil, SQLException, InternalException,
- PermissionException, AbortException, BusyException,
- LockedException, MemoryException, ReadOnlyException,
- InterruptException, IOException, CorruptException,
- NotFoundException, FullException, CantOpenException,
- ProtocolException, EmptyException, SchemaChangedException,
- TooBigException, ConstraintException, MismatchException,
- MisuseException, UnsupportedException, AuthorizationException,
- FormatException, RangeException, NotADatabaseException
- ].each_with_index { |e,i| e.instance_variable_set(:@code, i ) if e }
+ [
+ nil, SQLException, InternalException,
+ PermissionException, AbortException, BusyException,
+ LockedException, MemoryException, ReadOnlyException,
+ InterruptException, IOException, CorruptException,
+ NotFoundException, FullException, CantOpenException,
+ ProtocolException, EmptyException, SchemaChangedException,
+ TooBigException, ConstraintException, MismatchException,
+ MisuseException, UnsupportedException, AuthorizationException,
+ FormatException, RangeException, NotADatabaseException
+ ].each_with_index { |e, i| e.instance_variable_set(:@code, i ) if e }
module Error
def check( result, db=nil, msg=nil )
@@ -61,6 +63,7 @@ def check( result, db=nil, msg=nil )
raise(( EXCEPTIONS[result] || SQLite3::Exception ), msg)
end
end
+
module_function :check
end
View
2  lib/sqlite3/extensions.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
module Extensions
def enable_load_extension(onoff=true)
View
16 lib/sqlite3/pragmas.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
# This module is intended for inclusion solely by the Database class. It
@@ -40,7 +42,7 @@ def version_compare(v1, v2)
parts = [v1.length, v2.length].max
v1.push 0 while v1.length < parts
v2.push 0 while v2.length < parts
- v1.zip(v2).each do |a,b|
+ v1.zip(v2).each do |a, b|
return -1 if a < b
return 1 if a > b
end
@@ -52,12 +54,12 @@ def version_compare(v1, v2)
# unquotes those values.
def tweak_default(hash)
case hash["dflt_value"]
- when /^null$/i
- hash["dflt_value"] = nil
- when /^'(.*)'$/
- hash["dflt_value"] = $1.gsub(/''/, "'")
- when /^"(.*)"$/
- hash["dflt_value"] = $1.gsub(/""/, '"')
+ when /^null$/i
+ hash["dflt_value"] = nil
+ when /^'(.*)'$/
+ hash["dflt_value"] = $1.gsub(/''/, "'")
+ when /^"(.*)"$/
+ hash["dflt_value"] = $1.gsub(/""/, '"')
end
end
end
View
6 lib/sqlite3/resultset.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
# The ResultSet object encapsulates the enumerability of a query's output.
@@ -46,6 +48,7 @@ def commence
check result
@first_row = true
end
+
private :commence
def check(result)
@@ -53,6 +56,7 @@ def check(result)
found = (result == Constants::ErrorCode::ROW)
Error.check(result, @db) unless @eof || found
end
+
private :check
# Reset the cursor, so that a result set which has reached end-of-file
@@ -122,7 +126,7 @@ def next
if @db.results_as_hash
new_row = HashWithTypes[ *(@stmt.columns.zip(row).to_a.flatten) ]
- row.each_with_index { |value,idx| new_row[idx] = value }
+ row.each_with_index { |value, idx| new_row[idx] = value }
row = new_row
else
if row.respond_to?(:fields)
View
27 lib/sqlite3/statement.rb
@@ -1,3 +1,5 @@
+# encoding: UTF-8
+
module SQLite3
# A statement represents a prepared-but-unexecuted SQL query. It will rarely
@@ -76,20 +78,20 @@ def bind_param(param, value)
reset! if active?
if Fixnum === param
case value
- when Bignum then
- @driver.bind_int64(@handle, param, value)
- when Integer then
- if value >= (2 ** 31)
+ when Bignum then
@driver.bind_int64(@handle, param, value)
+ when Integer then
+ if value >= (2 ** 31)
+ @driver.bind_int64(@handle, param, value)
+ else
+ @driver.bind_int(@handle, param, value)
+ end
+ when Numeric then
+ @driver.bind_double(@handle, param, value.to_f)
+ when nil then
+ @driver.bind_null(@handle, param)
else
- @driver.bind_int(@handle, param, value)
- end
- when Numeric then
- @driver.bind_double(@handle, param, value.to_f)
- when nil then
- @driver.bind_null(@handle, param)
- else
- @driver.bind_string(@handle, param, value.to_s)
+ @driver.bind_string(@handle, param, value.to_s)
end
else
param = param.to_s
@@ -199,6 +201,7 @@ def get_metadata
@types << @driver.column_decltype(@handle, column)
end
end
+
private :get_metadata
# Performs a sanity check to ensure that the statement is not
View
27 test/test_active_record.rb
@@ -12,6 +12,7 @@ def self.up
t.boolean :active
t.datetime :expires_at
t.text :about_me
+ t.string :test_hash
t.timestamps
end
end
@@ -21,7 +22,9 @@ def self.down
end
end
-class User < ActiveRecord::Base; end
+class User < ActiveRecord::Base;
+ serialize :test_hash
+end
class TestActiveRecord < Test::Unit::TestCase
def setup
@@ -155,4 +158,26 @@ def test_attribute_assignment
user.reload
assert_equal 1, User.count
end
+
+ def test_serialized_attributes
+ hash = { :array => [1,2,3],
+ :bool => true,
+ :float => 1.0,
+ :int => 1,
+ :other_user => User.new(:login => 'login'),
+ :sub_hash => { :bool => true,
+ :int => 1,
+ :float => 1.0 }}
+ user = User.create!(:test_hash => hash)
+ user.reload
+
+ # test equality
+ hash.each_key do |k|
+ if hash[k].kind_of?(ActiveRecord::Base)
+ assert_equal hash[k].attributes, user.test_hash[k].attributes
+ else
+ assert_equal hash[k], user.test_hash[k]
+ end
+ end
+ end
end
View
30 test/test_database_initialization.rb
@@ -30,22 +30,36 @@ def test_encoding_conversion_from_utf_16_to_utf_8
File.delete(db_filename) if File.exists?(db_filename)
db = SQLite3::Database.new(db_filename, :encoding => "utf-16le")
db.execute("CREATE TABLE t1(t TEXT)")
- db.execute("INSERT INTO t1 VALUES (?)", expected_string.encode(Encoding::UTF_8))
- db.execute("INSERT INTO t1 VALUES (?)", expected_string.encode(Encoding::UTF_16LE))
+
+ if RUBY_VERSION >= '1.9.1'
+ db.execute("INSERT INTO t1 VALUES (?)", expected_string.encode(Encoding::UTF_8))
+ db.execute("INSERT INTO t1 VALUES (?)", expected_string.encode(Encoding::UTF_16LE))
+ else
+ db.execute("INSERT INTO t1 VALUES (?)", expected_string)
+ db.execute("INSERT INTO t1 VALUES (?)", expected_string)
+ end
+
rows = db.execute("SELECT * FROM t1")
assert_equal 2, rows.size
- assert_equal expected_string.encode(Encoding::UTF_16LE), rows[0][0]
- assert_equal Encoding::UTF_16LE, rows[0][0].encoding
- assert_equal expected_string.encode(Encoding::UTF_16LE), rows[1][0]
- assert_equal Encoding::UTF_16LE, rows[1][0].encoding
+
+ if RUBY_VERSION >= '1.9.1'
+ assert_equal expected_string.encode(Encoding::UTF_16LE), rows[0][0]
+ assert_equal Encoding::UTF_16LE, rows[0][0].encoding
+ assert_equal expected_string.encode(Encoding::UTF_16LE), rows[1][0]
+ assert_equal Encoding::UTF_16LE, rows[1][0].encoding
+ else
+ assert_equal expected_string, rows[0][0]
+ assert_equal expected_string, rows[1][0]
+ end
+
db.close
db = SQLite3::Database.new(db_filename)
rows = db.execute("SELECT * FROM t1")
assert_equal 2, rows.size
assert_equal expected_string, rows[0][0]
- assert_equal Encoding::UTF_8, rows[0][0].encoding
+ assert_equal Encoding::UTF_8, rows[0][0].encoding if RUBY_VERSION >= '1.9.1'
assert_equal expected_string, rows[1][0]
- assert_equal Encoding::UTF_8, rows[1][0].encoding
+ assert_equal Encoding::UTF_8, rows[1][0].encoding if RUBY_VERSION >= '1.9.1'
File.delete(db_filename) if File.exists?(db_filename)
end
end
View
144 test/test_database_queries_utf_16.rb
@@ -1,80 +1,82 @@
-require "helper"
+if RUBY_VERSION >= '1.9.1'
+ require "helper"
-class TestDatabaseQueriesUtf16 < Test::Unit::TestCase
- def setup
- @db = SQLite3::Database.new(":memory:", :encoding => "utf-16")
- @db.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY ASC, t TEXT, nu1 NUMERIC, i1 INTEGER, i2 INTEGER, no BLOB)")
- end
+ class TestDatabaseQueriesUtf16 < Test::Unit::TestCase
+ def setup
+ @db = SQLite3::Database.new(":memory:", :encoding => "utf-16")
+ @db.execute("CREATE TABLE t1(id INTEGER PRIMARY KEY ASC, t TEXT, nu1 NUMERIC, i1 INTEGER, i2 INTEGER, no BLOB)")
+ end
- def teardown
- @db.close
- end
+ def teardown
+ @db.close
+ end
- def test_tables_empty
- assert_equal [], @db.execute("SELECT * FROM t1")
- end
+ def test_tables_empty
+ assert_equal [], @db.execute("SELECT * FROM t1")
+ end
- def test_execute
- @db.execute("INSERT INTO t1 VALUES(NULL, 'text1', 1.22, 42, 4294967296, NULL)")
- rows = @db.execute("SELECT * FROM t1")
- assert_equal 1, rows.size
- row = rows[0]
- assert_equal "text1".encode(Encoding::UTF_16LE), row[1]
- assert_equal Encoding::UTF_16LE, row[1].encoding
- assert_equal 1.22, row[2]
- assert_equal 42, row[3]
- assert_equal 4294967296, row[4]
- assert_nil row[5]
- end
+ def test_execute
+ @db.execute("INSERT INTO t1 VALUES(NULL, 'text1', 1.22, 42, 4294967296, NULL)")
+ rows = @db.execute("SELECT * FROM t1")
+ assert_equal 1, rows.size
+ row = rows[0]
+ assert_equal "text1".encode(Encoding::UTF_16LE), row[1]
+ assert_equal Encoding::UTF_16LE, row[1].encoding
+ assert_equal 1.22, row[2]
+ assert_equal 42, row[3]
+ assert_equal 4294967296, row[4]
+ assert_nil row[5]
+ end
- def test_execute_with_bindings
- blob = open("test/fixtures/SQLite.gif", "rb").read
- @db.execute("INSERT INTO t1 VALUES(?, ?, ?, ?, ?, ?)", nil, "text1", 1.22, 42, 4294967296, blob)
- rows = @db.execute("SELECT * FROM t1")
- assert_equal 1, rows.size
- row = rows[0]
- assert_equal "text1".encode(Encoding::UTF_16LE), row[1]
- assert_equal Encoding::UTF_16LE, row[1].encoding
- assert_equal 1.22, row[2]
- assert_equal 42, row[3]
- assert_equal 4294967296, row[4]
- assert_equal blob, row[5]
- assert_equal Encoding::ASCII_8BIT, row[5].encoding
- end
+ def test_execute_with_bindings
+ blob = open("test/fixtures/SQLite.gif", "rb").read
+ @db.execute("INSERT INTO t1 VALUES(?, ?, ?, ?, ?, ?)", nil, "text1", 1.22, 42, 4294967296, blob)
+ rows = @db.execute("SELECT * FROM t1")
+ assert_equal 1, rows.size
+ row = rows[0]
+ assert_equal "text1".encode(Encoding::UTF_16LE), row[1]
+ assert_equal Encoding::UTF_16LE, row[1].encoding
+ assert_equal 1.22, row[2]
+ assert_equal 42, row[3]
+ assert_equal 4294967296, row[4]
+ assert_equal blob, row[5]
+ assert_equal Encoding::ASCII_8BIT, row[5].encoding
+ end
- def test_execute_with_different_encodings
- expected_string = "text1"
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::ASCII_8BIT))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_8))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16LE))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16BE))
- rows = @db.execute("SELECT * FROM t1")
- assert_equal 4, rows.size
- assert_equal expected_string, rows[0][1]
- assert_equal expected_string.encode(Encoding::UTF_16LE), rows[1][1]
- assert_equal expected_string.encode(Encoding::UTF_16LE), rows[2][1]
- assert_equal expected_string.encode(Encoding::UTF_16LE), rows[3][1]
- assert_equal Encoding::ASCII_8BIT, rows[0][1].encoding
- assert_equal Encoding::UTF_16LE, rows[1][1].encoding
- assert_equal Encoding::UTF_16LE, rows[2][1].encoding
- assert_equal Encoding::UTF_16LE, rows[3][1].encoding
- end
+ def test_execute_with_different_encodings
+ expected_string = "text1"
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::ASCII_8BIT))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_8))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16LE))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16BE))
+ rows = @db.execute("SELECT * FROM t1")
+ assert_equal 4, rows.size
+ assert_equal expected_string, rows[0][1]
+ assert_equal expected_string.encode(Encoding::UTF_16LE), rows[1][1]
+ assert_equal expected_string.encode(Encoding::UTF_16LE), rows[2][1]
+ assert_equal expected_string.encode(Encoding::UTF_16LE), rows[3][1]
+ assert_equal Encoding::ASCII_8BIT, rows[0][1].encoding
+ assert_equal Encoding::UTF_16LE, rows[1][1].encoding
+ assert_equal Encoding::UTF_16LE, rows[2][1].encoding
+ assert_equal Encoding::UTF_16LE, rows[3][1].encoding
+ end
- def test_execute_with_bad_query
- assert_raise(SQLite3::SQLException) { @db.execute("bad query") }
- assert_equal %Q{near "bad": syntax error}, @db.errmsg
- assert_equal 1, @db.errcode
- end
+ def test_execute_with_bad_query
+ assert_raise(SQLite3::SQLException) { @db.execute("bad query") }
+ assert_equal %Q{near "bad": syntax error}, @db.errmsg
+ assert_equal 1, @db.errcode
+ end
- def test_last_insert_row_id
- @db.execute("INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL)")
- id = @db.last_insert_row_id
- rows = @db.execute("SELECT * FROM t1 WHERE id = #{id}")
- assert_equal 1, rows.size
- end
+ def test_last_insert_row_id
+ @db.execute("INSERT INTO t1 VALUES(NULL, NULL, NULL, NULL, NULL, NULL)")
+ id = @db.last_insert_row_id
+ rows = @db.execute("SELECT * FROM t1 WHERE id = #{id}")
+ assert_equal 1, rows.size
+ end
- # def test_execute_with_closed_database
- # @db.close
- # @db.execute("SELECT * FROM t1")
- # end
-end
+ # def test_execute_with_closed_database
+ # @db.close
+ # @db.execute("SELECT * FROM t1")
+ # end
+ end
+end
View
42 test/test_database_queries_utf_8.rb
@@ -20,7 +20,7 @@ def test_execute
assert_equal 1, rows.size
row = rows[0]
assert_equal "text1", row[1]
- assert_equal Encoding::UTF_8, row[1].encoding
+ assert_equal Encoding::UTF_8, row[1].encoding if RUBY_VERSION >= '1.9.1'
assert_equal 1.22, row[2]
assert_equal 42, row[3]
assert_equal 4294967296, row[4]
@@ -34,30 +34,32 @@ def test_execute_with_bindings
assert_equal 1, rows.size
row = rows[0]
assert_equal "text1", row[1]
- assert_equal Encoding::UTF_8, row[1].encoding
+ assert_equal Encoding::UTF_8, row[1].encoding if RUBY_VERSION >= '1.9.1'
assert_equal 1.22, row[2]
assert_equal 42, row[3]
assert_equal 4294967296, row[4]
assert_equal blob, row[5]
- assert_equal Encoding::ASCII_8BIT, row[5].encoding
+ assert_equal Encoding::ASCII_8BIT, row[5].encoding if RUBY_VERSION >= '1.9.1'
end
-
- def test_execute_with_different_encodings
- expected_string = "text1"
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::ASCII_8BIT))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_8))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16LE))
- @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16BE))
- rows = @db.execute("SELECT * FROM t1")
- assert_equal 4, rows.size
- assert_equal expected_string, rows[0][1]
- assert_equal expected_string, rows[1][1]
- assert_equal expected_string, rows[2][1]
- assert_equal expected_string, rows[3][1]
- assert_equal Encoding::ASCII_8BIT, rows[0][1].encoding
- assert_equal Encoding::UTF_8, rows[1][1].encoding
- assert_equal Encoding::UTF_8, rows[2][1].encoding
- assert_equal Encoding::UTF_8, rows[3][1].encoding
+
+ if RUBY_VERSION >= '1.9.1'
+ def test_execute_with_different_encodings
+ expected_string = "text1"
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::ASCII_8BIT))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_8))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16LE))
+ @db.execute("INSERT INTO t1 VALUES(NULL, ?, NULL, NULL, NULL, NULL)", expected_string.encode(Encoding::UTF_16BE))
+ rows = @db.execute("SELECT * FROM t1")
+ assert_equal 4, rows.size
+ assert_equal expected_string, rows[0][1]
+ assert_equal expected_string, rows[1][1]
+ assert_equal expected_string, rows[2][1]
+ assert_equal expected_string, rows[3][1]
+ assert_equal Encoding::ASCII_8BIT, rows[0][1].encoding
+ assert_equal Encoding::UTF_8, rows[1][1].encoding
+ assert_equal Encoding::UTF_8, rows[2][1].encoding
+ assert_equal Encoding::UTF_8, rows[3][1].encoding
+ end
end
def test_execute_with_bad_query

Showing you all comments on commits in this comparison.

@rdp

so do these sqlite3 bindings work with AR? ... If so I might have a bounty for you :)

@DavyLandman

I really like you added ruby 1.8 support, perhaps you could create a pull request so it will eventually reach the gem?

Something went wrong with that request. Please try again.