sequel 4.36.0 → 5.61.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 (760) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +548 -5749
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +265 -159
  5. data/bin/sequel +34 -12
  6. data/doc/advanced_associations.rdoc +228 -187
  7. data/doc/association_basics.rdoc +281 -291
  8. data/doc/bin_sequel.rdoc +5 -3
  9. data/doc/cheat_sheet.rdoc +86 -51
  10. data/doc/code_order.rdoc +25 -19
  11. data/doc/core_extensions.rdoc +104 -63
  12. data/doc/dataset_basics.rdoc +12 -21
  13. data/doc/dataset_filtering.rdoc +99 -86
  14. data/doc/extensions.rdoc +3 -10
  15. data/doc/fork_safety.rdoc +84 -0
  16. data/doc/mass_assignment.rdoc +74 -31
  17. data/doc/migration.rdoc +59 -51
  18. data/doc/model_dataset_method_design.rdoc +129 -0
  19. data/doc/model_hooks.rdoc +15 -25
  20. data/doc/model_plugins.rdoc +12 -12
  21. data/doc/mssql_stored_procedures.rdoc +3 -3
  22. data/doc/object_model.rdoc +58 -68
  23. data/doc/opening_databases.rdoc +85 -95
  24. data/doc/postgresql.rdoc +263 -38
  25. data/doc/prepared_statements.rdoc +29 -24
  26. data/doc/querying.rdoc +189 -167
  27. data/doc/reflection.rdoc +5 -6
  28. data/doc/release_notes/5.0.0.txt +159 -0
  29. data/doc/release_notes/5.1.0.txt +31 -0
  30. data/doc/release_notes/5.10.0.txt +84 -0
  31. data/doc/release_notes/5.11.0.txt +83 -0
  32. data/doc/release_notes/5.12.0.txt +141 -0
  33. data/doc/release_notes/5.13.0.txt +27 -0
  34. data/doc/release_notes/5.14.0.txt +63 -0
  35. data/doc/release_notes/5.15.0.txt +39 -0
  36. data/doc/release_notes/5.16.0.txt +110 -0
  37. data/doc/release_notes/5.17.0.txt +31 -0
  38. data/doc/release_notes/5.18.0.txt +69 -0
  39. data/doc/release_notes/5.19.0.txt +28 -0
  40. data/doc/release_notes/5.2.0.txt +33 -0
  41. data/doc/release_notes/5.20.0.txt +89 -0
  42. data/doc/release_notes/5.21.0.txt +87 -0
  43. data/doc/release_notes/5.22.0.txt +48 -0
  44. data/doc/release_notes/5.23.0.txt +56 -0
  45. data/doc/release_notes/5.24.0.txt +56 -0
  46. data/doc/release_notes/5.25.0.txt +32 -0
  47. data/doc/release_notes/5.26.0.txt +35 -0
  48. data/doc/release_notes/5.27.0.txt +21 -0
  49. data/doc/release_notes/5.28.0.txt +16 -0
  50. data/doc/release_notes/5.29.0.txt +22 -0
  51. data/doc/release_notes/5.3.0.txt +121 -0
  52. data/doc/release_notes/5.30.0.txt +20 -0
  53. data/doc/release_notes/5.31.0.txt +148 -0
  54. data/doc/release_notes/5.32.0.txt +46 -0
  55. data/doc/release_notes/5.33.0.txt +24 -0
  56. data/doc/release_notes/5.34.0.txt +40 -0
  57. data/doc/release_notes/5.35.0.txt +56 -0
  58. data/doc/release_notes/5.36.0.txt +60 -0
  59. data/doc/release_notes/5.37.0.txt +30 -0
  60. data/doc/release_notes/5.38.0.txt +28 -0
  61. data/doc/release_notes/5.39.0.txt +19 -0
  62. data/doc/release_notes/5.4.0.txt +80 -0
  63. data/doc/release_notes/5.40.0.txt +40 -0
  64. data/doc/release_notes/5.41.0.txt +25 -0
  65. data/doc/release_notes/5.42.0.txt +136 -0
  66. data/doc/release_notes/5.43.0.txt +98 -0
  67. data/doc/release_notes/5.44.0.txt +32 -0
  68. data/doc/release_notes/5.45.0.txt +34 -0
  69. data/doc/release_notes/5.46.0.txt +87 -0
  70. data/doc/release_notes/5.47.0.txt +59 -0
  71. data/doc/release_notes/5.48.0.txt +14 -0
  72. data/doc/release_notes/5.49.0.txt +59 -0
  73. data/doc/release_notes/5.5.0.txt +61 -0
  74. data/doc/release_notes/5.50.0.txt +78 -0
  75. data/doc/release_notes/5.51.0.txt +47 -0
  76. data/doc/release_notes/5.52.0.txt +87 -0
  77. data/doc/release_notes/5.53.0.txt +23 -0
  78. data/doc/release_notes/5.54.0.txt +27 -0
  79. data/doc/release_notes/5.55.0.txt +21 -0
  80. data/doc/release_notes/5.56.0.txt +51 -0
  81. data/doc/release_notes/5.57.0.txt +23 -0
  82. data/doc/release_notes/5.58.0.txt +31 -0
  83. data/doc/release_notes/5.59.0.txt +73 -0
  84. data/doc/release_notes/5.6.0.txt +31 -0
  85. data/doc/release_notes/5.60.0.txt +22 -0
  86. data/doc/release_notes/5.61.0.txt +43 -0
  87. data/doc/release_notes/5.7.0.txt +108 -0
  88. data/doc/release_notes/5.8.0.txt +170 -0
  89. data/doc/release_notes/5.9.0.txt +99 -0
  90. data/doc/schema_modification.rdoc +95 -75
  91. data/doc/security.rdoc +109 -80
  92. data/doc/sharding.rdoc +74 -47
  93. data/doc/sql.rdoc +147 -122
  94. data/doc/testing.rdoc +43 -20
  95. data/doc/thread_safety.rdoc +2 -4
  96. data/doc/transactions.rdoc +97 -18
  97. data/doc/validations.rdoc +52 -50
  98. data/doc/virtual_rows.rdoc +90 -109
  99. data/lib/sequel/adapters/ado/access.rb +15 -17
  100. data/lib/sequel/adapters/ado/mssql.rb +6 -15
  101. data/lib/sequel/adapters/ado.rb +150 -20
  102. data/lib/sequel/adapters/amalgalite.rb +11 -23
  103. data/lib/sequel/adapters/ibmdb.rb +47 -55
  104. data/lib/sequel/adapters/jdbc/db2.rb +29 -39
  105. data/lib/sequel/adapters/jdbc/derby.rb +58 -54
  106. data/lib/sequel/adapters/jdbc/h2.rb +93 -35
  107. data/lib/sequel/adapters/jdbc/hsqldb.rb +24 -31
  108. data/lib/sequel/adapters/jdbc/jtds.rb +2 -10
  109. data/lib/sequel/adapters/jdbc/mssql.rb +3 -11
  110. data/lib/sequel/adapters/jdbc/mysql.rb +17 -20
  111. data/lib/sequel/adapters/jdbc/oracle.rb +22 -18
  112. data/lib/sequel/adapters/jdbc/postgresql.rb +69 -71
  113. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +11 -23
  114. data/lib/sequel/adapters/jdbc/sqlite.rb +47 -11
  115. data/lib/sequel/adapters/jdbc/sqlserver.rb +34 -9
  116. data/lib/sequel/adapters/jdbc/transactions.rb +22 -38
  117. data/lib/sequel/adapters/jdbc.rb +145 -130
  118. data/lib/sequel/adapters/mock.rb +100 -111
  119. data/lib/sequel/adapters/mysql.rb +114 -122
  120. data/lib/sequel/adapters/mysql2.rb +147 -63
  121. data/lib/sequel/adapters/odbc/db2.rb +1 -1
  122. data/lib/sequel/adapters/odbc/mssql.rb +8 -14
  123. data/lib/sequel/adapters/odbc/oracle.rb +11 -0
  124. data/lib/sequel/adapters/odbc.rb +20 -25
  125. data/lib/sequel/adapters/oracle.rb +50 -56
  126. data/lib/sequel/adapters/postgres.rb +305 -327
  127. data/lib/sequel/adapters/postgresql.rb +1 -1
  128. data/lib/sequel/adapters/shared/access.rb +74 -78
  129. data/lib/sequel/adapters/shared/db2.rb +118 -71
  130. data/lib/sequel/adapters/shared/mssql.rb +301 -220
  131. data/lib/sequel/adapters/shared/mysql.rb +299 -217
  132. data/lib/sequel/adapters/shared/oracle.rb +226 -65
  133. data/lib/sequel/adapters/shared/postgres.rb +935 -395
  134. data/lib/sequel/adapters/shared/sqlanywhere.rb +105 -126
  135. data/lib/sequel/adapters/shared/sqlite.rb +447 -173
  136. data/lib/sequel/adapters/sqlanywhere.rb +48 -35
  137. data/lib/sequel/adapters/sqlite.rb +156 -111
  138. data/lib/sequel/adapters/tinytds.rb +30 -38
  139. data/lib/sequel/adapters/utils/columns_limit_1.rb +22 -0
  140. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +3 -6
  141. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +2 -2
  142. data/lib/sequel/adapters/utils/mysql_mysql2.rb +87 -0
  143. data/lib/sequel/adapters/utils/mysql_prepared_statements.rb +56 -0
  144. data/lib/sequel/adapters/utils/replace.rb +1 -4
  145. data/lib/sequel/adapters/utils/stored_procedures.rb +7 -22
  146. data/lib/sequel/adapters/utils/unmodified_identifiers.rb +28 -0
  147. data/lib/sequel/ast_transformer.rb +17 -89
  148. data/lib/sequel/connection_pool/sharded_single.rb +18 -15
  149. data/lib/sequel/connection_pool/sharded_threaded.rb +130 -111
  150. data/lib/sequel/connection_pool/single.rb +18 -13
  151. data/lib/sequel/connection_pool/threaded.rb +121 -120
  152. data/lib/sequel/connection_pool.rb +48 -29
  153. data/lib/sequel/core.rb +351 -301
  154. data/lib/sequel/database/connecting.rb +69 -57
  155. data/lib/sequel/database/dataset.rb +13 -5
  156. data/lib/sequel/database/dataset_defaults.rb +18 -102
  157. data/lib/sequel/database/features.rb +18 -4
  158. data/lib/sequel/database/logging.rb +12 -11
  159. data/lib/sequel/database/misc.rb +180 -122
  160. data/lib/sequel/database/query.rb +47 -27
  161. data/lib/sequel/database/schema_generator.rb +178 -84
  162. data/lib/sequel/database/schema_methods.rb +172 -97
  163. data/lib/sequel/database/transactions.rb +205 -44
  164. data/lib/sequel/database.rb +17 -2
  165. data/lib/sequel/dataset/actions.rb +339 -155
  166. data/lib/sequel/dataset/dataset_module.rb +46 -0
  167. data/lib/sequel/dataset/features.rb +90 -35
  168. data/lib/sequel/dataset/graph.rb +80 -58
  169. data/lib/sequel/dataset/misc.rb +137 -47
  170. data/lib/sequel/dataset/placeholder_literalizer.rb +63 -25
  171. data/lib/sequel/dataset/prepared_statements.rb +188 -85
  172. data/lib/sequel/dataset/query.rb +530 -222
  173. data/lib/sequel/dataset/sql.rb +590 -368
  174. data/lib/sequel/dataset.rb +26 -16
  175. data/lib/sequel/deprecated.rb +12 -2
  176. data/lib/sequel/exceptions.rb +46 -16
  177. data/lib/sequel/extensions/_model_constraint_validations.rb +16 -0
  178. data/lib/sequel/extensions/_model_pg_row.rb +43 -0
  179. data/lib/sequel/extensions/_pretty_table.rb +2 -5
  180. data/lib/sequel/extensions/any_not_empty.rb +45 -0
  181. data/lib/sequel/extensions/arbitrary_servers.rb +10 -10
  182. data/lib/sequel/extensions/async_thread_pool.rb +438 -0
  183. data/lib/sequel/extensions/auto_literal_strings.rb +74 -0
  184. data/lib/sequel/extensions/blank.rb +8 -0
  185. data/lib/sequel/extensions/caller_logging.rb +79 -0
  186. data/lib/sequel/extensions/columns_introspection.rb +4 -3
  187. data/lib/sequel/extensions/connection_expiration.rb +20 -10
  188. data/lib/sequel/extensions/connection_validator.rb +11 -10
  189. data/lib/sequel/extensions/constant_sql_override.rb +65 -0
  190. data/lib/sequel/extensions/constraint_validations.rb +62 -39
  191. data/lib/sequel/extensions/core_extensions.rb +42 -48
  192. data/lib/sequel/extensions/core_refinements.rb +80 -59
  193. data/lib/sequel/extensions/current_datetime_timestamp.rb +1 -4
  194. data/lib/sequel/extensions/date_arithmetic.rb +98 -39
  195. data/lib/sequel/extensions/date_parse_input_handler.rb +67 -0
  196. data/lib/sequel/extensions/datetime_parse_to_time.rb +41 -0
  197. data/lib/sequel/extensions/duplicate_columns_handler.rb +21 -14
  198. data/lib/sequel/extensions/empty_array_consider_nulls.rb +2 -2
  199. data/lib/sequel/extensions/escaped_like.rb +100 -0
  200. data/lib/sequel/extensions/eval_inspect.rb +12 -15
  201. data/lib/sequel/extensions/exclude_or_null.rb +68 -0
  202. data/lib/sequel/extensions/fiber_concurrency.rb +24 -0
  203. data/lib/sequel/extensions/freeze_datasets.rb +3 -0
  204. data/lib/sequel/extensions/from_block.rb +1 -34
  205. data/lib/sequel/extensions/graph_each.rb +4 -4
  206. data/lib/sequel/extensions/identifier_mangling.rb +180 -0
  207. data/lib/sequel/extensions/implicit_subquery.rb +48 -0
  208. data/lib/sequel/extensions/index_caching.rb +109 -0
  209. data/lib/sequel/extensions/inflector.rb +13 -5
  210. data/lib/sequel/extensions/integer64.rb +32 -0
  211. data/lib/sequel/extensions/is_distinct_from.rb +141 -0
  212. data/lib/sequel/extensions/looser_typecasting.rb +17 -8
  213. data/lib/sequel/extensions/migration.rb +119 -78
  214. data/lib/sequel/extensions/named_timezones.rb +88 -23
  215. data/lib/sequel/extensions/no_auto_literal_strings.rb +2 -82
  216. data/lib/sequel/extensions/null_dataset.rb +8 -8
  217. data/lib/sequel/extensions/pagination.rb +32 -29
  218. data/lib/sequel/extensions/pg_array.rb +221 -287
  219. data/lib/sequel/extensions/pg_array_ops.rb +17 -9
  220. data/lib/sequel/extensions/pg_enum.rb +63 -23
  221. data/lib/sequel/extensions/pg_extended_date_support.rb +241 -0
  222. data/lib/sequel/extensions/pg_hstore.rb +45 -54
  223. data/lib/sequel/extensions/pg_hstore_ops.rb +58 -6
  224. data/lib/sequel/extensions/pg_inet.rb +31 -12
  225. data/lib/sequel/extensions/pg_inet_ops.rb +2 -2
  226. data/lib/sequel/extensions/pg_interval.rb +56 -29
  227. data/lib/sequel/extensions/pg_json.rb +417 -140
  228. data/lib/sequel/extensions/pg_json_ops.rb +270 -18
  229. data/lib/sequel/extensions/pg_loose_count.rb +4 -2
  230. data/lib/sequel/extensions/pg_multirange.rb +372 -0
  231. data/lib/sequel/extensions/pg_range.rb +131 -191
  232. data/lib/sequel/extensions/pg_range_ops.rb +42 -13
  233. data/lib/sequel/extensions/pg_row.rb +48 -81
  234. data/lib/sequel/extensions/pg_row_ops.rb +33 -14
  235. data/lib/sequel/extensions/pg_static_cache_updater.rb +2 -2
  236. data/lib/sequel/extensions/pg_timestamptz.rb +28 -0
  237. data/lib/sequel/extensions/query.rb +9 -7
  238. data/lib/sequel/extensions/round_timestamps.rb +0 -6
  239. data/lib/sequel/extensions/run_transaction_hooks.rb +72 -0
  240. data/lib/sequel/extensions/s.rb +60 -0
  241. data/lib/sequel/extensions/schema_caching.rb +10 -1
  242. data/lib/sequel/extensions/schema_dumper.rb +71 -48
  243. data/lib/sequel/extensions/select_remove.rb +4 -4
  244. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +85 -0
  245. data/lib/sequel/extensions/server_block.rb +51 -27
  246. data/lib/sequel/extensions/split_array_nil.rb +4 -4
  247. data/lib/sequel/extensions/sql_comments.rb +119 -7
  248. data/lib/sequel/extensions/sql_expr.rb +2 -1
  249. data/lib/sequel/extensions/sql_log_normalizer.rb +108 -0
  250. data/lib/sequel/extensions/sqlite_json_ops.rb +255 -0
  251. data/lib/sequel/extensions/string_agg.rb +11 -8
  252. data/lib/sequel/extensions/string_date_time.rb +19 -23
  253. data/lib/sequel/extensions/symbol_aref.rb +55 -0
  254. data/lib/sequel/extensions/symbol_aref_refinement.rb +43 -0
  255. data/lib/sequel/extensions/symbol_as.rb +23 -0
  256. data/lib/sequel/extensions/symbol_as_refinement.rb +37 -0
  257. data/lib/sequel/extensions/synchronize_sql.rb +45 -0
  258. data/lib/sequel/extensions/to_dot.rb +10 -4
  259. data/lib/sequel/extensions/virtual_row_method_block.rb +44 -0
  260. data/lib/sequel/model/associations.rb +1006 -284
  261. data/lib/sequel/model/base.rb +560 -805
  262. data/lib/sequel/model/dataset_module.rb +11 -10
  263. data/lib/sequel/model/default_inflections.rb +1 -1
  264. data/lib/sequel/model/errors.rb +10 -3
  265. data/lib/sequel/model/exceptions.rb +8 -10
  266. data/lib/sequel/model/inflections.rb +7 -20
  267. data/lib/sequel/model/plugins.rb +114 -0
  268. data/lib/sequel/model.rb +32 -82
  269. data/lib/sequel/plugins/active_model.rb +30 -14
  270. data/lib/sequel/plugins/after_initialize.rb +1 -1
  271. data/lib/sequel/plugins/association_dependencies.rb +25 -18
  272. data/lib/sequel/plugins/association_lazy_eager_option.rb +66 -0
  273. data/lib/sequel/plugins/association_multi_add_remove.rb +85 -0
  274. data/lib/sequel/plugins/association_pks.rb +147 -70
  275. data/lib/sequel/plugins/association_proxies.rb +33 -9
  276. data/lib/sequel/plugins/async_thread_pool.rb +39 -0
  277. data/lib/sequel/plugins/auto_restrict_eager_graph.rb +62 -0
  278. data/lib/sequel/plugins/auto_validations.rb +95 -28
  279. data/lib/sequel/plugins/auto_validations_constraint_validations_presence_message.rb +68 -0
  280. data/lib/sequel/plugins/before_after_save.rb +0 -42
  281. data/lib/sequel/plugins/blacklist_security.rb +21 -12
  282. data/lib/sequel/plugins/boolean_readers.rb +5 -5
  283. data/lib/sequel/plugins/boolean_subsets.rb +13 -8
  284. data/lib/sequel/plugins/caching.rb +25 -16
  285. data/lib/sequel/plugins/class_table_inheritance.rb +179 -100
  286. data/lib/sequel/plugins/column_conflicts.rb +16 -3
  287. data/lib/sequel/plugins/column_encryption.rb +728 -0
  288. data/lib/sequel/plugins/column_select.rb +7 -5
  289. data/lib/sequel/plugins/columns_updated.rb +42 -0
  290. data/lib/sequel/plugins/composition.rb +42 -26
  291. data/lib/sequel/plugins/concurrent_eager_loading.rb +174 -0
  292. data/lib/sequel/plugins/constraint_validations.rb +20 -14
  293. data/lib/sequel/plugins/csv_serializer.rb +56 -35
  294. data/lib/sequel/plugins/dataset_associations.rb +40 -17
  295. data/lib/sequel/plugins/def_dataset_method.rb +90 -0
  296. data/lib/sequel/plugins/defaults_setter.rb +65 -10
  297. data/lib/sequel/plugins/delay_add_association.rb +1 -1
  298. data/lib/sequel/plugins/dirty.rb +62 -24
  299. data/lib/sequel/plugins/eager_each.rb +3 -3
  300. data/lib/sequel/plugins/eager_graph_eager.rb +139 -0
  301. data/lib/sequel/plugins/empty_failure_backtraces.rb +38 -0
  302. data/lib/sequel/plugins/enum.rb +124 -0
  303. data/lib/sequel/plugins/error_splitter.rb +17 -12
  304. data/lib/sequel/plugins/finder.rb +246 -0
  305. data/lib/sequel/plugins/forbid_lazy_load.rb +216 -0
  306. data/lib/sequel/plugins/force_encoding.rb +7 -12
  307. data/lib/sequel/plugins/hook_class_methods.rb +37 -54
  308. data/lib/sequel/plugins/input_transformer.rb +18 -10
  309. data/lib/sequel/plugins/insert_conflict.rb +76 -0
  310. data/lib/sequel/plugins/insert_returning_select.rb +2 -2
  311. data/lib/sequel/plugins/instance_filters.rb +10 -8
  312. data/lib/sequel/plugins/instance_hooks.rb +34 -17
  313. data/lib/sequel/plugins/instance_specific_default.rb +113 -0
  314. data/lib/sequel/plugins/inverted_subsets.rb +22 -13
  315. data/lib/sequel/plugins/json_serializer.rb +124 -64
  316. data/lib/sequel/plugins/lazy_attributes.rb +21 -14
  317. data/lib/sequel/plugins/list.rb +35 -21
  318. data/lib/sequel/plugins/many_through_many.rb +134 -21
  319. data/lib/sequel/plugins/modification_detection.rb +15 -5
  320. data/lib/sequel/plugins/mssql_optimistic_locking.rb +6 -5
  321. data/lib/sequel/plugins/nested_attributes.rb +61 -31
  322. data/lib/sequel/plugins/optimistic_locking.rb +3 -3
  323. data/lib/sequel/plugins/pg_array_associations.rb +103 -53
  324. data/lib/sequel/plugins/pg_auto_constraint_validations.rb +350 -0
  325. data/lib/sequel/plugins/pg_row.rb +5 -51
  326. data/lib/sequel/plugins/prepared_statements.rb +60 -72
  327. data/lib/sequel/plugins/prepared_statements_safe.rb +9 -4
  328. data/lib/sequel/plugins/rcte_tree.rb +68 -82
  329. data/lib/sequel/plugins/require_valid_schema.rb +67 -0
  330. data/lib/sequel/plugins/serialization.rb +43 -46
  331. data/lib/sequel/plugins/serialization_modification_detection.rb +3 -2
  332. data/lib/sequel/plugins/sharding.rb +15 -10
  333. data/lib/sequel/plugins/single_table_inheritance.rb +67 -28
  334. data/lib/sequel/plugins/skip_create_refresh.rb +3 -3
  335. data/lib/sequel/plugins/skip_saving_columns.rb +108 -0
  336. data/lib/sequel/plugins/split_values.rb +11 -6
  337. data/lib/sequel/plugins/sql_comments.rb +189 -0
  338. data/lib/sequel/plugins/static_cache.rb +77 -53
  339. data/lib/sequel/plugins/static_cache_cache.rb +53 -0
  340. data/lib/sequel/plugins/string_stripper.rb +3 -3
  341. data/lib/sequel/plugins/subclasses.rb +43 -10
  342. data/lib/sequel/plugins/subset_conditions.rb +15 -5
  343. data/lib/sequel/plugins/table_select.rb +2 -2
  344. data/lib/sequel/plugins/tactical_eager_loading.rb +96 -12
  345. data/lib/sequel/plugins/throw_failures.rb +110 -0
  346. data/lib/sequel/plugins/timestamps.rb +20 -8
  347. data/lib/sequel/plugins/touch.rb +19 -8
  348. data/lib/sequel/plugins/tree.rb +62 -32
  349. data/lib/sequel/plugins/typecast_on_load.rb +12 -4
  350. data/lib/sequel/plugins/unlimited_update.rb +1 -7
  351. data/lib/sequel/plugins/unused_associations.rb +521 -0
  352. data/lib/sequel/plugins/update_or_create.rb +4 -4
  353. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  354. data/lib/sequel/plugins/update_refresh.rb +26 -15
  355. data/lib/sequel/plugins/uuid.rb +7 -11
  356. data/lib/sequel/plugins/validate_associated.rb +18 -0
  357. data/lib/sequel/plugins/validation_class_methods.rb +38 -19
  358. data/lib/sequel/plugins/validation_contexts.rb +49 -0
  359. data/lib/sequel/plugins/validation_helpers.rb +57 -41
  360. data/lib/sequel/plugins/whitelist_security.rb +122 -0
  361. data/lib/sequel/plugins/xml_serializer.rb +30 -31
  362. data/lib/sequel/sql.rb +471 -331
  363. data/lib/sequel/timezones.rb +78 -47
  364. data/lib/sequel/version.rb +7 -2
  365. data/lib/sequel.rb +1 -1
  366. metadata +217 -521
  367. data/Rakefile +0 -164
  368. data/doc/active_record.rdoc +0 -928
  369. data/doc/release_notes/1.0.txt +0 -38
  370. data/doc/release_notes/1.1.txt +0 -143
  371. data/doc/release_notes/1.3.txt +0 -101
  372. data/doc/release_notes/1.4.0.txt +0 -53
  373. data/doc/release_notes/1.5.0.txt +0 -155
  374. data/doc/release_notes/2.0.0.txt +0 -298
  375. data/doc/release_notes/2.1.0.txt +0 -271
  376. data/doc/release_notes/2.10.0.txt +0 -328
  377. data/doc/release_notes/2.11.0.txt +0 -215
  378. data/doc/release_notes/2.12.0.txt +0 -534
  379. data/doc/release_notes/2.2.0.txt +0 -253
  380. data/doc/release_notes/2.3.0.txt +0 -88
  381. data/doc/release_notes/2.4.0.txt +0 -106
  382. data/doc/release_notes/2.5.0.txt +0 -137
  383. data/doc/release_notes/2.6.0.txt +0 -157
  384. data/doc/release_notes/2.7.0.txt +0 -166
  385. data/doc/release_notes/2.8.0.txt +0 -171
  386. data/doc/release_notes/2.9.0.txt +0 -97
  387. data/doc/release_notes/3.0.0.txt +0 -221
  388. data/doc/release_notes/3.1.0.txt +0 -406
  389. data/doc/release_notes/3.10.0.txt +0 -286
  390. data/doc/release_notes/3.11.0.txt +0 -254
  391. data/doc/release_notes/3.12.0.txt +0 -304
  392. data/doc/release_notes/3.13.0.txt +0 -210
  393. data/doc/release_notes/3.14.0.txt +0 -118
  394. data/doc/release_notes/3.15.0.txt +0 -78
  395. data/doc/release_notes/3.16.0.txt +0 -45
  396. data/doc/release_notes/3.17.0.txt +0 -58
  397. data/doc/release_notes/3.18.0.txt +0 -120
  398. data/doc/release_notes/3.19.0.txt +0 -67
  399. data/doc/release_notes/3.2.0.txt +0 -268
  400. data/doc/release_notes/3.20.0.txt +0 -41
  401. data/doc/release_notes/3.21.0.txt +0 -87
  402. data/doc/release_notes/3.22.0.txt +0 -39
  403. data/doc/release_notes/3.23.0.txt +0 -172
  404. data/doc/release_notes/3.24.0.txt +0 -420
  405. data/doc/release_notes/3.25.0.txt +0 -88
  406. data/doc/release_notes/3.26.0.txt +0 -88
  407. data/doc/release_notes/3.27.0.txt +0 -82
  408. data/doc/release_notes/3.28.0.txt +0 -304
  409. data/doc/release_notes/3.29.0.txt +0 -459
  410. data/doc/release_notes/3.3.0.txt +0 -192
  411. data/doc/release_notes/3.30.0.txt +0 -135
  412. data/doc/release_notes/3.31.0.txt +0 -146
  413. data/doc/release_notes/3.32.0.txt +0 -202
  414. data/doc/release_notes/3.33.0.txt +0 -157
  415. data/doc/release_notes/3.34.0.txt +0 -671
  416. data/doc/release_notes/3.35.0.txt +0 -144
  417. data/doc/release_notes/3.36.0.txt +0 -245
  418. data/doc/release_notes/3.37.0.txt +0 -338
  419. data/doc/release_notes/3.38.0.txt +0 -234
  420. data/doc/release_notes/3.39.0.txt +0 -237
  421. data/doc/release_notes/3.4.0.txt +0 -325
  422. data/doc/release_notes/3.40.0.txt +0 -73
  423. data/doc/release_notes/3.41.0.txt +0 -155
  424. data/doc/release_notes/3.42.0.txt +0 -74
  425. data/doc/release_notes/3.43.0.txt +0 -105
  426. data/doc/release_notes/3.44.0.txt +0 -152
  427. data/doc/release_notes/3.45.0.txt +0 -179
  428. data/doc/release_notes/3.46.0.txt +0 -122
  429. data/doc/release_notes/3.47.0.txt +0 -270
  430. data/doc/release_notes/3.48.0.txt +0 -477
  431. data/doc/release_notes/3.5.0.txt +0 -510
  432. data/doc/release_notes/3.6.0.txt +0 -366
  433. data/doc/release_notes/3.7.0.txt +0 -179
  434. data/doc/release_notes/3.8.0.txt +0 -151
  435. data/doc/release_notes/3.9.0.txt +0 -233
  436. data/doc/release_notes/4.0.0.txt +0 -262
  437. data/doc/release_notes/4.1.0.txt +0 -85
  438. data/doc/release_notes/4.10.0.txt +0 -226
  439. data/doc/release_notes/4.11.0.txt +0 -147
  440. data/doc/release_notes/4.12.0.txt +0 -105
  441. data/doc/release_notes/4.13.0.txt +0 -169
  442. data/doc/release_notes/4.14.0.txt +0 -68
  443. data/doc/release_notes/4.15.0.txt +0 -56
  444. data/doc/release_notes/4.16.0.txt +0 -36
  445. data/doc/release_notes/4.17.0.txt +0 -38
  446. data/doc/release_notes/4.18.0.txt +0 -36
  447. data/doc/release_notes/4.19.0.txt +0 -45
  448. data/doc/release_notes/4.2.0.txt +0 -129
  449. data/doc/release_notes/4.20.0.txt +0 -79
  450. data/doc/release_notes/4.21.0.txt +0 -94
  451. data/doc/release_notes/4.22.0.txt +0 -72
  452. data/doc/release_notes/4.23.0.txt +0 -65
  453. data/doc/release_notes/4.24.0.txt +0 -99
  454. data/doc/release_notes/4.25.0.txt +0 -181
  455. data/doc/release_notes/4.26.0.txt +0 -44
  456. data/doc/release_notes/4.27.0.txt +0 -78
  457. data/doc/release_notes/4.28.0.txt +0 -57
  458. data/doc/release_notes/4.29.0.txt +0 -41
  459. data/doc/release_notes/4.3.0.txt +0 -40
  460. data/doc/release_notes/4.30.0.txt +0 -37
  461. data/doc/release_notes/4.31.0.txt +0 -57
  462. data/doc/release_notes/4.32.0.txt +0 -132
  463. data/doc/release_notes/4.33.0.txt +0 -88
  464. data/doc/release_notes/4.34.0.txt +0 -86
  465. data/doc/release_notes/4.35.0.txt +0 -130
  466. data/doc/release_notes/4.36.0.txt +0 -116
  467. data/doc/release_notes/4.4.0.txt +0 -92
  468. data/doc/release_notes/4.5.0.txt +0 -34
  469. data/doc/release_notes/4.6.0.txt +0 -30
  470. data/doc/release_notes/4.7.0.txt +0 -103
  471. data/doc/release_notes/4.8.0.txt +0 -175
  472. data/doc/release_notes/4.9.0.txt +0 -190
  473. data/lib/sequel/adapters/cubrid.rb +0 -144
  474. data/lib/sequel/adapters/do/mysql.rb +0 -66
  475. data/lib/sequel/adapters/do/postgres.rb +0 -44
  476. data/lib/sequel/adapters/do/sqlite3.rb +0 -42
  477. data/lib/sequel/adapters/do.rb +0 -158
  478. data/lib/sequel/adapters/jdbc/as400.rb +0 -84
  479. data/lib/sequel/adapters/jdbc/cubrid.rb +0 -64
  480. data/lib/sequel/adapters/jdbc/firebirdsql.rb +0 -36
  481. data/lib/sequel/adapters/jdbc/informix-sqli.rb +0 -33
  482. data/lib/sequel/adapters/jdbc/jdbcprogress.rb +0 -33
  483. data/lib/sequel/adapters/odbc/progress.rb +0 -10
  484. data/lib/sequel/adapters/shared/cubrid.rb +0 -245
  485. data/lib/sequel/adapters/shared/firebird.rb +0 -247
  486. data/lib/sequel/adapters/shared/informix.rb +0 -54
  487. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +0 -152
  488. data/lib/sequel/adapters/shared/progress.rb +0 -40
  489. data/lib/sequel/adapters/swift/mysql.rb +0 -49
  490. data/lib/sequel/adapters/swift/postgres.rb +0 -47
  491. data/lib/sequel/adapters/swift/sqlite.rb +0 -49
  492. data/lib/sequel/adapters/swift.rb +0 -160
  493. data/lib/sequel/adapters/utils/pg_types.rb +0 -70
  494. data/lib/sequel/dataset/mutation.rb +0 -111
  495. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +0 -5
  496. data/lib/sequel/extensions/filter_having.rb +0 -63
  497. data/lib/sequel/extensions/hash_aliases.rb +0 -49
  498. data/lib/sequel/extensions/meta_def.rb +0 -35
  499. data/lib/sequel/extensions/query_literals.rb +0 -84
  500. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +0 -24
  501. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +0 -122
  502. data/lib/sequel/extensions/set_overrides.rb +0 -76
  503. data/lib/sequel/no_core_ext.rb +0 -3
  504. data/lib/sequel/plugins/association_autoreloading.rb +0 -9
  505. data/lib/sequel/plugins/identifier_columns.rb +0 -47
  506. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +0 -9
  507. data/lib/sequel/plugins/pg_typecast_on_load.rb +0 -81
  508. data/lib/sequel/plugins/prepared_statements_associations.rb +0 -119
  509. data/lib/sequel/plugins/prepared_statements_with_pk.rb +0 -61
  510. data/lib/sequel/plugins/schema.rb +0 -82
  511. data/lib/sequel/plugins/scissors.rb +0 -35
  512. data/spec/adapter_spec.rb +0 -4
  513. data/spec/adapters/db2_spec.rb +0 -160
  514. data/spec/adapters/firebird_spec.rb +0 -411
  515. data/spec/adapters/informix_spec.rb +0 -100
  516. data/spec/adapters/mssql_spec.rb +0 -733
  517. data/spec/adapters/mysql_spec.rb +0 -1319
  518. data/spec/adapters/oracle_spec.rb +0 -313
  519. data/spec/adapters/postgres_spec.rb +0 -3790
  520. data/spec/adapters/spec_helper.rb +0 -49
  521. data/spec/adapters/sqlanywhere_spec.rb +0 -170
  522. data/spec/adapters/sqlite_spec.rb +0 -688
  523. data/spec/bin_spec.rb +0 -258
  524. data/spec/core/connection_pool_spec.rb +0 -1045
  525. data/spec/core/database_spec.rb +0 -2636
  526. data/spec/core/dataset_spec.rb +0 -5175
  527. data/spec/core/deprecated_spec.rb +0 -70
  528. data/spec/core/expression_filters_spec.rb +0 -1247
  529. data/spec/core/mock_adapter_spec.rb +0 -464
  530. data/spec/core/object_graph_spec.rb +0 -303
  531. data/spec/core/placeholder_literalizer_spec.rb +0 -163
  532. data/spec/core/schema_generator_spec.rb +0 -203
  533. data/spec/core/schema_spec.rb +0 -1676
  534. data/spec/core/spec_helper.rb +0 -34
  535. data/spec/core/version_spec.rb +0 -7
  536. data/spec/core_extensions_spec.rb +0 -699
  537. data/spec/core_model_spec.rb +0 -2
  538. data/spec/core_spec.rb +0 -1
  539. data/spec/extensions/accessed_columns_spec.rb +0 -51
  540. data/spec/extensions/active_model_spec.rb +0 -85
  541. data/spec/extensions/after_initialize_spec.rb +0 -24
  542. data/spec/extensions/arbitrary_servers_spec.rb +0 -109
  543. data/spec/extensions/association_dependencies_spec.rb +0 -117
  544. data/spec/extensions/association_pks_spec.rb +0 -405
  545. data/spec/extensions/association_proxies_spec.rb +0 -86
  546. data/spec/extensions/auto_validations_spec.rb +0 -192
  547. data/spec/extensions/before_after_save_spec.rb +0 -40
  548. data/spec/extensions/blacklist_security_spec.rb +0 -88
  549. data/spec/extensions/blank_spec.rb +0 -69
  550. data/spec/extensions/boolean_readers_spec.rb +0 -93
  551. data/spec/extensions/boolean_subsets_spec.rb +0 -47
  552. data/spec/extensions/caching_spec.rb +0 -270
  553. data/spec/extensions/class_table_inheritance_spec.rb +0 -444
  554. data/spec/extensions/column_conflicts_spec.rb +0 -60
  555. data/spec/extensions/column_select_spec.rb +0 -108
  556. data/spec/extensions/columns_introspection_spec.rb +0 -91
  557. data/spec/extensions/composition_spec.rb +0 -242
  558. data/spec/extensions/connection_expiration_spec.rb +0 -121
  559. data/spec/extensions/connection_validator_spec.rb +0 -127
  560. data/spec/extensions/constraint_validations_plugin_spec.rb +0 -288
  561. data/spec/extensions/constraint_validations_spec.rb +0 -389
  562. data/spec/extensions/core_refinements_spec.rb +0 -519
  563. data/spec/extensions/csv_serializer_spec.rb +0 -180
  564. data/spec/extensions/current_datetime_timestamp_spec.rb +0 -27
  565. data/spec/extensions/dataset_associations_spec.rb +0 -343
  566. data/spec/extensions/dataset_source_alias_spec.rb +0 -51
  567. data/spec/extensions/date_arithmetic_spec.rb +0 -167
  568. data/spec/extensions/defaults_setter_spec.rb +0 -102
  569. data/spec/extensions/delay_add_association_spec.rb +0 -74
  570. data/spec/extensions/dirty_spec.rb +0 -180
  571. data/spec/extensions/duplicate_columns_handler_spec.rb +0 -110
  572. data/spec/extensions/eager_each_spec.rb +0 -66
  573. data/spec/extensions/empty_array_consider_nulls_spec.rb +0 -24
  574. data/spec/extensions/error_splitter_spec.rb +0 -18
  575. data/spec/extensions/error_sql_spec.rb +0 -20
  576. data/spec/extensions/eval_inspect_spec.rb +0 -73
  577. data/spec/extensions/filter_having_spec.rb +0 -40
  578. data/spec/extensions/force_encoding_spec.rb +0 -114
  579. data/spec/extensions/from_block_spec.rb +0 -21
  580. data/spec/extensions/graph_each_spec.rb +0 -119
  581. data/spec/extensions/hash_aliases_spec.rb +0 -24
  582. data/spec/extensions/hook_class_methods_spec.rb +0 -429
  583. data/spec/extensions/identifier_columns_spec.rb +0 -17
  584. data/spec/extensions/inflector_spec.rb +0 -183
  585. data/spec/extensions/input_transformer_spec.rb +0 -54
  586. data/spec/extensions/insert_returning_select_spec.rb +0 -46
  587. data/spec/extensions/instance_filters_spec.rb +0 -79
  588. data/spec/extensions/instance_hooks_spec.rb +0 -276
  589. data/spec/extensions/inverted_subsets_spec.rb +0 -33
  590. data/spec/extensions/json_serializer_spec.rb +0 -304
  591. data/spec/extensions/lazy_attributes_spec.rb +0 -170
  592. data/spec/extensions/list_spec.rb +0 -278
  593. data/spec/extensions/looser_typecasting_spec.rb +0 -43
  594. data/spec/extensions/many_through_many_spec.rb +0 -2172
  595. data/spec/extensions/meta_def_spec.rb +0 -21
  596. data/spec/extensions/migration_spec.rb +0 -728
  597. data/spec/extensions/modification_detection_spec.rb +0 -80
  598. data/spec/extensions/mssql_optimistic_locking_spec.rb +0 -91
  599. data/spec/extensions/named_timezones_spec.rb +0 -108
  600. data/spec/extensions/nested_attributes_spec.rb +0 -697
  601. data/spec/extensions/no_auto_literal_strings_spec.rb +0 -65
  602. data/spec/extensions/null_dataset_spec.rb +0 -85
  603. data/spec/extensions/optimistic_locking_spec.rb +0 -128
  604. data/spec/extensions/pagination_spec.rb +0 -118
  605. data/spec/extensions/pg_array_associations_spec.rb +0 -736
  606. data/spec/extensions/pg_array_ops_spec.rb +0 -143
  607. data/spec/extensions/pg_array_spec.rb +0 -390
  608. data/spec/extensions/pg_enum_spec.rb +0 -92
  609. data/spec/extensions/pg_hstore_ops_spec.rb +0 -236
  610. data/spec/extensions/pg_hstore_spec.rb +0 -206
  611. data/spec/extensions/pg_inet_ops_spec.rb +0 -101
  612. data/spec/extensions/pg_inet_spec.rb +0 -52
  613. data/spec/extensions/pg_interval_spec.rb +0 -76
  614. data/spec/extensions/pg_json_ops_spec.rb +0 -275
  615. data/spec/extensions/pg_json_spec.rb +0 -218
  616. data/spec/extensions/pg_loose_count_spec.rb +0 -17
  617. data/spec/extensions/pg_range_ops_spec.rb +0 -58
  618. data/spec/extensions/pg_range_spec.rb +0 -473
  619. data/spec/extensions/pg_row_ops_spec.rb +0 -60
  620. data/spec/extensions/pg_row_plugin_spec.rb +0 -62
  621. data/spec/extensions/pg_row_spec.rb +0 -360
  622. data/spec/extensions/pg_static_cache_updater_spec.rb +0 -92
  623. data/spec/extensions/pg_typecast_on_load_spec.rb +0 -63
  624. data/spec/extensions/prepared_statements_associations_spec.rb +0 -159
  625. data/spec/extensions/prepared_statements_safe_spec.rb +0 -61
  626. data/spec/extensions/prepared_statements_spec.rb +0 -103
  627. data/spec/extensions/prepared_statements_with_pk_spec.rb +0 -31
  628. data/spec/extensions/pretty_table_spec.rb +0 -92
  629. data/spec/extensions/query_literals_spec.rb +0 -183
  630. data/spec/extensions/query_spec.rb +0 -102
  631. data/spec/extensions/rcte_tree_spec.rb +0 -392
  632. data/spec/extensions/round_timestamps_spec.rb +0 -43
  633. data/spec/extensions/schema_caching_spec.rb +0 -41
  634. data/spec/extensions/schema_dumper_spec.rb +0 -814
  635. data/spec/extensions/schema_spec.rb +0 -117
  636. data/spec/extensions/scissors_spec.rb +0 -26
  637. data/spec/extensions/select_remove_spec.rb +0 -38
  638. data/spec/extensions/sequel_3_dataset_methods_spec.rb +0 -101
  639. data/spec/extensions/serialization_modification_detection_spec.rb +0 -98
  640. data/spec/extensions/serialization_spec.rb +0 -362
  641. data/spec/extensions/server_block_spec.rb +0 -90
  642. data/spec/extensions/server_logging_spec.rb +0 -45
  643. data/spec/extensions/set_overrides_spec.rb +0 -61
  644. data/spec/extensions/sharding_spec.rb +0 -198
  645. data/spec/extensions/shared_caching_spec.rb +0 -175
  646. data/spec/extensions/single_table_inheritance_spec.rb +0 -297
  647. data/spec/extensions/singular_table_names_spec.rb +0 -22
  648. data/spec/extensions/skip_create_refresh_spec.rb +0 -17
  649. data/spec/extensions/spec_helper.rb +0 -71
  650. data/spec/extensions/split_array_nil_spec.rb +0 -24
  651. data/spec/extensions/split_values_spec.rb +0 -22
  652. data/spec/extensions/sql_comments_spec.rb +0 -27
  653. data/spec/extensions/sql_expr_spec.rb +0 -60
  654. data/spec/extensions/static_cache_spec.rb +0 -361
  655. data/spec/extensions/string_agg_spec.rb +0 -85
  656. data/spec/extensions/string_date_time_spec.rb +0 -95
  657. data/spec/extensions/string_stripper_spec.rb +0 -68
  658. data/spec/extensions/subclasses_spec.rb +0 -66
  659. data/spec/extensions/subset_conditions_spec.rb +0 -38
  660. data/spec/extensions/table_select_spec.rb +0 -71
  661. data/spec/extensions/tactical_eager_loading_spec.rb +0 -136
  662. data/spec/extensions/thread_local_timezones_spec.rb +0 -67
  663. data/spec/extensions/timestamps_spec.rb +0 -175
  664. data/spec/extensions/to_dot_spec.rb +0 -154
  665. data/spec/extensions/touch_spec.rb +0 -203
  666. data/spec/extensions/tree_spec.rb +0 -274
  667. data/spec/extensions/typecast_on_load_spec.rb +0 -80
  668. data/spec/extensions/unlimited_update_spec.rb +0 -20
  669. data/spec/extensions/update_or_create_spec.rb +0 -87
  670. data/spec/extensions/update_primary_key_spec.rb +0 -100
  671. data/spec/extensions/update_refresh_spec.rb +0 -53
  672. data/spec/extensions/uuid_spec.rb +0 -106
  673. data/spec/extensions/validate_associated_spec.rb +0 -52
  674. data/spec/extensions/validation_class_methods_spec.rb +0 -1027
  675. data/spec/extensions/validation_helpers_spec.rb +0 -554
  676. data/spec/extensions/xml_serializer_spec.rb +0 -207
  677. data/spec/files/bad_down_migration/001_create_alt_basic.rb +0 -4
  678. data/spec/files/bad_down_migration/002_create_alt_advanced.rb +0 -4
  679. data/spec/files/bad_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  680. data/spec/files/bad_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  681. data/spec/files/bad_timestamped_migrations/1273253853_3_create_users.rb +0 -3
  682. data/spec/files/bad_up_migration/001_create_alt_basic.rb +0 -4
  683. data/spec/files/bad_up_migration/002_create_alt_advanced.rb +0 -3
  684. data/spec/files/convert_to_timestamp_migrations/001_create_sessions.rb +0 -9
  685. data/spec/files/convert_to_timestamp_migrations/002_create_nodes.rb +0 -9
  686. data/spec/files/convert_to_timestamp_migrations/003_3_create_users.rb +0 -4
  687. data/spec/files/convert_to_timestamp_migrations/1273253850_create_artists.rb +0 -9
  688. data/spec/files/convert_to_timestamp_migrations/1273253852_create_albums.rb +0 -9
  689. data/spec/files/double_migration/001_create_sessions.rb +0 -9
  690. data/spec/files/double_migration/002_create_nodes.rb +0 -19
  691. data/spec/files/double_migration/003_3_create_users.rb +0 -4
  692. data/spec/files/duplicate_integer_migrations/001_create_alt_advanced.rb +0 -4
  693. data/spec/files/duplicate_integer_migrations/001_create_alt_basic.rb +0 -4
  694. data/spec/files/duplicate_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  695. data/spec/files/duplicate_timestamped_migrations/1273253853_create_nodes.rb +0 -9
  696. data/spec/files/duplicate_timestamped_migrations/1273253853_create_users.rb +0 -4
  697. data/spec/files/empty_migration/001_create_sessions.rb +0 -9
  698. data/spec/files/empty_migration/002_create_nodes.rb +0 -0
  699. data/spec/files/empty_migration/003_3_create_users.rb +0 -4
  700. data/spec/files/integer_migrations/001_create_sessions.rb +0 -9
  701. data/spec/files/integer_migrations/002_create_nodes.rb +0 -9
  702. data/spec/files/integer_migrations/003_3_create_users.rb +0 -4
  703. data/spec/files/interleaved_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  704. data/spec/files/interleaved_timestamped_migrations/1273253850_create_artists.rb +0 -9
  705. data/spec/files/interleaved_timestamped_migrations/1273253851_create_nodes.rb +0 -9
  706. data/spec/files/interleaved_timestamped_migrations/1273253852_create_albums.rb +0 -9
  707. data/spec/files/interleaved_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  708. data/spec/files/missing_integer_migrations/001_create_alt_basic.rb +0 -4
  709. data/spec/files/missing_integer_migrations/003_create_alt_advanced.rb +0 -4
  710. data/spec/files/missing_timestamped_migrations/1273253849_create_sessions.rb +0 -9
  711. data/spec/files/missing_timestamped_migrations/1273253853_3_create_users.rb +0 -4
  712. data/spec/files/reversible_migrations/001_reversible.rb +0 -5
  713. data/spec/files/reversible_migrations/002_reversible.rb +0 -5
  714. data/spec/files/reversible_migrations/003_reversible.rb +0 -5
  715. data/spec/files/reversible_migrations/004_reversible.rb +0 -5
  716. data/spec/files/reversible_migrations/005_reversible.rb +0 -10
  717. data/spec/files/reversible_migrations/006_reversible.rb +0 -10
  718. data/spec/files/reversible_migrations/007_reversible.rb +0 -10
  719. data/spec/files/timestamped_migrations/1273253849_create_sessions.rb +0 -9
  720. data/spec/files/timestamped_migrations/1273253851_create_nodes.rb +0 -9
  721. data/spec/files/timestamped_migrations/1273253853_3_create_users.rb +0 -4
  722. data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +0 -4
  723. data/spec/files/transaction_specified_migrations/002_create_basic.rb +0 -4
  724. data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +0 -3
  725. data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +0 -3
  726. data/spec/files/uppercase_timestamped_migrations/1273253849_CREATE_SESSIONS.RB +0 -9
  727. data/spec/files/uppercase_timestamped_migrations/1273253851_CREATE_NODES.RB +0 -9
  728. data/spec/files/uppercase_timestamped_migrations/1273253853_3_CREATE_USERS.RB +0 -4
  729. data/spec/guards_helper.rb +0 -55
  730. data/spec/integration/associations_test.rb +0 -2506
  731. data/spec/integration/database_test.rb +0 -113
  732. data/spec/integration/dataset_test.rb +0 -1858
  733. data/spec/integration/eager_loader_test.rb +0 -687
  734. data/spec/integration/migrator_test.rb +0 -262
  735. data/spec/integration/model_test.rb +0 -230
  736. data/spec/integration/plugin_test.rb +0 -2297
  737. data/spec/integration/prepared_statement_test.rb +0 -467
  738. data/spec/integration/schema_test.rb +0 -815
  739. data/spec/integration/spec_helper.rb +0 -56
  740. data/spec/integration/timezone_test.rb +0 -86
  741. data/spec/integration/transaction_test.rb +0 -406
  742. data/spec/integration/type_test.rb +0 -133
  743. data/spec/model/association_reflection_spec.rb +0 -565
  744. data/spec/model/associations_spec.rb +0 -4589
  745. data/spec/model/base_spec.rb +0 -759
  746. data/spec/model/class_dataset_methods_spec.rb +0 -150
  747. data/spec/model/dataset_methods_spec.rb +0 -149
  748. data/spec/model/eager_loading_spec.rb +0 -2197
  749. data/spec/model/hooks_spec.rb +0 -604
  750. data/spec/model/inflector_spec.rb +0 -26
  751. data/spec/model/model_spec.rb +0 -1097
  752. data/spec/model/plugins_spec.rb +0 -299
  753. data/spec/model/record_spec.rb +0 -2162
  754. data/spec/model/spec_helper.rb +0 -46
  755. data/spec/model/validations_spec.rb +0 -193
  756. data/spec/model_no_assoc_spec.rb +0 -1
  757. data/spec/model_spec.rb +0 -1
  758. data/spec/plugin_spec.rb +0 -1
  759. data/spec/sequel_coverage.rb +0 -15
  760. data/spec/spec_config.rb +0 -10
