sequel 3.21.0 → 3.41.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (363) hide show
  1. data/CHANGELOG +1131 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +106 -65
  4. data/Rakefile +59 -27
  5. data/bin/sequel +50 -26
  6. data/doc/active_record.rdoc +68 -52
  7. data/doc/advanced_associations.rdoc +201 -75
  8. data/doc/association_basics.rdoc +327 -79
  9. data/doc/bin_sequel.rdoc +144 -0
  10. data/doc/cheat_sheet.rdoc +21 -21
  11. data/doc/core_extensions.rdoc +374 -0
  12. data/doc/dataset_basics.rdoc +10 -10
  13. data/doc/dataset_filtering.rdoc +54 -42
  14. data/doc/mass_assignment.rdoc +56 -0
  15. data/doc/migration.rdoc +89 -557
  16. data/doc/model_hooks.rdoc +80 -29
  17. data/doc/object_model.rdoc +576 -0
  18. data/doc/opening_databases.rdoc +121 -53
  19. data/doc/prepared_statements.rdoc +41 -15
  20. data/doc/querying.rdoc +137 -56
  21. data/doc/reflection.rdoc +36 -10
  22. data/doc/release_notes/3.22.0.txt +39 -0
  23. data/doc/release_notes/3.23.0.txt +172 -0
  24. data/doc/release_notes/3.24.0.txt +420 -0
  25. data/doc/release_notes/3.25.0.txt +88 -0
  26. data/doc/release_notes/3.26.0.txt +88 -0
  27. data/doc/release_notes/3.27.0.txt +82 -0
  28. data/doc/release_notes/3.28.0.txt +304 -0
  29. data/doc/release_notes/3.29.0.txt +459 -0
  30. data/doc/release_notes/3.30.0.txt +135 -0
  31. data/doc/release_notes/3.31.0.txt +146 -0
  32. data/doc/release_notes/3.32.0.txt +202 -0
  33. data/doc/release_notes/3.33.0.txt +157 -0
  34. data/doc/release_notes/3.34.0.txt +671 -0
  35. data/doc/release_notes/3.35.0.txt +144 -0
  36. data/doc/release_notes/3.36.0.txt +245 -0
  37. data/doc/release_notes/3.37.0.txt +338 -0
  38. data/doc/release_notes/3.38.0.txt +234 -0
  39. data/doc/release_notes/3.39.0.txt +237 -0
  40. data/doc/release_notes/3.40.0.txt +73 -0
  41. data/doc/release_notes/3.41.0.txt +155 -0
  42. data/doc/schema_modification.rdoc +585 -0
  43. data/doc/sharding.rdoc +99 -8
  44. data/doc/sql.rdoc +154 -112
  45. data/doc/testing.rdoc +169 -0
  46. data/doc/thread_safety.rdoc +17 -0
  47. data/doc/transactions.rdoc +137 -0
  48. data/doc/validations.rdoc +1 -1
  49. data/doc/virtual_rows.rdoc +78 -43
  50. data/lib/sequel/adapters/ado/access.rb +334 -0
  51. data/lib/sequel/adapters/ado/mssql.rb +18 -12
  52. data/lib/sequel/adapters/ado.rb +69 -21
  53. data/lib/sequel/adapters/amalgalite.rb +17 -14
  54. data/lib/sequel/adapters/cubrid.rb +143 -0
  55. data/lib/sequel/adapters/db2.rb +178 -85
  56. data/lib/sequel/adapters/dbi.rb +19 -21
  57. data/lib/sequel/adapters/do/mysql.rb +17 -11
  58. data/lib/sequel/adapters/do/postgres.rb +2 -61
  59. data/lib/sequel/adapters/do/sqlite.rb +0 -10
  60. data/lib/sequel/adapters/do.rb +20 -39
  61. data/lib/sequel/adapters/firebird.rb +33 -210
  62. data/lib/sequel/adapters/ibmdb.rb +452 -0
  63. data/lib/sequel/adapters/informix.rb +6 -29
  64. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  65. data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
  66. data/lib/sequel/adapters/jdbc/db2.rb +78 -0
  67. data/lib/sequel/adapters/jdbc/derby.rb +325 -0
  68. data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
  69. data/lib/sequel/adapters/jdbc/h2.rb +68 -31
  70. data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
  71. data/lib/sequel/adapters/jdbc/informix.rb +21 -0
  72. data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
  73. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  74. data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
  75. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  76. data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
  77. data/lib/sequel/adapters/jdbc/progress.rb +21 -0
  78. data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
  79. data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
  80. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  81. data/lib/sequel/adapters/jdbc.rb +308 -114
  82. data/lib/sequel/adapters/mock.rb +372 -0
  83. data/lib/sequel/adapters/mysql.rb +130 -230
  84. data/lib/sequel/adapters/mysql2.rb +64 -63
  85. data/lib/sequel/adapters/odbc/mssql.rb +17 -9
  86. data/lib/sequel/adapters/odbc.rb +29 -10
  87. data/lib/sequel/adapters/openbase.rb +7 -11
  88. data/lib/sequel/adapters/oracle.rb +364 -57
  89. data/lib/sequel/adapters/postgres.rb +379 -145
  90. data/lib/sequel/adapters/shared/access.rb +236 -11
  91. data/lib/sequel/adapters/shared/cubrid.rb +216 -0
  92. data/lib/sequel/adapters/shared/db2.rb +353 -0
  93. data/lib/sequel/adapters/shared/firebird.rb +231 -0
  94. data/lib/sequel/adapters/shared/informix.rb +53 -0
  95. data/lib/sequel/adapters/shared/mssql.rb +412 -116
  96. data/lib/sequel/adapters/shared/mysql.rb +396 -89
  97. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
  98. data/lib/sequel/adapters/shared/oracle.rb +262 -45
  99. data/lib/sequel/adapters/shared/postgres.rb +688 -279
  100. data/lib/sequel/adapters/shared/progress.rb +5 -8
  101. data/lib/sequel/adapters/shared/sqlite.rb +317 -96
  102. data/lib/sequel/adapters/sqlite.rb +109 -46
  103. data/lib/sequel/adapters/swift/mysql.rb +10 -12
  104. data/lib/sequel/adapters/swift/postgres.rb +13 -79
  105. data/lib/sequel/adapters/swift/sqlite.rb +9 -6
  106. data/lib/sequel/adapters/swift.rb +31 -27
  107. data/lib/sequel/adapters/tinytds.rb +177 -25
  108. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
  109. data/lib/sequel/adapters/utils/pg_types.rb +81 -0
  110. data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
  111. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  112. data/lib/sequel/ast_transformer.rb +194 -0
  113. data/lib/sequel/connection_pool/sharded_single.rb +23 -13
  114. data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
  115. data/lib/sequel/connection_pool/single.rb +11 -3
  116. data/lib/sequel/connection_pool/threaded.rb +69 -20
  117. data/lib/sequel/connection_pool.rb +20 -18
  118. data/lib/sequel/core.rb +143 -11
  119. data/lib/sequel/database/connecting.rb +66 -29
  120. data/lib/sequel/database/dataset.rb +4 -4
  121. data/lib/sequel/database/dataset_defaults.rb +63 -2
  122. data/lib/sequel/database/logging.rb +7 -2
  123. data/lib/sequel/database/misc.rb +192 -51
  124. data/lib/sequel/database/query.rb +299 -114
  125. data/lib/sequel/database/schema_generator.rb +103 -36
  126. data/lib/sequel/database/schema_methods.rb +310 -69
  127. data/lib/sequel/dataset/actions.rb +344 -90
  128. data/lib/sequel/dataset/features.rb +101 -8
  129. data/lib/sequel/dataset/graph.rb +42 -15
  130. data/lib/sequel/dataset/misc.rb +52 -25
  131. data/lib/sequel/dataset/mutation.rb +12 -7
  132. data/lib/sequel/dataset/prepared_statements.rb +68 -30
  133. data/lib/sequel/dataset/query.rb +322 -68
  134. data/lib/sequel/dataset/sql.rb +716 -293
  135. data/lib/sequel/dataset.rb +8 -0
  136. data/lib/sequel/exceptions.rb +4 -0
  137. data/lib/sequel/extensions/_pretty_table.rb +83 -0
  138. data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
  139. data/lib/sequel/extensions/blank.rb +4 -0
  140. data/lib/sequel/extensions/columns_introspection.rb +72 -0
  141. data/lib/sequel/extensions/connection_validator.rb +109 -0
  142. data/lib/sequel/extensions/constraint_validations.rb +451 -0
  143. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
  144. data/lib/sequel/extensions/eval_inspect.rb +173 -0
  145. data/lib/sequel/extensions/inflector.rb +4 -0
  146. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  147. data/lib/sequel/extensions/migration.rb +100 -11
  148. data/lib/sequel/extensions/named_timezones.rb +9 -0
  149. data/lib/sequel/extensions/null_dataset.rb +94 -0
  150. data/lib/sequel/extensions/pagination.rb +4 -0
  151. data/lib/sequel/extensions/pg_array.rb +539 -0
  152. data/lib/sequel/extensions/pg_array_ops.rb +263 -0
  153. data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
  154. data/lib/sequel/extensions/pg_hstore.rb +334 -0
  155. data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
  156. data/lib/sequel/extensions/pg_inet.rb +113 -0
  157. data/lib/sequel/extensions/pg_interval.rb +191 -0
  158. data/lib/sequel/extensions/pg_json.rb +212 -0
  159. data/lib/sequel/extensions/pg_range.rb +513 -0
  160. data/lib/sequel/extensions/pg_range_ops.rb +150 -0
  161. data/lib/sequel/extensions/pg_row.rb +576 -0
  162. data/lib/sequel/extensions/pg_row_ops.rb +182 -0
  163. data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
  164. data/lib/sequel/extensions/pretty_table.rb +17 -72
  165. data/lib/sequel/extensions/query.rb +8 -4
  166. data/lib/sequel/extensions/query_literals.rb +79 -0
  167. data/lib/sequel/extensions/schema_caching.rb +76 -0
  168. data/lib/sequel/extensions/schema_dumper.rb +282 -76
  169. data/lib/sequel/extensions/select_remove.rb +39 -0
  170. data/lib/sequel/extensions/server_block.rb +140 -0
  171. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  172. data/lib/sequel/extensions/sql_expr.rb +8 -110
  173. data/lib/sequel/extensions/string_date_time.rb +4 -0
  174. data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
  175. data/lib/sequel/extensions/to_dot.rb +99 -83
  176. data/lib/sequel/model/associations.rb +1263 -409
  177. data/lib/sequel/model/base.rb +624 -171
  178. data/lib/sequel/model/errors.rb +1 -1
  179. data/lib/sequel/model/exceptions.rb +24 -2
  180. data/lib/sequel/model/inflections.rb +1 -1
  181. data/lib/sequel/model.rb +30 -11
  182. data/lib/sequel/no_core_ext.rb +2 -0
  183. data/lib/sequel/plugins/active_model.rb +13 -1
  184. data/lib/sequel/plugins/association_pks.rb +137 -16
  185. data/lib/sequel/plugins/caching.rb +25 -18
  186. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  187. data/lib/sequel/plugins/composition.rb +44 -12
  188. data/lib/sequel/plugins/constraint_validations.rb +198 -0
  189. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  190. data/lib/sequel/plugins/defaults_setter.rb +72 -0
  191. data/lib/sequel/plugins/dirty.rb +214 -0
  192. data/lib/sequel/plugins/eager_each.rb +59 -0
  193. data/lib/sequel/plugins/force_encoding.rb +6 -6
  194. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  195. data/lib/sequel/plugins/identity_map.rb +134 -15
  196. data/lib/sequel/plugins/instance_filters.rb +10 -0
  197. data/lib/sequel/plugins/instance_hooks.rb +1 -1
  198. data/lib/sequel/plugins/json_serializer.rb +77 -6
  199. data/lib/sequel/plugins/list.rb +13 -2
  200. data/lib/sequel/plugins/many_through_many.rb +103 -51
  201. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  202. data/lib/sequel/plugins/nested_attributes.rb +150 -66
  203. data/lib/sequel/plugins/optimistic_locking.rb +8 -0
  204. data/lib/sequel/plugins/pg_row.rb +121 -0
  205. data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
  206. data/lib/sequel/plugins/prepared_statements.rb +168 -0
  207. data/lib/sequel/plugins/prepared_statements_associations.rb +87 -0
  208. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  209. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  210. data/lib/sequel/plugins/rcte_tree.rb +31 -17
  211. data/lib/sequel/plugins/schema.rb +8 -3
  212. data/lib/sequel/plugins/serialization.rb +98 -49
  213. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  214. data/lib/sequel/plugins/sharding.rb +21 -54
  215. data/lib/sequel/plugins/single_table_inheritance.rb +57 -12
  216. data/lib/sequel/plugins/static_cache.rb +99 -0
  217. data/lib/sequel/plugins/subclasses.rb +29 -3
  218. data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
  219. data/lib/sequel/plugins/timestamps.rb +1 -1
  220. data/lib/sequel/plugins/touch.rb +18 -6
  221. data/lib/sequel/plugins/tree.rb +3 -3
  222. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  223. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  224. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  225. data/lib/sequel/plugins/validation_helpers.rb +57 -4
  226. data/lib/sequel/plugins/xml_serializer.rb +15 -4
  227. data/lib/sequel/sql.rb +721 -141
  228. data/lib/sequel/timezones.rb +67 -40
  229. data/lib/sequel/version.rb +1 -1
  230. data/spec/adapters/db2_spec.rb +146 -0
  231. data/spec/adapters/firebird_spec.rb +53 -39
  232. data/spec/adapters/mssql_spec.rb +261 -66
  233. data/spec/adapters/mysql_spec.rb +597 -352
  234. data/spec/adapters/oracle_spec.rb +92 -117
  235. data/spec/adapters/postgres_spec.rb +2103 -341
  236. data/spec/adapters/spec_helper.rb +16 -6
  237. data/spec/adapters/sqlite_spec.rb +237 -76
  238. data/spec/core/connection_pool_spec.rb +270 -141
  239. data/spec/core/database_spec.rb +980 -524
  240. data/spec/core/dataset_spec.rb +1658 -1243
  241. data/spec/core/expression_filters_spec.rb +741 -334
  242. data/spec/core/mock_adapter_spec.rb +453 -0
  243. data/spec/core/object_graph_spec.rb +88 -129
  244. data/spec/core/schema_generator_spec.rb +4 -4
  245. data/spec/core/schema_spec.rb +556 -53
  246. data/spec/core/spec_helper.rb +7 -48
  247. data/spec/core_extensions_spec.rb +626 -0
  248. data/spec/extensions/active_model_spec.rb +13 -0
  249. data/spec/extensions/arbitrary_servers_spec.rb +110 -0
  250. data/spec/extensions/association_autoreloading_spec.rb +18 -10
  251. data/spec/extensions/association_dependencies_spec.rb +15 -25
  252. data/spec/extensions/association_pks_spec.rb +227 -33
  253. data/spec/extensions/association_proxies_spec.rb +4 -4
  254. data/spec/extensions/boolean_readers_spec.rb +25 -25
  255. data/spec/extensions/caching_spec.rb +47 -51
  256. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  257. data/spec/extensions/columns_introspection_spec.rb +91 -0
  258. data/spec/extensions/composition_spec.rb +18 -13
  259. data/spec/extensions/connection_validator_spec.rb +118 -0
  260. data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
  261. data/spec/extensions/constraint_validations_spec.rb +316 -0
  262. data/spec/extensions/dataset_associations_spec.rb +199 -0
  263. data/spec/extensions/defaults_setter_spec.rb +88 -0
  264. data/spec/extensions/dirty_spec.rb +155 -0
  265. data/spec/extensions/eager_each_spec.rb +34 -0
  266. data/spec/extensions/eval_inspect_spec.rb +67 -0
  267. data/spec/extensions/force_encoding_spec.rb +4 -2
  268. data/spec/extensions/hook_class_methods_spec.rb +97 -128
  269. data/spec/extensions/identity_map_spec.rb +142 -24
  270. data/spec/extensions/inflector_spec.rb +0 -4
  271. data/spec/extensions/instance_filters_spec.rb +11 -21
  272. data/spec/extensions/instance_hooks_spec.rb +72 -0
  273. data/spec/extensions/json_serializer_spec.rb +49 -12
  274. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  275. data/spec/extensions/list_spec.rb +49 -40
  276. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  277. data/spec/extensions/many_through_many_spec.rb +368 -254
  278. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  279. data/spec/extensions/migration_spec.rb +140 -35
  280. data/spec/extensions/named_timezones_spec.rb +29 -11
  281. data/spec/extensions/nested_attributes_spec.rb +268 -89
  282. data/spec/extensions/null_dataset_spec.rb +85 -0
  283. data/spec/extensions/optimistic_locking_spec.rb +24 -21
  284. data/spec/extensions/pg_array_ops_spec.rb +112 -0
  285. data/spec/extensions/pg_array_spec.rb +324 -0
  286. data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
  287. data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
  288. data/spec/extensions/pg_hstore_spec.rb +200 -0
  289. data/spec/extensions/pg_inet_spec.rb +47 -0
  290. data/spec/extensions/pg_interval_spec.rb +72 -0
  291. data/spec/extensions/pg_json_spec.rb +99 -0
  292. data/spec/extensions/pg_range_ops_spec.rb +56 -0
  293. data/spec/extensions/pg_range_spec.rb +395 -0
  294. data/spec/extensions/pg_row_ops_spec.rb +58 -0
  295. data/spec/extensions/pg_row_plugin_spec.rb +49 -0
  296. data/spec/extensions/pg_row_spec.rb +340 -0
  297. data/spec/extensions/pg_statement_cache_spec.rb +208 -0
  298. data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
  299. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  300. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  301. data/spec/extensions/prepared_statements_spec.rb +87 -0
  302. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  303. data/spec/extensions/pretty_table_spec.rb +7 -6
  304. data/spec/extensions/query_literals_spec.rb +167 -0
  305. data/spec/extensions/query_spec.rb +9 -3
  306. data/spec/extensions/rcte_tree_spec.rb +50 -43
  307. data/spec/extensions/schema_caching_spec.rb +41 -0
  308. data/spec/extensions/schema_dumper_spec.rb +434 -49
  309. data/spec/extensions/schema_spec.rb +30 -49
  310. data/spec/extensions/select_remove_spec.rb +38 -0
  311. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  312. data/spec/extensions/serialization_spec.rb +86 -48
  313. data/spec/extensions/server_block_spec.rb +90 -0
  314. data/spec/extensions/sharding_spec.rb +69 -143
  315. data/spec/extensions/single_table_inheritance_spec.rb +65 -29
  316. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  317. data/spec/extensions/spec_helper.rb +34 -67
  318. data/spec/extensions/split_array_nil_spec.rb +24 -0
  319. data/spec/extensions/sql_expr_spec.rb +29 -60
  320. data/spec/extensions/static_cache_spec.rb +145 -0
  321. data/spec/extensions/subclasses_spec.rb +14 -0
  322. data/spec/extensions/tactical_eager_loading_spec.rb +17 -19
  323. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  324. data/spec/extensions/timestamps_spec.rb +6 -6
  325. data/spec/extensions/to_dot_spec.rb +8 -11
  326. data/spec/extensions/touch_spec.rb +53 -14
  327. data/spec/extensions/tree_spec.rb +11 -26
  328. data/spec/extensions/typecast_on_load_spec.rb +9 -6
  329. data/spec/extensions/update_primary_key_spec.rb +30 -24
  330. data/spec/extensions/validation_class_methods_spec.rb +77 -68
  331. data/spec/extensions/validation_helpers_spec.rb +48 -37
  332. data/spec/extensions/xml_serializer_spec.rb +29 -4
  333. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
  334. data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
  335. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
  336. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
  337. data/spec/integration/associations_test.rb +659 -21
  338. data/spec/integration/database_test.rb +25 -5
  339. data/spec/integration/dataset_test.rb +729 -141
  340. data/spec/integration/eager_loader_test.rb +38 -54
  341. data/spec/integration/migrator_test.rb +2 -3
  342. data/spec/integration/model_test.rb +81 -2
  343. data/spec/integration/plugin_test.rb +871 -160
  344. data/spec/integration/prepared_statement_test.rb +272 -128
  345. data/spec/integration/schema_test.rb +377 -57
  346. data/spec/integration/spec_helper.rb +49 -32
  347. data/spec/integration/timezone_test.rb +38 -12
  348. data/spec/integration/transaction_test.rb +183 -8
  349. data/spec/integration/type_test.rb +40 -8
  350. data/spec/model/association_reflection_spec.rb +207 -8
  351. data/spec/model/associations_spec.rb +1206 -693
  352. data/spec/model/base_spec.rb +334 -100
  353. data/spec/model/dataset_methods_spec.rb +45 -27
  354. data/spec/model/eager_loading_spec.rb +828 -692
  355. data/spec/model/hooks_spec.rb +355 -67
  356. data/spec/model/model_spec.rb +251 -179
  357. data/spec/model/plugins_spec.rb +24 -13
  358. data/spec/model/record_spec.rb +506 -232
  359. data/spec/model/spec_helper.rb +16 -77
  360. data/spec/model/validations_spec.rb +38 -2
  361. data/spec/rcov.opts +2 -0
  362. metadata +223 -81
  363. data/spec/core/core_sql_spec.rb +0 -451
