Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

removed 'load_driver'

  • Loading branch information...
commit c43261aedc297d26010e2377b708b80cb61326e9 1 parent 635bddd
Jakub Kuźma authored
View
2  Rakefile
@@ -12,7 +12,7 @@ begin
gem.email = "qoobaa@gmail.com"
gem.homepage = "http://github.com/qoobaa/sqlite3"
gem.authors = ["Jakub Kuźma"]
- gem.add_dependency "ffi", ">= 0.5.1"
+ gem.add_dependency "ffi", ">= 0.6.0"
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
View
2  lib/sqlite3.rb
@@ -1,5 +1,7 @@
require "ffi"
+require "sqlite3/api"
+require "sqlite3/driver"
require "sqlite3/constants"
require "sqlite3/errors"
require "sqlite3/pragmas"
View
40 lib/sqlite3/api.rb
@@ -0,0 +1,40 @@
+module SQLite3
+ module API
+ extend FFI::Library
+
+ ffi_lib ["libsqlite3.dylib", "libsqlite3.so", "sqlite3.dll"]
+
+ attach_function :sqlite3_libversion, [], :string
+ attach_function :sqlite3_open, [:string, :pointer], :int
+ attach_function :sqlite3_open16, [:pointer, :pointer], :int
+ attach_function :sqlite3_close, [:pointer], :int
+ attach_function :sqlite3_errmsg, [:pointer], :string
+ attach_function :sqlite3_errmsg16, [:pointer], :pointer
+ attach_function :sqlite3_errcode, [:pointer], :int
+ attach_function :sqlite3_prepare, [:pointer, :string, :int, :pointer, :pointer], :int
+ attach_function :sqlite3_finalize, [:pointer], :int
+ attach_function :sqlite3_step, [:pointer], :int
+ attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
+ attach_function :sqlite3_changes, [:pointer], :int
+ attach_function :sqlite3_busy_timeout, [:pointer, :int], :int
+ 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_text, [:pointer, :int, :string, :int, :pointer], :int
+ attach_function :sqlite3_bind_text16, [:pointer, :int, :pointer, :int, :pointer], :int
+ attach_function :sqlite3_column_count, [:pointer], :int
+ attach_function :sqlite3_data_count, [: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_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
+ end
+end
View
31 lib/sqlite3/database.rb
@@ -64,7 +64,7 @@ def quote(string)
def initialize(file_name, options = {})
@encoding = Encoding.find(options.fetch(:encoding, "utf-8"))
- load_driver(options[:driver])
+ @driver = Driver.new
@statement_factory = options[:statement_factory] || Statement
@@ -275,34 +275,5 @@ def rollback
def transaction_active?
@transaction_active
end
-
- private
-
- # Loads the corresponding driver, or if it is nil, attempts to locate a
- # suitable driver.
- def load_driver(driver)
- case driver
- when Class
- # do nothing--use what was given
- when Symbol, String
- require "sqlite3/driver/#{driver.to_s.downcase}/driver"
- driver = SQLite3::Driver.const_get(driver)::Driver
- else
- ["FFI"].each do |d|
- begin
- require "sqlite3/driver/#{d.downcase}/driver"
- driver = SQLite3::Driver.const_get(d)::Driver
- break
- rescue SyntaxError
- raise
- rescue ScriptError, Exception, NameError
- end
- end
- raise "no driver for sqlite3 found" unless driver
- end
-
- @driver = driver.new
- end
-
end
end
View
121 lib/sqlite3/driver.rb
@@ -0,0 +1,121 @@
+module SQLite3
+ class Driver
+ TRANSIENT = FFI::Pointer.new(-1)
+
+ def open(filename, utf_16 = false)
+ handle = FFI::MemoryPointer.new(:pointer)
+ if utf_16
+ filename = filename.encode(Encoding.utf_16native)
+ result = API.sqlite3_open16(c_string(filename), handle)
+ else
+ filename = filename.encode(Encoding.utf_8)
+ result = API.sqlite3_open(filename, handle)
+ end
+ [result, handle.get_pointer(0)]
+ end
+
+ def errmsg(db, utf_16 = false)
+ if utf_16
+ 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)
+ end
+ end
+
+ def prepare(db, sql)
+ handle = FFI::MemoryPointer.new(:pointer)
+ remainder = FFI::MemoryPointer.new(:pointer)
+
+ if Encoding.utf_16?(sql)
+ str = c_string(sql)
+ result = API.sqlite3_prepare16(db, str, str.bytesize, handle, remainder)
+ remainder_string = get_string_utf_16(remainder.get_pointer(0))
+ else
+ result = API.sqlite3_prepare(db, sql, sql.bytesize, handle, remainder)
+ remainder_string = remainder.get_pointer(0).get_string(0)
+ end
+
+ [result, handle.get_pointer(0), remainder_string]
+ 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)
+ else
+ API.sqlite3_bind_blob(stmt, index, value, value.bytesize, TRANSIENT)
+ end
+ end
+
+ def column_blob(stmt, column)
+ blob = API.sqlite3_column_blob(stmt, column)
+ length = API.sqlite3_column_bytes(stmt, column)
+ blob.get_bytes(0, length) # free?
+ end
+
+ def column_text(stmt, column, utf_16 = false)
+ if utf_16
+ ptr = API.sqlite3_column_text16(stmt, column)
+ 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)
+ end
+ end
+
+ def self.api_delegate(name)
+ define_method(name) { |*args| API.send("sqlite3_#{name}", *args) }
+ end
+
+ api_delegate :column_name
+ api_delegate :column_decltype
+ api_delegate :bind_double
+ api_delegate :bind_int
+ api_delegate :bind_int64
+ api_delegate :bind_null
+ api_delegate :bind_parameter_index
+ api_delegate :bind_parameter_name
+ api_delegate :busy_timeout
+ api_delegate :changes
+ api_delegate :close
+ api_delegate :column_count
+ api_delegate :column_double
+ api_delegate :column_int64
+ api_delegate :column_type
+ api_delegate :data_count
+ api_delegate :errcode
+ api_delegate :finalize
+ api_delegate :last_insert_rowid
+ api_delegate :libversion
+ api_delegate :step
+
+ private
+
+ def c_string(string)
+ if Encoding.utf_16?(string)
+ result = add_byte_order_mask(string)
+ terminate_string!(result)
+ else
+ string # FFI does the job
+ end
+ end
+
+ def add_byte_order_mask(string)
+ "\uFEFF".encode(string.encoding) + string
+ end
+
+ def terminate_string!(string)
+ string << "\0\0".force_encoding(string.encoding)
+ end
+
+ def get_string_utf_16(ptr)
+ length = 0
+ length += 2 until ptr.get_bytes(length, 2) == "\0\0"
+ ptr.get_bytes(0, length)
+ end
+ end
+end
View
46 lib/sqlite3/driver/ffi/api.rb
@@ -1,46 +0,0 @@
-module SQLite3
- module Driver
- module FFI
-
- module API
- extend ::FFI::Library
-
- ffi_lib "libsqlite3.dylib", "libsqlite3.so" "sqlite3.dll"
-
- attach_function :sqlite3_libversion, [], :string
- attach_function :sqlite3_open, [:string, :pointer], :int
- attach_function :sqlite3_open16, [:pointer, :pointer], :int
- attach_function :sqlite3_close, [:pointer], :int
- attach_function :sqlite3_errmsg, [:pointer], :string
- attach_function :sqlite3_errmsg16, [:pointer], :pointer
- attach_function :sqlite3_errcode, [:pointer], :int
- attach_function :sqlite3_prepare, [:pointer, :string, :int, :pointer, :pointer], :int
- attach_function :sqlite3_finalize, [:pointer], :int
- attach_function :sqlite3_step, [:pointer], :int
- attach_function :sqlite3_last_insert_rowid, [:pointer], :int64
- attach_function :sqlite3_changes, [:pointer], :int
- attach_function :sqlite3_busy_timeout, [:pointer, :int], :int
- 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_text, [:pointer, :int, :string, :int, :pointer], :int
- attach_function :sqlite3_bind_text16, [:pointer, :int, :pointer, :int, :pointer], :int
- attach_function :sqlite3_column_count, [:pointer], :int
- attach_function :sqlite3_data_count, [: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_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
- end
-
- end
- end
-end
View
128 lib/sqlite3/driver/ffi/driver.rb
@@ -1,128 +0,0 @@
-require 'sqlite3/driver/ffi/api'
-
-module SQLite3
- module Driver
- module FFI
-
- class Driver
- TRANSIENT = ::FFI::Pointer.new(-1)
-
- def open(filename, utf_16 = false)
- handle = ::FFI::MemoryPointer.new(:pointer)
- if utf_16
- filename = filename.encode(Encoding.utf_16native)
- result = API.sqlite3_open16(c_string(filename), handle)
- else
- filename = filename.encode(Encoding.utf_8)
- result = API.sqlite3_open(filename, handle)
- end
- [result, handle.get_pointer(0)]
- end
-
- def errmsg(db, utf_16 = false)
- if utf_16
- 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)
- end
- end
-
- def prepare(db, sql)
- handle = ::FFI::MemoryPointer.new(:pointer)
- remainder = ::FFI::MemoryPointer.new(:pointer)
-
- if Encoding.utf_16?(sql)
- str = c_string(sql)
- result = API.sqlite3_prepare16(db, str, str.bytesize, handle, remainder)
- remainder_string = get_string_utf_16(remainder.get_pointer(0))
- else
- result = API.sqlite3_prepare(db, sql, sql.bytesize, handle, remainder)
- remainder_string = remainder.get_pointer(0).get_string(0)
- end
-
- [result, handle.get_pointer(0), remainder_string]
- 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)
- else
- API.sqlite3_bind_blob(stmt, index, value, value.bytesize, TRANSIENT)
- end
- end
-
- def column_blob(stmt, column)
- blob = API.sqlite3_column_blob(stmt, column)
- length = API.sqlite3_column_bytes(stmt, column)
- blob.get_bytes(0, length) # free?
- end
-
- def column_text(stmt, column, utf_16 = false)
- if utf_16
- ptr = API.sqlite3_column_text16(stmt, column)
- 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)
- end
- end
-
- def self.api_delegate(name)
- define_method(name) { |*args| API.send("sqlite3_#{name}", *args) }
- end
-
- api_delegate :column_name
- api_delegate :column_decltype
- api_delegate :bind_double
- api_delegate :bind_int
- api_delegate :bind_int64
- api_delegate :bind_null
- api_delegate :bind_parameter_index
- api_delegate :bind_parameter_name
- api_delegate :busy_timeout
- api_delegate :changes
- api_delegate :close
- api_delegate :column_count
- api_delegate :column_double
- api_delegate :column_int64
- api_delegate :column_type
- api_delegate :data_count
- api_delegate :errcode
- api_delegate :finalize
- api_delegate :last_insert_rowid
- api_delegate :libversion
- api_delegate :step
-
- private
-
- def c_string(string)
- if Encoding.utf_16?(string)
- result = add_byte_order_mask(string)
- terminate_string!(result)
- else
- string # FFI does the job
- end
- end
-
- def add_byte_order_mask(string)
- "\uFEFF".encode(string.encoding) + string
- end
-
- def terminate_string!(string)
- string << "\0\0".force_encoding(string.encoding)
- end
-
- def get_string_utf_16(ptr)
- length = 0
- length += 2 until ptr.get_bytes(length, 2) == "\0\0"
- ptr.get_bytes(0, length)
- end
- end
- end
- end
-end
View
4 test/test_active_record.rb
@@ -21,9 +21,7 @@ def self.down
end
end
-class User < ActiveRecord::Base
-
-end
+class User < ActiveRecord::Base; end
class TestActiveRecord < Test::Unit::TestCase
def setup
Please sign in to comment.
Something went wrong with that request. Please try again.