@@ -1,22 +1,19 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- Sequel.require %w'emulate_offset_with_row_number split_alter_table', 'adapters/utils'
3
+ require_relative '../utils/emulate_offset_with_row_number'
4
+ require_relative '../utils/split_alter_table'
4
5
 
5
6
  module Sequel
6
- Dataset::NON_SQL_OPTIONS << :disable_insert_output
7
7
  module MSSQL
8
+ Sequel::Database.set_shared_adapter_scheme(:mssql, self)
9
+
10
+ def self.mock_adapter_setup(db)
11
+ db.instance_exec do
12
+ @server_version = 11000000
13
+ end
14
+ end
15
+
8
16
  module DatabaseMethods
9
- extend Sequel::Database::ResetIdentifierMangling
10
-
11
- AUTO_INCREMENT = 'IDENTITY(1,1)'.freeze
12
- SERVER_VERSION_RE = /^(\d+)\.(\d+)\.(\d+)/.freeze
13
- SERVER_VERSION_SQL = "SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)".freeze
14
- SQL_BEGIN = "BEGIN TRANSACTION".freeze
15
- SQL_COMMIT = "COMMIT TRANSACTION".freeze
16
- SQL_ROLLBACK = "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION".freeze
17
- SQL_ROLLBACK_TO_SAVEPOINT = 'IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_%d'.freeze
18
- SQL_SAVEPOINT = 'SAVE TRANSACTION autopoint_%d'.freeze
19
- MSSQL_DEFAULT_RE = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/
20
17
  FOREIGN_KEY_ACTION_MAP = {0 => :no_action, 1 => :cascade, 2 => :set_null, 3 => :set_default}.freeze
