sequel 3.21.0 → 3.39.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 (352) hide show
  1. data/CHANGELOG +1061 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +103 -63
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +67 -51
  7. data/doc/advanced_associations.rdoc +189 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/cheat_sheet.rdoc +21 -21
  10. data/doc/core_extensions.rdoc +374 -0
  11. data/doc/dataset_basics.rdoc +10 -10
  12. data/doc/dataset_filtering.rdoc +54 -42
  13. data/doc/mass_assignment.rdoc +56 -0
  14. data/doc/migration.rdoc +89 -557
  15. data/doc/model_hooks.rdoc +80 -29
  16. data/doc/object_model.rdoc +547 -0
  17. data/doc/opening_databases.rdoc +114 -53
  18. data/doc/prepared_statements.rdoc +41 -15
  19. data/doc/querying.rdoc +137 -56
  20. data/doc/reflection.rdoc +36 -10
  21. data/doc/release_notes/3.22.0.txt +39 -0
  22. data/doc/release_notes/3.23.0.txt +172 -0
  23. data/doc/release_notes/3.24.0.txt +420 -0
  24. data/doc/release_notes/3.25.0.txt +88 -0
  25. data/doc/release_notes/3.26.0.txt +88 -0
  26. data/doc/release_notes/3.27.0.txt +82 -0
  27. data/doc/release_notes/3.28.0.txt +304 -0
  28. data/doc/release_notes/3.29.0.txt +459 -0
  29. data/doc/release_notes/3.30.0.txt +135 -0
  30. data/doc/release_notes/3.31.0.txt +146 -0
  31. data/doc/release_notes/3.32.0.txt +202 -0
  32. data/doc/release_notes/3.33.0.txt +157 -0
  33. data/doc/release_notes/3.34.0.txt +671 -0
  34. data/doc/release_notes/3.35.0.txt +144 -0
  35. data/doc/release_notes/3.36.0.txt +245 -0
  36. data/doc/release_notes/3.37.0.txt +338 -0
  37. data/doc/release_notes/3.38.0.txt +234 -0
  38. data/doc/release_notes/3.39.0.txt +237 -0
  39. data/doc/schema_modification.rdoc +585 -0
  40. data/doc/sharding.rdoc +99 -8
  41. data/doc/sql.rdoc +154 -112
  42. data/doc/testing.rdoc +169 -0
  43. data/doc/thread_safety.rdoc +17 -0
  44. data/doc/transactions.rdoc +137 -0
  45. data/doc/validations.rdoc +1 -1
  46. data/doc/virtual_rows.rdoc +78 -43
  47. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  48. data/lib/sequel/adapters/ado.rb +40 -18
  49. data/lib/sequel/adapters/amalgalite.rb +17 -9
  50. data/lib/sequel/adapters/db2.rb +175 -86
  51. data/lib/sequel/adapters/dbi.rb +15 -15
  52. data/lib/sequel/adapters/do/mysql.rb +17 -11
  53. data/lib/sequel/adapters/do/postgres.rb +2 -61
  54. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  55. data/lib/sequel/adapters/do.rb +18 -36
  56. data/lib/sequel/adapters/firebird.rb +27 -208
  57. data/lib/sequel/adapters/ibmdb.rb +453 -0
  58. data/lib/sequel/adapters/informix.rb +6 -23
  59. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  60. data/lib/sequel/adapters/jdbc/db2.rb +56 -0
  61. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  62. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  63. data/lib/sequel/adapters/jdbc/h2.rb +73 -31
  64. data/lib/sequel/adapters/jdbc/hsqldb.rb +184 -0
  65. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  66. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  67. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  68. data/lib/sequel/adapters/jdbc/mysql.rb +7 -24
  69. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  70. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  71. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  73. data/lib/sequel/adapters/jdbc/sqlserver.rb +66 -0
  74. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  75. data/lib/sequel/adapters/jdbc.rb +279 -97
  76. data/lib/sequel/adapters/mock.rb +372 -0
  77. data/lib/sequel/adapters/mysql.rb +125 -222
  78. data/lib/sequel/adapters/mysql2.rb +65 -56
  79. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  80. data/lib/sequel/adapters/odbc.rb +28 -9
  81. data/lib/sequel/adapters/openbase.rb +3 -5
  82. data/lib/sequel/adapters/oracle.rb +349 -53
  83. data/lib/sequel/adapters/postgres.rb +368 -138
  84. data/lib/sequel/adapters/shared/access.rb +32 -9
  85. data/lib/sequel/adapters/shared/db2.rb +343 -0
  86. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  87. data/lib/sequel/adapters/shared/informix.rb +53 -0
  88. data/lib/sequel/adapters/shared/mssql.rb +401 -116
  89. data/lib/sequel/adapters/shared/mysql.rb +424 -89
  90. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +155 -0
  91. data/lib/sequel/adapters/shared/oracle.rb +257 -45
  92. data/lib/sequel/adapters/shared/postgres.rb +675 -279
  93. data/lib/sequel/adapters/shared/progress.rb +5 -8
  94. data/lib/sequel/adapters/shared/sqlite.rb +285 -96
  95. data/lib/sequel/adapters/sqlite.rb +101 -39
  96. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  97. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  98. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  99. data/lib/sequel/adapters/swift.rb +28 -19
  100. data/lib/sequel/adapters/tinytds.rb +174 -22
  101. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  102. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  103. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  104. data/lib/sequel/ast_transformer.rb +194 -0
  105. data/lib/sequel/connection_pool/sharded_single.rb +11 -1
  106. data/lib/sequel/connection_pool/sharded_threaded.rb +33 -2
  107. data/lib/sequel/connection_pool/single.rb +5 -0
  108. data/lib/sequel/connection_pool/threaded.rb +43 -14
  109. data/lib/sequel/connection_pool.rb +10 -2
  110. data/lib/sequel/core.rb +143 -11
  111. data/lib/sequel/database/connecting.rb +38 -28
  112. data/lib/sequel/database/dataset.rb +4 -4
  113. data/lib/sequel/database/dataset_defaults.rb +63 -2
  114. data/lib/sequel/database/logging.rb +7 -2
  115. data/lib/sequel/database/misc.rb +190 -46
  116. data/lib/sequel/database/query.rb +272 -110
  117. data/lib/sequel/database/schema_generator.rb +103 -36
  118. data/lib/sequel/database/schema_methods.rb +300 -67
  119. data/lib/sequel/dataset/actions.rb +344 -90
  120. data/lib/sequel/dataset/features.rb +101 -8
  121. data/lib/sequel/dataset/graph.rb +42 -15
  122. data/lib/sequel/dataset/misc.rb +52 -25
  123. data/lib/sequel/dataset/mutation.rb +12 -7
  124. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  125. data/lib/sequel/dataset/query.rb +305 -54
  126. data/lib/sequel/dataset/sql.rb +720 -292
  127. data/lib/sequel/dataset.rb +8 -0
  128. data/lib/sequel/exceptions.rb +4 -0
  129. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  130. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  131. data/lib/sequel/extensions/blank.rb +4 -0
  132. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  133. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  134. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  135. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  136. data/lib/sequel/extensions/inflector.rb +4 -0
  137. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  138. data/lib/sequel/extensions/migration.rb +100 -11
  139. data/lib/sequel/extensions/named_timezones.rb +9 -0
  140. data/lib/sequel/extensions/null_dataset.rb +94 -0
  141. data/lib/sequel/extensions/pagination.rb +4 -0
  142. data/lib/sequel/extensions/pg_array.rb +537 -0
  143. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  144. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  145. data/lib/sequel/extensions/pg_hstore.rb +313 -0
  146. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  147. data/lib/sequel/extensions/pg_inet.rb +113 -0
  148. data/lib/sequel/extensions/pg_interval.rb +191 -0
  149. data/lib/sequel/extensions/pg_json.rb +208 -0
  150. data/lib/sequel/extensions/pg_range.rb +512 -0
  151. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  152. data/lib/sequel/extensions/pg_row.rb +572 -0
  153. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  154. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  155. data/lib/sequel/extensions/pretty_table.rb +17 -72
  156. data/lib/sequel/extensions/query.rb +8 -4
  157. data/lib/sequel/extensions/query_literals.rb +79 -0
  158. data/lib/sequel/extensions/schema_caching.rb +76 -0
  159. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  160. data/lib/sequel/extensions/select_remove.rb +39 -0
  161. data/lib/sequel/extensions/server_block.rb +140 -0
  162. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  163. data/lib/sequel/extensions/sql_expr.rb +8 -110
  164. data/lib/sequel/extensions/string_date_time.rb +4 -0
  165. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  166. data/lib/sequel/extensions/to_dot.rb +99 -83
  167. data/lib/sequel/model/associations.rb +1263 -409
  168. data/lib/sequel/model/base.rb +624 -171
  169. data/lib/sequel/model/errors.rb +1 -1
  170. data/lib/sequel/model/exceptions.rb +24 -2
  171. data/lib/sequel/model/inflections.rb +1 -1
  172. data/lib/sequel/model.rb +30 -11
  173. data/lib/sequel/no_core_ext.rb +2 -0
  174. data/lib/sequel/plugins/active_model.rb +13 -1
  175. data/lib/sequel/plugins/association_pks.rb +22 -4
  176. data/lib/sequel/plugins/caching.rb +25 -18
  177. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  178. data/lib/sequel/plugins/composition.rb +44 -12
  179. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  180. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  181. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  182. data/lib/sequel/plugins/dirty.rb +214 -0
  183. data/lib/sequel/plugins/eager_each.rb +59 -0
  184. data/lib/sequel/plugins/force_encoding.rb +6 -6
  185. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  186. data/lib/sequel/plugins/identity_map.rb +134 -15
  187. data/lib/sequel/plugins/instance_filters.rb +10 -0
  188. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  189. data/lib/sequel/plugins/json_serializer.rb +58 -6
  190. data/lib/sequel/plugins/list.rb +13 -2
  191. data/lib/sequel/plugins/many_through_many.rb +103 -51
  192. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  193. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  194. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  195. data/lib/sequel/plugins/pg_row.rb +121 -0
  196. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  197. data/lib/sequel/plugins/prepared_statements.rb +167 -0
  198. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  199. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  200. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  201. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  202. data/lib/sequel/plugins/schema.rb +8 -3
  203. data/lib/sequel/plugins/serialization.rb +98 -49
  204. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  205. data/lib/sequel/plugins/sharding.rb +21 -54
  206. data/lib/sequel/plugins/single_table_inheritance.rb +5 -3
  207. data/lib/sequel/plugins/static_cache.rb +99 -0
  208. data/lib/sequel/plugins/subclasses.rb +29 -3
  209. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  210. data/lib/sequel/plugins/timestamps.rb +1 -1
  211. data/lib/sequel/plugins/tree.rb +3 -3
  212. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  213. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  214. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  215. data/lib/sequel/plugins/validation_helpers.rb +55 -4
  216. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  217. data/lib/sequel/sql.rb +649 -122
  218. data/lib/sequel/timezones.rb +67 -40
  219. data/lib/sequel/version.rb +1 -1
  220. data/spec/adapters/db2_spec.rb +146 -0
  221. data/spec/adapters/firebird_spec.rb +1 -1
  222. data/spec/adapters/mssql_spec.rb +194 -66
  223. data/spec/adapters/mysql_spec.rb +475 -306
  224. data/spec/adapters/oracle_spec.rb +92 -117
  225. data/spec/adapters/postgres_spec.rb +1982 -325
  226. data/spec/adapters/spec_helper.rb +9 -6
  227. data/spec/adapters/sqlite_spec.rb +203 -75
  228. data/spec/core/connection_pool_spec.rb +218 -93
  229. data/spec/core/database_spec.rb +956 -522
  230. data/spec/core/dataset_spec.rb +1631 -1242
  231. data/spec/core/expression_filters_spec.rb +690 -334
  232. data/spec/core/mock_adapter_spec.rb +453 -0
  233. data/spec/core/object_graph_spec.rb +88 -129
  234. data/spec/core/schema_generator_spec.rb +4 -4
  235. data/spec/core/schema_spec.rb +556 -53
  236. data/spec/core/spec_helper.rb +7 -48
  237. data/spec/core_extensions_spec.rb +626 -0
  238. data/spec/extensions/active_model_spec.rb +13 -0
  239. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  240. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  241. data/spec/extensions/association_dependencies_spec.rb +15 -25
  242. data/spec/extensions/association_pks_spec.rb +66 -32
  243. data/spec/extensions/association_proxies_spec.rb +4 -4
  244. data/spec/extensions/boolean_readers_spec.rb +25 -25
  245. data/spec/extensions/caching_spec.rb +47 -51
  246. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  247. data/spec/extensions/columns_introspection_spec.rb +91 -0
  248. data/spec/extensions/composition_spec.rb +18 -13
  249. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  250. data/spec/extensions/constraint_validations_spec.rb +316 -0
  251. data/spec/extensions/dataset_associations_spec.rb +199 -0
  252. data/spec/extensions/defaults_setter_spec.rb +88 -0
  253. data/spec/extensions/dirty_spec.rb +155 -0
  254. data/spec/extensions/eager_each_spec.rb +34 -0
  255. data/spec/extensions/eval_inspect_spec.rb +67 -0
  256. data/spec/extensions/force_encoding_spec.rb +4 -2
  257. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  258. data/spec/extensions/identity_map_spec.rb +142 -24
  259. data/spec/extensions/inflector_spec.rb +0 -4
  260. data/spec/extensions/instance_filters_spec.rb +11 -21
  261. data/spec/extensions/instance_hooks_spec.rb +72 -0
  262. data/spec/extensions/json_serializer_spec.rb +49 -12
  263. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  264. data/spec/extensions/list_spec.rb +49 -40
  265. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  266. data/spec/extensions/many_through_many_spec.rb +368 -254
  267. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  268. data/spec/extensions/migration_spec.rb +140 -35
  269. data/spec/extensions/named_timezones_spec.rb +29 -11
  270. data/spec/extensions/nested_attributes_spec.rb +268 -89
  271. data/spec/extensions/null_dataset_spec.rb +85 -0
  272. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  273. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  274. data/spec/extensions/pg_array_spec.rb +320 -0
  275. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  276. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  277. data/spec/extensions/pg_hstore_spec.rb +194 -0
  278. data/spec/extensions/pg_inet_spec.rb +47 -0
  279. data/spec/extensions/pg_interval_spec.rb +72 -0
  280. data/spec/extensions/pg_json_spec.rb +99 -0
  281. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  282. data/spec/extensions/pg_range_spec.rb +395 -0
  283. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  284. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  285. data/spec/extensions/pg_row_spec.rb +323 -0
  286. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  287. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  288. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  289. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  290. data/spec/extensions/prepared_statements_spec.rb +87 -0
  291. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  292. data/spec/extensions/pretty_table_spec.rb +7 -6
  293. data/spec/extensions/query_literals_spec.rb +167 -0
  294. data/spec/extensions/query_spec.rb +9 -3
  295. data/spec/extensions/rcte_tree_spec.rb +50 -43
  296. data/spec/extensions/schema_caching_spec.rb +41 -0
  297. data/spec/extensions/schema_dumper_spec.rb +434 -49
  298. data/spec/extensions/schema_spec.rb +30 -49
  299. data/spec/extensions/select_remove_spec.rb +38 -0
  300. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  301. data/spec/extensions/serialization_spec.rb +86 -48
  302. data/spec/extensions/server_block_spec.rb +90 -0
  303. data/spec/extensions/sharding_spec.rb +69 -143
  304. data/spec/extensions/single_table_inheritance_spec.rb +23 -29
  305. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  306. data/spec/extensions/spec_helper.rb +34 -67
  307. data/spec/extensions/split_array_nil_spec.rb +24 -0
  308. data/spec/extensions/sql_expr_spec.rb +29 -60
  309. data/spec/extensions/static_cache_spec.rb +145 -0
  310. data/spec/extensions/subclasses_spec.rb +14 -0
  311. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  312. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  313. data/spec/extensions/timestamps_spec.rb +6 -6
  314. data/spec/extensions/to_dot_spec.rb +8 -11
  315. data/spec/extensions/touch_spec.rb +13 -14
  316. data/spec/extensions/tree_spec.rb +11 -26
  317. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  318. data/spec/extensions/update_primary_key_spec.rb +30 -24
  319. data/spec/extensions/validation_class_methods_spec.rb +58 -67
  320. data/spec/extensions/validation_helpers_spec.rb +31 -37
  321. data/spec/extensions/xml_serializer_spec.rb +29 -4
  322. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  323. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  324. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  325. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  326. data/spec/integration/associations_test.rb +659 -21
  327. data/spec/integration/database_test.rb +11 -5
  328. data/spec/integration/dataset_test.rb +717 -129
  329. data/spec/integration/eager_loader_test.rb +38 -54
  330. data/spec/integration/migrator_test.rb +2 -3
  331. data/spec/integration/model_test.rb +81 -2
  332. data/spec/integration/plugin_test.rb +604 -147
  333. data/spec/integration/prepared_statement_test.rb +272 -128
  334. data/spec/integration/schema_test.rb +367 -57
  335. data/spec/integration/spec_helper.rb +42 -32
  336. data/spec/integration/timezone_test.rb +38 -12
  337. data/spec/integration/transaction_test.rb +183 -8
  338. data/spec/integration/type_test.rb +31 -8
  339. data/spec/model/association_reflection_spec.rb +207 -8
  340. data/spec/model/associations_spec.rb +1206 -693
  341. data/spec/model/base_spec.rb +334 -100
  342. data/spec/model/dataset_methods_spec.rb +45 -27
  343. data/spec/model/eager_loading_spec.rb +828 -692
  344. data/spec/model/hooks_spec.rb +355 -67
  345. data/spec/model/model_spec.rb +251 -179
  346. data/spec/model/plugins_spec.rb +24 -13
  347. data/spec/model/record_spec.rb +506 -232
  348. data/spec/model/spec_helper.rb +16 -77
  349. data/spec/model/validations_spec.rb +38 -2
  350. data/spec/rcov.opts +2 -0
  351. metadata +209 -80
  352. data/spec/core/core_sql_spec.rb +0 -451
