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
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swift
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2012-
|
13
|
+
date: 2012-08-01 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: minitest
|
17
|
-
requirement:
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,14 +22,18 @@ dependencies:
|
|
22
22
|
version: 1.7.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements:
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ! '>='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 1.7.0
|
26
31
|
description: A rational rudimentary database abstraction.
|
27
32
|
email:
|
28
33
|
- shane.hanna@gmail.com
|
29
34
|
- deepfryed@gmail.com
|
30
35
|
executables: []
|
31
|
-
extensions:
|
32
|
-
- ext/extconf.rb
|
36
|
+
extensions: []
|
33
37
|
extra_rdoc_files:
|
34
38
|
- LICENSE
|
35
39
|
- README.md
|
@@ -39,32 +43,21 @@ files:
|
|
39
43
|
- README.md
|
40
44
|
- Rakefile
|
41
45
|
- VERSION
|
42
|
-
- ext/adapter.cc
|
43
|
-
- ext/adapter.h
|
44
|
-
- ext/adapter_io.cc
|
45
|
-
- ext/adapter_io.h
|
46
|
-
- ext/attribute.cc
|
47
|
-
- ext/attribute.h
|
48
|
-
- ext/datetime.cc
|
49
|
-
- ext/datetime.h
|
50
|
-
- ext/extconf.rb
|
51
|
-
- ext/query.cc
|
52
|
-
- ext/query.h
|
53
|
-
- ext/result.cc
|
54
|
-
- ext/result.h
|
55
|
-
- ext/statement.cc
|
56
|
-
- ext/statement.h
|
57
|
-
- ext/swift.cc
|
58
|
-
- ext/swift.h
|
59
46
|
- lib/swift.rb
|
60
47
|
- lib/swift/adapter.rb
|
48
|
+
- lib/swift/adapter/mysql.rb
|
49
|
+
- lib/swift/adapter/postgres.rb
|
61
50
|
- lib/swift/adapter/sql.rb
|
51
|
+
- lib/swift/adapter/sqlite3.rb
|
62
52
|
- lib/swift/attribute.rb
|
63
|
-
- lib/swift/
|
53
|
+
- lib/swift/eventmachine.rb
|
64
54
|
- lib/swift/header.rb
|
65
55
|
- lib/swift/identity_map.rb
|
66
56
|
- lib/swift/migrations.rb
|
67
|
-
- lib/swift/
|
57
|
+
- lib/swift/record.rb
|
58
|
+
- lib/swift/result.rb
|
59
|
+
- lib/swift/statement.rb
|
60
|
+
- lib/swift/synchrony.rb
|
68
61
|
- lib/swift/type.rb
|
69
62
|
- lib/swift/validations.rb
|
70
63
|
- swift.gemspec
|
@@ -78,7 +71,7 @@ files:
|
|
78
71
|
- test/test_error.rb
|
79
72
|
- test/test_identity_map.rb
|
80
73
|
- test/test_io.rb
|
81
|
-
- test/
|
74
|
+
- test/test_record.rb
|
82
75
|
- test/test_swift.rb
|
83
76
|
- test/test_timestamps.rb
|
84
77
|
- test/test_transactions.rb
|
@@ -104,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
97
|
version: '0'
|
105
98
|
requirements: []
|
106
99
|
rubyforge_project:
|
107
|
-
rubygems_version: 1.8.
|
100
|
+
rubygems_version: 1.8.23
|
108
101
|
signing_key:
|
109
102
|
specification_version: 3
|
110
103
|
summary: A rational rudimentary database abstraction.
|
data/ext/adapter.cc
DELETED
@@ -1,479 +0,0 @@
|
|
1
|
-
// vim:ts=2:sts=2:sw=2:expandtab
|
2
|
-
|
3
|
-
#include "adapter.h"
|
4
|
-
#include "sys/select.h"
|
5
|
-
|
6
|
-
// Extend the default dbi::FieldSet class with some ruby love.
|
7
|
-
class Fields : public dbi::FieldSet {
|
8
|
-
public:
|
9
|
-
Fields() : dbi::FieldSet(0) {}
|
10
|
-
|
11
|
-
void operator<<(VALUE v) {
|
12
|
-
VALUE name = TO_S(v);
|
13
|
-
fields.push_back(std::string(RSTRING_PTR(name), RSTRING_LEN(name)));
|
14
|
-
}
|
15
|
-
};
|
16
|
-
|
17
|
-
static VALUE cSwiftAdapter;
|
18
|
-
|
19
|
-
void build_extra_options_string(VALUE key, VALUE value, VALUE ptr) {
|
20
|
-
std::string *optstring = (std::string *)ptr;
|
21
|
-
*optstring += CSTRING(key) + std::string("=") + CSTRING(value) + std::string(";");
|
22
|
-
}
|
23
|
-
|
24
|
-
std::string parse_extra_options(VALUE options) {
|
25
|
-
std::string optstring = "";
|
26
|
-
if (!NIL_P(options))
|
27
|
-
rb_hash_foreach(options, RUBY_STATIC_FUNC(build_extra_options_string), (VALUE)&optstring);
|
28
|
-
return optstring;
|
29
|
-
}
|
30
|
-
|
31
|
-
static void adapter_free(dbi::Handle *handle) {
|
32
|
-
if (handle) {
|
33
|
-
handle->conn()->cleanup();
|
34
|
-
delete handle;
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
|
-
VALUE adapter_alloc(VALUE klass) {
|
39
|
-
dbi::Handle *handle = 0;
|
40
|
-
return Data_Wrap_Struct(klass, 0, adapter_free, handle);
|
41
|
-
}
|
42
|
-
|
43
|
-
dbi::Handle* adapter_handle(VALUE self) {
|
44
|
-
dbi::Handle *handle;
|
45
|
-
Data_Get_Struct(self, dbi::Handle, handle);
|
46
|
-
if (!handle) rb_raise(eSwiftRuntimeError, "Invalid object, did you forget to call #super?");
|
47
|
-
|
48
|
-
return handle;
|
49
|
-
}
|
50
|
-
|
51
|
-
/*
|
52
|
-
Begin a transaction (unit of work).
|
53
|
-
|
54
|
-
@overload commit(name = nil)
|
55
|
-
@param [Symbol, String] name Optional transaction name.
|
56
|
-
|
57
|
-
@see Swift::Adapter#transaction
|
58
|
-
*/
|
59
|
-
static VALUE adapter_begin(int argc, VALUE *argv, VALUE self) {
|
60
|
-
VALUE save_point;
|
61
|
-
rb_scan_args(argc, argv, "01", &save_point);
|
62
|
-
|
63
|
-
dbi::Handle *handle = adapter_handle(self);
|
64
|
-
try {
|
65
|
-
NIL_P(save_point) ? handle->begin() : handle->begin(CSTRING(save_point));
|
66
|
-
}
|
67
|
-
CATCH_DBI_EXCEPTIONS();
|
68
|
-
return Qtrue;
|
69
|
-
}
|
70
|
-
|
71
|
-
/*
|
72
|
-
Close the connection.
|
73
|
-
*/
|
74
|
-
static VALUE adapter_close(VALUE self) {
|
75
|
-
dbi::Handle *handle = adapter_handle(self);
|
76
|
-
try { handle->close(); } CATCH_DBI_EXCEPTIONS();
|
77
|
-
rb_iv_set(self, "@closed", true);
|
78
|
-
return Qtrue;
|
79
|
-
}
|
80
|
-
|
81
|
-
|
82
|
-
/*
|
83
|
-
Check if connection is closed.
|
84
|
-
*/
|
85
|
-
static VALUE adapter_closed(VALUE self) {
|
86
|
-
return rb_iv_get(self, "@closed");
|
87
|
-
}
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
/*
|
93
|
-
Shallow copy of adapter.
|
94
|
-
|
95
|
-
@note Currently not allowed.
|
96
|
-
@see Object.clone
|
97
|
-
*/
|
98
|
-
static VALUE adapter_clone(VALUE self) {
|
99
|
-
rb_raise(eSwiftRuntimeError, "clone is not allowed.");
|
100
|
-
}
|
101
|
-
|
102
|
-
/*
|
103
|
-
Commit a transaction (unit of work).
|
104
|
-
|
105
|
-
@overload commit(name = nil)
|
106
|
-
@param [Symbol, String] name Optional transaction name.
|
107
|
-
*/
|
108
|
-
static VALUE adapter_commit(int argc, VALUE *argv, VALUE self) {
|
109
|
-
VALUE save_point;
|
110
|
-
rb_scan_args(argc, argv, "01", &save_point);
|
111
|
-
dbi::Handle *handle = adapter_handle(self);
|
112
|
-
|
113
|
-
try {
|
114
|
-
NIL_P(save_point) ? handle->commit() : handle->commit(CSTRING(save_point));
|
115
|
-
}
|
116
|
-
CATCH_DBI_EXCEPTIONS();
|
117
|
-
return Qtrue;
|
118
|
-
}
|
119
|
-
|
120
|
-
/*
|
121
|
-
Shallow copy of adapter.
|
122
|
-
|
123
|
-
@note Currently not allowed.
|
124
|
-
@see Object.dup
|
125
|
-
*/
|
126
|
-
static VALUE adapter_dup(VALUE self) {
|
127
|
-
rb_raise(eSwiftRuntimeError, "dup is not allowed.");
|
128
|
-
}
|
129
|
-
|
130
|
-
/*
|
131
|
-
Escape a string.
|
132
|
-
|
133
|
-
@note Bind values do not need to be escaped.
|
134
|
-
|
135
|
-
@overload escape(value)
|
136
|
-
@param [String] value String to be escaped.
|
137
|
-
@return [String]
|
138
|
-
*/
|
139
|
-
static VALUE adapter_escape(VALUE self, VALUE value) {
|
140
|
-
if (TYPE(value) != T_STRING)
|
141
|
-
value = TO_S(value);
|
142
|
-
|
143
|
-
dbi::Handle *handle = adapter_handle(self);
|
144
|
-
try {
|
145
|
-
std::string safe = handle->escape(std::string(RSTRING_PTR(value), RSTRING_LEN(value)));
|
146
|
-
return rb_str_new(safe.data(), safe.length());
|
147
|
-
}
|
148
|
-
CATCH_DBI_EXCEPTIONS();
|
149
|
-
}
|
150
|
-
|
151
|
-
/*
|
152
|
-
Execute a single statement.
|
153
|
-
|
154
|
-
@example
|
155
|
-
result = User.execute("select * from #{User} where #{User.name} = ?", 'apple')
|
156
|
-
result.first # User object.
|
157
|
-
|
158
|
-
@overload execute(statement = '', *binds, &block)
|
159
|
-
@param [String] statement Query statement.
|
160
|
-
@param [*Object] binds Bind values.
|
161
|
-
@yield [Swift::Result]
|
162
|
-
@return [Swift::Result]
|
163
|
-
*/
|
164
|
-
static VALUE adapter_execute(int argc, VALUE *argv, VALUE self) {
|
165
|
-
VALUE statement, bind_values, block, rows, scheme = Qnil;
|
166
|
-
|
167
|
-
dbi::Handle *handle = adapter_handle(self);
|
168
|
-
rb_scan_args(argc, argv, "1*&", &statement, &bind_values, &block);
|
169
|
-
|
170
|
-
if (TYPE(statement) == T_CLASS) {
|
171
|
-
scheme = statement;
|
172
|
-
statement = rb_ary_shift(bind_values);
|
173
|
-
}
|
174
|
-
|
175
|
-
try {
|
176
|
-
Query query;
|
177
|
-
query.sql = CSTRING(statement);
|
178
|
-
query.handle = handle;
|
179
|
-
|
180
|
-
if (RARRAY_LEN(bind_values) > 0) query_bind_values(&query, bind_values);
|
181
|
-
if (dbi::_trace) dbi::logMessage(dbi::_trace_fd, dbi::formatParams(query.sql, query.bind));
|
182
|
-
|
183
|
-
if ((rows = rb_thread_blocking_region(((VALUE (*)(void*))query_execute), &query, RUBY_UBF_IO, 0)) == Qfalse)
|
184
|
-
rb_raise(query.error_klass, "%s", query.error_message);
|
185
|
-
|
186
|
-
VALUE result = result_wrap_handle(cSwiftResult, self, handle->conn()->result(), true);
|
187
|
-
if (!NIL_P(scheme))
|
188
|
-
rb_iv_set(result, "@scheme", scheme);
|
189
|
-
return rb_block_given_p() ? result_each(result) : result;
|
190
|
-
}
|
191
|
-
CATCH_DBI_EXCEPTIONS();
|
192
|
-
}
|
193
|
-
|
194
|
-
/*
|
195
|
-
Reestablish a connection.
|
196
|
-
*/
|
197
|
-
static VALUE adapter_reconnect(VALUE self) {
|
198
|
-
dbi::Handle *handle = adapter_handle(self);
|
199
|
-
try {
|
200
|
-
handle->reconnect();
|
201
|
-
rb_iv_set(self, "@closed", false);
|
202
|
-
}
|
203
|
-
CATCH_DBI_EXCEPTIONS();
|
204
|
-
return Qtrue;
|
205
|
-
}
|
206
|
-
|
207
|
-
/*
|
208
|
-
Setup a new DB connection.
|
209
|
-
|
210
|
-
You almost certainly want to setup a <tt>:default</tt> named adapter. The <tt>:default</tt> scope will be used
|
211
|
-
for unscoped calls to <tt>Swift.db</tt>.
|
212
|
-
|
213
|
-
@example
|
214
|
-
Swift.setup :default, Swift::DB::Postgres, db: 'db1'
|
215
|
-
Swift.setup :other, Swift::DB::Postgres, db: 'db2'
|
216
|
-
|
217
|
-
@overload new(options = {})
|
218
|
-
@param [Hash] options Connection options
|
219
|
-
@option options [String] :db Name.
|
220
|
-
@option options [String] :user (*nix login user)
|
221
|
-
@option options [String] :password ('')
|
222
|
-
@option options [String] :host ('localhost')
|
223
|
-
@option options [Integer] :port (DB default)
|
224
|
-
@return [Swift::Adapter]
|
225
|
-
|
226
|
-
@see Swift::DB
|
227
|
-
@see Swift::Adapter
|
228
|
-
*/
|
229
|
-
static VALUE adapter_initialize(VALUE self, VALUE options) {
|
230
|
-
VALUE db = rb_hash_aref(options, ID2SYM(rb_intern("db")));
|
231
|
-
VALUE driver = rb_hash_aref(options, ID2SYM(rb_intern("driver")));
|
232
|
-
VALUE user = rb_hash_aref(options, ID2SYM(rb_intern("user")));
|
233
|
-
|
234
|
-
if (NIL_P(db)) rb_raise(eSwiftArgumentError, "Adapter#new called without :db");
|
235
|
-
if (NIL_P(driver)) rb_raise(eSwiftArgumentError, "Adapter#new called without :driver");
|
236
|
-
|
237
|
-
user = NIL_P(user) ? current_user() : user;
|
238
|
-
VALUE extra = rb_hash_dup(options);
|
239
|
-
|
240
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("db")));
|
241
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("driver")));
|
242
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("user")));
|
243
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("password")));
|
244
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("host")));
|
245
|
-
rb_hash_delete(extra, ID2SYM(rb_intern("port")));
|
246
|
-
|
247
|
-
std::string extra_options_string = parse_extra_options(extra);
|
248
|
-
|
249
|
-
try {
|
250
|
-
DATA_PTR(self) = new dbi::Handle(
|
251
|
-
CSTRING(driver),
|
252
|
-
CSTRING(user),
|
253
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("password")))),
|
254
|
-
CSTRING(db),
|
255
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("host")))),
|
256
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("port")))),
|
257
|
-
extra_options_string.size() > 0 ? (char*)extra_options_string.c_str() : 0
|
258
|
-
);
|
259
|
-
}
|
260
|
-
CATCH_DBI_EXCEPTIONS();
|
261
|
-
|
262
|
-
rb_iv_set(self, "@options", options);
|
263
|
-
|
264
|
-
return Qnil;
|
265
|
-
}
|
266
|
-
|
267
|
-
/*
|
268
|
-
Prepare a statement for on or more executions.
|
269
|
-
|
270
|
-
@example
|
271
|
-
sth = User.prepare("select * from #{User} where #{User.name} = ?")
|
272
|
-
sth.execute('apple') #=> Result
|
273
|
-
sth.execute('benny') #=> Result
|
274
|
-
|
275
|
-
@overload prepare(statement, &block)
|
276
|
-
@param [String] statement Query statement.
|
277
|
-
@return [Swift::Statement]
|
278
|
-
*/
|
279
|
-
static VALUE adapter_prepare(int argc, VALUE *argv, VALUE self) {
|
280
|
-
VALUE sql, scheme, prepared;
|
281
|
-
dbi::AbstractStatement *statement;
|
282
|
-
|
283
|
-
rb_scan_args(argc, argv, "11", &scheme, &sql);
|
284
|
-
if (TYPE(scheme) != T_CLASS) {
|
285
|
-
sql = scheme;
|
286
|
-
scheme = Qnil;
|
287
|
-
}
|
288
|
-
|
289
|
-
dbi::Handle *handle = adapter_handle(self);
|
290
|
-
try {
|
291
|
-
// TODO: Move to statement_* constructor.
|
292
|
-
statement = handle->conn()->prepare(CSTRING(sql));
|
293
|
-
prepared = statement_wrap_handle(cSwiftStatement, self, statement);
|
294
|
-
rb_iv_set(prepared, "@scheme", scheme);
|
295
|
-
rb_iv_set(prepared, "@sql", sql);
|
296
|
-
return prepared;
|
297
|
-
}
|
298
|
-
CATCH_DBI_EXCEPTIONS();
|
299
|
-
}
|
300
|
-
|
301
|
-
/*
|
302
|
-
Rollback the current transaction.
|
303
|
-
|
304
|
-
@overload rollback(name = nil)
|
305
|
-
@param [Symbol, String] name Optional transaction name.
|
306
|
-
*/
|
307
|
-
static VALUE adapter_rollback(int argc, VALUE *argv, VALUE self) {
|
308
|
-
VALUE save_point;
|
309
|
-
dbi::Handle *handle = adapter_handle(self);
|
310
|
-
rb_scan_args(argc, argv, "01", &save_point);
|
311
|
-
|
312
|
-
try {
|
313
|
-
NIL_P(save_point) ? handle->rollback() : handle->rollback(CSTRING(save_point));
|
314
|
-
}
|
315
|
-
CATCH_DBI_EXCEPTIONS();
|
316
|
-
return Qtrue;
|
317
|
-
}
|
318
|
-
|
319
|
-
/*
|
320
|
-
Block form transaction sugar.
|
321
|
-
|
322
|
-
@overload transaction(name = nil, &block)
|
323
|
-
@param [Symbol, String] name Optional transaction name.
|
324
|
-
*/
|
325
|
-
static VALUE adapter_transaction(int argc, VALUE *argv, VALUE self) {
|
326
|
-
int status;
|
327
|
-
VALUE sp, block, block_result = Qnil;
|
328
|
-
dbi::Handle *handle = adapter_handle(self);
|
329
|
-
rb_scan_args(argc, argv, "01&", &sp, &block);
|
330
|
-
|
331
|
-
if (NIL_P(block)) rb_raise(eSwiftArgumentError, "Transaction called without a block.");
|
332
|
-
std::string save_point = NIL_P(sp) ? "SP" + dbi::generateCompactUUID() : CSTRING(sp);
|
333
|
-
|
334
|
-
try {
|
335
|
-
handle->begin(save_point);
|
336
|
-
block_result = rb_protect(rb_yield, self, &status);
|
337
|
-
if (!status && handle->transactions().size() > 0) {
|
338
|
-
handle->commit(save_point);
|
339
|
-
}
|
340
|
-
else if (status && handle->transactions().size() > 0) {
|
341
|
-
handle->rollback(save_point);
|
342
|
-
rb_jump_tag(status);
|
343
|
-
}
|
344
|
-
}
|
345
|
-
CATCH_DBI_EXCEPTIONS();
|
346
|
-
|
347
|
-
return block_result;
|
348
|
-
}
|
349
|
-
|
350
|
-
/*
|
351
|
-
Bulk insert resources.
|
352
|
-
|
353
|
-
@overload write(store, fields, stream)
|
354
|
-
@param [Swift::Scheme, String] store Write to store.
|
355
|
-
@param [Array<Swift::Attribute, String>] fields Write to fields in store.
|
356
|
-
@param [IO] stream IO to read from.
|
357
|
-
|
358
|
-
@note The format of the stream and bulk write performance are entirely down to each adapter.
|
359
|
-
*/
|
360
|
-
static VALUE adapter_write(int argc, VALUE *argv, VALUE self) {
|
361
|
-
uint64_t rows = 0;
|
362
|
-
VALUE stream, table, fields;
|
363
|
-
dbi::Handle *handle = adapter_handle(self);
|
364
|
-
|
365
|
-
rb_scan_args(argc, argv, "30", &table, &fields, &stream);
|
366
|
-
if (TYPE(stream) != T_STRING && !rb_respond_to(stream, rb_intern("read")))
|
367
|
-
rb_raise(eSwiftArgumentError, "Stream must be a String or IO object.");
|
368
|
-
if (TYPE(fields) != T_ARRAY)
|
369
|
-
rb_raise(eSwiftArgumentError, "Fields must be an Array.");
|
370
|
-
|
371
|
-
try {
|
372
|
-
Fields write_fields;
|
373
|
-
for (int i = 0; i < RARRAY_LEN(fields); i++)
|
374
|
-
write_fields << rb_ary_entry(fields, i);
|
375
|
-
|
376
|
-
/*
|
377
|
-
TODO: Adapter specific code is balls.
|
378
|
-
This is just for the friggin mysql support - mysql does not like a statement close command being send on a
|
379
|
-
handle when the writing has started.
|
380
|
-
*/
|
381
|
-
rb_gc();
|
382
|
-
|
383
|
-
if (TYPE(stream) == T_STRING) {
|
384
|
-
dbi::StringIO io(RSTRING_PTR(stream), RSTRING_LEN(stream));
|
385
|
-
rows = handle->write(RSTRING_PTR(TO_S(table)), write_fields, &io);
|
386
|
-
}
|
387
|
-
else {
|
388
|
-
AdapterIO io(stream);
|
389
|
-
rows = handle->write(RSTRING_PTR(TO_S(table)), write_fields, &io);
|
390
|
-
}
|
391
|
-
return SIZET2NUM(rows);
|
392
|
-
}
|
393
|
-
CATCH_DBI_EXCEPTIONS();
|
394
|
-
}
|
395
|
-
|
396
|
-
/*
|
397
|
-
Returns the socket fileno for the connection.
|
398
|
-
|
399
|
-
@overload fileno()
|
400
|
-
@return [Fixnum]
|
401
|
-
*/
|
402
|
-
VALUE adapter_fileno(VALUE self) {
|
403
|
-
dbi::Handle *handle = adapter_handle(self);
|
404
|
-
return INT2NUM(handle->conn()->socket());
|
405
|
-
}
|
406
|
-
|
407
|
-
/*
|
408
|
-
Executes a query asynchronously and returns the result instance.
|
409
|
-
|
410
|
-
@example
|
411
|
-
|
412
|
-
@overload async_execute(statement = '', *binds, &block)
|
413
|
-
@param [String] statement Query statement.
|
414
|
-
@param [*Object] binds Bind values.
|
415
|
-
@return [Swift::Result]
|
416
|
-
*/
|
417
|
-
VALUE adapter_async_execute(int argc, VALUE *argv, VALUE self) {
|
418
|
-
VALUE statement, bind_values, block, scheme = Qnil, result;
|
419
|
-
|
420
|
-
dbi::Handle *handle = adapter_handle(self);
|
421
|
-
rb_scan_args(argc, argv, "1*&", &statement, &bind_values, &block);
|
422
|
-
|
423
|
-
if (TYPE(statement) == T_CLASS) {
|
424
|
-
scheme = statement;
|
425
|
-
statement = rb_ary_shift(bind_values);
|
426
|
-
}
|
427
|
-
|
428
|
-
try {
|
429
|
-
dbi::AbstractResult *dbi_result;
|
430
|
-
if (RARRAY_LEN(bind_values) > 0) {
|
431
|
-
Query query;
|
432
|
-
query_bind_values(&query, bind_values);
|
433
|
-
dbi_result = handle->conn()->aexecute(CSTRING(statement), query.bind);
|
434
|
-
}
|
435
|
-
else
|
436
|
-
dbi_result = handle->conn()->aexecute(CSTRING(statement));
|
437
|
-
|
438
|
-
result = result_wrap_handle(cSwiftResult, self, dbi_result, true);
|
439
|
-
if (!NIL_P(scheme))
|
440
|
-
rb_iv_set(result, "@scheme", scheme);
|
441
|
-
|
442
|
-
// if block given, just use rb_thread_select
|
443
|
-
if (rb_block_given_p()) {
|
444
|
-
rb_thread_wait_fd(handle->socket());
|
445
|
-
while (dbi_result->consumeResult());
|
446
|
-
dbi_result->prepareResult();
|
447
|
-
}
|
448
|
-
}
|
449
|
-
CATCH_DBI_EXCEPTIONS();
|
450
|
-
|
451
|
-
return rb_block_given_p() ? result_each(result) : result;
|
452
|
-
}
|
453
|
-
|
454
|
-
void init_swift_adapter() {
|
455
|
-
VALUE mSwift = rb_define_module("Swift");
|
456
|
-
cSwiftAdapter = rb_define_class_under(mSwift, "Adapter", rb_cObject);
|
457
|
-
|
458
|
-
rb_define_method(cSwiftAdapter, "begin", RUBY_METHOD_FUNC(adapter_begin), -1);
|
459
|
-
rb_define_method(cSwiftAdapter, "clone", RUBY_METHOD_FUNC(adapter_clone), 0);
|
460
|
-
rb_define_method(cSwiftAdapter, "close", RUBY_METHOD_FUNC(adapter_close), 0);
|
461
|
-
rb_define_method(cSwiftAdapter, "closed?", RUBY_METHOD_FUNC(adapter_closed), 0);
|
462
|
-
rb_define_method(cSwiftAdapter, "commit", RUBY_METHOD_FUNC(adapter_commit), -1);
|
463
|
-
rb_define_method(cSwiftAdapter, "dup", RUBY_METHOD_FUNC(adapter_dup), 0);
|
464
|
-
rb_define_method(cSwiftAdapter, "escape", RUBY_METHOD_FUNC(adapter_escape), 1);
|
465
|
-
rb_define_method(cSwiftAdapter, "execute", RUBY_METHOD_FUNC(adapter_execute), -1);
|
466
|
-
rb_define_method(cSwiftAdapter, "initialize", RUBY_METHOD_FUNC(adapter_initialize), 1);
|
467
|
-
rb_define_method(cSwiftAdapter, "prepare", RUBY_METHOD_FUNC(adapter_prepare), -1);
|
468
|
-
rb_define_method(cSwiftAdapter, "rollback", RUBY_METHOD_FUNC(adapter_rollback), -1);
|
469
|
-
rb_define_method(cSwiftAdapter, "transaction", RUBY_METHOD_FUNC(adapter_transaction), -1);
|
470
|
-
rb_define_method(cSwiftAdapter, "write", RUBY_METHOD_FUNC(adapter_write), -1);
|
471
|
-
rb_define_method(cSwiftAdapter, "reconnect", RUBY_METHOD_FUNC(adapter_reconnect), 0);
|
472
|
-
|
473
|
-
// stuff you need for async
|
474
|
-
rb_define_method(cSwiftAdapter, "fileno", RUBY_METHOD_FUNC(adapter_fileno), 0);
|
475
|
-
rb_define_method(cSwiftAdapter, "async_execute", RUBY_METHOD_FUNC(adapter_async_execute), -1);
|
476
|
-
|
477
|
-
rb_define_alloc_func(cSwiftAdapter, adapter_alloc);
|
478
|
-
}
|
479
|
-
|
data/ext/adapter.h
DELETED
data/ext/adapter_io.cc
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
#include "adapter_io.h"
|
2
|
-
|
3
|
-
AdapterIO::AdapterIO(VALUE s) {
|
4
|
-
stream = s;
|
5
|
-
}
|
6
|
-
|
7
|
-
std::string& AdapterIO::read() {
|
8
|
-
VALUE response = rb_funcall(stream, rb_intern("read"), 0);
|
9
|
-
if (response == Qnil) {
|
10
|
-
return empty;
|
11
|
-
}
|
12
|
-
else {
|
13
|
-
// Attempt TO_S first before complaining?
|
14
|
-
if (TYPE(response) != T_STRING) {
|
15
|
-
rb_raise(
|
16
|
-
CONST_GET(rb_mKernel, "ArgumentError"),
|
17
|
-
"Write can only process string data. You need to stringify values returned in the callback."
|
18
|
-
);
|
19
|
-
}
|
20
|
-
stringdata = std::string(RSTRING_PTR(response), RSTRING_LEN(response));
|
21
|
-
return stringdata;
|
22
|
-
}
|
23
|
-
}
|
24
|
-
|
25
|
-
uint32_t AdapterIO::read(char *buffer, uint32_t length) {
|
26
|
-
VALUE response = rb_funcall(stream, rb_intern("read"), 1, INT2NUM(length));
|
27
|
-
if (response == Qnil) {
|
28
|
-
return 0;
|
29
|
-
}
|
30
|
-
else {
|
31
|
-
length = length < RSTRING_LEN(response) ? length : RSTRING_LEN(response);
|
32
|
-
memcpy(buffer, RSTRING_PTR(response), length);
|
33
|
-
return length;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
|
37
|
-
void AdapterIO::write(const char *str) {
|
38
|
-
rb_funcall(stream, rb_intern("write"), 1, rb_str_new2(str));
|
39
|
-
}
|
40
|
-
|
41
|
-
void AdapterIO::write(const char *str, uint64_t l) {
|
42
|
-
rb_funcall(stream, rb_intern("write"), 1, rb_str_new(str, l));
|
43
|
-
}
|
44
|
-
|
45
|
-
bool AdapterIO::readline(std::string &line) {
|
46
|
-
VALUE response = rb_funcall(stream, rb_intern("gets"), 0);
|
47
|
-
if (response == Qnil) {
|
48
|
-
return false;
|
49
|
-
}
|
50
|
-
else {
|
51
|
-
line = std::string(RSTRING_PTR(response), RSTRING_LEN(response));
|
52
|
-
return true;
|
53
|
-
}
|
54
|
-
}
|
55
|
-
|
56
|
-
char* AdapterIO::readline() {
|
57
|
-
return readline(stringdata) ? (char*)stringdata.c_str() : 0;
|
58
|
-
}
|
59
|
-
|
60
|
-
void AdapterIO::truncate() {
|
61
|
-
rb_funcall(stream, rb_intern("truncate"), 0);
|
62
|
-
}
|
data/ext/adapter_io.h
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
#ifndef SWIFT_ADAPTER_IO_H
|
2
|
-
#define SWIFT_ADAPTER_IO_H
|
3
|
-
|
4
|
-
#include "swift.h"
|
5
|
-
|
6
|
-
class AdapterIO : public dbi::IO {
|
7
|
-
private:
|
8
|
-
VALUE stream;
|
9
|
-
std::string stringdata, empty;
|
10
|
-
public:
|
11
|
-
AdapterIO(VALUE);
|
12
|
-
std::string& read();
|
13
|
-
uint32_t read(char *, uint32_t);
|
14
|
-
|
15
|
-
void write(const char *);
|
16
|
-
void write(const char *, uint64_t);
|
17
|
-
|
18
|
-
void truncate();
|
19
|
-
|
20
|
-
bool readline(string&);
|
21
|
-
char* readline();
|
22
|
-
};
|
23
|
-
|
24
|
-
#endif
|
data/ext/attribute.cc
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
#include "attribute.h"
|
2
|
-
|
3
|
-
ID fcall;
|
4
|
-
|
5
|
-
VALUE attribute_default(VALUE self) {
|
6
|
-
VALUE value = rb_iv_get(self, "@default");
|
7
|
-
|
8
|
-
if (NIL_P(value) || rb_obj_is_kind_of(value, rb_cNumeric) || rb_special_const_p(value))
|
9
|
-
return value;
|
10
|
-
else if (rb_respond_to(value, fcall))
|
11
|
-
return rb_funcall(value, fcall, 0);
|
12
|
-
else
|
13
|
-
return rb_obj_dup(value);
|
14
|
-
}
|
15
|
-
|
16
|
-
void init_swift_attribute() {
|
17
|
-
VALUE mSwift = rb_define_module("Swift");
|
18
|
-
VALUE cSwiftAttribute = rb_define_class_under(mSwift, "Attribute", rb_cObject);
|
19
|
-
|
20
|
-
fcall = rb_intern("call");
|
21
|
-
rb_define_method(cSwiftAttribute, "default", RUBY_METHOD_FUNC(attribute_default), 0);
|
22
|
-
}
|