Skip to content

Commit

Permalink
ease vtable declaration using SQLite3::vtable
Browse files Browse the repository at this point in the history
  • Loading branch information
lionelperrin committed Apr 1, 2016
1 parent 410d6b1 commit 2054e2e
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 7 deletions.
6 changes: 5 additions & 1 deletion ext/sqlite3/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ static int xCreate(sqlite3* db, VALUE *module_name,
const char* module_name_cstr = (const char*)StringValuePtr(*module_name);
const char* table_name_cstr = (const char*)argv[2];

// method will raise in case of error: no need to use pzErr
*pzErr = NULL;

// lookup for ruby class named like <module_id>::<table_name>
module_id = rb_intern( module_name_cstr );
module = rb_const_get(rb_cObject, module_id);
Expand All @@ -57,8 +60,9 @@ static int xCreate(sqlite3* db, VALUE *module_name,
sql_stmt = rb_str_export_to_enc(sql_stmt, rb_utf8_encoding());
}
#endif
if ( sqlite3_declare_vtab(db, StringValuePtr(sql_stmt)) )
if ( sqlite3_declare_vtab(db, StringValuePtr(sql_stmt)) ) {
rb_raise(rb_eArgError, "fail to declare virtual table");
}

return SQLITE_OK;
}
Expand Down
53 changes: 53 additions & 0 deletions lib/sqlite3/vtable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
module SQLite3Vtable
# this module contains the vtable classes generated
# using SQLite3::vtable method
end

module SQLite3
class VTableInterface
#this method is needed to declare the type of each column to sqlite
def create_statement
fail 'VTableInterface#create_statement not implemented'
end

#called before each statement
def open
# do nothing by default
end

#called before each statement
def close
# do nothing by default
end

# called to retrieve a new row
def next
fail 'VTableInterface#next not implemented'
end
end

def self.vtable(db, table_name, table_columns)
if SQLite3Vtable.const_defined?(table_name, inherit = false)
raise "'#{table_name}' already declared"
end

klass = Class.new(VTableInterface) do
def initialize(enumerable)
@enumerable = enumerable
end
def create_statement
"create table #{table_name}(#{table_columns})"
end
def next
@enumerable.next
end
end

begin
SQLite3Vtable.const_set(table_name, klass)
rescue NameError
raise "'#{table_name}' must be a valid ruby constant name"
end
db.execute("create virtual table #{table_name} using SQLite3Vtable")
end
end
8 changes: 2 additions & 6 deletions test/test_vtable.rb
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
require "helper"
require 'sqlite3/vtable'

#the ruby module name should be the one given to sqlite when creating the virtual table.
module RubyModule
class TestVTable
class TestVTable < VTableInterface
def initialize
@str = "A"*1500
end
Expand Down Expand Up @@ -32,11 +33,6 @@ def next
end

end

#required method for vtable
#called after each statement
def close
end
end
end

Expand Down

0 comments on commit 2054e2e

Please sign in to comment.