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.
- checksums.yaml +4 -4
- data/CHANGELOG +114 -0
- data/Rakefile +10 -7
- data/doc/association_basics.rdoc +25 -23
- data/doc/code_order.rdoc +7 -0
- data/doc/core_extensions.rdoc +0 -10
- data/doc/object_model.rdoc +4 -1
- data/doc/querying.rdoc +3 -3
- data/doc/release_notes/4.0.0.txt +262 -0
- data/doc/security.rdoc +0 -28
- data/doc/testing.rdoc +8 -14
- data/lib/sequel/adapters/ado.rb +7 -11
- data/lib/sequel/adapters/ado/access.rb +8 -8
- data/lib/sequel/adapters/ado/mssql.rb +4 -4
- data/lib/sequel/adapters/amalgalite.rb +6 -6
- data/lib/sequel/adapters/cubrid.rb +7 -7
- data/lib/sequel/adapters/db2.rb +5 -9
- data/lib/sequel/adapters/dbi.rb +2 -6
- data/lib/sequel/adapters/do.rb +4 -4
- data/lib/sequel/adapters/firebird.rb +4 -4
- data/lib/sequel/adapters/ibmdb.rb +8 -8
- data/lib/sequel/adapters/informix.rb +2 -10
- data/lib/sequel/adapters/jdbc.rb +17 -17
- data/lib/sequel/adapters/jdbc/as400.rb +2 -2
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -1
- data/lib/sequel/adapters/jdbc/db2.rb +1 -1
- data/lib/sequel/adapters/jdbc/derby.rb +1 -1
- data/lib/sequel/adapters/jdbc/h2.rb +2 -2
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -1
- data/lib/sequel/adapters/jdbc/informix.rb +1 -1
- data/lib/sequel/adapters/jdbc/mssql.rb +2 -2
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +5 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -3
- data/lib/sequel/adapters/jdbc/sqlite.rb +3 -3
- data/lib/sequel/adapters/jdbc/transactions.rb +3 -3
- data/lib/sequel/adapters/mock.rb +7 -7
- data/lib/sequel/adapters/mysql.rb +3 -3
- data/lib/sequel/adapters/mysql2.rb +4 -4
- data/lib/sequel/adapters/odbc.rb +2 -6
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -5
- data/lib/sequel/adapters/oracle.rb +13 -17
- data/lib/sequel/adapters/postgres.rb +20 -25
- data/lib/sequel/adapters/shared/cubrid.rb +3 -3
- data/lib/sequel/adapters/shared/db2.rb +2 -2
- data/lib/sequel/adapters/shared/firebird.rb +7 -7
- data/lib/sequel/adapters/shared/mssql.rb +9 -9
- data/lib/sequel/adapters/shared/mysql.rb +29 -13
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +7 -7
- data/lib/sequel/adapters/shared/oracle.rb +22 -13
- data/lib/sequel/adapters/shared/postgres.rb +61 -46
- data/lib/sequel/adapters/shared/sqlite.rb +9 -9
- data/lib/sequel/adapters/sqlite.rb +17 -11
- data/lib/sequel/adapters/swift.rb +3 -3
- data/lib/sequel/adapters/swift/mysql.rb +1 -1
- data/lib/sequel/adapters/swift/sqlite.rb +1 -1
- data/lib/sequel/adapters/tinytds.rb +8 -8
- data/lib/sequel/ast_transformer.rb +3 -1
- data/lib/sequel/connection_pool.rb +4 -2
- data/lib/sequel/connection_pool/sharded_single.rb +2 -2
- data/lib/sequel/connection_pool/sharded_threaded.rb +5 -5
- data/lib/sequel/connection_pool/threaded.rb +7 -7
- data/lib/sequel/core.rb +4 -67
- data/lib/sequel/database.rb +1 -0
- data/lib/sequel/database/connecting.rb +2 -8
- data/lib/sequel/database/dataset.rb +2 -7
- data/lib/sequel/database/dataset_defaults.rb +0 -18
- data/lib/sequel/database/features.rb +4 -4
- data/lib/sequel/database/misc.rb +6 -8
- data/lib/sequel/database/query.rb +5 -61
- data/lib/sequel/database/schema_generator.rb +22 -20
- data/lib/sequel/database/schema_methods.rb +48 -20
- data/lib/sequel/database/transactions.rb +7 -17
- data/lib/sequel/dataset.rb +2 -0
- data/lib/sequel/dataset/actions.rb +23 -91
- data/lib/sequel/dataset/features.rb +1 -4
- data/lib/sequel/dataset/graph.rb +3 -47
- data/lib/sequel/dataset/misc.rb +4 -33
- data/lib/sequel/dataset/prepared_statements.rb +3 -1
- data/lib/sequel/dataset/query.rb +116 -240
- data/lib/sequel/dataset/sql.rb +19 -97
- data/lib/sequel/deprecated.rb +0 -16
- data/lib/sequel/exceptions.rb +0 -3
- data/lib/sequel/extensions/_pretty_table.rb +1 -1
- data/lib/sequel/extensions/columns_introspection.rb +1 -12
- data/lib/sequel/extensions/constraint_validations.rb +3 -3
- data/lib/sequel/extensions/core_extensions.rb +0 -9
- data/lib/sequel/extensions/date_arithmetic.rb +1 -2
- data/lib/sequel/extensions/graph_each.rb +11 -0
- data/lib/sequel/extensions/migration.rb +5 -5
- data/lib/sequel/extensions/null_dataset.rb +11 -13
- data/lib/sequel/extensions/pagination.rb +3 -6
- data/lib/sequel/extensions/pg_array.rb +6 -4
- data/lib/sequel/extensions/pg_array_ops.rb +35 -1
- data/lib/sequel/extensions/pg_json.rb +12 -2
- data/lib/sequel/extensions/pg_json_ops.rb +266 -0
- data/lib/sequel/extensions/pg_range.rb +2 -2
- data/lib/sequel/extensions/pg_range_ops.rb +0 -8
- data/lib/sequel/extensions/pg_row.rb +2 -2
- data/lib/sequel/extensions/pretty_table.rb +0 -4
- data/lib/sequel/extensions/query.rb +3 -8
- data/lib/sequel/extensions/schema_caching.rb +0 -7
- data/lib/sequel/extensions/schema_dumper.rb +10 -17
- data/lib/sequel/extensions/select_remove.rb +0 -4
- data/lib/sequel/extensions/set_overrides.rb +28 -0
- data/lib/sequel/extensions/to_dot.rb +6 -10
- data/lib/sequel/model.rb +6 -7
- data/lib/sequel/model/associations.rb +127 -182
- data/lib/sequel/model/base.rb +88 -211
- data/lib/sequel/model/errors.rb +0 -13
- data/lib/sequel/model/plugins.rb +2 -2
- data/lib/sequel/no_core_ext.rb +0 -1
- data/lib/sequel/plugins/after_initialize.rb +11 -17
- data/lib/sequel/plugins/association_autoreloading.rb +1 -47
- data/lib/sequel/plugins/association_dependencies.rb +2 -2
- data/lib/sequel/plugins/auto_validations.rb +2 -8
- data/lib/sequel/plugins/blacklist_security.rb +32 -2
- data/lib/sequel/plugins/caching.rb +1 -1
- data/lib/sequel/plugins/class_table_inheritance.rb +2 -2
- data/lib/sequel/plugins/composition.rb +10 -8
- data/lib/sequel/plugins/constraint_validations.rb +2 -2
- data/lib/sequel/plugins/dataset_associations.rb +4 -0
- data/lib/sequel/plugins/defaults_setter.rb +8 -6
- data/lib/sequel/plugins/dirty.rb +6 -6
- data/lib/sequel/plugins/force_encoding.rb +13 -8
- data/lib/sequel/plugins/hook_class_methods.rb +1 -7
- data/lib/sequel/plugins/json_serializer.rb +13 -74
- data/lib/sequel/plugins/lazy_attributes.rb +2 -4
- data/lib/sequel/plugins/list.rb +1 -1
- data/lib/sequel/plugins/many_through_many.rb +4 -11
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +1 -49
- data/lib/sequel/plugins/nested_attributes.rb +1 -1
- data/lib/sequel/plugins/optimistic_locking.rb +3 -5
- data/lib/sequel/plugins/pg_array_associations.rb +453 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +23 -7
- data/lib/sequel/plugins/prepared_statements.rb +1 -1
- data/lib/sequel/plugins/prepared_statements_associations.rb +20 -14
- data/lib/sequel/plugins/prepared_statements_safe.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +1 -1
- data/lib/sequel/plugins/serialization.rb +5 -4
- data/lib/sequel/plugins/serialization_modification_detection.rb +1 -1
- data/lib/sequel/plugins/sharding.rb +7 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +2 -2
- data/lib/sequel/plugins/tree.rb +1 -1
- data/lib/sequel/plugins/typecast_on_load.rb +19 -4
- data/lib/sequel/plugins/validation_class_methods.rb +0 -30
- data/lib/sequel/plugins/validation_helpers.rb +13 -31
- data/lib/sequel/plugins/xml_serializer.rb +18 -57
- data/lib/sequel/sql.rb +20 -22
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/db2_spec.rb +14 -23
- data/spec/adapters/firebird_spec.rb +25 -29
- data/spec/adapters/informix_spec.rb +11 -14
- data/spec/adapters/mssql_spec.rb +71 -77
- data/spec/adapters/mysql_spec.rb +165 -172
- data/spec/adapters/oracle_spec.rb +36 -39
- data/spec/adapters/postgres_spec.rb +175 -100
- data/spec/adapters/spec_helper.rb +13 -11
- data/spec/adapters/sqlite_spec.rb +36 -44
- data/spec/core/connection_pool_spec.rb +2 -1
- data/spec/core/database_spec.rb +55 -55
- data/spec/core/dataset_spec.rb +45 -249
- data/spec/core/deprecated_spec.rb +0 -8
- data/spec/core/expression_filters_spec.rb +23 -5
- data/spec/core/object_graph_spec.rb +4 -66
- data/spec/core/schema_spec.rb +35 -12
- data/spec/core/spec_helper.rb +3 -2
- data/spec/core_extensions_spec.rb +17 -19
- data/spec/extensions/arbitrary_servers_spec.rb +2 -3
- data/spec/extensions/association_dependencies_spec.rb +14 -14
- data/spec/extensions/auto_validations_spec.rb +7 -0
- data/spec/extensions/blacklist_security_spec.rb +5 -5
- data/spec/extensions/blank_spec.rb +2 -0
- data/spec/extensions/class_table_inheritance_spec.rb +2 -2
- data/spec/extensions/columns_introspection_spec.rb +2 -29
- data/spec/extensions/composition_spec.rb +10 -17
- data/spec/extensions/core_refinements_spec.rb +5 -1
- data/spec/extensions/dataset_associations_spec.rb +18 -0
- data/spec/extensions/date_arithmetic_spec.rb +2 -2
- data/spec/extensions/defaults_setter_spec.rb +9 -9
- data/spec/extensions/dirty_spec.rb +0 -5
- data/spec/extensions/eval_inspect_spec.rb +2 -0
- data/spec/extensions/force_encoding_spec.rb +2 -18
- data/spec/extensions/hash_aliases_spec.rb +8 -0
- data/spec/extensions/hook_class_methods_spec.rb +39 -58
- data/spec/extensions/inflector_spec.rb +2 -0
- data/spec/extensions/instance_filters_spec.rb +8 -8
- data/spec/extensions/json_serializer_spec.rb +1 -41
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +106 -109
- data/spec/extensions/migration_spec.rb +2 -0
- data/spec/extensions/named_timezones_spec.rb +1 -0
- data/spec/extensions/pg_array_associations_spec.rb +603 -0
- data/spec/extensions/pg_array_ops_spec.rb +25 -0
- data/spec/extensions/pg_array_spec.rb +9 -1
- data/spec/extensions/pg_hstore_ops_spec.rb +13 -0
- data/spec/extensions/pg_hstore_spec.rb +1 -0
- data/spec/extensions/pg_json_ops_spec.rb +131 -0
- data/spec/extensions/pg_json_spec.rb +10 -4
- data/spec/extensions/pg_range_ops_spec.rb +2 -5
- data/spec/extensions/pg_range_spec.rb +6 -2
- data/spec/extensions/pg_row_ops_spec.rb +2 -0
- data/spec/extensions/prepared_statements_associations_spec.rb +26 -5
- data/spec/extensions/rcte_tree_spec.rb +15 -15
- data/spec/extensions/schema_dumper_spec.rb +0 -1
- data/spec/extensions/schema_spec.rb +9 -9
- data/spec/extensions/serialization_modification_detection_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +18 -29
- data/spec/extensions/set_overrides_spec.rb +4 -0
- data/spec/extensions/{many_to_one_pk_lookup_spec.rb → shared_caching_spec.rb} +1 -4
- data/spec/extensions/single_table_inheritance_spec.rb +4 -4
- data/spec/extensions/spec_helper.rb +8 -9
- data/spec/extensions/sql_expr_spec.rb +2 -0
- data/spec/extensions/string_date_time_spec.rb +2 -0
- data/spec/extensions/string_stripper_spec.rb +2 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +12 -12
- data/spec/extensions/thread_local_timezones_spec.rb +2 -0
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +24 -24
- data/spec/extensions/tree_spec.rb +7 -7
- data/spec/extensions/typecast_on_load_spec.rb +8 -1
- data/spec/extensions/update_primary_key_spec.rb +10 -10
- data/spec/extensions/validation_class_methods_spec.rb +10 -39
- data/spec/extensions/validation_helpers_spec.rb +29 -47
- data/spec/extensions/xml_serializer_spec.rb +1 -23
- data/spec/integration/associations_test.rb +231 -40
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +64 -64
- data/spec/integration/eager_loader_test.rb +28 -28
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +2 -2
- data/spec/integration/plugin_test.rb +21 -21
- data/spec/integration/prepared_statement_test.rb +7 -7
- data/spec/integration/schema_test.rb +115 -110
- data/spec/integration/spec_helper.rb +17 -27
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +10 -10
- data/spec/integration/type_test.rb +2 -2
- data/spec/model/association_reflection_spec.rb +2 -28
- data/spec/model/associations_spec.rb +239 -188
- data/spec/model/base_spec.rb +27 -68
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +160 -172
- data/spec/model/hooks_spec.rb +62 -79
- data/spec/model/model_spec.rb +36 -51
- data/spec/model/plugins_spec.rb +5 -19
- data/spec/model/record_spec.rb +125 -151
- data/spec/model/spec_helper.rb +8 -6
- data/spec/model/validations_spec.rb +4 -17
- data/spec/spec_config.rb +2 -10
- metadata +50 -56
- data/lib/sequel/deprecated_core_extensions.rb +0 -135
- data/lib/sequel/extensions/pg_auto_parameterize.rb +0 -185
- data/lib/sequel/extensions/pg_statement_cache.rb +0 -318
- data/lib/sequel/plugins/identity_map.rb +0 -260
- data/lib/sequel_core.rb +0 -2
- data/lib/sequel_model.rb +0 -2
- data/spec/extensions/association_autoreloading_spec.rb +0 -102
- data/spec/extensions/identity_map_spec.rb +0 -337
- data/spec/extensions/pg_auto_parameterize_spec.rb +0 -70
- data/spec/extensions/pg_statement_cache_spec.rb +0 -208
- data/spec/rcov.opts +0 -8
- 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]||
|
|
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]
|
|
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,
|
|
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,
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
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)
|
|
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)
|
|
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
|
|
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
|
|
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
|
-
|
|
200
|
-
|
|
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=
|
|
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
|
-
|
|
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]
|
|
813
|
-
|
|
826
|
+
expr = if schema = opts[:schema]
|
|
827
|
+
schema.to_s
|
|
814
828
|
else
|
|
815
|
-
|
|
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).
|
|
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
|
-
|
|
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
|