21
18
 
22
19
  include Sequel::Database::SplitAlterTable
@@ -25,16 +22,11 @@ module Sequel
25
22
  # strings. True by default for compatibility, can be set to false for a possible
26
23
  # performance increase. This sets the default for all datasets created from this
27
24
  # Database object.
28
- attr_reader :mssql_unicode_strings
29
-
30
- def mssql_unicode_strings=(v)
31
- @mssql_unicode_strings = v
32
- reset_default_dataset
33
- end
25
+ attr_accessor :mssql_unicode_strings
34
26
 
35
- # The types to check for 0 scale to transform :decimal types
36
- # to :integer.
37
- DECIMAL_TYPE_RE = /number|numeric|decimal/io
27
+ # Whether to use LIKE without COLLATE Latin1_General_CS_AS. Skipping the COLLATE
28
+ # can significantly increase performance in some cases.
29
+ attr_accessor :like_without_collate
38
30
 
39
31
  # Execute the given stored procedure with the given name.
40
32
  #
@@ -52,13 +44,19 @@ module Sequel
52
44
  # :numrows :: The number of rows affected by the stored procedure
53
45
  # output params :: Values for any output paramters, using the name given for the output parameter
54
46
  #
47
+ # Because Sequel datasets only support a single result set per query, and retrieving
48
+ # the result code and number of rows requires a query, this does not support
49
+ # stored procedures which also return result sets. To handle such stored procedures,
50
+ # you should drop down to the connection/driver level by using Sequel::Database#synchronize
51
+ # to get access to the underlying connection object.
52
+ #
55
53
  # Examples:
