ibm_db 5.2.0-x86-mingw32 → 5.3.2-x86-mingw32

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 (621) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/LICENSE +55 -18
  4. data/ext/Makefile +15 -13
  5. data/ext/ibm_db.c +62 -57
  6. data/ext/ibm_db.o +0 -0
  7. data/ext/ibm_db.so +0 -0
  8. data/ext/mkmf.log +26 -24
  9. data/ext/ruby_ibm_db_cli.c +1 -0
  10. data/ext/ruby_ibm_db_cli.o +0 -0
  11. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +1463 -1279
  12. data/lib/ibm_db.so +1 -0
  13. data/lib/mswin32/rb3x/i386/ruby30/ibm_db.so +0 -0
  14. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  15. data/test/activejob/destroy_association_async_test.rb +305 -0
  16. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  17. data/test/activejob/helper.rb +15 -0
  18. data/test/assets/schema_dump_5_1.yml +345 -0
  19. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  20. data/test/cases/adapter_test.rb +432 -218
  21. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  22. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  23. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  24. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  25. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  26. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  27. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  28. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  29. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  30. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  31. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  32. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  33. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  34. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  35. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  36. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  38. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  39. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  40. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  42. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  43. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  44. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  45. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  46. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  47. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  48. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  49. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  50. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  51. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  52. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  53. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  54. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  55. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  56. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  57. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  58. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  59. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  60. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  61. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  62. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  63. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  64. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  65. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  66. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  67. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  68. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  69. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  70. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  71. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  72. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  73. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  74. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  75. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  76. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  77. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  78. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  79. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  80. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  81. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  82. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  83. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  84. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  85. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  86. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  87. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  88. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  89. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  90. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  91. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  92. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  93. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  94. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  95. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  96. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  97. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  98. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  99. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  100. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  101. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  102. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  103. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  104. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  105. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  106. data/test/cases/aggregations_test.rb +14 -12
  107. data/test/cases/annotate_test.rb +46 -0
  108. data/test/cases/ar_schema_test.rb +153 -86
  109. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  110. data/test/cases/arel/attributes/math_test.rb +83 -0
  111. data/test/cases/arel/attributes_test.rb +27 -0
  112. data/test/cases/arel/collectors/bind_test.rb +40 -0
  113. data/test/cases/arel/collectors/composite_test.rb +47 -0
  114. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  115. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  116. data/test/cases/arel/crud_test.rb +65 -0
  117. data/test/cases/arel/delete_manager_test.rb +53 -0
  118. data/test/cases/arel/factory_methods_test.rb +46 -0
  119. data/test/cases/arel/helper.rb +45 -0
  120. data/test/cases/arel/insert_manager_test.rb +241 -0
  121. data/test/cases/arel/nodes/and_test.rb +30 -0
  122. data/test/cases/arel/nodes/as_test.rb +36 -0
  123. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  124. data/test/cases/arel/nodes/bin_test.rb +35 -0
  125. data/test/cases/arel/nodes/binary_test.rb +29 -0
  126. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  127. data/test/cases/arel/nodes/case_test.rb +96 -0
  128. data/test/cases/arel/nodes/casted_test.rb +18 -0
  129. data/test/cases/arel/nodes/comment_test.rb +22 -0
  130. data/test/cases/arel/nodes/count_test.rb +35 -0
  131. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  132. data/test/cases/arel/nodes/descending_test.rb +46 -0
  133. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  134. data/test/cases/arel/nodes/equality_test.rb +62 -0
  135. data/test/cases/arel/nodes/extract_test.rb +43 -0
  136. data/test/cases/arel/nodes/false_test.rb +21 -0
  137. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  138. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  139. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  140. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  141. data/test/cases/arel/nodes/node_test.rb +22 -0
  142. data/test/cases/arel/nodes/not_test.rb +31 -0
  143. data/test/cases/arel/nodes/or_test.rb +36 -0
  144. data/test/cases/arel/nodes/over_test.rb +69 -0
  145. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  146. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  147. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  148. data/test/cases/arel/nodes/sum_test.rb +35 -0
  149. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  150. data/test/cases/arel/nodes/true_test.rb +21 -0
  151. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  152. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  153. data/test/cases/arel/nodes/window_test.rb +81 -0
  154. data/test/cases/arel/nodes_test.rb +34 -0
  155. data/test/cases/arel/select_manager_test.rb +1238 -0
  156. data/test/cases/arel/support/fake_record.rb +135 -0
  157. data/test/cases/arel/table_test.rb +216 -0
  158. data/test/cases/arel/update_manager_test.rb +126 -0
  159. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  160. data/test/cases/arel/visitors/dot_test.rb +90 -0
  161. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  162. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  163. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  164. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  165. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  166. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  167. data/test/cases/associations/callbacks_test.rb +56 -38
  168. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  169. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  170. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  171. data/test/cases/associations/eager_singularization_test.rb +21 -21
  172. data/test/cases/associations/eager_test.rb +559 -415
  173. data/test/cases/associations/extension_test.rb +18 -12
  174. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  175. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  176. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  177. data/test/cases/associations/has_one_associations_test.rb +294 -129
  178. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  179. data/test/cases/associations/inner_join_association_test.rb +114 -38
  180. data/test/cases/associations/inverse_associations_test.rb +606 -398
  181. data/test/cases/associations/join_model_test.rb +158 -148
  182. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  183. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  184. data/test/cases/associations/required_test.rb +35 -10
  185. data/test/cases/associations_test.rb +241 -110
  186. data/test/cases/attribute_methods/read_test.rb +11 -11
  187. data/test/cases/attribute_methods_test.rb +413 -298
  188. data/test/cases/attributes_test.rb +145 -27
  189. data/test/cases/autosave_association_test.rb +681 -436
  190. data/test/cases/base_prevent_writes_test.rb +229 -0
  191. data/test/cases/base_test.rb +599 -542
  192. data/test/cases/batches_test.rb +288 -82
  193. data/test/cases/binary_test.rb +26 -31
  194. data/test/cases/bind_parameter_test.rb +194 -21
  195. data/test/cases/boolean_test.rb +52 -0
  196. data/test/cases/cache_key_test.rb +110 -5
  197. data/test/cases/calculations_test.rb +740 -177
  198. data/test/cases/callbacks_test.rb +74 -207
  199. data/test/cases/clone_test.rb +15 -10
  200. data/test/cases/coders/json_test.rb +2 -0
  201. data/test/cases/coders/yaml_column_test.rb +16 -13
  202. data/test/cases/collection_cache_key_test.rb +177 -20
  203. data/test/cases/column_alias_test.rb +9 -7
  204. data/test/cases/column_definition_test.rb +10 -68
  205. data/test/cases/comment_test.rb +166 -107
  206. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  207. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  208. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  209. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  210. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  211. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  212. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  213. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  214. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  215. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  216. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  217. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  218. data/test/cases/connection_management_test.rb +13 -11
  219. data/test/cases/connection_pool_test.rb +316 -83
  220. data/test/cases/core_test.rb +82 -58
  221. data/test/cases/counter_cache_test.rb +204 -50
  222. data/test/cases/custom_locking_test.rb +5 -3
  223. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  224. data/test/cases/database_configurations/resolver_test.rb +150 -0
  225. data/test/cases/database_configurations_test.rb +145 -0
  226. data/test/cases/database_selector_test.rb +296 -0
  227. data/test/cases/database_statements_test.rb +18 -16
  228. data/test/cases/date_test.rb +8 -16
  229. data/test/cases/date_time_precision_test.rb +100 -78
  230. data/test/cases/date_time_test.rb +23 -8
  231. data/test/cases/defaults_test.rb +106 -71
  232. data/test/cases/delegated_type_test.rb +57 -0
  233. data/test/cases/dirty_test.rb +419 -223
  234. data/test/cases/disconnected_test.rb +6 -6
  235. data/test/cases/dup_test.rb +54 -27
  236. data/test/cases/enum_test.rb +461 -82
  237. data/test/cases/errors_test.rb +7 -7
  238. data/test/cases/explain_subscriber_test.rb +17 -15
  239. data/test/cases/explain_test.rb +11 -19
  240. data/test/cases/filter_attributes_test.rb +153 -0
  241. data/test/cases/finder_respond_to_test.rb +14 -14
  242. data/test/cases/finder_test.rb +669 -287
  243. data/test/cases/fixture_set/file_test.rb +34 -38
  244. data/test/cases/fixtures_test.rb +833 -176
  245. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  246. data/test/cases/habtm_destroy_order_test.rb +25 -25
  247. data/test/cases/helper.rb +78 -49
  248. data/test/cases/hot_compatibility_test.rb +33 -32
  249. data/test/cases/i18n_test.rb +18 -17
  250. data/test/cases/inheritance_test.rb +180 -115
  251. data/test/cases/insert_all_test.rb +489 -0
  252. data/test/cases/instrumentation_test.rb +101 -0
  253. data/test/cases/integration_test.rb +119 -31
  254. data/test/cases/invalid_connection_test.rb +18 -16
  255. data/test/cases/invertible_migration_test.rb +183 -43
  256. data/test/cases/json_attribute_test.rb +35 -0
  257. data/test/cases/json_serialization_test.rb +57 -58
  258. data/test/cases/json_shared_test_cases.rb +290 -0
  259. data/test/cases/locking_test.rb +413 -119
  260. data/test/cases/log_subscriber_test.rb +68 -26
  261. data/test/cases/marshal_serialization_test.rb +39 -0
  262. data/test/cases/migration/change_schema_test.rb +118 -72
  263. data/test/cases/migration/change_table_test.rb +138 -30
  264. data/test/cases/migration/check_constraint_test.rb +162 -0
  265. data/test/cases/migration/column_attributes_test.rb +45 -35
  266. data/test/cases/migration/column_positioning_test.rb +18 -6
  267. data/test/cases/migration/columns_test.rb +93 -77
  268. data/test/cases/migration/command_recorder_test.rb +121 -34
  269. data/test/cases/migration/compatibility_test.rb +578 -23
  270. data/test/cases/migration/create_join_table_test.rb +35 -25
  271. data/test/cases/migration/foreign_key_test.rb +503 -284
  272. data/test/cases/migration/helper.rb +4 -3
  273. data/test/cases/migration/index_test.rb +119 -70
  274. data/test/cases/migration/logger_test.rb +9 -6
  275. data/test/cases/migration/pending_migrations_test.rb +88 -34
  276. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  277. data/test/cases/migration/references_index_test.rb +38 -19
  278. data/test/cases/migration/references_statements_test.rb +15 -14
  279. data/test/cases/migration/rename_table_test.rb +53 -30
  280. data/test/cases/migration_test.rb +637 -269
  281. data/test/cases/migrator_test.rb +191 -135
  282. data/test/cases/mixin_test.rb +7 -11
  283. data/test/cases/modules_test.rb +36 -34
  284. data/test/cases/multi_db_migrator_test.rb +223 -0
  285. data/test/cases/multiparameter_attributes_test.rb +60 -33
  286. data/test/cases/multiple_db_test.rb +16 -22
  287. data/test/cases/nested_attributes_test.rb +341 -320
  288. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  289. data/test/cases/null_relation_test.rb +84 -0
  290. data/test/cases/numeric_data_test.rb +93 -0
  291. data/test/cases/persistence_test.rb +361 -269
  292. data/test/cases/pooled_connections_test.rb +18 -26
  293. data/test/cases/prepared_statement_status_test.rb +48 -0
  294. data/test/cases/primary_keys_test.rb +210 -104
  295. data/test/cases/query_cache_test.rb +610 -141
  296. data/test/cases/quoting_test.rb +132 -31
  297. data/test/cases/readonly_test.rb +49 -48
  298. data/test/cases/reaper_test.rb +146 -32
  299. data/test/cases/reflection_test.rb +167 -156
  300. data/test/cases/relation/delegation_test.rb +49 -36
  301. data/test/cases/relation/delete_all_test.rb +117 -0
  302. data/test/cases/relation/merging_test.rb +319 -42
  303. data/test/cases/relation/mutation_test.rb +55 -93
  304. data/test/cases/relation/or_test.rb +129 -29
  305. data/test/cases/relation/predicate_builder_test.rb +21 -6
  306. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  307. data/test/cases/relation/select_test.rb +67 -0
  308. data/test/cases/relation/update_all_test.rb +317 -0
  309. data/test/cases/relation/where_chain_test.rb +68 -32
  310. data/test/cases/relation/where_clause_test.rb +136 -61
  311. data/test/cases/relation/where_test.rb +155 -48
  312. data/test/cases/relation_test.rb +266 -112
  313. data/test/cases/relations_test.rb +969 -744
  314. data/test/cases/reload_models_test.rb +13 -9
  315. data/test/cases/reserved_word_test.rb +141 -0
  316. data/test/cases/result_test.rb +68 -17
  317. data/test/cases/sanitize_test.rb +87 -71
  318. data/test/cases/schema_dumper_test.rb +221 -128
  319. data/test/cases/schema_loading_test.rb +3 -2
  320. data/test/cases/scoping/default_scoping_test.rb +185 -144
  321. data/test/cases/scoping/named_scoping_test.rb +177 -89
  322. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  323. data/test/cases/secure_token_test.rb +18 -3
  324. data/test/cases/serialization_test.rb +30 -28
  325. data/test/cases/serialized_attribute_test.rb +133 -42
  326. data/test/cases/signed_id_test.rb +168 -0
  327. data/test/cases/statement_cache_test.rb +41 -24
  328. data/test/cases/statement_invalid_test.rb +42 -0
  329. data/test/cases/store_test.rb +180 -55
  330. data/test/cases/strict_loading_test.rb +473 -0
  331. data/test/cases/suppressor_test.rb +26 -12
  332. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  333. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  334. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  335. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  336. data/test/cases/test_case.rb +51 -40
  337. data/test/cases/test_databases_test.rb +79 -0
  338. data/test/cases/test_fixtures_test.rb +79 -19
  339. data/test/cases/time_precision_test.rb +98 -76
  340. data/test/cases/timestamp_test.rb +102 -99
  341. data/test/cases/touch_later_test.rb +12 -10
  342. data/test/cases/transaction_callbacks_test.rb +344 -90
  343. data/test/cases/transaction_isolation_test.rb +12 -12
  344. data/test/cases/transactions_test.rb +612 -162
  345. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  346. data/test/cases/type/date_time_test.rb +4 -2
  347. data/test/cases/type/integer_test.rb +4 -2
  348. data/test/cases/type/string_test.rb +10 -8
  349. data/test/cases/type/time_test.rb +28 -0
  350. data/test/cases/type/type_map_test.rb +29 -28
  351. data/test/cases/type/unsigned_integer_test.rb +19 -0
  352. data/test/cases/type_test.rb +2 -0
  353. data/test/cases/types_test.rb +3 -1
  354. data/test/cases/unconnected_test.rb +14 -1
  355. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  356. data/test/cases/validations/absence_validation_test.rb +19 -17
  357. data/test/cases/validations/association_validation_test.rb +30 -28
  358. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  359. data/test/cases/validations/i18n_validation_test.rb +22 -21
  360. data/test/cases/validations/length_validation_test.rb +34 -33
  361. data/test/cases/validations/numericality_validation_test.rb +181 -0
  362. data/test/cases/validations/presence_validation_test.rb +21 -19
  363. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  364. data/test/cases/validations_repair_helper.rb +2 -0
  365. data/test/cases/validations_test.rb +61 -26
  366. data/test/cases/view_test.rb +122 -116
  367. data/test/cases/yaml_serialization_test.rb +79 -34
  368. data/test/config.example.yml +19 -19
  369. data/test/config.rb +3 -1
  370. data/test/config.yml +16 -6
  371. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  372. data/test/fixtures/author_addresses.yml +1 -8
  373. data/test/fixtures/authors.yml +1 -7
  374. data/test/fixtures/binaries.yml +4 -0
  375. data/test/fixtures/books.yml +9 -2
  376. data/test/fixtures/categories_posts.yml +3 -0
  377. data/test/fixtures/citations.yml +5 -0
  378. data/test/fixtures/comments.yml +7 -0
  379. data/test/fixtures/companies.yml +5 -0
  380. data/test/fixtures/computers.yml +2 -0
  381. data/test/fixtures/customers.yml +10 -1
  382. data/test/fixtures/developers.yml +1 -1
  383. data/test/fixtures/essays.yml +10 -0
  384. data/test/fixtures/faces.yml +3 -3
  385. data/test/fixtures/humans.yml +5 -0
  386. data/test/fixtures/interests.yml +7 -7
  387. data/test/fixtures/memberships.yml +7 -0
  388. data/test/fixtures/minimalistics.yml +3 -0
  389. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  390. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  391. data/test/fixtures/naked/yml/parrots.yml +1 -0
  392. data/test/fixtures/other_books.yml +26 -0
  393. data/test/fixtures/other_posts.yml +1 -0
  394. data/test/fixtures/parrots.yml +7 -1
  395. data/test/fixtures/pirates.yml +3 -0
  396. data/test/fixtures/posts.yml +11 -3
  397. data/test/fixtures/readers.yml +6 -0
  398. data/test/fixtures/reserved_words/values.yml +2 -2
  399. data/test/fixtures/sponsors.yml +3 -0
  400. data/test/fixtures/strict_zines.yml +2 -0
  401. data/test/fixtures/subscribers.yml +1 -1
  402. data/test/fixtures/tasks.yml +1 -1
  403. data/test/fixtures/warehouse-things.yml +3 -0
  404. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  405. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  406. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  407. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  408. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  409. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  410. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  411. data/test/migrations/rename/1_we_need_things.rb +2 -0
  412. data/test/migrations/rename/2_rename_things.rb +2 -0
  413. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  414. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  415. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  416. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  417. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  418. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  419. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  420. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  421. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  422. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  423. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  424. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  425. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  426. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  427. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  428. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  429. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  430. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  431. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  432. data/test/models/account.rb +46 -0
  433. data/test/models/admin/account.rb +3 -1
  434. data/test/models/admin/randomly_named_c1.rb +2 -0
  435. data/test/models/admin/user.rb +16 -8
  436. data/test/models/admin.rb +4 -2
  437. data/test/models/aircraft.rb +3 -1
  438. data/test/models/arunit2_model.rb +2 -0
  439. data/test/models/author.rb +153 -102
  440. data/test/models/auto_id.rb +2 -0
  441. data/test/models/autoloadable/extra_firm.rb +2 -0
  442. data/test/models/binary.rb +3 -1
  443. data/test/models/binary_field.rb +6 -0
  444. data/test/models/bird.rb +13 -1
  445. data/test/models/book.rb +14 -4
  446. data/test/models/book_destroy_async.rb +24 -0
  447. data/test/models/boolean.rb +5 -0
  448. data/test/models/bulb.rb +13 -4
  449. data/test/models/cake_designer.rb +2 -0
  450. data/test/models/car.rb +17 -10
  451. data/test/models/carrier.rb +2 -0
  452. data/test/models/cart.rb +5 -0
  453. data/test/models/cat.rb +2 -0
  454. data/test/models/categorization.rb +8 -6
  455. data/test/models/category.rb +28 -16
  456. data/test/models/chef.rb +2 -0
  457. data/test/models/citation.rb +5 -1
  458. data/test/models/club.rb +13 -10
  459. data/test/models/college.rb +4 -2
  460. data/test/models/column.rb +2 -0
  461. data/test/models/column_name.rb +2 -0
  462. data/test/models/comment.rb +32 -10
  463. data/test/models/company.rb +102 -106
  464. data/test/models/company_in_module.rb +27 -26
  465. data/test/models/computer.rb +3 -1
  466. data/test/models/contact.rb +15 -13
  467. data/test/models/content.rb +5 -3
  468. data/test/models/contract.rb +21 -3
  469. data/test/models/country.rb +2 -4
  470. data/test/models/course.rb +3 -1
  471. data/test/models/customer.rb +10 -8
  472. data/test/models/customer_carrier.rb +2 -0
  473. data/test/models/dashboard.rb +2 -0
  474. data/test/models/default.rb +2 -0
  475. data/test/models/department.rb +2 -0
  476. data/test/models/destroy_async_parent.rb +15 -0
  477. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  478. data/test/models/developer.rb +152 -85
  479. data/test/models/dl_keyed_belongs_to.rb +13 -0
  480. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  481. data/test/models/dl_keyed_has_many.rb +5 -0
  482. data/test/models/dl_keyed_has_many_through.rb +5 -0
  483. data/test/models/dl_keyed_has_one.rb +5 -0
  484. data/test/models/dl_keyed_join.rb +10 -0
  485. data/test/models/dog.rb +2 -0
  486. data/test/models/dog_lover.rb +2 -0
  487. data/test/models/doubloon.rb +3 -1
  488. data/test/models/drink_designer.rb +17 -0
  489. data/test/models/edge.rb +4 -2
  490. data/test/models/electron.rb +2 -0
  491. data/test/models/engine.rb +3 -2
  492. data/test/models/entrant.rb +2 -0
  493. data/test/models/entry.rb +5 -0
  494. data/test/models/essay.rb +6 -3
  495. data/test/models/essay_destroy_async.rb +12 -0
  496. data/test/models/event.rb +3 -1
  497. data/test/models/eye.rb +5 -3
  498. data/test/models/face.rb +14 -6
  499. data/test/models/family.rb +6 -0
  500. data/test/models/family_tree.rb +6 -0
  501. data/test/models/friendship.rb +5 -3
  502. data/test/models/frog.rb +8 -0
  503. data/test/models/guid.rb +3 -1
  504. data/test/models/guitar.rb +2 -0
  505. data/test/models/hotel.rb +5 -3
  506. data/test/models/human.rb +39 -0
  507. data/test/models/image.rb +3 -1
  508. data/test/models/interest.rb +14 -3
  509. data/test/models/invoice.rb +4 -2
  510. data/test/models/item.rb +3 -1
  511. data/test/models/job.rb +5 -3
  512. data/test/models/joke.rb +4 -2
  513. data/test/models/keyboard.rb +3 -1
  514. data/test/models/legacy_thing.rb +2 -0
  515. data/test/models/lesson.rb +2 -0
  516. data/test/models/line_item.rb +3 -1
  517. data/test/models/liquid.rb +2 -0
  518. data/test/models/matey.rb +3 -1
  519. data/test/models/measurement.rb +4 -0
  520. data/test/models/member.rb +23 -20
  521. data/test/models/member_detail.rb +3 -0
  522. data/test/models/member_type.rb +2 -0
  523. data/test/models/membership.rb +4 -1
  524. data/test/models/mentor.rb +3 -1
  525. data/test/models/message.rb +5 -0
  526. data/test/models/minimalistic.rb +2 -0
  527. data/test/models/minivan.rb +3 -2
  528. data/test/models/mixed_case_monkey.rb +3 -1
  529. data/test/models/molecule.rb +2 -0
  530. data/test/models/mouse.rb +6 -0
  531. data/test/models/movie.rb +2 -0
  532. data/test/models/node.rb +4 -2
  533. data/test/models/non_primary_key.rb +2 -0
  534. data/test/models/notification.rb +2 -0
  535. data/test/models/numeric_data.rb +12 -0
  536. data/test/models/order.rb +4 -2
  537. data/test/models/organization.rb +9 -7
  538. data/test/models/other_dog.rb +3 -1
  539. data/test/models/owner.rb +6 -4
  540. data/test/models/parrot.rb +12 -4
  541. data/test/models/person.rb +59 -54
  542. data/test/models/personal_legacy_thing.rb +3 -1
  543. data/test/models/pet.rb +4 -2
  544. data/test/models/pet_treasure.rb +2 -0
  545. data/test/models/pirate.rb +67 -43
  546. data/test/models/possession.rb +3 -1
  547. data/test/models/post.rb +184 -86
  548. data/test/models/price_estimate.rb +11 -1
  549. data/test/models/professor.rb +3 -1
  550. data/test/models/project.rb +14 -12
  551. data/test/models/publisher/article.rb +2 -0
  552. data/test/models/publisher/magazine.rb +2 -0
  553. data/test/models/publisher.rb +2 -0
  554. data/test/models/randomly_named_c1.rb +2 -0
  555. data/test/models/rating.rb +5 -1
  556. data/test/models/reader.rb +7 -5
  557. data/test/models/recipe.rb +2 -0
  558. data/test/models/record.rb +2 -0
  559. data/test/models/reference.rb +6 -3
  560. data/test/models/reply.rb +39 -21
  561. data/test/models/room.rb +6 -0
  562. data/test/models/section.rb +6 -0
  563. data/test/models/seminar.rb +6 -0
  564. data/test/models/session.rb +6 -0
  565. data/test/models/ship.rb +12 -9
  566. data/test/models/ship_part.rb +5 -3
  567. data/test/models/shop.rb +4 -2
  568. data/test/models/shop_account.rb +2 -0
  569. data/test/models/speedometer.rb +2 -0
  570. data/test/models/sponsor.rb +8 -5
  571. data/test/models/squeak.rb +6 -0
  572. data/test/models/strict_zine.rb +7 -0
  573. data/test/models/string_key_object.rb +2 -0
  574. data/test/models/student.rb +2 -0
  575. data/test/models/subscriber.rb +4 -2
  576. data/test/models/subscription.rb +5 -1
  577. data/test/models/tag.rb +6 -3
  578. data/test/models/tagging.rb +13 -6
  579. data/test/models/task.rb +2 -0
  580. data/test/models/topic.rb +54 -19
  581. data/test/models/toy.rb +4 -0
  582. data/test/models/traffic_light.rb +2 -0
  583. data/test/models/treasure.rb +5 -3
  584. data/test/models/treaty.rb +2 -4
  585. data/test/models/tree.rb +2 -0
  586. data/test/models/tuning_peg.rb +2 -0
  587. data/test/models/tyre.rb +2 -0
  588. data/test/models/user.rb +12 -4
  589. data/test/models/uuid_child.rb +2 -0
  590. data/test/models/uuid_item.rb +2 -0
  591. data/test/models/uuid_parent.rb +2 -0
  592. data/test/models/vegetables.rb +12 -3
  593. data/test/models/vertex.rb +6 -4
  594. data/test/models/warehouse_thing.rb +2 -0
  595. data/test/models/wheel.rb +3 -1
  596. data/test/models/without_table.rb +3 -1
  597. data/test/models/zine.rb +3 -1
  598. data/test/schema/mysql2_specific_schema.rb +49 -35
  599. data/test/schema/oracle_specific_schema.rb +13 -15
  600. data/test/schema/postgresql_specific_schema.rb +51 -40
  601. data/test/schema/schema.rb +334 -154
  602. data/test/schema/sqlite_specific_schema.rb +9 -16
  603. data/test/support/config.rb +26 -26
  604. data/test/support/connection.rb +14 -8
  605. data/test/support/connection_helper.rb +3 -1
  606. data/test/support/ddl_helper.rb +2 -0
  607. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  608. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  609. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  610. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  611. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  612. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  617. data/test/support/schema_dumping_helper.rb +2 -0
  618. data/test/support/stubs/strong_parameters.rb +40 -0
  619. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  620. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  621. metadata +190 -14
