sequel 0.2.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +76 -0
- data/Rakefile +1 -1
- data/lib/sequel.rb +1 -1
- data/lib/sequel/ado.rb +17 -0
- data/lib/sequel/array_keys.rb +233 -0
- data/lib/sequel/connection_pool.rb +14 -0
- data/lib/sequel/core_ext.rb +3 -3
- data/lib/sequel/database.rb +25 -7
- data/lib/sequel/dataset.rb +46 -15
- data/lib/sequel/dataset/convenience.rb +27 -2
- data/lib/sequel/dataset/sequelizer.rb +2 -2
- data/lib/sequel/dataset/sql.rb +49 -18
- data/lib/sequel/dbi.rb +17 -0
- data/lib/sequel/model.rb +276 -82
- data/lib/sequel/model/base.rb +41 -30
- data/lib/sequel/model/caching.rb +42 -0
- data/lib/sequel/model/hooks.rb +113 -27
- data/lib/sequel/model/record.rb +78 -21
- data/lib/sequel/model/relations.rb +5 -0
- data/lib/sequel/model/schema.rb +11 -1
- data/lib/sequel/mysql.rb +61 -17
- data/lib/sequel/odbc.rb +42 -1
- data/lib/sequel/postgres.rb +45 -0
- data/lib/sequel/pretty_table.rb +14 -11
- data/lib/sequel/schema/schema_generator.rb +9 -3
- data/lib/sequel/sqlite.rb +33 -1
- data/spec/adapters/mysql_spec.rb +69 -15
- data/spec/adapters/postgres_spec.rb +66 -12
- data/spec/adapters/sqlite_spec.rb +113 -1
- data/spec/array_keys_spec.rb +544 -0
- data/spec/connection_pool_spec.rb +83 -0
- data/spec/database_spec.rb +81 -2
- data/spec/dataset_spec.rb +227 -9
- data/spec/model_spec.rb +392 -68
- data/spec/schema_spec.rb +7 -0
- metadata +5 -2
@@ -267,4 +267,87 @@ context "A connection pool with a max size of 5" do
|
|
267
267
|
@pool.available_connections.size.should == 5
|
268
268
|
@pool.allocated.should be_empty
|
269
269
|
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "ConnectionPool#disconnect" do
|
273
|
+
setup do
|
274
|
+
@count = 0
|
275
|
+
@pool = Sequel::ConnectionPool.new(5) {{:id => @count += 1}}
|
276
|
+
end
|
277
|
+
|
278
|
+
specify "should invoke the given block for each available connection" do
|
279
|
+
threads = []
|
280
|
+
stop = nil
|
281
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
|
282
|
+
while @pool.size < 5
|
283
|
+
sleep 0.2
|
284
|
+
end
|
285
|
+
stop = true
|
286
|
+
sleep 0.2
|
287
|
+
|
288
|
+
@pool.size.should == 5
|
289
|
+
@pool.available_connections.size.should == 5
|
290
|
+
@pool.available_connections.each {|c| c[:id].should_not be_nil}
|
291
|
+
conns = []
|
292
|
+
@pool.disconnect {|c| conns << c}
|
293
|
+
conns.size.should == 5
|
294
|
+
end
|
295
|
+
|
296
|
+
specify "should remove all available connections" do
|
297
|
+
threads = []
|
298
|
+
stop = nil
|
299
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
|
300
|
+
while @pool.size < 5
|
301
|
+
sleep 0.2
|
302
|
+
end
|
303
|
+
stop = true
|
304
|
+
sleep 0.2
|
305
|
+
|
306
|
+
@pool.size.should == 5
|
307
|
+
@pool.disconnect
|
308
|
+
@pool.size.should == 0
|
309
|
+
end
|
310
|
+
|
311
|
+
specify "should not touch connections in use" do
|
312
|
+
threads = []
|
313
|
+
stop = nil
|
314
|
+
5.times {|i| threads << Thread.new {@pool.hold {|c| while !stop;sleep 0.1;end}}; sleep 0.1}
|
315
|
+
while @pool.size < 5
|
316
|
+
sleep 0.2
|
317
|
+
end
|
318
|
+
stop = true
|
319
|
+
sleep 0.2
|
320
|
+
|
321
|
+
@pool.size.should == 5
|
322
|
+
|
323
|
+
@pool.hold do |conn|
|
324
|
+
@pool.available_connections.size.should == 4
|
325
|
+
@pool.available_connections.each {|c| c.should_not be(conn)}
|
326
|
+
conns = []
|
327
|
+
@pool.disconnect {|c| conns << c}
|
328
|
+
conns.size.should == 4
|
329
|
+
end
|
330
|
+
@pool.size.should == 1
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
context "SingleThreadedPool" do
|
335
|
+
setup do
|
336
|
+
@pool = Sequel::SingleThreadedPool.new {1234}
|
337
|
+
end
|
338
|
+
|
339
|
+
specify "should provide a #hold method" do
|
340
|
+
conn = nil
|
341
|
+
@pool.hold {|c| conn = c}
|
342
|
+
conn.should == 1234
|
343
|
+
end
|
344
|
+
|
345
|
+
specify "should provide a #disconnect method" do
|
346
|
+
@pool.hold {|c|}
|
347
|
+
@pool.conn.should == 1234
|
348
|
+
conn = nil
|
349
|
+
@pool.disconnect {|c| conn = c}
|
350
|
+
conn.should == 1234
|
351
|
+
@pool.conn.should be_nil
|
352
|
+
end
|
270
353
|
end
|
data/spec/database_spec.rb
CHANGED
@@ -34,6 +34,12 @@ context "Database#connect" do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
context "Database#disconnect" do
|
38
|
+
specify "should raise NotImplementedError" do
|
39
|
+
proc {Sequel::Database.new.disconnect}.should raise_error(NotImplementedError)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
37
43
|
context "Database#uri" do
|
38
44
|
setup do
|
39
45
|
@c = Class.new(Sequel::Database) do
|
@@ -125,16 +131,21 @@ context "Database#<<" do
|
|
125
131
|
"CREATE TABLE items (a integer, b text, c integer); DROP TABLE old_items;"
|
126
132
|
end
|
127
133
|
|
128
|
-
specify "should remove comments and whitespace from
|
134
|
+
specify "should remove comments and whitespace from arrays" do
|
129
135
|
s = %[
|
130
136
|
--
|
131
137
|
CREATE TABLE items (a integer, /*b integer*/
|
132
138
|
b text, c integer); \r\n
|
133
139
|
DROP TABLE old_items;
|
134
|
-
]
|
140
|
+
].split($/)
|
135
141
|
(@db << s).should ==
|
136
142
|
"CREATE TABLE items (a integer, b text, c integer); DROP TABLE old_items;"
|
137
143
|
end
|
144
|
+
|
145
|
+
specify "should not remove comments and whitespace from strings" do
|
146
|
+
s = "INSERT INTO items VALUES ('---abc')"
|
147
|
+
(@db << s).should == s
|
148
|
+
end
|
138
149
|
end
|
139
150
|
|
140
151
|
context "Database#synchronize" do
|
@@ -487,6 +498,15 @@ context "A database" do
|
|
487
498
|
db.should be_single_threaded
|
488
499
|
db.should_not be_multi_threaded
|
489
500
|
end
|
501
|
+
|
502
|
+
specify "should accept a logger object" do
|
503
|
+
db = Sequel::Database.new
|
504
|
+
s = "I'm a logger"
|
505
|
+
db.logger = s
|
506
|
+
db.logger.should be(s)
|
507
|
+
db.logger = nil
|
508
|
+
db.logger.should be_nil
|
509
|
+
end
|
490
510
|
end
|
491
511
|
|
492
512
|
context "Database#dataset" do
|
@@ -499,4 +519,63 @@ context "Database#dataset" do
|
|
499
519
|
@d.should be_a_kind_of(Sequel::Dataset)
|
500
520
|
@d.sql.should == "SELECT x FROM y"
|
501
521
|
end
|
522
|
+
end
|
523
|
+
|
524
|
+
context "Database#fetch" do
|
525
|
+
setup do
|
526
|
+
@db = Sequel::Database.new
|
527
|
+
c = Class.new(Sequel::Dataset) do
|
528
|
+
def fetch_rows(sql); yield({:sql => sql}); end
|
529
|
+
end
|
530
|
+
@db.meta_def(:dataset) {c.new(self)}
|
531
|
+
end
|
532
|
+
|
533
|
+
specify "should create a dataset and invoke its fetch_rows method with the given sql" do
|
534
|
+
sql = nil
|
535
|
+
@db.fetch('select * from xyz') {|r| sql = r[:sql]}
|
536
|
+
sql.should == 'select * from xyz'
|
537
|
+
end
|
538
|
+
|
539
|
+
specify "should format the given sql with any additional arguments" do
|
540
|
+
sql = nil
|
541
|
+
@db.fetch('select * from xyz where x = ? and y = ?', 15, 'abc') {|r| sql = r[:sql]}
|
542
|
+
sql.should == "select * from xyz where x = 15 and y = 'abc'"
|
543
|
+
|
544
|
+
# and Aman Gupta's example
|
545
|
+
@db.fetch('select name from table where name = ? or id in (?)',
|
546
|
+
'aman', [3,4,7]) {|r| sql = r[:sql]}
|
547
|
+
sql.should == "select name from table where name = 'aman' or id in (3, 4, 7)"
|
548
|
+
end
|
549
|
+
|
550
|
+
specify "should return an enumerator if no block is given" do
|
551
|
+
@db.fetch('select * from xyz').should respond_to(:each)
|
552
|
+
|
553
|
+
@db.fetch('select a from b').map {|r| r[:sql]}.should == ['select a from b']
|
554
|
+
|
555
|
+
@db.fetch('select c from d').inject([]) {|m, r| m << r; m}.should == \
|
556
|
+
[{:sql => 'select c from d'}]
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
context "Database#[]" do
|
561
|
+
setup do
|
562
|
+
@db = Sequel::Database.new
|
563
|
+
end
|
564
|
+
|
565
|
+
specify "should return a dataset when symbols are given" do
|
566
|
+
ds = @db[:items]
|
567
|
+
ds.class.should == Sequel::Dataset
|
568
|
+
ds.opts[:from].should == [:items]
|
569
|
+
end
|
570
|
+
|
571
|
+
specify "should return an enumerator when a string is given" do
|
572
|
+
c = Class.new(Sequel::Dataset) do
|
573
|
+
def fetch_rows(sql); yield({:sql => sql}); end
|
574
|
+
end
|
575
|
+
@db.meta_def(:dataset) {c.new(self)}
|
576
|
+
|
577
|
+
sql = nil
|
578
|
+
@db['select * from xyz where x = ? and y = ?', 15, 'abc'].each {|r| sql = r[:sql]}
|
579
|
+
sql.should == "select * from xyz where x = 15 and y = 'abc'"
|
580
|
+
end
|
502
581
|
end
|
data/spec/dataset_spec.rb
CHANGED
@@ -105,12 +105,28 @@ context "A simple dataset" do
|
|
105
105
|
specify "should format an insert statement with hash" do
|
106
106
|
@dataset.insert_sql(:name => 'wxyz', :price => 342).
|
107
107
|
should match(/INSERT INTO test \(name, price\) VALUES \('wxyz', 342\)|INSERT INTO test \(price, name\) VALUES \(342, 'wxyz'\)/)
|
108
|
+
|
109
|
+
@dataset.insert_sql({}).should == "INSERT INTO test DEFAULT VALUES;"
|
110
|
+
end
|
111
|
+
|
112
|
+
specify "should format an insert statement with array fields" do
|
113
|
+
v = [1, 2, 3]
|
114
|
+
v.fields = [:a, :b, :c]
|
115
|
+
@dataset.insert_sql(v).should == "INSERT INTO test (a, b, c) VALUES (1, 2, 3);"
|
116
|
+
|
117
|
+
v = []
|
118
|
+
v.fields = [:a, :b]
|
119
|
+
@dataset.insert_sql(v).should == "INSERT INTO test DEFAULT VALUES;"
|
120
|
+
end
|
121
|
+
|
122
|
+
specify "should format an insert statement with an arbitrary value" do
|
123
|
+
@dataset.insert_sql(123).should == "INSERT INTO test VALUES (123);"
|
108
124
|
end
|
109
125
|
|
110
126
|
specify "should format an insert statement with sub-query" do
|
111
127
|
@sub = Sequel::Dataset.new(nil).from(:something).filter(:x => 2)
|
112
128
|
@dataset.insert_sql(@sub).should == \
|
113
|
-
"INSERT INTO test (SELECT * FROM something WHERE (x = 2))"
|
129
|
+
"INSERT INTO test (SELECT * FROM something WHERE (x = 2));"
|
114
130
|
end
|
115
131
|
|
116
132
|
specify "should format an insert statement with array" do
|
@@ -123,6 +139,13 @@ context "A simple dataset" do
|
|
123
139
|
"UPDATE test SET name = 'abc'"
|
124
140
|
end
|
125
141
|
|
142
|
+
specify "should format an update statement with array fields" do
|
143
|
+
v = ['abc']
|
144
|
+
v.fields = [:name]
|
145
|
+
|
146
|
+
@dataset.update_sql(v).should == "UPDATE test SET name = 'abc'"
|
147
|
+
end
|
148
|
+
|
126
149
|
specify "should be able to return rows for arbitrary SQL" do
|
127
150
|
@dataset.select_sql(:sql => 'xxx yyy zzz').should ==
|
128
151
|
"xxx yyy zzz"
|
@@ -244,6 +267,16 @@ context "Dataset#where" do
|
|
244
267
|
|
245
268
|
@dataset.filter {:id.in?(4..7)}.sql.should ==
|
246
269
|
'SELECT * FROM test WHERE (id >= 4 AND id <= 7)'
|
270
|
+
|
271
|
+
@dataset.filter(:table__id => 4..7).sql.should ==
|
272
|
+
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
273
|
+
@dataset.filter(:table__id => 4...7).sql.should ==
|
274
|
+
'SELECT * FROM test WHERE (table.id >= 4 AND table.id < 7)'
|
275
|
+
|
276
|
+
@dataset.filter {:table__id == (4..7)}.sql.should ==
|
277
|
+
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
278
|
+
@dataset.filter {:table__id.in?(4..7)}.sql.should ==
|
279
|
+
'SELECT * FROM test WHERE (table.id >= 4 AND table.id <= 7)'
|
247
280
|
end
|
248
281
|
|
249
282
|
specify "should accept nil" do
|
@@ -537,7 +570,26 @@ context "Dataset#from" do
|
|
537
570
|
|
538
571
|
specify "should format a Dataset as a subquery if it has had options set" do
|
539
572
|
@dataset.from(@dataset.from(:a).where(:a=>1)).select_sql.should ==
|
540
|
-
"SELECT * FROM (SELECT * FROM a WHERE (a = 1))"
|
573
|
+
"SELECT * FROM (SELECT * FROM a WHERE (a = 1)) t1"
|
574
|
+
end
|
575
|
+
|
576
|
+
specify "should automatically alias sub-queries" do
|
577
|
+
@dataset.from(@dataset.from(:a).group(:b)).select_sql.should ==
|
578
|
+
"SELECT * FROM (SELECT * FROM a GROUP BY b) t1"
|
579
|
+
|
580
|
+
d1 = @dataset.from(:a).group(:b)
|
581
|
+
d2 = @dataset.from(:c).group(:d)
|
582
|
+
|
583
|
+
@dataset.from(d1, d2).sql.should ==
|
584
|
+
"SELECT * FROM (SELECT * FROM a GROUP BY b) t1, (SELECT * FROM c GROUP BY d) t2"
|
585
|
+
end
|
586
|
+
|
587
|
+
specify "should accept a hash for aliasing" do
|
588
|
+
@dataset.from(:a => :b).sql.should ==
|
589
|
+
"SELECT * FROM a b"
|
590
|
+
|
591
|
+
@dataset.from(@dataset.from(:a).group(:b) => :c).sql.should ==
|
592
|
+
"SELECT * FROM (SELECT * FROM a GROUP BY b) c"
|
541
593
|
end
|
542
594
|
|
543
595
|
specify "should use the relevant table name if given a simple dataset" do
|
@@ -560,12 +612,12 @@ context "Dataset#select" do
|
|
560
612
|
@d.select(:a, :b, :test__c).sql.should == 'SELECT a, b, test.c FROM test'
|
561
613
|
end
|
562
614
|
|
563
|
-
specify "should accept
|
564
|
-
@d.select('aaa').sql.should == 'SELECT aaa FROM test'
|
565
|
-
@d.select(:a, 'b').sql.should == 'SELECT a, b FROM test'
|
566
|
-
@d.select(:test__cc, 'test.d AS e').sql.should ==
|
615
|
+
specify "should accept symbols and literal strings" do
|
616
|
+
@d.select('aaa'.lit).sql.should == 'SELECT aaa FROM test'
|
617
|
+
@d.select(:a, 'b'.lit).sql.should == 'SELECT a, b FROM test'
|
618
|
+
@d.select(:test__cc, 'test.d AS e'.lit).sql.should ==
|
567
619
|
'SELECT test.cc, test.d AS e FROM test'
|
568
|
-
@d.select('test.d AS e', :test__cc).sql.should ==
|
620
|
+
@d.select('test.d AS e'.lit, :test__cc).sql.should ==
|
569
621
|
'SELECT test.d AS e, test.cc FROM test'
|
570
622
|
|
571
623
|
# symbol helpers
|
@@ -590,6 +642,14 @@ context "Dataset#select" do
|
|
590
642
|
@d.select(:a, :b, :c).select.sql.should == 'SELECT * FROM test'
|
591
643
|
@d.select(:price).select(:name).sql.should == 'SELECT name FROM test'
|
592
644
|
end
|
645
|
+
|
646
|
+
specify "should accept arbitrary objects and literalize them correctly" do
|
647
|
+
@d.select(1, :a, 't').sql.should == "SELECT 1, a, 't' FROM test"
|
648
|
+
|
649
|
+
@d.select(nil, :sum[:t], :x___y).sql.should == "SELECT NULL, sum(t), x AS y FROM test"
|
650
|
+
|
651
|
+
@d.select(nil, 1, :x => :y).sql.should == "SELECT NULL, 1, x AS y FROM test"
|
652
|
+
end
|
593
653
|
end
|
594
654
|
|
595
655
|
context "Dataset#order" do
|
@@ -613,7 +673,7 @@ context "Dataset#order" do
|
|
613
673
|
end
|
614
674
|
|
615
675
|
specify "should accept a string" do
|
616
|
-
@dataset.order('dada ASC').sql.should ==
|
676
|
+
@dataset.order('dada ASC'.lit).sql.should ==
|
617
677
|
'SELECT * FROM test ORDER BY dada ASC'
|
618
678
|
end
|
619
679
|
end
|
@@ -639,7 +699,7 @@ context "Dataset#order_by" do
|
|
639
699
|
end
|
640
700
|
|
641
701
|
specify "should accept a string" do
|
642
|
-
@dataset.order_by('dada ASC').sql.should ==
|
702
|
+
@dataset.order_by('dada ASC'.lit).sql.should ==
|
643
703
|
'SELECT * FROM test ORDER BY dada ASC'
|
644
704
|
end
|
645
705
|
end
|
@@ -915,6 +975,17 @@ context "Dataset#join_table" do
|
|
915
975
|
@d.from('stats s').join('players p', :id => :player_id).sql.should ==
|
916
976
|
'SELECT * FROM stats s INNER JOIN players p ON (p.id = s.player_id)'
|
917
977
|
end
|
978
|
+
|
979
|
+
specify "should allow for arbitrary conditions in the JOIN clause" do
|
980
|
+
@d.join_table(:left_outer, :categories, :id => :category_id, :status => 0).sql.should ==
|
981
|
+
'SELECT * FROM items LEFT OUTER JOIN categories ON (categories.id = items.category_id) AND (categories.status = 0)'
|
982
|
+
@d.join_table(:left_outer, :categories, :id => :category_id, :categorizable_type => "Post").sql.should ==
|
983
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.categorizable_type = 'Post') AND (categories.id = items.category_id)"
|
984
|
+
@d.join_table(:left_outer, :categories, :id => :category_id, :timestamp => "CURRENT_TIMESTAMP".lit).sql.should ==
|
985
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.id = items.category_id) AND (categories.timestamp = CURRENT_TIMESTAMP)"
|
986
|
+
@d.join_table(:left_outer, :categories, :id => :category_id, :status => [1, 2, 3]).sql.should ==
|
987
|
+
"SELECT * FROM items LEFT OUTER JOIN categories ON (categories.id = items.category_id) AND (categories.status IN (1, 2, 3))"
|
988
|
+
end
|
918
989
|
end
|
919
990
|
|
920
991
|
context "Dataset#[]=" do
|
@@ -1029,6 +1100,11 @@ context "Dataset#first" do
|
|
1029
1100
|
@c.last_opts[:where].should == ('z = 15')
|
1030
1101
|
end
|
1031
1102
|
|
1103
|
+
specify "should return the first matching record if a block is given" do
|
1104
|
+
@d.first {:z > 26}.should == {:a => 1, :b => 2}
|
1105
|
+
@c.last_opts[:where].should == ('(z > 26)')
|
1106
|
+
end
|
1107
|
+
|
1032
1108
|
specify "should return a single record if no argument is given" do
|
1033
1109
|
@d.first.should == {:a => 1, :b => 2}
|
1034
1110
|
end
|
@@ -1844,4 +1920,146 @@ context "Dataset#transform" do
|
|
1844
1920
|
@ds.each(:naked => true) {|r| f = r}
|
1845
1921
|
f.should == {:x => "wow", :y => 'hello'}
|
1846
1922
|
end
|
1923
|
+
end
|
1924
|
+
|
1925
|
+
context "Dataset#transform" do
|
1926
|
+
setup do
|
1927
|
+
@c = Class.new(Sequel::Dataset) do
|
1928
|
+
attr_accessor :raw
|
1929
|
+
attr_accessor :sql
|
1930
|
+
|
1931
|
+
def fetch_rows(sql, &block)
|
1932
|
+
block[@raw]
|
1933
|
+
end
|
1934
|
+
|
1935
|
+
def insert(v)
|
1936
|
+
@sql = insert_sql(v)
|
1937
|
+
end
|
1938
|
+
|
1939
|
+
def update(v)
|
1940
|
+
@sql = update_sql(v)
|
1941
|
+
end
|
1942
|
+
end
|
1943
|
+
|
1944
|
+
@ds = @c.new(nil).from(:items)
|
1945
|
+
end
|
1946
|
+
|
1947
|
+
specify "should raise SequelError for invalid transformations" do
|
1948
|
+
proc {@ds.transform(:x => 'mau')}.should raise_error(SequelError)
|
1949
|
+
proc {@ds.transform(:x => :mau)}.should raise_error(SequelError)
|
1950
|
+
proc {@ds.transform(:x => [])}.should raise_error(SequelError)
|
1951
|
+
proc {@ds.transform(:x => ['mau'])}.should raise_error(SequelError)
|
1952
|
+
proc {@ds.transform(:x => [proc {|v|}, proc {|v|}])}.should_not raise_error(SequelError)
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
specify "should support stock YAML transformation" do
|
1956
|
+
@ds.transform(:x => :yaml)
|
1957
|
+
|
1958
|
+
@ds.raw = {:x => [1, 2, 3].to_yaml, :y => 'hello'}
|
1959
|
+
@ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
1960
|
+
|
1961
|
+
@ds.insert(:x => :toast)
|
1962
|
+
@ds.sql.should == "INSERT INTO items (x) VALUES ('#{:toast.to_yaml}');"
|
1963
|
+
@ds.insert(:y => 'butter')
|
1964
|
+
@ds.sql.should == "INSERT INTO items (y) VALUES ('butter');"
|
1965
|
+
@ds.update(:x => ['dream'])
|
1966
|
+
@ds.sql.should == "UPDATE items SET x = '#{['dream'].to_yaml}'"
|
1967
|
+
|
1968
|
+
@ds2 = @ds.filter(:a => 1)
|
1969
|
+
@ds2.raw = {:x => [1, 2, 3].to_yaml, :y => 'hello'}
|
1970
|
+
@ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
1971
|
+
@ds2.insert(:x => :toast)
|
1972
|
+
@ds2.sql.should == "INSERT INTO items (x) VALUES ('#{:toast.to_yaml}');"
|
1973
|
+
|
1974
|
+
@ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
|
1975
|
+
@ds.raw = {:x => "wow".to_yaml, :y => 'hello'}
|
1976
|
+
@ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
|
1977
|
+
f = nil
|
1978
|
+
@ds.raw = {:x => "wow".to_yaml, :y => 'hello'}
|
1979
|
+
@ds.each(:naked => true) {|r| f = r}
|
1980
|
+
f.should == {:x => "wow", :y => 'hello'}
|
1981
|
+
end
|
1982
|
+
|
1983
|
+
specify "should support stock Marshal transformation" do
|
1984
|
+
@ds.transform(:x => :marshal)
|
1985
|
+
|
1986
|
+
@ds.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
|
1987
|
+
@ds.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
1988
|
+
|
1989
|
+
@ds.insert(:x => :toast)
|
1990
|
+
@ds.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}');"
|
1991
|
+
@ds.insert(:y => 'butter')
|
1992
|
+
@ds.sql.should == "INSERT INTO items (y) VALUES ('butter');"
|
1993
|
+
@ds.update(:x => ['dream'])
|
1994
|
+
@ds.sql.should == "UPDATE items SET x = '#{Marshal.dump(['dream'])}'"
|
1995
|
+
|
1996
|
+
@ds2 = @ds.filter(:a => 1)
|
1997
|
+
@ds2.raw = {:x => Marshal.dump([1, 2, 3]), :y => 'hello'}
|
1998
|
+
@ds2.first.should == {:x => [1, 2, 3], :y => 'hello'}
|
1999
|
+
@ds2.insert(:x => :toast)
|
2000
|
+
@ds2.sql.should == "INSERT INTO items (x) VALUES ('#{Marshal.dump(:toast)}');"
|
2001
|
+
|
2002
|
+
@ds.set_row_proc {|r| r[:z] = r[:x] * 2; r}
|
2003
|
+
@ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
|
2004
|
+
@ds.first.should == {:x => "wow", :y => 'hello', :z => "wowwow"}
|
2005
|
+
f = nil
|
2006
|
+
@ds.raw = {:x => Marshal.dump("wow"), :y => 'hello'}
|
2007
|
+
@ds.each(:naked => true) {|r| f = r}
|
2008
|
+
f.should == {:x => "wow", :y => 'hello'}
|
2009
|
+
end
|
2010
|
+
end
|
2011
|
+
|
2012
|
+
context "Dataset#to_csv" do
|
2013
|
+
setup do
|
2014
|
+
@c = Class.new(Sequel::Dataset) do
|
2015
|
+
attr_accessor :data
|
2016
|
+
attr_accessor :cols
|
2017
|
+
|
2018
|
+
def fetch_rows(sql, &block)
|
2019
|
+
@columns = @cols
|
2020
|
+
@data.each {|r| r.fields = @columns; block[r]}
|
2021
|
+
end
|
2022
|
+
|
2023
|
+
# naked should return self here because to_csv wants a naked result set.
|
2024
|
+
def naked
|
2025
|
+
self
|
2026
|
+
end
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
@ds = @c.new(nil).from(:items)
|
2030
|
+
|
2031
|
+
@ds.cols = [:a, :b, :c]
|
2032
|
+
@ds.data = [
|
2033
|
+
[1, 2, 3], [4, 5, 6], [7, 8, 9]
|
2034
|
+
]
|
2035
|
+
end
|
2036
|
+
|
2037
|
+
specify "should format a CSV representation of the records" do
|
2038
|
+
@ds.to_csv.should ==
|
2039
|
+
"a, b, c\r\n1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
2040
|
+
end
|
2041
|
+
|
2042
|
+
specify "should exclude column titles if so specified" do
|
2043
|
+
@ds.to_csv(false).should ==
|
2044
|
+
"1, 2, 3\r\n4, 5, 6\r\n7, 8, 9\r\n"
|
2045
|
+
end
|
2046
|
+
end
|
2047
|
+
|
2048
|
+
context "Dataset#each_hash" do
|
2049
|
+
setup do
|
2050
|
+
@c = Class.new(Sequel::Dataset) do
|
2051
|
+
def each(&block)
|
2052
|
+
a = [[1, 2, 3], [4, 5, 6]]
|
2053
|
+
a.each {|r| r.fields = [:a, :b, :c]; block[r]}
|
2054
|
+
end
|
2055
|
+
end
|
2056
|
+
|
2057
|
+
@ds = @c.new(nil).from(:items)
|
2058
|
+
end
|
2059
|
+
|
2060
|
+
specify "should yield records converted to hashes" do
|
2061
|
+
hashes = []
|
2062
|
+
@ds.each_hash {|h| hashes << h}
|
2063
|
+
hashes.should == [{:a => 1, :b => 2, :c => 3}, {:a => 4, :b => 5, :c => 6}]
|
2064
|
+
end
|
1847
2065
|
end
|