56
54
  #
57
- # DB.call_mssql_sproc(:SequelTest, {:args => ['input arg', :output]})
58
- # DB.call_mssql_sproc(:SequelTest, {:args => ['input arg', [:output, 'int', 'varname']]})
55
+ # DB.call_mssql_sproc(:SequelTest, {args: ['input arg', :output]})
56
+ # DB.call_mssql_sproc(:SequelTest, {args: ['input arg', [:output, 'int', 'varname']]})
59
57
  #
60
58
  # named params:
61
- # DB.call_mssql_sproc(:SequelTest, :args => {
59
+ # DB.call_mssql_sproc(:SequelTest, args: {
62
60
  # 'input_arg1_name' => 'input arg1 value',
63
61
  # 'input_arg2_name' => 'input arg2 value',
64
62
  # 'output_arg_name' => [:output, 'int', 'varname']
@@ -77,7 +75,7 @@ module Sequel
77
75
  method = :each_with_index
78
76
  end
79
77
 
80
- args.send(method) do |v, i|
78
+ args.public_send(method) do |v, i|
81
79
  if named_args
82
80
  k = v
83
81
  v, type, select = i
@@ -115,7 +113,6 @@ module Sequel
115
113
  ds.first
116
114
  end
117
115
 
118
- # Microsoft SQL Server uses the :mssql type.
119
116
  def database_type
