swift 0.14.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
|