@@ -0,0 +1,1145 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../helper"
4
+ require "ostruct"
5
+
6
+ module Arel
7
+ module Attributes
8
+ class AttributeTest < Arel::Spec
9
+ describe "#not_eq" do
10
+ it "should create a NotEqual node" do
11
+ relation = Table.new(:users)
12
+ _(relation[:id].not_eq(10)).must_be_kind_of Nodes::NotEqual
13
+ end
14
+
15
+ it "should generate != in sql" do
16
+ relation = Table.new(:users)
17
+ mgr = relation.project relation[:id]
18
+ mgr.where relation[:id].not_eq(10)
19
+ _(mgr.to_sql).must_be_like %{
20
+ SELECT "users"."id" FROM "users" WHERE "users"."id" != 10
21
+ }
22
+ end
23
+
24
+ it "should handle nil" do
25
+ relation = Table.new(:users)
26
+ mgr = relation.project relation[:id]
27
+ mgr.where relation[:id].not_eq(nil)
28
+ _(mgr.to_sql).must_be_like %{
29
+ SELECT "users"."id" FROM "users" WHERE "users"."id" IS NOT NULL
30
+ }
31
+ end
32
+ end
33
+
34
+ describe "#not_eq_any" do
35
+ it "should create a Grouping node" do
36
+ relation = Table.new(:users)
37
+ _(relation[:id].not_eq_any([1, 2])).must_be_kind_of Nodes::Grouping
38
+ end
39
+
40
+ it "should generate ORs in sql" do
41
+ relation = Table.new(:users)
42
+ mgr = relation.project relation[:id]
43
+ mgr.where relation[:id].not_eq_any([1, 2])
44
+ _(mgr.to_sql).must_be_like %{
45
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" != 1 OR "users"."id" != 2)
46
+ }
47
+ end
48
+ end
49
+
50
+ describe "#not_eq_all" do
51
+ it "should create a Grouping node" do
52
+ relation = Table.new(:users)
53
+ _(relation[:id].not_eq_all([1, 2])).must_be_kind_of Nodes::Grouping
54
+ end
55
+
56
+ it "should generate ANDs in sql" do
57
+ relation = Table.new(:users)
58
+ mgr = relation.project relation[:id]
59
+ mgr.where relation[:id].not_eq_all([1, 2])
60
+ _(mgr.to_sql).must_be_like %{
61
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" != 1 AND "users"."id" != 2)
62
+ }
63
+ end
64
+ end
65
+
66
+ describe "#gt" do
67
+ it "should create a GreaterThan node" do
68
+ relation = Table.new(:users)
69
+ _(relation[:id].gt(10)).must_be_kind_of Nodes::GreaterThan
70
+ end
71
+
72
+ it "should generate > in sql" do
73
+ relation = Table.new(:users)
74
+ mgr = relation.project relation[:id]
75
+ mgr.where relation[:id].gt(10)
76
+ _(mgr.to_sql).must_be_like %{
77
+ SELECT "users"."id" FROM "users" WHERE "users"."id" > 10
78
+ }
79
+ end
80
+
81
+ it "should handle comparing with a subquery" do
82
+ users = Table.new(:users)
83
+
84
+ avg = users.project(users[:karma].average)
85
+ mgr = users.project(Arel.star).where(users[:karma].gt(avg))
86
+
87
+ _(mgr.to_sql).must_be_like %{
88
+ SELECT * FROM "users" WHERE "users"."karma" > (SELECT AVG("users"."karma") FROM "users")
89
+ }
90
+ end
91
+
92
+ it "should accept various data types." do
93
+ relation = Table.new(:users)
94
+ mgr = relation.project relation[:id]
95
+ mgr.where relation[:name].gt("fake_name")
96
+ _(mgr.to_sql).must_match %{"users"."name" > 'fake_name'}
97
+
98
+ current_time = ::Time.now
99
+ mgr.where relation[:created_at].gt(current_time)
100
+ _(mgr.to_sql).must_match %{"users"."created_at" > '#{current_time}'}
101
+ end
102
+ end
103
+
104
+ describe "#gt_any" do
105
+ it "should create a Grouping node" do
106
+ relation = Table.new(:users)
107
+ _(relation[:id].gt_any([1, 2])).must_be_kind_of Nodes::Grouping
108
+ end
109
+
110
+ it "should generate ORs in sql" do
111
+ relation = Table.new(:users)
112
+ mgr = relation.project relation[:id]
113
+ mgr.where relation[:id].gt_any([1, 2])
114
+ _(mgr.to_sql).must_be_like %{
115
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" > 1 OR "users"."id" > 2)
116
+ }
117
+ end
118
+ end
119
+
120
+ describe "#gt_all" do
121
+ it "should create a Grouping node" do
122
+ relation = Table.new(:users)
123
+ _(relation[:id].gt_all([1, 2])).must_be_kind_of Nodes::Grouping
124
+ end
125
+
126
+ it "should generate ANDs in sql" do
127
+ relation = Table.new(:users)
128
+ mgr = relation.project relation[:id]
129
+ mgr.where relation[:id].gt_all([1, 2])
130
+ _(mgr.to_sql).must_be_like %{
131
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" > 1 AND "users"."id" > 2)
132
+ }
133
+ end
134
+ end
135
+
136
+ describe "#gteq" do
137
+ it "should create a GreaterThanOrEqual node" do
138
+ relation = Table.new(:users)
139
+ _(relation[:id].gteq(10)).must_be_kind_of Nodes::GreaterThanOrEqual
140
+ end
141
+
142
+ it "should generate >= in sql" do
143
+ relation = Table.new(:users)
144
+ mgr = relation.project relation[:id]
145
+ mgr.where relation[:id].gteq(10)
146
+ _(mgr.to_sql).must_be_like %{
147
+ SELECT "users"."id" FROM "users" WHERE "users"."id" >= 10
148
+ }
149
+ end
150
+
151
+ it "should accept various data types." do
152
+ relation = Table.new(:users)
153
+ mgr = relation.project relation[:id]
154
+ mgr.where relation[:name].gteq("fake_name")
155
+ _(mgr.to_sql).must_match %{"users"."name" >= 'fake_name'}
156
+
157
+ current_time = ::Time.now
158
+ mgr.where relation[:created_at].gteq(current_time)
159
+ _(mgr.to_sql).must_match %{"users"."created_at" >= '#{current_time}'}
160
+ end
161
+ end
162
+
163
+ describe "#gteq_any" do
164
+ it "should create a Grouping node" do
165
+ relation = Table.new(:users)
166
+ _(relation[:id].gteq_any([1, 2])).must_be_kind_of Nodes::Grouping
167
+ end
168
+
169
+ it "should generate ORs in sql" do
170
+ relation = Table.new(:users)
171
+ mgr = relation.project relation[:id]
172
+ mgr.where relation[:id].gteq_any([1, 2])
173
+ _(mgr.to_sql).must_be_like %{
174
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" >= 1 OR "users"."id" >= 2)
175
+ }
176
+ end
177
+ end
178
+
179
+ describe "#gteq_all" do
180
+ it "should create a Grouping node" do
181
+ relation = Table.new(:users)
182
+ _(relation[:id].gteq_all([1, 2])).must_be_kind_of Nodes::Grouping
183
+ end
184
+
185
+ it "should generate ANDs in sql" do
186
+ relation = Table.new(:users)
187
+ mgr = relation.project relation[:id]
188
+ mgr.where relation[:id].gteq_all([1, 2])
189
+ _(mgr.to_sql).must_be_like %{
190
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" >= 1 AND "users"."id" >= 2)
191
+ }
192
+ end
193
+ end
194
+
195
+ describe "#lt" do
196
+ it "should create a LessThan node" do
197
+ relation = Table.new(:users)
198
+ _(relation[:id].lt(10)).must_be_kind_of Nodes::LessThan
199
+ end
200
+
201
+ it "should generate < in sql" do
202
+ relation = Table.new(:users)
203
+ mgr = relation.project relation[:id]
204
+ mgr.where relation[:id].lt(10)
205
+ _(mgr.to_sql).must_be_like %{
206
+ SELECT "users"."id" FROM "users" WHERE "users"."id" < 10
207
+ }
208
+ end
209
+
210
+ it "should accept various data types." do
211
+ relation = Table.new(:users)
212
+ mgr = relation.project relation[:id]
213
+ mgr.where relation[:name].lt("fake_name")
214
+ _(mgr.to_sql).must_match %{"users"."name" < 'fake_name'}
215
+
216
+ current_time = ::Time.now
217
+ mgr.where relation[:created_at].lt(current_time)
218
+ _(mgr.to_sql).must_match %{"users"."created_at" < '#{current_time}'}
219
+ end
220
+ end
221
+
222
+ describe "#lt_any" do
223
+ it "should create a Grouping node" do
224
+ relation = Table.new(:users)
225
+ _(relation[:id].lt_any([1, 2])).must_be_kind_of Nodes::Grouping
226
+ end
227
+
228
+ it "should generate ORs in sql" do
229
+ relation = Table.new(:users)
230
+ mgr = relation.project relation[:id]
231
+ mgr.where relation[:id].lt_any([1, 2])
232
+ _(mgr.to_sql).must_be_like %{
233
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" < 1 OR "users"."id" < 2)
234
+ }
235
+ end
236
+ end
237
+
238
+ describe "#lt_all" do
239
+ it "should create a Grouping node" do
240
+ relation = Table.new(:users)
241
+ _(relation[:id].lt_all([1, 2])).must_be_kind_of Nodes::Grouping
242
+ end
243
+
244
+ it "should generate ANDs in sql" do
245
+ relation = Table.new(:users)
246
+ mgr = relation.project relation[:id]
247
+ mgr.where relation[:id].lt_all([1, 2])
248
+ _(mgr.to_sql).must_be_like %{
249
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" < 1 AND "users"."id" < 2)
250
+ }
251
+ end
252
+ end
253
+
254
+ describe "#lteq" do
255
+ it "should create a LessThanOrEqual node" do
256
+ relation = Table.new(:users)
257
+ _(relation[:id].lteq(10)).must_be_kind_of Nodes::LessThanOrEqual
258
+ end
259
+
260
+ it "should generate <= in sql" do
261
+ relation = Table.new(:users)
262
+ mgr = relation.project relation[:id]
263
+ mgr.where relation[:id].lteq(10)
264
+ _(mgr.to_sql).must_be_like %{
265
+ SELECT "users"."id" FROM "users" WHERE "users"."id" <= 10
266
+ }
267
+ end
268
+
269
+ it "should accept various data types." do
270
+ relation = Table.new(:users)
271
+ mgr = relation.project relation[:id]
272
+ mgr.where relation[:name].lteq("fake_name")
273
+ _(mgr.to_sql).must_match %{"users"."name" <= 'fake_name'}
274
+
275
+ current_time = ::Time.now
276
+ mgr.where relation[:created_at].lteq(current_time)
277
+ _(mgr.to_sql).must_match %{"users"."created_at" <= '#{current_time}'}
278
+ end
279
+ end
280
+
281
+ describe "#lteq_any" do
282
+ it "should create a Grouping node" do
283
+ relation = Table.new(:users)
284
+ _(relation[:id].lteq_any([1, 2])).must_be_kind_of Nodes::Grouping
285
+ end
286
+
287
+ it "should generate ORs in sql" do
288
+ relation = Table.new(:users)
289
+ mgr = relation.project relation[:id]
290
+ mgr.where relation[:id].lteq_any([1, 2])
291
+ _(mgr.to_sql).must_be_like %{
292
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" <= 1 OR "users"."id" <= 2)
293
+ }
294
+ end
295
+ end
296
+
297
+ describe "#lteq_all" do
298
+ it "should create a Grouping node" do
299
+ relation = Table.new(:users)
300
+ _(relation[:id].lteq_all([1, 2])).must_be_kind_of Nodes::Grouping
301
+ end
302
+
303
+ it "should generate ANDs in sql" do
304
+ relation = Table.new(:users)
305
+ mgr = relation.project relation[:id]
306
+ mgr.where relation[:id].lteq_all([1, 2])
307
+ _(mgr.to_sql).must_be_like %{
308
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" <= 1 AND "users"."id" <= 2)
309
+ }
310
+ end
311
+ end
312
+
313
+ describe "#average" do
314
+ it "should create a AVG node" do
315
+ relation = Table.new(:users)
316
+ _(relation[:id].average).must_be_kind_of Nodes::Avg
317
+ end
318
+
319
+ it "should generate the proper SQL" do
320
+ relation = Table.new(:users)
321
+ mgr = relation.project relation[:id].average
322
+ _(mgr.to_sql).must_be_like %{
323
+ SELECT AVG("users"."id")
324
+ FROM "users"
325
+ }
326
+ end
327
+ end
328
+
329
+ describe "#maximum" do
330
+ it "should create a MAX node" do
331
+ relation = Table.new(:users)
332
+ _(relation[:id].maximum).must_be_kind_of Nodes::Max
333
+ end
334
+
335
+ it "should generate proper SQL" do
336
+ relation = Table.new(:users)
337
+ mgr = relation.project relation[:id].maximum
338
+ _(mgr.to_sql).must_be_like %{
339
+ SELECT MAX("users"."id")
340
+ FROM "users"
341
+ }
342
+ end
343
+ end
344
+
345
+ describe "#minimum" do
346
+ it "should create a Min node" do
347
+ relation = Table.new(:users)
348
+ _(relation[:id].minimum).must_be_kind_of Nodes::Min
349
+ end
350
+
351
+ it "should generate proper SQL" do
352
+ relation = Table.new(:users)
353
+ mgr = relation.project relation[:id].minimum
354
+ _(mgr.to_sql).must_be_like %{
355
+ SELECT MIN("users"."id")
356
+ FROM "users"
357
+ }
358
+ end
359
+ end
360
+
361
+ describe "#sum" do
362
+ it "should create a SUM node" do
363
+ relation = Table.new(:users)
364
+ _(relation[:id].sum).must_be_kind_of Nodes::Sum
365
+ end
366
+
367
+ it "should generate the proper SQL" do
368
+ relation = Table.new(:users)
369
+ mgr = relation.project relation[:id].sum
370
+ _(mgr.to_sql).must_be_like %{
371
+ SELECT SUM("users"."id")
372
+ FROM "users"
373
+ }
374
+ end
375
+ end
376
+
377
+ describe "#count" do
378
+ it "should return a count node" do
379
+ relation = Table.new(:users)
380
+ _(relation[:id].count).must_be_kind_of Nodes::Count
381
+ end
382
+
383
+ it "should take a distinct param" do
384
+ relation = Table.new(:users)
385
+ count = relation[:id].count(nil)
386
+ _(count).must_be_kind_of Nodes::Count
387
+ _(count.distinct).must_be_nil
388
+ end
389
+ end
390
+
391
+ describe "#eq" do
392
+ it "should return an equality node" do
393
+ attribute = Attribute.new nil, nil
394
+ equality = attribute.eq 1
395
+ _(equality.left).must_equal attribute
396
+ _(equality.right.value).must_equal 1
397
+ _(equality).must_be_kind_of Nodes::Equality
398
+ end
399
+
400
+ it "should generate = in sql" do
401
+ relation = Table.new(:users)
402
+ mgr = relation.project relation[:id]
403
+ mgr.where relation[:id].eq(10)
404
+ _(mgr.to_sql).must_be_like %{
405
+ SELECT "users"."id" FROM "users" WHERE "users"."id" = 10
406
+ }
407
+ end
408
+
409
+ it "should handle nil" do
410
+ relation = Table.new(:users)
411
+ mgr = relation.project relation[:id]
412
+ mgr.where relation[:id].eq(nil)
413
+ _(mgr.to_sql).must_be_like %{
414
+ SELECT "users"."id" FROM "users" WHERE "users"."id" IS NULL
415
+ }
416
+ end
417
+ end
418
+
419
+ describe "#eq_any" do
420
+ it "should create a Grouping node" do
421
+ relation = Table.new(:users)
422
+ _(relation[:id].eq_any([1, 2])).must_be_kind_of Nodes::Grouping
423
+ end
424
+
425
+ it "should generate ORs in sql" do
426
+ relation = Table.new(:users)
427
+ mgr = relation.project relation[:id]
428
+ mgr.where relation[:id].eq_any([1, 2])
429
+ _(mgr.to_sql).must_be_like %{
430
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" = 1 OR "users"."id" = 2)
431
+ }
432
+ end
433
+
434
+ it "should not eat input" do
435
+ relation = Table.new(:users)
436
+ mgr = relation.project relation[:id]
437
+ values = [1, 2]
438
+ mgr.where relation[:id].eq_any(values)
439
+ _(values).must_equal [1, 2]
440
+ end
441
+ end
442
+
443
+ describe "#eq_all" do
444
+ it "should create a Grouping node" do
445
+ relation = Table.new(:users)
446
+ _(relation[:id].eq_all([1, 2])).must_be_kind_of Nodes::Grouping
447
+ end
448
+
449
+ it "should generate ANDs in sql" do
450
+ relation = Table.new(:users)
451
+ mgr = relation.project relation[:id]
452
+ mgr.where relation[:id].eq_all([1, 2])
453
+ _(mgr.to_sql).must_be_like %{
454
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" = 1 AND "users"."id" = 2)
455
+ }
456
+ end
457
+
458
+ it "should not eat input" do
459
+ relation = Table.new(:users)
460
+ mgr = relation.project relation[:id]
461
+ values = [1, 2]
462
+ mgr.where relation[:id].eq_all(values)
463
+ _(values).must_equal [1, 2]
464
+ end
465
+ end
466
+
467
+ describe "#matches" do
468
+ it "should create a Matches node" do
469
+ relation = Table.new(:users)
470
+ _(relation[:name].matches("%bacon%")).must_be_kind_of Nodes::Matches
471
+ end
472
+
473
+ it "should generate LIKE in sql" do
474
+ relation = Table.new(:users)
475
+ mgr = relation.project relation[:id]
476
+ mgr.where relation[:name].matches("%bacon%")
477
+ _(mgr.to_sql).must_be_like %{
478
+ SELECT "users"."id" FROM "users" WHERE "users"."name" LIKE '%bacon%'
479
+ }
480
+ end
481
+ end
482
+
483
+ describe "#matches_any" do
484
+ it "should create a Grouping node" do
485
+ relation = Table.new(:users)
486
+ _(relation[:name].matches_any(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
487
+ end
488
+
489
+ it "should generate ORs in sql" do
490
+ relation = Table.new(:users)
491
+ mgr = relation.project relation[:id]
492
+ mgr.where relation[:name].matches_any(["%chunky%", "%bacon%"])
493
+ _(mgr.to_sql).must_be_like %{
494
+ SELECT "users"."id" FROM "users" WHERE ("users"."name" LIKE '%chunky%' OR "users"."name" LIKE '%bacon%')
495
+ }
496
+ end
497
+ end
498
+
499
+ describe "#matches_all" do
500
+ it "should create a Grouping node" do
501
+ relation = Table.new(:users)
502
+ _(relation[:name].matches_all(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
503
+ end
504
+
505
+ it "should generate ANDs in sql" do
506
+ relation = Table.new(:users)
507
+ mgr = relation.project relation[:id]
508
+ mgr.where relation[:name].matches_all(["%chunky%", "%bacon%"])
509
+ _(mgr.to_sql).must_be_like %{
510
+ SELECT "users"."id" FROM "users" WHERE ("users"."name" LIKE '%chunky%' AND "users"."name" LIKE '%bacon%')
511
+ }
512
+ end
513
+ end
514
+
515
+ describe "#does_not_match" do
516
+ it "should create a DoesNotMatch node" do
517
+ relation = Table.new(:users)
518
+ _(relation[:name].does_not_match("%bacon%")).must_be_kind_of Nodes::DoesNotMatch
519
+ end
520
+
521
+ it "should generate NOT LIKE in sql" do
522
+ relation = Table.new(:users)
523
+ mgr = relation.project relation[:id]
524
+ mgr.where relation[:name].does_not_match("%bacon%")
525
+ _(mgr.to_sql).must_be_like %{
526
+ SELECT "users"."id" FROM "users" WHERE "users"."name" NOT LIKE '%bacon%'
527
+ }
528
+ end
529
+ end
530
+
531
+ describe "#does_not_match_any" do
532
+ it "should create a Grouping node" do
533
+ relation = Table.new(:users)
534
+ _(relation[:name].does_not_match_any(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
535
+ end
536
+
537
+ it "should generate ORs in sql" do
538
+ relation = Table.new(:users)
539
+ mgr = relation.project relation[:id]
540
+ mgr.where relation[:name].does_not_match_any(["%chunky%", "%bacon%"])
541
+ _(mgr.to_sql).must_be_like %{
542
+ SELECT "users"."id" FROM "users" WHERE ("users"."name" NOT LIKE '%chunky%' OR "users"."name" NOT LIKE '%bacon%')
543
+ }
544
+ end
545
+ end
546
+
547
+ describe "#does_not_match_all" do
548
+ it "should create a Grouping node" do
549
+ relation = Table.new(:users)
550
+ _(relation[:name].does_not_match_all(["%chunky%", "%bacon%"])).must_be_kind_of Nodes::Grouping
551
+ end
552
+
553
+ it "should generate ANDs in sql" do
554
+ relation = Table.new(:users)
555
+ mgr = relation.project relation[:id]
556
+ mgr.where relation[:name].does_not_match_all(["%chunky%", "%bacon%"])
557
+ _(mgr.to_sql).must_be_like %{
558
+ SELECT "users"."id" FROM "users" WHERE ("users"."name" NOT LIKE '%chunky%' AND "users"."name" NOT LIKE '%bacon%')
559
+ }
560
+ end
561
+ end
562
+
563
+ describe "#between" do
564
+ it "can be constructed with a standard range" do
565
+ attribute = Attribute.new nil, nil
566
+ node = attribute.between(1..3)
567
+
568
+ _(node).must_equal Nodes::Between.new(
569
+ attribute,
570
+ Nodes::And.new([
571
+ Nodes::Casted.new(1, attribute),
572
+ Nodes::Casted.new(3, attribute)
573
+ ])
574
+ )
575
+ end
576
+
577
+ it "can be constructed with a range starting from -Infinity" do
578
+ attribute = Attribute.new nil, nil
579
+ node = attribute.between(-::Float::INFINITY..3)
580
+
581
+ _(node).must_equal Nodes::LessThanOrEqual.new(
582
+ attribute,
583
+ Nodes::Casted.new(3, attribute)
584
+ )
585
+ end
586
+
587
+ it "can be constructed with a quoted range starting from -Infinity" do
588
+ attribute = Attribute.new nil, nil
589
+ node = attribute.between(quoted_range(-::Float::INFINITY, 3, false))
590
+
591
+ _(node).must_equal Nodes::LessThanOrEqual.new(
592
+ attribute,
593
+ Nodes::Quoted.new(3)
594
+ )
595
+ end
596
+
597
+ it "can be constructed with an exclusive range starting from -Infinity" do
598
+ attribute = Attribute.new nil, nil
599
+ node = attribute.between(-::Float::INFINITY...3)
600
+
601
+ _(node).must_equal Nodes::LessThan.new(
602
+ attribute,
603
+ Nodes::Casted.new(3, attribute)
604
+ )
605
+ end
606
+
607
+ it "can be constructed with a quoted exclusive range starting from -Infinity" do
608
+ attribute = Attribute.new nil, nil
609
+ node = attribute.between(quoted_range(-::Float::INFINITY, 3, true))
610
+
611
+ _(node).must_equal Nodes::LessThan.new(
612
+ attribute,
613
+ Nodes::Quoted.new(3)
614
+ )
615
+ end
616
+
617
+ it "can be constructed with an infinite range" do
618
+ attribute = Attribute.new nil, nil
619
+ node = attribute.between(-::Float::INFINITY..::Float::INFINITY)
620
+
621
+ _(node).must_equal Nodes::NotIn.new(attribute, [])
622
+ end
623
+
624
+ it "can be constructed with a quoted infinite range" do
625
+ attribute = Attribute.new nil, nil
626
+ node = attribute.between(quoted_range(-::Float::INFINITY, ::Float::INFINITY, false))
627
+
628
+ _(node).must_equal Nodes::NotIn.new(attribute, [])
629
+ end
630
+
631
+ it "can be constructed with a range ending at Infinity" do
632
+ attribute = Attribute.new nil, nil
633
+ node = attribute.between(0..::Float::INFINITY)
634
+
635
+ _(node).must_equal Nodes::GreaterThanOrEqual.new(
636
+ attribute,
637
+ Nodes::Casted.new(0, attribute)
638
+ )
639
+ end
640
+
641
+ if RUBY_VERSION >= "2.7"
642
+ it "can be constructed with a range implicitly starting at Infinity" do
643
+ attribute = Attribute.new nil, nil
644
+ node = attribute.between(eval("..0")) # eval for backwards compatibility
645
+
646
+ _(node).must_equal Nodes::LessThanOrEqual.new(
647
+ attribute,
648
+ Nodes::Casted.new(0, attribute)
649
+ )
650
+ end
651
+ end
652
+
653
+ if RUBY_VERSION >= "2.6"
654
+ it "can be constructed with a range implicitly ending at Infinity" do
655
+ attribute = Attribute.new nil, nil
656
+ node = attribute.between(eval("0..")) # Use eval for compatibility with Ruby < 2.6 parser
657
+
658
+ _(node).must_equal Nodes::GreaterThanOrEqual.new(
659
+ attribute,
660
+ Nodes::Casted.new(0, attribute)
661
+ )
662
+ end
663
+ end
664
+
665
+ it "can be constructed with a quoted range ending at Infinity" do
666
+ attribute = Attribute.new nil, nil
667
+ node = attribute.between(quoted_range(0, ::Float::INFINITY, false))
668
+
669
+ _(node).must_equal Nodes::GreaterThanOrEqual.new(
670
+ attribute,
671
+ Nodes::Quoted.new(0)
672
+ )
673
+ end
674
+
675
+ it "can be constructed with an exclusive range" do
676
+ attribute = Attribute.new nil, nil
677
+ node = attribute.between(0...3)
678
+
679
+ _(node).must_equal Nodes::And.new([
680
+ Nodes::GreaterThanOrEqual.new(
681
+ attribute,
682
+ Nodes::Casted.new(0, attribute)
683
+ ),
684
+ Nodes::LessThan.new(
685
+ attribute,
686
+ Nodes::Casted.new(3, attribute)
687
+ )
688
+ ])
689
+ end
690
+ end
691
+
692
+ describe "#in" do
693
+ it "can be constructed with a subquery" do
694
+ relation = Table.new(:users)
695
+ mgr = relation.project relation[:id]
696
+ mgr.where relation[:name].does_not_match_all(["%chunky%", "%bacon%"])
697
+ attribute = Attribute.new nil, nil
698
+
699
+ node = attribute.in(mgr)
700
+
701
+ _(node).must_equal Nodes::In.new(attribute, mgr.ast)
702
+ end
703
+
704
+ it "can be constructed with a list" do
705
+ attribute = Attribute.new nil, nil
706
+ node = attribute.in([1, 2, 3])
707
+
708
+ _(node).must_equal Nodes::In.new(
709
+ attribute,
710
+ [
711
+ Nodes::Casted.new(1, attribute),
712
+ Nodes::Casted.new(2, attribute),
713
+ Nodes::Casted.new(3, attribute),
714
+ ]
715
+ )
716
+ end
717
+
718
+ it "can be constructed with a random object" do
719
+ attribute = Attribute.new nil, nil
720
+ random_object = Object.new
721
+ node = attribute.in(random_object)
722
+
723
+ _(node).must_equal Nodes::In.new(
724
+ attribute,
725
+ Nodes::Casted.new(random_object, attribute)
726
+ )
727
+ end
728
+
729
+ it "should generate IN in sql" do
730
+ relation = Table.new(:users)
731
+ mgr = relation.project relation[:id]
732
+ mgr.where relation[:id].in([1, 2, 3])
733
+ _(mgr.to_sql).must_be_like %{
734
+ SELECT "users"."id" FROM "users" WHERE "users"."id" IN (1, 2, 3)
735
+ }
736
+ end
737
+ end
738
+
739
+ describe "#in_any" do
740
+ it "should create a Grouping node" do
741
+ relation = Table.new(:users)
742
+ _(relation[:id].in_any([1, 2])).must_be_kind_of Nodes::Grouping
743
+ end
744
+
745
+ it "should generate ORs in sql" do
746
+ relation = Table.new(:users)
747
+ mgr = relation.project relation[:id]
748
+ mgr.where relation[:id].in_any([[1, 2], [3, 4]])
749
+ _(mgr.to_sql).must_be_like %{
750
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" IN (1, 2) OR "users"."id" IN (3, 4))
751
+ }
752
+ end
753
+ end
754
+
755
+ describe "#in_all" do
756
+ it "should create a Grouping node" do
757
+ relation = Table.new(:users)
758
+ _(relation[:id].in_all([1, 2])).must_be_kind_of Nodes::Grouping
759
+ end
760
+
761
+ it "should generate ANDs in sql" do
762
+ relation = Table.new(:users)
763
+ mgr = relation.project relation[:id]
764
+ mgr.where relation[:id].in_all([[1, 2], [3, 4]])
765
+ _(mgr.to_sql).must_be_like %{
766
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" IN (1, 2) AND "users"."id" IN (3, 4))
767
+ }
768
+ end
769
+ end
770
+
771
+ describe "#not_between" do
772
+ it "can be constructed with a standard range" do
773
+ attribute = Attribute.new nil, nil
774
+ node = attribute.not_between(1..3)
775
+
776
+ _(node).must_equal Nodes::Grouping.new(
777
+ Nodes::Or.new(
778
+ Nodes::LessThan.new(
779
+ attribute,
780
+ Nodes::Casted.new(1, attribute)
781
+ ),
782
+ Nodes::GreaterThan.new(
783
+ attribute,
784
+ Nodes::Casted.new(3, attribute)
785
+ )
786
+ )
787
+ )
788
+ end
789
+
790
+ it "can be constructed with a range starting from -Infinity" do
791
+ attribute = Attribute.new nil, nil
792
+ node = attribute.not_between(-::Float::INFINITY..3)
793
+
794
+ _(node).must_equal Nodes::GreaterThan.new(
795
+ attribute,
796
+ Nodes::Casted.new(3, attribute)
797
+ )
798
+ end
799
+
800
+ it "can be constructed with a quoted range starting from -Infinity" do
801
+ attribute = Attribute.new nil, nil
802
+ node = attribute.not_between(quoted_range(-::Float::INFINITY, 3, false))
803
+
804
+ _(node).must_equal Nodes::GreaterThan.new(
805
+ attribute,
806
+ Nodes::Quoted.new(3)
807
+ )
808
+ end
809
+
810
+ it "can be constructed with an exclusive range starting from -Infinity" do
811
+ attribute = Attribute.new nil, nil
812
+ node = attribute.not_between(-::Float::INFINITY...3)
813
+
814
+ _(node).must_equal Nodes::GreaterThanOrEqual.new(
815
+ attribute,
816
+ Nodes::Casted.new(3, attribute)
817
+ )
818
+ end
819
+
820
+ it "can be constructed with a quoted exclusive range starting from -Infinity" do
821
+ attribute = Attribute.new nil, nil
822
+ node = attribute.not_between(quoted_range(-::Float::INFINITY, 3, true))
823
+
824
+ _(node).must_equal Nodes::GreaterThanOrEqual.new(
825
+ attribute,
826
+ Nodes::Quoted.new(3)
827
+ )
828
+ end
829
+
830
+ it "can be constructed with an infinite range" do
831
+ attribute = Attribute.new nil, nil
832
+ node = attribute.not_between(-::Float::INFINITY..::Float::INFINITY)
833
+
834
+ _(node).must_equal Nodes::In.new(attribute, [])
835
+ end
836
+
837
+ it "can be constructed with a quoted infinite range" do
838
+ attribute = Attribute.new nil, nil
839
+ node = attribute.not_between(quoted_range(-::Float::INFINITY, ::Float::INFINITY, false))
840
+
841
+ _(node).must_equal Nodes::In.new(attribute, [])
842
+ end
843
+
844
+ it "can be constructed with a range ending at Infinity" do
845
+ attribute = Attribute.new nil, nil
846
+ node = attribute.not_between(0..::Float::INFINITY)
847
+
848
+ _(node).must_equal Nodes::LessThan.new(
849
+ attribute,
850
+ Nodes::Casted.new(0, attribute)
851
+ )
852
+ end
853
+
854
+ if RUBY_VERSION >= "2.7"
855
+ it "can be constructed with a range implicitly starting at Infinity" do
856
+ attribute = Attribute.new nil, nil
857
+ node = attribute.not_between(eval("..0")) # eval for backwards compatibility
858
+
859
+ _(node).must_equal Nodes::GreaterThan.new(
860
+ attribute,
861
+ Nodes::Casted.new(0, attribute)
862
+ )
863
+ end
864
+ end
865
+
866
+ if RUBY_VERSION >= "2.6"
867
+ it "can be constructed with a range implicitly ending at Infinity" do
868
+ attribute = Attribute.new nil, nil
869
+ node = attribute.not_between(eval("0..")) # Use eval for compatibility with Ruby < 2.6 parser
870
+
871
+ _(node).must_equal Nodes::LessThan.new(
872
+ attribute,
873
+ Nodes::Casted.new(0, attribute)
874
+ )
875
+ end
876
+ end
877
+
878
+ it "can be constructed with a quoted range ending at Infinity" do
879
+ attribute = Attribute.new nil, nil
880
+ node = attribute.not_between(quoted_range(0, ::Float::INFINITY, false))
881
+
882
+ _(node).must_equal Nodes::LessThan.new(
883
+ attribute,
884
+ Nodes::Quoted.new(0)
885
+ )
886
+ end
887
+
888
+ it "can be constructed with an exclusive range" do
889
+ attribute = Attribute.new nil, nil
890
+ node = attribute.not_between(0...3)
891
+
892
+ _(node).must_equal Nodes::Grouping.new(
893
+ Nodes::Or.new(
894
+ Nodes::LessThan.new(
895
+ attribute,
896
+ Nodes::Casted.new(0, attribute)
897
+ ),
898
+ Nodes::GreaterThanOrEqual.new(
899
+ attribute,
900
+ Nodes::Casted.new(3, attribute)
901
+ )
902
+ )
903
+ )
904
+ end
905
+ end
906
+
907
+ describe "#not_in" do
908
+ it "can be constructed with a subquery" do
909
+ relation = Table.new(:users)
910
+ mgr = relation.project relation[:id]
911
+ mgr.where relation[:name].does_not_match_all(["%chunky%", "%bacon%"])
912
+ attribute = Attribute.new nil, nil
913
+
914
+ node = attribute.not_in(mgr)
915
+
916
+ _(node).must_equal Nodes::NotIn.new(attribute, mgr.ast)
917
+ end
918
+
919
+ it "can be constructed with a Union" do
920
+ relation = Table.new(:users)
921
+ mgr1 = relation.project(relation[:id])
922
+ mgr2 = relation.project(relation[:id])
923
+
924
+ union = mgr1.union(mgr2)
925
+ node = relation[:id].in(union)
926
+ _(node.to_sql).must_be_like %{
927
+ "users"."id" IN (( SELECT "users"."id" FROM "users" UNION SELECT "users"."id" FROM "users" ))
928
+ }
929
+ end
930
+
931
+ it "can be constructed with a list" do
932
+ attribute = Attribute.new nil, nil
933
+ node = attribute.not_in([1, 2, 3])
934
+
935
+ _(node).must_equal Nodes::NotIn.new(
936
+ attribute,
937
+ [
938
+ Nodes::Casted.new(1, attribute),
939
+ Nodes::Casted.new(2, attribute),
940
+ Nodes::Casted.new(3, attribute),
941
+ ]
942
+ )
943
+ end
944
+
945
+ it "can be constructed with a random object" do
946
+ attribute = Attribute.new nil, nil
947
+ random_object = Object.new
948
+ node = attribute.not_in(random_object)
949
+
950
+ _(node).must_equal Nodes::NotIn.new(
951
+ attribute,
952
+ Nodes::Casted.new(random_object, attribute)
953
+ )
954
+ end
955
+
956
+ it "should generate NOT IN in sql" do
957
+ relation = Table.new(:users)
958
+ mgr = relation.project relation[:id]
959
+ mgr.where relation[:id].not_in([1, 2, 3])
960
+ _(mgr.to_sql).must_be_like %{
961
+ SELECT "users"."id" FROM "users" WHERE "users"."id" NOT IN (1, 2, 3)
962
+ }
963
+ end
964
+ end
965
+
966
+ describe "#not_in_any" do
967
+ it "should create a Grouping node" do
968
+ relation = Table.new(:users)
969
+ _(relation[:id].not_in_any([1, 2])).must_be_kind_of Nodes::Grouping
970
+ end
971
+
972
+ it "should generate ORs in sql" do
973
+ relation = Table.new(:users)
974
+ mgr = relation.project relation[:id]
975
+ mgr.where relation[:id].not_in_any([[1, 2], [3, 4]])
976
+ _(mgr.to_sql).must_be_like %{
977
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" NOT IN (1, 2) OR "users"."id" NOT IN (3, 4))
978
+ }
979
+ end
980
+ end
981
+
982
+ describe "#not_in_all" do
983
+ it "should create a Grouping node" do
984
+ relation = Table.new(:users)
985
+ _(relation[:id].not_in_all([1, 2])).must_be_kind_of Nodes::Grouping
986
+ end
987
+
988
+ it "should generate ANDs in sql" do
989
+ relation = Table.new(:users)
990
+ mgr = relation.project relation[:id]
991
+ mgr.where relation[:id].not_in_all([[1, 2], [3, 4]])
992
+ _(mgr.to_sql).must_be_like %{
993
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" NOT IN (1, 2) AND "users"."id" NOT IN (3, 4))
994
+ }
995
+ end
996
+ end
997
+
998
+ describe "#eq_all" do
999
+ it "should create a Grouping node" do
1000
+ relation = Table.new(:users)
1001
+ _(relation[:id].eq_all([1, 2])).must_be_kind_of Nodes::Grouping
1002
+ end
1003
+
1004
+ it "should generate ANDs in sql" do
1005
+ relation = Table.new(:users)
1006
+ mgr = relation.project relation[:id]
1007
+ mgr.where relation[:id].eq_all([1, 2])
1008
+ _(mgr.to_sql).must_be_like %{
1009
+ SELECT "users"."id" FROM "users" WHERE ("users"."id" = 1 AND "users"."id" = 2)
1010
+ }
1011
+ end
1012
+ end
1013
+
1014
+ describe "#asc" do
1015
+ it "should create an Ascending node" do
1016
+ relation = Table.new(:users)
1017
+ _(relation[:id].asc).must_be_kind_of Nodes::Ascending
1018
+ end
1019
+
1020
+ it "should generate ASC in sql" do
1021
+ relation = Table.new(:users)
1022
+ mgr = relation.project relation[:id]
1023
+ mgr.order relation[:id].asc
1024
+ _(mgr.to_sql).must_be_like %{
1025
+ SELECT "users"."id" FROM "users" ORDER BY "users"."id" ASC
1026
+ }
1027
+ end
1028
+ end
1029
+
1030
+ describe "#desc" do
1031
+ it "should create a Descending node" do
1032
+ relation = Table.new(:users)
1033
+ _(relation[:id].desc).must_be_kind_of Nodes::Descending
1034
+ end
1035
+
1036
+ it "should generate DESC in sql" do
1037
+ relation = Table.new(:users)
1038
+ mgr = relation.project relation[:id]
1039
+ mgr.order relation[:id].desc
1040
+ _(mgr.to_sql).must_be_like %{
1041
+ SELECT "users"."id" FROM "users" ORDER BY "users"."id" DESC
1042
+ }
1043
+ end
1044
+ end
1045
+
1046
+ describe "#contains" do
1047
+ it "should create a Contains node" do
1048
+ relation = Table.new(:products)
1049
+ _(relation[:tags].contains(["foo", "bar"])).must_be_kind_of Nodes::Contains
1050
+ end
1051
+
1052
+ it "should generate @> in sql" do
1053
+ relation = Table.new(:products, type_caster: fake_pg_caster)
1054
+ mgr = relation.project relation[:id]
1055
+ mgr.where relation[:tags].contains(["foo", "bar"])
1056
+ _(mgr.to_sql).must_be_like %{ SELECT "products"."id" FROM "products" WHERE "products"."tags" @> '{foo,bar}' }
1057
+ end
1058
+ end
1059
+
1060
+ describe "#overlaps" do
1061
+ it "should create an Overlaps node" do
1062
+ relation = Table.new(:products)
1063
+ _(relation[:tags].overlaps(["foo", "bar"])).must_be_kind_of Nodes::Overlaps
1064
+ end
1065
+
1066
+ it "should generate && in sql" do
1067
+ relation = Table.new(:products, type_caster: fake_pg_caster)
1068
+ mgr = relation.project relation[:id]
1069
+ mgr.where relation[:tags].overlaps(["foo", "bar"])
1070
+ _(mgr.to_sql).must_be_like %{ SELECT "products"."id" FROM "products" WHERE "products"."tags" && '{foo,bar}' }
1071
+ end
1072
+ end
1073
+
1074
+ describe "equality" do
1075
+ describe "#to_sql" do
1076
+ it "should produce sql" do
1077
+ table = Table.new :users
1078
+ condition = table["id"].eq 1
1079
+ _(condition.to_sql).must_equal '"users"."id" = 1'
1080
+ end
1081
+ end
1082
+ end
1083
+
1084
+ describe "type casting" do
1085
+ it "does not type cast by default" do
1086
+ table = Table.new(:foo)
1087
+ condition = table["id"].eq("1")
1088
+
1089
+ assert_not table.able_to_type_cast?
1090
+ _(condition.to_sql).must_equal %("foo"."id" = '1')
1091
+ end
1092
+
1093
+ it "type casts when given an explicit caster" do
1094
+ fake_caster = Object.new
1095
+ def fake_caster.type_cast_for_database(attr_name, value)
1096
+ if attr_name == "id"
1097
+ value.to_i
1098
+ else
1099
+ value
1100
+ end
1101
+ end
1102
+ table = Table.new(:foo, type_caster: fake_caster)
1103
+ condition = table["id"].eq("1").and(table["other_id"].eq("2"))
1104
+
1105
+ assert table.able_to_type_cast?
1106
+ _(condition.to_sql).must_equal %("foo"."id" = 1 AND "foo"."other_id" = '2')
1107
+ end
1108
+
1109
+ it "does not type cast SqlLiteral nodes" do
1110
+ fake_caster = Object.new
1111
+ def fake_caster.type_cast_for_database(attr_name, value)
1112
+ value.to_i
1113
+ end
1114
+ table = Table.new(:foo, type_caster: fake_caster)
1115
+ condition = table["id"].eq(Arel.sql("(select 1)"))
1116
+
1117
+ assert table.able_to_type_cast?
1118
+ _(condition.to_sql).must_equal %("foo"."id" = (select 1))
1119
+ end
1120
+ end
1121
+
1122
+ private
1123
+ def quoted_range(begin_val, end_val, exclude)
1124
+ OpenStruct.new(
1125
+ begin: Nodes::Quoted.new(begin_val),
1126
+ end: Nodes::Quoted.new(end_val),
1127
+ exclude_end?: exclude,
1128
+ )
1129
+ end
1130
+
1131
+ # Mimic PG::TextDecoder::Array casting
1132
+ def fake_pg_caster
1133
+ Object.new.tap do |caster|
1134
+ def caster.type_cast_for_database(attr_name, value)
1135
+ if attr_name == "tags"
1136
+ "{#{value.join(",")}}"
1137
+ else
1138
+ value
1139
+ end
1140
+ end
1141
+ end
1142
+ end
1143
+ end
1144
+ end
1145
+ end