sequel 3.48.0 → 4.0.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 (267) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +114 -0
  3. data/Rakefile +10 -7
  4. data/doc/association_basics.rdoc +25 -23
  5. data/doc/code_order.rdoc +7 -0
  6. data/doc/core_extensions.rdoc +0 -10
  7. data/doc/object_model.rdoc +4 -1
  8. data/doc/querying.rdoc +3 -3
  9. data/doc/release_notes/4.0.0.txt +262 -0
  10. data/doc/security.rdoc +0 -28
  11. data/doc/testing.rdoc +8 -14
  12. data/lib/sequel/adapters/ado.rb +7 -11
  13. data/lib/sequel/adapters/ado/access.rb +8 -8
  14. data/lib/sequel/adapters/ado/mssql.rb +4 -4
  15. data/lib/sequel/adapters/amalgalite.rb +6 -6
  16. data/lib/sequel/adapters/cubrid.rb +7 -7
  17. data/lib/sequel/adapters/db2.rb +5 -9
  18. data/lib/sequel/adapters/dbi.rb +2 -6
  19. data/lib/sequel/adapters/do.rb +4 -4
  20. data/lib/sequel/adapters/firebird.rb +4 -4
  21. data/lib/sequel/adapters/ibmdb.rb +8 -8
  22. data/lib/sequel/adapters/informix.rb +2 -10
  23. data/lib/sequel/adapters/jdbc.rb +17 -17
  24. data/lib/sequel/adapters/jdbc/as400.rb +2 -2
  25. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
  26. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  27. data/lib/sequel/adapters/jdbc/derby.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/h2.rb +2 -2
  29. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
  30. data/lib/sequel/adapters/jdbc/informix.rb +1 -1
  31. data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
  32. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  33. data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
  34. data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
  35. data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
  36. data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
  37. data/lib/sequel/adapters/mock.rb +7 -7
  38. data/lib/sequel/adapters/mysql.rb +3 -3
  39. data/lib/sequel/adapters/mysql2.rb +4 -4
  40. data/lib/sequel/adapters/odbc.rb +2 -6
  41. data/lib/sequel/adapters/odbc/mssql.rb +1 -1
  42. data/lib/sequel/adapters/openbase.rb +1 -5
  43. data/lib/sequel/adapters/oracle.rb +13 -17
  44. data/lib/sequel/adapters/postgres.rb +20 -25
  45. data/lib/sequel/adapters/shared/cubrid.rb +3 -3
  46. data/lib/sequel/adapters/shared/db2.rb +2 -2
  47. data/lib/sequel/adapters/shared/firebird.rb +7 -7
  48. data/lib/sequel/adapters/shared/mssql.rb +9 -9
  49. data/lib/sequel/adapters/shared/mysql.rb +29 -13
  50. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
  51. data/lib/sequel/adapters/shared/oracle.rb +22 -13
  52. data/lib/sequel/adapters/shared/postgres.rb +61 -46
  53. data/lib/sequel/adapters/shared/sqlite.rb +9 -9
  54. data/lib/sequel/adapters/sqlite.rb +17 -11
  55. data/lib/sequel/adapters/swift.rb +3 -3
  56. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  57. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  58. data/lib/sequel/adapters/tinytds.rb +8 -8
  59. data/lib/sequel/ast_transformer.rb +3 -1
  60. data/lib/sequel/connection_pool.rb +4 -2
  61. data/lib/sequel/connection_pool/sharded_single.rb +2 -2
  62. data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
  63. data/lib/sequel/connection_pool/threaded.rb +7 -7
  64. data/lib/sequel/core.rb +4 -67
  65. data/lib/sequel/database.rb +1 -0
  66. data/lib/sequel/database/connecting.rb +2 -8
  67. data/lib/sequel/database/dataset.rb +2 -7
  68. data/lib/sequel/database/dataset_defaults.rb +0 -18
  69. data/lib/sequel/database/features.rb +4 -4
  70. data/lib/sequel/database/misc.rb +6 -8
  71. data/lib/sequel/database/query.rb +5 -61
  72. data/lib/sequel/database/schema_generator.rb +22 -20
  73. data/lib/sequel/database/schema_methods.rb +48 -20
  74. data/lib/sequel/database/transactions.rb +7 -17
  75. data/lib/sequel/dataset.rb +2 -0
  76. data/lib/sequel/dataset/actions.rb +23 -91
  77. data/lib/sequel/dataset/features.rb +1 -4
  78. data/lib/sequel/dataset/graph.rb +3 -47
  79. data/lib/sequel/dataset/misc.rb +4 -33
  80. data/lib/sequel/dataset/prepared_statements.rb +3 -1
  81. data/lib/sequel/dataset/query.rb +116 -240
  82. data/lib/sequel/dataset/sql.rb +19 -97
  83. data/lib/sequel/deprecated.rb +0 -16
  84. data/lib/sequel/exceptions.rb +0 -3
  85. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  86. data/lib/sequel/extensions/columns_introspection.rb +1 -12
  87. data/lib/sequel/extensions/constraint_validations.rb +3 -3
  88. data/lib/sequel/extensions/core_extensions.rb +0 -9
  89. data/lib/sequel/extensions/date_arithmetic.rb +1 -2
  90. data/lib/sequel/extensions/graph_each.rb +11 -0
  91. data/lib/sequel/extensions/migration.rb +5 -5
  92. data/lib/sequel/extensions/null_dataset.rb +11 -13
  93. data/lib/sequel/extensions/pagination.rb +3 -6
  94. data/lib/sequel/extensions/pg_array.rb +6 -4
  95. data/lib/sequel/extensions/pg_array_ops.rb +35 -1
  96. data/lib/sequel/extensions/pg_json.rb +12 -2
  97. data/lib/sequel/extensions/pg_json_ops.rb +266 -0
  98. data/lib/sequel/extensions/pg_range.rb +2 -2
  99. data/lib/sequel/extensions/pg_range_ops.rb +0 -8
  100. data/lib/sequel/extensions/pg_row.rb +2 -2
  101. data/lib/sequel/extensions/pretty_table.rb +0 -4
  102. data/lib/sequel/extensions/query.rb +3 -8
  103. data/lib/sequel/extensions/schema_caching.rb +0 -7
  104. data/lib/sequel/extensions/schema_dumper.rb +10 -17
  105. data/lib/sequel/extensions/select_remove.rb +0 -4
  106. data/lib/sequel/extensions/set_overrides.rb +28 -0
  107. data/lib/sequel/extensions/to_dot.rb +6 -10
  108. data/lib/sequel/model.rb +6 -7
  109. data/lib/sequel/model/associations.rb +127 -182
  110. data/lib/sequel/model/base.rb +88 -211
  111. data/lib/sequel/model/errors.rb +0 -13
  112. data/lib/sequel/model/plugins.rb +2 -2
  113. data/lib/sequel/no_core_ext.rb +0 -1
  114. data/lib/sequel/plugins/after_initialize.rb +11 -17
  115. data/lib/sequel/plugins/association_autoreloading.rb +1 -47
  116. data/lib/sequel/plugins/association_dependencies.rb +2 -2
  117. data/lib/sequel/plugins/auto_validations.rb +2 -8
  118. data/lib/sequel/plugins/blacklist_security.rb +32 -2
  119. data/lib/sequel/plugins/caching.rb +1 -1
  120. data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
  121. data/lib/sequel/plugins/composition.rb +10 -8
  122. data/lib/sequel/plugins/constraint_validations.rb +2 -2
  123. data/lib/sequel/plugins/dataset_associations.rb +4 -0
  124. data/lib/sequel/plugins/defaults_setter.rb +8 -6
  125. data/lib/sequel/plugins/dirty.rb +6 -6
  126. data/lib/sequel/plugins/force_encoding.rb +13 -8
  127. data/lib/sequel/plugins/hook_class_methods.rb +1 -7
  128. data/lib/sequel/plugins/json_serializer.rb +13 -74
  129. data/lib/sequel/plugins/lazy_attributes.rb +2 -4
  130. data/lib/sequel/plugins/list.rb +1 -1
  131. data/lib/sequel/plugins/many_through_many.rb +4 -11
  132. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
  133. data/lib/sequel/plugins/nested_attributes.rb +1 -1
  134. data/lib/sequel/plugins/optimistic_locking.rb +3 -5
  135. data/lib/sequel/plugins/pg_array_associations.rb +453 -0
  136. data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
  137. data/lib/sequel/plugins/prepared_statements.rb +1 -1
  138. data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
  139. data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
  140. data/lib/sequel/plugins/rcte_tree.rb +1 -1
  141. data/lib/sequel/plugins/serialization.rb +5 -4
  142. data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
  143. data/lib/sequel/plugins/sharding.rb +7 -1
  144. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  145. data/lib/sequel/plugins/timestamps.rb +1 -1
  146. data/lib/sequel/plugins/touch.rb +2 -2
  147. data/lib/sequel/plugins/tree.rb +1 -1
  148. data/lib/sequel/plugins/typecast_on_load.rb +19 -4
  149. data/lib/sequel/plugins/validation_class_methods.rb +0 -30
  150. data/lib/sequel/plugins/validation_helpers.rb +13 -31
  151. data/lib/sequel/plugins/xml_serializer.rb +18 -57
  152. data/lib/sequel/sql.rb +20 -22
  153. data/lib/sequel/version.rb +2 -2
  154. data/spec/adapters/db2_spec.rb +14 -23
  155. data/spec/adapters/firebird_spec.rb +25 -29
  156. data/spec/adapters/informix_spec.rb +11 -14
  157. data/spec/adapters/mssql_spec.rb +71 -77
  158. data/spec/adapters/mysql_spec.rb +165 -172
  159. data/spec/adapters/oracle_spec.rb +36 -39
  160. data/spec/adapters/postgres_spec.rb +175 -100
  161. data/spec/adapters/spec_helper.rb +13 -11
  162. data/spec/adapters/sqlite_spec.rb +36 -44
  163. data/spec/core/connection_pool_spec.rb +2 -1
  164. data/spec/core/database_spec.rb +55 -55
  165. data/spec/core/dataset_spec.rb +45 -249
  166. data/spec/core/deprecated_spec.rb +0 -8
  167. data/spec/core/expression_filters_spec.rb +23 -5
  168. data/spec/core/object_graph_spec.rb +4 -66
  169. data/spec/core/schema_spec.rb +35 -12
  170. data/spec/core/spec_helper.rb +3 -2
  171. data/spec/core_extensions_spec.rb +17 -19
  172. data/spec/extensions/arbitrary_servers_spec.rb +2 -3
  173. data/spec/extensions/association_dependencies_spec.rb +14 -14
  174. data/spec/extensions/auto_validations_spec.rb +7 -0
  175. data/spec/extensions/blacklist_security_spec.rb +5 -5
  176. data/spec/extensions/blank_spec.rb +2 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +2 -2
  178. data/spec/extensions/columns_introspection_spec.rb +2 -29
  179. data/spec/extensions/composition_spec.rb +10 -17
  180. data/spec/extensions/core_refinements_spec.rb +5 -1
  181. data/spec/extensions/dataset_associations_spec.rb +18 -0
  182. data/spec/extensions/date_arithmetic_spec.rb +2 -2
  183. data/spec/extensions/defaults_setter_spec.rb +9 -9
  184. data/spec/extensions/dirty_spec.rb +0 -5
  185. data/spec/extensions/eval_inspect_spec.rb +2 -0
  186. data/spec/extensions/force_encoding_spec.rb +2 -18
  187. data/spec/extensions/hash_aliases_spec.rb +8 -0
  188. data/spec/extensions/hook_class_methods_spec.rb +39 -58
  189. data/spec/extensions/inflector_spec.rb +2 -0
  190. data/spec/extensions/instance_filters_spec.rb +8 -8
  191. data/spec/extensions/json_serializer_spec.rb +1 -41
  192. data/spec/extensions/list_spec.rb +1 -1
  193. data/spec/extensions/many_through_many_spec.rb +106 -109
  194. data/spec/extensions/migration_spec.rb +2 -0
  195. data/spec/extensions/named_timezones_spec.rb +1 -0
  196. data/spec/extensions/pg_array_associations_spec.rb +603 -0
  197. data/spec/extensions/pg_array_ops_spec.rb +25 -0
  198. data/spec/extensions/pg_array_spec.rb +9 -1
  199. data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
  200. data/spec/extensions/pg_hstore_spec.rb +1 -0
  201. data/spec/extensions/pg_json_ops_spec.rb +131 -0
  202. data/spec/extensions/pg_json_spec.rb +10 -4
  203. data/spec/extensions/pg_range_ops_spec.rb +2 -5
  204. data/spec/extensions/pg_range_spec.rb +6 -2
  205. data/spec/extensions/pg_row_ops_spec.rb +2 -0
  206. data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
  207. data/spec/extensions/rcte_tree_spec.rb +15 -15
  208. data/spec/extensions/schema_dumper_spec.rb +0 -1
  209. data/spec/extensions/schema_spec.rb +9 -9
  210. data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
  211. data/spec/extensions/serialization_spec.rb +18 -29
  212. data/spec/extensions/set_overrides_spec.rb +4 -0
  213. data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
  214. data/spec/extensions/single_table_inheritance_spec.rb +4 -4
  215. data/spec/extensions/spec_helper.rb +8 -9
  216. data/spec/extensions/sql_expr_spec.rb +2 -0
  217. data/spec/extensions/string_date_time_spec.rb +2 -0
  218. data/spec/extensions/string_stripper_spec.rb +2 -0
  219. data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
  220. data/spec/extensions/thread_local_timezones_spec.rb +2 -0
  221. data/spec/extensions/timestamps_spec.rb +1 -1
  222. data/spec/extensions/to_dot_spec.rb +1 -1
  223. data/spec/extensions/touch_spec.rb +24 -24
  224. data/spec/extensions/tree_spec.rb +7 -7
  225. data/spec/extensions/typecast_on_load_spec.rb +8 -1
  226. data/spec/extensions/update_primary_key_spec.rb +10 -10
  227. data/spec/extensions/validation_class_methods_spec.rb +10 -39
  228. data/spec/extensions/validation_helpers_spec.rb +29 -47
  229. data/spec/extensions/xml_serializer_spec.rb +1 -23
  230. data/spec/integration/associations_test.rb +231 -40
  231. data/spec/integration/database_test.rb +1 -1
  232. data/spec/integration/dataset_test.rb +64 -64
  233. data/spec/integration/eager_loader_test.rb +28 -28
  234. data/spec/integration/migrator_test.rb +1 -1
  235. data/spec/integration/model_test.rb +2 -2
  236. data/spec/integration/plugin_test.rb +21 -21
  237. data/spec/integration/prepared_statement_test.rb +7 -7
  238. data/spec/integration/schema_test.rb +115 -110
  239. data/spec/integration/spec_helper.rb +17 -27
  240. data/spec/integration/timezone_test.rb +1 -1
  241. data/spec/integration/transaction_test.rb +10 -10
  242. data/spec/integration/type_test.rb +2 -2
  243. data/spec/model/association_reflection_spec.rb +2 -28
  244. data/spec/model/associations_spec.rb +239 -188
  245. data/spec/model/base_spec.rb +27 -68
  246. data/spec/model/dataset_methods_spec.rb +4 -4
  247. data/spec/model/eager_loading_spec.rb +160 -172
  248. data/spec/model/hooks_spec.rb +62 -79
  249. data/spec/model/model_spec.rb +36 -51
  250. data/spec/model/plugins_spec.rb +5 -19
  251. data/spec/model/record_spec.rb +125 -151
  252. data/spec/model/spec_helper.rb +8 -6
  253. data/spec/model/validations_spec.rb +4 -17
  254. data/spec/spec_config.rb +2 -10
  255. metadata +50 -56
  256. data/lib/sequel/deprecated_core_extensions.rb +0 -135
  257. data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
  258. data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
  259. data/lib/sequel/plugins/identity_map.rb +0 -260
  260. data/lib/sequel_core.rb +0 -2
  261. data/lib/sequel_model.rb +0 -2
  262. data/spec/extensions/association_autoreloading_spec.rb +0 -102
  263. data/spec/extensions/identity_map_spec.rb +0 -337
  264. data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
  265. data/spec/extensions/pg_statement_cache_spec.rb +0 -208
  266. data/spec/rcov.opts +0 -8
  267. data/spec/spec_config.rb.example +0 -10