120
117
  :mssql
121
118
  end
@@ -133,20 +130,22 @@ module Sequel
133
130
  schema, table = schema_and_table(table)
134
131
  current_schema = m.call(get(Sequel.function('schema_name')))
135
132
  fk_action_map = FOREIGN_KEY_ACTION_MAP
133
+ fk = Sequel[:fk]
134
+ fkc = Sequel[:fkc]
136
135
  ds = metadata_dataset.from(Sequel.lit('[sys].[foreign_keys]').as(:fk)).
137
136
  join(Sequel.lit('[sys].[foreign_key_columns]').as(:fkc), :constraint_object_id => :object_id).
138
- join(Sequel.lit('[sys].[all_columns]').as(:pc), :object_id => :fkc__parent_object_id, :column_id => :fkc__parent_column_id).
139
- join(Sequel.lit('[sys].[all_columns]').as(:rc), :object_id => :fkc__referenced_object_id, :column_id => :fkc__referenced_column_id).
140
- where{{object_schema_name(:fk__parent_object_id) => im.call(schema || current_schema)}}.
141
- where{{object_name(:fk__parent_object_id) => im.call(table)}}.
142
- select{[:fk__name,
143
- :fk__delete_referential_action,
144
- :fk__update_referential_action,
145
- :pc__name___column,
146
- :rc__name___referenced_column,
147
- object_schema_name(:fk__referenced_object_id).as(:schema),
148
- object_name(:fk__referenced_object_id).as(:table)]}.
149
- order(:fk__name, :fkc__constraint_column_id)
137
+ join(Sequel.lit('[sys].[all_columns]').as(:pc), :object_id => fkc[:parent_object_id], :column_id => fkc[:parent_column_id]).
138
+ join(Sequel.lit('[sys].[all_columns]').as(:rc), :object_id => fkc[:referenced_object_id], :column_id => fkc[:referenced_column_id]).
139
+ where{{object_schema_name(fk[:parent_object_id]) => im.call(schema || current_schema)}}.
140
+ where{{object_name(fk[:parent_object_id]) => im.call(table)}}.
141
+ select{[fk[:name],
142
+ fk[:delete_referential_action],
143
+ fk[:update_referential_action],
144
+ pc[:name].as(:column),
145
+ rc[:name].as(:referenced_column),
146
+ object_schema_name(fk[:referenced_object_id]).as(:schema),
147
+ object_name(fk[:referenced_object_id]).as(:table)]}.
148
+ order(fk[:name], fkc[:constraint_column_id])
150
149
  h = {}
151
150
  ds.each do |row|
152
151
  if r = h[row[:name]]
@@ -166,22 +165,29 @@ module Sequel
166
165
  h.values
167
166
  end
168
167
 
168
+ def freeze
169
+ server_version
170
+ super
171
+ end
172
+
169
173
  # Use the system tables to get index information
170
174
  def indexes(table, opts=OPTS)
171
175
  m = output_identifier_meth
172
176
  im = input_identifier_meth
173
177
  indexes = {}
178
+ table = table.value if table.is_a?(Sequel::SQL::Identifier)
179
+ i = Sequel[:i]
174
180
  ds = metadata_dataset.from(Sequel.lit('[sys].[tables]').as(:t)).
175
181
  join(Sequel.lit('[sys].[indexes]').as(:i), :object_id=>:object_id).
176
182
  join(Sequel.lit('[sys].[index_columns]').as(:ic), :object_id=>:object_id, :index_id=>:index_id).
177
183
  join(Sequel.lit('[sys].[columns]').as(:c), :object_id=>:object_id, :column_id=>:column_id).
178
- select(:i__name, :i__is_unique, :c__name___column).
179
- where{{t__name=>im.call(table)}}.
180
- where(:i__is_primary_key=>0, :i__is_disabled=>0).
181
- order(:i__name, :ic__index_column_id)
184
+ select(i[:name], i[:is_unique], Sequel[:c][:name].as(:column)).
185
+ where{{t[:name]=>im.call(table)}}.
186
+ where(i[:is_primary_key]=>0, i[:is_disabled]=>0).
187
+ order(i[:name], Sequel[:ic][:index_column_id])
182
188
 
183
189
  if supports_partial_indexes?
184
- ds = ds.where(:i__has_filter=>0)
190
+ ds = ds.where(i[:has_filter]=>0)
185
191
  end
186
192
 
187
193
  ds.each do |r|
@@ -202,7 +208,7 @@ module Sequel
202
208
  (conn.server_version rescue nil) if conn.respond_to?(:server_version)
203
209
  end
204
210
  unless @server_version
205
- m = SERVER_VERSION_RE.match(fetch(SERVER_VERSION_SQL).single_value.to_s)
211
+ m = /^(\d+)\.(\d+)\.(\d+)/.match(fetch("SELECT CAST(SERVERPROPERTY('ProductVersion') AS varchar)").single_value.to_s)
206
212
  @server_version = (m[1].to_i * 1000000) + (m[2].to_i * 10000) + m[3].to_i
207
213
  end
208
214
  @server_version
@@ -213,7 +219,7 @@ module Sequel
213
219
  dataset.send(:is_2008_or_later?)
214
220
  end
215
221
 
216
- # MSSQL supports savepoints, though it doesn't support committing/releasing them savepoint
222
+ # MSSQL supports savepoints, though it doesn't support releasing them
217
223
  def supports_savepoints?
218
224
  true
219
225
  end
@@ -242,6 +248,16 @@ module Sequel
242
248
 
243
249
  private
244
250
 
251
+ # Add CLUSTERED or NONCLUSTERED as needed
252
+ def add_clustered_sql_fragment(sql, opts)
253
+ clustered = opts[:clustered]
254
+ unless clustered.nil?
255
+ sql += " #{'NON' unless clustered}CLUSTERED"
256
+ end
257
+
258
+ sql
259
+ end
260
+
245
261
  # Add dropping of the default constraint to the list of SQL queries.
