sequel_impala 1.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +50 -0
- data/LICENSE +463 -0
- data/README.md +45 -0
- data/Rakefile +39 -0
- data/lib/driver/commons-collections-3.2.1.jar +0 -0
- data/lib/driver/commons-configuration-1.10.jar +0 -0
- data/lib/driver/commons-logging-1.2.jar +0 -0
- data/lib/driver/hadoop-auth-2.9.0.jar +0 -0
- data/lib/driver/hadoop-common-2.9.0.jar +0 -0
- data/lib/driver/hadoop-core-2.6.0.jar +0 -0
- data/lib/driver/hive-exec-1.1.0.jar +0 -0
- data/lib/driver/hive-jdbc-1.1.0.jar +0 -0
- data/lib/driver/hive-metastore-1.1.0.jar +0 -0
- data/lib/driver/hive-service-1.1.0.jar +0 -0
- data/lib/driver/httpclient-4.3.jar +0 -0
- data/lib/driver/httpcore-4.3.jar +0 -0
- data/lib/driver/libfb303-0.9.0.jar +0 -0
- data/lib/driver/log4j-1.2.17.jar +0 -0
- data/lib/driver/slf4j-api-1.7.5.jar +0 -0
- data/lib/driver/stax2-api-3.1.4.jar +0 -0
- data/lib/driver/woodstox-core-asl-4.4.1.jar +0 -0
- data/lib/impala.rb +55 -0
- data/lib/impala/connection.rb +180 -0
- data/lib/impala/cursor.rb +200 -0
- data/lib/impala/progress_reporter.rb +40 -0
- data/lib/impala/protocol.rb +8 -0
- data/lib/impala/protocol/beeswax_constants.rb +15 -0
- data/lib/impala/protocol/beeswax_service.rb +747 -0
- data/lib/impala/protocol/beeswax_types.rb +193 -0
- data/lib/impala/protocol/exec_stats_constants.rb +13 -0
- data/lib/impala/protocol/exec_stats_types.rb +133 -0
- data/lib/impala/protocol/facebook_service.rb +706 -0
- data/lib/impala/protocol/fb303_constants.rb +15 -0
- data/lib/impala/protocol/fb303_types.rb +25 -0
- data/lib/impala/protocol/hive_metastore_constants.rb +53 -0
- data/lib/impala/protocol/hive_metastore_types.rb +698 -0
- data/lib/impala/protocol/impala_hive_server2_service.rb +137 -0
- data/lib/impala/protocol/impala_service.rb +443 -0
- data/lib/impala/protocol/impala_service_constants.rb +13 -0
- data/lib/impala/protocol/impala_service_types.rb +192 -0
- data/lib/impala/protocol/status_constants.rb +13 -0
- data/lib/impala/protocol/status_types.rb +46 -0
- data/lib/impala/protocol/t_c_l_i_service.rb +1108 -0
- data/lib/impala/protocol/t_c_l_i_service_constants.rb +72 -0
- data/lib/impala/protocol/t_c_l_i_service_types.rb +1802 -0
- data/lib/impala/protocol/thrift_hive_metastore.rb +4707 -0
- data/lib/impala/protocol/types_constants.rb +13 -0
- data/lib/impala/protocol/types_types.rb +332 -0
- data/lib/impala/sasl_transport.rb +117 -0
- data/lib/impala/thrift_patch.rb +31 -0
- data/lib/impala/version.rb +3 -0
- data/lib/jdbc/hive2.rb +52 -0
- data/lib/jdbc/impala.rb +50 -0
- data/lib/rbhive.rb +8 -0
- data/lib/rbhive/connection.rb +150 -0
- data/lib/rbhive/explain_result.rb +46 -0
- data/lib/rbhive/result_set.rb +37 -0
- data/lib/rbhive/schema_definition.rb +86 -0
- data/lib/rbhive/t_c_l_i_connection.rb +466 -0
- data/lib/rbhive/t_c_l_i_result_set.rb +3 -0
- data/lib/rbhive/t_c_l_i_schema_definition.rb +87 -0
- data/lib/rbhive/table_schema.rb +122 -0
- data/lib/rbhive/version.rb +3 -0
- data/lib/sequel/adapters/impala.rb +220 -0
- data/lib/sequel/adapters/jdbc/hive2.rb +36 -0
- data/lib/sequel/adapters/jdbc/impala.rb +38 -0
- data/lib/sequel/adapters/rbhive.rb +177 -0
- data/lib/sequel/adapters/shared/impala.rb +808 -0
- data/lib/sequel/extensions/csv_to_parquet.rb +166 -0
- data/lib/thrift/facebook_service.rb +700 -0
- data/lib/thrift/fb303_constants.rb +9 -0
- data/lib/thrift/fb303_types.rb +19 -0
- data/lib/thrift/hive_metastore_constants.rb +41 -0
- data/lib/thrift/hive_metastore_types.rb +630 -0
- data/lib/thrift/hive_service_constants.rb +13 -0
- data/lib/thrift/hive_service_types.rb +72 -0
- data/lib/thrift/queryplan_constants.rb +13 -0
- data/lib/thrift/queryplan_types.rb +261 -0
- data/lib/thrift/sasl_client_transport.rb +161 -0
- data/lib/thrift/serde_constants.rb +92 -0
- data/lib/thrift/serde_types.rb +7 -0
- data/lib/thrift/t_c_l_i_service.rb +1054 -0
- data/lib/thrift/t_c_l_i_service_constants.rb +72 -0
- data/lib/thrift/t_c_l_i_service_types.rb +1768 -0
- data/lib/thrift/thrift_hive.rb +508 -0
- data/lib/thrift/thrift_hive_metastore.rb +3856 -0
- data/spec/database_test.rb +56 -0
- data/spec/dataset_test.rb +1268 -0
- data/spec/files/bad_down_migration/001_create_alt_basic.rb +4 -0
- data/spec/files/bad_down_migration/002_create_alt_advanced.rb +4 -0
- data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +9 -0
- data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +9 -0
- data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +3 -0
- data/spec/files/bad_up_migration/001_create_alt_basic.rb +4 -0
- data/spec/files/bad_up_migration/002_create_alt_advanced.rb +3 -0
- data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +9 -0
- data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +9 -0
- data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +4 -0
- data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +9 -0
- data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +9 -0
- data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +9 -0
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +9 -0
- data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +4 -0
- data/spec/files/integer_migrations/001_create_sessions.rb +9 -0
- data/spec/files/integer_migrations/002_create_nodes.rb +9 -0
- data/spec/files/integer_migrations/003_3_create_users.rb +4 -0
- data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +9 -0
- data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +9 -0
- data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +9 -0
- data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +9 -0
- data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +4 -0
- data/spec/files/reversible_migrations/001_reversible.rb +5 -0
- data/spec/files/reversible_migrations/002_reversible.rb +5 -0
- data/spec/files/reversible_migrations/003_reversible.rb +5 -0
- data/spec/files/reversible_migrations/004_reversible.rb +5 -0
- data/spec/files/reversible_migrations/005_reversible.rb +10 -0
- data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +9 -0
- data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +9 -0
- data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +4 -0
- data/spec/impala_test.rb +290 -0
- data/spec/migrator_test.rb +240 -0
- data/spec/plugin_test.rb +91 -0
- data/spec/prepared_statement_test.rb +327 -0
- data/spec/schema_test.rb +356 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/timezone_test.rb +86 -0
- data/spec/type_test.rb +99 -0
- metadata +294 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
|
+
|
|
3
|
+
describe Sequel::Database do
|
|
4
|
+
before do
|
|
5
|
+
@db = DB
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it "should provide disconnect functionality" do
|
|
9
|
+
@db.disconnect
|
|
10
|
+
@db.pool.size.must_equal 0
|
|
11
|
+
@db.test_connection
|
|
12
|
+
@db.pool.size.must_equal 1
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should provide disconnect functionality after preparing a statement" do
|
|
16
|
+
@db.create_table!(:items){Integer :i}
|
|
17
|
+
@db[:items].prepare(:first, :a).call
|
|
18
|
+
@db.disconnect
|
|
19
|
+
@db.pool.size.must_equal 0
|
|
20
|
+
@db.drop_table?(:items)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should raise Sequel::DatabaseError on invalid SQL" do
|
|
24
|
+
proc{@db << "S"}.must_raise(Sequel::DatabaseError)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should store underlying wrapped exception in Sequel::DatabaseError" do
|
|
28
|
+
begin
|
|
29
|
+
@db << "SELECT"
|
|
30
|
+
rescue Sequel::DatabaseError=>e
|
|
31
|
+
if defined?(Java::JavaLang::Exception)
|
|
32
|
+
(e.wrapped_exception.is_a?(Exception) || e.wrapped_exception.is_a?(Java::JavaLang::Exception)).must_equal true
|
|
33
|
+
else
|
|
34
|
+
e.wrapped_exception.must_be_kind_of(Exception)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "should not have the connection pool swallow non-StandardError based exceptions" do
|
|
40
|
+
proc{@db.pool.hold{raise Interrupt, "test"}}.must_raise(Interrupt)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should be able to disconnect connections more than once without exceptions" do
|
|
44
|
+
conn = @db.synchronize{|c| c}
|
|
45
|
+
@db.disconnect
|
|
46
|
+
@db.disconnect_connection(conn)
|
|
47
|
+
@db.disconnect_connection(conn)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should provide ability to check connections for validity" do
|
|
51
|
+
conn = @db.synchronize{|c| c}
|
|
52
|
+
@db.valid_connection?(conn).must_equal true
|
|
53
|
+
@db.disconnect
|
|
54
|
+
@db.valid_connection?(conn).must_equal false
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,1268 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
|
|
2
|
+
|
|
3
|
+
describe "Simple Dataset operations" do
|
|
4
|
+
before(:all) do
|
|
5
|
+
@db = DB
|
|
6
|
+
@ds = @db[:items]
|
|
7
|
+
end
|
|
8
|
+
after do
|
|
9
|
+
@db.drop_table?(:items)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should support sequential primary keys with a Bignum" do
|
|
13
|
+
@db.create_table!(:items) do
|
|
14
|
+
primary_key :id, :type=>Bignum
|
|
15
|
+
Integer :number
|
|
16
|
+
end
|
|
17
|
+
@ds << {:id=>1, :number=>20}
|
|
18
|
+
@ds << {:id=>2, :number=>30}
|
|
19
|
+
@ds.order(:number).all.must_equal [{:id => 1, :number=>20}, {:id => 2, :number=>30}]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should have insert work correctly with static SQL" do
|
|
23
|
+
@db.create_table!(:items) do
|
|
24
|
+
primary_key :id
|
|
25
|
+
Integer :number
|
|
26
|
+
end
|
|
27
|
+
@db["INSERT INTO #{@ds.literal(:items)} (id, number) VALUES (2, 30)"].insert
|
|
28
|
+
@ds.all.must_equal [{:id => 2, :number=>30}]
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should have insert work correctly when inserting a row with all NULL values" do
|
|
32
|
+
@db.create_table!(:items) do
|
|
33
|
+
Integer :id
|
|
34
|
+
Integer :number
|
|
35
|
+
end
|
|
36
|
+
@ds.insert
|
|
37
|
+
@ds.all.must_equal [{:id=>nil, :number=>nil}]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should support iterating over large numbers of records with paged_each" do
|
|
41
|
+
@db.create_table!(:items) do
|
|
42
|
+
Integer :id
|
|
43
|
+
Integer :number
|
|
44
|
+
end
|
|
45
|
+
@ds.import([:id, :number], (1..10).map{|i| [i, i*10]})
|
|
46
|
+
|
|
47
|
+
[:offset, :filter].each do |strategy|
|
|
48
|
+
rows = []
|
|
49
|
+
@ds.order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
|
|
50
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}})
|
|
51
|
+
|
|
52
|
+
rows = []
|
|
53
|
+
@ds.order(:number).paged_each(:rows_per_fetch=>3, :strategy=>strategy){|row| rows << row}
|
|
54
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}})
|
|
55
|
+
|
|
56
|
+
rows = []
|
|
57
|
+
@ds.order(:number, :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
|
|
58
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}})
|
|
59
|
+
|
|
60
|
+
rows = []
|
|
61
|
+
@ds.reverse_order(:number).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
|
|
62
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}}.reverse)
|
|
63
|
+
|
|
64
|
+
rows = []
|
|
65
|
+
@ds.order(Sequel.desc(:number), :id).paged_each(:rows_per_fetch=>5, :strategy=>strategy){|row| rows << row}
|
|
66
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}}.reverse)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
rows = []
|
|
70
|
+
@ds.order(:number).limit(5, 2).paged_each(:rows_per_fetch=>3){|row| rows << row}
|
|
71
|
+
rows.must_equal((3..7).map{|i| {:id=>i, :number=>i*10}})
|
|
72
|
+
|
|
73
|
+
rows = []
|
|
74
|
+
@ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5){|row| rows << row}
|
|
75
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}})
|
|
76
|
+
|
|
77
|
+
rows = []
|
|
78
|
+
@ds.order(Sequel.*(:number, 2)).paged_each(:rows_per_fetch=>5, :strategy=>:filter, :filter_values=>proc{|row, _| [row[:number] * 2]}){|row| rows << row}
|
|
79
|
+
rows.must_equal((1..10).map{|i| {:id=>i, :number=>i*10}})
|
|
80
|
+
|
|
81
|
+
if RUBY_ENGINE == 'jruby'
|
|
82
|
+
# check retrival with varying fetch sizes
|
|
83
|
+
array = (1..10).to_a
|
|
84
|
+
[1, 2, 5, 10, 20].each do |i|
|
|
85
|
+
@ds.with_fetch_size(i).select_order_map(:id).must_equal array
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should fetch correctly with a limit and offset for different combinations of from and join tables" do
|
|
91
|
+
@db.create_table!(:items) do
|
|
92
|
+
Integer :id
|
|
93
|
+
Integer :number
|
|
94
|
+
end
|
|
95
|
+
@ds.insert(:id=>1, :number=>10)
|
|
96
|
+
@db.create_table!(:items2){primary_key :id2; Integer :number2}
|
|
97
|
+
@db[:items2].insert(:id2=>1, :number2=>10)
|
|
98
|
+
@ds.from(:items, :items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
|
99
|
+
@ds.from(:items___i, :items2___i2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
|
100
|
+
@ds.cross_join(:items2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
|
101
|
+
@ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10}]
|
|
102
|
+
@ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 0).all.must_equal [{:id=>1, :number=>10, :id2=>1, :number2=>10, :id3=>1, :number3=>10}]
|
|
103
|
+
|
|
104
|
+
@ds.from(:items, :items2).order(:id).limit(2, 1).all.must_equal []
|
|
105
|
+
@ds.from(:items___i, :items2___i2).order(:id).limit(2, 1).all.must_equal []
|
|
106
|
+
@ds.cross_join(:items2).order(:id).limit(2, 1).all.must_equal []
|
|
107
|
+
@ds.from(:items___i).cross_join(:items2___i2).order(:id).limit(2, 1).all.must_equal []
|
|
108
|
+
@ds.cross_join(:items2___i).cross_join(@db[:items2].select(:id2___id3, :number2___number3)).order(:id).limit(2, 1).all.must_equal []
|
|
109
|
+
@db.drop_table(:items2)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
describe "Simple Dataset operations" do
|
|
115
|
+
before(:all) do
|
|
116
|
+
@db = DB
|
|
117
|
+
@db.create_table!(:items) do
|
|
118
|
+
primary_key :id
|
|
119
|
+
Integer :number
|
|
120
|
+
end
|
|
121
|
+
@ds = @db[:items]
|
|
122
|
+
@ds.insert(:id=>1, :number=>10)
|
|
123
|
+
end
|
|
124
|
+
after(:all) do
|
|
125
|
+
@db.drop_table?(:items)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should join correctly" do
|
|
129
|
+
@ds.join(:items___b, :id=>:id).select_all(:items).all.must_equal [{:id=>1, :number=>10}]
|
|
130
|
+
@ds.join(:items___b, [:id]).select_all(:items).all.must_equal [{:id=>1, :number=>10}]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "should correctly handle subqueries" do
|
|
134
|
+
@ds.from_self(:alias=>:a).all.must_equal [{:id=>1, :number=>10}]
|
|
135
|
+
@ds.join(@ds.as(:a), :id=>:id).select_all(:a).all.must_equal [{:id=>1, :number=>10}]
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
it "should graph correctly" do
|
|
139
|
+
a = [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
|
|
140
|
+
pr = proc{|t| @ds.graph(t, {:id=>:id}, :table_alias=>:b).extension(:graph_each).all.must_equal a}
|
|
141
|
+
pr[:items]
|
|
142
|
+
pr[:items___foo]
|
|
143
|
+
pr[Sequel.identifier(:items)]
|
|
144
|
+
pr[Sequel.identifier('items')]
|
|
145
|
+
pr[Sequel.as(:items, :foo)]
|
|
146
|
+
pr[Sequel.as(Sequel.identifier('items'), 'foo')]
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "should graph correctly with a subselect" do
|
|
150
|
+
@ds.from_self(:alias=>:items).graph(@ds.from_self, {:id=>:id}, :table_alias=>:b).extension(:graph_each).all.must_equal [{:items=>{:id=>1, :number=>10}, :b=>{:id=>1, :number=>10}}]
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
it "should iterate over records as they come in" do
|
|
154
|
+
called = false
|
|
155
|
+
@ds.each{|row| called = true; row.must_equal(:id=>1, :number=>10)}
|
|
156
|
+
called.must_equal true
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "should fetch all results correctly" do
|
|
160
|
+
@ds.all.must_equal [{:id=>1, :number=>10}]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "should fetch a single row correctly" do
|
|
164
|
+
@ds.first.must_equal(:id=>1, :number=>10)
|
|
165
|
+
@ds.single_record.must_equal(:id=>1, :number=>10)
|
|
166
|
+
@ds.single_record!.must_equal(:id=>1, :number=>10)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
it "should work correctly when returning from each without iterating over the whole result set" do
|
|
170
|
+
@ds.order(:id).each{|v| break v}.must_equal(:id=>1, :number=>10)
|
|
171
|
+
@ds.reverse(:id).each{|v| break v}.must_equal(:id=>1, :number=>10)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
it "should fetch a single value correctly" do
|
|
175
|
+
@ds.get(:id).must_equal 1
|
|
176
|
+
@ds.select(:id).single_value.must_equal 1
|
|
177
|
+
@ds.select(:id).single_value!.must_equal 1
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "should have distinct work with limit" do
|
|
181
|
+
@ds.limit(1).distinct.all.must_equal [{:id=>1, :number=>10}]
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should fetch correctly with a limit" do
|
|
185
|
+
@ds.order(:id).limit(1).all.must_equal [{:id=>1, :number=>10}]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should fetch correctly with a limit and offset" do
|
|
189
|
+
@ds.order(:id).limit(1, 0).all.must_equal [{:id=>1, :number=>10}]
|
|
190
|
+
@ds.order(:id).limit(1, 1).all.must_equal []
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it "should fetch correctly with just offset" do
|
|
194
|
+
@ds.order(:id).offset(0).all.must_equal [{:id=>1, :number=>10}]
|
|
195
|
+
@ds.order(:id).offset(1).all.must_equal []
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
it "should fetch correctly with a limit and offset using seperate methods" do
|
|
199
|
+
@ds.order(:id).limit(1).offset(0).all.must_equal [{:id=>1, :number=>10}]
|
|
200
|
+
@ds.order(:id).limit(1).offset(1).all.must_equal []
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "should provide correct columns when using a limit and offset" do
|
|
204
|
+
ds = @ds.order(:id).limit(1, 1)
|
|
205
|
+
ds.all
|
|
206
|
+
ds.columns.must_equal [:id, :number]
|
|
207
|
+
@ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "should fetch correctly with a limit and offset without an order" do
|
|
211
|
+
ds = @ds.order(1)
|
|
212
|
+
ds.limit(2, 1).all.must_equal []
|
|
213
|
+
ds.join(:items___i, :id=>:id).select(:items__id___s, :i__id___id2).limit(2, 1).all.must_equal []
|
|
214
|
+
ds.join(:items___i, :id=>:id).select(:items__id).limit(2, 1).all.must_equal []
|
|
215
|
+
ds.join(:items___i, :id=>:id).select(Sequel.qualify(:items, :id)).limit(2, 1).all.must_equal []
|
|
216
|
+
ds.join(:items___i, :id=>:id).select(Sequel.qualify(:items, :id).as(:s)).limit(2, 1).all.must_equal []
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "should be orderable by column number" do
|
|
220
|
+
@ds.order(2, 1).select_map([:id, :number]).must_equal [[1, 10]]
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "should fetch correctly with a limit in an IN subselect" do
|
|
224
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(1)).all.must_equal [{:id=>1, :number=>10}]
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "should fetch correctly with a limit and offset in an IN subselect" do
|
|
228
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 0)).all.must_equal [{:id=>1, :number=>10}]
|
|
229
|
+
@ds.where(:id=>@ds.select(:id).order(:id).limit(2, 1)).all.must_equal []
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
it "should fetch correctly when using limit and offset in a from_self" do
|
|
233
|
+
ds = @ds.order(:id).limit(1, 1).from_self
|
|
234
|
+
ds.all.must_equal []
|
|
235
|
+
ds.columns.must_equal [:id, :number]
|
|
236
|
+
@ds.order(:id).limit(1, 1).columns.must_equal [:id, :number]
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
it "should fetch correctly when using nested limit and offset in a from_self" do
|
|
240
|
+
ds = @ds.order(:id).limit(1, 0).from_self.reverse_order(:number).limit(1, 0)
|
|
241
|
+
ds.all.must_equal [{:number=>10, :id=>1}]
|
|
242
|
+
ds.columns.must_equal [:id, :number]
|
|
243
|
+
@ds.order(:id).limit(1, 0).from_self.reverse_order(:number).limit(1, 0).columns.must_equal [:id, :number]
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should alias columns correctly" do
|
|
247
|
+
@ds.select(:id___x, :number___n).first.must_equal(:x=>1, :n=>10)
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it "should handle true/false properly" do
|
|
251
|
+
@ds.filter(Sequel::TRUE).select_map(:number).must_equal [10]
|
|
252
|
+
@ds.filter(Sequel::FALSE).select_map(:number).must_equal []
|
|
253
|
+
@ds.filter(true).select_map(:number).must_equal [10]
|
|
254
|
+
@ds.filter(false).select_map(:number).must_equal []
|
|
255
|
+
@ds.filter({:id=>1}=>true).select_map(:number).must_equal [10]
|
|
256
|
+
@ds.filter({:id=>1}=>false).select_map(:number).must_equal []
|
|
257
|
+
@ds.literal(true)
|
|
258
|
+
@ds.literal(false)
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
describe Sequel::Dataset do
|
|
263
|
+
before(:all) do
|
|
264
|
+
DB.create_table!(:test) do
|
|
265
|
+
String :name
|
|
266
|
+
Integer :value
|
|
267
|
+
end
|
|
268
|
+
@d = DB[:test]
|
|
269
|
+
@d.multi_insert([{:name => 'abc', :value => 123}, {:name => 'abc', :value => 456}, {:name => 'def', :value => 789}])
|
|
270
|
+
end
|
|
271
|
+
after(:all) do
|
|
272
|
+
DB.drop_table?(:test)
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
it "should correctly return avg" do
|
|
276
|
+
@d.avg(:value).to_i.must_equal 456
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
it "should correctly return sum" do
|
|
280
|
+
@d.sum(:value).to_i.must_equal 1368
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
it "should correctly return max" do
|
|
284
|
+
@d.max(:value).to_i.must_equal 789
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
it "should correctly return min" do
|
|
288
|
+
@d.min(:value).to_i.must_equal 123
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
it "should return the correct record count" do
|
|
292
|
+
@d.count.must_equal 3
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
it "should handle functions with identifier names correctly" do
|
|
296
|
+
@d.get{sum.function(:value)}.must_equal 1368
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
it "should handle aggregate methods on limited datasets correctly" do
|
|
300
|
+
@d = @d.order(:name).limit(2)
|
|
301
|
+
@d.count.must_equal 2
|
|
302
|
+
@d.avg(:value).to_i.must_equal 289
|
|
303
|
+
@d.min(:value).to_i.must_equal 123
|
|
304
|
+
@d.reverse(:value).min(:value).to_i.must_equal 456
|
|
305
|
+
@d.max(:value).to_i.must_equal 456
|
|
306
|
+
@d.sum(:value).to_i.must_equal 579
|
|
307
|
+
@d.interval(:value).to_i.must_equal 333
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
it "should return the correct records" do
|
|
311
|
+
@d.order(:value).to_a.must_equal [{:name => 'abc', :value => 123}, {:name => 'abc', :value => 456}, {:name => 'def', :value => 789}]
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
describe Sequel::Database do
|
|
316
|
+
it "should correctly escape strings" do
|
|
317
|
+
["\\\n",
|
|
318
|
+
"\\\\\n",
|
|
319
|
+
"\\\r\n",
|
|
320
|
+
"\\\\\r\n",
|
|
321
|
+
"\\\\\n\n",
|
|
322
|
+
"\\\\\r\n\r\n",
|
|
323
|
+
"\b\a'\0\3",
|
|
324
|
+
#"\t\b\a'\0\3",
|
|
325
|
+
"\\dingo",
|
|
326
|
+
"\\'dingo",
|
|
327
|
+
"\\\\''dingo",
|
|
328
|
+
].each do |str|
|
|
329
|
+
DB.get(Sequel.cast(str, String)).must_equal str
|
|
330
|
+
str = "1#{str}1"
|
|
331
|
+
DB.get(Sequel.cast(str, String)).must_equal str
|
|
332
|
+
str = "#{str}#{str}"
|
|
333
|
+
DB.get(Sequel.cast(str, String)).must_equal str
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
it "should have a working table_exists?" do
|
|
338
|
+
t = :basdfdsafsaddsaf
|
|
339
|
+
DB.drop_table?(t)
|
|
340
|
+
DB.table_exists?(t).must_equal false
|
|
341
|
+
DB.create_table(t){Integer :a}
|
|
342
|
+
begin
|
|
343
|
+
DB.table_exists?(t).must_equal true
|
|
344
|
+
ensure
|
|
345
|
+
DB.drop_table(t)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
describe "Simple Dataset operations" do
|
|
351
|
+
before do
|
|
352
|
+
DB.create_table!(:items) do
|
|
353
|
+
Integer :number
|
|
354
|
+
TrueClass :flag
|
|
355
|
+
end
|
|
356
|
+
@ds = DB[:items]
|
|
357
|
+
end
|
|
358
|
+
after do
|
|
359
|
+
DB.drop_table?(:items)
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
it "should deal with boolean conditions correctly" do
|
|
363
|
+
@ds.insert(:number=>1, :flag=>true)
|
|
364
|
+
@ds.insert(:number=>2, :flag=>false)
|
|
365
|
+
@ds.insert(:number=>3, :flag=>nil)
|
|
366
|
+
@ds.order!(:number)
|
|
367
|
+
@ds.filter(:flag=>true).map(:number).must_equal [1]
|
|
368
|
+
@ds.filter(:flag=>false).map(:number).must_equal [2]
|
|
369
|
+
@ds.filter(:flag=>nil).map(:number).must_equal [3]
|
|
370
|
+
@ds.exclude(:flag=>true).map(:number).must_equal [2, 3]
|
|
371
|
+
@ds.exclude(:flag=>false).map(:number).must_equal [1, 3]
|
|
372
|
+
@ds.exclude(:flag=>nil).map(:number).must_equal [1, 2]
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
describe "Dataset UNION, EXCEPT, and INTERSECT" do
|
|
377
|
+
before(:all) do
|
|
378
|
+
DB.create_table!(:i1){integer :number}
|
|
379
|
+
DB.create_table!(:i2){integer :number}
|
|
380
|
+
DB.create_table!(:i3){integer :number}
|
|
381
|
+
@ds1 = DB[:i1]
|
|
382
|
+
@ds1.insert(:number=>8)
|
|
383
|
+
@ds1.insert(:number=>10)
|
|
384
|
+
@ds1.insert(:number=>20)
|
|
385
|
+
@ds1.insert(:number=>38)
|
|
386
|
+
@ds2 = DB[:i2]
|
|
387
|
+
@ds2.insert(:number=>9)
|
|
388
|
+
@ds2.insert(:number=>10)
|
|
389
|
+
@ds2.insert(:number=>30)
|
|
390
|
+
@ds2.insert(:number=>39)
|
|
391
|
+
@ds3 = DB[:i3]
|
|
392
|
+
@ds3.insert(:number=>10)
|
|
393
|
+
@ds3.insert(:number=>40)
|
|
394
|
+
end
|
|
395
|
+
after(:all) do
|
|
396
|
+
DB.drop_table?(:i1, :i2, :i3)
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it "should give the correct results for simple UNION" do
|
|
400
|
+
@ds1.union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it "should give the correct results for UNION when used with ordering and limits" do
|
|
404
|
+
|
|
405
|
+
@ds1.reverse_order(:number).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
|
|
406
|
+
@ds1.union(@ds2.reverse_order(:number)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39'
|
|
407
|
+
|
|
408
|
+
@ds1.reverse_order(:number).limit(1).union(@ds2).order(:number).map{|x| x[:number].to_s}.must_equal %w'9 10 30 38 39'
|
|
409
|
+
@ds2.reverse_order(:number).limit(1).union(@ds1).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 10 20 38 39'
|
|
410
|
+
|
|
411
|
+
@ds1.union(@ds2.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 38'
|
|
412
|
+
@ds2.union(@ds1.order(:number).limit(1)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 30 39'
|
|
413
|
+
|
|
414
|
+
@ds1.union(@ds2).limit(2).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9'
|
|
415
|
+
@ds2.union(@ds1).reverse_order(:number).limit(2).map{|x| x[:number].to_s}.must_equal %w'39 38'
|
|
416
|
+
|
|
417
|
+
@ds1.reverse_order(:number).limit(2).union(@ds2.reverse_order(:number).limit(2)).order(:number).limit(3).map{|x| x[:number].to_s}.must_equal %w'20 30 38'
|
|
418
|
+
@ds2.order(:number).limit(2).union(@ds1.order(:number).limit(2)).reverse_order(:number).limit(3).map{|x| x[:number].to_s}.must_equal %w'10 9 8'
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it "should give the correct results for compound UNION" do
|
|
422
|
+
@ds1.union(@ds2).union(@ds3).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39 40'
|
|
423
|
+
@ds1.union(@ds2.union(@ds3)).order(:number).map{|x| x[:number].to_s}.must_equal %w'8 9 10 20 30 38 39 40'
|
|
424
|
+
end
|
|
425
|
+
end
|
|
426
|
+
|
|
427
|
+
describe "Common Table Expressions" do
|
|
428
|
+
before(:all) do
|
|
429
|
+
@db = DB
|
|
430
|
+
@db.create_table!(:i1){Integer :id; Integer :parent_id}
|
|
431
|
+
@ds = @db[:i1]
|
|
432
|
+
@ds.insert(:id=>1)
|
|
433
|
+
@ds.insert(:id=>2)
|
|
434
|
+
@ds.insert(:id=>3, :parent_id=>1)
|
|
435
|
+
@ds.insert(:id=>4, :parent_id=>1)
|
|
436
|
+
@ds.insert(:id=>5, :parent_id=>3)
|
|
437
|
+
@ds.insert(:id=>6, :parent_id=>5)
|
|
438
|
+
end
|
|
439
|
+
after(:all) do
|
|
440
|
+
@db.drop_table?(:i1)
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
it "should give correct results for WITH" do
|
|
444
|
+
@db[:t].with(:t, @ds.filter(:parent_id=>nil).select(:id)).order(:id).map(:id).must_equal [1, 2]
|
|
445
|
+
end
|
|
446
|
+
|
|
447
|
+
it "should support joining a dataset with a CTE" do
|
|
448
|
+
@ds.inner_join(@db[:t].with(:t, @ds.filter(:parent_id=>nil)), :id => :id).select(:i1__id).order(:i1__id).map(:id).must_equal [1,2]
|
|
449
|
+
@db[:t].with(:t, @ds).inner_join(@db[:s].with(:s, @ds.filter(:parent_id=>nil)), :id => :id).select(:t__id).order(:t__id).map(:id).must_equal [1,2]
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
it "should support a subselect in the FROM clause with a CTE" do
|
|
453
|
+
@ds.from(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
|
|
454
|
+
@db[:t].with(:t, @ds).from_self.select_order_map(:id).must_equal [1,2,3,4,5,6]
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
it "should support using a CTE inside a CTE" do
|
|
458
|
+
@db[:s].with(:s, @db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
|
|
459
|
+
@db[:s].with_recursive(:s, @db[:t].with(:t, @ds), @db[:t2].with(:t2, @ds)).select_order_map(:id).must_equal [1,1,2,2,3,3,4,4,5,5,6,6]
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
it "should support using a CTE inside UNION/EXCEPT/INTERSECT" do
|
|
463
|
+
@ds.union(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
|
|
464
|
+
if @ds.supports_intersect_except?
|
|
465
|
+
@ds.intersect(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal [1,2,3,4,5,6]
|
|
466
|
+
@ds.except(@db[:t].with(:t, @ds)).select_order_map(:id).must_equal []
|
|
467
|
+
end
|
|
468
|
+
end
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
describe "Window Functions" do
|
|
472
|
+
before(:all) do
|
|
473
|
+
@db = DB
|
|
474
|
+
@db.create_table!(:i1){Integer :id; Integer :group_id; Integer :amount}
|
|
475
|
+
@ds = @db[:i1].order(:id)
|
|
476
|
+
@ds.insert(:id=>1, :group_id=>1, :amount=>1)
|
|
477
|
+
@ds.insert(:id=>2, :group_id=>1, :amount=>10)
|
|
478
|
+
@ds.insert(:id=>3, :group_id=>1, :amount=>100)
|
|
479
|
+
@ds.insert(:id=>4, :group_id=>2, :amount=>1000)
|
|
480
|
+
@ds.insert(:id=>5, :group_id=>2, :amount=>10000)
|
|
481
|
+
@ds.insert(:id=>6, :group_id=>2, :amount=>100000)
|
|
482
|
+
end
|
|
483
|
+
after(:all) do
|
|
484
|
+
@db.drop_table?(:i1)
|
|
485
|
+
end
|
|
486
|
+
|
|
487
|
+
it "should give correct results for aggregate window functions" do
|
|
488
|
+
@ds.select(:id){sum(:amount).over(:partition=>:group_id).as(:sum)}.all.
|
|
489
|
+
must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
|
|
490
|
+
@ds.select(:id){sum(:amount).over.as(:sum)}.all.
|
|
491
|
+
must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
|
|
492
|
+
end
|
|
493
|
+
|
|
494
|
+
it "should give correct results for ranking window functions with orders" do
|
|
495
|
+
@ds.select(:id){rank{}.over(:partition=>:group_id, :order=>:id).as(:rank)}.all.
|
|
496
|
+
must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>1, :id=>4}, {:rank=>2, :id=>5}, {:rank=>3, :id=>6}]
|
|
497
|
+
@ds.select(:id){rank{}.over(:order=>id).as(:rank)}.all.
|
|
498
|
+
must_equal [{:rank=>1, :id=>1}, {:rank=>2, :id=>2}, {:rank=>3, :id=>3}, {:rank=>4, :id=>4}, {:rank=>5, :id=>5}, {:rank=>6, :id=>6}]
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it "should give correct results for aggregate window functions with orders" do
|
|
502
|
+
@ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id).as(:sum)}.all.
|
|
503
|
+
must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
|
|
504
|
+
@ds.select(:id){sum(:amount).over(:order=>:id).as(:sum)}.all.
|
|
505
|
+
must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
it "should give correct results for aggregate window functions with frames" do
|
|
509
|
+
@ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:all).as(:sum)}.all.
|
|
510
|
+
must_equal [{:sum=>111, :id=>1}, {:sum=>111, :id=>2}, {:sum=>111, :id=>3}, {:sum=>111000, :id=>4}, {:sum=>111000, :id=>5}, {:sum=>111000, :id=>6}]
|
|
511
|
+
@ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:all).as(:sum)}.all.
|
|
512
|
+
must_equal [{:sum=>111111, :id=>1}, {:sum=>111111, :id=>2}, {:sum=>111111, :id=>3}, {:sum=>111111, :id=>4}, {:sum=>111111, :id=>5}, {:sum=>111111, :id=>6}]
|
|
513
|
+
|
|
514
|
+
@ds.select(:id){sum(:amount).over(:partition=>:group_id, :order=>:id, :frame=>:rows).as(:sum)}.all.
|
|
515
|
+
must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1000, :id=>4}, {:sum=>11000, :id=>5}, {:sum=>111000, :id=>6}]
|
|
516
|
+
@ds.select(:id){sum(:amount).over(:order=>:id, :frame=>:rows).as(:sum)}.all.
|
|
517
|
+
must_equal [{:sum=>1, :id=>1}, {:sum=>11, :id=>2}, {:sum=>111, :id=>3}, {:sum=>1111, :id=>4}, {:sum=>11111, :id=>5}, {:sum=>111111, :id=>6}]
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
|
|
521
|
+
describe Sequel::SQL::Constants do
|
|
522
|
+
before do
|
|
523
|
+
@db = DB
|
|
524
|
+
@ds = @db[:constants]
|
|
525
|
+
@c = proc do |v|
|
|
526
|
+
case v
|
|
527
|
+
when Time
|
|
528
|
+
v
|
|
529
|
+
when DateTime, String
|
|
530
|
+
Time.parse(v.to_s)
|
|
531
|
+
else
|
|
532
|
+
v
|
|
533
|
+
end
|
|
534
|
+
end
|
|
535
|
+
@c2 = proc{|v| v.is_a?(Date) ? v : Date.parse(v) }
|
|
536
|
+
end
|
|
537
|
+
after do
|
|
538
|
+
@db.drop_table?(:constants)
|
|
539
|
+
end
|
|
540
|
+
|
|
541
|
+
it "should have working CURRENT_TIMESTAMP" do
|
|
542
|
+
@db.create_table!(:constants){DateTime :ts}
|
|
543
|
+
@ds.insert(:ts=>Sequel::CURRENT_TIMESTAMP)
|
|
544
|
+
(Time.now - @c[@ds.get(:ts)]).must_be_close_to 0, 86400
|
|
545
|
+
end
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
describe "Sequel::Dataset#import and #multi_insert" do
|
|
549
|
+
before do
|
|
550
|
+
@db = DB
|
|
551
|
+
@db.create_table!(:imp){Integer :i}
|
|
552
|
+
@ids = @db[:imp].order(:i)
|
|
553
|
+
end
|
|
554
|
+
after do
|
|
555
|
+
@db.drop_table?(:imp)
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
it "should import with multi_insert and an array of hashes" do
|
|
559
|
+
@ids.multi_insert([{:i=>10}, {:i=>20}])
|
|
560
|
+
@ids.all.must_equal [{:i=>10}, {:i=>20}]
|
|
561
|
+
end
|
|
562
|
+
|
|
563
|
+
it "should import with an array of arrays of values" do
|
|
564
|
+
@ids.import([:i], [[10], [20]])
|
|
565
|
+
@ids.all.must_equal [{:i=>10}, {:i=>20}]
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
it "should import with a dataset" do
|
|
569
|
+
@db.create_table!(:exp2){Integer :i}
|
|
570
|
+
@db[:exp2].import([:i], [[10], [20]])
|
|
571
|
+
@ids.import([:i], @db[:exp2])
|
|
572
|
+
@ids.all.must_equal [{:i=>10}, {:i=>20}]
|
|
573
|
+
@db.drop_table(:exp2)
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
it "should have import work with the :slice_size option" do
|
|
577
|
+
@ids.import([:i], [[10], [20], [30]], :slice_size=>1)
|
|
578
|
+
@ids.all.must_equal [{:i=>10}, {:i=>20}, {:i=>30}]
|
|
579
|
+
end
|
|
580
|
+
|
|
581
|
+
it "should import many rows at once" do
|
|
582
|
+
@ids.import([:i], (1..20).to_a.map{|x| [x]})
|
|
583
|
+
@ids.select_order_map(:i).must_equal((1..20).to_a)
|
|
584
|
+
end
|
|
585
|
+
end
|
|
586
|
+
|
|
587
|
+
describe "Sequel::Dataset convenience methods" do
|
|
588
|
+
before do
|
|
589
|
+
@db = DB
|
|
590
|
+
@db.create_table!(:a){Integer :a; Integer :b}
|
|
591
|
+
@ds = @db[:a].order(:a)
|
|
592
|
+
end
|
|
593
|
+
after do
|
|
594
|
+
@db.drop_table?(:a)
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it "#empty? should return whether the dataset returns no rows" do
|
|
598
|
+
@ds.empty?.must_equal true
|
|
599
|
+
@ds.insert(20, 10)
|
|
600
|
+
@ds.empty?.must_equal false
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it "#empty? should work correctly for datasets with limits" do
|
|
604
|
+
ds = @ds.limit(1)
|
|
605
|
+
ds.empty?.must_equal true
|
|
606
|
+
ds.insert(20, 10)
|
|
607
|
+
ds.empty?.must_equal false
|
|
608
|
+
end
|
|
609
|
+
|
|
610
|
+
it "#empty? should work correctly for datasets with limits and offsets" do
|
|
611
|
+
ds = @ds.order(:a).limit(1, 1)
|
|
612
|
+
ds.empty?.must_equal true
|
|
613
|
+
ds.insert(20, 10)
|
|
614
|
+
ds.empty?.must_equal true
|
|
615
|
+
ds.insert(20, 10)
|
|
616
|
+
ds.empty?.must_equal false
|
|
617
|
+
end
|
|
618
|
+
|
|
619
|
+
it "#group_and_count should return a grouping by count" do
|
|
620
|
+
@ds.group_and_count(:a).order{count(:a)}.all.must_equal []
|
|
621
|
+
@ds.insert(20, 10)
|
|
622
|
+
@ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>1}]
|
|
623
|
+
@ds.insert(20, 30)
|
|
624
|
+
@ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>20, :count=>2}]
|
|
625
|
+
@ds.insert(30, 30)
|
|
626
|
+
@ds.group_and_count(:a).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:a=>30, :count=>1}, {:a=>20, :count=>2}]
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
it "#group_and_count should support column aliases" do
|
|
630
|
+
@ds.group_and_count(:a___c).order{count(:a)}.all.must_equal []
|
|
631
|
+
@ds.insert(20, 10)
|
|
632
|
+
@ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>1}]
|
|
633
|
+
@ds.insert(20, 30)
|
|
634
|
+
@ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>20, :count=>2}]
|
|
635
|
+
@ds.insert(30, 30)
|
|
636
|
+
@ds.group_and_count(:a___c).order{count(:a)}.all.each{|h| h[:count] = h[:count].to_i}.must_equal [{:c=>30, :count=>1}, {:c=>20, :count=>2}]
|
|
637
|
+
end
|
|
638
|
+
|
|
639
|
+
it "#range should return the range between the maximum and minimum values" do
|
|
640
|
+
@ds = @ds.unordered
|
|
641
|
+
@ds.insert(20, 10)
|
|
642
|
+
@ds.insert(30, 10)
|
|
643
|
+
@ds.range(:a).must_equal(20..30)
|
|
644
|
+
@ds.range(:b).must_equal(10..10)
|
|
645
|
+
end
|
|
646
|
+
|
|
647
|
+
it "#interval should return the different between the maximum and minimum values" do
|
|
648
|
+
@ds = @ds.unordered
|
|
649
|
+
@ds.insert(20, 10)
|
|
650
|
+
@ds.insert(30, 10)
|
|
651
|
+
@ds.interval(:a).to_i.must_equal 10
|
|
652
|
+
@ds.interval(:b).to_i.must_equal 0
|
|
653
|
+
end
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
describe "Sequel::Dataset main SQL methods" do
|
|
657
|
+
before do
|
|
658
|
+
@db = DB
|
|
659
|
+
@db.create_table!(:d){Integer :a; Integer :b}
|
|
660
|
+
@ds = @db[:d].order(:a)
|
|
661
|
+
end
|
|
662
|
+
after do
|
|
663
|
+
@db.drop_table?(:d)
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
it "#exists should return a usable exists clause" do
|
|
667
|
+
@ds.filter(@db[:d___c].filter(:c__a=>:d__b).exists).all.must_equal []
|
|
668
|
+
@ds.insert(20, 30)
|
|
669
|
+
@ds.insert(10, 20)
|
|
670
|
+
@ds.filter(@db[:d___c].filter(:c__a=>:d__b).exists).all.must_equal [{:a=>10, :b=>20}]
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
it "#filter and #exclude should work with placeholder strings" do
|
|
674
|
+
@ds.insert(20, 30)
|
|
675
|
+
@ds.filter("a > ?", 15).all.must_equal [{:a=>20, :b=>30}]
|
|
676
|
+
@ds.exclude("b < ?", 15).all.must_equal [{:a=>20, :b=>30}]
|
|
677
|
+
@ds.filter("b < ?", 15).invert.all.must_equal [{:a=>20, :b=>30}]
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
it "#and and #or should work correctly" do
|
|
681
|
+
@ds.insert(20, 30)
|
|
682
|
+
@ds.filter(:a=>20).and(:b=>30).all.must_equal [{:a=>20, :b=>30}]
|
|
683
|
+
@ds.filter(:a=>20).and(:b=>15).all.must_equal []
|
|
684
|
+
@ds.filter(:a=>20).or(:b=>15).all.must_equal [{:a=>20, :b=>30}]
|
|
685
|
+
@ds.filter(:a=>10).or(:b=>15).all.must_equal []
|
|
686
|
+
end
|
|
687
|
+
|
|
688
|
+
it "#select_group should work correctly" do
|
|
689
|
+
@ds.unordered!
|
|
690
|
+
@ds.select_group(:a).all.must_equal []
|
|
691
|
+
@ds.insert(20, 30)
|
|
692
|
+
@ds.select_group(:a).all.must_equal [{:a=>20}]
|
|
693
|
+
@ds.select_group(:b).all.must_equal [{:b=>30}]
|
|
694
|
+
@ds.insert(20, 40)
|
|
695
|
+
@ds.select_group(:a).all.must_equal [{:a=>20}]
|
|
696
|
+
@ds.order(:b).select_group(:b).all.must_equal [{:b=>30}, {:b=>40}]
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
it "#select_group should work correctly when aliasing" do
|
|
700
|
+
@ds.unordered!
|
|
701
|
+
@ds.insert(20, 30)
|
|
702
|
+
@ds.select_group(:b___c).all.must_equal [{:c=>30}]
|
|
703
|
+
end
|
|
704
|
+
|
|
705
|
+
it "#having should work correctly" do
|
|
706
|
+
@ds.unordered!
|
|
707
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
|
|
708
|
+
@ds.insert(20, 30)
|
|
709
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.must_equal []
|
|
710
|
+
@ds.insert(40, 20)
|
|
711
|
+
@ds.select{[b, max(a).as(c)]}.group(:b).having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.must_equal [{:b=>20, :c=>40}]
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
it "#having should work without a previous group" do
|
|
715
|
+
@ds.unordered!
|
|
716
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
|
|
717
|
+
@ds.insert(20, 30)
|
|
718
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.must_equal []
|
|
719
|
+
@ds.insert(40, 20)
|
|
720
|
+
@ds.select{max(a).as(c)}.having{max(a) > 30}.all.each{|h| h[:c] = h[:c].to_i}.must_equal [{:c=>40}]
|
|
721
|
+
end
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
describe "Sequel::Dataset convenience methods" do
|
|
725
|
+
before do
|
|
726
|
+
@db = DB
|
|
727
|
+
@db.create_table!(:a){Integer :a; Integer :b; Integer :c; Integer :d}
|
|
728
|
+
@ds = @db[:a].order(:a)
|
|
729
|
+
@ds.insert(1, 2, 3, 4)
|
|
730
|
+
@ds.insert(5, 6, 7, 8)
|
|
731
|
+
end
|
|
732
|
+
after do
|
|
733
|
+
@db.drop_table?(:a)
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
it "should have working #map" do
|
|
737
|
+
@ds.map(:a).must_equal [1, 5]
|
|
738
|
+
@ds.map(:b).must_equal [2, 6]
|
|
739
|
+
@ds.map([:a, :b]).must_equal [[1, 2], [5, 6]]
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
it "should have working #to_hash" do
|
|
743
|
+
@ds.to_hash(:a).must_equal(1=>{:a=>1, :b=>2, :c=>3, :d=>4}, 5=>{:a=>5, :b=>6, :c=>7, :d=>8})
|
|
744
|
+
@ds.to_hash(:b).must_equal(2=>{:a=>1, :b=>2, :c=>3, :d=>4}, 6=>{:a=>5, :b=>6, :c=>7, :d=>8})
|
|
745
|
+
@ds.to_hash([:a, :b]).must_equal([1, 2]=>{:a=>1, :b=>2, :c=>3, :d=>4}, [5, 6]=>{:a=>5, :b=>6, :c=>7, :d=>8})
|
|
746
|
+
|
|
747
|
+
@ds.to_hash(:a, :b).must_equal(1=>2, 5=>6)
|
|
748
|
+
@ds.to_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
|
|
749
|
+
@ds.to_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
|
|
750
|
+
@ds.to_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
it "should have working #to_hash_groups" do
|
|
754
|
+
ds = @ds.order(*@ds.columns)
|
|
755
|
+
ds.insert(1, 2, 3, 9)
|
|
756
|
+
ds.to_hash_groups(:a).must_equal(1=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 5=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
|
|
757
|
+
ds.to_hash_groups(:b).must_equal(2=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], 6=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
|
|
758
|
+
ds.to_hash_groups([:a, :b]).must_equal([1, 2]=>[{:a=>1, :b=>2, :c=>3, :d=>4}, {:a=>1, :b=>2, :c=>3, :d=>9}], [5, 6]=>[{:a=>5, :b=>6, :c=>7, :d=>8}])
|
|
759
|
+
|
|
760
|
+
ds.to_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
|
|
761
|
+
ds.to_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
|
|
762
|
+
ds.to_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
|
|
763
|
+
ds.to_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
|
|
764
|
+
end
|
|
765
|
+
|
|
766
|
+
it "should have working #select_map" do
|
|
767
|
+
@ds.select_map(:a).must_equal [1, 5]
|
|
768
|
+
@ds.select_map(:b).must_equal [2, 6]
|
|
769
|
+
@ds.select_map([:a]).must_equal [[1], [5]]
|
|
770
|
+
@ds.select_map([:a, :b]).must_equal [[1, 2], [5, 6]]
|
|
771
|
+
|
|
772
|
+
@ds.select_map(:a___e).must_equal [1, 5]
|
|
773
|
+
@ds.select_map(:b___e).must_equal [2, 6]
|
|
774
|
+
@ds.select_map([:a___e, :b___f]).must_equal [[1, 2], [5, 6]]
|
|
775
|
+
@ds.select_map([:a__a___e, :a__b___f]).must_equal [[1, 2], [5, 6]]
|
|
776
|
+
@ds.select_map([Sequel.expr(:a__a).as(:e), Sequel.expr(:a__b).as(:f)]).must_equal [[1, 2], [5, 6]]
|
|
777
|
+
@ds.select_map([Sequel.qualify(:a, :a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
|
|
778
|
+
@ds.select_map([Sequel.identifier(:a).qualify(:a).as(:e), Sequel.qualify(:a, :b).as(:f)]).must_equal [[1, 2], [5, 6]]
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
it "should have working #select_order_map" do
|
|
782
|
+
@ds.select_order_map(:a).must_equal [1, 5]
|
|
783
|
+
@ds.select_order_map(Sequel.desc(:a__b)).must_equal [6, 2]
|
|
784
|
+
@ds.select_order_map(Sequel.desc(:a__b___e)).must_equal [6, 2]
|
|
785
|
+
@ds.select_order_map(Sequel.qualify(:a, :b).as(:e)).must_equal [2, 6]
|
|
786
|
+
@ds.select_order_map([:a]).must_equal [[1], [5]]
|
|
787
|
+
@ds.select_order_map([Sequel.desc(:a), :b]).must_equal [[5, 6], [1, 2]]
|
|
788
|
+
|
|
789
|
+
@ds.select_order_map(:a___e).must_equal [1, 5]
|
|
790
|
+
@ds.select_order_map(:b___e).must_equal [2, 6]
|
|
791
|
+
@ds.select_order_map([Sequel.desc(:a___e), :b___f]).must_equal [[5, 6], [1, 2]]
|
|
792
|
+
@ds.select_order_map([Sequel.desc(:a__a___e), :a__b___f]).must_equal [[5, 6], [1, 2]]
|
|
793
|
+
@ds.select_order_map([Sequel.desc(:a__a), Sequel.expr(:a__b).as(:f)]).must_equal [[5, 6], [1, 2]]
|
|
794
|
+
@ds.select_order_map([Sequel.qualify(:a, :a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
|
|
795
|
+
@ds.select_order_map([Sequel.identifier(:a).qualify(:a).desc, Sequel.qualify(:a, :b).as(:f)]).must_equal [[5, 6], [1, 2]]
|
|
796
|
+
end
|
|
797
|
+
|
|
798
|
+
it "should have working #select_hash" do
|
|
799
|
+
@ds.select_hash(:a, :b).must_equal(1=>2, 5=>6)
|
|
800
|
+
@ds.select_hash(:a__a___e, :b).must_equal(1=>2, 5=>6)
|
|
801
|
+
@ds.select_hash(Sequel.expr(:a__a).as(:e), :b).must_equal(1=>2, 5=>6)
|
|
802
|
+
@ds.select_hash(Sequel.qualify(:a, :a).as(:e), :b).must_equal(1=>2, 5=>6)
|
|
803
|
+
@ds.select_hash(Sequel.identifier(:a).qualify(:a).as(:e), :b).must_equal(1=>2, 5=>6)
|
|
804
|
+
@ds.select_hash([:a, :c], :b).must_equal([1, 3]=>2, [5, 7]=>6)
|
|
805
|
+
@ds.select_hash(:a, [:b, :c]).must_equal(1=>[2, 3], 5=>[6, 7])
|
|
806
|
+
@ds.select_hash([:a, :c], [:b, :d]).must_equal([1, 3]=>[2, 4], [5, 7]=>[6, 8])
|
|
807
|
+
end
|
|
808
|
+
|
|
809
|
+
it "should have working #select_hash_groups" do
|
|
810
|
+
ds = @ds.order(*@ds.columns)
|
|
811
|
+
ds.insert(1, 2, 3, 9)
|
|
812
|
+
ds.select_hash_groups(:a, :d).must_equal(1=>[4, 9], 5=>[8])
|
|
813
|
+
ds.select_hash_groups(:a__a___e, :d).must_equal(1=>[4, 9], 5=>[8])
|
|
814
|
+
ds.select_hash_groups(Sequel.expr(:a__a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
|
|
815
|
+
ds.select_hash_groups(Sequel.qualify(:a, :a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
|
|
816
|
+
ds.select_hash_groups(Sequel.identifier(:a).qualify(:a).as(:e), :d).must_equal(1=>[4, 9], 5=>[8])
|
|
817
|
+
ds.select_hash_groups([:a, :c], :d).must_equal([1, 3]=>[4, 9], [5, 7]=>[8])
|
|
818
|
+
ds.select_hash_groups(:a, [:b, :d]).must_equal(1=>[[2, 4], [2, 9]], 5=>[[6, 8]])
|
|
819
|
+
ds.select_hash_groups([:a, :c], [:b, :d]).must_equal([1, 3]=>[[2, 4], [2, 9]], [5, 7]=>[[6, 8]])
|
|
820
|
+
end
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
describe "Sequel::Dataset DSL support" do
|
|
824
|
+
before do
|
|
825
|
+
@db = DB
|
|
826
|
+
@db.create_table!(:a){Integer :a; Integer :b}
|
|
827
|
+
@ds = @db[:a].order(:a)
|
|
828
|
+
end
|
|
829
|
+
after do
|
|
830
|
+
@db.drop_table?(:a)
|
|
831
|
+
end
|
|
832
|
+
|
|
833
|
+
it "should work with standard mathematical operators" do
|
|
834
|
+
@ds.insert(20, 10)
|
|
835
|
+
@ds.get{a + b}.to_i.must_equal 30
|
|
836
|
+
@ds.get{a - b}.to_i.must_equal 10
|
|
837
|
+
@ds.get{a * b}.to_i.must_equal 200
|
|
838
|
+
@ds.get{a / b}.to_i.must_equal 2
|
|
839
|
+
end
|
|
840
|
+
|
|
841
|
+
it "should work with bitwise AND and OR operators" do
|
|
842
|
+
@ds.insert(3, 5)
|
|
843
|
+
@ds.get{a.sql_number | b}.to_i.must_equal 7
|
|
844
|
+
@ds.get{a.sql_number & b}.to_i.must_equal 1
|
|
845
|
+
@ds.get{a.sql_number | b | 8}.to_i.must_equal 15
|
|
846
|
+
@ds.get{a.sql_number & b & 8}.to_i.must_equal 0
|
|
847
|
+
end
|
|
848
|
+
|
|
849
|
+
it "should work with the bitwise compliment operator" do
|
|
850
|
+
@ds.insert(-3, 3)
|
|
851
|
+
@ds.get{~a.sql_number}.to_i.must_equal 2
|
|
852
|
+
@ds.get{~b.sql_number}.to_i.must_equal(-4)
|
|
853
|
+
end
|
|
854
|
+
|
|
855
|
+
it "should work with the bitwise xor operator" do
|
|
856
|
+
@ds.insert(3, 5)
|
|
857
|
+
@ds.get{a.sql_number ^ b}.to_i.must_equal 6
|
|
858
|
+
@ds.get{a.sql_number ^ b ^ 1}.to_i.must_equal 7
|
|
859
|
+
end
|
|
860
|
+
|
|
861
|
+
it "should work with the modulus operator" do
|
|
862
|
+
@ds.insert(3, 5)
|
|
863
|
+
@ds.get{a.sql_number % 4}.to_i.must_equal 3
|
|
864
|
+
@ds.get{b.sql_number % 4}.to_i.must_equal 1
|
|
865
|
+
@ds.get{a.sql_number % 4 % 2}.to_i.must_equal 1
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
it "should work with inequality operators" do
|
|
869
|
+
@ds.insert(10, 11)
|
|
870
|
+
@ds.insert(11, 11)
|
|
871
|
+
@ds.insert(20, 19)
|
|
872
|
+
@ds.insert(20, 20)
|
|
873
|
+
@ds.filter{a > b}.select_order_map(:a).must_equal [20]
|
|
874
|
+
@ds.filter{a >= b}.select_order_map(:a).must_equal [11, 20, 20]
|
|
875
|
+
@ds.filter{a < b}.select_order_map(:a).must_equal [10]
|
|
876
|
+
@ds.filter{a <= b}.select_order_map(:a).must_equal [10, 11, 20]
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
it "should work with casting and string concatentation" do
|
|
880
|
+
@ds.insert(20, 20)
|
|
881
|
+
@ds.get{Sequel.cast(a, String).sql_string + Sequel.cast(b, String)}.must_equal '2020'
|
|
882
|
+
end
|
|
883
|
+
|
|
884
|
+
it "should work with ordering" do
|
|
885
|
+
@ds.insert(10, 20)
|
|
886
|
+
@ds.insert(20, 10)
|
|
887
|
+
@ds.order(:a, :b).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
|
|
888
|
+
@ds.order(Sequel.asc(:a), Sequel.asc(:b)).all.must_equal [{:a=>10, :b=>20}, {:a=>20, :b=>10}]
|
|
889
|
+
@ds.order(Sequel.desc(:a), Sequel.desc(:b)).all.must_equal [{:a=>20, :b=>10}, {:a=>10, :b=>20}]
|
|
890
|
+
end
|
|
891
|
+
|
|
892
|
+
it "should work with qualifying" do
|
|
893
|
+
@ds.insert(10, 20)
|
|
894
|
+
@ds.get(:a__b).must_equal 20
|
|
895
|
+
@ds.get{a__b}.must_equal 20
|
|
896
|
+
@ds.get(Sequel.qualify(:a, :b)).must_equal 20
|
|
897
|
+
end
|
|
898
|
+
|
|
899
|
+
it "should work with aliasing" do
|
|
900
|
+
@ds.insert(10, 20)
|
|
901
|
+
@ds.get(:a__b___c).must_equal 20
|
|
902
|
+
@ds.get{a__b.as(c)}.must_equal 20
|
|
903
|
+
@ds.get(Sequel.qualify(:a, :b).as(:c)).must_equal 20
|
|
904
|
+
@ds.get(Sequel.as(:b, :c)).must_equal 20
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
it "should work with selecting all columns of a table" do
|
|
908
|
+
@ds.insert(20, 10)
|
|
909
|
+
@ds.select_all(:a).all.must_equal [{:a=>20, :b=>10}]
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
it "should work with ranges as hash values" do
|
|
913
|
+
@ds.insert(20, 10)
|
|
914
|
+
@ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
|
|
915
|
+
@ds.filter(:a=>(25..30)).all.must_equal []
|
|
916
|
+
@ds.filter(:a=>(10..15)).all.must_equal []
|
|
917
|
+
@ds.exclude(:a=>(10..30)).all.must_equal []
|
|
918
|
+
@ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
|
|
919
|
+
@ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
|
|
920
|
+
end
|
|
921
|
+
|
|
922
|
+
it "should work with nil as hash value" do
|
|
923
|
+
@ds.insert(20, nil)
|
|
924
|
+
@ds.filter(:a=>nil).all.must_equal []
|
|
925
|
+
@ds.filter(:b=>nil).all.must_equal [{:a=>20, :b=>nil}]
|
|
926
|
+
@ds.exclude(:b=>nil).all.must_equal []
|
|
927
|
+
@ds.exclude(:a=>nil).all.must_equal [{:a=>20, :b=>nil}]
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
it "should work with arrays as hash values" do
|
|
931
|
+
@ds.insert(20, 10)
|
|
932
|
+
@ds.filter(:a=>[10]).all.must_equal []
|
|
933
|
+
@ds.filter(:a=>[20, 10]).all.must_equal [{:a=>20, :b=>10}]
|
|
934
|
+
@ds.exclude(:a=>[10]).all.must_equal [{:a=>20, :b=>10}]
|
|
935
|
+
@ds.exclude(:a=>[20, 10]).all.must_equal []
|
|
936
|
+
end
|
|
937
|
+
|
|
938
|
+
it "should work with ranges as hash values" do
|
|
939
|
+
@ds.insert(20, 10)
|
|
940
|
+
@ds.filter(:a=>(10..30)).all.must_equal [{:a=>20, :b=>10}]
|
|
941
|
+
@ds.filter(:a=>(25..30)).all.must_equal []
|
|
942
|
+
@ds.filter(:a=>(10..15)).all.must_equal []
|
|
943
|
+
@ds.exclude(:a=>(10..30)).all.must_equal []
|
|
944
|
+
@ds.exclude(:a=>(25..30)).all.must_equal [{:a=>20, :b=>10}]
|
|
945
|
+
@ds.exclude(:a=>(10..15)).all.must_equal [{:a=>20, :b=>10}]
|
|
946
|
+
end
|
|
947
|
+
|
|
948
|
+
it "should work with CASE statements" do
|
|
949
|
+
@ds.insert(20, 10)
|
|
950
|
+
@ds.filter(Sequel.case({{:a=>20}=>20}, 0) > 0).all.must_equal [{:a=>20, :b=>10}]
|
|
951
|
+
@ds.filter(Sequel.case({{:a=>15}=>20}, 0) > 0).all.must_equal []
|
|
952
|
+
@ds.filter(Sequel.case({20=>20}, 0, :a) > 0).all.must_equal [{:a=>20, :b=>10}]
|
|
953
|
+
@ds.filter(Sequel.case({15=>20}, 0, :a) > 0).all.must_equal []
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
it "should work with multiple value arrays" do
|
|
957
|
+
@ds.insert(20, 10)
|
|
958
|
+
@ds.quote_identifiers = false
|
|
959
|
+
@ds.filter([:a, :b]=>[[20, 10]]).all.must_equal [{:a=>20, :b=>10}]
|
|
960
|
+
@ds.filter([:a, :b]=>[[10, 20]]).all.must_equal []
|
|
961
|
+
@ds.filter([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal [{:a=>20, :b=>10}]
|
|
962
|
+
@ds.filter([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal []
|
|
963
|
+
|
|
964
|
+
@ds.exclude([:a, :b]=>[[20, 10]]).all.must_equal []
|
|
965
|
+
@ds.exclude([:a, :b]=>[[10, 20]]).all.must_equal [{:a=>20, :b=>10}]
|
|
966
|
+
@ds.exclude([:a, :b]=>[[20, 10], [1, 2]]).all.must_equal []
|
|
967
|
+
@ds.exclude([:a, :b]=>[[10, 10], [20, 20]]).all.must_equal [{:a=>20, :b=>10}]
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
it "should work with IN/NOT in with datasets" do
|
|
971
|
+
@ds.insert(20, 10)
|
|
972
|
+
ds = @ds.unordered
|
|
973
|
+
@ds.quote_identifiers = false
|
|
974
|
+
|
|
975
|
+
@ds.filter(:a=>ds.select(:a)).all.must_equal [{:a=>20, :b=>10}]
|
|
976
|
+
@ds.filter(:a=>ds.select(:a).where(:a=>15)).all.must_equal []
|
|
977
|
+
@ds.exclude(:a=>ds.select(:a)).all.must_equal []
|
|
978
|
+
@ds.exclude(:a=>ds.select(:a).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
|
|
979
|
+
|
|
980
|
+
@ds.filter([:a, :b]=>ds.select(:a, :b)).all.must_equal [{:a=>20, :b=>10}]
|
|
981
|
+
@ds.filter([:a, :b]=>ds.select(:b, :a)).all.must_equal []
|
|
982
|
+
@ds.exclude([:a, :b]=>ds.select(:a, :b)).all.must_equal []
|
|
983
|
+
@ds.exclude([:a, :b]=>ds.select(:b, :a)).all.must_equal [{:a=>20, :b=>10}]
|
|
984
|
+
|
|
985
|
+
@ds.filter([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal []
|
|
986
|
+
@ds.exclude([:a, :b]=>ds.select(:a, :b).where(:a=>15)).all.must_equal [{:a=>20, :b=>10}]
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
it "should work empty arrays" do
|
|
990
|
+
@ds.insert(20, 10)
|
|
991
|
+
@ds.filter(:a=>[]).all.must_equal []
|
|
992
|
+
@ds.exclude(:a=>[]).all.must_equal [{:a=>20, :b=>10}]
|
|
993
|
+
@ds.filter([:a, :b]=>[]).all.must_equal []
|
|
994
|
+
@ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>20, :b=>10}]
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
it "should work empty arrays with nulls" do
|
|
998
|
+
@ds = @ds.extension(:empty_array_consider_nulls)
|
|
999
|
+
@ds.insert(nil, nil)
|
|
1000
|
+
@ds.filter(:a=>[]).all.must_equal []
|
|
1001
|
+
@ds.exclude(:a=>[]).all.must_equal []
|
|
1002
|
+
@ds.filter([:a, :b]=>[]).all.must_equal []
|
|
1003
|
+
@ds.exclude([:a, :b]=>[]).all.must_equal []
|
|
1004
|
+
|
|
1005
|
+
pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
|
|
1006
|
+
assert_nil(pr[@ds.get(Sequel.expr(:a=>[]))])
|
|
1007
|
+
assert_nil(pr[@ds.get(~Sequel.expr(:a=>[]))])
|
|
1008
|
+
assert_nil(pr[@ds.get(Sequel.expr([:a, :b]=>[]))])
|
|
1009
|
+
assert_nil(pr[@ds.get(~Sequel.expr([:a, :b]=>[]))])
|
|
1010
|
+
end
|
|
1011
|
+
|
|
1012
|
+
it "should work empty arrays with nulls and the empty_array_ignore_nulls extension" do
|
|
1013
|
+
ds = @ds
|
|
1014
|
+
ds.insert(nil, nil)
|
|
1015
|
+
ds.filter(:a=>[]).all.must_equal []
|
|
1016
|
+
ds.exclude(:a=>[]).all.must_equal [{:a=>nil, :b=>nil}]
|
|
1017
|
+
ds.filter([:a, :b]=>[]).all.must_equal []
|
|
1018
|
+
ds.exclude([:a, :b]=>[]).all.must_equal [{:a=>nil, :b=>nil}]
|
|
1019
|
+
|
|
1020
|
+
pr = proc{|r| r.is_a?(Integer) ? (r != 0) : r}
|
|
1021
|
+
pr[ds.get(Sequel.expr(:a=>[]))].must_equal false
|
|
1022
|
+
pr[ds.get(~Sequel.expr(:a=>[]))].must_equal true
|
|
1023
|
+
pr[ds.get(Sequel.expr([:a, :b]=>[]))].must_equal false
|
|
1024
|
+
pr[ds.get(~Sequel.expr([:a, :b]=>[]))].must_equal true
|
|
1025
|
+
end
|
|
1026
|
+
|
|
1027
|
+
it "should work multiple conditions" do
|
|
1028
|
+
@ds.insert(20, 10)
|
|
1029
|
+
@ds.filter(:a=>20, :b=>10).all.must_equal [{:a=>20, :b=>10}]
|
|
1030
|
+
@ds.filter([[:a, 20], [:b, 10]]).all.must_equal [{:a=>20, :b=>10}]
|
|
1031
|
+
@ds.filter({:a=>20}, {:b=>10}).all.must_equal [{:a=>20, :b=>10}]
|
|
1032
|
+
@ds.filter(Sequel.|({:a=>20}, {:b=>5})).all.must_equal [{:a=>20, :b=>10}]
|
|
1033
|
+
@ds.filter(Sequel.~(:a=>10)).all.must_equal [{:a=>20, :b=>10}]
|
|
1034
|
+
end
|
|
1035
|
+
end
|
|
1036
|
+
|
|
1037
|
+
describe "SQL Extract Function" do
|
|
1038
|
+
before do
|
|
1039
|
+
@db = DB
|
|
1040
|
+
@db.create_table!(:a){DateTime :a}
|
|
1041
|
+
@ds = @db[:a].order(:a)
|
|
1042
|
+
end
|
|
1043
|
+
after do
|
|
1044
|
+
@db.drop_table?(:a)
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
it "should return the part of the datetime asked for" do
|
|
1048
|
+
t = Time.now
|
|
1049
|
+
def @ds.supports_timestamp_timezones?() false end
|
|
1050
|
+
@ds.insert(t)
|
|
1051
|
+
@ds.get{a.extract(:year)}.must_equal t.year
|
|
1052
|
+
@ds.get{a.extract(:month)}.must_equal t.month
|
|
1053
|
+
@ds.get{a.extract(:day)}.must_equal t.day
|
|
1054
|
+
@ds.get{a.extract(:hour)}.must_equal t.hour
|
|
1055
|
+
@ds.get{a.extract(:minute)}.must_equal t.min
|
|
1056
|
+
@ds.get{a.extract(:second)}.to_i.must_equal t.sec
|
|
1057
|
+
end
|
|
1058
|
+
end
|
|
1059
|
+
|
|
1060
|
+
describe "Dataset string methods" do
|
|
1061
|
+
before do
|
|
1062
|
+
@db = DB
|
|
1063
|
+
@db.create_table!(:a) do
|
|
1064
|
+
String :a
|
|
1065
|
+
String :b
|
|
1066
|
+
end
|
|
1067
|
+
@ds = @db[:a].order(:a)
|
|
1068
|
+
end
|
|
1069
|
+
after do
|
|
1070
|
+
@db.drop_table?(:a)
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
it "#grep should return matching rows" do
|
|
1074
|
+
@ds.insert('foo', 'bar')
|
|
1075
|
+
@ds.grep(:a, 'foo').all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1076
|
+
@ds.grep(:b, 'foo').all.must_equal []
|
|
1077
|
+
@ds.grep(:b, 'bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1078
|
+
@ds.grep(:a, 'bar').all.must_equal []
|
|
1079
|
+
@ds.grep([:a, :b], %w'foo bar').all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1080
|
+
@ds.grep([:a, :b], %w'boo far').all.must_equal []
|
|
1081
|
+
end
|
|
1082
|
+
|
|
1083
|
+
it "#grep should work with :all_patterns and :all_columns options" do
|
|
1084
|
+
@ds.insert('foo bar', ' ')
|
|
1085
|
+
@ds.insert('foo d', 'bar')
|
|
1086
|
+
@ds.insert('foo e', ' ')
|
|
1087
|
+
@ds.insert(' ', 'bar')
|
|
1088
|
+
@ds.insert('foo f', 'baz')
|
|
1089
|
+
@ds.insert('foo baz', 'bar baz')
|
|
1090
|
+
@ds.insert('foo boo', 'boo foo')
|
|
1091
|
+
|
|
1092
|
+
@ds.grep([:a, :b], %w'%foo% %bar%', :all_patterns=>true).all.must_equal [{:a=>'foo bar', :b=>' '}, {:a=>'foo baz', :b=>'bar baz'}, {:a=>'foo d', :b=>'bar'}]
|
|
1093
|
+
@ds.grep([:a, :b], %w'%foo% %bar% %blob%', :all_patterns=>true).all.must_equal []
|
|
1094
|
+
|
|
1095
|
+
@ds.grep([:a, :b], %w'%bar% %foo%', :all_columns=>true).all.must_equal [{:a=>"foo baz", :b=>"bar baz"}, {:a=>"foo boo", :b=>"boo foo"}, {:a=>"foo d", :b=>"bar"}]
|
|
1096
|
+
@ds.grep([:a, :b], %w'%baz%', :all_columns=>true).all.must_equal [{:a=>'foo baz', :b=>'bar baz'}]
|
|
1097
|
+
|
|
1098
|
+
@ds.grep([:a, :b], %w'%baz% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal []
|
|
1099
|
+
@ds.grep([:a, :b], %w'%boo% %foo%', :all_columns=>true, :all_patterns=>true).all.must_equal [{:a=>'foo boo', :b=>'boo foo'}]
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
it "#like should return matching rows" do
|
|
1103
|
+
@ds.insert('foo', 'bar')
|
|
1104
|
+
@ds.filter(Sequel.expr(:a).like('foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1105
|
+
@ds.filter(Sequel.expr(:a).like('bar')).all.must_equal []
|
|
1106
|
+
@ds.filter(Sequel.expr(:a).like('foo', 'bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1107
|
+
@ds.exclude(Sequel.expr(:a).like('foo')).all.must_equal []
|
|
1108
|
+
@ds.exclude(Sequel.expr(:a).like('bar')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1109
|
+
@ds.exclude(Sequel.expr(:a).like('foo', 'bar')).all.must_equal []
|
|
1110
|
+
end
|
|
1111
|
+
|
|
1112
|
+
it "#like should be case sensitive" do
|
|
1113
|
+
@ds.insert('foo', 'bar')
|
|
1114
|
+
@ds.filter(Sequel.expr(:a).like('Foo')).all.must_equal []
|
|
1115
|
+
@ds.filter(Sequel.expr(:b).like('baR')).all.must_equal []
|
|
1116
|
+
@ds.filter(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal []
|
|
1117
|
+
@ds.exclude(Sequel.expr(:a).like('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1118
|
+
@ds.exclude(Sequel.expr(:b).like('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1119
|
+
@ds.exclude(Sequel.expr(:a).like('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1120
|
+
end
|
|
1121
|
+
|
|
1122
|
+
it "#ilike should return matching rows, in a case insensitive manner" do
|
|
1123
|
+
@ds.insert('foo', 'bar')
|
|
1124
|
+
@ds.filter(Sequel.expr(:a).ilike('Foo')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1125
|
+
@ds.filter(Sequel.expr(:a).ilike('baR')).all.must_equal []
|
|
1126
|
+
@ds.filter(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1127
|
+
@ds.exclude(Sequel.expr(:a).ilike('Foo')).all.must_equal []
|
|
1128
|
+
@ds.exclude(Sequel.expr(:a).ilike('baR')).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1129
|
+
@ds.exclude(Sequel.expr(:a).ilike('FOO', 'BAR')).all.must_equal []
|
|
1130
|
+
end
|
|
1131
|
+
|
|
1132
|
+
it "#like with regexp return matching rows" do
|
|
1133
|
+
@ds.insert('foo', 'bar')
|
|
1134
|
+
@ds.filter(Sequel.expr(:a).like(/fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1135
|
+
@ds.filter(Sequel.expr(:a).like(/fo$/)).all.must_equal []
|
|
1136
|
+
@ds.filter(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1137
|
+
@ds.exclude(Sequel.expr(:a).like(/fo/)).all.must_equal []
|
|
1138
|
+
@ds.exclude(Sequel.expr(:a).like(/fo$/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1139
|
+
@ds.exclude(Sequel.expr(:a).like(/fo/, /ar/)).all.must_equal []
|
|
1140
|
+
end
|
|
1141
|
+
|
|
1142
|
+
it "#like with regexp should be case sensitive if regexp is case sensitive" do
|
|
1143
|
+
@ds.insert('foo', 'bar')
|
|
1144
|
+
@ds.filter(Sequel.expr(:a).like(/Fo/)).all.must_equal []
|
|
1145
|
+
@ds.filter(Sequel.expr(:b).like(/baR/)).all.must_equal []
|
|
1146
|
+
@ds.filter(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal []
|
|
1147
|
+
@ds.exclude(Sequel.expr(:a).like(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1148
|
+
@ds.exclude(Sequel.expr(:b).like(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1149
|
+
@ds.exclude(Sequel.expr(:a).like(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1150
|
+
|
|
1151
|
+
@ds.filter(Sequel.expr(:a).like(/Fo/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1152
|
+
@ds.filter(Sequel.expr(:b).like(/baR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1153
|
+
@ds.filter(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1154
|
+
@ds.exclude(Sequel.expr(:a).like(/Fo/i)).all.must_equal []
|
|
1155
|
+
@ds.exclude(Sequel.expr(:b).like(/baR/i)).all.must_equal []
|
|
1156
|
+
@ds.exclude(Sequel.expr(:a).like(/FOO/i, /BAR/i)).all.must_equal []
|
|
1157
|
+
end
|
|
1158
|
+
|
|
1159
|
+
it "#ilike with regexp should return matching rows, in a case insensitive manner" do
|
|
1160
|
+
@ds.insert('foo', 'bar')
|
|
1161
|
+
@ds.filter(Sequel.expr(:a).ilike(/Fo/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1162
|
+
@ds.filter(Sequel.expr(:b).ilike(/baR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1163
|
+
@ds.filter(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal [{:a=>'foo', :b=>'bar'}]
|
|
1164
|
+
@ds.exclude(Sequel.expr(:a).ilike(/Fo/)).all.must_equal []
|
|
1165
|
+
@ds.exclude(Sequel.expr(:b).ilike(/baR/)).all.must_equal []
|
|
1166
|
+
@ds.exclude(Sequel.expr(:a).ilike(/FOO/, /BAR/)).all.must_equal []
|
|
1167
|
+
end
|
|
1168
|
+
|
|
1169
|
+
it "should work with strings created with Sequel.join" do
|
|
1170
|
+
@ds.insert('foo', 'bar')
|
|
1171
|
+
@ds.get(Sequel.join([:a, "bar"])).must_equal 'foobar'
|
|
1172
|
+
@ds.get(Sequel.join(["foo", :b], ' ')).must_equal 'foo bar'
|
|
1173
|
+
end
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
describe "Dataset identifier methods" do
|
|
1177
|
+
before(:all) do
|
|
1178
|
+
class ::String
|
|
1179
|
+
def uprev
|
|
1180
|
+
upcase.reverse
|
|
1181
|
+
end
|
|
1182
|
+
end
|
|
1183
|
+
@db = DB
|
|
1184
|
+
@db.create_table!(:a){Integer :ab}
|
|
1185
|
+
@db[:a].insert(1)
|
|
1186
|
+
end
|
|
1187
|
+
before do
|
|
1188
|
+
@ds = @db[:a].order(:ab)
|
|
1189
|
+
end
|
|
1190
|
+
after(:all) do
|
|
1191
|
+
@db.drop_table?(:a)
|
|
1192
|
+
end
|
|
1193
|
+
|
|
1194
|
+
it "#identifier_output_method should change how identifiers are output" do
|
|
1195
|
+
@ds.identifier_output_method = :upcase
|
|
1196
|
+
@ds.first.must_equal(:AB=>1)
|
|
1197
|
+
@ds.identifier_output_method = :uprev
|
|
1198
|
+
@ds.first.must_equal(:BA=>1)
|
|
1199
|
+
end
|
|
1200
|
+
|
|
1201
|
+
it "should work with a nil identifier_output_method" do
|
|
1202
|
+
@ds.identifier_output_method = nil
|
|
1203
|
+
[{:ab=>1}, {:AB=>1}].must_include(@ds.first)
|
|
1204
|
+
end
|
|
1205
|
+
|
|
1206
|
+
it "should work when not quoting identifiers" do
|
|
1207
|
+
@ds.quote_identifiers = false
|
|
1208
|
+
@ds.first.must_equal(:ab=>1)
|
|
1209
|
+
end
|
|
1210
|
+
end
|
|
1211
|
+
|
|
1212
|
+
describe "Dataset defaults and overrides" do
|
|
1213
|
+
before do
|
|
1214
|
+
@db = DB
|
|
1215
|
+
@db.create_table!(:a){Integer :a}
|
|
1216
|
+
@ds = @db[:a].order(:a).extension(:set_overrides)
|
|
1217
|
+
end
|
|
1218
|
+
after do
|
|
1219
|
+
@db.drop_table?(:a)
|
|
1220
|
+
end
|
|
1221
|
+
|
|
1222
|
+
it "#set_defaults should set defaults that can be overridden" do
|
|
1223
|
+
@ds = @ds.set_defaults(:a=>10)
|
|
1224
|
+
@ds.insert
|
|
1225
|
+
@ds.insert(:a=>20)
|
|
1226
|
+
@ds.all.must_equal [{:a=>10}, {:a=>20}]
|
|
1227
|
+
end
|
|
1228
|
+
|
|
1229
|
+
it "#set_overrides should set defaults that cannot be overridden" do
|
|
1230
|
+
@ds = @ds.set_overrides(:a=>10)
|
|
1231
|
+
@ds.insert
|
|
1232
|
+
@ds.insert(:a=>20)
|
|
1233
|
+
@ds.all.must_equal [{:a=>10}, {:a=>10}]
|
|
1234
|
+
end
|
|
1235
|
+
end
|
|
1236
|
+
|
|
1237
|
+
describe "Emulated functions" do
|
|
1238
|
+
before do
|
|
1239
|
+
@db = DB
|
|
1240
|
+
@db.create_table!(:a){String :a}
|
|
1241
|
+
@ds = @db[:a]
|
|
1242
|
+
end
|
|
1243
|
+
after do
|
|
1244
|
+
@db.drop_table?(:a)
|
|
1245
|
+
end
|
|
1246
|
+
|
|
1247
|
+
it "Sequel.char_length should return the length of characters in the string" do
|
|
1248
|
+
assert_nil(@ds.get(Sequel.char_length(:a)))
|
|
1249
|
+
@ds.insert(:a=>'foo')
|
|
1250
|
+
@ds.get(Sequel.char_length(:a)).must_equal 3
|
|
1251
|
+
end
|
|
1252
|
+
|
|
1253
|
+
it "Sequel.char_length should return the length of characters in the string including trailing blanks" do
|
|
1254
|
+
@ds.insert(:a=>' foo22 ')
|
|
1255
|
+
@ds.get(Sequel.char_length(:a)).must_equal 7
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
it "Sequel.trim should return the string with spaces trimmed from both sides" do
|
|
1259
|
+
assert_nil(@ds.get(Sequel.trim(:a)))
|
|
1260
|
+
@ds.insert(:a=>'foo')
|
|
1261
|
+
@ds.get(Sequel.trim(:a)).must_equal 'foo'
|
|
1262
|
+
end
|
|
1263
|
+
|
|
1264
|
+
it "Sequel.trim should return the string with spaces trimmed from both sides" do
|
|
1265
|
+
@ds.insert(:a=>' foo22 ')
|
|
1266
|
+
@ds.get(Sequel.trim(:a)).must_equal 'foo22'
|
|
1267
|
+
end
|
|
1268
|
+
end
|