@@ -46,7 +46,7 @@ module Sequel
46
46
 
47
47
  # Return foreign key information using the system views, including
48
48
  # :name, :on_delete, and :on_update entries in the hashes.
49
- def foreign_key_list(table, opts={})
49
+ def foreign_key_list(table, opts=OPTS)
50
50
  m = output_identifier_meth
51
51
  im = input_identifier_meth
52
52
  schema, table = schema_and_table(table)
@@ -86,7 +86,7 @@ module Sequel
86
86
  end
87
87
 
88
88
  # Use the system tables to get index information
89
- def indexes(table, opts={})
89
+ def indexes(table, opts=OPTS)
90
90
  m = output_identifier_meth
91
91
  im = input_identifier_meth
92
92
  indexes = {}
@@ -136,13 +136,13 @@ module Sequel
136
136
 
137
137
  # Microsoft SQL Server supports using the INFORMATION_SCHEMA to get
138
138
  # information on tables.
139
- def tables(opts={})
139
+ def tables(opts=OPTS)
140
140
  information_schema_tables('BASE TABLE', opts)
141
141
  end
142
142
 
143
143
  # Microsoft SQL Server supports using the INFORMATION_SCHEMA to get
144
144
  # information on views.
145
- def views(opts={})
145
+ def views(opts=OPTS)
146
146
  information_schema_tables('VIEW', opts)
