sequel 0.2.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|