246
262
  # This is necessary before dropping the column or changing its type.
247
263
  def add_drop_default_constraint_sql(sqls, table, column)
@@ -252,10 +268,9 @@ module Sequel
252
268
 
253
269
  # MSSQL uses the IDENTITY(1,1) column for autoincrementing columns.
254
270
  def auto_increment_sql
255
- AUTO_INCREMENT
271
+ 'IDENTITY(1,1)'
256
272
  end
257
273
 
258
- # MSSQL specific syntax for altering tables.
259
274
  def alter_table_sql(table, op)
260
275
  case op[:op]
261
276
  when :add_column
@@ -265,7 +280,7 @@ module Sequel
265
280
  add_drop_default_constraint_sql(sqls, table, op[:name])
266
281
  sqls << super
267
282
  when :rename_column
268
- "sp_rename #{literal("#{quote_schema_table(table)}.#{quote_identifier(op[:name])}")}, #{literal(op[:new_name].to_s)}, 'COLUMN'"
283
+ "sp_rename #{literal("#{quote_schema_table(table)}.#{quote_identifier(op[:name])}")}, #{literal(metadata_dataset.with_quote_identifiers(false).quote_identifier(op[:new_name]))}, 'COLUMN'"
269
284
  when :set_column_type
270
285
  sqls = []
271
286
  if sch = schema(table)
@@ -278,50 +293,53 @@ module Sequel
278
293
  end
279
294
  end
280
295
  sqls << "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{column_definition_sql(op)}"
281
- sqls << alter_table_sql(table, op.merge(:op=>:set_column_default, :default=>default)) if default
296
+ sqls << alter_table_sql(table, op.merge(:op=>:set_column_default, :default=>default, :skip_drop_default=>true)) if default
282
297
  sqls
283
298
  when :set_column_null
284
299
  sch = schema(table).find{|k,v| k.to_s == op[:name].to_s}.last
285
300
  type = sch[:db_type]
286
- if [:string, :decimal].include?(sch[:type]) && !["text", "ntext"].include?(type) && (size = (sch[:max_chars] || sch[:column_size]))
301
+ if [:string, :decimal, :blob].include?(sch[:type]) && !["text", "ntext"].include?(type) && (size = (sch[:max_chars] || sch[:column_size]))
287
302
  size = "MAX" if size == -1
288
303
  type += "(#{size}#{", #{sch[:scale]}" if sch[:scale] && sch[:scale].to_i > 0})"
289
304
  end
290
305
  "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(:type=>type)} #{'NOT ' unless op[:null]}NULL"
291
306
  when :set_column_default
292
- "ALTER TABLE #{quote_schema_table(table)} ADD CONSTRAINT #{quote_identifier("sequel_#{table}_#{op[:name]}_def")} DEFAULT #{literal(op[:default])} FOR #{quote_identifier(op[:name])}"
307
+ sqls = []
308
+ add_drop_default_constraint_sql(sqls, table, op[:name]) unless op[:skip_drop_default]
309
+ sqls << "ALTER TABLE #{quote_schema_table(table)} ADD CONSTRAINT #{quote_identifier("sequel_#{table}_#{op[:name]}_def")} DEFAULT #{literal(op[:default])} FOR #{quote_identifier(op[:name])}"
293
310
  else
294
311
  super(table, op)
295
312
  end
296
313
  end
297
314
 
298
- # SQL to start a new savepoint
299
315
  def begin_savepoint_sql(depth)
300
- SQL_SAVEPOINT % depth
316
+ "SAVE TRANSACTION autopoint_#{depth}"
301
317
  end
302
318
 
303
- # SQL to BEGIN a transaction.
304
319
  def begin_transaction_sql
305
- SQL_BEGIN
320
+ "BEGIN TRANSACTION"
321
+ end
322
+
323
+ # MSSQL does not allow adding primary key constraints to NULLable columns.
324
+ def can_add_primary_key_constraint_on_nullable_columns?
325
+ false
306
326
  end
307
327
 
308
328
  # Handle MSSQL specific default format.
309
329
  def column_schema_normalize_default(default, type)
310
- if m = MSSQL_DEFAULT_RE.match(default)
330
+ if m = /\A(?:\(N?('.*')\)|\(\((-?\d+(?:\.\d+)?)\)\))\z/.match(default)
311
331
  default = m[1] || m[2]
312
332
  end
313
333
  super(default, type)
314
334
  end
315
335
 
316
- # Commit the active transaction on the connection, does not commit/release
317
- # savepoints.
336
+ # Commit the active transaction on the connection, does not release savepoints.
318
337
  def commit_transaction(conn, opts=OPTS)
319
338
  log_connection_execute(conn, commit_transaction_sql) unless savepoint_level(conn) > 1
320
339
  end
321
340
 
322
- # SQL to COMMIT a transaction.
323
341
  def commit_transaction_sql
324
- SQL_COMMIT
342
+ "COMMIT TRANSACTION"
325
343
  end
326
344
 
327
345
  # MSSQL uses the name of the table to decide the difference between
@@ -346,6 +364,7 @@ module Sequel
346
364
  /conflicted with the CHECK constraint/ => CheckConstraintViolation,
347
365
  /column does not allow nulls/ => NotNullConstraintViolation,
348
366
  /was deadlocked on lock resources with another process and has been chosen as the deadlock victim/ => SerializationFailure,
367
+ /Lock request time out period exceeded\./ => DatabaseLockTimeout,
349
368
  }.freeze
350
369
  def database_error_regexps
351
370
  DATABASE_ERROR_REGEXPS
@@ -357,18 +376,16 @@ module Sequel
357
376
  def default_constraint_name(table, column_name)
358
377
  if server_version >= 9000000
359
378
  table_name = schema_and_table(table).compact.join('.')
360
- self[:sys__default_constraints].
379
+ self[Sequel[:sys][:default_constraints]].
361
380
  where{{:parent_object_id => Sequel::SQL::Function.new(:object_id, table_name), col_name(:parent_object_id, :parent_column_id) => column_name.to_s}}.
362
381
  get(:name)
363
382
  end
364
383
  end
365
384
 
366
- # The SQL to drop an index for the table.
367
385
  def drop_index_sql(table, op)
368
386
  "DROP INDEX #{quote_identifier(op[:name] || default_index_name(table, op[:columns]))} ON #{quote_schema_table(table)}"
369
387
  end
370
388
 
371
- # support for clustered index type
372
389
  def index_definition_sql(table_name, index)
373
390
  index_name = index[:name] || default_index_name(table_name, index[:columns])
374
391
  raise Error, "Partial indexes are not supported for this database" if index[:where] && !supports_partial_indexes?
@@ -382,17 +399,20 @@ module Sequel
382
399
  # Backbone of the tables and views support.
383
400
  def information_schema_tables(type, opts)
384
401
  m = output_identifier_meth
385
- metadata_dataset.from(:information_schema__tables___t).
402
+ metadata_dataset.from(Sequel[:information_schema][:tables].as(:t)).
386
403
  select(:table_name).
387
- filter(:table_type=>type, :table_schema=>(opts[:schema]||'dbo').to_s).
404
+ where(:table_type=>type, :table_schema=>(opts[:schema]||'dbo').to_s).
388
405
  map{|x| m.call(x[:table_name])}
389
406
  end
390
407
 
391
408
  # Always quote identifiers in the metadata_dataset, so schema parsing works.
392
- def metadata_dataset
393
- ds = super
394
- ds.quote_identifiers = true
395
- ds
409
+ def _metadata_dataset
410
+ super.with_quote_identifiers(true)
411
+ end
412
+
413
+ # Handle clustered and nonclustered primary keys
414
+ def primary_key_constraint_sql_fragment(opts)
415
+ add_clustered_sql_fragment(super, opts)
396
416
  end
397
417
 
398
418
  # Use sp_rename to rename the table
@@ -400,17 +420,14 @@ module Sequel
400
420
  "sp_rename #{literal(quote_schema_table(name))}, #{quote_identifier(schema_and_table(new_name).pop)}"
401
421
  end
402
422
 
403
- # SQL to rollback to a savepoint
404
423
  def rollback_savepoint_sql(depth)
405
- SQL_ROLLBACK_TO_SAVEPOINT % depth
424
+ "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION autopoint_#{depth}"
406
425
  end
407
426
 
408
- # SQL to ROLLBACK a transaction.
409
427
  def rollback_transaction_sql
410
- SQL_ROLLBACK
428
+ "IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION"
411
429
  end
412
430
 
413
- # The closest MSSQL equivalent of a boolean datatype is the bit type.
414
431
  def schema_column_type(db_type)
415
432
  case db_type
416
433
  when /\A(?:bit)\z/io
@@ -431,31 +448,30 @@ module Sequel
431
448
  m = output_identifier_meth(opts[:dataset])
432
449
  m2 = input_identifier_meth(opts[:dataset])
433
450
  tn = m2.call(table_name.to_s)
434
- table_id = get(Sequel.function(:object_id, tn))
435
451
  info_sch_sch = opts[:information_schema_schema]
436
- inf_sch_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, s) : Sequel.expr(s)}
437
- sys_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, Sequel.qualify(Sequel.lit(''), s)) : Sequel.expr(s)}
452
+ inf_sch_qual = lambda{|s| info_sch_sch ? Sequel.qualify(info_sch_sch, s) : Sequel[s]}
453
+ table_id = metadata_dataset.from(inf_sch_qual.call(Sequel[:sys][:objects])).where(:name => tn).select_map(:object_id).first
438
454
 
439
- identity_cols = metadata_dataset.from(Sequel.lit('[sys].[columns]')).
455
+ identity_cols = metadata_dataset.from(inf_sch_qual.call(Sequel[:sys][:columns])).
440
456
  where(:object_id=>table_id, :is_identity=>true).
441
457
  select_map(:name)
442
458
 
443
- pk_index_id = metadata_dataset.from(sys_qual.call(Sequel.lit('sysindexes'))).
459
+ pk_index_id = metadata_dataset.from(inf_sch_qual.call(Sequel[:sys][:sysindexes])).
444
460
  where(:id=>table_id, :indid=>1..254){{(status & 2048)=>2048}}.
445
461
  get(:indid)
446
- pk_cols = metadata_dataset.from(sys_qual.call(Sequel.lit('sysindexkeys')).as(:sik)).
447
- join(sys_qual.call(Sequel.lit('syscolumns')).as(:sc), :id=>:id, :colid=>:colid).
448
- where(:sik__id=>table_id, :sik__indid=>pk_index_id).
449
- select_order_map(:sc__name)
462
+ pk_cols = metadata_dataset.from(inf_sch_qual.call(Sequel[:sys][:sysindexkeys]).as(:sik)).
463
+ join(inf_sch_qual.call(Sequel[:sys][:syscolumns]).as(:sc), :id=>:id, :colid=>:colid).
464
+ where{{sik[:id]=>table_id, sik[:indid]=>pk_index_id}}.
465
+ select_order_map{sc[:name]}
450
466
 
