Skip to content

Commit

Permalink
adding statements and whatnot
Browse files Browse the repository at this point in the history
  • Loading branch information
tenderlove committed Jan 20, 2010
1 parent 2ab9c72 commit f7580a7
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 4 deletions.
35 changes: 31 additions & 4 deletions ext/deebee/deebee.c
Expand Up @@ -2,7 +2,6 @@


VALUE mSqlite3; VALUE mSqlite3;
VALUE cDeeBee; VALUE cDeeBee;
VALUE cDeeBeeStatement;


static VALUE libversion(VALUE klass) static VALUE libversion(VALUE klass)
{ {
Expand All @@ -13,7 +12,7 @@ static VALUE open_connection(VALUE klass, VALUE file)
{ {
sqlite3 * database; sqlite3 * database;
if(SQLITE_OK != sqlite3_open(StringValuePtr(file), &database)) { if(SQLITE_OK != sqlite3_open(StringValuePtr(file), &database)) {
rb_raise(rb_eRuntimeError, "fixme!"); rb_raise(rb_eRuntimeError, "%s", sqlite3_errmsg(database));
} }


return Data_Wrap_Struct(klass, 0, 0, database); return Data_Wrap_Struct(klass, 0, 0, database);
Expand All @@ -36,16 +35,44 @@ static VALUE prepare(VALUE self, VALUE sql)
if(SQLITE_OK != status) if(SQLITE_OK != status)
rb_raise(rb_eRuntimeError, "%s", sqlite3_errmsg(ctx)); rb_raise(rb_eRuntimeError, "%s", sqlite3_errmsg(ctx));


return Data_Wrap_Struct(cDeeBeeStatement, 0, 0, stmt); VALUE statement = Data_Wrap_Struct(cDeeBeeStatement, 0, 0, stmt);
rb_iv_set(statement, "@connection", self);

return statement;
}

int enc_cb(void * _self, int columns, char **data, char **names)
{
VALUE self = (VALUE)_self;
int index = rb_enc_find_index("UTF-8");
VALUE enc = rb_str_new2(data[0]);
rb_enc_associate_index(enc, index);

rb_iv_set(self, "@encoding", enc);

return 0;
}

static VALUE encoding_str(VALUE self)
{
sqlite3 * ctx;

Data_Get_Struct(self, sqlite3, ctx);

sqlite3_exec(ctx, "PRAGMA encoding", enc_cb, (void *)self, NULL);

return rb_iv_get(self, "@encoding");
} }


void Init_deebee() void Init_deebee()
{ {
mSqlite3 = rb_define_module("SQLite3"); mSqlite3 = rb_define_module("SQLite3");
cDeeBee = rb_define_class_under(mSqlite3, "DeeBee", rb_cObject); cDeeBee = rb_define_class_under(mSqlite3, "DeeBee", rb_cObject);
cDeeBeeStatement = rb_define_class_under(cDeeBee, "Statement", rb_cObject);
init_deebee_statement();


rb_define_singleton_method(cDeeBee, "libversion", libversion, 0); rb_define_singleton_method(cDeeBee, "libversion", libversion, 0);
rb_define_singleton_method(cDeeBee, "open", open_connection, 1); rb_define_singleton_method(cDeeBee, "open", open_connection, 1);
rb_define_method(cDeeBee, "prepare", prepare, 1); rb_define_method(cDeeBee, "prepare", prepare, 1);
rb_define_private_method(cDeeBee, "encoding_str", encoding_str, 0);
} }
5 changes: 5 additions & 0 deletions ext/deebee/deebee.h
Expand Up @@ -4,4 +4,9 @@
#include <ruby.h> #include <ruby.h>
#include <sqlite3.h> #include <sqlite3.h>


extern VALUE mSqlite3;
extern VALUE cDeeBee;

#include <deebee_statement.h>

#endif #endif
56 changes: 56 additions & 0 deletions ext/deebee/deebee_statement.c
@@ -0,0 +1,56 @@
#include <deebee.h>

VALUE cDeeBeeStatement;

static VALUE each(VALUE self)
{
sqlite3_stmt *stmt;

Data_Get_Struct(self, sqlite3_stmt, stmt);
int value = sqlite3_step(stmt);
while(value != SQLITE_DONE) {
switch(value) {
case SQLITE_ROW:
{
int length = sqlite3_column_count(stmt);
VALUE list = rb_ary_new2(length);

int i;
for(i = 0; i < length; i++) {
switch(sqlite3_column_type(stmt, i)) {
case SQLITE_INTEGER:
rb_ary_push(list, INT2NUM(sqlite3_column_int(stmt, i)));
break;
case SQLITE_FLOAT:
rb_ary_push(list, rb_float_new(sqlite3_column_double(stmt, i)));
break;
case SQLITE_TEXT:
rb_ary_push(list, rb_str_new2(sqlite3_column_text(stmt, i)));
break;
case SQLITE_BLOB:
rb_ary_push(list, rb_str_new2(sqlite3_column_blob(stmt, i)));
break;
case SQLITE_NULL:
rb_ary_push(list, Qnil);
break;
default:
rb_raise(rb_eRuntimeError, "oh no!");
}
}
rb_yield(list);
}
break;
default:
rb_raise(rb_eRuntimeError, "oh no!");
}
value = sqlite3_step(stmt);
}
return self;
}

void init_deebee_statement()
{
cDeeBeeStatement = rb_define_class_under(cDeeBee, "Statement", rb_cObject);

rb_define_method(cDeeBeeStatement, "each", each, 0);
}
10 changes: 10 additions & 0 deletions ext/deebee/deebee_statement.h
@@ -0,0 +1,10 @@
#ifndef DEEBEE_STATEMENT
#define DEEBEE_STATEMENT

#include <deebee.h>

extern VALUE cDeeBeeStatement;

void init_deebee_statement();

#endif
5 changes: 5 additions & 0 deletions lib/deebee.rb
@@ -1,7 +1,12 @@
require 'deebee/deebee' require 'deebee/deebee'
require 'deebee/statement'


module SQLite3 module SQLite3
class DeeBee class DeeBee
VERSION = '1.0.0' VERSION = '1.0.0'

def encoding
Encoding.find(encoding_str)
end
end end
end end
7 changes: 7 additions & 0 deletions lib/deebee/statement.rb
@@ -0,0 +1,7 @@
module SQLite3
class DeeBee
class Statement
include Enumerable
end
end
end
6 changes: 6 additions & 0 deletions test/test_deebee.rb
Expand Up @@ -16,4 +16,10 @@ def test_prepare
stmt = db.prepare('PRAGMA encoding') stmt = db.prepare('PRAGMA encoding')
assert_instance_of(SQLite3::DeeBee::Statement, stmt); assert_instance_of(SQLite3::DeeBee::Statement, stmt);
end end

def test_encoding
enc = Encoding.find('UTF-8')
db = SQLite3::DeeBee.open(File.join(Dir.tmpdir, 'foo.db'))
assert_equal enc, db.encoding
end
end end
13 changes: 13 additions & 0 deletions test/test_statement.rb
@@ -0,0 +1,13 @@
require "test/unit"
require "deebee"
require 'tmpdir'

class TestStatement < Test::Unit::TestCase
def test_step
db = SQLite3::DeeBee.open(File.join(Dir.tmpdir, 'foo.db'))
stmt = db.prepare('PRAGMA encoding')
called = false
stmt.each { |row| called = true }
assert called
end
end

0 comments on commit f7580a7

Please sign in to comment.