Skip to content

Commit 2054e2e

Browse files
committed
ease vtable declaration using SQLite3::vtable
1 parent 410d6b1 commit 2054e2e

File tree

3 files changed

+60
-7
lines changed

3 files changed

+60
-7
lines changed

ext/sqlite3/module.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ static int xCreate(sqlite3* db, VALUE *module_name,
3636
const char* module_name_cstr = (const char*)StringValuePtr(*module_name);
3737
const char* table_name_cstr = (const char*)argv[2];
3838

39+
// method will raise in case of error: no need to use pzErr
40+
*pzErr = NULL;
41+
3942
// lookup for ruby class named like <module_id>::<table_name>
4043
module_id = rb_intern( module_name_cstr );
4144
module = rb_const_get(rb_cObject, module_id);
@@ -57,8 +60,9 @@ static int xCreate(sqlite3* db, VALUE *module_name,
5760
sql_stmt = rb_str_export_to_enc(sql_stmt, rb_utf8_encoding());
5861
}
5962
#endif
60-
if ( sqlite3_declare_vtab(db, StringValuePtr(sql_stmt)) )
63+
if ( sqlite3_declare_vtab(db, StringValuePtr(sql_stmt)) ) {
6164
rb_raise(rb_eArgError, "fail to declare virtual table");
65+
}
6266

6367
return SQLITE_OK;
6468
}

lib/sqlite3/vtable.rb

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module SQLite3Vtable
2+
# this module contains the vtable classes generated
3+
# using SQLite3::vtable method
4+
end
5+
6+
module SQLite3
7+
class VTableInterface
8+
#this method is needed to declare the type of each column to sqlite
9+
def create_statement
10+
fail 'VTableInterface#create_statement not implemented'
11+
end
12+
13+
#called before each statement
14+
def open
15+
# do nothing by default
16+
end
17+
18+
#called before each statement
19+
def close
20+
# do nothing by default
21+
end
22+
23+
# called to retrieve a new row
24+
def next
25+
fail 'VTableInterface#next not implemented'
26+
end
27+
end
28+
29+
def self.vtable(db, table_name, table_columns)
30+
if SQLite3Vtable.const_defined?(table_name, inherit = false)
31+
raise "'#{table_name}' already declared"
32+
end
33+
34+
klass = Class.new(VTableInterface) do
35+
def initialize(enumerable)
36+
@enumerable = enumerable
37+
end
38+
def create_statement
39+
"create table #{table_name}(#{table_columns})"
40+
end
41+
def next
42+
@enumerable.next
43+
end
44+
end
45+
46+
begin
47+
SQLite3Vtable.const_set(table_name, klass)
48+
rescue NameError
49+
raise "'#{table_name}' must be a valid ruby constant name"
50+
end
51+
db.execute("create virtual table #{table_name} using SQLite3Vtable")
52+
end
53+
end

test/test_vtable.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
require "helper"
2+
require 'sqlite3/vtable'
23

34
#the ruby module name should be the one given to sqlite when creating the virtual table.
45
module RubyModule
5-
class TestVTable
6+
class TestVTable < VTableInterface
67
def initialize
78
@str = "A"*1500
89
end
@@ -32,11 +33,6 @@ def next
3233
end
3334

3435
end
35-
36-
#required method for vtable
37-
#called after each statement
38-
def close
39-
end
4036
end
4137
end
4238

0 commit comments

Comments
 (0)