Skip to content

Instantly share code, notes, and snippets.

@threez
Last active August 29, 2015 14:16
Show Gist options
  • Save threez/d5e0a53f331e88256b3f to your computer and use it in GitHub Desktop.
Save threez/d5e0a53f331e88256b3f to your computer and use it in GitHub Desktop.
minimal sqlite3 driver
#!/usb/bin/env ruby
require 'fiddle'
require 'fiddle/import'
require 'pp'
module Sqlite3
SQLITE_OK = 0
module Driver
extend Fiddle::Importer
dlload 'libsqlite3.dylib'
extern 'char* sqlite3_errstr(int)'
extern 'int sqlite3_open(const char *, sqlite3**)'
extern 'int sqlite3_exec(sqlite3*, const char *, void *, void *, char **)'
extern 'int sqlite3_close(sqlite3*)'
end
class Error < StandardError; end
class Connection
include Fiddle
CALLBACK =[ TYPE_VOIDP, TYPE_INT, TYPE_VOIDP, TYPE_VOIDP ].freeze
def initialize(uri)
@db = Pointer.malloc(SIZEOF_VOIDP)
check Driver.sqlite3_open(uri.to_s, @db.ref)
end
def close
check Driver.sqlite3_close(@db)
end
def exec(stmt, &handler)
@errptr = Pointer.malloc(SIZEOF_VOIDP)
rownr = 0
column_cache = {}
cb = Closure::BlockCaller.new(TYPE_INT, CALLBACK) do |_, argc, argv, columns|
row = {}
argc.times do |i|
column = column_cache[i] || begin
column_cache[i] = (columns + i * SIZEOF_VOIDP).ptr.to_s
.downcase.to_sym
end
value = (argv + i * SIZEOF_VOIDP).ptr.to_s
if value =~ /^\d+\.\d+$/
value = value.to_f
elsif value =~ /^\d+$/
value = value.to_i
end
row[column] = value
end
handler.call(row, rownr)
rownr += 1
0
end if block_given?
if Driver.sqlite3_exec(@db, stmt, cb, 0, @errptr.ref) != SQLITE_OK
fail Error, @errptr.to_s
end
ensure
@errptr.free
end
def check(error_code)
if error_code != SQLITE_OK
fail Error, Driver.sqlite3_errstr(error_code).to_s
end
end
end
end
connection = Sqlite3::Connection.new(":memory:")
connection.exec "CREATE TABLE COMPANY(" +
"ID INT PRIMARY KEY NOT NULL," +
"NAME TEXT NOT NULL," +
"AGE INT NOT NULL," +
"ADDRESS CHAR(50)," +
"SALARY REAL );"
connection.exec "INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
"VALUES (1, 'Paul', 32, 'California', 20000.00 ); " +
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY) " +
"VALUES (2, 'Allen', 25, 'Texas', 15000.00 ); " +
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" +
"VALUES (3, 'Teddy', 23, 'Norway', 20000.00 );" +
"INSERT INTO COMPANY (ID,NAME,AGE,ADDRESS,SALARY)" +
"VALUES (4, 'Mark', 25, 'Rich-Mond', 65000.00 );"
connection.exec "SELECT * from COMPANY" do |row, i|
p [i, row]
end
connection.close
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment