ibm_db 5.1.0 → 5.6.1

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 (626) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +29 -0
  3. data/LICENSE +55 -18
  4. data/README +4 -2
  5. data/ext/Makefile +26 -23
  6. data/ext/extconf.rb +32 -34
  7. data/ext/ibm_db.c +40 -54
  8. data/ext/ibm_db.o +0 -0
  9. data/ext/ibm_db.so +0 -0
  10. data/ext/mkmf.log +16 -17
  11. data/ext/ruby_ibm_db_cli.c +2 -1
  12. data/ext/ruby_ibm_db_cli.h +8 -0
  13. data/ext/ruby_ibm_db_cli.o +0 -0
  14. data/lib/IBM_DB.rb +1 -1
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3168 -2354
  16. data/test/active_record/connection_adapters/fake_adapter.rb +5 -2
  17. data/test/activejob/destroy_association_async_test.rb +305 -0
  18. data/test/activejob/destroy_async_job_not_present_test.rb +31 -0
  19. data/test/activejob/helper.rb +15 -0
  20. data/test/assets/schema_dump_5_1.yml +345 -0
  21. data/test/cases/adapter_prevent_writes_test.rb +334 -0
  22. data/test/cases/adapter_test.rb +432 -218
  23. data/test/cases/adapters/mysql2/active_schema_test.rb +85 -75
  24. data/test/cases/adapters/mysql2/auto_increment_test.rb +34 -0
  25. data/test/cases/adapters/mysql2/bind_parameter_test.rb +5 -3
  26. data/test/cases/adapters/mysql2/boolean_test.rb +6 -4
  27. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +26 -24
  28. data/test/cases/adapters/mysql2/charset_collation_test.rb +20 -17
  29. data/test/cases/adapters/mysql2/connection_test.rb +48 -50
  30. data/test/cases/adapters/mysql2/count_deleted_rows_with_lock_test.rb +28 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +23 -19
  32. data/test/cases/adapters/mysql2/enum_test.rb +32 -11
  33. data/test/cases/adapters/mysql2/explain_test.rb +13 -11
  34. data/test/cases/adapters/mysql2/json_test.rb +17 -188
  35. data/test/cases/adapters/mysql2/mysql2_adapter_prevent_writes_test.rb +208 -0
  36. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +183 -28
  37. data/test/cases/adapters/mysql2/nested_deadlock_test.rb +75 -0
  38. data/test/cases/adapters/mysql2/optimizer_hints_test.rb +69 -0
  39. data/test/cases/adapters/mysql2/schema_migrations_test.rb +26 -21
  40. data/test/cases/adapters/mysql2/schema_test.rb +24 -22
  41. data/test/cases/adapters/mysql2/set_test.rb +32 -0
  42. data/test/cases/adapters/mysql2/sp_test.rb +10 -8
  43. data/test/cases/adapters/mysql2/sql_types_test.rb +8 -6
  44. data/test/cases/adapters/mysql2/table_options_test.rb +93 -10
  45. data/test/cases/adapters/mysql2/transaction_test.rb +151 -0
  46. data/test/cases/adapters/mysql2/unsigned_type_test.rb +11 -9
  47. data/test/cases/adapters/mysql2/virtual_column_test.rb +66 -0
  48. data/test/cases/adapters/postgresql/active_schema_test.rb +40 -25
  49. data/test/cases/adapters/postgresql/array_test.rb +118 -63
  50. data/test/cases/adapters/postgresql/bit_string_test.rb +12 -10
  51. data/test/cases/adapters/postgresql/bytea_test.rb +26 -25
  52. data/test/cases/adapters/postgresql/case_insensitive_test.rb +10 -9
  53. data/test/cases/adapters/postgresql/change_schema_test.rb +7 -5
  54. data/test/cases/adapters/postgresql/cidr_test.rb +2 -0
  55. data/test/cases/adapters/postgresql/citext_test.rb +58 -58
  56. data/test/cases/adapters/postgresql/collation_test.rb +17 -15
  57. data/test/cases/adapters/postgresql/composite_test.rb +25 -23
  58. data/test/cases/adapters/postgresql/connection_test.rb +73 -85
  59. data/test/cases/adapters/postgresql/create_unlogged_tables_test.rb +74 -0
  60. data/test/cases/adapters/postgresql/datatype_test.rb +19 -22
  61. data/test/cases/adapters/postgresql/date_test.rb +42 -0
  62. data/test/cases/adapters/postgresql/domain_test.rb +9 -7
  63. data/test/cases/adapters/postgresql/enum_test.rb +12 -10
  64. data/test/cases/adapters/postgresql/explain_test.rb +10 -8
  65. data/test/cases/adapters/postgresql/extension_migration_test.rb +13 -12
  66. data/test/cases/adapters/postgresql/foreign_table_test.rb +109 -0
  67. data/test/cases/adapters/postgresql/full_text_test.rb +8 -6
  68. data/test/cases/adapters/postgresql/geometric_test.rb +57 -63
  69. data/test/cases/adapters/postgresql/hstore_test.rb +288 -280
  70. data/test/cases/adapters/postgresql/infinity_test.rb +54 -15
  71. data/test/cases/adapters/postgresql/integer_test.rb +2 -0
  72. data/test/cases/adapters/postgresql/interval_test.rb +99 -0
  73. data/test/cases/adapters/postgresql/json_test.rb +16 -201
  74. data/test/cases/adapters/postgresql/ltree_test.rb +14 -16
  75. data/test/cases/adapters/postgresql/money_test.rb +47 -16
  76. data/test/cases/adapters/postgresql/network_test.rb +36 -28
  77. data/test/cases/adapters/postgresql/numbers_test.rb +7 -5
  78. data/test/cases/adapters/postgresql/optimizer_hints_test.rb +71 -0
  79. data/test/cases/adapters/postgresql/partitions_test.rb +22 -0
  80. data/test/cases/adapters/postgresql/postgresql_adapter_prevent_writes_test.rb +205 -0
  81. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +178 -136
  82. data/test/cases/adapters/postgresql/prepared_statements_disabled_test.rb +27 -0
  83. data/test/cases/adapters/postgresql/quoting_test.rb +12 -6
  84. data/test/cases/adapters/postgresql/range_test.rb +406 -292
  85. data/test/cases/adapters/postgresql/referential_integrity_test.rb +16 -15
  86. data/test/cases/adapters/postgresql/rename_table_test.rb +9 -8
  87. data/test/cases/adapters/postgresql/schema_authorization_test.rb +14 -23
  88. data/test/cases/adapters/postgresql/schema_test.rb +207 -91
  89. data/test/cases/adapters/postgresql/serial_test.rb +9 -7
  90. data/test/cases/adapters/postgresql/statement_pool_test.rb +26 -6
  91. data/test/cases/adapters/postgresql/timestamp_test.rb +17 -15
  92. data/test/cases/adapters/postgresql/transaction_nested_test.rb +114 -0
  93. data/test/cases/adapters/postgresql/transaction_test.rb +189 -0
  94. data/test/cases/adapters/postgresql/type_lookup_test.rb +12 -10
  95. data/test/cases/adapters/postgresql/utils_test.rb +11 -9
  96. data/test/cases/adapters/postgresql/uuid_test.rb +226 -109
  97. data/test/cases/adapters/postgresql/xml_test.rb +10 -14
  98. data/test/cases/adapters/sqlite3/collation_test.rb +26 -15
  99. data/test/cases/adapters/sqlite3/copy_table_test.rb +31 -28
  100. data/test/cases/adapters/sqlite3/explain_test.rb +13 -11
  101. data/test/cases/adapters/sqlite3/json_test.rb +29 -0
  102. data/test/cases/adapters/sqlite3/quoting_test.rb +35 -57
  103. data/test/cases/adapters/sqlite3/sqlite3_adapter_prevent_writes_test.rb +186 -0
  104. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +318 -131
  105. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +11 -11
  106. data/test/cases/adapters/sqlite3/statement_pool_test.rb +7 -6
  107. data/test/cases/adapters/sqlite3/transaction_test.rb +123 -0
  108. data/test/cases/aggregations_test.rb +14 -12
  109. data/test/cases/annotate_test.rb +46 -0
  110. data/test/cases/ar_schema_test.rb +153 -86
  111. data/test/cases/arel/attributes/attribute_test.rb +1145 -0
  112. data/test/cases/arel/attributes/math_test.rb +83 -0
  113. data/test/cases/arel/attributes_test.rb +27 -0
  114. data/test/cases/arel/collectors/bind_test.rb +40 -0
  115. data/test/cases/arel/collectors/composite_test.rb +47 -0
  116. data/test/cases/arel/collectors/sql_string_test.rb +41 -0
  117. data/test/cases/arel/collectors/substitute_bind_collector_test.rb +48 -0
  118. data/test/cases/arel/crud_test.rb +65 -0
  119. data/test/cases/arel/delete_manager_test.rb +53 -0
  120. data/test/cases/arel/factory_methods_test.rb +46 -0
  121. data/test/cases/arel/helper.rb +45 -0
  122. data/test/cases/arel/insert_manager_test.rb +241 -0
  123. data/test/cases/arel/nodes/and_test.rb +30 -0
  124. data/test/cases/arel/nodes/as_test.rb +36 -0
  125. data/test/cases/arel/nodes/ascending_test.rb +46 -0
  126. data/test/cases/arel/nodes/bin_test.rb +35 -0
  127. data/test/cases/arel/nodes/binary_test.rb +29 -0
  128. data/test/cases/arel/nodes/bind_param_test.rb +22 -0
  129. data/test/cases/arel/nodes/case_test.rb +96 -0
  130. data/test/cases/arel/nodes/casted_test.rb +18 -0
  131. data/test/cases/arel/nodes/comment_test.rb +22 -0
  132. data/test/cases/arel/nodes/count_test.rb +35 -0
  133. data/test/cases/arel/nodes/delete_statement_test.rb +36 -0
  134. data/test/cases/arel/nodes/descending_test.rb +46 -0
  135. data/test/cases/arel/nodes/distinct_test.rb +21 -0
  136. data/test/cases/arel/nodes/equality_test.rb +62 -0
  137. data/test/cases/arel/nodes/extract_test.rb +43 -0
  138. data/test/cases/arel/nodes/false_test.rb +21 -0
  139. data/test/cases/arel/nodes/grouping_test.rb +26 -0
  140. data/test/cases/arel/nodes/infix_operation_test.rb +42 -0
  141. data/test/cases/arel/nodes/insert_statement_test.rb +44 -0
  142. data/test/cases/arel/nodes/named_function_test.rb +48 -0
  143. data/test/cases/arel/nodes/node_test.rb +22 -0
  144. data/test/cases/arel/nodes/not_test.rb +31 -0
  145. data/test/cases/arel/nodes/or_test.rb +36 -0
  146. data/test/cases/arel/nodes/over_test.rb +69 -0
  147. data/test/cases/arel/nodes/select_core_test.rb +79 -0
  148. data/test/cases/arel/nodes/select_statement_test.rb +51 -0
  149. data/test/cases/arel/nodes/sql_literal_test.rb +75 -0
  150. data/test/cases/arel/nodes/sum_test.rb +35 -0
  151. data/test/cases/arel/nodes/table_alias_test.rb +29 -0
  152. data/test/cases/arel/nodes/true_test.rb +21 -0
  153. data/test/cases/arel/nodes/unary_operation_test.rb +41 -0
  154. data/test/cases/arel/nodes/update_statement_test.rb +60 -0
  155. data/test/cases/arel/nodes/window_test.rb +81 -0
  156. data/test/cases/arel/nodes_test.rb +34 -0
  157. data/test/cases/arel/select_manager_test.rb +1238 -0
  158. data/test/cases/arel/support/fake_record.rb +135 -0
  159. data/test/cases/arel/table_test.rb +216 -0
  160. data/test/cases/arel/update_manager_test.rb +126 -0
  161. data/test/cases/arel/visitors/dispatch_contamination_test.rb +78 -0
  162. data/test/cases/arel/visitors/dot_test.rb +90 -0
  163. data/test/cases/arel/visitors/mysql_test.rb +157 -0
  164. data/test/cases/arel/visitors/postgres_test.rb +366 -0
  165. data/test/cases/arel/visitors/sqlite_test.rb +75 -0
  166. data/test/cases/arel/visitors/to_sql_test.rb +750 -0
  167. data/test/cases/associations/belongs_to_associations_test.rb +510 -158
  168. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +4 -2
  169. data/test/cases/associations/callbacks_test.rb +56 -38
  170. data/test/cases/associations/cascaded_eager_loading_test.rb +118 -61
  171. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +138 -18
  172. data/test/cases/associations/eager_load_nested_include_test.rb +38 -37
  173. data/test/cases/associations/eager_singularization_test.rb +21 -21
  174. data/test/cases/associations/eager_test.rb +559 -415
  175. data/test/cases/associations/extension_test.rb +18 -12
  176. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +234 -213
  177. data/test/cases/associations/has_many_associations_test.rb +1038 -465
  178. data/test/cases/associations/has_many_through_associations_test.rb +558 -249
  179. data/test/cases/associations/has_one_associations_test.rb +294 -129
  180. data/test/cases/associations/has_one_through_associations_test.rb +121 -75
  181. data/test/cases/associations/inner_join_association_test.rb +114 -38
  182. data/test/cases/associations/inverse_associations_test.rb +606 -398
  183. data/test/cases/associations/join_model_test.rb +158 -148
  184. data/test/cases/associations/left_outer_join_association_test.rb +59 -24
  185. data/test/cases/associations/nested_through_associations_test.rb +166 -109
  186. data/test/cases/associations/required_test.rb +35 -10
  187. data/test/cases/associations_test.rb +241 -110
  188. data/test/cases/attribute_methods/read_test.rb +11 -11
  189. data/test/cases/attribute_methods_test.rb +413 -298
  190. data/test/cases/attributes_test.rb +145 -27
  191. data/test/cases/autosave_association_test.rb +681 -436
  192. data/test/cases/base_prevent_writes_test.rb +229 -0
  193. data/test/cases/base_test.rb +599 -542
  194. data/test/cases/batches_test.rb +288 -82
  195. data/test/cases/binary_test.rb +26 -31
  196. data/test/cases/bind_parameter_test.rb +194 -21
  197. data/test/cases/boolean_test.rb +52 -0
  198. data/test/cases/cache_key_test.rb +110 -5
  199. data/test/cases/calculations_test.rb +740 -177
  200. data/test/cases/callbacks_test.rb +74 -207
  201. data/test/cases/clone_test.rb +15 -10
  202. data/test/cases/coders/json_test.rb +2 -0
  203. data/test/cases/coders/yaml_column_test.rb +16 -13
  204. data/test/cases/collection_cache_key_test.rb +177 -20
  205. data/test/cases/column_alias_test.rb +9 -7
  206. data/test/cases/column_definition_test.rb +10 -68
  207. data/test/cases/comment_test.rb +166 -107
  208. data/test/cases/connection_adapters/adapter_leasing_test.rb +14 -10
  209. data/test/cases/connection_adapters/connection_handler_test.rb +358 -51
  210. data/test/cases/connection_adapters/connection_handlers_multi_db_test.rb +400 -0
  211. data/test/cases/connection_adapters/connection_handlers_multi_pool_config_test.rb +103 -0
  212. data/test/cases/connection_adapters/connection_handlers_sharding_db_test.rb +499 -0
  213. data/test/cases/connection_adapters/connection_swapping_nested_test.rb +457 -0
  214. data/test/cases/connection_adapters/legacy_connection_handlers_multi_db_test.rb +486 -0
  215. data/test/cases/connection_adapters/legacy_connection_handlers_sharding_db_test.rb +586 -0
  216. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +319 -138
  217. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +62 -50
  218. data/test/cases/connection_adapters/schema_cache_test.rb +259 -26
  219. data/test/cases/connection_adapters/type_lookup_test.rb +96 -95
  220. data/test/cases/connection_management_test.rb +13 -11
  221. data/test/cases/connection_pool_test.rb +316 -83
  222. data/test/cases/core_test.rb +82 -58
  223. data/test/cases/counter_cache_test.rb +204 -50
  224. data/test/cases/custom_locking_test.rb +5 -3
  225. data/test/cases/database_configurations/hash_config_test.rb +74 -0
  226. data/test/cases/database_configurations/resolver_test.rb +150 -0
  227. data/test/cases/database_configurations_test.rb +145 -0
  228. data/test/cases/database_selector_test.rb +296 -0
  229. data/test/cases/database_statements_test.rb +18 -16
  230. data/test/cases/date_test.rb +8 -16
  231. data/test/cases/date_time_precision_test.rb +100 -78
  232. data/test/cases/date_time_test.rb +23 -8
  233. data/test/cases/defaults_test.rb +106 -71
  234. data/test/cases/delegated_type_test.rb +57 -0
  235. data/test/cases/dirty_test.rb +419 -223
  236. data/test/cases/disconnected_test.rb +6 -6
  237. data/test/cases/dup_test.rb +54 -27
  238. data/test/cases/enum_test.rb +461 -82
  239. data/test/cases/errors_test.rb +7 -7
  240. data/test/cases/explain_subscriber_test.rb +17 -15
  241. data/test/cases/explain_test.rb +11 -19
  242. data/test/cases/filter_attributes_test.rb +153 -0
  243. data/test/cases/finder_respond_to_test.rb +14 -14
  244. data/test/cases/finder_test.rb +669 -287
  245. data/test/cases/fixture_set/file_test.rb +34 -38
  246. data/test/cases/fixtures_test.rb +833 -176
  247. data/test/cases/forbidden_attributes_protection_test.rb +32 -67
  248. data/test/cases/habtm_destroy_order_test.rb +25 -25
  249. data/test/cases/helper.rb +78 -49
  250. data/test/cases/hot_compatibility_test.rb +33 -32
  251. data/test/cases/i18n_test.rb +18 -17
  252. data/test/cases/inheritance_test.rb +180 -115
  253. data/test/cases/insert_all_test.rb +489 -0
  254. data/test/cases/instrumentation_test.rb +101 -0
  255. data/test/cases/integration_test.rb +119 -31
  256. data/test/cases/invalid_connection_test.rb +18 -16
  257. data/test/cases/invertible_migration_test.rb +183 -43
  258. data/test/cases/json_attribute_test.rb +35 -0
  259. data/test/cases/json_serialization_test.rb +57 -58
  260. data/test/cases/json_shared_test_cases.rb +290 -0
  261. data/test/cases/locking_test.rb +413 -119
  262. data/test/cases/log_subscriber_test.rb +68 -26
  263. data/test/cases/marshal_serialization_test.rb +39 -0
  264. data/test/cases/migration/change_schema_test.rb +118 -72
  265. data/test/cases/migration/change_table_test.rb +138 -30
  266. data/test/cases/migration/check_constraint_test.rb +162 -0
  267. data/test/cases/migration/column_attributes_test.rb +45 -35
  268. data/test/cases/migration/column_positioning_test.rb +18 -6
  269. data/test/cases/migration/columns_test.rb +93 -77
  270. data/test/cases/migration/command_recorder_test.rb +121 -34
  271. data/test/cases/migration/compatibility_test.rb +578 -23
  272. data/test/cases/migration/create_join_table_test.rb +35 -25
  273. data/test/cases/migration/foreign_key_test.rb +503 -284
  274. data/test/cases/migration/helper.rb +4 -3
  275. data/test/cases/migration/index_test.rb +119 -70
  276. data/test/cases/migration/logger_test.rb +9 -6
  277. data/test/cases/migration/pending_migrations_test.rb +88 -34
  278. data/test/cases/migration/references_foreign_key_test.rb +164 -150
  279. data/test/cases/migration/references_index_test.rb +38 -19
  280. data/test/cases/migration/references_statements_test.rb +15 -14
  281. data/test/cases/migration/rename_table_test.rb +53 -30
  282. data/test/cases/migration_test.rb +637 -269
  283. data/test/cases/migrator_test.rb +191 -135
  284. data/test/cases/mixin_test.rb +7 -11
  285. data/test/cases/modules_test.rb +36 -34
  286. data/test/cases/multi_db_migrator_test.rb +223 -0
  287. data/test/cases/multiparameter_attributes_test.rb +60 -33
  288. data/test/cases/multiple_db_test.rb +16 -22
  289. data/test/cases/nested_attributes_test.rb +341 -320
  290. data/test/cases/nested_attributes_with_callbacks_test.rb +26 -24
  291. data/test/cases/null_relation_test.rb +84 -0
  292. data/test/cases/numeric_data_test.rb +93 -0
  293. data/test/cases/persistence_test.rb +361 -269
  294. data/test/cases/pooled_connections_test.rb +18 -26
  295. data/test/cases/prepared_statement_status_test.rb +48 -0
  296. data/test/cases/primary_keys_test.rb +210 -104
  297. data/test/cases/query_cache_test.rb +610 -141
  298. data/test/cases/quoting_test.rb +132 -31
  299. data/test/cases/readonly_test.rb +49 -48
  300. data/test/cases/reaper_test.rb +146 -32
  301. data/test/cases/reflection_test.rb +167 -156
  302. data/test/cases/relation/delegation_test.rb +49 -36
  303. data/test/cases/relation/delete_all_test.rb +117 -0
  304. data/test/cases/relation/merging_test.rb +319 -42
  305. data/test/cases/relation/mutation_test.rb +55 -93
  306. data/test/cases/relation/or_test.rb +129 -29
  307. data/test/cases/relation/predicate_builder_test.rb +21 -6
  308. data/test/cases/relation/record_fetch_warning_test.rb +5 -3
  309. data/test/cases/relation/select_test.rb +67 -0
  310. data/test/cases/relation/update_all_test.rb +317 -0
  311. data/test/cases/relation/where_chain_test.rb +68 -32
  312. data/test/cases/relation/where_clause_test.rb +136 -61
  313. data/test/cases/relation/where_test.rb +155 -48
  314. data/test/cases/relation_test.rb +266 -112
  315. data/test/cases/relations_test.rb +969 -744
  316. data/test/cases/reload_models_test.rb +13 -9
  317. data/test/cases/reserved_word_test.rb +141 -0
  318. data/test/cases/result_test.rb +68 -17
  319. data/test/cases/sanitize_test.rb +87 -71
  320. data/test/cases/schema_dumper_test.rb +221 -128
  321. data/test/cases/schema_loading_test.rb +3 -2
  322. data/test/cases/scoping/default_scoping_test.rb +185 -144
  323. data/test/cases/scoping/named_scoping_test.rb +177 -89
  324. data/test/cases/scoping/relation_scoping_test.rb +197 -75
  325. data/test/cases/secure_token_test.rb +18 -3
  326. data/test/cases/serialization_test.rb +30 -28
  327. data/test/cases/serialized_attribute_test.rb +133 -42
  328. data/test/cases/signed_id_test.rb +168 -0
  329. data/test/cases/statement_cache_test.rb +41 -24
  330. data/test/cases/statement_invalid_test.rb +42 -0
  331. data/test/cases/store_test.rb +180 -55
  332. data/test/cases/strict_loading_test.rb +473 -0
  333. data/test/cases/suppressor_test.rb +26 -12
  334. data/test/cases/tasks/database_tasks_test.rb +1258 -194
  335. data/test/cases/tasks/mysql_rake_test.rb +370 -298
  336. data/test/cases/tasks/postgresql_rake_test.rb +481 -251
  337. data/test/cases/tasks/sqlite_rake_test.rb +225 -178
  338. data/test/cases/test_case.rb +51 -40
  339. data/test/cases/test_databases_test.rb +79 -0
  340. data/test/cases/test_fixtures_test.rb +79 -19
  341. data/test/cases/time_precision_test.rb +98 -76
  342. data/test/cases/timestamp_test.rb +102 -99
  343. data/test/cases/touch_later_test.rb +12 -10
  344. data/test/cases/transaction_callbacks_test.rb +344 -90
  345. data/test/cases/transaction_isolation_test.rb +12 -12
  346. data/test/cases/transactions_test.rb +612 -162
  347. data/test/cases/type/adapter_specific_registry_test.rb +14 -2
  348. data/test/cases/type/date_time_test.rb +4 -2
  349. data/test/cases/type/integer_test.rb +4 -2
  350. data/test/cases/type/string_test.rb +10 -8
  351. data/test/cases/type/time_test.rb +28 -0
  352. data/test/cases/type/type_map_test.rb +29 -28
  353. data/test/cases/type/unsigned_integer_test.rb +19 -0
  354. data/test/cases/type_test.rb +2 -0
  355. data/test/cases/types_test.rb +3 -1
  356. data/test/cases/unconnected_test.rb +14 -1
  357. data/test/cases/unsafe_raw_sql_test.rb +274 -0
  358. data/test/cases/validations/absence_validation_test.rb +19 -17
  359. data/test/cases/validations/association_validation_test.rb +30 -28
  360. data/test/cases/validations/i18n_generate_message_validation_test.rb +34 -16
  361. data/test/cases/validations/i18n_validation_test.rb +22 -21
  362. data/test/cases/validations/length_validation_test.rb +34 -33
  363. data/test/cases/validations/numericality_validation_test.rb +181 -0
  364. data/test/cases/validations/presence_validation_test.rb +21 -19
  365. data/test/cases/validations/uniqueness_validation_test.rb +156 -86
  366. data/test/cases/validations_repair_helper.rb +2 -0
  367. data/test/cases/validations_test.rb +61 -26
  368. data/test/cases/view_test.rb +122 -116
  369. data/test/cases/yaml_serialization_test.rb +79 -34
  370. data/test/config.example.yml +19 -19
  371. data/test/config.rb +3 -1
  372. data/test/config.yml +74 -8
  373. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  374. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  375. data/test/fixtures/all/namespaced/accounts.yml +2 -0
  376. data/test/fixtures/author_addresses.yml +1 -8
  377. data/test/fixtures/authors.yml +1 -7
  378. data/test/fixtures/binaries.yml +4 -0
  379. data/test/fixtures/books.yml +9 -2
  380. data/test/fixtures/categories_posts.yml +3 -0
  381. data/test/fixtures/citations.yml +5 -0
  382. data/test/fixtures/comments.yml +7 -0
  383. data/test/fixtures/companies.yml +5 -0
  384. data/test/fixtures/computers.yml +2 -0
  385. data/test/fixtures/customers.yml +10 -1
  386. data/test/fixtures/developers.yml +1 -1
  387. data/test/fixtures/essays.yml +10 -0
  388. data/test/fixtures/faces.yml +3 -3
  389. data/test/fixtures/humans.yml +5 -0
  390. data/test/fixtures/interests.yml +7 -7
  391. data/test/fixtures/memberships.yml +7 -0
  392. data/test/fixtures/minimalistics.yml +3 -0
  393. data/test/fixtures/mixed_case_monkeys.yml +2 -2
  394. data/test/fixtures/naked/yml/courses_with_invalid_key.yml +3 -0
  395. data/test/fixtures/naked/yml/parrots.yml +1 -0
  396. data/test/fixtures/other_books.yml +26 -0
  397. data/test/fixtures/other_posts.yml +1 -0
  398. data/test/fixtures/parrots.yml +7 -1
  399. data/test/fixtures/pirates.yml +3 -0
  400. data/test/fixtures/posts.yml +11 -3
  401. data/test/fixtures/randomly_named_a9.yml +7 -7
  402. data/test/fixtures/readers.yml +6 -0
  403. data/test/fixtures/reserved_words/values.yml +2 -2
  404. data/test/fixtures/sponsors.yml +3 -0
  405. data/test/fixtures/strict_zines.yml +2 -0
  406. data/test/fixtures/subscribers.yml +1 -1
  407. data/test/fixtures/tasks.yml +1 -1
  408. data/test/fixtures/warehouse-things.yml +3 -0
  409. data/test/migrations/10_urban/9_add_expressions.rb +2 -0
  410. data/test/migrations/decimal/1_give_me_big_numbers.rb +6 -4
  411. data/test/migrations/magic/1_currencies_have_symbols.rb +3 -2
  412. data/test/migrations/missing/1000_people_have_middle_names.rb +2 -0
  413. data/test/migrations/missing/1_people_have_last_names.rb +2 -0
  414. data/test/migrations/missing/3_we_need_reminders.rb +2 -0
  415. data/test/migrations/missing/4_innocent_jointable.rb +3 -1
  416. data/test/migrations/rename/1_we_need_things.rb +2 -0
  417. data/test/migrations/rename/2_rename_things.rb +2 -0
  418. data/test/migrations/to_copy/1_people_have_hobbies.rb +3 -1
  419. data/test/migrations/to_copy/2_people_have_descriptions.rb +3 -1
  420. data/test/migrations/to_copy2/1_create_articles.rb +2 -0
  421. data/test/migrations/to_copy2/2_create_comments.rb +3 -1
  422. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +3 -1
  423. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +3 -1
  424. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +3 -1
  425. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +2 -0
  426. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +2 -0
  427. data/test/migrations/valid/1_valid_people_have_last_names.rb +2 -0
  428. data/test/migrations/valid/2_we_need_reminders.rb +2 -0
  429. data/test/migrations/valid/3_innocent_jointable.rb +3 -1
  430. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +2 -0
  431. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +2 -0
  432. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +3 -1
  433. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +2 -0
  434. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +2 -0
  435. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +3 -1
  436. data/test/migrations/version_check/20131219224947_migration_version_check.rb +2 -0
  437. data/test/models/account.rb +46 -0
  438. data/test/models/admin/account.rb +3 -1
  439. data/test/models/admin/randomly_named_c1.rb +2 -0
  440. data/test/models/admin/user.rb +16 -8
  441. data/test/models/admin.rb +4 -2
  442. data/test/models/aircraft.rb +3 -1
  443. data/test/models/arunit2_model.rb +2 -0
  444. data/test/models/author.rb +153 -102
  445. data/test/models/auto_id.rb +2 -0
  446. data/test/models/autoloadable/extra_firm.rb +2 -0
  447. data/test/models/binary.rb +3 -1
  448. data/test/models/binary_field.rb +6 -0
  449. data/test/models/bird.rb +13 -1
  450. data/test/models/book.rb +14 -4
  451. data/test/models/book_destroy_async.rb +24 -0
  452. data/test/models/boolean.rb +5 -0
  453. data/test/models/bulb.rb +13 -4
  454. data/test/models/cake_designer.rb +2 -0
  455. data/test/models/car.rb +17 -10
  456. data/test/models/carrier.rb +2 -0
  457. data/test/models/cart.rb +5 -0
  458. data/test/models/cat.rb +2 -0
  459. data/test/models/categorization.rb +8 -6
  460. data/test/models/category.rb +28 -16
  461. data/test/models/chef.rb +2 -0
  462. data/test/models/citation.rb +5 -1
  463. data/test/models/club.rb +13 -10
  464. data/test/models/college.rb +4 -2
  465. data/test/models/column.rb +2 -0
  466. data/test/models/column_name.rb +2 -0
  467. data/test/models/comment.rb +32 -10
  468. data/test/models/company.rb +102 -106
  469. data/test/models/company_in_module.rb +27 -26
  470. data/test/models/computer.rb +3 -1
  471. data/test/models/contact.rb +15 -13
  472. data/test/models/content.rb +5 -3
  473. data/test/models/contract.rb +21 -3
  474. data/test/models/country.rb +2 -4
  475. data/test/models/course.rb +3 -1
  476. data/test/models/customer.rb +10 -8
  477. data/test/models/customer_carrier.rb +2 -0
  478. data/test/models/dashboard.rb +2 -0
  479. data/test/models/default.rb +2 -0
  480. data/test/models/department.rb +2 -0
  481. data/test/models/destroy_async_parent.rb +15 -0
  482. data/test/models/destroy_async_parent_soft_delete.rb +20 -0
  483. data/test/models/developer.rb +152 -85
  484. data/test/models/dl_keyed_belongs_to.rb +13 -0
  485. data/test/models/dl_keyed_belongs_to_soft_delete.rb +19 -0
  486. data/test/models/dl_keyed_has_many.rb +5 -0
  487. data/test/models/dl_keyed_has_many_through.rb +5 -0
  488. data/test/models/dl_keyed_has_one.rb +5 -0
  489. data/test/models/dl_keyed_join.rb +10 -0
  490. data/test/models/dog.rb +2 -0
  491. data/test/models/dog_lover.rb +2 -0
  492. data/test/models/doubloon.rb +3 -1
  493. data/test/models/drink_designer.rb +17 -0
  494. data/test/models/edge.rb +4 -2
  495. data/test/models/electron.rb +2 -0
  496. data/test/models/engine.rb +3 -2
  497. data/test/models/entrant.rb +2 -0
  498. data/test/models/entry.rb +5 -0
  499. data/test/models/essay.rb +6 -3
  500. data/test/models/essay_destroy_async.rb +12 -0
  501. data/test/models/event.rb +3 -1
  502. data/test/models/eye.rb +5 -3
  503. data/test/models/face.rb +14 -6
  504. data/test/models/family.rb +6 -0
  505. data/test/models/family_tree.rb +6 -0
  506. data/test/models/friendship.rb +5 -3
  507. data/test/models/frog.rb +8 -0
  508. data/test/models/guid.rb +3 -1
  509. data/test/models/guitar.rb +2 -0
  510. data/test/models/hotel.rb +5 -3
  511. data/test/models/human.rb +39 -0
  512. data/test/models/image.rb +3 -1
  513. data/test/models/interest.rb +14 -3
  514. data/test/models/invoice.rb +4 -2
  515. data/test/models/item.rb +3 -1
  516. data/test/models/job.rb +5 -3
  517. data/test/models/joke.rb +4 -2
  518. data/test/models/keyboard.rb +3 -1
  519. data/test/models/legacy_thing.rb +2 -0
  520. data/test/models/lesson.rb +2 -0
  521. data/test/models/line_item.rb +3 -1
  522. data/test/models/liquid.rb +2 -0
  523. data/test/models/matey.rb +3 -1
  524. data/test/models/measurement.rb +4 -0
  525. data/test/models/member.rb +23 -20
  526. data/test/models/member_detail.rb +3 -0
  527. data/test/models/member_type.rb +2 -0
  528. data/test/models/membership.rb +4 -1
  529. data/test/models/mentor.rb +3 -1
  530. data/test/models/message.rb +5 -0
  531. data/test/models/minimalistic.rb +2 -0
  532. data/test/models/minivan.rb +3 -2
  533. data/test/models/mixed_case_monkey.rb +3 -1
  534. data/test/models/molecule.rb +2 -0
  535. data/test/models/mouse.rb +6 -0
  536. data/test/models/movie.rb +2 -0
  537. data/test/models/node.rb +4 -2
  538. data/test/models/non_primary_key.rb +2 -0
  539. data/test/models/notification.rb +2 -0
  540. data/test/models/numeric_data.rb +12 -0
  541. data/test/models/order.rb +4 -2
  542. data/test/models/organization.rb +9 -7
  543. data/test/models/other_dog.rb +3 -1
  544. data/test/models/owner.rb +6 -4
  545. data/test/models/parrot.rb +12 -4
  546. data/test/models/person.rb +59 -54
  547. data/test/models/personal_legacy_thing.rb +3 -1
  548. data/test/models/pet.rb +4 -2
  549. data/test/models/pet_treasure.rb +2 -0
  550. data/test/models/pirate.rb +67 -43
  551. data/test/models/possession.rb +3 -1
  552. data/test/models/post.rb +184 -86
  553. data/test/models/price_estimate.rb +11 -1
  554. data/test/models/professor.rb +3 -1
  555. data/test/models/project.rb +14 -12
  556. data/test/models/publisher/article.rb +2 -0
  557. data/test/models/publisher/magazine.rb +2 -0
  558. data/test/models/publisher.rb +2 -0
  559. data/test/models/randomly_named_c1.rb +2 -0
  560. data/test/models/rating.rb +5 -1
  561. data/test/models/reader.rb +7 -5
  562. data/test/models/recipe.rb +2 -0
  563. data/test/models/record.rb +2 -0
  564. data/test/models/reference.rb +6 -3
  565. data/test/models/reply.rb +39 -21
  566. data/test/models/room.rb +6 -0
  567. data/test/models/section.rb +6 -0
  568. data/test/models/seminar.rb +6 -0
  569. data/test/models/session.rb +6 -0
  570. data/test/models/ship.rb +12 -9
  571. data/test/models/ship_part.rb +5 -3
  572. data/test/models/shop.rb +4 -2
  573. data/test/models/shop_account.rb +2 -0
  574. data/test/models/speedometer.rb +2 -0
  575. data/test/models/sponsor.rb +8 -5
  576. data/test/models/squeak.rb +6 -0
  577. data/test/models/strict_zine.rb +7 -0
  578. data/test/models/string_key_object.rb +2 -0
  579. data/test/models/student.rb +2 -0
  580. data/test/models/subscriber.rb +4 -2
  581. data/test/models/subscription.rb +5 -1
  582. data/test/models/tag.rb +6 -3
  583. data/test/models/tagging.rb +13 -6
  584. data/test/models/task.rb +2 -0
  585. data/test/models/topic.rb +54 -19
  586. data/test/models/toy.rb +4 -0
  587. data/test/models/traffic_light.rb +2 -0
  588. data/test/models/treasure.rb +5 -3
  589. data/test/models/treaty.rb +2 -4
  590. data/test/models/tree.rb +2 -0
  591. data/test/models/tuning_peg.rb +2 -0
  592. data/test/models/tyre.rb +2 -0
  593. data/test/models/user.rb +12 -4
  594. data/test/models/uuid_child.rb +2 -0
  595. data/test/models/uuid_item.rb +2 -0
  596. data/test/models/uuid_parent.rb +2 -0
  597. data/test/models/vegetables.rb +12 -3
  598. data/test/models/vertex.rb +6 -4
  599. data/test/models/warehouse_thing.rb +2 -0
  600. data/test/models/wheel.rb +3 -1
  601. data/test/models/without_table.rb +3 -1
  602. data/test/models/zine.rb +3 -1
  603. data/test/schema/mysql2_specific_schema.rb +49 -35
  604. data/test/schema/oracle_specific_schema.rb +13 -15
  605. data/test/schema/postgresql_specific_schema.rb +51 -40
  606. data/test/schema/schema.rb +334 -154
  607. data/test/schema/sqlite_specific_schema.rb +9 -16
  608. data/test/support/config.rb +26 -26
  609. data/test/support/connection.rb +14 -8
  610. data/test/support/connection_helper.rb +3 -1
  611. data/test/support/ddl_helper.rb +2 -0
  612. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic.dump +0 -0
  613. data/test/support/marshal_compatibility_fixtures/IBM_DB/rails_6_0_topic_associations.dump +0 -0
  614. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic.dump +0 -0
  615. data/test/support/marshal_compatibility_fixtures/Mysql2/rails_6_0_topic_associations.dump +0 -0
  616. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic.dump +0 -0
  617. data/test/support/marshal_compatibility_fixtures/PostgreSQL/rails_6_0_topic_associations.dump +0 -0
  618. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic.dump +0 -0
  619. data/test/support/marshal_compatibility_fixtures/SQLite/rails_6_0_topic_associations.dump +0 -0
  620. data/test/support/marshal_compatibility_fixtures/legacy_6_0_record_mysql.dump +0 -0
  621. data/test/support/marshal_compatibility_fixtures/legacy_relation.dump +0 -0
  622. data/test/support/schema_dumping_helper.rb +2 -0
  623. data/test/support/stubs/strong_parameters.rb +40 -0
  624. data/test/support/yaml_compatibility_fixtures/rails_v1_mysql.yml +206 -0
  625. data/test/support/yaml_compatibility_fixtures/rails_v2.yml +55 -0
  626. metadata +230 -10
