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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +50 -0
  3. data/LICENSE +463 -0
  4. data/README.md +45 -0
  5. data/Rakefile +39 -0
  6. data/lib/driver/commons-collections-3.2.1.jar +0 -0
  7. data/lib/driver/commons-configuration-1.10.jar +0 -0
  8. data/lib/driver/commons-logging-1.2.jar +0 -0
  9. data/lib/driver/hadoop-auth-2.9.0.jar +0 -0
  10. data/lib/driver/hadoop-common-2.9.0.jar +0 -0
  11. data/lib/driver/hadoop-core-2.6.0.jar +0 -0
  12. data/lib/driver/hive-exec-1.1.0.jar +0 -0
  13. data/lib/driver/hive-jdbc-1.1.0.jar +0 -0
  14. data/lib/driver/hive-metastore-1.1.0.jar +0 -0
  15. data/lib/driver/hive-service-1.1.0.jar +0 -0
  16. data/lib/driver/httpclient-4.3.jar +0 -0
  17. data/lib/driver/httpcore-4.3.jar +0 -0
  18. data/lib/driver/libfb303-0.9.0.jar +0 -0
  19. data/lib/driver/log4j-1.2.17.jar +0 -0
  20. data/lib/driver/slf4j-api-1.7.5.jar +0 -0
  21. data/lib/driver/stax2-api-3.1.4.jar +0 -0
  22. data/lib/driver/woodstox-core-asl-4.4.1.jar +0 -0
  23. data/lib/impala.rb +55 -0
  24. data/lib/impala/connection.rb +180 -0
  25. data/lib/impala/cursor.rb +200 -0
  26. data/lib/impala/progress_reporter.rb +40 -0
  27. data/lib/impala/protocol.rb +8 -0
  28. data/lib/impala/protocol/beeswax_constants.rb +15 -0
  29. data/lib/impala/protocol/beeswax_service.rb +747 -0
  30. data/lib/impala/protocol/beeswax_types.rb +193 -0
  31. data/lib/impala/protocol/exec_stats_constants.rb +13 -0
  32. data/lib/impala/protocol/exec_stats_types.rb +133 -0
  33. data/lib/impala/protocol/facebook_service.rb +706 -0
  34. data/lib/impala/protocol/fb303_constants.rb +15 -0
  35. data/lib/impala/protocol/fb303_types.rb +25 -0
  36. data/lib/impala/protocol/hive_metastore_constants.rb +53 -0
  37. data/lib/impala/protocol/hive_metastore_types.rb +698 -0
  38. data/lib/impala/protocol/impala_hive_server2_service.rb +137 -0
  39. data/lib/impala/protocol/impala_service.rb +443 -0
  40. data/lib/impala/protocol/impala_service_constants.rb +13 -0
  41. data/lib/impala/protocol/impala_service_types.rb +192 -0
  42. data/lib/impala/protocol/status_constants.rb +13 -0
  43. data/lib/impala/protocol/status_types.rb +46 -0
  44. data/lib/impala/protocol/t_c_l_i_service.rb +1108 -0
  45. data/lib/impala/protocol/t_c_l_i_service_constants.rb +72 -0
  46. data/lib/impala/protocol/t_c_l_i_service_types.rb +1802 -0
  47. data/lib/impala/protocol/thrift_hive_metastore.rb +4707 -0
  48. data/lib/impala/protocol/types_constants.rb +13 -0
  49. data/lib/impala/protocol/types_types.rb +332 -0
  50. data/lib/impala/sasl_transport.rb +117 -0
  51. data/lib/impala/thrift_patch.rb +31 -0
  52. data/lib/impala/version.rb +3 -0
  53. data/lib/jdbc/hive2.rb +52 -0
  54. data/lib/jdbc/impala.rb +50 -0
  55. data/lib/rbhive.rb +8 -0
  56. data/lib/rbhive/connection.rb +150 -0
  57. data/lib/rbhive/explain_result.rb +46 -0
  58. data/lib/rbhive/result_set.rb +37 -0
  59. data/lib/rbhive/schema_definition.rb +86 -0
  60. data/lib/rbhive/t_c_l_i_connection.rb +466 -0
  61. data/lib/rbhive/t_c_l_i_result_set.rb +3 -0
  62. data/lib/rbhive/t_c_l_i_schema_definition.rb +87 -0
  63. data/lib/rbhive/table_schema.rb +122 -0
  64. data/lib/rbhive/version.rb +3 -0
  65. data/lib/sequel/adapters/impala.rb +220 -0
  66. data/lib/sequel/adapters/jdbc/hive2.rb +36 -0
  67. data/lib/sequel/adapters/jdbc/impala.rb +38 -0
  68. data/lib/sequel/adapters/rbhive.rb +177 -0
  69. data/lib/sequel/adapters/shared/impala.rb +808 -0
  70. data/lib/sequel/extensions/csv_to_parquet.rb +166 -0
  71. data/lib/thrift/facebook_service.rb +700 -0
  72. data/lib/thrift/fb303_constants.rb +9 -0
  73. data/lib/thrift/fb303_types.rb +19 -0
  74. data/lib/thrift/hive_metastore_constants.rb +41 -0
  75. data/lib/thrift/hive_metastore_types.rb +630 -0
  76. data/lib/thrift/hive_service_constants.rb +13 -0
  77. data/lib/thrift/hive_service_types.rb +72 -0
  78. data/lib/thrift/queryplan_constants.rb +13 -0
  79. data/lib/thrift/queryplan_types.rb +261 -0
  80. data/lib/thrift/sasl_client_transport.rb +161 -0
  81. data/lib/thrift/serde_constants.rb +92 -0
  82. data/lib/thrift/serde_types.rb +7 -0
  83. data/lib/thrift/t_c_l_i_service.rb +1054 -0
  84. data/lib/thrift/t_c_l_i_service_constants.rb +72 -0
  85. data/lib/thrift/t_c_l_i_service_types.rb +1768 -0
  86. data/lib/thrift/thrift_hive.rb +508 -0
  87. data/lib/thrift/thrift_hive_metastore.rb +3856 -0
  88. data/spec/database_test.rb +56 -0
  89. data/spec/dataset_test.rb +1268 -0
  90. data/spec/files/bad_down_migration/001_create_alt_basic.rb +4 -0
  91. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +4 -0
  92. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  93. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  94. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +3 -0
  95. data/spec/files/bad_up_migration/001_create_alt_basic.rb +4 -0
  96. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +3 -0
  97. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +9 -0
  98. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +9 -0
  99. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +4 -0
  100. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +9 -0
  101. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +9 -0
  102. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  103. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +9 -0
  104. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +4 -0
  105. data/spec/files/integer_migrations/001_create_sessions.rb +9 -0
  106. data/spec/files/integer_migrations/002_create_nodes.rb +9 -0
  107. data/spec/files/integer_migrations/003_3_create_users.rb +4 -0
  108. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +9 -0
  109. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +9 -0
  110. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +9 -0
  111. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +9 -0
  112. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +4 -0
  113. data/spec/files/reversible_migrations/001_reversible.rb +5 -0
  114. data/spec/files/reversible_migrations/002_reversible.rb +5 -0
  115. data/spec/files/reversible_migrations/003_reversible.rb +5 -0
  116. data/spec/files/reversible_migrations/004_reversible.rb +5 -0
  117. data/spec/files/reversible_migrations/005_reversible.rb +10 -0
  118. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +9 -0
  119. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +9 -0
  120. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +4 -0
  121. data/spec/impala_test.rb +290 -0
  122. data/spec/migrator_test.rb +240 -0
  123. data/spec/plugin_test.rb +91 -0
  124. data/spec/prepared_statement_test.rb +327 -0
  125. data/spec/schema_test.rb +356 -0
  126. data/spec/spec_helper.rb +19 -0
  127. data/spec/timezone_test.rb +86 -0
  128. data/spec/type_test.rb +99 -0
  129. metadata +294 -0