147
147
  end
148
148
 
@@ -220,7 +220,7 @@ module Sequel
220
220
 
221
221
  # Commit the active transaction on the connection, does not commit/release
222
222
  # savepoints.
223
- def commit_transaction(conn, opts={})
223
+ def commit_transaction(conn, opts=OPTS)
224
224
  log_connection_execute(conn, commit_transaction_sql) unless _trans(conn)[:savepoint_level] > 1
225
225
  end
226
226
 
@@ -288,7 +288,7 @@ module Sequel
288
288
  m = output_identifier_meth
289
289
  metadata_dataset.from(:information_schema__tables___t).
290
290
  select(:table_name).
291
- filter(:table_type=>type, :table_schema=>(opts[:schema]||_default_schema||'dbo').to_s).
291
+ filter(:table_type=>type, :table_schema=>(opts[:schema]||'dbo').to_s).
292
292
  map{|x| m.call(x[:table_name])}
293
293
  end
294
294
 
@@ -350,7 +350,7 @@ module Sequel
350
350
  :table_schema => :table_schema, :table_name => :table_name).
351
351
  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).
352
352
  filter(:c__table_name=>tn)
353
- if schema = opts[:schema] || _default_schema
353
+ if schema = opts[:schema]
354
354
  ds.filter!(:c__table_schema=>schema)
355
355
  end
356
356
  ds.map do |row|
@@ -524,7 +524,7 @@ module Sequel
524
524
  end
525
525
 
526
526
  # MSSQL uses the CONTAINS keyword for full text search
527
- def full_text_search(cols, terms, opts = {})
527
+ def full_text_search(cols, terms, opts = OPTS)
528
528
  terms = "\"#{terms.join('" OR "')}\"" if terms.is_a?(Array)
529
529
  filter("CONTAINS (?, ?)", cols, terms)
530
530
  end
@@ -660,7 +660,7 @@ module Sequel
660
660
  # dataset. If OUTPUT is already set, use existing returning values. If OUTPUT
661
661
  # is only set to return a single columns, return an array of just that column.
662
662
  # Otherwise, return an array of hashes.
663
- def _import(columns, values, opts={})
663
+ def _import(columns, values, opts=OPTS)
664
664
  if opts[:return] == :primary_key && !@opts[:output]
665
665
  output(nil, [SQL::QualifiedIdentifier.new(:inserted, first_primary_key)])._import(columns, values, opts)
666
666
  elsif @opts[:output]
@@ -61,7 +61,7 @@ module Sequel
61
61
  # Use the Information Schema's KEY_COLUMN_USAGE table to get
62
62
  # basic information on foreign key columns, but include the
63
63
  # constraint name.
64
- def foreign_key_list(table, opts={})
64
+ def foreign_key_list(table, opts=OPTS)
65
65
  m = output_identifier_meth
66
66
  im = input_identifier_meth
67
67
  ds = metadata_dataset.
@@ -93,7 +93,7 @@ module Sequel
93
93
  #
94
94
  # By default partial indexes are not included, you can use the
95
95
  # option :partial to override this.
96
- def indexes(table, opts={})
96
+ def indexes(table, opts=OPTS)
97
97
  indexes = {}
98
98
  remove_indexes = []
99
99
  m = output_identifier_meth
@@ -153,7 +153,7 @@ module Sequel
153
153
  #
154
154
  # Options:
155
155
  # * :server - Set the server to use