451
- ds = metadata_dataset.from(inf_sch_qual.call(:information_schema__tables).as(:t)).
452
- join(inf_sch_qual.call(:information_schema__columns).as(:c), :table_catalog=>:table_catalog,
467
+ ds = metadata_dataset.from(inf_sch_qual.call(Sequel[:information_schema][:tables]).as(:t)).
468
+ join(inf_sch_qual.call(Sequel[:information_schema][:columns]).as(:c), :table_catalog=>:table_catalog,
453
469
  :table_schema => :table_schema, :table_name => :table_name).
454
- select(:column_name___column, :data_type___db_type, :character_maximum_length___max_chars, :column_default___default, :is_nullable___allow_null, :numeric_precision___column_size, :numeric_scale___scale).
455
- filter(:c__table_name=>tn)
470
+ select{[column_name.as(:column), data_type.as(:db_type), character_maximum_length.as(:max_chars), column_default.as(:default), is_nullable.as(:allow_null), numeric_precision.as(:column_size), numeric_scale.as(:scale)]}.
471
+ where{{c[:table_name]=>tn}}
456
472
 
457
473
  if schema = opts[:schema]
458
- ds.filter!(:c__table_schema=>schema)
474
+ ds = ds.where{{c[:table_schema]=>schema}}
459
475
  end
460
476
 
461
477
  ds.map do |row|
@@ -464,7 +480,7 @@ module Sequel
464
480
  end
465
481
  row[:allow_null] = row[:allow_null] == 'YES' ? true : false
466
482
  row[:default] = nil if blank_object?(row[:default])
467
- row[:type] = if row[:db_type] =~ DECIMAL_TYPE_RE && row[:scale] == 0
483
+ row[:type] = if row[:db_type] =~ /number|numeric|decimal/i && row[:scale] == 0
468
484
  :integer
469
485
  else
470
486
  schema_column_type(row[:db_type])
@@ -485,12 +501,6 @@ module Sequel
485
501
  :datetime
486
502
  end
487
503
 
488
- # MSSQL has both datetime and timestamp classes, most people are going
489
- # to want datetime
490
- def type_literal_generic_time(column)
491
- column[:only_time] ? :time : :datetime
492
- end
493
-
494
504
  # MSSQL doesn't have a true boolean class, so it uses bit
495
505
  def type_literal_generic_trueclass(column)
496
506
  :bit
@@ -501,6 +511,11 @@ module Sequel
501
511
  :'varbinary(max)'
502
512
  end
503
513
 
514
+ # Handle clustered and nonclustered unique constraints
515
+ def unique_constraint_sql_fragment(opts)
516
+ add_clustered_sql_fragment(super, opts)
517
+ end
518
+
504
519
  # MSSQL supports views with check option, but not local.
505
520
  def view_with_check_option_support
506
521
  true
@@ -509,95 +524,53 @@ module Sequel
509
524
 
510
525
  module DatasetMethods
511
526
  include(Module.new do
512
- Dataset.def_sql_method(self, :select, %w'with select distinct limit columns into from lock join where group having order compounds')
527
+ Dataset.def_sql_method(self, :select, %w'with select distinct limit columns into from lock join where group having compounds order')
513
528
  end)
514
529
  include EmulateOffsetWithRowNumber
515
530
 
516
- BOOL_TRUE = '1'.freeze
517
- BOOL_FALSE = '0'.freeze
518
- COMMA_SEPARATOR = ', '.freeze
519
- TABLE_HINT = " WITH (".freeze
520
- READPAST = "READPAST".freeze
521
- NOLOCK = 'NOLOCK'.freeze
522
- UPDLOCK = 'UPDLOCK'.freeze
523
- WILDCARD = LiteralString.new('*').freeze
524
- CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}
525
- EXTRACT_MAP = {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}
526
- BRACKET_CLOSE = Dataset::BRACKET_CLOSE
527
- BRACKET_OPEN = Dataset::BRACKET_OPEN
528
- COMMA = Dataset::COMMA
529
- PAREN_CLOSE = Dataset::PAREN_CLOSE
530
- PAREN_SPACE_OPEN = Dataset::PAREN_SPACE_OPEN
531
- SPACE = Dataset::SPACE
532
- FROM = Dataset::FROM
533
- APOS = Dataset::APOS
534
- APOS_RE = Dataset::APOS_RE
535
- DOUBLE_APOS = Dataset::DOUBLE_APOS
536
- INTO = Dataset::INTO
537
- DOUBLE_BRACKET_CLOSE = ']]'.freeze
538
- DATEPART_SECOND_OPEN = "CAST((datepart(".freeze
539
- DATEPART_SECOND_MIDDLE = ') + datepart(ns, '.freeze
540
- DATEPART_SECOND_CLOSE = ")/1000000000.0) AS double precision)".freeze
541
- DATEPART_OPEN = "datepart(".freeze
542
- OUTPUT_INSERTED = " OUTPUT INSERTED.*".freeze
543
- HEX_START = '0x'.freeze
544
- UNICODE_STRING_START = "N'".freeze
545
- BACKSLASH_CRLF_RE = /\\((?:\r\n)|\n)/.freeze
546
- BACKSLASH_CRLF_REPLACE = '\\\\\\\\\\1\\1'.freeze
547
- TOP_PAREN = " TOP (".freeze
548
- TOP = " TOP ".freeze
549
- OUTPUT = " OUTPUT ".freeze
550
- HSTAR = "H*".freeze
551
- CASE_SENSITIVE_COLLATION = 'Latin1_General_CS_AS'.freeze
552
- CASE_INSENSITIVE_COLLATION = 'Latin1_General_CI_AS'.freeze
553
- DEFAULT_TIMESTAMP_FORMAT = "'%Y-%m-%dT%H:%M:%S%N%z'".freeze
554
- FORMAT_DATE = "'%Y%m%d'".freeze
555
- CROSS_APPLY = 'CROSS APPLY'.freeze
556
- OUTER_APPLY = 'OUTER APPLY'.freeze
557
- OFFSET = " OFFSET ".freeze
558
- ROWS = " ROWS".freeze
559
- ROWS_ONLY = " ROWS ONLY".freeze
560
- FETCH_NEXT = " FETCH NEXT ".freeze
561
-
562
- Dataset.def_mutation_method(:disable_insert_output, :output, :module=>self)
563
- Dataset.def_sql_method(self, :delete, %w'with delete from output from2 where')
531
+ CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}.freeze
532
+ EXTRACT_MAP = {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}.freeze
533
+ EXTRACT_MAP.each_value(&:freeze)
534
+ LIMIT_ALL = Object.new.freeze
535
+
536
+ Dataset.def_sql_method(self, :delete, %w'with delete limit from output from2 where')
564
537
  Dataset.def_sql_method(self, :insert, %w'with insert into columns output values')
565
538
  Dataset.def_sql_method(self, :update, [['if is_2005_or_later?', %w'with update limit table set output from where'], ['else', %w'update table set output from where']])
566
539
 
567
-
568
- # Allow overriding of the mssql_unicode_strings option at the dataset level.
569
- attr_writer :mssql_unicode_strings
570
-
571
540
  # Use the database's mssql_unicode_strings setting if the dataset hasn't overridden it.
572
541
  def mssql_unicode_strings
573
- defined?(@mssql_unicode_strings) ? @mssql_unicode_strings : (@mssql_unicode_strings = db.mssql_unicode_strings)
542
+ opts.has_key?(:mssql_unicode_strings) ? opts[:mssql_unicode_strings] : db.mssql_unicode_strings
543
+ end
544
+
545
+ # Return a cloned dataset with the mssql_unicode_strings option set.
546
+ def with_mssql_unicode_strings(v)
547
+ clone(:mssql_unicode_strings=>v)
574
548
  end
575
549
 
576
- # MSSQL uses + for string concatenation, and LIKE is case insensitive by default.
577
550
  def complex_expression_sql_append(sql, op, args)
578
551
  case op
579
552
  when :'||'
580
553
  super(sql, :+, args)
581
554
  when :LIKE, :"NOT LIKE"
582
- super(sql, op, args.map{|a| Sequel.lit(["(", " COLLATE #{CASE_SENSITIVE_COLLATION})"], a)})
555
+ super(sql, op, complex_expression_sql_like_args(args, " COLLATE Latin1_General_CS_AS)"))
583
556
  when :ILIKE, :"NOT ILIKE"
584
- super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|a| Sequel.lit(["(", " COLLATE #{CASE_INSENSITIVE_COLLATION})"], a)})
557
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), complex_expression_sql_like_args(args, " COLLATE Latin1_General_CI_AS)"))
585
558
  when :<<, :>>
586
559
  complex_expression_emulate_append(sql, op, args)
587
560
  when :extract
588
- part = args.at(0)
561
+ part = args[0]
589
562
  raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part]
590
563
  if part == :second
591
- expr = args.at(1)
592
- sql << DATEPART_SECOND_OPEN << format.to_s << COMMA
564
+ expr = args[1]
565
+ sql << "CAST((datepart(" << format.to_s << ', '
593
566
  literal_append(sql, expr)
594
- sql << DATEPART_SECOND_MIDDLE
567
+ sql << ') + datepart(ns, '
595
568
  literal_append(sql, expr)
596
- sql << DATEPART_SECOND_CLOSE
569
+ sql << ")/1000000000.0) AS double precision)"
597
570
  else
598
- sql << DATEPART_OPEN << format.to_s << COMMA
599
- literal_append(sql, args.at(1))
600
- sql << PAREN_CLOSE
571
+ sql << "datepart(" << format.to_s << ', '
572
+ literal_append(sql, args[1])
573
+ sql << ')'
601
574
  end
602
575
  else
603
576
  super
@@ -631,13 +604,15 @@ module Sequel
631
604
  # MSSQL uses the CONTAINS keyword for full text search
632
605
  def full_text_search(cols, terms, opts = OPTS)
633
606
  terms = "\"#{terms.join('" OR "')}\"" if terms.is_a?(Array)
634
- filter("CONTAINS (?, ?)", cols, terms)
607
+ where(Sequel.lit("CONTAINS (?, ?)", cols, terms))
635
608
  end
636
609
 
637
- # Use the OUTPUT clause to get the value of all columns for the newly inserted record.
610
+ # Insert a record, returning the record inserted, using OUTPUT. Always returns nil without
611
+ # running an INSERT statement if disable_insert_output is used. If the query runs
612
+ # but returns no values, returns false.
638
613
  def insert_select(*values)
639
614
  return unless supports_insert_select?
640
- with_sql_first(insert_select_sql(*values))
615
+ with_sql_first(insert_select_sql(*values)) || false
641
616
  end
642
617
 
643
618
  # Add OUTPUT clause unless there is already an existing output clause, then return
@@ -672,8 +647,8 @@ module Sequel
672
647
  #
673
648
  # Examples:
674
649
  #
675
- # dataset.output(:output_table, [:deleted__id, :deleted__name])
676
- # dataset.output(:output_table, :id => :inserted__id, :name => :inserted__name)
650
+ # dataset.output(:output_table, [Sequel[:deleted][:id], Sequel[:deleted][:name]])
651
+ # dataset.output(:output_table, id: Sequel[:inserted][:id], name: Sequel[:inserted][:name])
677
652
  def output(into, values)
678
653
  raise(Error, "SQL Server versions 2000 and earlier do not support the OUTPUT clause") unless supports_output_clause?
679
654
  output = {}
@@ -689,7 +664,7 @@ module Sequel
689
664
 
690
665
  # MSSQL uses [] to quote identifiers.
691
666
  def quoted_identifier_append(sql, name)
692
- sql << BRACKET_OPEN << name.to_s.gsub(/\]/, DOUBLE_BRACKET_CLOSE) << BRACKET_CLOSE
667
+ sql << '[' << name.to_s.gsub(/\]/, ']]') << ']'
693
668
  end
694
669
 
695
670
  # Emulate RETURNING using the output clause. This only handles values that are simple column references.
@@ -708,11 +683,11 @@ module Sequel
708
683
  # case by default, and that also adds a default order, so it's better to just
709
684
  # avoid the subquery.
710
685
  def select_sql
711
- if @opts[:offset] && !@opts[:order] && is_2012_or_later?
712
- order(1).select_sql
713
- else
714
- super
686
+ if @opts[:offset]
687
+ raise(Error, "Using with_ties is not supported with an offset on Microsoft SQL Server") if @opts[:limit_with_ties]
688
+ return order(1).select_sql if is_2012_or_later? && !@opts[:order]
715
689
  end
690
+ super
716
691
  end
717
692
 
718
693
  # The version of the database server.
@@ -759,6 +734,11 @@ module Sequel
759
734
  false
760
735
  end
761
736
 
737
+ # MSSQL 2008+ supports MERGE
738
+ def supports_merge?
739
+ is_2008_or_later?
740
+ end
741
+
762
742
  # MSSQL 2005+ supports modifying joined datasets
763
743
  def supports_modifying_joins?
764
744
  is_2005_or_later?
@@ -769,6 +749,11 @@ module Sequel
769
749
  false
770
750
  end
771
751
 
752
+ # MSSQL supports NOWAIT.
753
+ def supports_nowait?
754
+ true
755
+ end
756
+
772
757
  # MSSQL 2012+ supports offsets in correlated subqueries.
773
758
  def supports_offsets_in_correlated_subqueries?
774
759
  is_2012_or_later?
@@ -799,6 +784,12 @@ module Sequel
799
784
  false
800
785
  end
801
786
 
787
+ # Use WITH TIES when limiting the result set to also include additional
788
+ # rows matching the last row.
789
+ def with_ties
790
+ clone(:limit_with_ties=>true)
791
+ end
792
+
802
793
  protected
803
794
 
804
795
  # If returned primary keys are requested, use OUTPUT unless already set on the
@@ -810,20 +801,74 @@ module Sequel
810
801
  output(nil, [SQL::QualifiedIdentifier.new(:inserted, first_primary_key)])._import(columns, values, opts)
811
802
  elsif @opts[:output]
812
803
  statements = multi_insert_sql(columns, values)
804
+ ds = naked
813
805
  @db.transaction(opts.merge(:server=>@opts[:server])) do
814
- statements.map{|st| with_sql(st)}
806
+ statements.map{|st| ds.with_sql(st)}
815
807
  end.first.map{|v| v.length == 1 ? v.values.first : v}
816
808
  else
817
809
  super
818
810
  end
819
811
  end
820
812
 
