sequel 3.48.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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