swift 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/pool.cc ADDED
@@ -0,0 +1,89 @@
1
+ #include "pool.h"
2
+
3
+ VALUE cSwiftPool;
4
+
5
+ static void pool_free(dbi::ConnectionPool *self) {
6
+ if (self) delete self;
7
+ }
8
+
9
+ VALUE pool_alloc(VALUE klass) {
10
+ dbi::ConnectionPool *pool = 0;
11
+ return Data_Wrap_Struct(klass, 0, pool_free, pool);
12
+ }
13
+
14
+ static dbi::ConnectionPool* pool_handle(VALUE self) {
15
+ dbi::ConnectionPool *pool;
16
+ Data_Get_Struct(self, dbi::ConnectionPool, pool);
17
+ if (!pool) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super ?");
18
+ return pool;
19
+ }
20
+
21
+ // TODO: Remove unnecessary assignments. See Adapter.
22
+ VALUE pool_init(VALUE self, VALUE n, VALUE options) {
23
+ VALUE db = rb_hash_aref(options, ID2SYM(rb_intern("db")));
24
+ VALUE host = rb_hash_aref(options, ID2SYM(rb_intern("host")));
25
+ VALUE port = rb_hash_aref(options, ID2SYM(rb_intern("port")));
26
+ VALUE user = rb_hash_aref(options, ID2SYM(rb_intern("user")));
27
+ VALUE driver = rb_hash_aref(options, ID2SYM(rb_intern("driver")));
28
+ VALUE password = rb_hash_aref(options, ID2SYM(rb_intern("password")));
29
+ VALUE zone = rb_hash_aref(options, ID2SYM(rb_intern("timezone")));
30
+
31
+ if (NIL_P(db)) rb_raise(eSwiftArgumentError, "Pool#new called without :db");
32
+ if (NIL_P(driver)) rb_raise(eSwiftArgumentError, "#new called without :driver");
33
+
34
+ user = NIL_P(user) ? rb_str_new2(getlogin()) : user;
35
+ if (NUM2INT(n) < 1) rb_raise(eSwiftArgumentError, "Pool#new called with invalid pool size.");
36
+
37
+ try {
38
+ DATA_PTR(self) = new dbi::ConnectionPool(
39
+ NUM2INT(n),
40
+ CSTRING(driver),
41
+ CSTRING(user),
42
+ CSTRING(password),
43
+ CSTRING(db),
44
+ CSTRING(host),
45
+ CSTRING(port)
46
+ );
47
+ }
48
+ CATCH_DBI_EXCEPTIONS();
49
+ return Qnil;
50
+ }
51
+
52
+ void pool_callback(dbi::AbstractResultSet *result) {
53
+ VALUE callback = (VALUE)result->context;
54
+ // NOTE ResultSet will be free'd by the underlying connection pool dispatcher ib dbic++
55
+ if (!NIL_P(callback)) rb_proc_call(callback, rb_ary_new3(1, Data_Wrap_Struct(cSwiftResult, 0, 0, result)));
56
+ }
57
+
58
+ VALUE pool_execute(int argc, VALUE *argv, VALUE self) {
59
+ int n;
60
+ VALUE sql;
61
+ VALUE bind_values;
62
+ VALUE callback;
63
+ VALUE request = Qnil;
64
+
65
+ dbi::ConnectionPool *pool = pool_handle(self);
66
+ rb_scan_args(argc, argv, "1*&", &sql, &bind_values, &callback);
67
+
68
+ if (NIL_P(callback)) rb_raise(eSwiftArgumentError, "No block given in Pool#execute");
69
+
70
+ try {
71
+ Query query;
72
+ query_bind_values(&query, bind_values);
73
+ request = request_alloc(cSwiftRequest);
74
+ DATA_PTR(request) = pool->execute(CSTRING(sql), query.bind, pool_callback, (void*)callback);
75
+ return request;
76
+ }
77
+ CATCH_DBI_EXCEPTIONS();
78
+ }
79
+
80
+ void init_swift_pool() {
81
+ VALUE mSwift = rb_define_module("Swift");
82
+ VALUE mDB = rb_define_module_under(mSwift, "DB");
83
+ cSwiftPool = rb_define_class_under(mDB, "Pool", rb_cObject);
84
+
85
+ rb_define_alloc_func(cSwiftPool, pool_alloc);
86
+
87
+ rb_define_method(cSwiftPool, "initialize", RUBY_METHOD_FUNC(pool_init), 2);
88
+ rb_define_method(cSwiftPool, "execute", RUBY_METHOD_FUNC(pool_execute), -1);
89
+ }
data/ext/pool.h ADDED
@@ -0,0 +1,8 @@
1
+ #ifndef SWIFT_POOL_H
2
+ #define SWIFT_POOL_H
3
+
4
+ #include "swift.h"
5
+
6
+ void init_swift_pool();
7
+
8
+ #endif
data/ext/query.cc ADDED
@@ -0,0 +1,38 @@
1
+ #include "query.h"
2
+
3
+ VALUE query_execute(Query *query) {
4
+ return UINT2NUM(
5
+ query->bind.size() == 0
6
+ ? query->handle->conn()->execute(query->sql)
7
+ : query->handle->conn()->execute(query->sql, query->bind)
8
+ );
9
+ }
10
+
11
+ VALUE query_execute_statement(Query *query) {
12
+ return UINT2NUM(
13
+ query->bind.size() == 0
14
+ ? query->statement->execute()
15
+ : query->statement->execute(query->bind)
16
+ );
17
+ }
18
+
19
+ void query_bind_values(Query *query, VALUE bind_values) {
20
+ for (int i = 0; i < RARRAY_LEN(bind_values); i++) {
21
+ VALUE bind_value = rb_ary_entry(bind_values, i);
22
+
23
+ if (bind_value == Qnil) {
24
+ query->bind.push_back(dbi::PARAM(dbi::null()));
25
+ }
26
+ else if (rb_obj_is_kind_of(bind_value, rb_cIO) == Qtrue || rb_obj_is_kind_of(bind_value, cStringIO) == Qtrue) {
27
+ bind_value = rb_funcall(bind_value, rb_intern("read"), 0);
28
+ query->bind.push_back(dbi::PARAM_BINARY((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
29
+ }
30
+ else {
31
+ bind_value = TO_S(bind_value);
32
+ if (strcmp(rb_enc_get(bind_value)->name, "UTF-8") != 0)
33
+ bind_value = rb_str_encode(bind_value, rb_str_new2("UTF-8"), 0, Qnil);
34
+ query->bind.push_back(dbi::PARAM((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
35
+ }
36
+ }
37
+ }
38
+
data/ext/query.h ADDED
@@ -0,0 +1,17 @@
1
+ #ifndef SWIFT_QUERY_H
2
+ #define SWIFT_QUERY_H
3
+
4
+ #include "swift.h"
5
+
6
+ struct Query {
7
+ char *sql;
8
+ dbi::Handle *handle;
9
+ dbi::AbstractStatement *statement;
10
+ dbi::ResultRow bind;
11
+ };
12
+
13
+ VALUE query_execute(Query*);
14
+ VALUE query_execute_statement(Query*);
15
+ void query_bind_values(Query*, VALUE);
16
+
17
+ #endif
data/ext/request.cc ADDED
@@ -0,0 +1,44 @@
1
+ #include "request.h"
2
+
3
+ VALUE cSwiftRequest;
4
+
5
+ static void request_free(dbi::Request *request) {
6
+ if(request) delete request;
7
+ }
8
+
9
+ VALUE request_alloc(VALUE klass) {
10
+ dbi::Request *request = 0;
11
+ return Data_Wrap_Struct(klass, 0, request_free, request);
12
+ }
13
+
14
+ static dbi::Request* request_handle(VALUE self) {
15
+ dbi::Request *request;
16
+ Data_Get_Struct(self, dbi::Request, request);
17
+ if (!request) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super ?");
18
+ return request;
19
+ }
20
+
21
+ VALUE request_socket(VALUE self) {
22
+ dbi::Request *request = request_handle(self);
23
+ try {
24
+ return INT2NUM(request->socket());
25
+ }
26
+ CATCH_DBI_EXCEPTIONS();
27
+ }
28
+
29
+ VALUE request_process(VALUE self) {
30
+ dbi::Request *request = request_handle(self);
31
+ try {
32
+ return request->process() ? Qtrue : Qfalse;
33
+ }
34
+ CATCH_DBI_EXCEPTIONS();
35
+ }
36
+
37
+ void init_swift_request() {
38
+ VALUE mSwift = rb_define_module("Swift");
39
+ cSwiftRequest = rb_define_class_under(mSwift, "Request", rb_cObject);
40
+
41
+ rb_define_alloc_func(cSwiftRequest, request_alloc);
42
+ rb_define_method(cSwiftRequest, "socket", RUBY_METHOD_FUNC(request_socket), 0);
43
+ rb_define_method(cSwiftRequest, "process", RUBY_METHOD_FUNC(request_process), 0);
44
+ }
data/ext/request.h ADDED
@@ -0,0 +1,10 @@
1
+ #ifndef SWIFT_REQUEST_H
2
+ #define SWIFT_REQUEST_H
3
+
4
+ #include "swift.h"
5
+
6
+ extern VALUE cSwiftRequest;
7
+ VALUE request_alloc(VALUE klass);
8
+ void init_swift_request();
9
+
10
+ #endif
data/ext/result.cc ADDED
@@ -0,0 +1,246 @@
1
+ #include "result.h"
2
+
3
+ VALUE cSwiftResult;
4
+ VALUE cDateTime;
5
+ VALUE cStringIO;
6
+ VALUE cBigDecimal;
7
+
8
+ VALUE fNew, fNewBang;
9
+
10
+ uint64_t epoch_ajd_n, epoch_ajd_d;
11
+ VALUE daysecs, sg;
12
+
13
+ void result_free(dbi::AbstractResultSet *result) {
14
+ if (result) {
15
+ result->cleanup();
16
+ delete result;
17
+ }
18
+ }
19
+
20
+ VALUE result_alloc(VALUE klass) {
21
+ dbi::AbstractResultSet *result = 0;
22
+ return Data_Wrap_Struct(klass, 0, result_free, result);
23
+ }
24
+
25
+ // TODO:
26
+ static VALUE result_clone(VALUE self) {
27
+ rb_raise(eSwiftRuntimeError, "clone is not allowed.");
28
+ }
29
+
30
+ // TODO:
31
+ static VALUE result_dup(VALUE self) {
32
+ rb_raise(eSwiftRuntimeError, "dup is not allowed.");
33
+ }
34
+
35
+ VALUE result_each(VALUE self) {
36
+ uint64_t length;
37
+ const char *data;
38
+
39
+ dbi::AbstractResultSet *result = result_handle(self);
40
+ VALUE scheme = rb_iv_get(self, "@scheme");
41
+
42
+ try {
43
+ VALUE fields = rb_ary_new();
44
+ std::vector<string> result_fields = result->fields();
45
+ std::vector<int> result_types = result->types();
46
+ for (uint32_t i = 0; i < result_fields.size(); i++) {
47
+ rb_ary_push(fields, ID2SYM(rb_intern(result_fields[i].c_str())));
48
+ }
49
+
50
+ result->seek(0);
51
+ for (uint32_t row = 0; row < result->rows(); row++) {
52
+ VALUE tuple = rb_hash_new();
53
+ for (uint32_t column = 0; column < result->columns(); column++) {
54
+ data = (const char*)result->read(row, column, &length);
55
+ if (data) {
56
+ rb_hash_aset(
57
+ tuple,
58
+ rb_ary_entry(fields, column),
59
+ typecast_field(result_types[column], data, length)
60
+ );
61
+ }
62
+ else {
63
+ rb_hash_aset(tuple, rb_ary_entry(fields, column), Qnil);
64
+ }
65
+ } // column loop
66
+ NIL_P(scheme) ? rb_yield(tuple) : rb_yield(rb_funcall(scheme, rb_intern("load"), 1, tuple));
67
+ } // row loop
68
+ }
69
+ CATCH_DBI_EXCEPTIONS();
70
+
71
+ return Qnil;
72
+ }
73
+
74
+ dbi::AbstractResultSet* result_handle(VALUE self) {
75
+ dbi::AbstractResultSet *result;
76
+ Data_Get_Struct(self, dbi::AbstractResultSet, result);
77
+ if (!result) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?");
78
+
79
+ return result;
80
+ }
81
+
82
+ static VALUE result_finish(VALUE self) {
83
+ dbi::AbstractResultSet *result = result_handle(self);
84
+ try {
85
+ result->finish();
86
+ }
87
+ CATCH_DBI_EXCEPTIONS();
88
+ }
89
+
90
+ // Calculates local offset at a given time, including dst.
91
+ size_t client_tzoffset(uint64_t local, int isdst) {
92
+ struct tm tm;
93
+ gmtime_r((const time_t*)&local, &tm);
94
+ return local + (isdst ? 3600 : 0) - mktime(&tm);
95
+ }
96
+
97
+ // pinched from do_postgres
98
+ static void reduce(uint64_t *numerator, uint64_t *denominator) {
99
+ uint64_t a, b, c;
100
+ a = *numerator;
101
+ b = *denominator;
102
+ while (a) {
103
+ c = a; a = b % a; b = c;
104
+ }
105
+ *numerator = *numerator / b;
106
+ *denominator = *denominator / b;
107
+ }
108
+
109
+ VALUE typecast_datetime(const char *data, uint64_t len) {
110
+ struct tm tm;
111
+ uint64_t epoch, adjust, offset;
112
+
113
+ double usec = 0;
114
+ char tzsign = 0;
115
+ int tzhour = 0, tzmin = 0;
116
+
117
+ memset(&tm, 0, sizeof(struct tm));
118
+ if (strchr(data, '.')) {
119
+ sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%lf%c%02d:%02d",
120
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec,
121
+ &usec, &tzsign, &tzhour, &tzmin);
122
+ }
123
+ else {
124
+ sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%c%02d:%02d",
125
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec,
126
+ &tzsign, &tzhour, &tzmin);
127
+ }
128
+
129
+ tm.tm_year -= 1900;
130
+ tm.tm_mon -= 1;
131
+ tm.tm_isdst = -1;
132
+ if (tm.tm_mday > 0) {
133
+ epoch = mktime(&tm);
134
+ adjust = client_tzoffset(epoch, tm.tm_isdst);
135
+ offset = adjust;
136
+
137
+ if (tzsign == '+' || tzsign == '-') {
138
+ offset = tzsign == '+'
139
+ ? (time_t)tzhour * 3600 + (time_t)tzmin * 60
140
+ : (time_t)tzhour * -3600 + (time_t)tzmin * -60;
141
+ }
142
+
143
+ // 32bit platforms are for weenies
144
+ uint64_t ajd_n = (epoch + adjust - offset), ajd_d = 86400L;
145
+ reduce(&ajd_n, &ajd_d);
146
+ ajd_n = epoch_ajd_n*ajd_d + ajd_n*epoch_ajd_d;
147
+ ajd_d = epoch_ajd_d*ajd_d;
148
+ reduce(&ajd_n, &ajd_d);
149
+
150
+ VALUE ajd = rb_rational_new(SIZET2NUM(ajd_n), SIZET2NUM(ajd_d));
151
+ return rb_funcall(cDateTime, fNewBang, 3, ajd, rb_rational_new(INT2FIX(offset), daysecs), sg);
152
+ }
153
+
154
+ // TODO: throw a warning ?
155
+ return rb_str_new(data, len);
156
+ }
157
+
158
+ VALUE typecast_field(int type, const char *data, uint64_t length) {
159
+ switch(type) {
160
+ case DBI_TYPE_BOOLEAN:
161
+ return strcmp(data, "t") == 0 || strcmp(data, "1") == 0 ? Qtrue : Qfalse;
162
+ case DBI_TYPE_INT:
163
+ return rb_cstr2inum(data, 10);
164
+ case DBI_TYPE_BLOB:
165
+ return rb_funcall(cStringIO, fNew, 1, rb_str_new(data, length));
166
+ case DBI_TYPE_TEXT:
167
+ return rb_enc_str_new(data, length, rb_utf8_encoding());
168
+ case DBI_TYPE_TIME:
169
+ return typecast_datetime(data, length);
170
+ case DBI_TYPE_NUMERIC:
171
+ return rb_funcall(cBigDecimal, fNew, 1, rb_str_new2(data));
172
+ case DBI_TYPE_FLOAT:
173
+ return rb_float_new(atof(data));
174
+ }
175
+ }
176
+
177
+ VALUE result_insert_id(VALUE self) {
178
+ dbi::AbstractResultSet *result = result_handle(self);
179
+ try {
180
+ return SIZET2NUM(result->lastInsertID());
181
+ }
182
+ CATCH_DBI_EXCEPTIONS();
183
+ return Qnil;
184
+ }
185
+
186
+ VALUE result_rows(VALUE self) {
187
+ dbi::AbstractResultSet *result = result_handle(self);
188
+ try {
189
+ return SIZET2NUM(result->rows());
190
+ }
191
+ CATCH_DBI_EXCEPTIONS();
192
+ }
193
+
194
+ VALUE result_columns(VALUE self) {
195
+ dbi::AbstractResultSet *result = result_handle(self);
196
+ try {
197
+ return SIZET2NUM(result->columns());
198
+ }
199
+ CATCH_DBI_EXCEPTIONS();
200
+ }
201
+
202
+ VALUE result_fields(VALUE self) {
203
+ dbi::AbstractResultSet *result = result_handle(self);
204
+ try {
205
+ std::vector<string> result_fields = result->fields();
206
+ VALUE fields = rb_ary_new();
207
+ for (int i = 0; i < result_fields.size(); i++)
208
+ rb_ary_push(fields, rb_str_new2(result_fields[i].c_str()));
209
+ return fields;
210
+ }
211
+ CATCH_DBI_EXCEPTIONS();
212
+ }
213
+
214
+ void init_swift_result() {
215
+ rb_require("bigdecimal");
216
+ rb_require("stringio");
217
+ rb_require("date");
218
+
219
+ VALUE mSwift = rb_define_module("Swift");
220
+ cSwiftResult = rb_define_class_under(mSwift, "Result", rb_cObject);
221
+ cDateTime = CONST_GET(rb_mKernel, "DateTime");
222
+ cStringIO = CONST_GET(rb_mKernel, "StringIO");
223
+ cBigDecimal = CONST_GET(rb_mKernel, "BigDecimal");
224
+
225
+ fNew = rb_intern("new");
226
+ fNewBang = rb_intern("new!");
227
+
228
+ rb_define_alloc_func(cSwiftResult, result_alloc);
229
+ rb_include_module(cSwiftResult, CONST_GET(rb_mKernel, "Enumerable"));
230
+
231
+ rb_define_method(cSwiftResult, "clone", RUBY_METHOD_FUNC(result_clone), 0);
232
+ rb_define_method(cSwiftResult, "dup", RUBY_METHOD_FUNC(result_dup), 0);
233
+ rb_define_method(cSwiftResult, "each", RUBY_METHOD_FUNC(result_each), 0);
234
+ rb_define_method(cSwiftResult, "finish", RUBY_METHOD_FUNC(result_finish), 0);
235
+ rb_define_method(cSwiftResult, "insert_id", RUBY_METHOD_FUNC(result_insert_id), 0);
236
+ rb_define_method(cSwiftResult, "rows", RUBY_METHOD_FUNC(result_rows), 0);
237
+ rb_define_method(cSwiftResult, "columns", RUBY_METHOD_FUNC(result_columns), 0);
238
+ rb_define_method(cSwiftResult, "fields", RUBY_METHOD_FUNC(result_fields), 0);
239
+
240
+ // typecast_datetime setup.
241
+ epoch_ajd_d = 2;
242
+ epoch_ajd_n = 4881175L; // 1970-01-01 00:00:00 is 2440587.5 in ajd
243
+ daysecs = SIZET2NUM(86400L);
244
+ sg = SIZET2NUM(2299161L); // day of calendar reform Date::ITALY
245
+ }
246
+
data/ext/result.h ADDED
@@ -0,0 +1,17 @@
1
+ #ifndef SWIFT_RESULT_H
2
+ #define SWIFT_RESULT_H
3
+
4
+ #include "swift.h"
5
+
6
+ extern VALUE cSwiftResult;
7
+ extern VALUE cStringIO;
8
+
9
+ void init_swift_result();
10
+ void result_free(dbi::AbstractResultSet*);
11
+ VALUE result_each(VALUE);
12
+ dbi::AbstractResultSet* result_handle(VALUE);
13
+
14
+ VALUE typecast_field(int, const char*, uint64_t);
15
+ VALUE typecast_datetime(const char*, uint64_t);
16
+
17
+ #endif
data/ext/statement.cc ADDED
@@ -0,0 +1,87 @@
1
+ #include "statement.h"
2
+ #include "adapter.h"
3
+ #include "result.h"
4
+ #include "query.h"
5
+
6
+ VALUE cSwiftStatement;
7
+
8
+ void statement_free(dbi::AbstractStatement *statement) {
9
+ if (statement) {
10
+ statement->cleanup();
11
+ delete statement;
12
+ }
13
+ }
14
+
15
+ VALUE statement_alloc(VALUE klass) {
16
+ dbi::AbstractStatement *statement = 0;
17
+ return Data_Wrap_Struct(klass, 0, statement_free, statement);
18
+ }
19
+
20
+ dbi::AbstractStatement* statement_handle(VALUE self) {
21
+ dbi::AbstractStatement *handle;
22
+ Data_Get_Struct(self, dbi::AbstractStatement, handle);
23
+ if (!handle) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?");
24
+
25
+ return handle;
26
+ }
27
+
28
+ // TODO: Change bind_values to an array in the interface? Avoid array -> splat -> array.
29
+ static VALUE statement_execute(int argc, VALUE *argv, VALUE self) {
30
+ VALUE bind_values, block;
31
+ rb_scan_args(argc, argv, "0*&", &bind_values, &block);
32
+
33
+ dbi::AbstractStatement *statement = (dbi::AbstractStatement*)statement_handle(self);
34
+ try {
35
+ Query query;
36
+ query.statement = statement;
37
+ if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values);
38
+ if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(statement->command(), query.bind));
39
+
40
+ // TODO: http://redmine.ruby-lang.org/issues/show/3762
41
+ // rb_thread_blocking_region and C++ exceptions don't mix in 1.9.2.
42
+ // rb_thread_blocking_region(((VALUE (*)(void*))query_execute_statement), &query, RUBY_UBF_IO, 0);
43
+ query_execute_statement(&query);
44
+ }
45
+ CATCH_DBI_EXCEPTIONS();
46
+
47
+ if (rb_block_given_p()) return result_each(self);
48
+ return self;
49
+ }
50
+
51
+ VALUE statement_initialize(VALUE self, VALUE adapter, VALUE sql) {
52
+ dbi::Handle *handle = adapter_handle(adapter);
53
+
54
+ if (NIL_P(adapter)) rb_raise(eSwiftArgumentError, "Statement#new called without an Adapter instance.");
55
+ if (NIL_P(sql)) rb_raise(eSwiftArgumentError, "Statement#new called without a command.");
56
+
57
+ try {
58
+ DATA_PTR(self) = handle->conn()->prepare(CSTRING(sql));
59
+ }
60
+ CATCH_DBI_EXCEPTIONS();
61
+
62
+ return Qnil;
63
+ }
64
+
65
+ void init_swift_statement() {
66
+ VALUE mSwift = rb_define_module("Swift");
67
+
68
+ /*
69
+ TODO Inheritance confusion.
70
+
71
+ dbic++ has this,
72
+ dbi::Statement < dbi::AbstractStatement
73
+ dbi::AbstractStatement < dbi::AbstractResult
74
+
75
+ Swift has this,
76
+ Statement < Result
77
+
78
+ Not sure if this hierarchy is correct or perfect. I reckon Statement should not
79
+ inherit Result and just return a Result on execute() - maybe cleaner but very
80
+ inefficient when doing tons on non-select style queries.
81
+ */
82
+
83
+ cSwiftStatement = rb_define_class_under(mSwift, "Statement", cSwiftResult);
84
+ rb_define_method(cSwiftStatement, "execute", RUBY_METHOD_FUNC(statement_execute), -1);
85
+ rb_define_method(cSwiftStatement, "initialize", RUBY_METHOD_FUNC(statement_initialize), 2);
86
+ rb_define_alloc_func(cSwiftStatement, statement_alloc);
87
+ }
data/ext/statement.h ADDED
@@ -0,0 +1,12 @@
1
+ #ifndef SWIFT_STATEMENT_H
2
+ #define SWIFT_STATEMENT_H
3
+
4
+ #include "swift.h"
5
+
6
+ extern VALUE cSwiftStatement;
7
+
8
+ void init_swift_statement();
9
+ void statement_free(dbi::AbstractStatement*);
10
+
11
+ #endif
12
+