821
- # MSSQL does not allow ordering in sub-clauses unless 'top' (limit) is specified
813
+ # If the dataset using a order without a limit or offset or custom SQL,
814
+ # remove the order. Compounds on Microsoft SQL Server have undefined
815
+ # order unless the result is specifically ordered. Applying the current
816
+ # order before the compound doesn't work in all cases, such as when
817
+ # qualified identifiers are used. If you want to ensure a order
818
+ # for a compound dataset, apply the order after all compounds have been
819
+ # added.
820
+ def compound_from_self
821
+ if @opts[:offset] && !@opts[:limit] && !is_2012_or_later?
822
+ clone(:limit=>LIMIT_ALL).from_self
823
+ elsif @opts[:order] && !(@opts[:sql] || @opts[:limit] || @opts[:offset])
824
+ unordered
825
+ else
826
+ super
827
+ end
828
+ end
829
+
830
+ private
831
+
832
+ # Normalize conditions for MERGE WHEN.
833
+ def _merge_when_conditions_sql(sql, data)
834
+ if data.has_key?(:conditions)
835
+ sql << " AND "
836
+ literal_append(sql, _normalize_merge_when_conditions(data[:conditions]))
837
+ end
838
+ end
839
+
840
+ # Handle nil, false, and true MERGE WHEN conditions to avoid non-boolean
841
+ # type error.
842
+ def _normalize_merge_when_conditions(conditions)
843
+ case conditions
844
+ when nil, false
845
+ {1=>0}
846
+ when true
847
+ {1=>1}
848
+ when Sequel::SQL::DelayedEvaluation
849
+ Sequel.delay{_normalize_merge_when_conditions(conditions.call(self))}
850
+ else
851
+ conditions
852
+ end
853
+ end
854
+
855
+ # MSSQL requires a semicolon at the end of MERGE.
856
+ def _merge_when_sql(sql)
857
+ super
858
+ sql << ';'
859
+ end
860
+
861
+ # MSSQL does not allow ordering in sub-clauses unless TOP (limit) is specified
822
862
  def aggregate_dataset
823
863
  (options_overlap(Sequel::Dataset::COUNT_FROM_SELF_OPTS) && !options_overlap([:limit])) ? unordered.from_self : super
824
864
  end
825
865
 
826
- private
866
+ # Allow update and delete for unordered, limited datasets only.
867
+ def check_not_limited!(type)
868
+ return if @opts[:skip_limit_check] && type != :truncate
869
+ raise Sequel::InvalidOperation, "Dataset##{type} not suppored on ordered, limited datasets" if opts[:order] && opts[:limit]
870
+ super if type == :truncate || @opts[:offset]
871
+ end
827
872
 
828
873
  # Whether we are using SQL Server 2005 or later.
829
874
  def is_2005_or_later?
@@ -840,16 +885,25 @@ module Sequel
840
885
  server_version >= 11000000
841
886
  end
842
887
 
888
+ # Determine whether to add the COLLATE for LIKE arguments, based on the Database setting.
889
+ def complex_expression_sql_like_args(args, collation)
890
+ if db.like_without_collate
891
+ args
892
+ else
893
+ args.map{|a| Sequel.lit(["(", collation], a)}
894
+ end
895
+ end
896
+
843
897
  # Use strict ISO-8601 format with T between date and time,
844
898
  # since that is the format that is multilanguage and not
845
899
  # DATEFORMAT dependent.
846
900
  def default_timestamp_format
847
- DEFAULT_TIMESTAMP_FORMAT
901
+ "'%Y-%m-%dT%H:%M:%S%N%z'"
848
902
  end
849
903
 
850
904
  # Only include the primary table in the main delete clause
851
905
  def delete_from_sql(sql)
852
- sql << FROM
906
+ sql << ' FROM '
853
907
  source_list_append(sql, @opts[:from][0..0])
854
908
  end
855
909
 
@@ -883,7 +937,7 @@ module Sequel
883
937
  end
884
938
  end
885
939
 
886
- # Microsoft SQL Server 2012 has native support for offsets, but only for ordered datasets.
940
+ # Microsoft SQL Server 2012+ has native support for offsets, but only for ordered datasets.
887
941
  def emulate_offset_with_row_number?
888
942
  super && !(is_2012_or_later? && @opts[:order])
889
943
  end
@@ -903,9 +957,9 @@ module Sequel
903
957
  def join_type_sql(join_type)
904
958
  case join_type
905
959
  when :cross_apply
906
- CROSS_APPLY
960
+ 'CROSS APPLY'
907
961
  when :outer_apply
908
- OUTER_APPLY
962
+ 'OUTER APPLY'
909
963
  else
910
964
  super
911
965
  end
@@ -913,30 +967,30 @@ module Sequel
913
967
 
914
968
  # MSSQL uses a literal hexidecimal number for blob strings
915
969
  def literal_blob_append(sql, v)
916
- sql << HEX_START << v.unpack(HSTAR).first
970
+ sql << '0x' << v.unpack("H*").first
917
971
  end
918
972
 
919
- # Use YYYYmmdd format, since that's the only want that is
973
+ # Use YYYYmmdd format, since that's the only format that is
920
974
  # multilanguage and not DATEFORMAT dependent.
921
975
  def literal_date(v)
922
- v.strftime(FORMAT_DATE)
976
+ v.strftime("'%Y%m%d'")
923
977
  end
924
978
 
925
979
  # Use 0 for false on MSSQL
926
980
  def literal_false
927
- BOOL_FALSE
981
+ '0'
928
982
  end
929
983
 
930
984
  # Optionally use unicode string syntax for all strings. Don't double
931
985
  # backslashes.
932
986
  def literal_string_append(sql, v)
933
- sql << (mssql_unicode_strings ? UNICODE_STRING_START : APOS)
934
- sql << v.gsub(APOS_RE, DOUBLE_APOS).gsub(BACKSLASH_CRLF_RE, BACKSLASH_CRLF_REPLACE) << APOS
987
+ sql << (mssql_unicode_strings ? "N'" : "'")
988
+ sql << v.gsub("'", "''").gsub(/\\((?:\r\n)|\n)/, '\\\\\\\\\\1\\1') << "'"
935
989
  end
936
990
 
937
991
  # Use 1 for true on MSSQL
938
992
  def literal_true
939
- BOOL_TRUE
993
+ '1'
940
994
  end
941
995
 
942
996
  # MSSQL 2008+ supports multiple rows in the VALUES clause, older versions
@@ -945,59 +999,74 @@ module Sequel
945
999
  is_2008_or_later? ? :values : :union
946
1000
  end
947
1001
 
1002
+ def non_sql_option?(key)
1003
+ super || key == :disable_insert_output || key == :mssql_unicode_strings
1004
+ end
1005
+
948
1006
  def select_into_sql(sql)
949
1007
  if i = @opts[:into]
950
- sql << INTO
1008
+ sql << " INTO "
951
1009
  identifier_append(sql, i)
952
1010
  end
953
1011
  end
954
1012
 
955
- # MSSQL uses TOP N for limit. For MSSQL 2005+ TOP (N) is used
1013
+ # MSSQL 2000 uses TOP N for limit. For MSSQL 2005+ TOP (N) is used
956
1014
  # to allow the limit to be a bound variable.
957
1015
  def select_limit_sql(sql)
958
1016
  if l = @opts[:limit]
959
1017
  return if is_2012_or_later? && @opts[:order] && @opts[:offset]
1018
+ shared_limit_sql(sql, l)
1019
+ end
1020
+ end
960
1021
 
961
- if is_2005_or_later?
962
- sql << TOP_PAREN
963
- literal_append(sql, l)
964
- sql << PAREN_CLOSE
1022
+ def shared_limit_sql(sql, l)
1023
+ if is_2005_or_later?
1024
+ if l == LIMIT_ALL
1025
+ sql << " TOP (100) PERCENT"
965
1026
  else
966
- sql << TOP
1027
+ sql << " TOP ("
967
1028
  literal_append(sql, l)
1029
+ sql << ')'
968
1030
  end
1031
+ else
1032
+ sql << " TOP "
1033
+ literal_append(sql, l)
1034
+ end
1035
+
1036
+ if @opts[:limit_with_ties]
1037
+ sql << " WITH TIES"
969
1038
  end
970
1039
  end
971
- alias update_limit_sql select_limit_sql
972
1040
 
973
- # Support different types of locking styles
1041
+ def update_limit_sql(sql)
1042
+ if l = @opts[:limit]
1043
+ shared_limit_sql(sql, l)
1044
+ end
1045
+ end
1046
+ alias delete_limit_sql update_limit_sql
1047
+
1048
+ # Handle dirty, skip locked, and for update locking
974
1049
  def select_lock_sql(sql)
975
1050
  lock = @opts[:lock]
976
1051
  skip_locked = @opts[:skip_locked]
1052
+ nowait = @opts[:nowait]
977
1053
  for_update = lock == :update
978
1054
  dirty = lock == :dirty
979
1055
  lock_hint = for_update || dirty
980
1056
 
981
1057
  if lock_hint || skip_locked
982
- sql << TABLE_HINT
1058
+ sql << " WITH ("
983
1059
 
984
1060
  if lock_hint
985
- sql << if for_update
986
- UPDLOCK
987
- else
988
- NOLOCK
989
- end
990
- end
991
-
992
- if lock_hint && skip_locked
993
- sql << COMMA_SEPARATOR
1061
+ sql << (for_update ? 'UPDLOCK' : 'NOLOCK')
994
1062
  end
995
1063
 
996
- if skip_locked
997
- sql << READPAST
1064
+ if skip_locked || nowait
1065
+ sql << ', ' if lock_hint
1066
+ sql << (skip_locked ? "READPAST" : "NOWAIT")
998
1067
  end
999
1068
 
1000
- sql << PAREN_CLOSE
1069
+ sql << ')'
1001
1070
  else
1002
1071
  super
1003
1072
  end
@@ -1009,20 +1078,19 @@ module Sequel
1009
1078
  super
1010
1079
  if is_2012_or_later? && @opts[:order]
1011
1080
  if o = @opts[:offset]
1012
- sql << OFFSET
1081
+ sql << " OFFSET "
1013
1082
  literal_append(sql, o)
1014
- sql << ROWS
1083
+ sql << " ROWS"
1015
1084
 
1016
1085
  if l = @opts[:limit]
1017
- sql << FETCH_NEXT
1086
+ sql << " FETCH NEXT "
1018
1087
  literal_append(sql, l)
1019
- sql << ROWS_ONLY
1088
+ sql << " ROWS ONLY"
1020
1089
  end
1021
1090
  end
1022
1091
  end
1023
1092
  end
1024
1093
 
1025
- # SQL fragment for MSSQL's OUTPUT clause.
1026
1094
  def output_sql(sql, type)
1027
1095
  return unless supports_output_clause?
1028
1096
  if output = @opts[:output]
@@ -1033,21 +1101,21 @@ module Sequel
1033
1101
  end
1034
1102
 
1035
1103
  def output_list_sql(sql, output)
1036
- sql << OUTPUT
1104
+ sql << " OUTPUT "
1037
1105
  column_list_append(sql, output[:select_list])
1038
1106
  if into = output[:into]
1039
- sql << INTO
1107
+ sql << " INTO "
1040
1108
  identifier_append(sql, into)
1041
1109
  if column_list = output[:column_list]
1042
- sql << PAREN_SPACE_OPEN
1110
+ sql << ' ('
1043
1111
  source_list_append(sql, column_list)
1044
- sql << PAREN_CLOSE
1112
+ sql << ')'
1045
1113
  end
1046
1114
  end
1047
1115
  end
1048
1116
 
1049
1117
  def output_returning_sql(sql, type, values)
1050
- sql << OUTPUT
1118
+ sql << " OUTPUT "
1051
1119
  if values.empty?
1052
1120
  literal_append(sql, SQL::ColumnAll.new(type))
1053
1121
  else
@@ -1063,14 +1131,27 @@ module Sequel
1063
1131
  end
1064
1132
  end
1065
1133
 
1066
- # MSSQL supports millisecond timestamp precision.
1134
+ # MSSQL does not natively support NULLS FIRST/LAST.
1135
+ def requires_emulating_nulls_first?
1136
+ true
1137
+ end
1138
+
1139
+ # MSSQL supports 100-nsec precision for time columns, but ruby by
1140
+ # default only supports usec precision.
1141
+ def sqltime_precision
1142
+ 6
1143
+ end
1144
+
1145
+ # MSSQL supports millisecond timestamp precision for datetime columns.
1146
+ # 100-nsec precision is supported for datetime2 columns, but Sequel does
1147
+ # not know what the column type is when formatting values.
1067
1148
  def timestamp_precision
1068
1149
  3
1069
1150
  end
1070
1151
 
1071
1152
  # Only include the primary table in the main update clause
1072
1153
  def update_table_sql(sql)
1073
- sql << SPACE
1154
+ sql << ' '
1074
1155
  source_list_append(sql, @opts[:from][0..0])
1075
1156
  end
1076
1157