swift 0.14.0 → 1.0.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/API.rdoc +14 -14
- data/README.md +110 -61
- data/Rakefile +2 -5
- data/VERSION +1 -1
- data/lib/swift/adapter/mysql.rb +30 -0
- data/lib/swift/adapter/postgres.rb +27 -0
- data/lib/swift/adapter/sql.rb +23 -29
- data/lib/swift/adapter/sqlite3.rb +59 -0
- data/lib/swift/adapter.rb +129 -70
- data/lib/swift/attribute.rb +19 -8
- data/lib/swift/eventmachine.rb +49 -0
- data/lib/swift/identity_map.rb +7 -7
- data/lib/swift/migrations.rb +12 -12
- data/lib/swift/{scheme.rb → record.rb} +16 -17
- data/lib/swift/result.rb +24 -0
- data/lib/swift/statement.rb +25 -0
- data/lib/swift/synchrony.rb +38 -0
- data/lib/swift/validations.rb +2 -2
- data/lib/swift.rb +8 -6
- data/swift.gemspec +19 -31
- data/test/helper.rb +11 -6
- data/test/test_adapter.rb +11 -25
- data/test/test_async.rb +9 -12
- data/test/test_encoding.rb +2 -2
- data/test/test_error.rb +8 -8
- data/test/test_io.rb +2 -2
- data/test/{test_scheme.rb → test_record.rb} +6 -6
- data/test/test_swift.rb +9 -51
- data/test/test_timestamps.rb +1 -1
- data/test/test_transactions.rb +2 -2
- data/test/test_types.rb +3 -3
- data/test/test_validations.rb +2 -2
- metadata +20 -27
- data/ext/adapter.cc +0 -479
- data/ext/adapter.h +0 -13
- data/ext/adapter_io.cc +0 -62
- data/ext/adapter_io.h +0 -24
- data/ext/attribute.cc +0 -22
- data/ext/attribute.h +0 -8
- data/ext/datetime.cc +0 -96
- data/ext/datetime.h +0 -12
- data/ext/extconf.rb +0 -61
- data/ext/query.cc +0 -104
- data/ext/query.h +0 -20
- data/ext/result.cc +0 -229
- data/ext/result.h +0 -27
- data/ext/statement.cc +0 -116
- data/ext/statement.h +0 -22
- data/ext/swift.cc +0 -114
- data/ext/swift.h +0 -60
- data/lib/swift/db.rb +0 -89
data/ext/attribute.h
DELETED
data/ext/datetime.cc
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
#include "datetime.h"
|
2
|
-
|
3
|
-
extern VALUE dtformat;
|
4
|
-
|
5
|
-
VALUE cSwiftDateTime, day_seconds;
|
6
|
-
ID fcivil, fparse, fstrptime;
|
7
|
-
|
8
|
-
// NOTE: only parses '%F %T.%N %z' format and falls back to the built-in DateTime#parse
|
9
|
-
// and is almost 2x faster than doing:
|
10
|
-
//
|
11
|
-
// rb_funcall(klass, fstrptime, 2, rb_str_new(data, size), dtformat);
|
12
|
-
//
|
13
|
-
VALUE datetime_parse(VALUE klass, const char *data, uint64_t size) {
|
14
|
-
struct tm tm;
|
15
|
-
double seconds;
|
16
|
-
const char *ptr;
|
17
|
-
char tzsign = 0, fraction[32];
|
18
|
-
int tzhour = 0, tzmin = 0, lastmatch = -1, offset = 0, idx;
|
19
|
-
|
20
|
-
memset(&tm, 0, sizeof(struct tm));
|
21
|
-
sscanf(data, "%04d-%02d-%02d %02d:%02d:%02d%n",
|
22
|
-
&tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec, &lastmatch);
|
23
|
-
|
24
|
-
// fallback to default datetime parser, this is more expensive.
|
25
|
-
if (tm.tm_mday == 0)
|
26
|
-
return Qnil;
|
27
|
-
|
28
|
-
seconds = tm.tm_sec;
|
29
|
-
|
30
|
-
// parse millisecs if any -- tad faster than using %lf in sscanf above.
|
31
|
-
if (lastmatch > 0 && lastmatch < size && *(data + lastmatch) == '.') {
|
32
|
-
idx = 0;
|
33
|
-
ptr = data + ++lastmatch;
|
34
|
-
while (*ptr && isdigit(*ptr) && idx < 31) {
|
35
|
-
lastmatch++;
|
36
|
-
fraction[idx++] = *ptr++;
|
37
|
-
}
|
38
|
-
|
39
|
-
fraction[idx] = 0;
|
40
|
-
seconds += (double)atoll(fraction) / pow(10, idx);
|
41
|
-
}
|
42
|
-
|
43
|
-
// parse timezone offsets if any - matches +HH:MM +HH MM +HHMM
|
44
|
-
if (lastmatch > 0 && lastmatch < size) {
|
45
|
-
const char *ptr = data + lastmatch;
|
46
|
-
while(*ptr && *ptr != '+' && *ptr != '-') ptr++;
|
47
|
-
tzsign = *ptr++;
|
48
|
-
if (*ptr && isdigit(*ptr)) {
|
49
|
-
tzhour = *ptr++ - '0';
|
50
|
-
if (*ptr && isdigit(*ptr)) tzhour = tzhour * 10 + *ptr++ - '0';
|
51
|
-
while(*ptr && !isdigit(*ptr)) ptr++;
|
52
|
-
if (*ptr) {
|
53
|
-
tzmin = *ptr++ - '0';
|
54
|
-
if (*ptr && isdigit(*ptr)) tzmin = tzmin * 10 + *ptr++ - '0';
|
55
|
-
}
|
56
|
-
}
|
57
|
-
}
|
58
|
-
|
59
|
-
if (tzsign) {
|
60
|
-
offset = tzsign == '+'
|
61
|
-
? (time_t)tzhour * 3600 + (time_t)tzmin * 60
|
62
|
-
: (time_t)tzhour * -3600 + (time_t)tzmin * -60;
|
63
|
-
}
|
64
|
-
|
65
|
-
return rb_funcall(klass, fcivil, 7,
|
66
|
-
INT2FIX(tm.tm_year), INT2FIX(tm.tm_mon), INT2FIX(tm.tm_mday),
|
67
|
-
INT2FIX(tm.tm_hour), INT2FIX(tm.tm_min), DBL2NUM(seconds),
|
68
|
-
offset == 0 ? INT2FIX(0) : rb_Rational(INT2FIX(offset), day_seconds)
|
69
|
-
);
|
70
|
-
}
|
71
|
-
|
72
|
-
VALUE rb_datetime_parse(VALUE self, VALUE string) {
|
73
|
-
const char *data = CSTRING(string);
|
74
|
-
int size = TYPE(string) == T_STRING ? RSTRING_LEN(string) : strlen(data);
|
75
|
-
|
76
|
-
if (NIL_P(string))
|
77
|
-
return Qnil;
|
78
|
-
|
79
|
-
VALUE datetime = datetime_parse(self, data, size);
|
80
|
-
return NIL_P(datetime) ? rb_call_super(1, &string) : datetime;
|
81
|
-
}
|
82
|
-
|
83
|
-
void init_swift_datetime() {
|
84
|
-
rb_require("date");
|
85
|
-
|
86
|
-
VALUE mSwift = rb_define_module("Swift");
|
87
|
-
VALUE cDateTime = CONST_GET(rb_mKernel, "DateTime");
|
88
|
-
cSwiftDateTime = rb_define_class_under(mSwift, "DateTime", cDateTime);
|
89
|
-
fcivil = rb_intern("civil");
|
90
|
-
fparse = rb_intern("parse");
|
91
|
-
fstrptime = rb_intern("strptime");
|
92
|
-
day_seconds = INT2FIX(86400);
|
93
|
-
|
94
|
-
rb_global_variable(&day_seconds);
|
95
|
-
rb_define_singleton_method(cSwiftDateTime, "parse", RUBY_METHOD_FUNC(rb_datetime_parse), 1);
|
96
|
-
}
|
data/ext/datetime.h
DELETED
data/ext/extconf.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'mkmf'
|
3
|
-
|
4
|
-
ConfigClass = defined?(RbConfig) ? RbConfig : Config
|
5
|
-
|
6
|
-
ConfigClass::CONFIG['CC'] = 'g++'
|
7
|
-
ConfigClass::CONFIG['CPP'] = 'g++'
|
8
|
-
|
9
|
-
$CFLAGS = '-fPIC -Os -I/usr/include -I/opt/local/include -I/usr/local/include'
|
10
|
-
|
11
|
-
def apt_install_hint pkg
|
12
|
-
"sudo apt-get install #{pkg}"
|
13
|
-
end
|
14
|
-
|
15
|
-
def library_installed? name, hint
|
16
|
-
if find_library(name, 'main', *%w(/usr/lib /usr/local/lib /opt/lib /opt/local/lib /sw/lib))
|
17
|
-
true
|
18
|
-
else
|
19
|
-
$stderr.puts <<-ERROR
|
20
|
-
|
21
|
-
Unable to find required library: #{name}.
|
22
|
-
On debian systems, it can be installed as,
|
23
|
-
|
24
|
-
#{hint}
|
25
|
-
|
26
|
-
You may have to add the following ppa to your sources,
|
27
|
-
|
28
|
-
sudo add-apt-repository ppa:deepfryed
|
29
|
-
|
30
|
-
to install dbic++-dev and associated drivers dbic++-mysql or dbic++-pg
|
31
|
-
|
32
|
-
ERROR
|
33
|
-
false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def assert_dbicpp_version ver
|
38
|
-
passed = false
|
39
|
-
header = '/usr/include/dbic++.h'
|
40
|
-
message = "Swift needs dbic++ >= #{ver}. Please update your dbic++ installation."
|
41
|
-
|
42
|
-
if File.exists?(header) && match = File.read(header).match(/DBI_VERSION\s+(.*?)\n/mi)
|
43
|
-
rmajor, rminor, rbuild = ver.strip.split(/\./).map(&:to_i)
|
44
|
-
imajor, iminor, ibuild = match.captures.first.strip.split(/\./).map(&:to_i)
|
45
|
-
passed = (imajor > rmajor) ||
|
46
|
-
(imajor == rmajor && iminor > rminor) ||
|
47
|
-
(imajor == rmajor && iminor == rminor && ibuild >= rbuild)
|
48
|
-
else
|
49
|
-
message = "Cannot find #{header} or version number. You need to install dbic++ >= #{ver}"
|
50
|
-
passed = false
|
51
|
-
end
|
52
|
-
|
53
|
-
raise message unless passed
|
54
|
-
end
|
55
|
-
|
56
|
-
exit 1 unless library_installed? 'pcrecpp', apt_install_hint('libpcre3-dev')
|
57
|
-
exit 1 unless library_installed? 'uuid', apt_install_hint('uuid-dev')
|
58
|
-
exit 1 unless library_installed? 'dbic++', apt_install_hint('dbic++-dev')
|
59
|
-
|
60
|
-
assert_dbicpp_version '0.6.0'
|
61
|
-
create_makefile 'swift'
|
data/ext/query.cc
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
#include "query.h"
|
2
|
-
#include <math.h>
|
3
|
-
|
4
|
-
ID fstrftime;
|
5
|
-
VALUE dtformat, utf8;
|
6
|
-
VALUE cDateTime;
|
7
|
-
|
8
|
-
VALUE query_execute(Query *query) {
|
9
|
-
try {
|
10
|
-
return UINT2NUM(
|
11
|
-
query->bind.size() == 0
|
12
|
-
? query->handle->conn()->execute(query->sql)
|
13
|
-
: query->handle->conn()->execute(query->sql, query->bind)
|
14
|
-
);
|
15
|
-
}
|
16
|
-
catch (dbi::ConnectionError &e) {
|
17
|
-
query->error_klass = eSwiftConnectionError;
|
18
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
19
|
-
}
|
20
|
-
catch (dbi::Error &e) {
|
21
|
-
query->error_klass = eSwiftRuntimeError;
|
22
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
23
|
-
}
|
24
|
-
catch (std::bad_alloc &e) {
|
25
|
-
query->error_klass = rb_eNoMemError;
|
26
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
27
|
-
}
|
28
|
-
catch (std::exception &e) {
|
29
|
-
query->error_klass = rb_eRuntimeError;
|
30
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
31
|
-
}
|
32
|
-
|
33
|
-
return Qfalse;
|
34
|
-
}
|
35
|
-
|
36
|
-
VALUE query_execute_statement(Query *query) {
|
37
|
-
try {
|
38
|
-
return UINT2NUM(
|
39
|
-
query->bind.size() == 0
|
40
|
-
? query->statement->execute()
|
41
|
-
: query->statement->execute(query->bind)
|
42
|
-
);
|
43
|
-
}
|
44
|
-
catch (dbi::ConnectionError &e) {
|
45
|
-
query->error_klass = eSwiftConnectionError;
|
46
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
47
|
-
}
|
48
|
-
catch (dbi::Error &e) {
|
49
|
-
query->error_klass = eSwiftRuntimeError;
|
50
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
51
|
-
}
|
52
|
-
catch (std::bad_alloc &e) {
|
53
|
-
query->error_klass = rb_eNoMemError;
|
54
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
55
|
-
}
|
56
|
-
catch (std::exception &e) {
|
57
|
-
query->error_klass = rb_eRuntimeError;
|
58
|
-
snprintf(query->error_message, 8192, "%s", e.what());
|
59
|
-
}
|
60
|
-
|
61
|
-
return Qfalse;
|
62
|
-
}
|
63
|
-
|
64
|
-
void query_bind_values(Query *query, VALUE bind_values) {
|
65
|
-
for (int i = 0; i < RARRAY_LEN(bind_values); i++) {
|
66
|
-
VALUE bind_value = rb_ary_entry(bind_values, i);
|
67
|
-
|
68
|
-
if (bind_value == Qnil) {
|
69
|
-
query->bind.push_back(dbi::PARAM(dbi::null()));
|
70
|
-
}
|
71
|
-
else if (bind_value == Qtrue) {
|
72
|
-
query->bind.push_back(dbi::PARAM("1"));
|
73
|
-
}
|
74
|
-
else if (bind_value == Qfalse) {
|
75
|
-
query->bind.push_back(dbi::PARAM("0"));
|
76
|
-
}
|
77
|
-
else if (rb_obj_is_kind_of(bind_value, rb_cIO) == Qtrue || rb_obj_is_kind_of(bind_value, cStringIO) == Qtrue) {
|
78
|
-
bind_value = rb_funcall(bind_value, rb_intern("read"), 0);
|
79
|
-
query->bind.push_back(dbi::PARAM_BINARY((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
|
80
|
-
}
|
81
|
-
else if (rb_obj_is_kind_of(bind_value, rb_cTime) || rb_obj_is_kind_of(bind_value, cDateTime)) {
|
82
|
-
std::string timestamp = RSTRING_PTR(rb_funcall(bind_value, fstrftime, 1, dtformat));
|
83
|
-
query->bind.push_back(dbi::PARAM(timestamp));
|
84
|
-
}
|
85
|
-
else {
|
86
|
-
bind_value = TO_S(bind_value);
|
87
|
-
if (strcmp(rb_enc_get(bind_value)->name, "UTF-8") != 0)
|
88
|
-
bind_value = rb_str_encode(bind_value, utf8, 0, Qnil);
|
89
|
-
query->bind.push_back(dbi::PARAM((unsigned char*)RSTRING_PTR(bind_value), RSTRING_LEN(bind_value)));
|
90
|
-
}
|
91
|
-
}
|
92
|
-
}
|
93
|
-
|
94
|
-
void init_swift_query() {
|
95
|
-
rb_require("date");
|
96
|
-
|
97
|
-
utf8 = rb_str_new2("UTF-8");
|
98
|
-
fstrftime = rb_intern("strftime");
|
99
|
-
dtformat = rb_str_new2("%F %T.%N %z");
|
100
|
-
cDateTime = CONST_GET(rb_mKernel, "DateTime");
|
101
|
-
|
102
|
-
rb_global_variable(&utf8);
|
103
|
-
rb_global_variable(&dtformat);
|
104
|
-
}
|
data/ext/query.h
DELETED
@@ -1,20 +0,0 @@
|
|
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
|
-
std::vector<dbi::Param> bind;
|
11
|
-
char error_message[8192];
|
12
|
-
VALUE error_klass;
|
13
|
-
};
|
14
|
-
|
15
|
-
VALUE query_execute(Query*);
|
16
|
-
VALUE query_execute_statement(Query*);
|
17
|
-
void query_bind_values(Query*, VALUE);
|
18
|
-
void init_swift_query();
|
19
|
-
|
20
|
-
#endif
|
data/ext/result.cc
DELETED
@@ -1,229 +0,0 @@
|
|
1
|
-
#include "result.h"
|
2
|
-
#include "datetime.h"
|
3
|
-
#include <math.h>
|
4
|
-
|
5
|
-
#define date_parse(klass, data,len) rb_funcall(datetime_parse(klass, data, len), fto_date, 0)
|
6
|
-
|
7
|
-
VALUE cBigDecimal, cStringIO, cSwiftResult;
|
8
|
-
ID fnew, fload, fto_date;
|
9
|
-
|
10
|
-
void result_mark(ResultWrapper *handle) {
|
11
|
-
if (handle)
|
12
|
-
rb_gc_mark(handle->adapter);
|
13
|
-
}
|
14
|
-
|
15
|
-
void result_free(ResultWrapper *handle) {
|
16
|
-
if (handle) {
|
17
|
-
if (handle->free) delete handle->result;
|
18
|
-
delete handle;
|
19
|
-
}
|
20
|
-
}
|
21
|
-
|
22
|
-
VALUE result_alloc(VALUE klass) {
|
23
|
-
ResultWrapper *handle = 0;
|
24
|
-
return Data_Wrap_Struct(klass, result_mark, result_free, handle);
|
25
|
-
}
|
26
|
-
|
27
|
-
VALUE result_wrap_handle(VALUE klass, VALUE adapter, dbi::AbstractResult *result, bool free) {
|
28
|
-
ResultWrapper *handle = new ResultWrapper;
|
29
|
-
handle->result = result;
|
30
|
-
handle->adapter = adapter;
|
31
|
-
handle->free = free;
|
32
|
-
|
33
|
-
VALUE obj = Data_Wrap_Struct(klass, result_mark, result_free, handle);
|
34
|
-
if (!NIL_P(adapter))
|
35
|
-
rb_iv_set(obj, "@timezone", rb_iv_get(adapter, "@timezone"));
|
36
|
-
|
37
|
-
return obj;
|
38
|
-
}
|
39
|
-
|
40
|
-
dbi::AbstractResult* result_handle(VALUE self) {
|
41
|
-
ResultWrapper *handle;
|
42
|
-
Data_Get_Struct(self, ResultWrapper, handle);
|
43
|
-
if (!handle) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?");
|
44
|
-
|
45
|
-
return handle->result;
|
46
|
-
}
|
47
|
-
|
48
|
-
// NOTE clone and dup cannot be allowed since the underlying c++ object needs to be cloned, which
|
49
|
-
// frankly is too much work :)
|
50
|
-
static VALUE result_clone(VALUE self) {
|
51
|
-
rb_raise(eSwiftRuntimeError, "clone is not allowed.");
|
52
|
-
}
|
53
|
-
|
54
|
-
static VALUE result_dup(VALUE self) {
|
55
|
-
rb_raise(eSwiftRuntimeError, "dup is not allowed.");
|
56
|
-
}
|
57
|
-
|
58
|
-
VALUE result_each(VALUE self) {
|
59
|
-
uint64_t length;
|
60
|
-
const char *data;
|
61
|
-
|
62
|
-
dbi::AbstractResult *result = result_handle(self);
|
63
|
-
VALUE scheme = rb_iv_get(self, "@scheme");
|
64
|
-
|
65
|
-
try {
|
66
|
-
std::vector<string> result_fields = result->fields();
|
67
|
-
std::vector<int> result_types = result->types();
|
68
|
-
std::vector<VALUE> fields;
|
69
|
-
for (uint32_t i = 0; i < result_fields.size(); i++)
|
70
|
-
fields.push_back(ID2SYM(rb_intern(result_fields[i].c_str())));
|
71
|
-
|
72
|
-
result->seek(0);
|
73
|
-
for (uint32_t row = 0; row < result->rows(); row++) {
|
74
|
-
VALUE tuple = rb_hash_new();
|
75
|
-
for (uint32_t column = 0; column < result->columns(); column++) {
|
76
|
-
data = (const char*)result->read(row, column, &length);
|
77
|
-
if (data) {
|
78
|
-
rb_hash_aset(
|
79
|
-
tuple,
|
80
|
-
fields[column],
|
81
|
-
typecast_field(result_types[column], data, length)
|
82
|
-
);
|
83
|
-
}
|
84
|
-
else {
|
85
|
-
rb_hash_aset(tuple, fields[column], Qnil);
|
86
|
-
}
|
87
|
-
} // column loop
|
88
|
-
NIL_P(scheme) ? rb_yield(tuple) : rb_yield(rb_funcall(scheme, fload, 1, tuple));
|
89
|
-
} // row loop
|
90
|
-
}
|
91
|
-
CATCH_DBI_EXCEPTIONS();
|
92
|
-
|
93
|
-
return Qnil;
|
94
|
-
}
|
95
|
-
|
96
|
-
VALUE typecast_field(int type, const char *data, uint64_t length) {
|
97
|
-
switch(type) {
|
98
|
-
case DBI_TYPE_BOOLEAN:
|
99
|
-
return (data && (data[0] =='t' || data[0] == '1')) ? Qtrue : Qfalse;
|
100
|
-
case DBI_TYPE_INT:
|
101
|
-
return rb_cstr2inum(data, 10);
|
102
|
-
case DBI_TYPE_BLOB:
|
103
|
-
return rb_funcall(cStringIO, fnew, 1, rb_str_new(data, length));
|
104
|
-
case DBI_TYPE_TIMESTAMP:
|
105
|
-
return datetime_parse(cSwiftDateTime, data, length);
|
106
|
-
case DBI_TYPE_DATE:
|
107
|
-
return date_parse(cSwiftDateTime, data, length);
|
108
|
-
case DBI_TYPE_NUMERIC:
|
109
|
-
return rb_funcall(cBigDecimal, fnew, 1, rb_str_new2(data));
|
110
|
-
case DBI_TYPE_FLOAT:
|
111
|
-
return rb_float_new(atof(data));
|
112
|
-
|
113
|
-
// DBI_TYPE_TIME
|
114
|
-
// DBI_TYPE_TEXT
|
115
|
-
default:
|
116
|
-
return rb_enc_str_new(data, length, rb_utf8_encoding());
|
117
|
-
}
|
118
|
-
}
|
119
|
-
|
120
|
-
VALUE result_insert_id(VALUE self) {
|
121
|
-
dbi::AbstractResult *result = result_handle(self);
|
122
|
-
try {
|
123
|
-
return SIZET2NUM(result->lastInsertID());
|
124
|
-
}
|
125
|
-
CATCH_DBI_EXCEPTIONS();
|
126
|
-
return Qnil;
|
127
|
-
}
|
128
|
-
|
129
|
-
VALUE result_rows(VALUE self) {
|
130
|
-
dbi::AbstractResult *result = result_handle(self);
|
131
|
-
try {
|
132
|
-
return SIZET2NUM(result->rows());
|
133
|
-
}
|
134
|
-
CATCH_DBI_EXCEPTIONS();
|
135
|
-
}
|
136
|
-
|
137
|
-
VALUE result_columns(VALUE self) {
|
138
|
-
dbi::AbstractResult *result = result_handle(self);
|
139
|
-
try {
|
140
|
-
return SIZET2NUM(result->columns());
|
141
|
-
}
|
142
|
-
CATCH_DBI_EXCEPTIONS();
|
143
|
-
}
|
144
|
-
|
145
|
-
VALUE result_fields(VALUE self) {
|
146
|
-
dbi::AbstractResult *result = result_handle(self);
|
147
|
-
try {
|
148
|
-
std::vector<string> result_fields = result->fields();
|
149
|
-
VALUE fields = rb_ary_new();
|
150
|
-
for (int i = 0; i < result_fields.size(); i++)
|
151
|
-
rb_ary_push(fields, ID2SYM(rb_intern(result_fields[i].c_str())));
|
152
|
-
return fields;
|
153
|
-
}
|
154
|
-
CATCH_DBI_EXCEPTIONS();
|
155
|
-
}
|
156
|
-
|
157
|
-
VALUE result_field_types(VALUE self) {
|
158
|
-
dbi::AbstractResult *result = result_handle(self);
|
159
|
-
std::vector<int> result_types = result->types();
|
160
|
-
|
161
|
-
VALUE types = rb_ary_new();
|
162
|
-
for (std::vector<int>::iterator it = result_types.begin(); it != result_types.end(); it++) {
|
163
|
-
switch(*it) {
|
164
|
-
case DBI_TYPE_BOOLEAN:
|
165
|
-
rb_ary_push(types, rb_str_new2("boolean"));
|
166
|
-
break;
|
167
|
-
case DBI_TYPE_INT:
|
168
|
-
rb_ary_push(types, rb_str_new2("integer"));
|
169
|
-
break;
|
170
|
-
case DBI_TYPE_BLOB:
|
171
|
-
rb_ary_push(types, rb_str_new2("blob"));
|
172
|
-
break;
|
173
|
-
case DBI_TYPE_TIMESTAMP:
|
174
|
-
rb_ary_push(types, rb_str_new2("timestamp"));
|
175
|
-
break;
|
176
|
-
case DBI_TYPE_DATE:
|
177
|
-
rb_ary_push(types, rb_str_new2("date"));
|
178
|
-
break;
|
179
|
-
case DBI_TYPE_NUMERIC:
|
180
|
-
rb_ary_push(types, rb_str_new2("numeric"));
|
181
|
-
break;
|
182
|
-
case DBI_TYPE_FLOAT:
|
183
|
-
rb_ary_push(types, rb_str_new2("float"));
|
184
|
-
break;
|
185
|
-
case DBI_TYPE_TIME:
|
186
|
-
rb_ary_push(types, rb_str_new2("time"));
|
187
|
-
break;
|
188
|
-
default:
|
189
|
-
rb_ary_push(types, rb_str_new2("text"));
|
190
|
-
}
|
191
|
-
}
|
192
|
-
|
193
|
-
return types;
|
194
|
-
}
|
195
|
-
|
196
|
-
VALUE result_retrieve(VALUE self) {
|
197
|
-
dbi::AbstractResult *result = result_handle(self);
|
198
|
-
while (result->consumeResult());
|
199
|
-
result->prepareResult();
|
200
|
-
return true;
|
201
|
-
}
|
202
|
-
|
203
|
-
void init_swift_result() {
|
204
|
-
rb_require("bigdecimal");
|
205
|
-
rb_require("stringio");
|
206
|
-
|
207
|
-
VALUE mSwift = rb_define_module("Swift");
|
208
|
-
cSwiftResult = rb_define_class_under(mSwift, "Result", rb_cObject);
|
209
|
-
cStringIO = CONST_GET(rb_mKernel, "StringIO");
|
210
|
-
cBigDecimal = CONST_GET(rb_mKernel, "BigDecimal");
|
211
|
-
|
212
|
-
fto_date = rb_intern("to_date");
|
213
|
-
fnew = rb_intern("new");
|
214
|
-
fload = rb_intern("load");
|
215
|
-
|
216
|
-
rb_define_alloc_func(cSwiftResult, result_alloc);
|
217
|
-
rb_include_module(cSwiftResult, CONST_GET(rb_mKernel, "Enumerable"));
|
218
|
-
|
219
|
-
rb_define_method(cSwiftResult, "retrieve", RUBY_METHOD_FUNC(result_retrieve), 0);
|
220
|
-
rb_define_method(cSwiftResult, "clone", RUBY_METHOD_FUNC(result_clone), 0);
|
221
|
-
rb_define_method(cSwiftResult, "dup", RUBY_METHOD_FUNC(result_dup), 0);
|
222
|
-
rb_define_method(cSwiftResult, "each", RUBY_METHOD_FUNC(result_each), 0);
|
223
|
-
rb_define_method(cSwiftResult, "insert_id", RUBY_METHOD_FUNC(result_insert_id), 0);
|
224
|
-
rb_define_method(cSwiftResult, "rows", RUBY_METHOD_FUNC(result_rows), 0);
|
225
|
-
rb_define_method(cSwiftResult, "columns", RUBY_METHOD_FUNC(result_columns), 0);
|
226
|
-
rb_define_method(cSwiftResult, "fields", RUBY_METHOD_FUNC(result_fields), 0);
|
227
|
-
rb_define_method(cSwiftResult, "field_types", RUBY_METHOD_FUNC(result_field_types), 0);
|
228
|
-
}
|
229
|
-
|
data/ext/result.h
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
#ifndef SWIFT_RESULT_H
|
2
|
-
#define SWIFT_RESULT_H
|
3
|
-
|
4
|
-
#include "swift.h"
|
5
|
-
|
6
|
-
struct ResultWrapper {
|
7
|
-
dbi::AbstractResult *result;
|
8
|
-
VALUE adapter;
|
9
|
-
bool free;
|
10
|
-
};
|
11
|
-
|
12
|
-
extern VALUE cSwiftResult;
|
13
|
-
extern VALUE cStringIO;
|
14
|
-
|
15
|
-
void init_swift_result();
|
16
|
-
|
17
|
-
void result_free(ResultWrapper *);
|
18
|
-
void result_mark(ResultWrapper *);
|
19
|
-
|
20
|
-
VALUE result_wrap_handle(VALUE, VALUE, dbi::AbstractResult *, bool free);
|
21
|
-
dbi::AbstractResult* result_handle(VALUE);
|
22
|
-
|
23
|
-
VALUE result_each(VALUE);
|
24
|
-
|
25
|
-
VALUE typecast_field(int, const char*, uint64_t);
|
26
|
-
|
27
|
-
#endif
|
data/ext/statement.cc
DELETED
@@ -1,116 +0,0 @@
|
|
1
|
-
#include "statement.h"
|
2
|
-
#include "adapter.h"
|
3
|
-
#include "result.h"
|
4
|
-
#include "query.h"
|
5
|
-
|
6
|
-
VALUE cSwiftStatement;
|
7
|
-
|
8
|
-
void statement_mark(StatementWrapper *handle) {
|
9
|
-
if (handle)
|
10
|
-
rb_gc_mark(handle->adapter);
|
11
|
-
}
|
12
|
-
|
13
|
-
void statement_free(StatementWrapper *handle) {
|
14
|
-
if (handle) {
|
15
|
-
if (handle->free) delete handle->statement;
|
16
|
-
delete handle;
|
17
|
-
}
|
18
|
-
}
|
19
|
-
|
20
|
-
VALUE statement_alloc(VALUE klass) {
|
21
|
-
StatementWrapper *handle = 0;
|
22
|
-
return Data_Wrap_Struct(klass, statement_mark, statement_free, handle);
|
23
|
-
}
|
24
|
-
|
25
|
-
VALUE statement_wrap_handle(VALUE klass, VALUE adapter, dbi::AbstractStatement *statement) {
|
26
|
-
StatementWrapper *handle = new StatementWrapper;
|
27
|
-
handle->statement = statement;
|
28
|
-
handle->adapter = adapter;
|
29
|
-
handle->free = true;
|
30
|
-
|
31
|
-
VALUE obj = Data_Wrap_Struct(klass, statement_mark, statement_free, handle);
|
32
|
-
if (!NIL_P(adapter))
|
33
|
-
rb_iv_set(obj, "@timezone", rb_iv_get(adapter, "@timezone"));
|
34
|
-
|
35
|
-
return obj;
|
36
|
-
}
|
37
|
-
|
38
|
-
dbi::AbstractStatement* statement_handle(VALUE self) {
|
39
|
-
StatementWrapper *handle;
|
40
|
-
Data_Get_Struct(self, StatementWrapper, handle);
|
41
|
-
if (!handle) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?");
|
42
|
-
|
43
|
-
return handle->statement;
|
44
|
-
}
|
45
|
-
|
46
|
-
// array -> splat -> array is an overhead, but it reads nicer.
|
47
|
-
static VALUE statement_execute(int argc, VALUE *argv, VALUE self) {
|
48
|
-
VALUE bind_values, block;
|
49
|
-
rb_scan_args(argc, argv, "0*&", &bind_values, &block);
|
50
|
-
|
51
|
-
dbi::AbstractStatement *statement = (dbi::AbstractStatement*)statement_handle(self);
|
52
|
-
try {
|
53
|
-
Query query;
|
54
|
-
query.statement = statement;
|
55
|
-
if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values);
|
56
|
-
if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(statement->command(), query.bind));
|
57
|
-
|
58
|
-
if (rb_thread_blocking_region(((VALUE (*)(void*))query_execute_statement), &query, RUBY_UBF_IO, 0) == Qfalse)
|
59
|
-
rb_raise(query.error_klass, "%s", query.error_message);
|
60
|
-
}
|
61
|
-
CATCH_DBI_EXCEPTIONS();
|
62
|
-
|
63
|
-
StatementWrapper *handle;
|
64
|
-
Data_Get_Struct(self, StatementWrapper, handle);
|
65
|
-
|
66
|
-
VALUE result = result_wrap_handle(cSwiftResult, handle->adapter, statement->result(), true);
|
67
|
-
rb_iv_set(result, "@scheme", rb_iv_get(self, "@scheme"));
|
68
|
-
|
69
|
-
return rb_block_given_p() ? result_each(result) : result;
|
70
|
-
}
|
71
|
-
|
72
|
-
VALUE statement_insert_id(VALUE self) {
|
73
|
-
dbi::AbstractStatement *statement = statement_handle(self);
|
74
|
-
try {
|
75
|
-
return SIZET2NUM(statement->lastInsertID());
|
76
|
-
}
|
77
|
-
CATCH_DBI_EXCEPTIONS();
|
78
|
-
return Qnil;
|
79
|
-
}
|
80
|
-
|
81
|
-
VALUE statement_initialize(VALUE self, VALUE adapter, VALUE sql) {
|
82
|
-
dbi::Handle *handle = adapter_handle(adapter);
|
83
|
-
|
84
|
-
if (NIL_P(adapter)) rb_raise(eSwiftArgumentError, "Statement#new called without an Adapter instance.");
|
85
|
-
if (NIL_P(sql)) rb_raise(eSwiftArgumentError, "Statement#new called without a command.");
|
86
|
-
|
87
|
-
try {
|
88
|
-
// needs to happen before wrapping in case it raises errors.
|
89
|
-
dbi::AbstractStatement *statement = handle->conn()->prepare(CSTRING(sql));
|
90
|
-
StatementWrapper *statement_handle = new StatementWrapper;
|
91
|
-
statement_handle->statement = statement;
|
92
|
-
statement_handle->adapter = adapter;
|
93
|
-
statement_handle->free = true;
|
94
|
-
DATA_PTR(self) = statement_handle;
|
95
|
-
}
|
96
|
-
CATCH_DBI_EXCEPTIONS();
|
97
|
-
|
98
|
-
return Qnil;
|
99
|
-
}
|
100
|
-
|
101
|
-
VALUE statement_command(VALUE self) {
|
102
|
-
return rb_iv_get(self, "@sql");
|
103
|
-
}
|
104
|
-
|
105
|
-
void init_swift_statement() {
|
106
|
-
VALUE mSwift = rb_define_module("Swift");
|
107
|
-
|
108
|
-
cSwiftStatement = rb_define_class_under(mSwift, "Statement", rb_cObject);
|
109
|
-
rb_define_method(cSwiftStatement, "execute", RUBY_METHOD_FUNC(statement_execute), -1);
|
110
|
-
rb_define_method(cSwiftStatement, "initialize", RUBY_METHOD_FUNC(statement_initialize), 2);
|
111
|
-
rb_define_method(cSwiftStatement, "insert_id", RUBY_METHOD_FUNC(statement_insert_id), 0);
|
112
|
-
rb_define_method(cSwiftStatement, "command", RUBY_METHOD_FUNC(statement_command), 0);
|
113
|
-
|
114
|
-
rb_define_alias(cSwiftStatement, "to_s", "command");
|
115
|
-
rb_define_alloc_func(cSwiftStatement, statement_alloc);
|
116
|
-
}
|
data/ext/statement.h
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#ifndef SWIFT_STATEMENT_H
|
2
|
-
#define SWIFT_STATEMENT_H
|
3
|
-
|
4
|
-
#include "swift.h"
|
5
|
-
|
6
|
-
struct StatementWrapper {
|
7
|
-
dbi::AbstractStatement *statement;
|
8
|
-
VALUE adapter;
|
9
|
-
bool free;
|
10
|
-
};
|
11
|
-
|
12
|
-
extern VALUE cSwiftStatement;
|
13
|
-
|
14
|
-
void init_swift_statement();
|
15
|
-
void statement_free(StatementWrapper *);
|
16
|
-
void statement_mark(StatementWrapper *);
|
17
|
-
|
18
|
-
VALUE statement_wrap_handle(VALUE, VALUE, dbi::AbstractStatement *);
|
19
|
-
dbi::AbstractStatement* statement_handle(VALUE);
|
20
|
-
|
21
|
-
#endif
|
22
|
-
|