@@ -0,0 +1,240 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
+
3
+ Sequel.extension :migration
4
+ describe Sequel::Migrator do
5
+ before do
6
+ @db = DB
7
+ @m = Sequel::Migrator
8
+ end
9
+ after do
10
+ @db.drop_table?(:schema_info, :schema_migrations, :sm1111, :sm1122, :sm2222, :sm2233, :sm3333, :sm11111, :sm22222)
11
+ end
12
+
13
+ it "should be able to migrate up and down all the way successfully" do
14
+ @dir = 'spec/files/integer_migrations'
15
+ @m.apply(@db, @dir)
16
+ [:schema_info, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
17
+ @db[:schema_info].get(:version).must_equal 3
18
+ @m.apply(@db, @dir, 0)
19
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
20
+ @db[:schema_info].get(:version).must_equal 0
21
+ end
22
+
23
+ it "should be able to migrate up and down to specific versions successfully" do
24
+ @dir = 'spec/files/integer_migrations'
25
+ @m.apply(@db, @dir, 2)
26
+ [:schema_info, :sm1111, :sm2222].each{|n| @db.table_exists?(n).must_equal true}
27
+ @db.table_exists?(:sm3333).must_equal false
28
+ @db[:schema_info].get(:version).must_equal 2
29
+ @m.apply(@db, @dir, 1)
30
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
31
+ @db.table_exists?(:sm1111).must_equal true
32
+ @db[:schema_info].get(:version).must_equal 1
33
+ end
34
+
35
+ it "should correctly set migration version to the last successful migration if the migration raises an error when migrating up" do
36
+ @dir = 'spec/files/bad_up_migration'
37
+ proc{@m.apply(@db, @dir)}.must_raise Sequel::DatabaseError
38
+ [:schema_info, :sm11111].each{|n| @db.table_exists?(n).must_equal true}
39
+ @db.table_exists?(:sm22222).must_equal false
40
+ @db[:schema_info].get(:version).must_equal 1
41
+ @m.apply(@db, @dir, 0)
42
+ [:sm11111, :sm22222].each{|n| @db.table_exists?(n).must_equal false}
43
+ @db[:schema_info].get(:version).must_equal 0
44
+ end
45
+
46
+ it "should correctly set migration version to the last successful migration if the migration raises an error when migrating down" do
47
+ @dir = 'spec/files/bad_down_migration'
48
+ @m.apply(@db, @dir)
49
+ [:schema_info, :sm11111, :sm22222].each{|n| @db.table_exists?(n).must_equal true}
50
+ @db[:schema_info].get(:version).must_equal 2
51
+ proc{@m.apply(@db, @dir, 0)}.must_raise Sequel::DatabaseError
52
+ [:sm22222].each{|n| @db.table_exists?(n).must_equal false}
53
+ @db.table_exists?(:sm11111).must_equal true
54
+ @db[:schema_info].get(:version).must_equal 1
55
+ end
56
+
57
+ it "should handle migrating up or down all the way with timestamped migrations" do
58
+ @dir = 'spec/files/timestamped_migrations'
59
+ @m.apply(@db, @dir)
60
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
61
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb 1273253853_3_create_users.rb'
62
+ @m.apply(@db, @dir, 0)
63
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
64
+ @db[:schema_migrations].select_order_map(:filename).must_equal []
65
+ end
66
+
67
+ it "should handle migrating up or down to specific timestamps with timestamped migrations" do
68
+ @dir = 'spec/files/timestamped_migrations'
69
+ @m.apply(@db, @dir, 1273253851)
70
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).must_equal true}
71
+ @db.table_exists?(:sm3333).must_equal false
72
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
73
+ @m.apply(@db, @dir, 1273253849)
74
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
75
+ @db.table_exists?(:sm1111).must_equal true
76
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb'
77
+ end
78
+
79
+ it "should apply all missing files when migrating up with timestamped migrations" do
80
+ @dir = 'spec/files/timestamped_migrations'
81
+ @m.apply(@db, @dir)
82
+ @dir = 'spec/files/interleaved_timestamped_migrations'
83
+ @m.apply(@db, @dir)
84
+ [:schema_migrations, :sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
85
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253850_create_artists.rb 1273253851_create_nodes.rb 1273253852_create_albums.rb 1273253853_3_create_users.rb'
86
+ end
87
+
88
+ it "should not apply down action to migrations where up action hasn't been applied" do
89
+ @dir = 'spec/files/timestamped_migrations'
90
+ @m.apply(@db, @dir)
91
+ @dir = 'spec/files/interleaved_timestamped_migrations'
92
+ @m.apply(@db, @dir, 0)
93
+ [:sm1111, :sm1122, :sm2222, :sm2233, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
94
+ @db[:schema_migrations].select_order_map(:filename).must_equal []
95
+ end
96
+
97
+ it "should handle updating to a specific timestamp when interleaving migrations with timestamps" do
98
+ @dir = 'spec/files/timestamped_migrations'
99
+ @m.apply(@db, @dir)
100
+ @dir = 'spec/files/interleaved_timestamped_migrations'
101
+ @m.apply(@db, @dir, 1273253851)
102
+ [:schema_migrations, :sm1111, :sm1122, :sm2222].each{|n| @db.table_exists?(n).must_equal true}
103
+ [:sm2233, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
104
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253850_create_artists.rb 1273253851_create_nodes.rb'
105
+ end
106
+
107
+ it "should correctly update schema_migrations table when an error occurs when migrating up or down using timestamped migrations" do
108
+ @dir = 'spec/files/bad_timestamped_migrations'
109
+ proc{@m.apply(@db, @dir)}.must_raise Sequel::DatabaseError
110
+ [:schema_migrations, :sm1111, :sm2222].each{|n| @db.table_exists?(n).must_equal true}
111
+ @db.table_exists?(:sm3333).must_equal false
112
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253851_create_nodes.rb'
113
+ proc{@m.apply(@db, @dir, 0)}.must_raise Sequel::DatabaseError
114
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
115
+ @db.table_exists?(:sm1111).must_equal true
116
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb'
117
+ end
118
+
119
+ it "should handle multiple migrations with the same timestamp correctly" do
120
+ @dir = 'spec/files/duplicate_timestamped_migrations'
121
+ @m.apply(@db, @dir)
122
+ [:schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
123
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
124
+ @m.apply(@db, @dir, 1273253853)
125
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
126
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb 1273253853_create_nodes.rb 1273253853_create_users.rb'
127
+ @m.apply(@db, @dir, 1273253849)
128
+ [:sm1111].each{|n| @db.table_exists?(n).must_equal true}
129
+ [:sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
130
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'1273253849_create_sessions.rb'
131
+ @m.apply(@db, @dir, 1273253848)
132
+ [:sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal false}
133
+ @db[:schema_migrations].select_order_map(:filename).must_equal []
134
+ end
135
+
136
+ it "should convert schema_info table to schema_migrations table" do
137
+ @dir = 'spec/files/integer_migrations'
138
+ @m.apply(@db, @dir)
139
+ [:schema_info, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
140
+ [:schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
141
+
142
+ @dir = 'spec/files/convert_to_timestamp_migrations'
143
+ @m.apply(@db, @dir)
144
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal true}
145
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb 1273253852_create_albums.rb'
146
+
147
+ @m.apply(@db, @dir, 4)
148
+ [:schema_info, :schema_migrations, :sm1111, :sm2222, :sm3333].each{|n| @db.table_exists?(n).must_equal true}
149
+ [:sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
150
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb'
151
+
152
+ @m.apply(@db, @dir, 0)
153
+ [:schema_info, :schema_migrations].each{|n| @db.table_exists?(n).must_equal true}
154
+ [:sm1111, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
155
+ @db[:schema_migrations].select_order_map(:filename).must_equal []
156
+ end
157
+
158
+ it "should handle unapplied migrations when migrating schema_info table to schema_migrations table" do
159
+ @dir = 'spec/files/integer_migrations'
160
+ @m.apply(@db, @dir, 2)
161
+ [:schema_info, :sm1111, :sm2222].each{|n| @db.table_exists?(n).must_equal true}
162
+ [:schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
163
+
164
+ @dir = 'spec/files/convert_to_timestamp_migrations'
165
+ @m.apply(@db, @dir, 1273253850)
166
+ [:schema_info, :sm1111, :sm2222, :sm3333, :schema_migrations, :sm1122].each{|n| @db.table_exists?(n).must_equal true}
167
+ [:sm2233].each{|n| @db.table_exists?(n).must_equal false}
168
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb'
169
+ end
170
+
171
+ it "should handle unapplied migrations when migrating schema_info table to schema_migrations table and target is less than last integer migration version" do
172
+ @dir = 'spec/files/integer_migrations'
173
+ @m.apply(@db, @dir, 1)
174
+ [:schema_info, :sm1111].each{|n| @db.table_exists?(n).must_equal true}
175
+ [:schema_migrations, :sm2222, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
176
+
177
+ @dir = 'spec/files/convert_to_timestamp_migrations'
178
+ @m.apply(@db, @dir, 2)
179
+ [:schema_info, :sm1111, :sm2222, :schema_migrations].each{|n| @db.table_exists?(n).must_equal true}
180
+ [:sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal false}
181
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'001_create_sessions.rb 002_create_nodes.rb'
182
+
183
+ @m.apply(@db, @dir)
184
+ [:schema_info, :sm1111, :sm2222, :schema_migrations, :sm3333, :sm1122, :sm2233].each{|n| @db.table_exists?(n).must_equal true}
185
+ @db[:schema_migrations].select_order_map(:filename).must_equal %w'001_create_sessions.rb 002_create_nodes.rb 003_3_create_users.rb 1273253850_create_artists.rb 1273253852_create_albums.rb'
186
+ end
187
+
188
+ it "should handle reversible migrations" do
189
+ @dir = 'spec/files/reversible_migrations'
190
+ @db.drop_table?(:a, :b)
191
+ @m.apply(@db, @dir, 1)
192
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
193
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
194
+ @db[:a].columns.must_equal [:a]
195
+
196
+ @m.apply(@db, @dir, 2)
197
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
198
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
199
+ @db[:a].columns.must_equal [:a, :b]
200
+
201
+ @m.apply(@db, @dir, 3)
202
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
203
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
204
+ @db[:a].columns.must_equal [:a, :c]
205
+
206
+ @m.apply(@db, @dir, 4)
207
+ [:schema_info, :b].each{|n| @db.table_exists?(n).must_equal true}
208
+ [:schema_migrations, :a].each{|n| @db.table_exists?(n).must_equal false}
209
+ @db[:b].columns.must_equal [:a, :c]
210
+
211
+ @m.apply(@db, @dir, 5)
212
+ [:schema_info, :b].each{|n| @db.table_exists?(n).must_equal true}
213
+ [:schema_migrations, :a].each{|n| @db.table_exists?(n).must_equal false}
214
+ @db[:b].columns.must_equal [:a, :c, :e]
215
+
216
+ @m.apply(@db, @dir, 4)
217
+ [:schema_info, :b].each{|n| @db.table_exists?(n).must_equal true}
218
+ [:schema_migrations, :a].each{|n| @db.table_exists?(n).must_equal false}
219
+ @db[:b].columns.must_equal [:a, :c]
220
+
221
+ @m.apply(@db, @dir, 3)
222
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
223
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
224
+ @db[:a].columns.must_equal [:a, :c]
225
+
226
+ @m.apply(@db, @dir, 2)
227
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
228
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
229
+ @db[:a].columns.must_equal [:a, :b]
230
+
231
+ @m.apply(@db, @dir, 1)
232
+ [:schema_info, :a].each{|n| @db.table_exists?(n).must_equal true}
233
+ [:schema_migrations, :b].each{|n| @db.table_exists?(n).must_equal false}
234
+ @db[:a].columns.must_equal [:a]
235
+
236
+ @m.apply(@db, @dir, 0)
237
+ [:schema_info].each{|n| @db.table_exists?(n).must_equal true}
238
+ [:schema_migrations, :a, :b].each{|n| @db.table_exists?(n).must_equal false}
239
+ end
240
+ end
@@ -0,0 +1,91 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
+
3
+ describe "date_arithmetic extension" do
4
+ asd = begin
5
+ require 'active_support/duration'
6
+ require 'active_support/inflector'
7
+ require 'active_support/core_ext/string/inflections'
8
+ true
9
+ rescue LoadError
10
+ false
11
+ end
12
+
13
+ before(:all) do
14
+ @db = DB
15
+ @db.extension(:date_arithmetic)
16
+ if @db.database_type == :sqlite
17
+ @db.use_timestamp_timezones = false
18
+ end
19
+ @date = Date.civil(2010, 7, 12)
20
+ @dt = Time.local(2010, 7, 12)
21
+ if asd
22
+ @d0 = ActiveSupport::Duration.new(0, [[:days, 0]])
23
+ @d1 = ActiveSupport::Duration.new(1, [[:days, 1]])
24
+ @d2 = ActiveSupport::Duration.new(1, [[:years, 1], [:months, 1], [:days, 1], [:minutes, 61], [:seconds, 1]])
25
+ end
26
+ @h0 = {:days=>0}
27
+ @h1 = {:days=>1, :years=>nil, :hours=>0}
28
+ @h2 = {:years=>1, :months=>1, :days=>1, :hours=>1, :minutes=>1, :seconds=>1}
29
+ @a1 = Time.local(2010, 7, 13)
30
+ @a2 = Time.local(2011, 8, 13, 1, 1, 1)
31
+ @s1 = Time.local(2010, 7, 11)
32
+ @s2 = Time.local(2009, 6, 10, 22, 58, 59)
33
+ @check = lambda do |meth, in_date, in_interval, should|
34
+ output = @db.get(Sequel.send(meth, in_date, in_interval))
35
+ output = Time.parse(output.to_s) unless output.is_a?(Time) || output.is_a?(DateTime)
36
+ output.year.must_equal should.year
37
+ output.month.must_equal should.month
38
+ output.day.must_equal should.day
39
+ output.hour.must_equal should.hour
40
+ output.min.must_equal should.min
41
+ output.sec.must_equal should.sec
42
+ end
43
+ end
44
+ after(:all) do
45
+ if @db.database_type == :sqlite
46
+ @db.use_timestamp_timezones = true
47
+ end
48
+ end
49
+
50
+ if asd
51
+ it "be able to use Sequel.date_add to add ActiveSupport::Duration objects to dates and datetimes" do
52
+ @check.call(:date_add, @date, @d0, @dt)
53
+ @check.call(:date_add, @date, @d1, @a1)
54
+ @check.call(:date_add, @date, @d2, @a2)
55
+
56
+ @check.call(:date_add, @dt, @d0, @dt)
57
+ @check.call(:date_add, @dt, @d1, @a1)
58
+ @check.call(:date_add, @dt, @d2, @a2)
59
+ end
60
+
61
+ it "be able to use Sequel.date_sub to subtract ActiveSupport::Duration objects from dates and datetimes" do
62
+ @check.call(:date_sub, @date, @d0, @dt)
63
+ @check.call(:date_sub, @date, @d1, @s1)
64
+ @check.call(:date_sub, @date, @d2, @s2)
65
+
66
+ @check.call(:date_sub, @dt, @d0, @dt)
67
+ @check.call(:date_sub, @dt, @d1, @s1)
68
+ @check.call(:date_sub, @dt, @d2, @s2)
69
+ end
70
+ end
71
+
72
+ it "be able to use Sequel.date_add to add interval hashes to dates and datetimes" do
73
+ @check.call(:date_add, @date, @h0, @dt)
74
+ @check.call(:date_add, @date, @h1, @a1)
75
+ @check.call(:date_add, @date, @h2, @a2)
76
+
77
+ @check.call(:date_add, @dt, @h0, @dt)
78
+ @check.call(:date_add, @dt, @h1, @a1)
79
+ @check.call(:date_add, @dt, @h2, @a2)
80
+ end
81
+
82
+ it "be able to use Sequel.date_sub to subtract interval hashes from dates and datetimes" do
83
+ @check.call(:date_sub, @date, @h0, @dt)
84
+ @check.call(:date_sub, @date, @h1, @s1)
85
+ @check.call(:date_sub, @date, @h2, @s2)
86
+
87
+ @check.call(:date_sub, @dt, @h0, @dt)
88
+ @check.call(:date_sub, @dt, @h1, @s1)
89
+ @check.call(:date_sub, @dt, @h2, @s2)
90
+ end
91
+ end
@@ -0,0 +1,327 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper.rb')
2
+
3
+ describe "Prepared Statements and Bound Arguments" do
4
+ before do
5
+ @db = DB
6
+ @db.create_table!(:items) do
7
+ primary_key :id
8
+ integer :numb
9
+ end
10
+ @c = Class.new(Sequel::Model(:items))
11
+ @ds = @db[:items]
12
+ @ds.insert(:id=>1, :numb=>10)
13
+ @pr = @ds.requires_placeholder_type_specifiers? ? proc{|i| :"#{i}__integer"} : proc{|i| i}
14
+ end
15
+ after do
16
+ @db.drop_table?(:items)
17
+ end
18
+
19
+ it "should support bound variables when selecting" do
20
+ @ds.filter(:numb=>:$n).call(:each, :n=>10){|h| h.must_equal(:id=>1, :numb=>10)}
21
+ @ds.filter(:numb=>:$n).call(:select, :n=>10).must_equal [{:id=>1, :numb=>10}]
22
+ @ds.filter(:numb=>:$n).call(:all, :n=>10).must_equal [{:id=>1, :numb=>10}]
23
+ @ds.filter(:numb=>:$n).call(:first, :n=>10).must_equal(:id=>1, :numb=>10)
24
+ @ds.filter(:numb=>:$n).call([:map, :numb], :n=>10).must_equal [10]
25
+ @ds.filter(:numb=>:$n).call([:to_hash, :id, :numb], :n=>10).must_equal(1=>10)
26
+ @ds.filter(:numb=>:$n).call([:to_hash_groups, :id, :numb], :n=>10).must_equal(1=>[10])
27
+ end
28
+
29
+ it "should support blocks for each, select, all, and map when using bound variables" do
30
+ a = []
31
+ @ds.filter(:numb=>:$n).call(:each, :n=>10){|r| r[:numb] *= 2; a << r}; a.must_equal [{:id=>1, :numb=>20}]
32
+ @ds.filter(:numb=>:$n).call(:select, :n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
33
+ @ds.filter(:numb=>:$n).call(:all, :n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
34
+ @ds.filter(:numb=>:$n).call([:map], :n=>10){|r| r[:numb] * 2}.must_equal [20]
35
+ end
36
+
37
+ it "should support binding variables before the call with #bind" do
38
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:select).must_equal [{:id=>1, :numb=>10}]
39
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:all).must_equal [{:id=>1, :numb=>10}]
40
+ @ds.filter(:numb=>:$n).bind(:n=>10).call(:first).must_equal(:id=>1, :numb=>10)
41
+
42
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:select).must_equal [{:id=>1, :numb=>10}]
43
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:all).must_equal [{:id=>1, :numb=>10}]
44
+ @ds.bind(:n=>10).filter(:numb=>:$n).call(:first).must_equal(:id=>1, :numb=>10)
45
+ end
46
+
47
+ it "should allow overriding variables specified with #bind" do
48
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:select, :n=>10).must_equal [{:id=>1, :numb=>10}]
49
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:all, :n=>10).must_equal [{:id=>1, :numb=>10}]
50
+ @ds.filter(:numb=>:$n).bind(:n=>1).call(:first, :n=>10).must_equal(:id=>1, :numb=>10)
51
+
52
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:select).must_equal [{:id=>1, :numb=>10}]
53
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:all).must_equal [{:id=>1, :numb=>10}]
54
+ @ds.filter(:numb=>:$n).bind(:n=>1).bind(:n=>10).call(:first).must_equal(:id=>1, :numb=>10)
55
+ end
56
+
57
+ it "should support placeholder literal strings with call" do
58
+ @ds.filter("numb = ?", :$n).call(:select, :n=>10).must_equal [{:id=>1, :numb=>10}]
59
+ end
60
+
61
+ it "should support named placeholder literal strings and handle multiple named placeholders correctly with call" do
62
+ @ds.filter("numb = :n", :n=>:$n).call(:select, :n=>10).must_equal [{:id=>1, :numb=>10}]
63
+ @ds.insert(:id=>2, :numb=>20)
64
+ @ds.insert(:id=>3, :numb=>30)
65
+ @ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).must_equal [{:id=>2, :numb=>20}]
66
+ end
67
+
68
+ it "should support datasets with static sql and placeholders with call" do
69
+ @db["SELECT * FROM items WHERE numb = ?", :$n].call(:select, :n=>10).must_equal [{:id=>1, :numb=>10}]
70
+ end
71
+
72
+ it "should support subselects with call" do
73
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
74
+ end
75
+
76
+ it "should support subselects with exists with call" do
77
+ @ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
78
+ end
79
+
80
+ it "should support subselects with literal strings with call" do
81
+ @ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).call(:select, :n=>10, :i=>1).must_equal [{:id=>1, :numb=>10}]
82
+ end
83
+
84
+ it "should support subselects with static sql and placeholders with call" do
85
+ @ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).call(:select, :n=>10, :i=>1).must_equal [{:id=>1, :numb=>10}]
86
+ end
87
+
88
+ it "should support subselects of subselects with call" do
89
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).call(:select, :n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
90
+ end
91
+
92
+ it "should support using a bound variable for a limit and offset" do
93
+ @ds.insert(:id=>2, :numb=>20)
94
+ ds = @ds.limit(:$n, :$n2).order(:id)
95
+ ds.call(:select, :n=>1, :n2=>0).must_equal [{:id=>1, :numb=>10}]
96
+ ds.call(:select, :n=>1, :n2=>1).must_equal [{:id=>2, :numb=>20}]
97
+ ds.call(:select, :n=>1, :n2=>2).must_equal []
98
+ ds.call(:select, :n=>2, :n2=>0).must_equal [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
99
+ ds.call(:select, :n=>2, :n2=>1).must_equal [{:id=>2, :numb=>20}]
100
+ end
101
+
102
+ it "should support bound variables with insert" do
103
+ @ds.call(:insert, {:n=>20}, :numb=>:$n)
104
+ @ds.count.must_equal 2
105
+ @ds.order(:id).map(:numb).must_equal [10, 20]
106
+ end
107
+
108
+ it "should have insert return primary key value when using bound arguments" do
109
+ assert_nil(@ds.call(:insert, {:n=>20}, :numb=>:$n, :id=>2))
110
+ @ds.filter(:id=>2).first[:numb].must_equal 20
111
+ end
112
+
113
+ it "should support bound variables with delete" do
114
+ assert_nil(@ds.filter(:numb=>:$n).call(:delete, :n=>10))
115
+ @ds.count.must_equal 0
116
+ end
117
+
118
+ it "should support prepared statements when selecting" do
119
+ @ds.filter(:numb=>:$n).prepare(:each, :select_n)
120
+ @db.call(:select_n, :n=>10){|h| h.must_equal(:id=>1, :numb=>10)}
121
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
122
+ @db.call(:select_n, :n=>10).must_equal [{:id=>1, :numb=>10}]
123
+ @ds.filter(:numb=>:$n).prepare(:all, :select_n)
124
+ @db.call(:select_n, :n=>10).must_equal [{:id=>1, :numb=>10}]
125
+ @ds.filter(:numb=>:$n).prepare(:first, :select_n)
126
+ @db.call(:select_n, :n=>10).must_equal(:id=>1, :numb=>10)
127
+ @ds.filter(:numb=>:$n).prepare([:map, :numb], :select_n)
128
+ @db.call(:select_n, :n=>10).must_equal [10]
129
+ @ds.filter(:numb=>:$n).prepare([:to_hash, :id, :numb], :select_n)
130
+ @db.call(:select_n, :n=>10).must_equal(1=>10)
131
+ end
132
+
133
+ it "should support blocks for each, select, all, and map when using prepared statements" do
134
+ a = []
135
+ @ds.filter(:numb=>:$n).prepare(:each, :select_n).call(:n=>10){|r| r[:numb] *= 2; a << r}; a.must_equal [{:id=>1, :numb=>20}]
136
+ a = []
137
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2; a << r}; a.must_equal [{:id=>1, :numb=>20}]
138
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n).call(:n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
139
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
140
+ @ds.filter(:numb=>:$n).prepare(:all, :select_n).call(:n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
141
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.must_equal [{:id=>1, :numb=>20}]
142
+ @ds.filter(:numb=>:$n).prepare([:map], :select_n).call(:n=>10){|r| r[:numb] *= 2}.must_equal [20]
143
+ @db.call(:select_n, :n=>10){|r| r[:numb] *= 2}.must_equal [20]
144
+ end
145
+
146
+ it "should support prepared statements being called multiple times with different arguments" do
147
+ @ds.filter(:numb=>:$n).prepare(:select, :select_n)
148
+ @db.call(:select_n, :n=>10).must_equal [{:id=>1, :numb=>10}]
149
+ @db.call(:select_n, :n=>0).must_equal []
150
+ @db.call(:select_n, :n=>10).must_equal [{:id=>1, :numb=>10}]
151
+ end
152
+
153
+ it "should support placeholder literal strings with prepare" do
154
+ @ds.filter("numb = ?", :$n).prepare(:select, :seq_select).call(:n=>10).must_equal [{:id=>1, :numb=>10}]
155
+ end
156
+
157
+ it "should support named placeholder literal strings and handle multiple named placeholders correctly with prepare" do
158
+ @ds.filter("numb = :n", :n=>:$n).prepare(:select, :seq_select).call(:n=>10).must_equal [{:id=>1, :numb=>10}]
159
+ @ds.insert(:id=>2, :numb=>20)
160
+ @ds.insert(:id=>3, :numb=>30)
161
+ @ds.filter("numb > :n1 AND numb < :n2 AND numb = :n3", :n3=>:$n3, :n2=>:$n2, :n1=>:$n1).call(:select, :n3=>20, :n2=>30, :n1=>10).must_equal [{:id=>2, :numb=>20}]
162
+ end
163
+
164
+ it "should support datasets with static sql and placeholders with prepare" do
165
+ @db["SELECT * FROM items WHERE numb = ?", :$n].prepare(:select, :seq_select).call(:n=>10).must_equal [{:id=>1, :numb=>10}]
166
+ end
167
+
168
+ it "should support subselects with prepare" do
169
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n)).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
170
+ end
171
+
172
+ it "should support subselects with exists with prepare" do
173
+ @ds.filter(:id=>:$i).filter(@ds.select(:numb).filter(:numb=>:$n).exists).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
174
+ end
175
+
176
+ it "should support subselects with literal strings with prepare" do
177
+ @ds.filter(:id=>:$i, :numb=>@ds.select(:numb).filter("numb = ?", :$n)).prepare(:select, :seq_select).call(:n=>10, :i=>1).must_equal [{:id=>1, :numb=>10}]
178
+ end
179
+
180
+ it "should support subselects with static sql and placeholders with prepare" do
181
+ @ds.filter(:id=>:$i, :numb=>@db["SELECT numb FROM items WHERE numb = ?", :$n]).prepare(:select, :seq_select).call(:n=>10, :i=>1).must_equal [{:id=>1, :numb=>10}]
182
+ end
183
+
184
+ it "should support subselects of subselects with prepare" do
185
+ @ds.filter(:id=>:$i).filter(:numb=>@ds.select(:numb).filter(:numb=>@ds.select(:numb).filter(:numb=>:$n))).filter(:id=>:$j).prepare(:select, :seq_select).call(:n=>10, :i=>1, :j=>1).must_equal [{:id=>1, :numb=>10}]
186
+ end
187
+
188
+ it "should support using a prepared_statement for a limit and offset" do
189
+ @ds.insert(:id=>2, :numb=>20)
190
+ ps = @ds.limit(:$n, :$n2).order(:id).prepare(:select, :seq_select)
191
+ ps.call(:n=>1, :n2=>0).must_equal [{:id=>1, :numb=>10}]
192
+ ps.call(:n=>1, :n2=>1).must_equal [{:id=>2, :numb=>20}]
193
+ ps.call(:n=>1, :n2=>2).must_equal []
194
+ ps.call(:n=>2, :n2=>0).must_equal [{:id=>1, :numb=>10}, {:id=>2, :numb=>20}]
195
+ ps.call(:n=>2, :n2=>1).must_equal [{:id=>2, :numb=>20}]
196
+ end
197
+
198
+ it "should support prepared statements with insert" do
199
+ @ds.prepare(:insert, :insert_n, :numb=>:$n)
200
+ @db.call(:insert_n, :n=>20)
201
+ @ds.count.must_equal 2
202
+ @ds.order(:id).map(:numb).must_equal [10, 20]
203
+ end
204
+
205
+ it "should have insert return primary key value when using prepared statements" do
206
+ @ds.prepare(:insert, :insert_n, :numb=>:$n, :id=>2)
207
+ assert_nil(@db.call(:insert_n, :id=>2, :n=>20))
208
+ @ds.filter(:id=>2).first[:numb].must_equal 20
209
+ end
210
+
211
+ it "should support prepared statements with delete" do
212
+ @ds.filter(:numb=>:$n).prepare(:delete, :delete_n)
213
+ assert_nil(@db.call(:delete_n, :n=>10))
214
+ @ds.count.must_equal 0
215
+ end
216
+
217
+ it "model datasets should return model instances when using select, all, and first with bound variables" do
218
+ @c.filter(:numb=>:$n).call(:select, :n=>10).must_equal [@c.load(:id=>1, :numb=>10)]
219
+ @c.filter(:numb=>:$n).call(:all, :n=>10).must_equal [@c.load(:id=>1, :numb=>10)]
220
+ @c.filter(:numb=>:$n).call(:first, :n=>10).must_equal @c.load(:id=>1, :numb=>10)
221
+ end
222
+
223
+ it "model datasets should return model instances when using select, all, and first with prepared statements" do
224
+ @c.filter(:numb=>:$n).prepare(:select, :select_n1)
225
+ @db.call(:select_n1, :n=>10).must_equal [@c.load(:id=>1, :numb=>10)]
226
+ @c.filter(:numb=>:$n).prepare(:all, :select_n1)
227
+ @db.call(:select_n1, :n=>10).must_equal [@c.load(:id=>1, :numb=>10)]
228
+ @c.filter(:numb=>:$n).prepare(:first, :select_n1)
229
+ @db.call(:select_n1, :n=>10).must_equal @c.load(:id=>1, :numb=>10)
230
+ end
231
+ end
232
+
233
+ describe "Bound Argument Types" do
234
+ before do
235
+ @db = DB
236
+ @db.create_table!(:items) do
237
+ primary_key :id
238
+ DateTime :dt
239
+ String :s
240
+ Time :t
241
+ Float :f
242
+ TrueClass :b
243
+ end
244
+ @ds = @db[:items]
245
+ @vs = {:id=>1, :dt=>DateTime.civil(2010, 10, 12, 13, 14, 15), :f=>1.0, :s=>'str', :t=>Time.at(20101010), :b=>true}
246
+ @ds.insert(@vs)
247
+ end
248
+ after do
249
+ @db.drop_table?(:items)
250
+ end
251
+
252
+ it "should handle float type" do
253
+ @ds.filter(:f=>:$x).prepare(:first, :ps_float).call(:x=>@vs[:f])[:f].must_equal @vs[:f]
254
+ end
255
+
256
+ it "should handle string type" do
257
+ @ds.filter(:s=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:s])[:s].must_equal @vs[:s]
258
+ end
259
+
260
+ it "should handle boolean type" do
261
+ @ds.filter(:b=>:$x).prepare(:first, :ps_string).call(:x=>@vs[:b])[:b].must_equal @vs[:b]
262
+ end
263
+ end
264
+
265
+ describe "Dataset#unbind" do
266
+ before do
267
+ @ds = ds = DB[:items]
268
+ @ct = proc do |t, v|
269
+ DB.create_table!(:items) do
270
+ column :c, t
271
+ end
272
+ ds.insert(:c=>v)
273
+ end
274
+ @u = proc{|ds1| ds2, bv = ds1.unbind; ds2.call(:first, bv)}
275
+ end
276
+ after do
277
+ DB.drop_table?(:items)
278
+ end
279
+
280
+ it "should unbind values assigned to equality and inequality statements" do
281
+ @ct[Integer, 10]
282
+ @u[@ds.filter(:c=>10)].must_equal(:c=>10)
283
+ assert_nil(@u[@ds.exclude(:c=>10)])
284
+ assert_nil(@u[@ds.filter{c < 10}])
285
+ @u[@ds.filter{c <= 10}].must_equal(:c=>10)
286
+ assert_nil(@u[@ds.filter{c > 10}])
287
+ @u[@ds.filter{c >= 10}].must_equal(:c=>10)
288
+ end
289
+
290
+ it "should handle numerics and strings" do
291
+ @ct[Integer, 10]
292
+ @u[@ds.filter(:c=>10)].must_equal(:c=>10)
293
+ @ct[Float, 0.0]
294
+ @u[@ds.filter{c < 1}].must_equal(:c=>0.0)
295
+ @ct[String, 'foo']
296
+ @u[@ds.filter(:c=>'foo')].must_equal(:c=>'foo')
297
+
298
+ DB.create_table!(:items) do
299
+ BigDecimal :c, :size=>[15,2]
300
+ end
301
+ @ds.insert(:c=>BigDecimal.new('1.1'))
302
+ @u[@ds.filter{c > 0}].must_equal(:c=>BigDecimal.new('1.1'))
303
+ end
304
+
305
+ it "should handle QualifiedIdentifiers" do
306
+ @ct[Integer, 10]
307
+ @u[@ds.filter{items__c > 1}].must_equal(:c=>10)
308
+ end
309
+
310
+ it "should handle deep nesting" do
311
+ DB.create_table!(:items) do
312
+ Integer :a
313
+ Integer :b
314
+ Integer :c
315
+ Integer :d
316
+ end
317
+ @ds.insert(:a=>2, :b=>0, :c=>3, :d=>5)
318
+ @u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and(Sequel.case({~Sequel.expr(:d=>4)=>1}, 0) => 1)].must_equal(:a=>2, :b=>0, :c=>3, :d=>5)
319
+ assert_nil(@u[@ds.filter{a > 1}.and{b < 2}.or(:c=>3).and(Sequel.case({~Sequel.expr(:d=>5)=>1}, 0) => 1)])
320
+ end
321
+
322
+ it "should handle case where the same variable has the same value in multiple places " do
323
+ @ct[Integer, 1]
324
+ @u[@ds.filter{c > 1}.or{c < 1}.invert].must_equal(:c=>1)
325
+ assert_nil(@u[@ds.filter{c > 1}.or{c < 1}])
326
+ end
327
+ end