swift 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/API.rdoc +16 -12
- data/{README.rdoc → README.md} +120 -66
- data/Rakefile +0 -1
- data/VERSION +1 -1
- data/ext/adapter.cc +84 -5
- data/ext/datetime.cc +96 -0
- data/ext/datetime.h +12 -0
- data/ext/extconf.rb +5 -4
- data/ext/query.cc +42 -18
- data/ext/query.h +2 -1
- data/ext/result.cc +65 -148
- data/ext/result.h +1 -1
- data/ext/statement.cc +1 -1
- data/ext/swift.cc +1 -2
- data/ext/swift.h +4 -2
- data/lib/swift/adapter/sql.rb +11 -1
- data/lib/swift/db.rb +14 -1
- data/lib/swift/type.rb +9 -2
- data/lib/swift.rb +9 -1
- data/swift.gemspec +8 -13
- data/test/test_adapter.rb +18 -4
- data/test/test_async.rb +28 -0
- data/test/test_datetime_parser.rb +12 -0
- data/test/test_error.rb +23 -0
- data/test/test_scheme.rb +1 -1
- data/test/test_timestamps.rb +22 -12
- data/test/test_types.rb +2 -2
- metadata +10 -23
- data/ext/pool.cc +0 -96
- data/ext/pool.h +0 -8
- data/ext/request.cc +0 -44
- data/ext/request.h +0 -10
- data/lib/swift/pool.rb +0 -76
- data/test/test_pool.rb +0 -38
data/test/test_async.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
describe 'Adapter' do
|
4
|
+
supported_by Swift::DB::Postgres do
|
5
|
+
describe 'async operations' do
|
6
|
+
it 'can runs queries async' do
|
7
|
+
rows = []
|
8
|
+
pool = 3.times.map.with_index {|n| Swift.setup n, Swift::DB::Postgres, db: 'swift' }
|
9
|
+
|
10
|
+
Thread.new do
|
11
|
+
pool[0].async_execute('select pg_sleep(0.3), 1 as query_id') {|row| rows << row[:query_id]}
|
12
|
+
end
|
13
|
+
|
14
|
+
Thread.new do
|
15
|
+
pool[1].async_execute('select pg_sleep(0.2), 2 as query_id') {|row| rows << row[:query_id]}
|
16
|
+
end
|
17
|
+
|
18
|
+
Thread.new do
|
19
|
+
pool[2].async_execute('select pg_sleep(0.1), 3 as query_id') {|row| rows << row[:query_id]}
|
20
|
+
end
|
21
|
+
|
22
|
+
Thread.list.reject {|thread| Thread.current == thread}.each(&:join)
|
23
|
+
|
24
|
+
assert_equal [3, 2, 1], rows
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
|
3
|
+
describe 'DateTimeParser' do
|
4
|
+
it 'should handle ymd style values' do
|
5
|
+
text = "2011-12-31 09:01:02.80300899 +1100"
|
6
|
+
time = DateTime.parse(text)
|
7
|
+
result = Swift::DateTime.parse(text)
|
8
|
+
|
9
|
+
assert_equal time.strftime('%F %T %z'), result.strftime('%F %T %z')
|
10
|
+
assert_equal time.second_fraction.to_f.round(8), result.second_fraction.to_f.round(8)
|
11
|
+
end
|
12
|
+
end
|
data/test/test_error.rb
CHANGED
@@ -23,4 +23,27 @@ describe 'Error' do
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
end
|
26
|
+
|
27
|
+
supported_by Swift::DB::Postgres do
|
28
|
+
describe 'execute' do
|
29
|
+
before do
|
30
|
+
Swift.db do |db|
|
31
|
+
db.execute %q{drop table if exists users}
|
32
|
+
db.execute %q{create table users(id integer, name text, primary key(id))}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'throws connection error on connection failures' do
|
37
|
+
select1 = Swift.db.prepare("select * from users")
|
38
|
+
select2 = Swift.db.prepare("select * from users where id > ?")
|
39
|
+
|
40
|
+
Swift.db.close
|
41
|
+
|
42
|
+
assert_raises(SwiftConnectionError) { select1.execute }
|
43
|
+
assert_raises(SwiftConnectionError) { select2.execute(1) }
|
44
|
+
assert_raises(SwiftConnectionError) { Swift.db.execute("select * from users") }
|
45
|
+
assert_raises(SwiftConnectionError) { Swift.db.execute("select * from users where id > ?", 1) }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
26
49
|
end
|
data/test/test_scheme.rb
CHANGED
@@ -10,7 +10,7 @@ describe 'scheme' do
|
|
10
10
|
attribute :height, Swift::Type::Float, default: 172.25
|
11
11
|
attribute :email, Swift::Type::String
|
12
12
|
attribute :verified, Swift::Type::Boolean, default: false
|
13
|
-
attribute :created_at, Swift::Type::
|
13
|
+
attribute :created_at, Swift::Type::DateTime, default: proc { Time.now }
|
14
14
|
|
15
15
|
migrations do |db|
|
16
16
|
db.execute %q{
|
data/test/test_timestamps.rb
CHANGED
@@ -1,13 +1,18 @@
|
|
1
1
|
require_relative 'helper'
|
2
|
-
require 'date'
|
3
2
|
|
4
3
|
describe 'Adapter' do
|
5
4
|
supported_by Swift::DB::Postgres do
|
6
5
|
%w(America/Chicago Australia/Melbourne).each do |timezone|
|
7
6
|
describe 'time parsing in %s' % timezone do
|
8
7
|
before do
|
9
|
-
@db = Swift.db
|
10
8
|
ENV['TZ'] = ":#{timezone}"
|
9
|
+
@db = Swift.db
|
10
|
+
@db.execute 'create table datetime_test(id serial, ts timestamp with time zone)'
|
11
|
+
@db.execute "set time zone '#{timezone}'"
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
@db.execute 'drop table datetime_test'
|
11
16
|
end
|
12
17
|
|
13
18
|
it 'should parse timestamps and do conversion accordingly' do
|
@@ -25,14 +30,19 @@ describe 'Adapter' do
|
|
25
30
|
assert_timestamp_like time, fetch_timestamp_at(time), 'DST off'
|
26
31
|
end
|
27
32
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
it 'should store fractional seconds' do
|
34
|
+
time = Time.now
|
35
|
+
datetime = time.to_datetime
|
36
|
+
|
37
|
+
@db.execute 'insert into datetime_test(ts) values (?), (?)', time, datetime
|
38
|
+
values = @db.execute('select ts from datetime_test').map(&:values).flatten
|
39
|
+
|
40
|
+
assert_equal 2, values.size
|
41
|
+
|
42
|
+
# postgres resolution is microsecond.
|
43
|
+
values.each do |value|
|
44
|
+
assert_equal datetime.strftime('%F %T %z'), value.strftime('%F %T %z')
|
45
|
+
assert_equal datetime.second_fraction.to_f.round(6), value.second_fraction.to_f.round(6)
|
36
46
|
end
|
37
47
|
end
|
38
48
|
|
@@ -49,8 +59,8 @@ describe 'Adapter' do
|
|
49
59
|
|
50
60
|
def assert_timestamp_like expect, given, comment
|
51
61
|
match = Regexp.new expect.to_time.strftime('%F %T')
|
52
|
-
assert_kind_of
|
53
|
-
assert_match match, given.strftime('%F %T'), comment
|
62
|
+
assert_kind_of DateTime, given
|
63
|
+
assert_match match, given.to_time.strftime('%F %T'), comment
|
54
64
|
end
|
55
65
|
end
|
56
66
|
end
|
data/test/test_types.rb
CHANGED
@@ -37,10 +37,10 @@ describe 'Adapter' do
|
|
37
37
|
assert_kind_of TrueClass, result[:hacker]
|
38
38
|
assert_kind_of FalseClass, result[:slacker]
|
39
39
|
assert_kind_of Date, result[:created]
|
40
|
-
assert_kind_of
|
40
|
+
assert_kind_of DateTime, result[:updated]
|
41
41
|
|
42
42
|
assert_equal dt, result[:updated].strftime('%F %T')
|
43
|
-
assert_equal 65000, result[:updated].usec unless @db.kind_of?(Swift::DB::Mysql)
|
43
|
+
assert_equal 65000, result[:updated].to_time.usec unless @db.kind_of?(Swift::DB::Mysql)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
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: 0.14.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:
|
13
|
+
date: 2012-03-21 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: minitest
|
17
|
-
requirement: &
|
17
|
+
requirement: &10639060 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,18 +22,7 @@ dependencies:
|
|
22
22
|
version: 1.7.0
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: eventmachine
|
28
|
-
requirement: &6951140 !ruby/object:Gem::Requirement
|
29
|
-
none: false
|
30
|
-
requirements:
|
31
|
-
- - ! '>='
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: *6951140
|
25
|
+
version_requirements: *10639060
|
37
26
|
description: A rational rudimentary database abstraction.
|
38
27
|
email:
|
39
28
|
- shane.hanna@gmail.com
|
@@ -43,11 +32,11 @@ extensions:
|
|
43
32
|
- ext/extconf.rb
|
44
33
|
extra_rdoc_files:
|
45
34
|
- LICENSE
|
46
|
-
- README.
|
35
|
+
- README.md
|
47
36
|
files:
|
48
37
|
- API.rdoc
|
49
38
|
- LICENSE
|
50
|
-
- README.
|
39
|
+
- README.md
|
51
40
|
- Rakefile
|
52
41
|
- VERSION
|
53
42
|
- ext/adapter.cc
|
@@ -56,13 +45,11 @@ files:
|
|
56
45
|
- ext/adapter_io.h
|
57
46
|
- ext/attribute.cc
|
58
47
|
- ext/attribute.h
|
48
|
+
- ext/datetime.cc
|
49
|
+
- ext/datetime.h
|
59
50
|
- ext/extconf.rb
|
60
|
-
- ext/pool.cc
|
61
|
-
- ext/pool.h
|
62
51
|
- ext/query.cc
|
63
52
|
- ext/query.h
|
64
|
-
- ext/request.cc
|
65
|
-
- ext/request.h
|
66
53
|
- ext/result.cc
|
67
54
|
- ext/result.h
|
68
55
|
- ext/statement.cc
|
@@ -77,7 +64,6 @@ files:
|
|
77
64
|
- lib/swift/header.rb
|
78
65
|
- lib/swift/identity_map.rb
|
79
66
|
- lib/swift/migrations.rb
|
80
|
-
- lib/swift/pool.rb
|
81
67
|
- lib/swift/scheme.rb
|
82
68
|
- lib/swift/type.rb
|
83
69
|
- lib/swift/validations.rb
|
@@ -86,11 +72,12 @@ files:
|
|
86
72
|
- test/house-explode.jpg
|
87
73
|
- test/minitest_teardown_hack.rb
|
88
74
|
- test/test_adapter.rb
|
75
|
+
- test/test_async.rb
|
76
|
+
- test/test_datetime_parser.rb
|
89
77
|
- test/test_encoding.rb
|
90
78
|
- test/test_error.rb
|
91
79
|
- test/test_identity_map.rb
|
92
80
|
- test/test_io.rb
|
93
|
-
- test/test_pool.rb
|
94
81
|
- test/test_scheme.rb
|
95
82
|
- test/test_swift.rb
|
96
83
|
- test/test_timestamps.rb
|
data/ext/pool.cc
DELETED
@@ -1,96 +0,0 @@
|
|
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
|
-
VALUE pool_init(VALUE self, VALUE n, VALUE options) {
|
22
|
-
VALUE db = rb_hash_aref(options, ID2SYM(rb_intern("db")));
|
23
|
-
VALUE user = rb_hash_aref(options, ID2SYM(rb_intern("user")));
|
24
|
-
VALUE driver = rb_hash_aref(options, ID2SYM(rb_intern("driver")));
|
25
|
-
|
26
|
-
if (NIL_P(db)) rb_raise(eSwiftArgumentError, "Pool#new called without :db");
|
27
|
-
if (NIL_P(driver)) rb_raise(eSwiftArgumentError, "#new called without :driver");
|
28
|
-
|
29
|
-
user = NIL_P(user) ? current_user() : user;
|
30
|
-
if (NUM2INT(n) < 1) rb_raise(eSwiftArgumentError, "Pool#new called with invalid pool size.");
|
31
|
-
|
32
|
-
try {
|
33
|
-
DATA_PTR(self) = new dbi::ConnectionPool(
|
34
|
-
NUM2INT(n),
|
35
|
-
CSTRING(driver),
|
36
|
-
CSTRING(user),
|
37
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("password")))),
|
38
|
-
CSTRING(db),
|
39
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("host")))),
|
40
|
-
CSTRING(rb_hash_aref(options, ID2SYM(rb_intern("port"))))
|
41
|
-
);
|
42
|
-
|
43
|
-
rb_iv_set(self, "@timezone", rb_hash_aref(options, ID2SYM(rb_intern("timezone"))));
|
44
|
-
}
|
45
|
-
CATCH_DBI_EXCEPTIONS();
|
46
|
-
|
47
|
-
return Qnil;
|
48
|
-
}
|
49
|
-
|
50
|
-
void pool_callback(dbi::AbstractResult *result) {
|
51
|
-
VALUE callback = (VALUE)result->context;
|
52
|
-
|
53
|
-
// NOTE: C Result object will be deallocated in dbic++
|
54
|
-
if (!NIL_P(callback)) {
|
55
|
-
VALUE obj = result_wrap_handle(cSwiftResult, 0, result, false);
|
56
|
-
rb_iv_set(obj, "@timezone", rb_iv_get(callback, "@timezone"));
|
57
|
-
rb_proc_call(callback, rb_ary_new3(1, obj));
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
VALUE pool_execute(int argc, VALUE *argv, VALUE self) {
|
62
|
-
int n;
|
63
|
-
VALUE sql;
|
64
|
-
VALUE bind_values;
|
65
|
-
VALUE callback;
|
66
|
-
VALUE request = Qnil;
|
67
|
-
|
68
|
-
dbi::ConnectionPool *pool = pool_handle(self);
|
69
|
-
rb_scan_args(argc, argv, "1*&", &sql, &bind_values, &callback);
|
70
|
-
|
71
|
-
// The only way to pass timezone to the C callback routine.
|
72
|
-
if (NIL_P(callback))
|
73
|
-
rb_raise(eSwiftArgumentError, "No block given in Pool#execute");
|
74
|
-
else
|
75
|
-
rb_iv_set(callback, "@timezone", rb_iv_get(self, "@timezone"));
|
76
|
-
|
77
|
-
try {
|
78
|
-
Query query;
|
79
|
-
query_bind_values(&query, bind_values);
|
80
|
-
request = request_alloc(cSwiftRequest);
|
81
|
-
DATA_PTR(request) = pool->execute(CSTRING(sql), query.bind, pool_callback, (void*)callback);
|
82
|
-
return request;
|
83
|
-
}
|
84
|
-
CATCH_DBI_EXCEPTIONS();
|
85
|
-
}
|
86
|
-
|
87
|
-
void init_swift_pool() {
|
88
|
-
VALUE mSwift = rb_define_module("Swift");
|
89
|
-
VALUE mDB = rb_define_module_under(mSwift, "DB");
|
90
|
-
cSwiftPool = rb_define_class_under(mDB, "Pool", rb_cObject);
|
91
|
-
|
92
|
-
rb_define_alloc_func(cSwiftPool, pool_alloc);
|
93
|
-
|
94
|
-
rb_define_method(cSwiftPool, "initialize", RUBY_METHOD_FUNC(pool_init), 2);
|
95
|
-
rb_define_method(cSwiftPool, "execute", RUBY_METHOD_FUNC(pool_execute), -1);
|
96
|
-
}
|
data/ext/pool.h
DELETED
data/ext/request.cc
DELETED
@@ -1,44 +0,0 @@
|
|
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
DELETED
data/lib/swift/pool.rb
DELETED
@@ -1,76 +0,0 @@
|
|
1
|
-
require 'eventmachine'
|
2
|
-
|
3
|
-
module Swift
|
4
|
-
class Pool
|
5
|
-
module Handler
|
6
|
-
def initialize request, pool
|
7
|
-
@request, @pool = request, pool
|
8
|
-
end
|
9
|
-
|
10
|
-
def socket
|
11
|
-
@request.socket
|
12
|
-
end
|
13
|
-
|
14
|
-
def notify_readable
|
15
|
-
if @request.process
|
16
|
-
detach
|
17
|
-
@pool.detach self
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def notify_writable
|
22
|
-
notify_readable
|
23
|
-
end
|
24
|
-
end # Handler
|
25
|
-
|
26
|
-
|
27
|
-
def initialize size, options
|
28
|
-
@pool = Swift::DB::Pool.new size, options
|
29
|
-
|
30
|
-
# used to be used for db2
|
31
|
-
@writable = false
|
32
|
-
@pending = {}
|
33
|
-
@queue = []
|
34
|
-
end
|
35
|
-
|
36
|
-
def attach c
|
37
|
-
@pending[c] = true
|
38
|
-
end
|
39
|
-
|
40
|
-
def detach c
|
41
|
-
@pending.delete(c)
|
42
|
-
unless @queue.empty?
|
43
|
-
sql, bind, callback = @queue.shift
|
44
|
-
execute(sql, *bind, &callback)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def attached? fd
|
49
|
-
@pending.keys.select{|c| c.socket == fd}.length > 0
|
50
|
-
end
|
51
|
-
|
52
|
-
def execute sql, *bind, &callback
|
53
|
-
request = @pool.execute sql, *bind, &callback
|
54
|
-
# NOTE EM segfaults if we try to attach same fd twice.
|
55
|
-
if request && !attached?(request.socket)
|
56
|
-
EM.watch(request.socket, Handler, request, self) do |c|
|
57
|
-
attach c
|
58
|
-
c.notify_writable = @writable
|
59
|
-
c.notify_readable = true
|
60
|
-
end
|
61
|
-
else
|
62
|
-
@queue << [ sql, bind, callback ]
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def run &block
|
67
|
-
EM.run{ yield self }
|
68
|
-
end
|
69
|
-
end # Pool
|
70
|
-
|
71
|
-
def self.pool size, name = :default, &block
|
72
|
-
pool = Pool.new(size, Swift.db(name).options)
|
73
|
-
pool.run(&block) if block_given?
|
74
|
-
pool
|
75
|
-
end
|
76
|
-
end # Swift
|
data/test/test_pool.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require_relative 'helper'
|
2
|
-
require 'swift/pool'
|
3
|
-
|
4
|
-
describe 'Adapter' do
|
5
|
-
supported_by Swift::DB::Postgres, Swift::DB::Mysql do
|
6
|
-
describe 'Asynchronous connection pool' do
|
7
|
-
before do
|
8
|
-
Swift.db do |db|
|
9
|
-
db.execute %q{drop table if exists users}
|
10
|
-
db.execute %Q{create table users(name varchar(64))}
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
it 'creates connection pool and runs queries' do
|
15
|
-
rows = []
|
16
|
-
Swift.pool(5) do |pool|
|
17
|
-
assert pool
|
18
|
-
assert Swift.db.write('users', %w{name}, StringIO.new("user1\nuser2\nuser3\n"))
|
19
|
-
pool.execute('select * from users') do |rs|
|
20
|
-
rows += rs.to_a
|
21
|
-
Thread.new do
|
22
|
-
sleep 0.25
|
23
|
-
pool.execute('select * from users order by name desc') {|rs| rows += rs.to_a; EM.stop }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
pool.execute('select * from users') do |rs|
|
27
|
-
rows += rs.to_a
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
data = %w(user1 user2 user3)
|
32
|
-
|
33
|
-
assert_equal 9, rows.length
|
34
|
-
assert_equal data*2 + data.reverse, rows.map {|r| r[:name] }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|