@@ -0,0 +1,626 @@
1
+ require 'rubygems'
2
+
3
+ unless Object.const_defined?('Sequel') && Sequel.const_defined?('Model')
4
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "../../lib/"))
5
+ require 'sequel/no_core_ext'
6
+ end
7
+
8
+ Sequel.quote_identifiers = false
9
+ Sequel.identifier_input_method = nil
10
+ Sequel.identifier_output_method = nil
11
+
12
+ Regexp.send(:include, Sequel::SQL::StringMethods)
13
+ String.send(:include, Sequel::SQL::StringMethods)
14
+ Sequel.extension :core_extensions
15
+
16
+ describe "Sequel core extensions" do
17
+ specify "should have Sequel.core_extensions? be true if enabled" do
18
+ Sequel.core_extensions?.should be_true
19
+ end
20
+ end
21
+
22
+ describe "Core extensions" do
23
+ before do
24
+ db = Sequel::Database.new
25
+ @d = db[:items]
26
+ def @d.supports_regexp?; true end
27
+ def @d.l(*args, &block)
28
+ literal(filter_expr(*args, &block))
29
+ end
30
+ def @d.lit(*args)
31
+ literal(*args)
32
+ end
33
+ end
34
+
35
+ if RUBY_VERSION < '1.9.0'
36
+ it "should not allow inequality operations on true, false, or nil" do
37
+ @d.lit(:x > 1).should == "(x > 1)"
38
+ @d.lit(:x < true).should == "(x < 't')"
39
+ @d.lit(:x >= false).should == "(x >= 'f')"
40
+ @d.lit(:x <= nil).should == "(x <= NULL)"
41
+ end
42
+
43
+ it "should not allow inequality operations on boolean complex expressions" do
44
+ @d.lit(:x > (:y > 5)).should == "(x > (y > 5))"
45
+ @d.lit(:x < (:y < 5)).should == "(x < (y < 5))"
46
+ @d.lit(:x >= (:y >= 5)).should == "(x >= (y >= 5))"
47
+ @d.lit(:x <= (:y <= 5)).should == "(x <= (y <= 5))"
48
+ @d.lit(:x > {:y => nil}).should == "(x > (y IS NULL))"
49
+ @d.lit(:x < ~{:y => nil}).should == "(x < (y IS NOT NULL))"
50
+ @d.lit(:x >= {:y => 5}).should == "(x >= (y = 5))"
51
+ @d.lit(:x <= ~{:y => 5}).should == "(x <= (y != 5))"
52
+ @d.lit(:x >= {:y => [1,2,3]}).should == "(x >= (y IN (1, 2, 3)))"
53
+ @d.lit(:x <= ~{:y => [1,2,3]}).should == "(x <= (y NOT IN (1, 2, 3)))"
54
+ end
55
+
56
+ it "should support >, <, >=, and <= via Symbol#>,<,>=,<=" do
57
+ @d.l(:x > 100).should == '(x > 100)'
58
+ @d.l(:x < 100.01).should == '(x < 100.01)'
59
+ @d.l(:x >= 100000000000000000000000000000000000).should == '(x >= 100000000000000000000000000000000000)'
60
+ @d.l(:x <= 100).should == '(x <= 100)'
61
+ end
62
+
63
+ it "should support negation of >, <, >=, and <= via Symbol#~" do
64
+ @d.l(~(:x > 100)).should == '(x <= 100)'
65
+ @d.l(~(:x < 100.01)).should == '(x >= 100.01)'
66
+ @d.l(~(:x >= 100000000000000000000000000000000000)).should == '(x < 100000000000000000000000000000000000)'
67
+ @d.l(~(:x <= 100)).should == '(x > 100)'
68
+ end
69
+
70
+ it "should support double negation via ~" do
71
+ @d.l(~~(:x > 100)).should == '(x > 100)'
72
+ end
73
+ end
74
+ it "should support NOT via Symbol#~" do
75
+ @d.l(~:x).should == 'NOT x'
76
+ @d.l(~:x__y).should == 'NOT x.y'
77
+ end
78
+
79
+ it "should support + - * / via Symbol#+,-,*,/" do
80
+ @d.l(:x + 1 > 100).should == '((x + 1) > 100)'
81
+ @d.l((:x * :y) < 100.01).should == '((x * y) < 100.01)'
82
+ @d.l((:x - :y/2) >= 100000000000000000000000000000000000).should == '((x - (y / 2)) >= 100000000000000000000000000000000000)'
83
+ @d.l((((:x - :y)/(:x + :y))*:z) <= 100).should == '((((x - y) / (x + y)) * z) <= 100)'
84
+ @d.l(~((((:x - :y)/(:x + :y))*:z) <= 100)).should == '((((x - y) / (x + y)) * z) > 100)'
85
+ end
86
+
87
+ it "should support LIKE via Symbol#like" do
88
+ @d.l(:x.like('a')).should == '(x LIKE \'a\')'
89
+ @d.l(:x.like(/a/)).should == '(x ~ \'a\')'
90
+ @d.l(:x.like('a', 'b')).should == '((x LIKE \'a\') OR (x LIKE \'b\'))'
91
+ @d.l(:x.like(/a/, /b/i)).should == '((x ~ \'a\') OR (x ~* \'b\'))'
92
+ @d.l(:x.like('a', /b/)).should == '((x LIKE \'a\') OR (x ~ \'b\'))'
93
+
94
+ @d.l('a'.like(:x)).should == "('a' LIKE x)"
95
+ @d.l('a'.like(:x, 'b')).should == "(('a' LIKE x) OR ('a' LIKE 'b'))"
96
+ @d.l('a'.like(:x, /b/)).should == "(('a' LIKE x) OR ('a' ~ 'b'))"
97
+ @d.l('a'.like(:x, /b/i)).should == "(('a' LIKE x) OR ('a' ~* 'b'))"
98
+
99
+ @d.l(/a/.like(:x)).should == "('a' ~ x)"
100
+ @d.l(/a/.like(:x, 'b')).should == "(('a' ~ x) OR ('a' ~ 'b'))"
101
+ @d.l(/a/.like(:x, /b/)).should == "(('a' ~ x) OR ('a' ~ 'b'))"
102
+ @d.l(/a/.like(:x, /b/i)).should == "(('a' ~ x) OR ('a' ~* 'b'))"
103
+
104
+ @d.l(/a/i.like(:x)).should == "('a' ~* x)"
105
+ @d.l(/a/i.like(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
106
+ @d.l(/a/i.like(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
107
+ @d.l(/a/i.like(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
108
+ end
109
+
110
+ it "should support NOT LIKE via Symbol#like and Symbol#~" do
111
+ @d.l(~:x.like('a')).should == '(x NOT LIKE \'a\')'
112
+ @d.l(~:x.like(/a/)).should == '(x !~ \'a\')'
113
+ @d.l(~:x.like('a', 'b')).should == '((x NOT LIKE \'a\') AND (x NOT LIKE \'b\'))'
114
+ @d.l(~:x.like(/a/, /b/i)).should == '((x !~ \'a\') AND (x !~* \'b\'))'
115
+ @d.l(~:x.like('a', /b/)).should == '((x NOT LIKE \'a\') AND (x !~ \'b\'))'
116
+
117
+ @d.l(~'a'.like(:x)).should == "('a' NOT LIKE x)"
118
+ @d.l(~'a'.like(:x, 'b')).should == "(('a' NOT LIKE x) AND ('a' NOT LIKE 'b'))"
119
+ @d.l(~'a'.like(:x, /b/)).should == "(('a' NOT LIKE x) AND ('a' !~ 'b'))"
120
+ @d.l(~'a'.like(:x, /b/i)).should == "(('a' NOT LIKE x) AND ('a' !~* 'b'))"
121
+
122
+ @d.l(~/a/.like(:x)).should == "('a' !~ x)"
123
+ @d.l(~/a/.like(:x, 'b')).should == "(('a' !~ x) AND ('a' !~ 'b'))"
124
+ @d.l(~/a/.like(:x, /b/)).should == "(('a' !~ x) AND ('a' !~ 'b'))"
125
+ @d.l(~/a/.like(:x, /b/i)).should == "(('a' !~ x) AND ('a' !~* 'b'))"
126
+
127
+ @d.l(~/a/i.like(:x)).should == "('a' !~* x)"
128
+ @d.l(~/a/i.like(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
129
+ @d.l(~/a/i.like(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
130
+ @d.l(~/a/i.like(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
131
+ end
132
+
133
+ it "should support ILIKE via Symbol#ilike" do
134
+ @d.l(:x.ilike('a')).should == '(x ILIKE \'a\')'
135
+ @d.l(:x.ilike(/a/)).should == '(x ~* \'a\')'
136
+ @d.l(:x.ilike('a', 'b')).should == '((x ILIKE \'a\') OR (x ILIKE \'b\'))'
137
+ @d.l(:x.ilike(/a/, /b/i)).should == '((x ~* \'a\') OR (x ~* \'b\'))'
138
+ @d.l(:x.ilike('a', /b/)).should == '((x ILIKE \'a\') OR (x ~* \'b\'))'
139
+
140
+ @d.l('a'.ilike(:x)).should == "('a' ILIKE x)"
141
+ @d.l('a'.ilike(:x, 'b')).should == "(('a' ILIKE x) OR ('a' ILIKE 'b'))"
142
+ @d.l('a'.ilike(:x, /b/)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
143
+ @d.l('a'.ilike(:x, /b/i)).should == "(('a' ILIKE x) OR ('a' ~* 'b'))"
144
+
145
+ @d.l(/a/.ilike(:x)).should == "('a' ~* x)"
146
+ @d.l(/a/.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
147
+ @d.l(/a/.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
148
+ @d.l(/a/.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
149
+
150
+ @d.l(/a/i.ilike(:x)).should == "('a' ~* x)"
151
+ @d.l(/a/i.ilike(:x, 'b')).should == "(('a' ~* x) OR ('a' ~* 'b'))"
152
+ @d.l(/a/i.ilike(:x, /b/)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
153
+ @d.l(/a/i.ilike(:x, /b/i)).should == "(('a' ~* x) OR ('a' ~* 'b'))"
154
+ end
155
+
156
+ it "should support NOT ILIKE via Symbol#ilike and Symbol#~" do
157
+ @d.l(~:x.ilike('a')).should == '(x NOT ILIKE \'a\')'
158
+ @d.l(~:x.ilike(/a/)).should == '(x !~* \'a\')'
159
+ @d.l(~:x.ilike('a', 'b')).should == '((x NOT ILIKE \'a\') AND (x NOT ILIKE \'b\'))'
160
+ @d.l(~:x.ilike(/a/, /b/i)).should == '((x !~* \'a\') AND (x !~* \'b\'))'
161
+ @d.l(~:x.ilike('a', /b/)).should == '((x NOT ILIKE \'a\') AND (x !~* \'b\'))'
162
+
163
+ @d.l(~'a'.ilike(:x)).should == "('a' NOT ILIKE x)"
164
+ @d.l(~'a'.ilike(:x, 'b')).should == "(('a' NOT ILIKE x) AND ('a' NOT ILIKE 'b'))"
165
+ @d.l(~'a'.ilike(:x, /b/)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
166
+ @d.l(~'a'.ilike(:x, /b/i)).should == "(('a' NOT ILIKE x) AND ('a' !~* 'b'))"
167
+
168
+ @d.l(~/a/.ilike(:x)).should == "('a' !~* x)"
169
+ @d.l(~/a/.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
170
+ @d.l(~/a/.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
171
+ @d.l(~/a/.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
172
+
173
+ @d.l(~/a/i.ilike(:x)).should == "('a' !~* x)"
174
+ @d.l(~/a/i.ilike(:x, 'b')).should == "(('a' !~* x) AND ('a' !~* 'b'))"
175
+ @d.l(~/a/i.ilike(:x, /b/)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
176
+ @d.l(~/a/i.ilike(:x, /b/i)).should == "(('a' !~* x) AND ('a' !~* 'b'))"
177
+ end
178
+
179
+ it "should support sql_expr on arrays with all two pairs" do
180
+ @d.l([[:x, 100],[:y, 'a']].sql_expr).should == '((x = 100) AND (y = \'a\'))'
181
+ @d.l([[:x, true], [:y, false]].sql_expr).should == '((x IS TRUE) AND (y IS FALSE))'
182
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_expr).should == '((x IS NULL) AND (y IN (1, 2, 3)))'
183
+ end
184
+
185
+ it "should support sql_negate on arrays with all two pairs" do
186
+ @d.l([[:x, 100],[:y, 'a']].sql_negate).should == '((x != 100) AND (y != \'a\'))'
187
+ @d.l([[:x, true], [:y, false]].sql_negate).should == '((x IS NOT TRUE) AND (y IS NOT FALSE))'
188
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_negate).should == '((x IS NOT NULL) AND (y NOT IN (1, 2, 3)))'
189
+ end
190
+
191
+ it "should support ~ on arrays with all two pairs" do
192
+ @d.l(~[[:x, 100],[:y, 'a']]).should == '((x != 100) OR (y != \'a\'))'
193
+ @d.l(~[[:x, true], [:y, false]]).should == '((x IS NOT TRUE) OR (y IS NOT FALSE))'
194
+ @d.l(~[[:x, nil], [:y, [1,2,3]]]).should == '((x IS NOT NULL) OR (y NOT IN (1, 2, 3)))'
195
+ end
196
+
197
+ it "should support sql_or on arrays with all two pairs" do
198
+ @d.l([[:x, 100],[:y, 'a']].sql_or).should == '((x = 100) OR (y = \'a\'))'
199
+ @d.l([[:x, true], [:y, false]].sql_or).should == '((x IS TRUE) OR (y IS FALSE))'
200
+ @d.l([[:x, nil], [:y, [1,2,3]]].sql_or).should == '((x IS NULL) OR (y IN (1, 2, 3)))'
201
+ end
202
+
203
+ it "should support Array#sql_string_join for concatenation of SQL strings" do
204
+ @d.lit([:x].sql_string_join).should == '(x)'
205
+ @d.lit([:x].sql_string_join(', ')).should == '(x)'
206
+ @d.lit([:x, :y].sql_string_join).should == '(x || y)'
207
+ @d.lit([:x, :y].sql_string_join(', ')).should == "(x || ', ' || y)"
208
+ @d.lit([:x.sql_function(1), :y.sql_subscript(1)].sql_string_join).should == '(x(1) || y[1])'
209
+ @d.lit([:x.sql_function(1), 'y.z'.lit].sql_string_join(', ')).should == "(x(1) || ', ' || y.z)"
210
+ @d.lit([:x, 1, :y].sql_string_join).should == "(x || '1' || y)"
211
+ @d.lit([:x, 1, :y].sql_string_join(', ')).should == "(x || ', ' || '1' || ', ' || y)"
212
+ @d.lit([:x, 1, :y].sql_string_join(:y__z)).should == "(x || y.z || '1' || y.z || y)"
213
+ @d.lit([:x, 1, :y].sql_string_join(1)).should == "(x || '1' || '1' || '1' || y)"
214
+ @d.lit([:x, :y].sql_string_join('y.x || x.y'.lit)).should == "(x || y.x || x.y || y)"
215
+ @d.lit([[:x, :y].sql_string_join, [:a, :b].sql_string_join].sql_string_join).should == "(x || y || a || b)"
216
+ end
217
+
218
+ it "should support sql_expr on hashes" do
219
+ @d.l({:x => 100, :y => 'a'}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x = 100)', '(y = \'a\')']
220
+ @d.l({:x => true, :y => false}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
221
+ @d.l({:x => nil, :y => [1,2,3]}.sql_expr)[1...-1].split(' AND ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
222
+ end
223
+
224
+ it "should support sql_negate on hashes" do
225
+ @d.l({:x => 100, :y => 'a'}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x != 100)', '(y != \'a\')']
226
+ @d.l({:x => true, :y => false}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
227
+ @d.l({:x => nil, :y => [1,2,3]}.sql_negate)[1...-1].split(' AND ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
228
+ end
229
+
230
+ it "should support ~ on hashes" do
231
+ @d.l(~{:x => 100, :y => 'a'})[1...-1].split(' OR ').sort.should == ['(x != 100)', '(y != \'a\')']
232
+ @d.l(~{:x => true, :y => false})[1...-1].split(' OR ').sort.should == ['(x IS NOT TRUE)', '(y IS NOT FALSE)']
233
+ @d.l(~{:x => nil, :y => [1,2,3]})[1...-1].split(' OR ').sort.should == ['(x IS NOT NULL)', '(y NOT IN (1, 2, 3))']
234
+ end
235
+
236
+ it "should support sql_or on hashes" do
237
+ @d.l({:x => 100, :y => 'a'}.sql_or)[1...-1].split(' OR ').sort.should == ['(x = 100)', '(y = \'a\')']
238
+ @d.l({:x => true, :y => false}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS TRUE)', '(y IS FALSE)']
239
+ @d.l({:x => nil, :y => [1,2,3]}.sql_or)[1...-1].split(' OR ').sort.should == ['(x IS NULL)', '(y IN (1, 2, 3))']
240
+ end
241
+
242
+ it "should Hash#& and Hash#|" do
243
+ @d.l({:y => :z} & :x).should == '((y = z) AND x)'
244
+ @d.l({:x => :a} & {:y => :z}).should == '((x = a) AND (y = z))'
245
+ @d.l({:y => :z} | :x).should == '((y = z) OR x)'
246
+ @d.l({:x => :a} | {:y => :z}).should == '((x = a) OR (y = z))'
247
+ end
248
+ end
249
+
250
+ describe "Array#case and Hash#case" do
251
+ before do
252
+ @d = Sequel::Dataset.new(nil)
253
+ end
254
+
255
+ specify "should return SQL CASE expression" do
256
+ @d.literal({:x=>:y}.case(:z)).should == '(CASE WHEN x THEN y ELSE z END)'
257
+ @d.literal({:x=>:y}.case(:z, :exp)).should == '(CASE exp WHEN x THEN y ELSE z END)'
258
+ ['(CASE WHEN x THEN y WHEN a THEN b ELSE z END)',
259
+ '(CASE WHEN a THEN b WHEN x THEN y ELSE z END)'].should(include(@d.literal({:x=>:y, :a=>:b}.case(:z))))
260
+ @d.literal([[:x, :y]].case(:z)).should == '(CASE WHEN x THEN y ELSE z END)'
261
+ @d.literal([[:x, :y], [:a, :b]].case(:z)).should == '(CASE WHEN x THEN y WHEN a THEN b ELSE z END)'
262
+ @d.literal([[:x, :y], [:a, :b]].case(:z, :exp)).should == '(CASE exp WHEN x THEN y WHEN a THEN b ELSE z END)'
263
+ @d.literal([[:x, :y], [:a, :b]].case(:z, :exp__w)).should == '(CASE exp.w WHEN x THEN y WHEN a THEN b ELSE z END)'
264
+ end
265
+
266
+ specify "should return SQL CASE expression with expression even if nil" do
267
+ @d.literal({:x=>:y}.case(:z, nil)).should == '(CASE NULL WHEN x THEN y ELSE z END)'
268
+ end
269
+
270
+ specify "should raise an error if an array that isn't all two pairs is used" do
271
+ proc{[:b].case(:a)}.should raise_error(Sequel::Error)
272
+ proc{[:b, :c].case(:a)}.should raise_error(Sequel::Error)
273
+ proc{[[:b, :c], :d].case(:a)}.should raise_error(Sequel::Error)
274
+ end
275
+
276
+ specify "should raise an error if an empty array/hash is used" do
277
+ proc{[].case(:a)}.should raise_error(Sequel::Error)
278
+ proc{{}.case(:a)}.should raise_error(Sequel::Error)
279
+ end
280
+ end
281
+
282
+ describe "Array#sql_value_list and #sql_array" do
283
+ before do
284
+ @d = Sequel::Dataset.new(nil)
285
+ end
286
+
287
+ specify "should treat the array as an SQL value list instead of conditions when used as a placeholder value" do
288
+ @d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]]).sql.should == 'SELECT * WHERE ((a, b) IN ((x = 1) AND (y = 2)))'
289
+ @d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_value_list).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
290
+ @d.filter("(a, b) IN ?", [[:x, 1], [:y, 2]].sql_array).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
291
+ end
292
+
293
+ specify "should be no difference when used as a hash value" do
294
+ @d.filter([:a, :b]=>[[:x, 1], [:y, 2]]).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
295
+ @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_value_list).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
296
+ @d.filter([:a, :b]=>[[:x, 1], [:y, 2]].sql_array).sql.should == 'SELECT * WHERE ((a, b) IN ((x, 1), (y, 2)))'
297
+ end
298
+ end
299
+
300
+ describe "String#lit" do
301
+ before do
302
+ @ds = ds = Sequel::Database.new[:t]
303
+ end
304
+
305
+ specify "should return an LiteralString object" do
306
+ 'xyz'.lit.should be_a_kind_of(Sequel::LiteralString)
307
+ 'xyz'.lit.to_s.should == 'xyz'
308
+ end
309
+
310
+ specify "should inhibit string literalization" do
311
+ @ds.update_sql(:stamp => "NOW()".lit).should == "UPDATE t SET stamp = NOW()"
312
+ end
313
+
314
+ specify "should return a PlaceholderLiteralString object if args are given" do
315
+ a = 'DISTINCT ?'.lit(:a)
316
+ a.should be_a_kind_of(Sequel::SQL::PlaceholderLiteralString)
317
+ @ds.literal(a).should == 'DISTINCT a'
318
+ @ds.quote_identifiers = true
319
+ @ds.literal(a).should == 'DISTINCT "a"'
320
+ end
321
+
322
+ specify "should handle named placeholders if given a single argument hash" do
323
+ a = 'DISTINCT :b'.lit(:b=>:a)
324
+ a.should be_a_kind_of(Sequel::SQL::PlaceholderLiteralString)
325
+ @ds.literal(a).should == 'DISTINCT a'
326
+ @ds.quote_identifiers = true
327
+ @ds.literal(a).should == 'DISTINCT "a"'
328
+ end
329
+
330
+ specify "should treat placeholder literal strings as generic expressions" do
331
+ a = ':b'.lit(:b=>:a)
332
+ @ds.literal(a + 1).should == "(a + 1)"
333
+ @ds.literal(a & :b).should == "(a AND b)"
334
+ @ds.literal(a.sql_string + :b).should == "(a || b)"
335
+ end
336
+ end
337
+
338
+ describe "String#to_sequel_blob" do
339
+ specify "should return a Blob object" do
340
+ 'xyz'.to_sequel_blob.should be_a_kind_of(::Sequel::SQL::Blob)
341
+ 'xyz'.to_sequel_blob.should == 'xyz'
342
+ end
343
+
344
+ specify "should retain binary data" do
345
+ "\1\2\3\4".to_sequel_blob.should == "\1\2\3\4"
346
+ end
347
+ end
348
+
349
+ describe "#desc" do
350
+ before do
351
+ @ds = Sequel::Dataset.new(nil)
352
+ end
353
+
354
+ specify "should format a DESC clause for a column ref" do
355
+ :test.desc.to_s(@ds).should == 'test DESC'
356
+
357
+ :items__price.desc.to_s(@ds).should == 'items.price DESC'
358
+ end
359
+
360
+ specify "should format a DESC clause for a function" do
361
+ :avg.sql_function(:test).desc.to_s(@ds).should == 'avg(test) DESC'
362
+ end
363
+ end
364
+
365
+ describe "#asc" do
366
+ before do
367
+ @ds = Sequel::Dataset.new(nil)
368
+ end
369
+
370
+ specify "should format a ASC clause for a column ref" do
371
+ :test.asc.to_s(@ds).should == 'test ASC'
372
+
373
+ :items__price.asc.to_s(@ds).should == 'items.price ASC'
374
+ end
375
+
376
+ specify "should format a ASC clause for a function" do
377
+ :avg.sql_function(:test).asc.to_s(@ds).should == 'avg(test) ASC'
378
+ end
379
+ end
380
+
381
+ describe "#as" do
382
+ before do
383
+ @ds = Sequel::Dataset.new(nil)
384
+ end
385
+
386
+ specify "should format a AS clause for a column ref" do
387
+ :test.as(:t).to_s(@ds).should == 'test AS t'
388
+
389
+ :items__price.as(:p).to_s(@ds).should == 'items.price AS p'
390
+ end
391
+
392
+ specify "should format a AS clause for a function" do
393
+ :avg.sql_function(:test).as(:avg).to_s(@ds).should == 'avg(test) AS avg'
394
+ end
395
+
396
+ specify "should format a AS clause for a literal value" do
397
+ 'abc'.as(:abc).to_s(@ds).should == "'abc' AS abc"
398
+ end
399
+ end
400
+
401
+ describe "Column references" do
402
+ before do
403
+ @ds = Sequel::Database.new.dataset
404
+ def @ds.quoted_identifier_append(sql, c)
405
+ sql << "`#{c}`"
406
+ end
407
+ @ds.quote_identifiers = true
408
+ end
409
+
410
+ specify "should be quoted properly" do
411
+ @ds.literal(:xyz).should == "`xyz`"
412
+ @ds.literal(:xyz__abc).should == "`xyz`.`abc`"
413
+
414
+ @ds.literal(:xyz.as(:x)).should == "`xyz` AS `x`"
415
+ @ds.literal(:xyz__abc.as(:x)).should == "`xyz`.`abc` AS `x`"
416
+
417
+ @ds.literal(:xyz___x).should == "`xyz` AS `x`"
418
+ @ds.literal(:xyz__abc___x).should == "`xyz`.`abc` AS `x`"
419
+ end
420
+
421
+ specify "should be quoted properly in SQL functions" do
422
+ @ds.literal(:avg.sql_function(:xyz)).should == "avg(`xyz`)"
423
+ @ds.literal(:avg.sql_function(:xyz, 1)).should == "avg(`xyz`, 1)"
424
+ @ds.literal(:avg.sql_function(:xyz).as(:a)).should == "avg(`xyz`) AS `a`"
425
+ end
426
+
427
+ specify "should be quoted properly in ASC/DESC clauses" do
428
+ @ds.literal(:xyz.asc).should == "`xyz` ASC"
429
+ @ds.literal(:avg.sql_function(:xyz, 1).desc).should == "avg(`xyz`, 1) DESC"
430
+ end
431
+
432
+ specify "should be quoted properly in a cast function" do
433
+ @ds.literal(:x.cast(:integer)).should == "CAST(`x` AS integer)"
434
+ @ds.literal(:x__y.cast('varchar(20)')).should == "CAST(`x`.`y` AS varchar(20))"
435
+ end
436
+ end
437
+
438
+ describe "Blob" do
439
+ specify "#to_sequel_blob should return self" do
440
+ blob = "x".to_sequel_blob
441
+ blob.to_sequel_blob.object_id.should == blob.object_id
442
+ end
443
+ end
444
+
445
+ if RUBY_VERSION < '1.9.0'
446
+ describe "Symbol#[]" do
447
+ specify "should format an SQL Function" do
448
+ ds = Sequel::Dataset.new(nil)
449
+ ds.literal(:xyz[]).should == 'xyz()'
450
+ ds.literal(:xyz[1]).should == 'xyz(1)'
451
+ ds.literal(:xyz[1, 2, :abc[3]]).should == 'xyz(1, 2, abc(3))'
452
+ end
453
+ end
454
+ end
455
+
456
+ describe "Symbol#*" do
457
+ before do
458
+ @ds = Sequel::Dataset.new(nil)
459
+ end
460
+
461
+ specify "should format a qualified wildcard if no argument" do
462
+ :xyz.*.to_s(@ds).should == 'xyz.*'
463
+ :abc.*.to_s(@ds).should == 'abc.*'
464
+ end
465
+
466
+ specify "should format a filter expression if an argument" do
467
+ :xyz.*(3).to_s(@ds).should == '(xyz * 3)'
468
+ :abc.*(5).to_s(@ds).should == '(abc * 5)'
469
+ end
470
+
471
+ specify "should support qualified symbols if no argument" do
472
+ :xyz__abc.*.to_s(@ds).should == 'xyz.abc.*'
473
+ end
474
+ end
475
+
476
+ describe "Symbol" do
477
+ before do
478
+ @ds = Sequel::Dataset.new(nil)
479
+ @ds.quote_identifiers = true
480
+ @ds.identifier_input_method = :upcase
481
+ end
482
+
483
+ specify "#identifier should format an identifier" do
484
+ @ds.literal(:xyz__abc.identifier).should == '"XYZ__ABC"'
485
+ end
486
+
487
+ specify "#qualify should format a qualified column" do
488
+ @ds.literal(:xyz.qualify(:abc)).should == '"ABC"."XYZ"'
489
+ end
490
+
491
+ specify "#qualify should work on QualifiedIdentifiers" do
492
+ @ds.literal(:xyz.qualify(:abc).qualify(:def)).should == '"DEF"."ABC"."XYZ"'
493
+ end
494
+
495
+ specify "should be able to qualify an identifier" do
496
+ @ds.literal(:xyz.identifier.qualify(:xyz__abc)).should == '"XYZ"."ABC"."XYZ"'
497
+ end
498
+
499
+ specify "should be able to specify a schema.table.column" do
500
+ @ds.literal(:column.qualify(:table.qualify(:schema))).should == '"SCHEMA"."TABLE"."COLUMN"'
501
+ @ds.literal(:column.qualify(:table__name.identifier.qualify(:schema))).should == '"SCHEMA"."TABLE__NAME"."COLUMN"'
502
+ end
503
+
504
+ specify "should be able to specify order" do
505
+ @oe = :xyz.desc
506
+ @oe.class.should == Sequel::SQL::OrderedExpression
507
+ @oe.descending.should == true
508
+ @oe = :xyz.asc
509
+ @oe.class.should == Sequel::SQL::OrderedExpression
510
+ @oe.descending.should == false
511
+ end
512
+
513
+ specify "should work correctly with objects" do
514
+ o = Object.new
515
+ def o.sql_literal(ds) "(foo)" end
516
+ @ds.literal(:column.qualify(o)).should == '(foo)."COLUMN"'
517
+ end
518
+ end
519
+
520
+ describe "Symbol" do
521
+ before do
522
+ @ds = Sequel::Database.new.dataset
523
+ end
524
+
525
+ specify "should support sql_function method" do
526
+ :COUNT.sql_function('1').to_s(@ds).should == "COUNT('1')"
527
+ @ds.select(:COUNT.sql_function('1')).sql.should == "SELECT COUNT('1')"
528
+ end
529
+
530
+ specify "should support cast method" do
531
+ :abc.cast(:integer).to_s(@ds).should == "CAST(abc AS integer)"
532
+ end
533
+
534
+ specify "should support sql array accesses via sql_subscript" do
535
+ @ds.literal(:abc.sql_subscript(1)).should == "abc[1]"
536
+ @ds.literal(:abc__def.sql_subscript(1)).should == "abc.def[1]"
537
+ @ds.literal(:abc.sql_subscript(1)|2).should == "abc[1, 2]"
538
+ @ds.literal(:abc.sql_subscript(1)[2]).should == "abc[1][2]"
539
+ end
540
+
541
+ specify "should support cast_numeric and cast_string" do
542
+ x = :abc.cast_numeric
543
+ x.should be_a_kind_of(Sequel::SQL::NumericExpression)
544
+ x.to_s(@ds).should == "CAST(abc AS integer)"
545
+
546
+ x = :abc.cast_numeric(:real)
547
+ x.should be_a_kind_of(Sequel::SQL::NumericExpression)
548
+ x.to_s(@ds).should == "CAST(abc AS real)"
549
+
550
+ x = :abc.cast_string
551
+ x.should be_a_kind_of(Sequel::SQL::StringExpression)
552
+ x.to_s(@ds).should == "CAST(abc AS varchar(255))"
553
+
554
+ x = :abc.cast_string(:varchar)
555
+ x.should be_a_kind_of(Sequel::SQL::StringExpression)
556
+ x.to_s(@ds).should == "CAST(abc AS varchar(255))"
557
+ end
558
+
559
+ specify "should allow database independent types when casting" do
560
+ db = @ds.db
561
+ def db.cast_type_literal(type)
562
+ return :foo if type == Integer
563
+ return :bar if type == String
564
+ type
565
+ end
566
+ :abc.cast(String).to_s(@ds).should == "CAST(abc AS bar)"
567
+ :abc.cast(String).to_s(@ds).should == "CAST(abc AS bar)"
568
+ :abc.cast_string.to_s(@ds).should == "CAST(abc AS bar)"
569
+ :abc.cast_string(Integer).to_s(@ds).should == "CAST(abc AS foo)"
570
+ :abc.cast_numeric.to_s(@ds).should == "CAST(abc AS foo)"
571
+ :abc.cast_numeric(String).to_s(@ds).should == "CAST(abc AS bar)"
572
+ end
573
+
574
+ specify "should support SQL EXTRACT function via #extract " do
575
+ :abc.extract(:year).to_s(@ds).should == "extract(year FROM abc)"
576
+ end
577
+ end
578
+
579
+ describe "Postgres extensions integration" do
580
+ before do
581
+ @db = Sequel.mock
582
+ Sequel.extension(:pg_array, :pg_array_ops, :pg_hstore, :pg_hstore_ops, :pg_json, :pg_range, :pg_range_ops, :pg_row, :pg_row_ops)
583
+ end
584
+
585
+ it "Symbol#pg_array should return an ArrayOp" do
586
+ @db.literal(:a.pg_array.unnest).should == "unnest(a)"
587
+ end
588
+
589
+ it "Symbol#pg_row should return a PGRowOp" do
590
+ @db.literal(:a.pg_row[:a]).should == "(a).a"
591
+ end
592
+
593
+ it "Symbol#hstore should return an HStoreOp" do
594
+ @db.literal(:a.hstore['a']).should == "(a -> 'a')"
595
+ end
596
+
597
+ it "Symbol#pg_range should return a RangeOp" do
598
+ @db.literal(:a.pg_range.lower).should == "lower(a)"
599
+ end
600
+
601
+ it "Array#pg_array should return a PGArray" do
602
+ @db.literal([1].pg_array.op.unnest).should == "unnest(ARRAY[1])"
603
+ @db.literal([1].pg_array(:int4).op.unnest).should == "unnest(ARRAY[1]::int4[])"
604
+ end
605
+
606
+ it "Array#pg_json should return a JSONArray" do
607
+ @db.literal([1].pg_json).should == "'[1]'::json"
608
+ end
609
+
610
+ it "Array#pg_row should return a ArrayRow" do
611
+ @db.literal([1].pg_row).should == "ROW(1)"
612
+ end
613
+
614
+ it "Hash#hstore should return an HStore" do
615
+ @db.literal({'a'=>1}.hstore.op['a']).should == '(\'"a"=>"1"\'::hstore -> \'a\')'
616
+ end
617
+
618
+ it "Hash#pg_json should return an JSONHash" do
619
+ @db.literal({'a'=>'b'}.pg_json).should == "'{\"a\":\"b\"}'::json"
620
+ end
621
+
622
+ it "Range#pg_range should return an PGRange" do
623
+ @db.literal((1..2).pg_range).should == "'[1,2]'"
624
+ @db.literal((1..2).pg_range(:int4range)).should == "'[1,2]'::int4range"
625
+ end
626
+ end
@@ -24,6 +24,11 @@ describe "ActiveModel plugin" do
24
24
  columns :id, :id2
25
25
  def delete; end
26
26
  end
27
+ module ::Blog
28
+ class Post < Sequel::Model
29
+ plugin :active_model
30
+ end
31
+ end
27
32
  @c = AMLintTest
28
33
  @c.plugin :active_model
29
34
  @m = @model = @c.new
@@ -33,6 +38,7 @@ describe "ActiveModel plugin" do
33
38
  def teardown
34
39
  super
35
40
  Object.send(:remove_const, :AMLintTest)
41
+ Object.send(:remove_const, :Blog)
36
42
  end
37
43
  include ActiveModel::Lint::Tests
38
44
 
@@ -80,6 +86,13 @@ describe "ActiveModel plugin" do
80
86
  assert_equal false, @m.persisted?
81
87
  assert_equal false, @o.persisted?
82
88
  end
89
+
90
+ # Should return self, not a proxy object
91
+ def test__to_partial_path
92
+ assert_equal 'am_lint_tests/am_lint_test', @m.to_partial_path
93
+ assert_equal 'blog/posts/post', Blog::Post.new.to_partial_path
94
+ end
95
+
83
96
  end
84
97
  if defined?(MiniTest::Unit)
85
98
  tc.instance_methods.map{|x| x.to_s}.reject{|n| n !~ /\Atest_/}.each do |m|