156
- def tables(opts={})
156
+ def tables(opts=OPTS)
157
157
  full_tables('BASE TABLE', opts)
158
158
  end
159
159
 
@@ -170,7 +170,7 @@ module Sequel
170
170
  #
171
171
  # Options:
172
172
  # * :server - Set the server to use
173
- def views(opts={})
173
+ def views(opts=OPTS)
174
174
  full_tables('VIEW', opts)
175
175
  end
176
176
 
@@ -290,7 +290,7 @@ module Sequel
290
290
 
291
291
  # Use XA START to start a new prepared transaction if the :prepare
292
292
  # option is given.
293
- def begin_transaction(conn, opts={})
293
+ def begin_transaction(conn, opts=OPTS)
294
294
  if (s = opts[:prepare]) && (th = _trans(conn))[:savepoint_level] == 0
295
295
  log_connection_execute(conn, "XA START #{literal(s)}")
296
296
  th[:savepoint_level] += 1
@@ -313,7 +313,7 @@ module Sequel
313
313
 
314
314
  # Prepare the XA transaction for a two-phase commit if the
315
315
  # :prepare option is given.
316
- def commit_transaction(conn, opts={})
316
+ def commit_transaction(conn, opts=OPTS)
317
317
  if (s = opts[:prepare]) && _trans(conn)[:savepoint_level] <= 1
318
318
  log_connection_execute(conn, "XA END #{literal(s)}")
319
319
  log_connection_execute(conn, "XA PREPARE #{literal(s)}")
@@ -323,7 +323,7 @@ module Sequel
323
323
  end
324
324
 
325
325
  # Use MySQL specific syntax for engine type and character encoding
326
- def create_table_sql(name, generator, options = {})
326
+ def create_table_sql(name, generator, options = OPTS)
327
327
  engine = options.fetch(:engine, Sequel::MySQL.default_engine)
328
328
  charset = options.fetch(:charset, Sequel::MySQL.default_charset)
329
329
  collate = options.fetch(:collate, Sequel::MySQL.default_collate)
@@ -418,7 +418,7 @@ module Sequel
418
418
  end
419
419
 
420
420
  # Rollback the currently open XA transaction
421
- def rollback_transaction(conn, opts={})
421
+ def rollback_transaction(conn, opts=OPTS)
422
422
  if (s = opts[:prepare]) && _trans(conn)[:savepoint_level] <= 1
423
423
  log_connection_execute(conn, "XA END #{literal(s)}")
424
424
  log_connection_execute(conn, "XA PREPARE #{literal(s)}")
@@ -563,6 +563,8 @@ module Sequel
563
563
  EXPLAIN_EXTENDED = 'EXPLAIN EXTENDED '.freeze
564
564
  BACKSLASH_RE = /\\/.freeze
565
565
  QUAD_BACKSLASH = "\\\\\\\\".freeze
566
+ BLOB_START = "0x".freeze
567
+ HSTAR = "H*".freeze
566
568
 
567
569
  # MySQL specific syntax for LIKE/REGEXP searches, as well as
568
570
  # string concatenation.
@@ -620,7 +622,7 @@ module Sequel
620
622
 
621
623
  # Return the results of an EXPLAIN query as a string. Options:
622
624
  # :extended :: Use EXPLAIN EXPTENDED instead of EXPLAIN if true.
623
- def explain(opts={})
625
+ def explain(opts=OPTS)
624
626
  # Load the PrettyTable class, needed for explain output
625
627
  Sequel.extension(:_pretty_table) unless defined?(Sequel::PrettyTable)
626
628
 
@@ -635,12 +637,12 @@ module Sequel
635
637
  end
636
638
 
637
639
  # Adds full text filter
638
- def full_text_search(cols, terms, opts = {})
640
+ def full_text_search(cols, terms, opts = OPTS)
639
641
  filter(full_text_sql(cols, terms, opts))
640
642
  end
641
643
 
642
644
  # MySQL specific full text search syntax.
643
- def full_text_sql(cols, terms, opts = {})
645
+ def full_text_sql(cols, terms, opts = OPTS)
644
646
  terms = terms.join(' ') if terms.is_a?(Array)
645
647
  SQL::PlaceholderLiteralString.new((opts[:boolean] ? MATCH_AGAINST_BOOLEAN : MATCH_AGAINST), [Array(cols), terms])
646
648
  end
@@ -652,10 +654,10 @@ module Sequel
652
654
 
653
655
  # Transforms an CROSS JOIN to an INNER JOIN if the expr is not nil.
654
656
  # Raises an error on use of :full_outer type, since MySQL doesn't support it.
655
- def join_table(type, table, expr=nil, table_alias={}, &block)
657
+ def join_table(type, table, expr=nil, opts=OPTS, &block)
656
658
  type = :inner if (type == :cross) && !expr.nil?
657
659
  raise(Sequel::Error, "MySQL doesn't support FULL OUTER JOIN") if type == :full_outer
658
- super(type, table, expr, table_alias, &block)
660
+ super(type, table, expr, opts, &block)
659
661
  end
660
662
 
661
663
  # Transforms :natural_inner to NATURAL LEFT JOIN and straight to
@@ -893,11 +895,25 @@ module Sequel
893
895
  alias delete_limit_sql limit_sql
894
896
  alias update_limit_sql limit_sql
895
897
 
898
+ # MySQL uses a preceding X for hex escaping strings
899
+ def literal_blob_append(sql, v)
900
+ sql << BLOB_START << v.unpack(HSTAR).first
901
+ end
902
+
896
903
  # Use 0 for false on MySQL
897
904
  def literal_false
898
905
  BOOL_FALSE
899
906
  end
900
907
 
908
+ # Raise error for infinitate and NaN values
909
+ def literal_float(v)
910
+ if v.infinite? || v.nan?
911
+ raise InvalidValue, "Infinite floats and NaN values are not valid on MySQL"
912
+ else
913
+ super
914
+ end
915
+ end
916
+
901
917
  # SQL fragment for String. Doubles \ and ' by default.
902
918
  def literal_string_append(sql, v)
903
919
  sql << APOS << v.gsub(BACKSLASH_RE, QUAD_BACKSLASH).gsub(APOS_RE, DOUBLE_APOS) << APOS
@@ -18,14 +18,14 @@ module Sequel
18
18
  MYSQL_DATABASE_DISCONNECT_ERRORS = /\A#{Regexp.union(disconnect_errors)}/o
19
19
 
20
20
  # Support stored procedures on MySQL
21
- def call_sproc(name, opts={}, &block)
21
+ def call_sproc(name, opts=OPTS, &block)
22
22
  args = opts[:args] || []
23
23
  execute("CALL #{name}#{args.empty? ? '()' : literal(args)}", opts.merge(:sproc=>false), &block)
24
24
  end
25
25
 
26
26
  # Executes the given SQL using an available connection, yielding the
27
27
  # connection if the block is given.
28
- def execute(sql, opts={}, &block)
28
+ def execute(sql, opts=OPTS, &block)
29
29
  if opts[:sproc]
30
30
  call_sproc(sql, opts, &block)
31
31
  elsif sql.is_a?(Symbol)
