sequel 3.47.0 → 3.48.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 +230 -0
- data/README.rdoc +31 -40
- data/Rakefile +1 -14
- data/doc/active_record.rdoc +29 -29
- data/doc/association_basics.rdoc +4 -13
- data/doc/cheat_sheet.rdoc +8 -6
- data/doc/code_order.rdoc +89 -0
- data/doc/core_extensions.rdoc +3 -3
- data/doc/dataset_basics.rdoc +7 -8
- data/doc/dataset_filtering.rdoc +7 -2
- data/doc/mass_assignment.rdoc +2 -3
- data/doc/migration.rdoc +8 -8
- data/doc/model_hooks.rdoc +11 -7
- data/doc/object_model.rdoc +2 -2
- data/doc/opening_databases.rdoc +5 -14
- data/doc/prepared_statements.rdoc +5 -9
- data/doc/querying.rdoc +23 -28
- data/doc/reflection.rdoc +11 -0
- data/doc/release_notes/3.48.0.txt +477 -0
- data/doc/schema_modification.rdoc +12 -5
- data/doc/security.rdoc +2 -2
- data/doc/sharding.rdoc +1 -2
- data/doc/sql.rdoc +10 -13
- data/doc/testing.rdoc +8 -4
- data/doc/transactions.rdoc +2 -2
- data/doc/validations.rdoc +40 -17
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado.rb +25 -20
- data/lib/sequel/adapters/ado/access.rb +1 -0
- data/lib/sequel/adapters/ado/mssql.rb +1 -0
- data/lib/sequel/adapters/db2.rb +9 -7
- data/lib/sequel/adapters/dbi.rb +16 -16
- data/lib/sequel/adapters/do.rb +17 -18
- data/lib/sequel/adapters/do/mysql.rb +1 -0
- data/lib/sequel/adapters/do/postgres.rb +2 -0
- data/lib/sequel/adapters/do/sqlite.rb +1 -0
- data/lib/sequel/adapters/firebird.rb +5 -7
- data/lib/sequel/adapters/ibmdb.rb +23 -20
- data/lib/sequel/adapters/informix.rb +8 -2
- data/lib/sequel/adapters/jdbc.rb +39 -35
- data/lib/sequel/adapters/jdbc/as400.rb +1 -0
- data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
- data/lib/sequel/adapters/jdbc/db2.rb +1 -0
- data/lib/sequel/adapters/jdbc/derby.rb +1 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
- data/lib/sequel/adapters/jdbc/h2.rb +1 -0
- data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
- data/lib/sequel/adapters/jdbc/informix.rb +1 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
- data/lib/sequel/adapters/jdbc/progress.rb +1 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
- data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
- data/lib/sequel/adapters/mock.rb +30 -31
- data/lib/sequel/adapters/mysql.rb +6 -7
- data/lib/sequel/adapters/mysql2.rb +5 -6
- data/lib/sequel/adapters/odbc.rb +22 -20
- data/lib/sequel/adapters/odbc/mssql.rb +1 -0
- data/lib/sequel/adapters/openbase.rb +4 -1
- data/lib/sequel/adapters/oracle.rb +10 -8
- data/lib/sequel/adapters/postgres.rb +12 -10
- data/lib/sequel/adapters/shared/access.rb +6 -0
- data/lib/sequel/adapters/shared/cubrid.rb +2 -0
- data/lib/sequel/adapters/shared/db2.rb +2 -0
- data/lib/sequel/adapters/shared/firebird.rb +2 -0
- data/lib/sequel/adapters/shared/informix.rb +2 -0
- data/lib/sequel/adapters/shared/mssql.rb +14 -8
- data/lib/sequel/adapters/shared/mysql.rb +6 -0
- data/lib/sequel/adapters/shared/oracle.rb +2 -0
- data/lib/sequel/adapters/shared/postgres.rb +14 -4
- data/lib/sequel/adapters/shared/progress.rb +1 -0
- data/lib/sequel/adapters/shared/sqlite.rb +4 -3
- data/lib/sequel/adapters/sqlite.rb +6 -7
- data/lib/sequel/adapters/swift.rb +20 -21
- data/lib/sequel/adapters/swift/mysql.rb +1 -0
- data/lib/sequel/adapters/swift/postgres.rb +2 -0
- data/lib/sequel/adapters/swift/sqlite.rb +1 -0
- data/lib/sequel/adapters/tinytds.rb +5 -6
- data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +57 -50
- data/lib/sequel/database/connecting.rb +9 -10
- data/lib/sequel/database/dataset.rb +11 -6
- data/lib/sequel/database/dataset_defaults.rb +61 -69
- data/lib/sequel/database/features.rb +21 -0
- data/lib/sequel/database/misc.rb +23 -3
- data/lib/sequel/database/query.rb +13 -7
- data/lib/sequel/database/schema_methods.rb +6 -6
- data/lib/sequel/database/transactions.rb +1 -0
- data/lib/sequel/dataset/actions.rb +51 -38
- data/lib/sequel/dataset/features.rb +1 -0
- data/lib/sequel/dataset/graph.rb +9 -33
- data/lib/sequel/dataset/misc.rb +30 -5
- data/lib/sequel/dataset/mutation.rb +2 -3
- data/lib/sequel/dataset/prepared_statements.rb +1 -1
- data/lib/sequel/dataset/query.rb +91 -27
- data/lib/sequel/dataset/sql.rb +40 -6
- data/lib/sequel/deprecated.rb +74 -0
- data/lib/sequel/deprecated_core_extensions.rb +135 -0
- data/lib/sequel/extensions/columns_introspection.rb +1 -5
- data/lib/sequel/extensions/core_extensions.rb +10 -3
- data/lib/sequel/extensions/date_arithmetic.rb +1 -0
- data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
- data/lib/sequel/extensions/filter_having.rb +58 -0
- data/lib/sequel/extensions/graph_each.rb +63 -0
- data/lib/sequel/extensions/hash_aliases.rb +44 -0
- data/lib/sequel/extensions/looser_typecasting.rb +14 -3
- data/lib/sequel/extensions/migration.rb +2 -3
- data/lib/sequel/extensions/named_timezones.rb +14 -1
- data/lib/sequel/extensions/null_dataset.rb +7 -1
- data/lib/sequel/extensions/pagination.rb +15 -5
- data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
- data/lib/sequel/extensions/pg_json.rb +7 -7
- data/lib/sequel/extensions/pg_range_ops.rb +8 -2
- data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
- data/lib/sequel/extensions/pretty_table.rb +13 -4
- data/lib/sequel/extensions/query.rb +21 -4
- data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
- data/lib/sequel/extensions/schema_caching.rb +10 -7
- data/lib/sequel/extensions/schema_dumper.rb +35 -48
- data/lib/sequel/extensions/select_remove.rb +13 -4
- data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
- data/lib/sequel/extensions/set_overrides.rb +43 -0
- data/lib/sequel/extensions/to_dot.rb +6 -0
- data/lib/sequel/model.rb +12 -6
- data/lib/sequel/model/associations.rb +80 -38
- data/lib/sequel/model/base.rb +137 -52
- data/lib/sequel/model/errors.rb +7 -2
- data/lib/sequel/plugins/active_model.rb +13 -0
- data/lib/sequel/plugins/after_initialize.rb +43 -0
- data/lib/sequel/plugins/association_proxies.rb +63 -7
- data/lib/sequel/plugins/auto_validations.rb +56 -16
- data/lib/sequel/plugins/blacklist_security.rb +63 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
- data/lib/sequel/plugins/constraint_validations.rb +50 -8
- data/lib/sequel/plugins/dataset_associations.rb +2 -0
- data/lib/sequel/plugins/hook_class_methods.rb +7 -1
- data/lib/sequel/plugins/identity_map.rb +4 -0
- data/lib/sequel/plugins/json_serializer.rb +32 -13
- data/lib/sequel/plugins/optimistic_locking.rb +1 -1
- data/lib/sequel/plugins/rcte_tree.rb +4 -4
- data/lib/sequel/plugins/scissors.rb +33 -0
- data/lib/sequel/plugins/serialization.rb +1 -1
- data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
- data/lib/sequel/plugins/tree.rb +5 -1
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +15 -11
- data/lib/sequel/plugins/xml_serializer.rb +12 -3
- data/lib/sequel/sql.rb +12 -2
- data/lib/sequel/timezones.rb +1 -1
- data/lib/sequel/version.rb +1 -1
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/mssql_spec.rb +24 -57
- data/spec/adapters/postgres_spec.rb +27 -55
- data/spec/adapters/spec_helper.rb +1 -1
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/bin_spec.rb +251 -0
- data/spec/core/database_spec.rb +46 -32
- data/spec/core/dataset_spec.rb +233 -181
- data/spec/core/deprecated_spec.rb +78 -0
- data/spec/core/expression_filters_spec.rb +3 -4
- data/spec/core/mock_adapter_spec.rb +9 -9
- data/spec/core/object_graph_spec.rb +9 -19
- data/spec/core/schema_spec.rb +3 -1
- data/spec/core/spec_helper.rb +19 -0
- data/spec/core_extensions_spec.rb +80 -30
- data/spec/extensions/after_initialize_spec.rb +24 -0
- data/spec/extensions/association_proxies_spec.rb +37 -1
- data/spec/extensions/auto_validations_spec.rb +20 -4
- data/spec/extensions/blacklist_security_spec.rb +87 -0
- data/spec/extensions/boolean_readers_spec.rb +2 -1
- data/spec/extensions/class_table_inheritance_spec.rb +7 -0
- data/spec/extensions/columns_introspection_spec.rb +3 -3
- data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
- data/spec/extensions/core_refinements_spec.rb +7 -7
- data/spec/extensions/dataset_associations_spec.rb +2 -2
- data/spec/extensions/date_arithmetic_spec.rb +1 -1
- data/spec/extensions/defaults_setter_spec.rb +2 -1
- data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
- data/spec/extensions/filter_having_spec.rb +40 -0
- data/spec/extensions/graph_each_spec.rb +109 -0
- data/spec/extensions/hash_aliases_spec.rb +16 -0
- data/spec/extensions/hook_class_methods_spec.rb +2 -2
- data/spec/extensions/identity_map_spec.rb +3 -3
- data/spec/extensions/json_serializer_spec.rb +19 -19
- data/spec/extensions/lazy_attributes_spec.rb +1 -0
- data/spec/extensions/list_spec.rb +13 -13
- data/spec/extensions/looser_typecasting_spec.rb +10 -3
- data/spec/extensions/many_through_many_spec.rb +1 -1
- data/spec/extensions/migration_spec.rb +7 -7
- data/spec/extensions/named_timezones_spec.rb +6 -0
- data/spec/extensions/nested_attributes_spec.rb +2 -2
- data/spec/extensions/null_dataset_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +2 -2
- data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
- data/spec/extensions/pg_range_ops_spec.rb +4 -2
- data/spec/extensions/pg_row_plugin_spec.rb +1 -1
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_literals_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +3 -3
- data/spec/extensions/schema_caching_spec.rb +3 -3
- data/spec/extensions/schema_dumper_spec.rb +27 -2
- data/spec/extensions/schema_spec.rb +2 -2
- data/spec/extensions/scissors_spec.rb +26 -0
- data/spec/extensions/select_remove_spec.rb +1 -1
- data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
- data/spec/extensions/set_overrides_spec.rb +45 -0
- data/spec/extensions/single_table_inheritance_spec.rb +10 -0
- data/spec/extensions/spec_helper.rb +24 -1
- data/spec/extensions/static_cache_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +2 -1
- data/spec/extensions/to_dot_spec.rb +1 -1
- data/spec/extensions/typecast_on_load_spec.rb +3 -2
- data/spec/extensions/update_primary_key_spec.rb +2 -2
- data/spec/extensions/validation_class_methods_spec.rb +19 -19
- data/spec/extensions/validation_helpers_spec.rb +30 -21
- data/spec/extensions/xml_serializer_spec.rb +5 -5
- data/spec/integration/associations_test.rb +10 -30
- data/spec/integration/dataset_test.rb +20 -24
- data/spec/integration/eager_loader_test.rb +5 -5
- data/spec/integration/model_test.rb +3 -3
- data/spec/integration/plugin_test.rb +7 -39
- data/spec/integration/schema_test.rb +4 -38
- data/spec/integration/spec_helper.rb +2 -1
- data/spec/model/association_reflection_spec.rb +70 -5
- data/spec/model/associations_spec.rb +11 -11
- data/spec/model/base_spec.rb +25 -8
- data/spec/model/class_dataset_methods_spec.rb +143 -0
- data/spec/model/dataset_methods_spec.rb +1 -1
- data/spec/model/eager_loading_spec.rb +25 -25
- data/spec/model/hooks_spec.rb +1 -1
- data/spec/model/model_spec.rb +22 -7
- data/spec/model/plugins_spec.rb +1 -6
- data/spec/model/record_spec.rb +37 -29
- data/spec/model/spec_helper.rb +23 -1
- data/spec/model/validations_spec.rb +15 -17
- metadata +32 -3
|
@@ -79,8 +79,14 @@ module Sequel
|
|
|
79
79
|
OPERATORS.keys.each do |f|
|
|
80
80
|
class_eval("def #{f}(v); operator(:#{f}, v) end", __FILE__, __LINE__)
|
|
81
81
|
end
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
def starts_before(v)
|
|
83
|
+
Sequel::Deprecation.deprecate('Postgres::PGRangeOp#starts_before', "Please switch to Postgres::PGRangeOp#ends_before")
|
|
84
|
+
ends_before(v)
|
|
85
|
+
end
|
|
86
|
+
def ends_after(v)
|
|
87
|
+
Sequel::Deprecation.deprecate('Postgres::PGRangeOp#ends_after', "Please switch to Postgres::PGRangeOp#starts_after")
|
|
88
|
+
starts_after(v)
|
|
89
|
+
end
|
|
84
90
|
|
|
85
91
|
# These operators are already supported by the wrapper, but for ranges they
|
|
86
92
|
# return ranges, so wrap the results in another RangeOp.
|
|
@@ -228,6 +228,7 @@ module Sequel
|
|
|
228
228
|
# Set the statement_cache for the connection, using the database's
|
|
229
229
|
# :statement_cache_opts option.
|
|
230
230
|
def self.extended(c)
|
|
231
|
+
Sequel::Deprecation.deprecate('The pg_statement_cache extension', 'Please stop loading it') unless defined?(SEQUEL_EXTENSIONS_NO_DEPRECATION_WARNING)
|
|
231
232
|
c.instance_variable_set(:@statement_cache, StatementCache.new(c.sequel_db.opts[:statement_cache_opts] || {}){|name| c.deallocate(name)})
|
|
232
233
|
end
|
|
233
234
|
|
|
@@ -9,22 +9,31 @@
|
|
|
9
9
|
# |2 |test |
|
|
10
10
|
# +--+-------+
|
|
11
11
|
#
|
|
12
|
-
#
|
|
12
|
+
# You can load this extension into specific datasets:
|
|
13
13
|
#
|
|
14
|
-
#
|
|
14
|
+
# ds = DB[:table]
|
|
15
|
+
# ds.extension(:pretty_table)
|
|
16
|
+
#
|
|
17
|
+
# Or you can load it into all of a database's datasets, which
|
|
18
|
+
# is probably the desired behavior if you are using this extension:
|
|
19
|
+
#
|
|
20
|
+
# DB.extension(:pretty_table)
|
|
15
21
|
|
|
16
22
|
module Sequel
|
|
17
23
|
extension :_pretty_table
|
|
18
24
|
|
|
25
|
+
module DatasetPrinter
|
|
26
|
+
end
|
|
27
|
+
|
|
19
28
|
class Dataset
|
|
20
29
|
# Pretty prints the records in the dataset as plain-text table.
|
|
21
30
|
def print(*cols)
|
|
31
|
+
Sequel::Deprecation.deprecate('Loading the pretty_table extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(DatasetPrinter)
|
|
22
32
|
ds = naked
|
|
23
33
|
rows = ds.all
|
|
24
34
|
Sequel::PrettyTable.print(rows, cols.empty? ? ds.columns : cols)
|
|
25
35
|
end
|
|
26
36
|
end
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
Dataset.register_extension(:pretty_table){}
|
|
38
|
+
Dataset.register_extension(:pretty_table, DatasetPrinter)
|
|
30
39
|
end
|
|
@@ -2,18 +2,34 @@
|
|
|
2
2
|
# a different way to construct queries instead of the usual
|
|
3
3
|
# method chaining. See Sequel::Dataset#query for details.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# You can load this extension into specific datasets:
|
|
6
6
|
#
|
|
7
|
-
#
|
|
7
|
+
# ds = DB[:table]
|
|
8
|
+
# ds.extension(:query)
|
|
9
|
+
#
|
|
10
|
+
# Or you can load it into all of a database's datasets, which
|
|
11
|
+
# is probably the desired behavior if you are using this extension:
|
|
12
|
+
#
|
|
13
|
+
# DB.extension(:query)
|
|
8
14
|
|
|
9
15
|
module Sequel
|
|
16
|
+
module DatabaseQuery
|
|
17
|
+
def self.extended(db)
|
|
18
|
+
db.extend_datasets(DatasetQuery)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
10
22
|
class Database
|
|
11
23
|
# Return a dataset modified by the query block
|
|
12
24
|
def query(&block)
|
|
25
|
+
Sequel::Deprecation.deprecate('Loading the query extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(DatabaseQuery)
|
|
13
26
|
dataset.query(&block)
|
|
14
27
|
end
|
|
15
28
|
end
|
|
16
29
|
|
|
30
|
+
module DatasetQuery
|
|
31
|
+
end
|
|
32
|
+
|
|
17
33
|
class Dataset
|
|
18
34
|
# Translates a query block into a dataset. Query blocks are an
|
|
19
35
|
# alternative to Sequel's usual method chaining, by using
|
|
@@ -29,6 +45,7 @@ module Sequel
|
|
|
29
45
|
#
|
|
30
46
|
# dataset = DB[:items].select(:x, :y, :z).filter{(x > 1) & (y > 2)}.reverse(:z)
|
|
31
47
|
def query(&block)
|
|
48
|
+
Sequel::Deprecation.deprecate('Loading the query extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(DatasetQuery)
|
|
32
49
|
query = Query.new(self)
|
|
33
50
|
query.instance_eval(&block)
|
|
34
51
|
query.dataset
|
|
@@ -52,6 +69,6 @@ module Sequel
|
|
|
52
69
|
end
|
|
53
70
|
end
|
|
54
71
|
|
|
55
|
-
Dataset.register_extension(:query)
|
|
56
|
-
Database.register_extension(:query)
|
|
72
|
+
Dataset.register_extension(:query, DatasetQuery)
|
|
73
|
+
Database.register_extension(:query, DatabaseQuery)
|
|
57
74
|
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# The ruby18_symbol_extensions adds the <, <=, >, >= to Symbol
|
|
2
|
+
# to reflect the mathmatical operators. It also adds the [] method
|
|
3
|
+
# to Symbol for creating SQL functions.
|
|
4
|
+
#
|
|
5
|
+
# Usage of this extension is not recommended. This extension will
|
|
6
|
+
# only load on ruby 1.8, so you will not be able to upgrade to
|
|
7
|
+
# newer ruby versions if you use it. If you still want to use it,
|
|
8
|
+
# you can load it via:
|
|
9
|
+
#
|
|
10
|
+
# Sequel.extension :ruby18_symbol_extensions
|
|
11
|
+
|
|
12
|
+
raise(Sequel::Error, "The ruby18_symbol_extensions is only available on ruby 1.8.") unless RUBY_VERSION < '1.9.0'
|
|
13
|
+
|
|
14
|
+
class Symbol
|
|
15
|
+
include Sequel::SQL::InequalityMethods
|
|
16
|
+
|
|
17
|
+
# Create an SQL Function with the receiver as the function name
|
|
18
|
+
# and the given arguments.
|
|
19
|
+
def [](*args)
|
|
20
|
+
Sequel::SQL::Function.new(self, *args)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -6,10 +6,8 @@
|
|
|
6
6
|
#
|
|
7
7
|
# Basic usage in application code:
|
|
8
8
|
#
|
|
9
|
-
# Sequel.extension :schema_caching
|
|
10
|
-
#
|
|
11
9
|
# DB = Sequel.connect('...')
|
|
12
|
-
#
|
|
10
|
+
# DB.extension :schema_caching
|
|
13
11
|
# DB.load_schema_cache('/path/to/schema.dump')
|
|
14
12
|
#
|
|
15
13
|
# # load model files
|
|
@@ -23,10 +21,8 @@
|
|
|
23
21
|
# all tables, and you don't worry about race conditions, you can
|
|
24
22
|
# choose to use the following in your application code:
|
|
25
23
|
#
|
|
26
|
-
# Sequel.extension :schema_caching
|
|
27
|
-
#
|
|
28
24
|
# DB = Sequel.connect('...')
|
|
29
|
-
#
|
|
25
|
+
# DB.extension :schema_caching
|
|
30
26
|
# DB.load_schema_cache?('/path/to/schema.dump')
|
|
31
27
|
#
|
|
32
28
|
# # load model files
|
|
@@ -47,9 +43,13 @@
|
|
|
47
43
|
# you should not attempt to load the schema from a untrusted file.
|
|
48
44
|
|
|
49
45
|
module Sequel
|
|
46
|
+
module SchemaCaching
|
|
47
|
+
end
|
|
48
|
+
|
|
50
49
|
class Database
|
|
51
50
|
# Dump the cached schema to the filename given in Marshal format.
|
|
52
51
|
def dump_schema_cache(file)
|
|
52
|
+
Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
|
|
53
53
|
File.open(file, 'wb'){|f| f.write(Marshal.dump(@schemas))}
|
|
54
54
|
nil
|
|
55
55
|
end
|
|
@@ -57,12 +57,14 @@ module Sequel
|
|
|
57
57
|
# Dump the cached schema to the filename given unless the file
|
|
58
58
|
# already exists.
|
|
59
59
|
def dump_schema_cache?(file)
|
|
60
|
+
Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
|
|
60
61
|
dump_schema_cache(file) unless File.exist?(file)
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
# Replace the schema cache with the data from the given file, which
|
|
64
65
|
# should be in Marshal format.
|
|
65
66
|
def load_schema_cache(file)
|
|
67
|
+
Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
|
|
66
68
|
@schemas = Marshal.load(File.read(file))
|
|
67
69
|
nil
|
|
68
70
|
end
|
|
@@ -70,9 +72,10 @@ module Sequel
|
|
|
70
72
|
# Replace the schema cache with the data from the given file if the
|
|
71
73
|
# file exists.
|
|
72
74
|
def load_schema_cache?(file)
|
|
75
|
+
Sequel::Deprecation.deprecate('Loading the schema_caching extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaCaching)
|
|
73
76
|
load_schema_cache(file) if File.exist?(file)
|
|
74
77
|
end
|
|
75
78
|
end
|
|
76
79
|
|
|
77
|
-
Database.register_extension(:schema_caching)
|
|
80
|
+
Database.register_extension(:schema_caching, SchemaCaching)
|
|
78
81
|
end
|
|
@@ -6,11 +6,14 @@
|
|
|
6
6
|
#
|
|
7
7
|
# To load the extension:
|
|
8
8
|
#
|
|
9
|
-
#
|
|
9
|
+
# DB.extension :schema_dumper
|
|
10
10
|
|
|
11
11
|
Sequel.extension :eval_inspect
|
|
12
12
|
|
|
13
13
|
module Sequel
|
|
14
|
+
module SchemaDumper
|
|
15
|
+
end
|
|
16
|
+
|
|
14
17
|
class Database
|
|
15
18
|
# Dump foreign key constraints for all tables as a migration. This complements
|
|
16
19
|
# the :foreign_keys=>false option to dump_schema_migration. This only dumps
|
|
@@ -20,6 +23,7 @@ module Sequel
|
|
|
20
23
|
# Note that the migration this produces does not have a down
|
|
21
24
|
# block, so you cannot reverse it.
|
|
22
25
|
def dump_foreign_key_migration(options={})
|
|
26
|
+
Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
|
|
23
27
|
ts = tables(options)
|
|
24
28
|
<<END_MIG
|
|
25
29
|
Sequel.migration do
|
|
@@ -38,6 +42,7 @@ END_MIG
|
|
|
38
42
|
# set to :namespace, prepend the table name to the index name if the
|
|
39
43
|
# database does not use a global index namespace.
|
|
40
44
|
def dump_indexes_migration(options={})
|
|
45
|
+
Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
|
|
41
46
|
ts = tables(options)
|
|
42
47
|
<<END_MIG
|
|
43
48
|
Sequel.migration do
|
|
@@ -62,6 +67,7 @@ END_MIG
|
|
|
62
67
|
# :index_names :: If set to false, don't record names of indexes. If
|
|
63
68
|
# set to :namespace, prepend the table name to the index name.
|
|
64
69
|
def dump_schema_migration(options={})
|
|
70
|
+
Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
|
|
65
71
|
options = options.dup
|
|
66
72
|
if options[:indexes] == false && !options.has_key?(:foreign_keys)
|
|
67
73
|
# Unless foreign_keys option is specifically set, disable if indexes
|
|
@@ -91,6 +97,7 @@ END_MIG
|
|
|
91
97
|
# Return a string with a create table block that will recreate the given
|
|
92
98
|
# table's schema. Takes the same options as dump_schema_migration.
|
|
93
99
|
def dump_table_schema(table, options={})
|
|
100
|
+
Sequel::Deprecation.deprecate('Loading the schema_dumper extension globally', "Please use Database#extension to load the extension into this database") unless is_a?(SchemaDumper)
|
|
94
101
|
table = table.value.to_s if table.is_a?(SQL::Identifier)
|
|
95
102
|
gen = dump_table_generator(table, options)
|
|
96
103
|
commands = [gen.dump_columns, gen.dump_constraints, gen.dump_indexes].reject{|x| x == ''}.join("\n\n")
|
|
@@ -209,13 +216,11 @@ END_MIG
|
|
|
209
216
|
# For the table given, get the list of foreign keys and return an alter_table
|
|
210
217
|
# string that would add the foreign keys if run in a migration.
|
|
211
218
|
def dump_table_foreign_keys(table, options={})
|
|
212
|
-
|
|
219
|
+
if supports_foreign_key_parsing?
|
|
213
220
|
fks = foreign_key_list(table, options).sort_by{|fk| fk[:columns].map{|c| c.to_s}}
|
|
214
|
-
rescue Sequel::NotImplemented
|
|
215
|
-
return ''
|
|
216
221
|
end
|
|
217
222
|
|
|
218
|
-
if fks.empty?
|
|
223
|
+
if fks.nil? || fks.empty?
|
|
219
224
|
''
|
|
220
225
|
else
|
|
221
226
|
dump_add_fk_constraints(table, fks)
|
|
@@ -233,40 +238,32 @@ END_MIG
|
|
|
233
238
|
m = method(:recreate_column)
|
|
234
239
|
im = method(:index_to_generator_opts)
|
|
235
240
|
|
|
236
|
-
if options[:indexes] != false
|
|
237
|
-
|
|
238
|
-
indexes = indexes(table).sort_by{|k,v| k.to_s}
|
|
239
|
-
rescue Sequel::NotImplemented
|
|
240
|
-
nil
|
|
241
|
-
end
|
|
241
|
+
if options[:indexes] != false && supports_index_parsing?
|
|
242
|
+
indexes = indexes(table).sort_by{|k,v| k.to_s}
|
|
242
243
|
end
|
|
243
244
|
|
|
244
|
-
if options[:foreign_keys] != false
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
end
|
|
245
|
+
if options[:foreign_keys] != false && supports_foreign_key_parsing?
|
|
246
|
+
fk_list = foreign_key_list(table)
|
|
247
|
+
|
|
248
|
+
if (sfk = options[:skipped_foreign_keys]) && (sfkt = sfk[table])
|
|
249
|
+
fk_list.delete_if{|fk| sfkt.has_key?(fk[:columns])}
|
|
250
|
+
end
|
|
251
251
|
|
|
252
|
-
|
|
253
|
-
|
|
252
|
+
composite_fks, single_fks = fk_list.partition{|h| h[:columns].length > 1}
|
|
253
|
+
fk_hash = {}
|
|
254
254
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
255
|
+
single_fks.each do |fk|
|
|
256
|
+
column = fk.delete(:columns).first
|
|
257
|
+
fk.delete(:name)
|
|
258
|
+
fk_hash[column] = fk
|
|
259
|
+
end
|
|
260
260
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
end
|
|
261
|
+
s = s.map do |name, info|
|
|
262
|
+
if fk_info = fk_hash[name]
|
|
263
|
+
[name, fk_info.merge(info)]
|
|
264
|
+
else
|
|
265
|
+
[name, info]
|
|
267
266
|
end
|
|
268
|
-
rescue Sequel::NotImplemented
|
|
269
|
-
nil
|
|
270
267
|
end
|
|
271
268
|
end
|
|
272
269
|
|
|
@@ -281,11 +278,12 @@ END_MIG
|
|
|
281
278
|
# Return a string that containing add_index/drop_index method calls for
|
|
282
279
|
# creating the index migration.
|
|
283
280
|
def dump_table_indexes(table, meth, options={})
|
|
284
|
-
|
|
281
|
+
if supports_index_parsing?
|
|
285
282
|
indexes = indexes(table).sort_by{|k,v| k.to_s}
|
|
286
|
-
|
|
283
|
+
else
|
|
287
284
|
return ''
|
|
288
285
|
end
|
|
286
|
+
|
|
289
287
|
im = method(:index_to_generator_opts)
|
|
290
288
|
gen = create_table_generator do
|
|
291
289
|
indexes.each{|iname, iopts| send(:index, iopts[:columns], im.call(table, iname, iopts, options))}
|
|
@@ -311,18 +309,7 @@ END_MIG
|
|
|
311
309
|
# Sort the tables so that referenced tables are created before tables that
|
|
312
310
|
# reference them, and then by name. If foreign keys are disabled, just sort by name.
|
|
313
311
|
def sort_dumped_tables(tables, options={})
|
|
314
|
-
|
|
315
|
-
begin
|
|
316
|
-
foreign_key_list(:some_table_that_does_not_exist)
|
|
317
|
-
true
|
|
318
|
-
rescue Sequel::NotImplemented
|
|
319
|
-
false
|
|
320
|
-
rescue
|
|
321
|
-
true
|
|
322
|
-
end
|
|
323
|
-
end
|
|
324
|
-
|
|
325
|
-
if sort_topologically
|
|
312
|
+
if options[:foreign_keys] != false && supports_foreign_key_parsing?
|
|
326
313
|
table_fks = {}
|
|
327
314
|
tables.each{|t| table_fks[t] = foreign_key_list(t)}
|
|
328
315
|
# Remove self referential foreign keys, not important when sorting.
|
|
@@ -484,5 +471,5 @@ END_MIG
|
|
|
484
471
|
end
|
|
485
472
|
end
|
|
486
473
|
|
|
487
|
-
Database.register_extension(:schema_dumper)
|
|
474
|
+
Database.register_extension(:schema_dumper, SchemaDumper)
|
|
488
475
|
end
|
|
@@ -2,11 +2,20 @@
|
|
|
2
2
|
# columns from a dataset. It's not part of Sequel core as it is rarely needed and has
|
|
3
3
|
# some corner cases where it can't work correctly.
|
|
4
4
|
#
|
|
5
|
-
#
|
|
5
|
+
# You can load this extension into specific datasets:
|
|
6
6
|
#
|
|
7
|
-
#
|
|
7
|
+
# ds = DB[:table]
|
|
8
|
+
# ds.extension(:select_remove)
|
|
9
|
+
#
|
|
10
|
+
# Or you can load it into all of a database's datasets, which
|
|
11
|
+
# is probably the desired behavior if you are using this extension:
|
|
12
|
+
#
|
|
13
|
+
# DB.extension(:select_remove)
|
|
8
14
|
|
|
9
15
|
module Sequel
|
|
16
|
+
module SelectRemove
|
|
17
|
+
end
|
|
18
|
+
|
|
10
19
|
class Dataset
|
|
11
20
|
# Remove columns from the list of selected columns. If any of the currently selected
|
|
12
21
|
# columns use expressions/aliases, this will remove selected columns with the given
|
|
@@ -29,6 +38,7 @@ module Sequel
|
|
|
29
38
|
#
|
|
30
39
|
# There may be other cases where this method does not work correctly, use it with caution.
|
|
31
40
|
def select_remove(*cols)
|
|
41
|
+
Sequel::Deprecation.deprecate('Loading the select_remove extension globally', "Please use Database/Dataset#extension to load the extension into this dataset") unless is_a?(SelectRemove)
|
|
32
42
|
if (sel = @opts[:select]) && !sel.empty?
|
|
33
43
|
select(*(columns.zip(sel).reject{|c, s| cols.include?(c)}.map{|c, s| s} - cols))
|
|
34
44
|
else
|
|
@@ -37,6 +47,5 @@ module Sequel
|
|
|
37
47
|
end
|
|
38
48
|
end
|
|
39
49
|
|
|
40
|
-
|
|
41
|
-
Dataset.register_extension(:select_remove){}
|
|
50
|
+
Dataset.register_extension(:select_remove, SelectRemove)
|
|
42
51
|
end
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# This adds the following dataset methods:
|
|
2
|
+
#
|
|
3
|
+
# []= :: filter with the first argument, update with the second
|
|
4
|
+
# insert_multiple :: insert multiple rows at once
|
|
5
|
+
# set :: alias for update
|
|
6
|
+
# to_csv :: return string in csv format for the dataset
|
|
7
|
+
# db= :: change the dataset's database
|
|
8
|
+
# opts= :: change the dataset's opts
|
|
9
|
+
#
|
|
10
|
+
# It is only recommended to use this for backwards compatibility.
|
|
11
|
+
#
|
|
12
|
+
# You can load this extension into specific datasets:
|
|
13
|
+
#
|
|
14
|
+
# ds = DB[:table]
|
|
15
|
+
# ds.extension(:sequel_3_dataset_methods)
|
|
16
|
+
#
|
|
17
|
+
# Or you can load it into all of a database's datasets, which
|
|
18
|
+
# is probably the desired behavior if you are using this extension:
|
|
19
|
+
#
|
|
20
|
+
# DB.extension(:sequel_3_dataset_methods)
|
|
21
|
+
|
|
22
|
+
module Sequel
|
|
23
|
+
module Sequel3DatasetMethods
|
|
24
|
+
COMMA = Dataset::COMMA
|
|
25
|
+
# The database related to this dataset. This is the Database instance that
|
|
26
|
+
# will execute all of this dataset's queries.
|
|
27
|
+
attr_writer :db
|
|
28
|
+
|
|
29
|
+
# The hash of options for this dataset, keys are symbols.
|
|
30
|
+
attr_writer :opts
|
|
31
|
+
|
|
32
|
+
# Update all records matching the conditions with the values specified.
|
|
33
|
+
# Returns the number of rows affected.
|
|
34
|
+
#
|
|
35
|
+
# DB[:table][:id=>1] = {:id=>2} # UPDATE table SET id = 2 WHERE id = 1
|
|
36
|
+
# # => 1 # number of rows affected
|
|
37
|
+
def []=(conditions, values)
|
|
38
|
+
filter(conditions).update(values)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Inserts multiple values. If a block is given it is invoked for each
|
|
42
|
+
# item in the given array before inserting it. See +multi_insert+ as
|
|
43
|
+
# a possibly faster version that may be able to insert multiple
|
|
44
|
+
# records in one SQL statement (if supported by the database).
|
|
45
|
+
# Returns an array of primary keys of inserted rows.
|
|
46
|
+
#
|
|
47
|
+
# DB[:table].insert_multiple([{:x=>1}, {:x=>2}])
|
|
48
|
+
# # => [4, 5]
|
|
49
|
+
# # INSERT INTO table (x) VALUES (1)
|
|
50
|
+
# # INSERT INTO table (x) VALUES (2)
|
|
51
|
+
#
|
|
52
|
+
# DB[:table].insert_multiple([{:x=>1}, {:x=>2}]){|row| row[:y] = row[:x] * 2; row }
|
|
53
|
+
# # => [6, 7]
|
|
54
|
+
# # INSERT INTO table (x, y) VALUES (1, 2)
|
|
55
|
+
# # INSERT INTO table (x, y) VALUES (2, 4)
|
|
56
|
+
def insert_multiple(array, &block)
|
|
57
|
+
if block
|
|
58
|
+
array.map{|i| insert(block.call(i))}
|
|
59
|
+
else
|
|
60
|
+
array.map{|i| insert(i)}
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Return a copy of the dataset with unqualified identifiers in the
|
|
65
|
+
# SELECT, WHERE, GROUP, HAVING, and ORDER clauses qualified by the
|
|
66
|
+
# given table. If no columns are currently selected, select all
|
|
67
|
+
# columns of the given table.
|
|
68
|
+
#
|
|
69
|
+
# DB[:items].filter(:id=>1).qualify_to(:i)
|
|
70
|
+
# # SELECT i.* FROM items WHERE (i.id = 1)
|
|
71
|
+
def qualify_to(table)
|
|
72
|
+
qualify(table)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Qualify the dataset to its current first source. This is useful
|
|
76
|
+
# if you have unqualified identifiers in the query that all refer to
|
|
77
|
+
# the first source, and you want to join to another table which
|
|
78
|
+
# has columns with the same name as columns in the current dataset.
|
|
79
|
+
# See +qualify_to+.
|
|
80
|
+
#
|
|
81
|
+
# DB[:items].filter(:id=>1).qualify_to_first_source
|
|
82
|
+
# # SELECT items.* FROM items WHERE (items.id = 1)
|
|
83
|
+
def qualify_to_first_source
|
|
84
|
+
qualify
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# Alias for update, but not aliased directly so subclasses
|
|
88
|
+
# don't have to override both methods.
|
|
89
|
+
def set(*args)
|
|
90
|
+
update(*args)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Returns a string in CSV format containing the dataset records. By
|
|
94
|
+
# default the CSV representation includes the column titles in the
|
|
95
|
+
# first line. You can turn that off by passing false as the
|
|
96
|
+
# include_column_titles argument.
|
|
97
|
+
#
|
|
98
|
+
# This does not use a CSV library or handle quoting of values in
|
|
99
|
+
# any way. If any values in any of the rows could include commas or line
|
|
100
|
+
# endings, you shouldn't use this.
|
|
101
|
+
#
|
|
102
|
+
# puts DB[:table].to_csv # SELECT * FROM table
|
|
103
|
+
# # id,name
|
|
104
|
+
# # 1,Jim
|
|
105
|
+
# # 2,Bob
|
|
106
|
+
def to_csv(include_column_titles = true)
|
|
107
|
+
n = naked
|
|
108
|
+
cols = n.columns
|
|
109
|
+
csv = ''
|
|
110
|
+
csv << "#{cols.join(COMMA)}\r\n" if include_column_titles
|
|
111
|
+
n.each{|r| csv << "#{cols.collect{|c| r[c]}.join(COMMA)}\r\n"}
|
|
112
|
+
csv
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
Dataset.register_extension(:sequel_3_dataset_methods, Sequel3DatasetMethods)
|
|
117
|
+
end
|