@@ -0,0 +1,750 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../helper"
4
+ require "bigdecimal"
5
+
6
+ module Arel
7
+ module Visitors
8
+ describe "the to_sql visitor" do
9
+ before do
10
+ @conn = FakeRecord::Base.new
11
+ @visitor = ToSql.new @conn.connection
12
+ @table = Table.new(:users)
13
+ @attr = @table[:id]
14
+ end
15
+
16
+ def compile(node)
17
+ @visitor.accept(node, Collectors::SQLString.new).value
18
+ end
19
+
20
+ it "works with BindParams" do
21
+ node = Nodes::BindParam.new(1)
22
+ sql = compile node
23
+ _(sql).must_be_like "?"
24
+ end
25
+
26
+ it "does not quote BindParams used as part of a ValuesList" do
27
+ bp = Nodes::BindParam.new(1)
28
+ values = Nodes::ValuesList.new([[bp]])
29
+ sql = compile values
30
+ _(sql).must_be_like "VALUES (?)"
31
+ end
32
+
33
+ it "can define a dispatch method" do
34
+ visited = false
35
+ viz = Class.new(Arel::Visitors::Visitor) {
36
+ define_method(:hello) do |node, c|
37
+ visited = true
38
+ end
39
+
40
+ def dispatch
41
+ { Arel::Table => "hello" }
42
+ end
43
+ }.new
44
+
45
+ viz.accept(@table, Collectors::SQLString.new)
46
+ assert visited, "hello method was called"
47
+ end
48
+
49
+ it "should not quote sql literals" do
50
+ node = @table[Arel.star]
51
+ sql = compile node
52
+ _(sql).must_be_like '"users".*'
53
+ end
54
+
55
+ it "should visit named functions" do
56
+ function = Nodes::NamedFunction.new("omg", [Arel.star])
57
+ assert_equal "omg(*)", compile(function)
58
+ end
59
+
60
+ it "should chain predications on named functions" do
61
+ function = Nodes::NamedFunction.new("omg", [Arel.star])
62
+ sql = compile(function.eq(2))
63
+ _(sql).must_be_like %{ omg(*) = 2 }
64
+ end
65
+
66
+ it "should handle nil with named functions" do
67
+ function = Nodes::NamedFunction.new("omg", [Arel.star])
68
+ sql = compile(function.eq(nil))
69
+ _(sql).must_be_like %{ omg(*) IS NULL }
70
+ end
71
+
72
+ it "should visit built-in functions" do
73
+ function = Nodes::Count.new([Arel.star])
74
+ assert_equal "COUNT(*)", compile(function)
75
+
76
+ function = Nodes::Sum.new([Arel.star])
77
+ assert_equal "SUM(*)", compile(function)
78
+
79
+ function = Nodes::Max.new([Arel.star])
80
+ assert_equal "MAX(*)", compile(function)
81
+
82
+ function = Nodes::Min.new([Arel.star])
83
+ assert_equal "MIN(*)", compile(function)
84
+
85
+ function = Nodes::Avg.new([Arel.star])
86
+ assert_equal "AVG(*)", compile(function)
87
+ end
88
+
89
+ it "should visit built-in functions operating on distinct values" do
90
+ function = Nodes::Count.new([Arel.star])
91
+ function.distinct = true
92
+ assert_equal "COUNT(DISTINCT *)", compile(function)
93
+
94
+ function = Nodes::Sum.new([Arel.star])
95
+ function.distinct = true
96
+ assert_equal "SUM(DISTINCT *)", compile(function)
97
+
98
+ function = Nodes::Max.new([Arel.star])
99
+ function.distinct = true
100
+ assert_equal "MAX(DISTINCT *)", compile(function)
101
+
102
+ function = Nodes::Min.new([Arel.star])
103
+ function.distinct = true
104
+ assert_equal "MIN(DISTINCT *)", compile(function)
105
+
106
+ function = Nodes::Avg.new([Arel.star])
107
+ function.distinct = true
108
+ assert_equal "AVG(DISTINCT *)", compile(function)
109
+ end
110
+
111
+ it "works with lists" do
112
+ function = Nodes::NamedFunction.new("omg", [Arel.star, Arel.star])
113
+ assert_equal "omg(*, *)", compile(function)
114
+ end
115
+
116
+ describe "Nodes::Equality" do
117
+ it "should escape strings" do
118
+ test = Table.new(:users)[:name].eq "Aaron Patterson"
119
+ _(compile(test)).must_be_like %{
120
+ "users"."name" = 'Aaron Patterson'
121
+ }
122
+ end
123
+
124
+ it "should handle false" do
125
+ table = Table.new(:users)
126
+ val = Nodes.build_quoted(false, table[:active])
127
+ sql = compile Nodes::Equality.new(val, val)
128
+ _(sql).must_be_like %{ 'f' = 'f' }
129
+ end
130
+
131
+ it "should handle nil" do
132
+ sql = compile Nodes::Equality.new(@table[:name], nil)
133
+ _(sql).must_be_like %{ "users"."name" IS NULL }
134
+ end
135
+ end
136
+
137
+ describe "Nodes::Grouping" do
138
+ it "wraps nested groupings in brackets only once" do
139
+ sql = compile Nodes::Grouping.new(Nodes::Grouping.new(Nodes.build_quoted("foo")))
140
+ _(sql).must_equal "('foo')"
141
+ end
142
+ end
143
+
144
+ describe "Nodes::NotEqual" do
145
+ it "should handle false" do
146
+ val = Nodes.build_quoted(false, @table[:active])
147
+ sql = compile Nodes::NotEqual.new(@table[:active], val)
148
+ _(sql).must_be_like %{ "users"."active" != 'f' }
149
+ end
150
+
151
+ it "should handle nil" do
152
+ val = Nodes.build_quoted(nil, @table[:active])
153
+ sql = compile Nodes::NotEqual.new(@table[:name], val)
154
+ _(sql).must_be_like %{ "users"."name" IS NOT NULL }
155
+ end
156
+ end
157
+
158
+ describe "Nodes::IsNotDistinctFrom" do
159
+ it "should construct a valid generic SQL statement" do
160
+ test = Table.new(:users)[:name].is_not_distinct_from "Aaron Patterson"
161
+ _(compile(test)).must_be_like %{
162
+ CASE WHEN "users"."name" = 'Aaron Patterson' OR ("users"."name" IS NULL AND 'Aaron Patterson' IS NULL) THEN 0 ELSE 1 END = 0
163
+ }
164
+ end
165
+
166
+ it "should handle column names on both sides" do
167
+ test = Table.new(:users)[:first_name].is_not_distinct_from Table.new(:users)[:last_name]
168
+ _(compile(test)).must_be_like %{
169
+ CASE WHEN "users"."first_name" = "users"."last_name" OR ("users"."first_name" IS NULL AND "users"."last_name" IS NULL) THEN 0 ELSE 1 END = 0
170
+ }
171
+ end
172
+
173
+ it "should handle nil" do
174
+ val = Nodes.build_quoted(nil, @table[:active])
175
+ sql = compile Nodes::IsNotDistinctFrom.new(@table[:name], val)
176
+ _(sql).must_be_like %{ "users"."name" IS NULL }
177
+ end
178
+ end
179
+
180
+ describe "Nodes::IsDistinctFrom" do
181
+ it "should handle column names on both sides" do
182
+ test = Table.new(:users)[:first_name].is_distinct_from Table.new(:users)[:last_name]
183
+ _(compile(test)).must_be_like %{
184
+ CASE WHEN "users"."first_name" = "users"."last_name" OR ("users"."first_name" IS NULL AND "users"."last_name" IS NULL) THEN 0 ELSE 1 END = 1
185
+ }
186
+ end
187
+
188
+ it "should handle nil" do
189
+ val = Nodes.build_quoted(nil, @table[:active])
190
+ sql = compile Nodes::IsDistinctFrom.new(@table[:name], val)
191
+ _(sql).must_be_like %{ "users"."name" IS NOT NULL }
192
+ end
193
+ end
194
+
195
+ it "should visit string subclass" do
196
+ [
197
+ Class.new(String).new(":'("),
198
+ Class.new(Class.new(String)).new(":'("),
199
+ ].each do |obj|
200
+ val = Nodes.build_quoted(obj, @table[:active])
201
+ sql = compile Nodes::NotEqual.new(@table[:name], val)
202
+ _(sql).must_be_like %{ "users"."name" != ':\\'(' }
203
+ end
204
+ end
205
+
206
+ it "should visit_Class" do
207
+ _(compile(Nodes.build_quoted(DateTime))).must_equal "'DateTime'"
208
+ end
209
+
210
+ it "should escape LIMIT" do
211
+ sc = Arel::Nodes::SelectStatement.new
212
+ sc.limit = Arel::Nodes::Limit.new(Nodes.build_quoted("omg"))
213
+ assert_match(/LIMIT 'omg'/, compile(sc))
214
+ end
215
+
216
+ it "should contain a single space before ORDER BY" do
217
+ table = Table.new(:users)
218
+ test = table.order(table[:name])
219
+ sql = compile test
220
+ assert_match(/"users" ORDER BY/, sql)
221
+ end
222
+
223
+ it "should quote LIMIT without column type coercion" do
224
+ table = Table.new(:users)
225
+ sc = table.where(table[:name].eq(0)).take(1).ast
226
+ assert_match(/WHERE "users"."name" = 0 LIMIT 1/, compile(sc))
227
+ end
228
+
229
+ it "should visit_DateTime" do
230
+ dt = DateTime.now
231
+ table = Table.new(:users)
232
+ test = table[:created_at].eq dt
233
+ sql = compile test
234
+
235
+ _(sql).must_be_like %{"users"."created_at" = '#{dt.strftime("%Y-%m-%d %H:%M:%S")}'}
236
+ end
237
+
238
+ it "should visit_Float" do
239
+ test = Table.new(:products)[:price].eq 2.14
240
+ sql = compile test
241
+ _(sql).must_be_like %{"products"."price" = 2.14}
242
+ end
243
+
244
+ it "should visit_Not" do
245
+ sql = compile Nodes::Not.new(Arel.sql("foo"))
246
+ _(sql).must_be_like "NOT (foo)"
247
+ end
248
+
249
+ it "should apply Not to the whole expression" do
250
+ node = Nodes::And.new [@attr.eq(10), @attr.eq(11)]
251
+ sql = compile Nodes::Not.new(node)
252
+ _(sql).must_be_like %{NOT ("users"."id" = 10 AND "users"."id" = 11)}
253
+ end
254
+
255
+ it "should visit_As" do
256
+ as = Nodes::As.new(Arel.sql("foo"), Arel.sql("bar"))
257
+ sql = compile as
258
+ _(sql).must_be_like "foo AS bar"
259
+ end
260
+
261
+ it "should visit_Integer" do
262
+ compile 8787878092
263
+ end
264
+
265
+ it "should visit_Hash" do
266
+ compile(Nodes.build_quoted(a: 1))
267
+ end
268
+
269
+ it "should visit_Set" do
270
+ compile Nodes.build_quoted(Set.new([1, 2]))
271
+ end
272
+
273
+ it "should visit_BigDecimal" do
274
+ compile Nodes.build_quoted(BigDecimal("2.14"))
275
+ end
276
+
277
+ it "should visit_Date" do
278
+ dt = Date.today
279
+ table = Table.new(:users)
280
+ test = table[:created_at].eq dt
281
+ sql = compile test
282
+
283
+ _(sql).must_be_like %{"users"."created_at" = '#{dt.strftime("%Y-%m-%d")}'}
284
+ end
285
+
286
+ it "should visit_NilClass" do
287
+ _(compile(Nodes.build_quoted(nil))).must_be_like "NULL"
288
+ end
289
+
290
+ it "unsupported input should raise UnsupportedVisitError" do
291
+ error = assert_raises(UnsupportedVisitError) { compile(nil) }
292
+ assert_match(/\AUnsupported/, error.message)
293
+ end
294
+
295
+ it "should visit_Arel_SelectManager, which is a subquery" do
296
+ mgr = Table.new(:foo).project(:bar)
297
+ _(compile(mgr)).must_be_like '(SELECT bar FROM "foo")'
298
+ end
299
+
300
+ it "should visit_Arel_Nodes_And" do
301
+ node = Nodes::And.new [@attr.eq(10), @attr.eq(11)]
302
+ _(compile(node)).must_be_like %{
303
+ "users"."id" = 10 AND "users"."id" = 11
304
+ }
305
+ end
306
+
307
+ it "should visit_Arel_Nodes_Or" do
308
+ node = Nodes::Or.new @attr.eq(10), @attr.eq(11)
309
+ _(compile(node)).must_be_like %{
310
+ "users"."id" = 10 OR "users"."id" = 11
311
+ }
312
+ end
313
+
314
+ it "should visit_Arel_Nodes_Assignment" do
315
+ column = @table["id"]
316
+ node = Nodes::Assignment.new(
317
+ Nodes::UnqualifiedColumn.new(column),
318
+ Nodes::UnqualifiedColumn.new(column)
319
+ )
320
+ _(compile(node)).must_be_like %{
321
+ "id" = "id"
322
+ }
323
+ end
324
+
325
+ it "should visit visit_Arel_Attributes_Time" do
326
+ attr = Attributes::Time.new(@attr.relation, @attr.name)
327
+ compile attr
328
+ end
329
+
330
+ it "should visit_TrueClass" do
331
+ test = Table.new(:users)[:bool].eq(true)
332
+ _(compile(test)).must_be_like %{ "users"."bool" = 't' }
333
+ end
334
+
335
+ describe "Nodes::Matches" do
336
+ it "should know how to visit" do
337
+ node = @table[:name].matches("foo%")
338
+ _(compile(node)).must_be_like %{
339
+ "users"."name" LIKE 'foo%'
340
+ }
341
+ end
342
+
343
+ it "can handle ESCAPE" do
344
+ node = @table[:name].matches("foo!%", "!")
345
+ _(compile(node)).must_be_like %{
346
+ "users"."name" LIKE 'foo!%' ESCAPE '!'
347
+ }
348
+ end
349
+
350
+ it "can handle subqueries" do
351
+ subquery = @table.project(:id).where(@table[:name].matches("foo%"))
352
+ node = @attr.in subquery
353
+ _(compile(node)).must_be_like %{
354
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" LIKE 'foo%')
355
+ }
356
+ end
357
+ end
358
+
359
+ describe "Nodes::DoesNotMatch" do
360
+ it "should know how to visit" do
361
+ node = @table[:name].does_not_match("foo%")
362
+ _(compile(node)).must_be_like %{
363
+ "users"."name" NOT LIKE 'foo%'
364
+ }
365
+ end
366
+
367
+ it "can handle ESCAPE" do
368
+ node = @table[:name].does_not_match("foo!%", "!")
369
+ _(compile(node)).must_be_like %{
370
+ "users"."name" NOT LIKE 'foo!%' ESCAPE '!'
371
+ }
372
+ end
373
+
374
+ it "can handle subqueries" do
375
+ subquery = @table.project(:id).where(@table[:name].does_not_match("foo%"))
376
+ node = @attr.in subquery
377
+ _(compile(node)).must_be_like %{
378
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" NOT LIKE 'foo%')
379
+ }
380
+ end
381
+ end
382
+
383
+ describe "Nodes::Ordering" do
384
+ it "should know how to visit" do
385
+ node = @attr.desc
386
+ _(compile(node)).must_be_like %{
387
+ "users"."id" DESC
388
+ }
389
+ end
390
+ end
391
+
392
+ describe "Nodes::In" do
393
+ it "should know how to visit" do
394
+ node = @attr.in [1, 2, 3]
395
+ _(compile(node)).must_be_like %{
396
+ "users"."id" IN (1, 2, 3)
397
+ }
398
+ end
399
+
400
+ it "should return 1=0 when empty right which is always false" do
401
+ node = @attr.in []
402
+ _(compile(node)).must_equal "1=0"
403
+ end
404
+
405
+ it "can handle two dot ranges" do
406
+ node = @attr.between 1..3
407
+ _(compile(node)).must_be_like %{
408
+ "users"."id" BETWEEN 1 AND 3
409
+ }
410
+ end
411
+
412
+ it "can handle three dot ranges" do
413
+ node = @attr.between 1...3
414
+ _(compile(node)).must_be_like %{
415
+ "users"."id" >= 1 AND "users"."id" < 3
416
+ }
417
+ end
418
+
419
+ it "can handle ranges bounded by infinity" do
420
+ node = @attr.between 1..Float::INFINITY
421
+ _(compile(node)).must_be_like %{
422
+ "users"."id" >= 1
423
+ }
424
+ node = @attr.between(-Float::INFINITY..3)
425
+ _(compile(node)).must_be_like %{
426
+ "users"."id" <= 3
427
+ }
428
+ node = @attr.between(-Float::INFINITY...3)
429
+ _(compile(node)).must_be_like %{
430
+ "users"."id" < 3
431
+ }
432
+ node = @attr.between(-Float::INFINITY..Float::INFINITY)
433
+ _(compile(node)).must_be_like %{1=1}
434
+ end
435
+
436
+ it "can handle subqueries" do
437
+ table = Table.new(:users)
438
+ subquery = table.project(:id).where(table[:name].eq("Aaron"))
439
+ node = @attr.in subquery
440
+ _(compile(node)).must_be_like %{
441
+ "users"."id" IN (SELECT id FROM "users" WHERE "users"."name" = 'Aaron')
442
+ }
443
+ end
444
+ end
445
+
446
+ describe "Nodes::InfixOperation" do
447
+ it "should handle Multiplication" do
448
+ node = Arel::Attributes::Decimal.new(Table.new(:products), :price) * Arel::Attributes::Decimal.new(Table.new(:currency_rates), :rate)
449
+ _(compile(node)).must_equal %("products"."price" * "currency_rates"."rate")
450
+ end
451
+
452
+ it "should handle Division" do
453
+ node = Arel::Attributes::Decimal.new(Table.new(:products), :price) / 5
454
+ _(compile(node)).must_equal %("products"."price" / 5)
455
+ end
456
+
457
+ it "should handle Addition" do
458
+ node = Arel::Attributes::Decimal.new(Table.new(:products), :price) + 6
459
+ _(compile(node)).must_equal %(("products"."price" + 6))
460
+ end
461
+
462
+ it "should handle Subtraction" do
463
+ node = Arel::Attributes::Decimal.new(Table.new(:products), :price) - 7
464
+ _(compile(node)).must_equal %(("products"."price" - 7))
465
+ end
466
+
467
+ it "should handle Concatenation" do
468
+ table = Table.new(:users)
469
+ node = table[:name].concat(table[:name])
470
+ _(compile(node)).must_equal %("users"."name" || "users"."name")
471
+ end
472
+
473
+ it "should handle Contains" do
474
+ table = Table.new(:users)
475
+ node = table[:name].contains(table[:name])
476
+ _(compile(node)).must_equal %("users"."name" @> "users"."name")
477
+ end
478
+
479
+ it "should handle Overlaps" do
480
+ table = Table.new(:users)
481
+ node = table[:name].overlaps(table[:name])
482
+ _(compile(node)).must_equal %("users"."name" && "users"."name")
483
+ end
484
+
485
+ it "should handle BitwiseAnd" do
486
+ node = Arel::Attributes::Integer.new(Table.new(:products), :bitmap) & 16
487
+ _(compile(node)).must_equal %(("products"."bitmap" & 16))
488
+ end
489
+
490
+ it "should handle BitwiseOr" do
491
+ node = Arel::Attributes::Integer.new(Table.new(:products), :bitmap) | 16
492
+ _(compile(node)).must_equal %(("products"."bitmap" | 16))
493
+ end
494
+
495
+ it "should handle BitwiseXor" do
496
+ node = Arel::Attributes::Integer.new(Table.new(:products), :bitmap) ^ 16
497
+ _(compile(node)).must_equal %(("products"."bitmap" ^ 16))
498
+ end
499
+
500
+ it "should handle BitwiseShiftLeft" do
501
+ node = Arel::Attributes::Integer.new(Table.new(:products), :bitmap) << 4
502
+ _(compile(node)).must_equal %(("products"."bitmap" << 4))
503
+ end
504
+
505
+ it "should handle BitwiseShiftRight" do
506
+ node = Arel::Attributes::Integer.new(Table.new(:products), :bitmap) >> 4
507
+ _(compile(node)).must_equal %(("products"."bitmap" >> 4))
508
+ end
509
+
510
+ it "should handle arbitrary operators" do
511
+ node = Arel::Nodes::InfixOperation.new(
512
+ "&&",
513
+ Arel::Attributes::String.new(Table.new(:products), :name),
514
+ Arel::Attributes::String.new(Table.new(:products), :name)
515
+ )
516
+ _(compile(node)).must_equal %("products"."name" && "products"."name")
517
+ end
518
+ end
519
+
520
+ describe "Nodes::UnaryOperation" do
521
+ it "should handle BitwiseNot" do
522
+ node = ~ Arel::Attributes::Integer.new(Table.new(:products), :bitmap)
523
+ _(compile(node)).must_equal %( ~ "products"."bitmap")
524
+ end
525
+
526
+ it "should handle arbitrary operators" do
527
+ node = Arel::Nodes::UnaryOperation.new("!", Arel::Attributes::String.new(Table.new(:products), :active))
528
+ _(compile(node)).must_equal %( ! "products"."active")
529
+ end
530
+ end
531
+
532
+ describe "Nodes::Union" do
533
+ it "squashes parenthesis on multiple unions" do
534
+ subnode = Nodes::Union.new Arel.sql("left"), Arel.sql("right")
535
+ node = Nodes::Union.new subnode, Arel.sql("topright")
536
+ assert_equal("( left UNION right UNION topright )", compile(node))
537
+ subnode = Nodes::Union.new Arel.sql("left"), Arel.sql("right")
538
+ node = Nodes::Union.new Arel.sql("topleft"), subnode
539
+ assert_equal("( topleft UNION left UNION right )", compile(node))
540
+ end
541
+ end
542
+
543
+ describe "Nodes::UnionAll" do
544
+ it "squashes parenthesis on multiple union alls" do
545
+ subnode = Nodes::UnionAll.new Arel.sql("left"), Arel.sql("right")
546
+ node = Nodes::UnionAll.new subnode, Arel.sql("topright")
547
+ assert_equal("( left UNION ALL right UNION ALL topright )", compile(node))
548
+ subnode = Nodes::UnionAll.new Arel.sql("left"), Arel.sql("right")
549
+ node = Nodes::UnionAll.new Arel.sql("topleft"), subnode
550
+ assert_equal("( topleft UNION ALL left UNION ALL right )", compile(node))
551
+ end
552
+ end
553
+
554
+ describe "Nodes::NotIn" do
555
+ it "should know how to visit" do
556
+ node = @attr.not_in [1, 2, 3]
557
+ _(compile(node)).must_be_like %{
558
+ "users"."id" NOT IN (1, 2, 3)
559
+ }
560
+ end
561
+
562
+ it "should return 1=1 when empty right which is always true" do
563
+ node = @attr.not_in []
564
+ _(compile(node)).must_equal "1=1"
565
+ end
566
+
567
+ it "can handle two dot ranges" do
568
+ node = @attr.not_between 1..3
569
+ _(compile(node)).must_equal(
570
+ %{("users"."id" < 1 OR "users"."id" > 3)}
571
+ )
572
+ end
573
+
574
+ it "can handle three dot ranges" do
575
+ node = @attr.not_between 1...3
576
+ _(compile(node)).must_equal(
577
+ %{("users"."id" < 1 OR "users"."id" >= 3)}
578
+ )
579
+ end
580
+
581
+ it "can handle ranges bounded by infinity" do
582
+ node = @attr.not_between 1..Float::INFINITY
583
+ _(compile(node)).must_be_like %{
584
+ "users"."id" < 1
585
+ }
586
+ node = @attr.not_between(-Float::INFINITY..3)
587
+ _(compile(node)).must_be_like %{
588
+ "users"."id" > 3
589
+ }
590
+ node = @attr.not_between(-Float::INFINITY...3)
591
+ _(compile(node)).must_be_like %{
592
+ "users"."id" >= 3
593
+ }
594
+ node = @attr.not_between(-Float::INFINITY..Float::INFINITY)
595
+ _(compile(node)).must_be_like %{1=0}
596
+ end
597
+
598
+ it "can handle subqueries" do
599
+ table = Table.new(:users)
600
+ subquery = table.project(:id).where(table[:name].eq("Aaron"))
601
+ node = @attr.not_in subquery
602
+ _(compile(node)).must_be_like %{
603
+ "users"."id" NOT IN (SELECT id FROM "users" WHERE "users"."name" = 'Aaron')
604
+ }
605
+ end
606
+ end
607
+
608
+ describe "Constants" do
609
+ it "should handle true" do
610
+ test = Table.new(:users).create_true
611
+ _(compile(test)).must_be_like %{
612
+ TRUE
613
+ }
614
+ end
615
+
616
+ it "should handle false" do
617
+ test = Table.new(:users).create_false
618
+ _(compile(test)).must_be_like %{
619
+ FALSE
620
+ }
621
+ end
622
+ end
623
+
624
+ describe "TableAlias" do
625
+ it "should use the underlying table for checking columns" do
626
+ test = Table.new(:users).alias("zomgusers")[:id].eq "3"
627
+ _(compile(test)).must_be_like %{
628
+ "zomgusers"."id" = '3'
629
+ }
630
+ end
631
+ end
632
+
633
+ describe "distinct on" do
634
+ it "raises not implemented error" do
635
+ core = Arel::Nodes::SelectCore.new
636
+ core.set_quantifier = Arel::Nodes::DistinctOn.new(Arel.sql("aaron"))
637
+
638
+ assert_raises(NotImplementedError) do
639
+ compile(core)
640
+ end
641
+ end
642
+ end
643
+
644
+ describe "Nodes::Regexp" do
645
+ it "raises not implemented error" do
646
+ node = Arel::Nodes::Regexp.new(@table[:name], Nodes.build_quoted("foo%"))
647
+
648
+ assert_raises(NotImplementedError) do
649
+ compile(node)
650
+ end
651
+ end
652
+ end
653
+
654
+ describe "Nodes::NotRegexp" do
655
+ it "raises not implemented error" do
656
+ node = Arel::Nodes::NotRegexp.new(@table[:name], Nodes.build_quoted("foo%"))
657
+
658
+ assert_raises(NotImplementedError) do
659
+ compile(node)
660
+ end
661
+ end
662
+ end
663
+
664
+ describe "Nodes::Case" do
665
+ it "supports simple case expressions" do
666
+ node = Arel::Nodes::Case.new(@table[:name])
667
+ .when("foo").then(1)
668
+ .else(0)
669
+
670
+ _(compile(node)).must_be_like %{
671
+ CASE "users"."name" WHEN 'foo' THEN 1 ELSE 0 END
672
+ }
673
+ end
674
+
675
+ it "supports extended case expressions" do
676
+ node = Arel::Nodes::Case.new
677
+ .when(@table[:name].in(%w(foo bar))).then(1)
678
+ .else(0)
679
+
680
+ _(compile(node)).must_be_like %{
681
+ CASE WHEN "users"."name" IN ('foo', 'bar') THEN 1 ELSE 0 END
682
+ }
683
+ end
684
+
685
+ it "works without default branch" do
686
+ node = Arel::Nodes::Case.new(@table[:name])
687
+ .when("foo").then(1)
688
+
689
+ _(compile(node)).must_be_like %{
690
+ CASE "users"."name" WHEN 'foo' THEN 1 END
691
+ }
692
+ end
693
+
694
+ it "allows chaining multiple conditions" do
695
+ node = Arel::Nodes::Case.new(@table[:name])
696
+ .when("foo").then(1)
697
+ .when("bar").then(2)
698
+ .else(0)
699
+
700
+ _(compile(node)).must_be_like %{
701
+ CASE "users"."name" WHEN 'foo' THEN 1 WHEN 'bar' THEN 2 ELSE 0 END
702
+ }
703
+ end
704
+
705
+ it "supports #when with two arguments and no #then" do
706
+ node = Arel::Nodes::Case.new @table[:name]
707
+
708
+ { foo: 1, bar: 0 }.reduce(node) { |_node, pair| _node.when(*pair) }
709
+
710
+ _(compile(node)).must_be_like %{
711
+ CASE "users"."name" WHEN 'foo' THEN 1 WHEN 'bar' THEN 0 END
712
+ }
713
+ end
714
+
715
+ it "can be chained as a predicate" do
716
+ node = @table[:name].when("foo").then("bar").else("baz")
717
+
718
+ _(compile(node)).must_be_like %{
719
+ CASE "users"."name" WHEN 'foo' THEN 'bar' ELSE 'baz' END
720
+ }
721
+ end
722
+ end
723
+
724
+ describe "Nodes::With" do
725
+ it "handles table aliases" do
726
+ manager = Table.new(:foo).project(Arel.star).from(Arel.sql("expr2"))
727
+ expr1 = Table.new(:bar).project(Arel.star).as("expr1")
728
+ expr2 = Table.new(:baz).project(Arel.star).as("expr2")
729
+ manager.with(expr1, expr2)
730
+
731
+ _(compile(manager.ast)).must_be_like %{
732
+ WITH expr1 AS (SELECT * FROM "bar"), expr2 AS (SELECT * FROM "baz") SELECT * FROM expr2
733
+ }
734
+ end
735
+ end
736
+
737
+ describe "Nodes::WithRecursive" do
738
+ it "handles table aliases" do
739
+ manager = Table.new(:foo).project(Arel.star).from(Arel.sql("expr1"))
740
+ expr1 = Table.new(:bar).project(Arel.star).as("expr1")
741
+ manager.with(:recursive, expr1)
742
+
743
+ _(compile(manager.ast)).must_be_like %{
744
+ WITH RECURSIVE expr1 AS (SELECT * FROM "bar") SELECT * FROM expr1
745
+ }
746
+ end
747
+ end
748
+ end
749
+ end
750
+ end