@@ -114,17 +114,17 @@ module Sequel
114
114
 
115
115
  # Execute the prepared statement with the bind arguments instead of
116
116
  # the given SQL.
117
- def execute(sql, opts={}, &block)
117
+ def execute(sql, opts=OPTS, &block)
118
118
  super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
119
119
  end
120
120
 
121
121
  # Same as execute, explicit due to intricacies of alias and super.
122
- def execute_dui(sql, opts={}, &block)
122
+ def execute_dui(sql, opts=OPTS, &block)
123
123
  super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
124
124
  end
125
125
 
126
126
  # Same as execute, explicit due to intricacies of alias and super.
127
- def execute_insert(sql, opts={}, &block)
127
+ def execute_insert(sql, opts=OPTS, &block)
128
128
  super(prepared_statement_name, {:arguments=>bind_arguments}.merge(opts), &block)
129
129
  end
130
130
  end
@@ -136,12 +136,12 @@ module Sequel
136
136
  private
137
137
 
138
138
  # Execute the database stored procedure with the stored arguments.
139
- def execute(sql, opts={}, &block)
139
+ def execute(sql, opts=OPTS, &block)
140
140
  super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
141
141
  end
142
142
 
143
143
  # Same as execute, explicit due to intricacies of alias and super.
144
- def execute_dui(sql, opts={}, &block)
144
+ def execute_dui(sql, opts=OPTS, &block)
145
145
  super(@sproc_name, {:args=>@sproc_args, :sproc=>true}.merge(opts), &block)
146
146
  end
147
147
  end
@@ -10,7 +10,7 @@ module Sequel
10
10
 
11
11
  attr_accessor :autosequence
12
12
 
13
- def create_sequence(name, opts={})
13
+ def create_sequence(name, opts=OPTS)
14
14
  self << create_sequence_sql(name, opts)
15
15
  end
16
16
 
@@ -36,12 +36,12 @@ module Sequel
36
36
  false
37
37
  end
38
38
 
39
- def tables(opts={})
39
+ def tables(opts=OPTS)
40
40
  m = output_identifier_meth
41
41
  metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'TABLE').map{|r| m.call(r[:tname])}
42
42
  end
43
43
 
44
- def views(opts={})
44
+ def views(opts=OPTS)
45
45
  m = output_identifier_meth
46
46
  metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'VIEW').map{|r| m.call(r[:tname])}
47
47
  end
@@ -96,7 +96,7 @@ module Sequel
96
96
  AUTOINCREMENT
97
97
  end
98
98
 
99
- def create_sequence_sql(name, opts={})
99
+ def create_sequence_sql(name, opts=OPTS)
100
100
  "CREATE SEQUENCE #{quote_identifier(name)} start with #{opts [:start_with]||1} increment by #{opts[:increment_by]||1} nomaxvalue"
101
101
  end
102
102
 
@@ -106,7 +106,7 @@ module Sequel
106
106
  create_statements.each{|sql| execute_ddl(sql)}
107
107
  end
108
108
 
109
- def create_table_sql_list(name, generator, options={})
109
+ def create_table_sql_list(name, generator, options=OPTS)
110
110
  statements = [create_table_sql(name, generator, options)]
111
111
  drop_seq_statement = nil
112
112
  generator.columns.each do |c|
@@ -132,7 +132,7 @@ module Sequel
132
132
  [drop_seq_statement, statements]
133
133
  end
134
134
 
135
- def create_trigger_sql(table, name, definition, opts={})
135
+ def create_trigger_sql(table, name, definition, opts=OPTS)
136
136
  events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
137
137
  sql = <<-end_sql
138
138
  CREATE#{' OR REPLACE' if opts[:replace]} TRIGGER #{quote_identifier(name)}
@@ -247,17 +247,27 @@ module Sequel
247
247
  when :&
248
248
  sql << complex_expression_arg_pairs(args){|a, b| "CAST(BITAND(#{literal(a)}, #{literal(b)}) AS INTEGER)"}
249
249
  when :|
250
- sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} - #{complex_expression_sql(:&, [a, b])} + #{literal(b)})"}
250
+ sql << complex_expression_arg_pairs(args) do |a, b|
251
+ s1 = ''
252
+ complex_expression_sql_append(s1, :&, [a, b])
253
+ "(#{literal(a)} - #{s1} + #{literal(b)})"
254
+ end
251
255
  when :^
252
- sql << complex_expression_arg_pairs(args){|*x| "(#{complex_expression_sql(:|, x)} - #{complex_expression_sql(:&, x)})"}
256
+ sql << complex_expression_arg_pairs(args) do |*x|
257
+ s1 = ''
258
+ s2 = ''
259
+ complex_expression_sql_append(s1, :|, x)
260
+ complex_expression_sql_append(s2, :&, x)
261
+ "(#{s1} - #{s2})"
262
+ end
253
263
  when :'B~'
254
264
  sql << BITCOMP_OPEN
255
265
  literal_append(sql, args.at(0))
256
266
  sql << BITCOMP_CLOSE
257
267
  when :<<
258
- sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal b}))"}
268
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal(b)}))"}
259
269
  when :>>
260
- sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal b}))"}
270
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal(b)}))"}
261
271
  when :%
262
272
  sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
263
273
  else
@@ -291,8 +301,7 @@ module Sequel
291
301
  end
292
302
 
293
303
  # Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
294
- def except(dataset, opts={})
295
- opts = {:all=>opts} unless opts.is_a?(Hash)
304
+ def except(dataset, opts=OPTS)
296
305
  raise(Sequel::Error, "EXCEPT ALL not supported") if opts[:all]
297
306
  compound_clone(:minus, dataset, opts)
298
307
  end
@@ -391,7 +400,7 @@ module Sequel
391
400
 
392
401
  # If this dataset is associated with a sequence, return the most recently
393
402
  # inserted sequence value.
394
- def execute_insert(sql, opts={})
403
+ def execute_insert(sql, opts=OPTS)
395
404
  f = @opts[:from]
396
405
  super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))
397
406
  end
@@ -63,7 +63,7 @@ module Sequel
63
63
  # :using :: Override the index_method for the exclusion constraint (defaults to gist).
64
64
  # :where :: Create a partial exclusion constraint, which only affects
65
65
  # a subset of table rows, value should be a filter expression.
66
- def exclude(elements, opts={})
66
+ def exclude(elements, opts=OPTS)
67
67
  constraints << {:type => :exclude, :elements => elements}.merge(opts)
68
68
  end
69
69
  end
@@ -71,7 +71,7 @@ module Sequel
71
71
  class AlterTableGenerator < Sequel::Schema::AlterTableGenerator
72
72
  # Adds an exclusion constraint to an existing table, see
73
73
  # CreateTableGenerator#exclude.
74
- def add_exclusion_constraint(elements, opts={})
74
+ def add_exclusion_constraint(elements, opts=OPTS)
75
75
  @operations << {:op => :add_constraint, :type => :exclude, :elements => elements}.merge(opts)
76
76
  end
77
77
 
@@ -89,10 +89,8 @@ module Sequel
89
89
  module DatabaseMethods
90
90
  extend Sequel::Database::ResetIdentifierMangling
