sequel 3.36.1 → 3.37.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +84 -0
- data/Rakefile +13 -0
- data/bin/sequel +12 -16
- data/doc/advanced_associations.rdoc +36 -67
- data/doc/association_basics.rdoc +11 -16
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/schema_modification.rdoc +4 -0
- data/lib/sequel/adapters/jdbc/h2.rb +1 -1
- data/lib/sequel/adapters/jdbc/postgresql.rb +26 -8
- data/lib/sequel/adapters/mysql2.rb +4 -3
- data/lib/sequel/adapters/odbc/mssql.rb +2 -2
- data/lib/sequel/adapters/postgres.rb +4 -60
- data/lib/sequel/adapters/shared/mssql.rb +2 -1
- data/lib/sequel/adapters/shared/mysql.rb +0 -5
- data/lib/sequel/adapters/shared/postgres.rb +68 -2
- data/lib/sequel/adapters/shared/sqlite.rb +17 -1
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +12 -1
- data/lib/sequel/adapters/utils/pg_types.rb +76 -0
- data/lib/sequel/core.rb +13 -0
- data/lib/sequel/database/misc.rb +41 -1
- data/lib/sequel/database/schema_generator.rb +23 -10
- data/lib/sequel/database/schema_methods.rb +26 -4
- data/lib/sequel/dataset/graph.rb +2 -1
- data/lib/sequel/dataset/query.rb +62 -2
- data/lib/sequel/extensions/_pretty_table.rb +7 -3
- data/lib/sequel/extensions/arbitrary_servers.rb +5 -4
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +13 -2
- data/lib/sequel/extensions/core_extensions.rb +6 -0
- data/lib/sequel/extensions/eval_inspect.rb +158 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +4 -1
- data/lib/sequel/extensions/named_timezones.rb +4 -0
- data/lib/sequel/extensions/null_dataset.rb +4 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +219 -168
- data/lib/sequel/extensions/pg_array_ops.rb +7 -2
- data/lib/sequel/extensions/pg_auto_parameterize.rb +10 -4
- data/lib/sequel/extensions/pg_hstore.rb +3 -1
- data/lib/sequel/extensions/pg_hstore_ops.rb +7 -2
- data/lib/sequel/extensions/pg_inet.rb +28 -3
- data/lib/sequel/extensions/pg_interval.rb +192 -0
- data/lib/sequel/extensions/pg_json.rb +21 -9
- data/lib/sequel/extensions/pg_range.rb +487 -0
- data/lib/sequel/extensions/pg_range_ops.rb +122 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +3 -2
- data/lib/sequel/extensions/pretty_table.rb +12 -1
- data/lib/sequel/extensions/query.rb +4 -0
- data/lib/sequel/extensions/query_literals.rb +6 -6
- data/lib/sequel/extensions/schema_dumper.rb +39 -38
- data/lib/sequel/extensions/select_remove.rb +4 -0
- data/lib/sequel/extensions/server_block.rb +3 -2
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +4 -0
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +9 -3
- data/lib/sequel/extensions/to_dot.rb +4 -0
- data/lib/sequel/model/associations.rb +150 -91
- data/lib/sequel/plugins/identity_map.rb +2 -2
- data/lib/sequel/plugins/list.rb +1 -0
- data/lib/sequel/plugins/many_through_many.rb +33 -32
- data/lib/sequel/plugins/nested_attributes.rb +11 -3
- data/lib/sequel/plugins/rcte_tree.rb +2 -2
- data/lib/sequel/plugins/schema.rb +1 -1
- data/lib/sequel/sql.rb +14 -14
- data/lib/sequel/version.rb +2 -2
- data/spec/adapters/mysql_spec.rb +25 -0
- data/spec/adapters/postgres_spec.rb +572 -28
- data/spec/adapters/sqlite_spec.rb +16 -1
- data/spec/core/database_spec.rb +61 -2
- data/spec/core/dataset_spec.rb +92 -0
- data/spec/core/expression_filters_spec.rb +12 -0
- data/spec/extensions/arbitrary_servers_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/eval_inspect_spec.rb +58 -0
- data/spec/extensions/json_serializer_spec.rb +0 -6
- data/spec/extensions/list_spec.rb +1 -1
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +81 -0
- data/spec/extensions/nested_attributes_spec.rb +21 -4
- data/spec/extensions/pg_array_ops_spec.rb +1 -11
- data/spec/extensions/pg_array_spec.rb +181 -90
- data/spec/extensions/pg_auto_parameterize_spec.rb +3 -3
- data/spec/extensions/pg_hstore_spec.rb +1 -3
- data/spec/extensions/pg_inet_spec.rb +6 -1
- data/spec/extensions/pg_interval_spec.rb +73 -0
- data/spec/extensions/pg_json_spec.rb +5 -9
- data/spec/extensions/pg_range_ops_spec.rb +49 -0
- data/spec/extensions/pg_range_spec.rb +372 -0
- data/spec/extensions/pg_statement_cache_spec.rb +1 -2
- data/spec/extensions/query_literals_spec.rb +1 -2
- data/spec/extensions/schema_dumper_spec.rb +48 -89
- data/spec/extensions/serialization_spec.rb +1 -5
- data/spec/extensions/server_block_spec.rb +2 -2
- data/spec/extensions/spec_helper.rb +12 -2
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/integration/associations_test.rb +4 -4
- data/spec/integration/database_test.rb +2 -2
- data/spec/integration/dataset_test.rb +4 -4
- data/spec/integration/eager_loader_test.rb +6 -6
- data/spec/integration/plugin_test.rb +2 -2
- data/spec/integration/spec_helper.rb +2 -2
- data/spec/model/association_reflection_spec.rb +5 -0
- data/spec/model/associations_spec.rb +156 -49
- data/spec/model/eager_loading_spec.rb +137 -2
- data/spec/model/model_spec.rb +10 -10
- metadata +15 -2
data/lib/sequel/core.rb
CHANGED
@@ -228,6 +228,19 @@ module Sequel
|
|
228
228
|
def self.quote_identifiers=(value)
|
229
229
|
Database.quote_identifiers = value
|
230
230
|
end
|
231
|
+
|
232
|
+
# Convert each item in the array to the correct type, handling multi-dimensional
|
233
|
+
# arrays. For each element in the array or subarrays, call the converter,
|
234
|
+
# unless the value is nil.
|
235
|
+
def self.recursive_map(array, converter)
|
236
|
+
array.map do |i|
|
237
|
+
if i.is_a?(Array)
|
238
|
+
recursive_map(i, converter)
|
239
|
+
elsif i
|
240
|
+
converter.call(i)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
231
244
|
|
232
245
|
# Require all given +files+ which should be in the same or a subdirectory of
|
233
246
|
# this file. If a +subdir+ is given, assume all +files+ are in that subdir.
|
data/lib/sequel/database/misc.rb
CHANGED
@@ -4,6 +4,28 @@ module Sequel
|
|
4
4
|
# :section: 7 - Miscellaneous methods
|
5
5
|
# These methods don't fit neatly into another category.
|
6
6
|
# ---------------------
|
7
|
+
|
8
|
+
# Hash of extension name symbols to callable objects to load the extension
|
9
|
+
# into the Database object (usually by extending it with a module defined
|
10
|
+
# in the extension).
|
11
|
+
EXTENSIONS = {}
|
12
|
+
|
13
|
+
# Register an extension callback for Database objects. ext should be the
|
14
|
+
# extension name symbol, and mod should either be a Module that the
|
15
|
+
# database is extended with, or a callable object called with the database
|
16
|
+
# object. If mod is not provided, a block can be provided and is treated
|
17
|
+
# as the mod object.
|
18
|
+
def self.register_extension(ext, mod=nil, &block)
|
19
|
+
if mod
|
20
|
+
raise(Error, "cannot provide both mod and block to Database.register_extension") if block
|
21
|
+
if mod.is_a?(Module)
|
22
|
+
block = proc{|db| db.extend(mod)}
|
23
|
+
else
|
24
|
+
block = mod
|
25
|
+
end
|
26
|
+
end
|
27
|
+
Sequel.synchronize{EXTENSIONS[ext] = block}
|
28
|
+
end
|
7
29
|
|
8
30
|
# Converts a uri to an options hash. These options are then passed
|
9
31
|
# to a newly created database object.
|
@@ -107,6 +129,23 @@ module Sequel
|
|
107
129
|
type_literal(:type=>type)
|
108
130
|
end
|
109
131
|
|
132
|
+
# Load an extension into the receiver. In addition to requiring the extension file, this
|
133
|
+
# also modifies the database to work with the extension (usually extending it with a
|
134
|
+
# module defined in the extension file). If no related extension file exists or the
|
135
|
+
# extension does not have specific support for Database objects, an Error will be raised.
|
136
|
+
# Returns self.
|
137
|
+
def extension(*exts)
|
138
|
+
Sequel.extension(*exts)
|
139
|
+
exts.each do |ext|
|
140
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
141
|
+
pr.call(self)
|
142
|
+
else
|
143
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual databases")
|
144
|
+
end
|
145
|
+
end
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
110
149
|
# Convert the given timestamp from the application's timezone,
|
111
150
|
# to the databases's timezone or the default database timezone if
|
112
151
|
# the database does not have a timezone.
|
@@ -362,7 +401,8 @@ module Sequel
|
|
362
401
|
if value.is_a?(SQLTime)
|
363
402
|
value
|
364
403
|
else
|
365
|
-
|
404
|
+
# specifically check for nsec == 0 value to work around JRuby 1.6 ruby 1.9 mode bug
|
405
|
+
SQLTime.create(value.hour, value.min, value.sec, (value.respond_to?(:nsec) && value.nsec != 0) ? value.nsec/1000.0 : value.usec)
|
366
406
|
end
|
367
407
|
when String
|
368
408
|
Sequel.string_to_time(value)
|
@@ -1,20 +1,20 @@
|
|
1
1
|
module Sequel
|
2
2
|
# The Schema module holds the schema generators.
|
3
3
|
module Schema
|
4
|
-
# Schema::
|
4
|
+
# Schema::CreateTableGenerator is an internal class that the user is not expected
|
5
5
|
# to instantiate directly. Instances are created by Database#create_table.
|
6
6
|
# It is used to specify table creation parameters. It takes a Database
|
7
7
|
# object and a block of column/index/constraint specifications, and
|
8
8
|
# gives the Database a table description, which the database uses to
|
9
9
|
# create a table.
|
10
10
|
#
|
11
|
-
# Schema::
|
11
|
+
# Schema::CreateTableGenerator has some methods but also includes method_missing,
|
12
12
|
# allowing users to specify column type as a method instead of using
|
13
13
|
# the column method, which makes for a nicer DSL.
|
14
14
|
#
|
15
15
|
# For more information on Sequel's support for schema modification, see
|
16
16
|
# the {"Migrations and Schema Modification" guide}[link:files/doc/migration_rdoc.html].
|
17
|
-
class
|
17
|
+
class CreateTableGenerator
|
18
18
|
# Classes specifying generic types that Sequel will convert to database-specific types.
|
19
19
|
GENERIC_TYPES=[String, Integer, Fixnum, Bignum, Float, Numeric, BigDecimal,
|
20
20
|
Date, DateTime, Time, File, TrueClass, FalseClass]
|
@@ -255,6 +255,9 @@ module Sequel
|
|
255
255
|
|
256
256
|
add_type_method(*GENERIC_TYPES)
|
257
257
|
end
|
258
|
+
|
259
|
+
# Alias of CreateTableGenerator for backwards compatibility.
|
260
|
+
Generator = CreateTableGenerator
|
258
261
|
|
259
262
|
# Schema::AlterTableGenerator is an internal class that the user is not expected
|
260
263
|
# to instantiate directly. Instances are created by Database#alter_table.
|
@@ -278,7 +281,7 @@ module Sequel
|
|
278
281
|
end
|
279
282
|
|
280
283
|
# Add a column with the given name, type, and opts to the DDL for the table.
|
281
|
-
# See
|
284
|
+
# See CreateTableGenerator#column for the available options.
|
282
285
|
#
|
283
286
|
# add_column(:name, String) # ADD COLUMN name varchar(255)
|
284
287
|
def add_column(name, type, opts = {})
|
@@ -286,7 +289,7 @@ module Sequel
|
|
286
289
|
end
|
287
290
|
|
288
291
|
# Add a constraint with the given name and args to the DDL for the table.
|
289
|
-
# See
|
292
|
+
# See CreateTableGenerator#constraint.
|
290
293
|
#
|
291
294
|
# add_constraint(:valid_name, :name.like('A%'))
|
292
295
|
# # ADD CONSTRAINT valid_name CHECK (name LIKE 'A%')
|
@@ -303,7 +306,7 @@ module Sequel
|
|
303
306
|
end
|
304
307
|
|
305
308
|
# Add a foreign key with the given name and referencing the given table
|
306
|
-
# to the DDL for the table. See
|
309
|
+
# to the DDL for the table. See CreateTableGenerator#column for the available options.
|
307
310
|
#
|
308
311
|
# You can also pass an array of column names for creating composite foreign
|
309
312
|
# keys. In this case, it will assume the columns exist and will only add
|
@@ -314,26 +317,36 @@ module Sequel
|
|
314
317
|
#
|
315
318
|
# add_foreign_key(:artist_id, :table) # ADD COLUMN artist_id integer REFERENCES table
|
316
319
|
# add_foreign_key([:name], :table) # ADD FOREIGN KEY (name) REFERENCES table
|
320
|
+
#
|
321
|
+
# PostgreSQL specific options:
|
322
|
+
#
|
323
|
+
# :not_valid :: Set to true to add the constraint with the NOT VALID syntax.
|
324
|
+
# This makes it so that future inserts must respect referential
|
325
|
+
# integrity, but allows the constraint to be added even if existing
|
326
|
+
# column values reference rows that do not exist. After all the
|
327
|
+
# existing data has been cleaned up, validate_constraint can be used
|
328
|
+
# to mark the constraint as valid. Note that this option only makes
|
329
|
+
# sense when using an array of columns.
|
317
330
|
def add_foreign_key(name, table, opts = {})
|
318
331
|
return add_composite_foreign_key(name, table, opts) if name.is_a?(Array)
|
319
332
|
add_column(name, Integer, {:table=>table}.merge(opts))
|
320
333
|
end
|
321
334
|
|
322
335
|
# Add a full text index on the given columns to the DDL for the table.
|
323
|
-
# See
|
336
|
+
# See CreateTableGenerator#index for available options.
|
324
337
|
def add_full_text_index(columns, opts = {})
|
325
338
|
add_index(columns, {:type=>:full_text}.merge(opts))
|
326
339
|
end
|
327
340
|
|
328
341
|
# Add an index on the given columns to the DDL for the table. See
|
329
|
-
#
|
342
|
+
# CreateTableGenerator#index for available options.
|
330
343
|
#
|
331
344
|
# add_index(:artist_id) # CREATE INDEX table_artist_id_index ON table (artist_id)
|
332
345
|
def add_index(columns, opts = {})
|
333
346
|
@operations << {:op => :add_index, :columns => Array(columns)}.merge(opts)
|
334
347
|
end
|
335
348
|
|
336
|
-
# Add a primary key to the DDL for the table. See
|
349
|
+
# Add a primary key to the DDL for the table. See CreateTableGenerator#column
|
337
350
|
# for the available options. Like +add_foreign_key+, if you specify
|
338
351
|
# the column name as an array, it just creates a constraint:
|
339
352
|
#
|
@@ -346,7 +359,7 @@ module Sequel
|
|
346
359
|
end
|
347
360
|
|
348
361
|
# Add a spatial index on the given columns to the DDL for the table.
|
349
|
-
# See
|
362
|
+
# See CreateTableGenerator#index for available options.
|
350
363
|
def add_spatial_index(columns, opts = {})
|
351
364
|
add_index(columns, {:type=>:spatial}.merge(opts))
|
352
365
|
end
|
@@ -68,12 +68,18 @@ module Sequel
|
|
68
68
|
#
|
69
69
|
# See <tt>Schema::AlterTableGenerator</tt> and the {"Migrations and Schema Modification" guide}[link:files/doc/migration_rdoc.html].
|
70
70
|
def alter_table(name, generator=nil, &block)
|
71
|
-
generator ||=
|
71
|
+
generator ||= alter_table_generator(&block)
|
72
72
|
remove_cached_schema(name)
|
73
73
|
apply_alter_table(name, generator.operations)
|
74
74
|
nil
|
75
75
|
end
|
76
76
|
|
77
|
+
# Return a new Schema::AlterTableGenerator instance with the receiver as
|
78
|
+
# the database and the given block.
|
79
|
+
def alter_table_generator(&block)
|
80
|
+
alter_table_generator_class.new(self, &block)
|
81
|
+
end
|
82
|
+
|
77
83
|
# Create a join table using a hash of foreign keys to referenced
|
78
84
|
# table names. Example:
|
79
85
|
#
|
@@ -146,12 +152,12 @@ module Sequel
|
|
146
152
|
# See <tt>Schema::Generator</tt> and the {"Schema Modification" guide}[link:files/doc/schema_modification_rdoc.html].
|
147
153
|
def create_table(name, options={}, &block)
|
148
154
|
remove_cached_schema(name)
|
149
|
-
options = {:generator=>options} if options.is_a?(Schema::
|
155
|
+
options = {:generator=>options} if options.is_a?(Schema::CreateTableGenerator)
|
150
156
|
if sql = options[:as]
|
151
157
|
raise(Error, "can't provide both :as option and block to create_table") if block
|
152
158
|
create_table_as(name, sql, options)
|
153
159
|
else
|
154
|
-
generator = options[:generator] ||
|
160
|
+
generator = options[:generator] || create_table_generator(&block)
|
155
161
|
create_table_from_generator(name, generator, options)
|
156
162
|
create_table_indexes_from_generator(name, generator, options)
|
157
163
|
nil
|
@@ -181,6 +187,12 @@ module Sequel
|
|
181
187
|
create_table(name, options, &block)
|
182
188
|
end
|
183
189
|
end
|
190
|
+
|
191
|
+
# Return a new Schema::CreateTableGenerator instance with the receiver as
|
192
|
+
# the database and the given block.
|
193
|
+
def create_table_generator(&block)
|
194
|
+
create_table_generator_class.new(self, &block)
|
195
|
+
end
|
184
196
|
|
185
197
|
# Creates a view, replacing it if it already exists:
|
186
198
|
#
|
@@ -324,6 +336,11 @@ module Sequel
|
|
324
336
|
alter_table_sql_list(name, ops).flatten.each{|sql| execute_ddl(sql)}
|
325
337
|
end
|
326
338
|
|
339
|
+
# The class used for alter_table generators.
|
340
|
+
def alter_table_generator_class
|
341
|
+
Schema::AlterTableGenerator
|
342
|
+
end
|
343
|
+
|
327
344
|
# The SQL to execute to modify the DDL for the given table name. op
|
328
345
|
# should be one of the operations returned by the AlterTableGenerator.
|
329
346
|
def alter_table_sql(table, op)
|
@@ -465,6 +482,11 @@ module Sequel
|
|
465
482
|
execute_ddl(create_table_sql(name, generator, options))
|
466
483
|
end
|
467
484
|
|
485
|
+
# The class used for create_table generators.
|
486
|
+
def create_table_generator_class
|
487
|
+
Schema::CreateTableGenerator
|
488
|
+
end
|
489
|
+
|
468
490
|
# Execute the create index statements using the generator.
|
469
491
|
def create_table_indexes_from_generator(name, generator, options)
|
470
492
|
e = options[:ignore_index_errors] || options[:if_not_exists]
|
@@ -621,7 +643,7 @@ module Sequel
|
|
621
643
|
|
622
644
|
# Return true if the given column schema represents an autoincrementing primary key.
|
623
645
|
def schema_autoincrementing_primary_key?(schema)
|
624
|
-
!!schema[:primary_key]
|
646
|
+
!!(schema[:primary_key] && schema[:db_type] =~ /int/io)
|
625
647
|
end
|
626
648
|
|
627
649
|
# The dataset to use for proxying certain schema methods.
|
data/lib/sequel/dataset/graph.rb
CHANGED
@@ -63,6 +63,7 @@ module Sequel
|
|
63
63
|
# determines the alias to use.
|
64
64
|
# :implicit_qualifier :: The qualifier of implicit conditions, see #join_table.
|
65
65
|
# :join_type :: The type of join to use (passed to +join_table+). Defaults to :left_outer.
|
66
|
+
# :qualify:: The type of qualification to do, see #join_table.
|
66
67
|
# :select :: An array of columns to select. When not used, selects
|
67
68
|
# all columns in the given dataset. When set to false, selects no
|
68
69
|
# columns and is like simply joining the tables, though graph keeps
|
@@ -106,7 +107,7 @@ module Sequel
|
|
106
107
|
ds = (!@opts[:graph] && (@opts[:from].length > 1 || @opts[:join])) ? from_self(:alias=>options[:from_self_alias] || first_source) : self
|
107
108
|
|
108
109
|
# Join the table early in order to avoid cloning the dataset twice
|
109
|
-
ds = ds.join_table(options[:join_type] || :left_outer, table, join_conditions, :table_alias=>table_alias, :implicit_qualifier=>options[:implicit_qualifier], &block)
|
110
|
+
ds = ds.join_table(options[:join_type] || :left_outer, table, join_conditions, :table_alias=>table_alias, :implicit_qualifier=>options[:implicit_qualifier], :qualify=>options[:qualify], &block)
|
110
111
|
opts = ds.opts
|
111
112
|
|
112
113
|
# Whether to include the table in the result set
|
data/lib/sequel/dataset/query.rb
CHANGED
@@ -5,6 +5,11 @@ module Sequel
|
|
5
5
|
# These methods all return modified copies of the receiver.
|
6
6
|
# ---------------------
|
7
7
|
|
8
|
+
# Hash of extension name symbols to callable objects to load the extension
|
9
|
+
# into the Dataset object (usually by extending it with a module defined
|
10
|
+
# in the extension).
|
11
|
+
EXTENSIONS = {}
|
12
|
+
|
8
13
|
# The dataset options that require the removal of cached columns
|
9
14
|
# if changed.
|
10
15
|
COLUMN_CHANGE_OPTS = [:select, :sql, :from, :join].freeze
|
@@ -37,6 +42,27 @@ module Sequel
|
|
37
42
|
unlimited unordered where with with_recursive with_sql
|
38
43
|
METHS
|
39
44
|
|
45
|
+
# Register an extension callback for Dataset objects. ext should be the
|
46
|
+
# extension name symbol, and mod should either be a Module that the
|
47
|
+
# dataset is extended with, or a callable object called with the database
|
48
|
+
# object. If mod is not provided, a block can be provided and is treated
|
49
|
+
# as the mod object.
|
50
|
+
#
|
51
|
+
# If mod is a module, this also registers a Database extension that will
|
52
|
+
# extend all of the database's datasets.
|
53
|
+
def self.register_extension(ext, mod=nil, &block)
|
54
|
+
if mod
|
55
|
+
raise(Error, "cannot provide both mod and block to Dataset.register_extension") if block
|
56
|
+
if mod.is_a?(Module)
|
57
|
+
block = proc{|ds| ds.extend(mod)}
|
58
|
+
Sequel::Database.register_extension(ext){|db| db.extend_datasets(mod)}
|
59
|
+
else
|
60
|
+
block = mod
|
61
|
+
end
|
62
|
+
end
|
63
|
+
Sequel.synchronize{EXTENSIONS[ext] = block}
|
64
|
+
end
|
65
|
+
|
40
66
|
# Adds an further filter to an existing filter using AND. If no filter
|
41
67
|
# exists an error is raised. This method is identical to #filter except
|
42
68
|
# it expects an existing filter.
|
@@ -130,6 +156,28 @@ module Sequel
|
|
130
156
|
_filter_or_exclude(true, :where, *cond, &block)
|
131
157
|
end
|
132
158
|
|
159
|
+
# Return a clone of the dataset loaded with the extensions, see #extension!.
|
160
|
+
def extension(*exts)
|
161
|
+
clone.extension!(*exts)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Load an extension into the receiver. In addition to requiring the extension file, this
|
165
|
+
# also modifies the dataset to work with the extension (usually extending it with a
|
166
|
+
# module defined in the extension file). If no related extension file exists or the
|
167
|
+
# extension does not have specific support for Database objects, an Error will be raised.
|
168
|
+
# Returns self.
|
169
|
+
def extension!(*exts)
|
170
|
+
Sequel.extension(*exts)
|
171
|
+
exts.each do |ext|
|
172
|
+
if pr = Sequel.synchronize{EXTENSIONS[ext]}
|
173
|
+
pr.call(self)
|
174
|
+
else
|
175
|
+
raise(Error, "Extension #{ext} does not have specific support handling individual datasets")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
self
|
179
|
+
end
|
180
|
+
|
133
181
|
# Returns a copy of the dataset with the given conditions imposed upon it.
|
134
182
|
# If the query already has a HAVING clause, then the conditions are imposed in the
|
135
183
|
# HAVING clause. If not, then they are imposed in the WHERE clause.
|
@@ -432,6 +480,9 @@ module Sequel
|
|
432
480
|
# to the same table more than once. No alias is used by default.
|
433
481
|
# * :implicit_qualifier - The name to use for qualifying implicit conditions. By default,
|
434
482
|
# the last joined or primary table is used.
|
483
|
+
# * :qualify - Can be set to false to not do any implicit qualification. Can be set
|
484
|
+
# to :deep to use the Qualifier AST Transformer, which will attempt to qualify
|
485
|
+
# subexpressions of the expression tree.
|
435
486
|
# * block - The block argument should only be given if a JOIN with an ON clause is used,
|
436
487
|
# in which case it yields the table alias/name for the table currently being joined,
|
437
488
|
# the table alias/name for the last joined (or first table), and an array of previous
|
@@ -470,6 +521,7 @@ module Sequel
|
|
470
521
|
when Hash
|
471
522
|
table_alias = options[:table_alias]
|
472
523
|
last_alias = options[:implicit_qualifier]
|
524
|
+
qualify_type = options[:qualify]
|
473
525
|
when Symbol, String, SQL::Identifier
|
474
526
|
table_alias = options
|
475
527
|
last_alias = nil
|
@@ -499,8 +551,16 @@ module Sequel
|
|
499
551
|
last_alias ||= @opts[:last_joined_table] || first_source_alias
|
500
552
|
if Sequel.condition_specifier?(expr)
|
501
553
|
expr = expr.collect do |k, v|
|
502
|
-
|
503
|
-
|
554
|
+
case qualify_type
|
555
|
+
when false
|
556
|
+
nil # Do no qualification
|
557
|
+
when :deep
|
558
|
+
k = Sequel::Qualifier.new(self, table_name).transform(k)
|
559
|
+
v = Sequel::Qualifier.new(self, last_alias).transform(v)
|
560
|
+
else
|
561
|
+
k = qualified_column_name(k, table_name) if k.is_a?(Symbol)
|
562
|
+
v = qualified_column_name(v, last_alias) if v.is_a?(Symbol)
|
563
|
+
end
|
504
564
|
[k,v]
|
505
565
|
end
|
506
566
|
expr = SQL::BooleanExpression.from_value_pairs(expr)
|
@@ -1,6 +1,10 @@
|
|
1
|
-
#
|
2
|
-
# Sequel::PrettyTable class
|
3
|
-
#
|
1
|
+
# This _pretty_table extension is only for internal use.
|
2
|
+
# It adds the Sequel::PrettyTable class without modifying
|
3
|
+
# Sequel::Dataset.
|
4
|
+
#
|
5
|
+
# To load the extension:
|
6
|
+
#
|
7
|
+
# Sequel.extension :_pretty_table
|
4
8
|
|
5
9
|
module Sequel
|
6
10
|
module PrettyTable
|
@@ -1,10 +1,8 @@
|
|
1
1
|
# The arbitrary_servers extension allows you to connect to arbitrary
|
2
2
|
# servers/shards that were not defined when you created the database.
|
3
|
-
# To use it, you first
|
4
|
-
# Sequel::ArbitraryServers module:
|
3
|
+
# To use it, you first load the extension into the Database object:
|
5
4
|
#
|
6
|
-
#
|
7
|
-
# DB.pool.extend Sequel::ArbitraryServers
|
5
|
+
# DB.extension :arbitrary_servers
|
8
6
|
#
|
9
7
|
# Then you can pass arbitrary connection options for the server/shard
|
10
8
|
# to use as a hash:
|
@@ -105,4 +103,7 @@ module Sequel
|
|
105
103
|
end
|
106
104
|
end
|
107
105
|
end
|
106
|
+
|
107
|
+
Database.register_extension(:arbitrary_servers){|db| db.pool.extend(ArbitraryServers)}
|
108
108
|
end
|
109
|
+
|
@@ -5,9 +5,17 @@
|
|
5
5
|
# This method is not fool-proof, it's possible that some databases
|
6
6
|
# will use column names that Sequel does not expect.
|
7
7
|
#
|
8
|
-
# To
|
9
|
-
# Sequel::ColumnIntrospection. To enable this for all datasets, run:
|
8
|
+
# To attempt to introspect columns for a single dataset:
|
10
9
|
#
|
10
|
+
# ds.extension(:columns_introspection)
|
11
|
+
#
|
12
|
+
# To attempt to introspect columns for all datasets on a single database:
|
13
|
+
#
|
14
|
+
# DB.extension(:columns_introspection)
|
15
|
+
#
|
16
|
+
# To attempt to introspect columns for all datasets on all databases:
|
17
|
+
#
|
18
|
+
# Sequel.extension :columns_introspection
|
11
19
|
# Sequel::Dataset.introspect_all_columns
|
12
20
|
|
13
21
|
module Sequel
|
@@ -58,4 +66,7 @@ module Sequel
|
|
58
66
|
remove_method(:columns) if instance_methods(false).map{|x| x.to_s}.include?('columns')
|
59
67
|
end
|
60
68
|
end
|
69
|
+
|
70
|
+
Dataset.register_extension(:columns_introspection, Sequel::ColumnsIntrospection)
|
61
71
|
end
|
72
|
+
|