@@ -0,0 +1,353 @@
1
+ Sequel.require 'adapters/utils/emulate_offset_with_row_number'
2
+
3
+ module Sequel
4
+ module DB2
5
+ @use_clob_as_blob = true
6
+
7
+ class << self
8
+ # Whether to use clob as the generic File type, true by default.
9
+ attr_accessor :use_clob_as_blob
10
+ end
11
+
12
+ module DatabaseMethods
13
+ AUTOINCREMENT = 'GENERATED ALWAYS AS IDENTITY'.freeze
14
+ NOT_NULL = ' NOT NULL'.freeze
15
+ NULL = ''.freeze
16
+
17
+ # DB2 always uses :db2 as it's database type
18
+ def database_type
19
+ :db2
20
+ end
21
+
22
+ # Return the database version as a string. Don't rely on this,
23
+ # it may return an integer in the future.
24
+ def db2_version
25
+ return @db2_version if @db2_version
26
+ @db2_version = metadata_dataset.with_sql("select service_level from sysibmadm.env_inst_info").first[:service_level]
27
+ end
28
+ alias_method :server_version, :db2_version
29
+
30
+ # Use SYSIBM.SYSCOLUMNS to get the information on the tables.
31
+ def schema_parse_table(table, opts = {})
32
+ m = output_identifier_meth(opts[:dataset])
33
+ im = input_identifier_meth(opts[:dataset])
34
+ metadata_dataset.with_sql("SELECT * FROM SYSIBM.SYSCOLUMNS WHERE TBNAME = #{literal(im.call(table))} ORDER BY COLNO").
35
+ collect do |column|
36
+ column[:db_type] = column.delete(:typename)
37
+ if column[:db_type] == "DECIMAL"
38
+ column[:db_type] << "(#{column[:longlength]},#{column[:scale]})"
39
+ end
40
+ column[:allow_null] = column.delete(:nulls) == 'Y'
41
+ column[:primary_key] = column.delete(:identity) == 'Y' || !column[:keyseq].nil?
42
+ column[:type] = schema_column_type(column[:db_type])
43
+ [ m.call(column.delete(:name)), column]
44
+ end
45
+ end
46
+
47
+ # Use SYSCAT.TABLES to get the tables for the database
48
+ def tables
49
+ metadata_dataset.
50
+ with_sql("SELECT TABNAME FROM SYSCAT.TABLES WHERE TYPE='T' AND OWNER = #{literal(input_identifier_meth.call(opts[:user]))}").
51
+ all.map{|h| output_identifier_meth.call(h[:tabname]) }
52
+ end
53
+
54
+ # Use SYSCAT.TABLES to get the views for the database
55
+ def views
56
+ metadata_dataset.
57
+ with_sql("SELECT TABNAME FROM SYSCAT.TABLES WHERE TYPE='V' AND OWNER = #{literal(input_identifier_meth.call(opts[:user]))}").
58
+ all.map{|h| output_identifier_meth.call(h[:tabname]) }
59
+ end
60
+
61
+ # Use SYSCAT.INDEXES to get the indexes for the table
62
+ def indexes(table, opts = {})
63
+ m = output_identifier_meth
64
+ indexes = {}
65
+ metadata_dataset.
66
+ from(:syscat__indexes).
67
+ select(:indname, :uniquerule, :colnames).
68
+ where(:tabname=>input_identifier_meth.call(table), :system_required=>0).
69
+ each do |r|
70
+ indexes[m.call(r[:indname])] = {:unique=>(r[:uniquerule]=='U'), :columns=>r[:colnames][1..-1].split('+').map{|v| m.call(v)}}
71
+ end
72
+ indexes
73
+ end
74
+
75
+ private
76
+
77
+ # Handle DB2 specific alter table operations.
78
+ def alter_table_sql(table, op)
79
+ case op[:op]
80
+ when :add_column
81
+ if op[:primary_key] && op[:auto_increment] && op[:type] == Integer
82
+ [
83
+ "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op.merge(:auto_increment=>false, :primary_key=>false, :default=>0, :null=>false))}",
84
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{literal(op[:name])} DROP DEFAULT",
85
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{literal(op[:name])} SET #{AUTOINCREMENT}"
86
+ ]
87
+ else
88
+ "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
89
+ end
90
+ when :drop_column
91
+ "ALTER TABLE #{quote_schema_table(table)} DROP #{column_definition_sql(op)}"
92
+ when :rename_column # renaming is only possible after db2 v9.7
93
+ "ALTER TABLE #{quote_schema_table(table)} RENAME COLUMN #{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
94
+ when :set_column_type
95
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET DATA TYPE #{type_literal(op)}"
96
+ when :set_column_default
97
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET DEFAULT #{literal(op[:default])}"
98
+ when :add_constraint
99
+ if op[:type] == :unique
100
+ sqls = op[:columns].map{|c| ["ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(c)} SET NOT NULL", reorg_sql(table)]}
101
+ sqls << super
102
+ sqls.flatten
103
+ else
104
+ super
105
+ end
106
+ else
107
+ super
108
+ end
109
+ end
110
+
111
+ # DB2 uses an identity column for autoincrement.
112
+ def auto_increment_sql
113
+ AUTOINCREMENT
114
+ end
115
+
116
+ # Add null/not null SQL fragment to column creation SQL.
117
+ def column_definition_null_sql(sql, column)
118
+ null = column.fetch(:null, column[:allow_null])
119
+ null = false if column[:primary_key]
120
+
121
+ sql << NOT_NULL if null == false
122
+ sql << NULL if null == true
123
+ end
124
+
125
+ # Supply columns with NOT NULL if they are part of a composite
126
+ # primary key or unique constraint
127
+ def column_list_sql(g)
128
+ ks = []
129
+ g.constraints.each{|c| ks = c[:columns] if [:primary_key, :unique].include?(c[:type])}
130
+ g.columns.each{|c| c[:null] = false if ks.include?(c[:name]) }
131
+ super
132
+ end
133
+
134
+ # Insert data from the current table into the new table after
135
+ # creating the table, since it is not possible to do it in one step.
136
+ def create_table_as(name, sql, options)
137
+ super
138
+ from(name).insert(sql.is_a?(Dataset) ? sql : dataset.with_sql(sql))
139
+ end
140
+
141
+ # DB2 requires parens around the SELECT, and DEFINITION ONLY at the end.
142
+ def create_table_as_sql(name, sql, options)
143
+ "#{create_table_prefix_sql(name, options)} AS (#{sql}) DEFINITION ONLY"
144
+ end
145
+
146
+ # Here we use DGTT which has most backward compatibility, which uses
147
+ # DECLARE instead of CREATE. CGTT can only be used after version 9.7.
148
+ # http://www.ibm.com/developerworks/data/library/techarticle/dm-0912globaltemptable/
149
+ def create_table_prefix_sql(name, options)
150
+ if options[:temp]
151
+ "DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)}"
152
+ else
153
+ super
154
+ end
155
+ end
156
+
157
+ # DB2 has issues with quoted identifiers, so
158
+ # turn off database quoting by default.
159
+ def quote_identifiers_default
160
+ false
161
+ end
162
+
163
+ # DB2 uses RENAME TABLE to rename tables.
164
+ def rename_table_sql(name, new_name)
165
+ "RENAME TABLE #{quote_schema_table(name)} TO #{quote_schema_table(new_name)}"
166
+ end
167
+
168
+ # Run the REORG TABLE command for the table, necessary when
169
+ # the table has been altered.
170
+ def reorg(table)
171
+ synchronize(opts[:server]){|c| c.execute(reorg_sql(table))}
172
+ end
173
+
174
+ # The SQL to use for REORGing a table.
175
+ def reorg_sql(table)
176
+ "CALL ADMIN_CMD(#{literal("REORG TABLE #{table}")})"
177
+ end
178
+
179
+ # Treat clob as blob if use_clob_as_blob is true
180
+ def schema_column_type(db_type)
181
+ (::Sequel::DB2::use_clob_as_blob && db_type.downcase == 'clob') ? :blob : super
182
+ end
183
+
184
+ # We uses the clob type by default for Files.
185
+ # Note: if user select to use blob, then insert statement should use
186
+ # use this for blob value:
187
+ # cast(X'fffefdfcfbfa' as blob(2G))
188
+ def type_literal_generic_file(column)
189
+ ::Sequel::DB2::use_clob_as_blob ? :clob : :blob
190
+ end
191
+
192
+ # DB2 uses smallint to store booleans.
193
+ def type_literal_generic_trueclass(column)
194
+ :smallint
195
+ end
196
+ alias type_literal_generic_falseclass type_literal_generic_trueclass
197
+
198
+ # DB2 uses clob for text types.
199
+ def uses_clob_for_text?
200
+ true
201
+ end
202
+ end
203
+
204
+ module DatasetMethods
205
+ include EmulateOffsetWithRowNumber
206
+
207
+ PAREN_CLOSE = Dataset::PAREN_CLOSE
208
+ PAREN_OPEN = Dataset::PAREN_OPEN
209
+ BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR, :'B~'=>:BITNOT}
210
+ EMULATED_FUNCTION_MAP = {:char_length=>'length'.freeze}
211
+ BOOL_TRUE = '1'.freeze
212
+ BOOL_FALSE = '0'.freeze
213
+ CAST_STRING_OPEN = "RTRIM(CHAR(".freeze
214
+ CAST_STRING_CLOSE = "))".freeze
215
+ FETCH_FIRST_ROW_ONLY = " FETCH FIRST ROW ONLY".freeze
216
+ FETCH_FIRST = " FETCH FIRST ".freeze
217
+ ROWS_ONLY = " ROWS ONLY".freeze
218
+ EMPTY_FROM_TABLE = ' FROM "SYSIBM"."SYSDUMMY1"'.freeze
219
+
220
+ # DB2 casts strings using RTRIM and CHAR instead of VARCHAR.
221
+ def cast_sql_append(sql, expr, type)
222
+ if(type == String)
223
+ sql << CAST_STRING_OPEN
224
+ literal_append(sql, expr)
225
+ sql << CAST_STRING_CLOSE
226
+ else
227
+ super
228
+ end
229
+ end
230
+
231
+ # Handle DB2 specific LIKE and bitwise operator support, and
232
+ # emulate the extract method, which DB2 doesn't natively support.
233
+ def complex_expression_sql_append(sql, op, args)
234
+ case op
235
+ when :ILIKE
236
+ super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1)) ])
237
+ when :"NOT ILIKE"
238
+ super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1)) ])
239
+ when :&, :|, :^
240
+ # works with db2 v9.5 and after
241
+ op = BITWISE_METHOD_MAP[op]
242
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
243
+ when :<<
244
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
245
+ when :>>
246
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
247
+ when :%
248
+ sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
249
+ when :'B~'
250
+ literal_append(sql, SQL::Function.new(:BITNOT, *args))
251
+ when :extract
252
+ sql << args.at(0).to_s
253
+ sql << PAREN_OPEN
254
+ literal_append(sql, args.at(1))
255
+ sql << PAREN_CLOSE
256
+ else
257
+ super
258
+ end
259
+ end
260
+
261
+ # DB2 supports GROUP BY CUBE
262
+ def supports_group_cube?
263
+ true
264
+ end
265
+
266
+ # DB2 supports GROUP BY ROLLUP
267
+ def supports_group_rollup?
268
+ true
269
+ end
270
+
271
+ # DB2 does not support IS TRUE.
272
+ def supports_is_true?
273
+ false
274
+ end
275
+
276
+ # DB2 does not support multiple columns in IN.
277
+ def supports_multiple_column_in?
278
+ false
279
+ end
280
+
281
+ # DB2 only allows * in SELECT if it is the only thing being selected.
282
+ def supports_select_all_and_column?
283
+ false
284
+ end
285
+
286
+ # DB2 does not support fractional seconds in timestamps.
287
+ def supports_timestamp_usecs?
288
+ false
289
+ end
290
+
291
+ # DB2 supports window functions
292
+ def supports_window_functions?
293
+ true
294
+ end
295
+
296
+ # DB2 does not support WHERE 1.
297
+ def supports_where_true?
298
+ false
299
+ end
300
+
301
+ private
302
+
303
+ # DB2 needs the standard workaround to insert all default values into
304
+ # a table with more than one column.
305
+ def insert_supports_empty_values?
306
+ false
307
+ end
308
+
309
+ # Use 0 for false on DB2
310
+ def literal_false
311
+ BOOL_FALSE
312
+ end
313
+
314
+ # Use 1 for true on DB2
315
+ def literal_true
316
+ BOOL_TRUE
317
+ end
318
+
319
+ # Add a fallback table for empty from situation
320
+ def select_from_sql(sql)
321
+ @opts[:from] ? super : (sql << EMPTY_FROM_TABLE)
322
+ end
323
+
324
+ # Modify the sql to limit the number of rows returned
325
+ # Note:
326
+ #
327
+ # After db2 v9.7, MySQL flavored "LIMIT X OFFSET Y" can be enabled using
328
+ #
329
+ # db2set DB2_COMPATIBILITY_VECTOR=MYSQL
330
+ # db2stop
331
+ # db2start
332
+ #
333
+ # Support for this feature is not used in this adapter however.
334
+ def select_limit_sql(sql)
335
+ if l = @opts[:limit]
336
+ if l == 1
337
+ sql << FETCH_FIRST_ROW_ONLY
338
+ else
339
+ sql << FETCH_FIRST
340
+ literal_append(sql, l)
341
+ sql << ROWS_ONLY
342
+ end
343
+ end
344
+ end
345
+
346
+ def _truncate_sql(table)
347
+ # "TRUNCATE #{table} IMMEDIATE" is only for newer version of db2, so we
348
+ # use the following one
349
+ "ALTER TABLE #{quote_schema_table(table)} ACTIVATE NOT LOGGED INITIALLY WITH EMPTY TABLE"
350
+ end
351
+ end
352
+ end
353
+ end
@@ -0,0 +1,231 @@
1
+ module Sequel
2
+ module Firebird
3
+ module DatabaseMethods
4
+ AUTO_INCREMENT = ''.freeze
5
+ TEMPORARY = 'GLOBAL TEMPORARY '.freeze
6
+
7
+ def clear_primary_key(*tables)
8
+ tables.each{|t| @primary_keys.delete(dataset.send(:input_identifier, t))}
9
+ end
10
+
11
+ def create_trigger(*args)
12
+ self << create_trigger_sql(*args)
13
+ end
14
+
15
+ def database_type
16
+ :firebird
17
+ end
18
+
19
+ def drop_sequence(name)
20
+ self << drop_sequence_sql(name)
21
+ end
22
+
23
+ # Return primary key for the given table.
24
+ def primary_key(table)
25
+ t = dataset.send(:input_identifier, table)
26
+ @primary_keys.fetch(t) do
27
+ pk = fetch("SELECT RDB$FIELD_NAME FROM RDB$INDEX_SEGMENTS NATURAL JOIN RDB$RELATION_CONSTRAINTS WHERE RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' AND RDB$RELATION_NAME = ?", t).single_value
28
+ @primary_keys[t] = dataset.send(:output_identifier, pk.rstrip) if pk
29
+ end
30
+ end
31
+
32
+ def restart_sequence(*args)
33
+ self << restart_sequence_sql(*args)
34
+ end
35
+
36
+ def sequences(opts={})
37
+ ds = self[:"rdb$generators"].server(opts[:server]).filter(:"rdb$system_flag" => 0).select(:"rdb$generator_name")
38
+ block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$generator_name"])}
39
+ end
40
+
41
+ def tables(opts={})
42
+ tables_or_views(0, opts)
43
+ end
44
+
45
+ def views(opts={})
46
+ tables_or_views(1, opts)
47
+ end
48
+
49
+ private
50
+
51
+ # Use Firebird specific syntax for add column
52
+ def alter_table_sql(table, op)
53
+ case op[:op]
54
+ when :add_column
55
+ "ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
56
+ when :drop_column
57
+ "ALTER TABLE #{quote_schema_table(table)} DROP #{column_definition_sql(op)}"
58
+ when :rename_column
59
+ "ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
60
+ when :set_column_type
61
+ "ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TYPE #{type_literal(op)}"
62
+ else
63
+ super(table, op)
64
+ end
65
+ end
66
+
67
+ def auto_increment_sql()
68
+ AUTO_INCREMENT
69
+ end
70
+
71
+ def create_sequence_sql(name, opts={})
72
+ "CREATE SEQUENCE #{quote_identifier(name)}"
73
+ end
74
+
75
+ # Firebird gets an override because of the mess of creating a
76
+ # sequence and trigger for auto-incrementing primary keys.
77
+ def create_table_from_generator(name, generator, options)
78
+ drop_statement, create_statements = create_table_sql_list(name, generator, options)
79
+ (execute_ddl(drop_statement) rescue nil) if drop_statement
80
+ create_statements.each{|sql| execute_ddl(sql)}
81
+ end
82
+
83
+ def create_table_sql_list(name, generator, options={})
84
+ statements = [create_table_sql(name, generator, options)]
85
+ drop_seq_statement = nil
86
+ generator.columns.each do |c|
87
+ if c[:auto_increment]
88
+ c[:sequence_name] ||= "seq_#{name}_#{c[:name]}"
89
+ unless c[:create_sequence] == false
90
+ drop_seq_statement = drop_sequence_sql(c[:sequence_name])
91
+ statements << create_sequence_sql(c[:sequence_name])
92
+ statements << restart_sequence_sql(c[:sequence_name], {:restart_position => c[:sequence_start_position]}) if c[:sequence_start_position]
93
+ end
94
+ unless c[:create_trigger] == false
95
+ c[:trigger_name] ||= "BI_#{name}_#{c[:name]}"
96
+ c[:quoted_name] = quote_identifier(c[:name])
97
+ trigger_definition = <<-END
98
+ begin
99
+ if ((new.#{c[:quoted_name]} is null) or (new.#{c[:quoted_name]} = 0)) then
100
+ begin
101
+ new.#{c[:quoted_name]} = next value for #{c[:sequence_name]};
102
+ end
103
+ end
104
+ END
105
+ statements << create_trigger_sql(name, c[:trigger_name], trigger_definition, {:events => [:insert]})
106
+ end
107
+ end
108
+ end
109
+ [drop_seq_statement, statements]
110
+ end
111
+
112
+ def create_trigger_sql(table, name, definition, opts={})
113
+ events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
114
+ whence = opts[:after] ? 'AFTER' : 'BEFORE'
115
+ inactive = opts[:inactive] ? 'INACTIVE' : 'ACTIVE'
116
+ position = opts.fetch(:position, 0)
117
+ sql = <<-end_sql
118
+ CREATE TRIGGER #{quote_identifier(name)} for #{quote_identifier(table)}
119
+ #{inactive} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} position #{position}
120
+ as #{definition}
121
+ end_sql
122
+ sql
123
+ end
124
+
125
+ def drop_sequence_sql(name)
126
+ "DROP SEQUENCE #{quote_identifier(name)}"
127
+ end
128
+
129
+ def remove_cached_schema(table)
130
+ clear_primary_key(table)
131
+ super
132
+ end
133
+
134
+ def restart_sequence_sql(name, opts={})
135
+ seq_name = quote_identifier(name)
136
+ "ALTER SEQUENCE #{seq_name} RESTART WITH #{opts[:restart_position]}"
137
+ end
138
+
139
+ def tables_or_views(type, opts)
140
+ ds = self[:"rdb$relations"].server(opts[:server]).filter(:"rdb$relation_type" => type, Sequel::SQL::Function.new(:COALESCE, :"rdb$system_flag", 0) => 0).select(:"rdb$relation_name")
141
+ ds.map{|r| ds.send(:output_identifier, r[:"rdb$relation_name"].rstrip)}
142
+ end
143
+
144
+ def type_literal_generic_string(column)
145
+ column[:text] ? :"BLOB SUB_TYPE TEXT" : super
146
+ end
147
+ end
148
+
149
+ module DatasetMethods
150
+ BOOL_TRUE = '1'.freeze
151
+ BOOL_FALSE = '0'.freeze
152
+ NULL = LiteralString.new('NULL').freeze
153
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with select distinct limit columns from join where group having compounds order')
154
+ INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert into columns values returning')
155
+ FIRST = " FIRST ".freeze
156
+ SKIP = " SKIP ".freeze
157
+ DEFAULT_FROM = " FROM RDB$DATABASE"
158
+
159
+ # Insert given values into the database.
160
+ def insert(*values)
161
+ if @opts[:sql] || @opts[:returning]
162
+ super
163
+ else
164
+ returning(insert_pk).insert(*values){|r| return r.values.first}
165
+ end
166
+ end
167
+
168
+ # Insert a record returning the record inserted
169
+ def insert_select(*values)
170
+ returning.insert(*values){|r| return r}
171
+ end
172
+
173
+ def requires_sql_standard_datetimes?
174
+ true
175
+ end
176
+
177
+ def supports_insert_select?
178
+ true
179
+ end
180
+
181
+ # Firebird does not support INTERSECT or EXCEPT
182
+ def supports_intersect_except?
183
+ false
184
+ end
185
+
186
+ private
187
+
188
+ def insert_clause_methods
189
+ INSERT_CLAUSE_METHODS
190
+ end
191
+
192
+ def insert_pk(*values)
193
+ pk = db.primary_key(opts[:from].first)
194
+ pk ? Sequel::SQL::Identifier.new(pk) : NULL
195
+ end
196
+
197
+ def literal_false
198
+ BOOL_FALSE
199
+ end
200
+
201
+ def literal_true
202
+ BOOL_TRUE
203
+ end
204
+
205
+ # The order of clauses in the SELECT SQL statement
206
+ def select_clause_methods
207
+ SELECT_CLAUSE_METHODS
208
+ end
209
+
210
+ # Use a default FROM table if the dataset does not contain a FROM table.
211
+ def select_from_sql(sql)
212
+ if @opts[:from]
213
+ super
214
+ else
215
+ sql << DEFAULT_FROM
216
+ end
217
+ end
218
+
219
+ def select_limit_sql(sql)
220
+ if l = @opts[:limit]
221
+ sql << FIRST
222
+ literal_append(sql, l)
223
+ end
224
+ if o = @opts[:offset]
225
+ sql << SKIP
226
+ literal_append(sql, o)
227
+ end
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,53 @@
1
+ module Sequel
2
+ module Informix
3
+ module DatabaseMethods
4
+ TEMPORARY = 'TEMP '.freeze
5
+
6
+ # Informix uses the :informix database type
7
+ def database_type
8
+ :informix
9
+ end
10
+
11
+ private
12
+
13
+ # Informix has issues with quoted identifiers, so
14
+ # turn off database quoting by default.
15
+ def quote_identifiers_default
16
+ false
17
+ end
18
+
19
+ # SQL fragment for showing a table is temporary
20
+ def temporary_table_sql
21
+ TEMPORARY
22
+ end
23
+ end
24
+
25
+ module DatasetMethods
26
+ SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'select limit distinct columns from join where having group compounds order')
27
+ FIRST = " FIRST ".freeze
28
+ SKIP = " SKIP ".freeze
29
+
30
+ private
31
+
32
+ # Informix does not support INTERSECT or EXCEPT
33
+ def supports_intersect_except?
34
+ false
35
+ end
36
+
37
+ def select_clause_methods
38
+ SELECT_CLAUSE_METHODS
39
+ end
40
+
41
+ def select_limit_sql(sql)
42
+ if o = @opts[:offset]
43
+ sql << SKIP
44
+ literal_append(sql, o)
45
+ end
46
+ if l = @opts[:limit]
47
+ sql << FIRST
48
+ literal_append(sql, l)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end