91
91
 
92
- EXCLUDE_SCHEMAS = /pg_*|information_schema/i
93
92
  PREPARED_ARG_PLACEHOLDER = LiteralString.new('$').freeze
94
93
  RE_CURRVAL_ERROR = /currval of sequence "(.*)" is not yet defined in this session|relation "(.*)" does not exist/.freeze
95
- SYSTEM_TABLE_REGEXP = /^pg|sql/.freeze
96
94
  FOREIGN_KEY_LIST_ON_DELETE_MAP = {'a'.freeze=>:no_action, 'r'.freeze=>:restrict, 'c'.freeze=>:cascade, 'n'.freeze=>:set_null, 'd'.freeze=>:set_default}.freeze
97
95
  POSTGRES_DEFAULT_RE = /\A(?:B?('.*')::[^']+|\((-?\d+(?:\.\d+)?)\))\z/
98
96
  UNLOGGED = 'UNLOGGED '.freeze
@@ -179,7 +177,7 @@ module Sequel
179
177
  # * :set : Configuration variables to set while the function is being run, can be a hash or an array of two pairs. search_path is
180
178
  # often used here if :security_definer is used.
181
179
  # * :strict : Makes the function return NULL when any argument is NULL.
182
- def create_function(name, definition, opts={})
180
+ def create_function(name, definition, opts=OPTS)
183
181
  self << create_function_sql(name, definition, opts)
184
182
  end
185
183
 
@@ -187,17 +185,20 @@ module Sequel
187
185
  # * name : Name of the procedural language (e.g. plpgsql)
188
186
  # * opts : options hash:
189
187
  # * :handler : The name of a previously registered function used as a call handler for this language.
190
- # * :replace: Replace the installed language if it already exists (on PostgreSQL 9.0+).
188
+ # * :replace : Replace the installed language if it already exists (on PostgreSQL 9.0+).
191
189
  # * :trusted : Marks the language being created as trusted, allowing unprivileged users to create functions using this language.
192
190
  # * :validator : The name of previously registered function used as a validator of functions defined in this language.
193
- def create_language(name, opts={})
191
+ def create_language(name, opts=OPTS)
194
192
  self << create_language_sql(name, opts)
195
193
  end
196
194
 
197
195
  # Create a schema in the database. Arguments:
198
196
  # * name : Name of the schema (e.g. admin)
199
- def create_schema(name)
200
- self << create_schema_sql(name)
197
+ # * opts : options hash:
198
+ # * :if_not_exists : Don't raise an error if the schema already exists (PostgreSQL 9.3+)
199
+ # * :owner : The owner to set for the schema (defaults to current user if not specified)
200
+ def create_schema(name, opts=OPTS)
201
+ self << create_schema_sql(name, opts)
201
202
  end
202
203
 
203
204
  # Create a trigger in the database. Arguments:
@@ -210,7 +211,7 @@ module Sequel
210
211
  # * :each_row : Calls the trigger for each row instead of for each statement.
211
212
  # * :events : Can be :insert, :update, :delete, or an array of any of those. Calls the trigger whenever that type of statement is used. By default,
212
213
  # the trigger is called for insert, update, or delete.
213
- def create_trigger(table, name, function, opts={})
214
+ def create_trigger(table, name, function, opts=OPTS)
214
215
  self << create_trigger_sql(table, name, function, opts)
215
216
  end
216
217
 
@@ -224,7 +225,7 @@ module Sequel
224
225
  #
225
226
  # :language :: The procedural language the code is written in. The PostgreSQL
226
227
  # default is plpgsql. Can be specified as a string or a symbol.
227
- def do(code, opts={})
228
+ def do(code, opts=OPTS)
228
229
  language = opts[:language]
229
230
  run "DO #{"LANGUAGE #{literal(language.to_s)} " if language}#{literal(code)}"
230
231
  end
@@ -235,7 +236,7 @@ module Sequel
235
236
  # * :args : The arguments for the function. See create_function_sql.
236
237
  # * :cascade : Drop other objects depending on this function.
237
238
  # * :if_exists : Don't raise an error if the function doesn't exist.
238
- def drop_function(name, opts={})
239
+ def drop_function(name, opts=OPTS)
239
240
  self << drop_function_sql(name, opts)
240
241
  end
241
242
 
@@ -244,7 +245,7 @@ module Sequel
244
245
  # * opts : options hash:
245
246
  # * :cascade : Drop other objects depending on this function.
246
247
  # * :if_exists : Don't raise an error if the function doesn't exist.
247
- def drop_language(name, opts={})
248
+ def drop_language(name, opts=OPTS)
248
249
  self << drop_language_sql(name, opts)
249
250
  end
250
251
 
@@ -253,7 +254,7 @@ module Sequel
253
254
  # * opts : options hash:
254
255
  # * :cascade : Drop all objects in this schema.
255
256
  # * :if_exists : Don't raise an error if the schema doesn't exist.
256
- def drop_schema(name, opts={})
257
+ def drop_schema(name, opts=OPTS)
257
258
  self << drop_schema_sql(name, opts)
258
259
  end
259
260
 
@@ -263,13 +264,13 @@ module Sequel
263
264
  # * opts : options hash:
264
265
  # * :cascade : Drop other objects depending on this function.
265
266
  # * :if_exists : Don't raise an error if the function doesn't exist.
266
- def drop_trigger(table, name, opts={})
267
+ def drop_trigger(table, name, opts=OPTS)
267
268
  self << drop_trigger_sql(table, name, opts)
268
269
  end
269
270
 
270
271
  # Return full foreign key information using the pg system tables, including
271
272
  # :name, :on_delete, :on_update, and :deferrable entries in the hashes.
272
- def foreign_key_list(table, opts={})
273
+ def foreign_key_list(table, opts=OPTS)
273
274
  m = output_identifier_meth
274
275
  schema, _ = opts.fetch(:schema, schema_and_table(table))
275
276
  range = 0...32
@@ -323,7 +324,7 @@ module Sequel
323
324
  end
324
325
 
325
326
  # Use the pg_* system tables to determine indexes on a table
326
- def indexes(table, opts={})
327
+ def indexes(table, opts=OPTS)
327
328
  m = output_identifier_meth
328
329
  range = 0...32
329
330
  attnums = server_version >= 80100 ? SQL::Function.new(:ANY, :ind__indkey) : range.map{|x| SQL::Subscript.new(:ind__indkey, [x])}
@@ -358,7 +359,7 @@ module Sequel
358
359
  # in PostgreSQL 9.0+.
359
360
  # :server :: The server to which to send the NOTIFY statement, if the sharding support
360
361
  # is being used.
361
- def notify(channel, opts={})
362
+ def notify(channel, opts=OPTS)
362
363
  sql = "NOTIFY "
363
364
  dataset.send(:identifier_append, sql, channel)
364
365
  if payload = opts[:payload]
@@ -369,7 +370,7 @@ module Sequel
369
370
  end
370
371
 
371
372
  # Return primary key for the given table.
372
- def primary_key(table, opts={})
373
+ def primary_key(table, opts=OPTS)
373
374
  quoted_table = quote_schema_table(table)
374
375
  Sequel.synchronize{return @primary_keys[quoted_table] if @primary_keys.has_key?(quoted_table)}
375
376
  sql = "#{SELECT_PK_SQL} AND pg_class.oid = #{literal(regclass_oid(table, opts))}"
@@ -378,7 +379,7 @@ module Sequel
378
379
  end
379
380
 
380
381
  # Return the sequence providing the default for the primary key for the given table.
381
- def primary_key_sequence(table, opts={})
382
+ def primary_key_sequence(table, opts=OPTS)
382
383
  quoted_table = quote_schema_table(table)
383
384
  Sequel.synchronize{return @primary_key_sequences[quoted_table] if @primary_key_sequences.has_key?(quoted_table)}
384
385
  sql = "#{SELECT_SERIAL_SEQUENCE_SQL} AND t.oid = #{literal(regclass_oid(table, opts))}"
@@ -393,6 +394,14 @@ module Sequel
393
394
  end
394
395
  end
395
396
  end
397
+
398
+ # Refresh the materialized view with the given name.
399
+ #
400
+ # DB.refresh_view(:items_view)
401
+ # # REFRESH MATERIALIZED VIEW items_view
402
+ def refresh_view(name, opts=OPTS)
403
+ run "REFRESH MATERIALIZED VIEW #{quote_schema_table(name)}"
404
+ end
396
405
 
397
406
  # Reset the database's conversion procs, requires a server query if there
398
407
  # any named types.
@@ -492,7 +501,7 @@ module Sequel
492
501
  # using the schema the table is located in as the qualifier.
493
502
  # :schema :: The schema to search
494
503
  # :server :: The server to use
495
- def tables(opts={}, &block)
504
+ def tables(opts=OPTS, &block)
496
505
  pg_class_relname('r', opts, &block)
497
506
  end
498
507
 
@@ -510,7 +519,7 @@ module Sequel
510
519
  # using the schema the view is located in as the qualifier.
511
520
  # :schema :: The schema to search
512
521
  # :server :: The server to use
513
- def views(opts={})
522
+ def views(opts=OPTS)
514
523
  pg_class_relname('v', opts)
515
524
  end
516
525
 
@@ -578,7 +587,7 @@ module Sequel
578
587
 
579
588
  # If the :prepare option is given and we aren't in a savepoint,
580
589
  # prepare the transaction for a two-phase commit.
581
- def commit_transaction(conn, opts={})
590
+ def commit_transaction(conn, opts=OPTS)
582
591
  if (s = opts[:prepare]) && _trans(conn)[:savepoint_level] <= 1
583
592
  log_connection_execute(conn, "PREPARE TRANSACTION #{literal(s)}")
584
593
  else
@@ -602,7 +611,7 @@ module Sequel
602
611
  if (cmm = @opts.fetch(:client_min_messages, Postgres.client_min_messages)) && !cmm.to_s.empty?
603
612
  cmm = cmm.to_s.upcase.strip
604
613
  unless VALID_CLIENT_MIN_MESSAGES.include?(cmm)
605
- Sequel::Deprecation.deprecate("Using an unsupported client_min_messages setting will raise an Error in Sequel 4.")
614
+ raise Error, "Unsupported client_min_messages setting: #{cmm}"
606
615
  end
607
616
  sqls << "SET client_min_messages = '#{cmm.to_s.upcase}'"
608
617
  end
@@ -718,7 +727,7 @@ module Sequel
718
727
  end
719
728
 
720
729
  # SQL statement to create database function.
721
- def create_function_sql(name, definition, opts={})
730
+ def create_function_sql(name, definition, opts=OPTS)
722
731
  args = opts[:args]
723
732
  if !opts[:args].is_a?(Array) || !opts[:args].any?{|a| Array(a).length == 3 and %w'OUT INOUT'.include?(a[2].to_s)}
724
733
  returns = opts[:returns] || 'void'
@@ -739,13 +748,13 @@ module Sequel
739
748
  end
740
749
 
741
750
  # SQL for creating a procedural language.
742
- def create_language_sql(name, opts={})
751
+ def create_language_sql(name, opts=OPTS)
743
752
  "CREATE#{' OR REPLACE' if opts[:replace] && server_version >= 90000}#{' TRUSTED' if opts[:trusted]} LANGUAGE #{name}#{" HANDLER #{opts[:handler]}" if opts[:handler]}#{" VALIDATOR #{opts[:validator]}" if opts[:validator]}"
744
753
  end
745
754
 
746
755
  # SQL for creating a schema.
747
- def create_schema_sql(name)
748
- "CREATE SCHEMA #{quote_identifier(name)}"
756
+ def create_schema_sql(name, opts=OPTS)
757
+ "CREATE SCHEMA #{'IF NOT EXISTS ' if opts[:if_not_exists]}#{quote_identifier(name)}#{" AUTHORIZATION #{literal(opts[:owner])}" if opts[:owner]}"
749
758
  end
750
759
 
751
760
  # DDL statement for creating a table with the given name, columns, and options
@@ -765,7 +774,7 @@ module Sequel
765
774
  end
766
775
 
767
776
  # SQL for creating a database trigger.
768
- def create_trigger_sql(table, name, function, opts={})
777
+ def create_trigger_sql(table, name, function, opts=OPTS)
769
778
  events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
770
779
  whence = opts[:after] ? 'AFTER' : 'BEFORE'
771
780
  "CREATE TRIGGER #{name} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} ON #{quote_schema_table(table)}#{' FOR EACH ROW' if opts[:each_row]} EXECUTE PROCEDURE #{function}(#{Array(opts[:args]).map{|a| literal(a)}.join(', ')})"
@@ -773,7 +782,7 @@ module Sequel
773
782
 
774
783
  # DDL fragment for initial part of CREATE VIEW statement
775
784
  def create_view_prefix_sql(name, options)
776
- "CREATE #{'OR REPLACE 'if options[:replace]}#{'TEMPORARY 'if options[:temp]}VIEW #{quote_schema_table(name)}"
785
+ create_view_sql_append_columns("CREATE #{'OR REPLACE 'if options[:replace]}#{'TEMPORARY 'if options[:temp]}#{'RECURSIVE ' if options[:recursive]}#{'MATERIALIZED ' if options[:materialized]}VIEW #{quote_schema_table(name)}", options[:columns] || options[:recursive])
777
786
  end
778
787
 
779
788
  # The errors that the main adapters can raise, depends on the adapter being used
@@ -782,7 +791,7 @@ module Sequel
782
791
  end
783
792
 
784
793
  # SQL for dropping a function from the database.
785
- def drop_function_sql(name, opts={})
794
+ def drop_function_sql(name, opts=OPTS)
786
795
  "DROP FUNCTION#{' IF EXISTS' if opts[:if_exists]} #{name}#{sql_function_args(opts[:args])}#{' CASCADE' if opts[:cascade]}"
787
796
  end
788
797
 
@@ -792,28 +801,34 @@ module Sequel
792
801
  end
793
802
 
794
803
  # SQL for dropping a procedural language from the database.
795
- def drop_language_sql(name, opts={})
804
+ def drop_language_sql(name, opts=OPTS)
796
805
  "DROP LANGUAGE#{' IF EXISTS' if opts[:if_exists]} #{name}#{' CASCADE' if opts[:cascade]}"
797
806
  end
798
807
 
799
808
  # SQL for dropping a schema from the database.
800
- def drop_schema_sql(name, opts={})
809
+ def drop_schema_sql(name, opts=OPTS)
801
810
  "DROP SCHEMA#{' IF EXISTS' if opts[:if_exists]} #{quote_identifier(name)}#{' CASCADE' if opts[:cascade]}"
802
811
  end
803
812
 
804
813
  # SQL for dropping a trigger from the database.
805
- def drop_trigger_sql(table, name, opts={})
814
+ def drop_trigger_sql(table, name, opts=OPTS)
806
815
  "DROP TRIGGER#{' IF EXISTS' if opts[:if_exists]} #{name} ON #{quote_schema_table(table)}#{' CASCADE' if opts[:cascade]}"
807
816
  end
808
817
 
818
+ # SQL for dropping a view from the database.
819
+ def drop_view_sql(name, opts=OPTS)
820
+ "DROP #{'MATERIALIZED ' if opts[:materialized]}VIEW#{' IF EXISTS' if opts[:if_exists]} #{quote_schema_table(name)}#{' CASCADE' if opts[:cascade]}"
821
+ end
822
+
809
823
  # If opts includes a :schema option, or a default schema is used, restrict the dataset to
810
824
  # that schema. Otherwise, just exclude the default PostgreSQL schemas except for public.
811
825
  def filter_schema(ds, opts)
812
- if schema = opts[:schema] || _default_schema
813
- ds.filter(:pg_namespace__nspname=>schema.to_s)
826
+ expr = if schema = opts[:schema]
827
+ schema.to_s
814
828
  else
815
- ds.exclude(:pg_namespace__nspname=>EXCLUDE_SCHEMAS)
829
+ Sequel.function(:any, Sequel.function(:current_schemas, false))
816
830
  end
831
+ ds.where(:pg_namespace__nspname=>expr)
817
832
  end
818
833
 
819
834
  # Return a hash with oid keys and callable values, used for converting types.
@@ -850,7 +865,7 @@ module Sequel
850
865
  case index_type
851
866
  when :full_text
852
867
  expr = "(to_tsvector(#{literal(index[:language] || 'simple')}::regconfig, #{literal(dataset.send(:full_text_string_join, cols))}))"
853
- index_type = :gin
868
+ index_type = index[:index_type] || :gin
854
869
  when :spatial
855
870
  index_type = :gist
856
871
  end
@@ -867,7 +882,7 @@ module Sequel
867
882
 
868
883
  # Backbone of the tables and views support.
869
884
  def pg_class_relname(type, opts)
870
- ds = metadata_dataset.from(:pg_class).filter(:relkind=>type).select(:relname).exclude(SQL::StringExpression.like(:relname, SYSTEM_TABLE_REGEXP)).server(opts[:server]).join(:pg_namespace, :oid=>:relnamespace)
885
+ ds = metadata_dataset.from(:pg_class).filter(:relkind=>type).select(:relname).server(opts[:server]).join(:pg_namespace, :oid=>:relnamespace)
871
886
  ds = filter_schema(ds, opts)
872
887
  m = output_identifier_meth
873
888
  if block_given?
@@ -887,7 +902,7 @@ module Sequel
887
902
 
888
903
  # Return an expression the oid for the table expr. Used by the metadata parsing
889
904
  # code to disambiguate unqualified tables.
890
- def regclass_oid(expr, opts={})
905
+ def regclass_oid(expr, opts=OPTS)
891
906
  if expr.is_a?(String) && !expr.is_a?(LiteralString)
892
907
  expr = Sequel.identifier(expr)
893
908
  end
@@ -1133,7 +1148,7 @@ module Sequel
1133
1148
  end
1134
1149
 
1135
1150
  # Return the results of an EXPLAIN query as a string
1136
- def explain(opts={})
1151
+ def explain(opts=OPTS)
1137
1152
  with_sql((opts[:analyze] ? EXPLAIN_ANALYZE : EXPLAIN) + select_sql).map(QUERY_PLAN).join(CRLF)
1138
1153
  end
1139
1154
 
@@ -1144,7 +1159,7 @@ module Sequel
1144
1159
 
1145
1160
  # PostgreSQL specific full text search syntax, using tsearch2 (included
1146
1161
  # in 8.3 by default, and available for earlier versions as an add-on).
1147
- def full_text_search(cols, terms, opts = {})
1162
+ def full_text_search(cols, terms, opts = OPTS)
1148
1163
  lang = opts[:language] || 'simple'
1149
1164
  terms = terms.join(' | ') if terms.is_a?(Array)
1150
1165
  filter("to_tsvector(?::regconfig, ?) @@ to_tsquery(?::regconfig, ?)", lang, full_text_string_join(cols), lang, terms)
@@ -1178,7 +1193,7 @@ module Sequel
1178
1193
  # a new transaction, locks the table, and yields. If a block is not given
1179
1194
  # just locks the tables. Note that PostgreSQL will probably raise an error
1180
1195
  # if you lock the table outside of an existing transaction. Returns nil.
1181
- def lock(mode, opts={})
1196
+ def lock(mode, opts=OPTS)
1182
1197
  if block_given? # perform locking inside a transaction and yield to block
1183
1198
  @db.transaction(opts){lock(mode, opts); yield}
1184
1199
  else
@@ -1186,7 +1201,7 @@ module Sequel
1186
1201
  source_list_append(sql, @opts[:from])
1187
1202
  mode = mode.to_s.upcase.strip
1188
1203
  unless LOCK_MODES.include?(mode)
1189
- Sequel::Deprecation.deprecate("Calling Dataset#lock with an unsupported lock mode will raise an Error in Sequel 4.")
1204
+ raise Error, "Unsupported lock mode: #{mode}"
1190
1205
  end
1191
1206
  sql << " IN #{mode} MODE"
1192
1207
  @db.execute(sql, opts)
@@ -1252,7 +1267,7 @@ module Sequel
1252
1267
  # # => nil
1253
1268
  # DB[:table].truncate(:cascade => true, :only=>true, :restart=>true) # TRUNCATE TABLE ONLY "table" RESTART IDENTITY CASCADE
1254
1269
  # # => nil
1255
- def truncate(opts = {})
1270
+ def truncate(opts = OPTS)
1256
1271
  if opts.empty?
1257
1272
  super()
1258
1273
  else
@@ -1271,7 +1286,7 @@ module Sequel
1271
1286
  # dataset. If RETURNING is already set, use existing returning values. If RETURNING
1272
1287
  # is only set to return a single columns, return an array of just that column.
1273
1288
  # Otherwise, return an array of hashes.
1274
- def _import(columns, values, opts={})
1289
+ def _import(columns, values, opts=OPTS)
1275
1290
  if @opts[:returning]
1276
1291
  statements = multi_insert_sql(columns, values)
1277
1292
  @db.transaction(opts.merge(:server=>@opts[:server])) do