sequel 3.36.1 → 3.37.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (108) hide show
  1. data/CHANGELOG +84 -0
  2. data/Rakefile +13 -0
  3. data/bin/sequel +12 -16
  4. data/doc/advanced_associations.rdoc +36 -67
  5. data/doc/association_basics.rdoc +11 -16
  6. data/doc/release_notes/3.37.0.txt +338 -0
  7. data/doc/schema_modification.rdoc +4 -0
  8. data/lib/sequel/adapters/jdbc/h2.rb +1 -1
  9. data/lib/sequel/adapters/jdbc/postgresql.rb +26 -8
  10. data/lib/sequel/adapters/mysql2.rb +4 -3
  11. data/lib/sequel/adapters/odbc/mssql.rb +2 -2
  12. data/lib/sequel/adapters/postgres.rb +4 -60
  13. data/lib/sequel/adapters/shared/mssql.rb +2 -1
  14. data/lib/sequel/adapters/shared/mysql.rb +0 -5
  15. data/lib/sequel/adapters/shared/postgres.rb +68 -2
  16. data/lib/sequel/adapters/shared/sqlite.rb +17 -1
  17. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +12 -1
  18. data/lib/sequel/adapters/utils/pg_types.rb +76 -0
  19. data/lib/sequel/core.rb +13 -0
  20. data/lib/sequel/database/misc.rb +41 -1
  21. data/lib/sequel/database/schema_generator.rb +23 -10
  22. data/lib/sequel/database/schema_methods.rb +26 -4
  23. data/lib/sequel/dataset/graph.rb +2 -1
  24. data/lib/sequel/dataset/query.rb +62 -2
  25. data/lib/sequel/extensions/_pretty_table.rb +7 -3
  26. data/lib/sequel/extensions/arbitrary_servers.rb +5 -4
  27. data/lib/sequel/extensions/blank.rb +4 -0
  28. data/lib/sequel/extensions/columns_introspection.rb +13 -2
  29. data/lib/sequel/extensions/core_extensions.rb +6 -0
  30. data/lib/sequel/extensions/eval_inspect.rb +158 -0
  31. data/lib/sequel/extensions/inflector.rb +4 -0
  32. data/lib/sequel/extensions/looser_typecasting.rb +5 -4
  33. data/lib/sequel/extensions/migration.rb +4 -1
  34. data/lib/sequel/extensions/named_timezones.rb +4 -0
  35. data/lib/sequel/extensions/null_dataset.rb +4 -0
  36. data/lib/sequel/extensions/pagination.rb +4 -0
  37. data/lib/sequel/extensions/pg_array.rb +219 -168
  38. data/lib/sequel/extensions/pg_array_ops.rb +7 -2
  39. data/lib/sequel/extensions/pg_auto_parameterize.rb +10 -4
  40. data/lib/sequel/extensions/pg_hstore.rb +3 -1
  41. data/lib/sequel/extensions/pg_hstore_ops.rb +7 -2
  42. data/lib/sequel/extensions/pg_inet.rb +28 -3
  43. data/lib/sequel/extensions/pg_interval.rb +192 -0
  44. data/lib/sequel/extensions/pg_json.rb +21 -9
  45. data/lib/sequel/extensions/pg_range.rb +487 -0
  46. data/lib/sequel/extensions/pg_range_ops.rb +122 -0
  47. data/lib/sequel/extensions/pg_statement_cache.rb +3 -2
  48. data/lib/sequel/extensions/pretty_table.rb +12 -1
  49. data/lib/sequel/extensions/query.rb +4 -0
  50. data/lib/sequel/extensions/query_literals.rb +6 -6
  51. data/lib/sequel/extensions/schema_dumper.rb +39 -38
  52. data/lib/sequel/extensions/select_remove.rb +4 -0
  53. data/lib/sequel/extensions/server_block.rb +3 -2
  54. data/lib/sequel/extensions/split_array_nil.rb +65 -0
  55. data/lib/sequel/extensions/sql_expr.rb +4 -0
  56. data/lib/sequel/extensions/string_date_time.rb +4 -0
  57. data/lib/sequel/extensions/thread_local_timezones.rb +9 -3
  58. data/lib/sequel/extensions/to_dot.rb +4 -0
  59. data/lib/sequel/model/associations.rb +150 -91
  60. data/lib/sequel/plugins/identity_map.rb +2 -2
  61. data/lib/sequel/plugins/list.rb +1 -0
  62. data/lib/sequel/plugins/many_through_many.rb +33 -32
  63. data/lib/sequel/plugins/nested_attributes.rb +11 -3
  64. data/lib/sequel/plugins/rcte_tree.rb +2 -2
  65. data/lib/sequel/plugins/schema.rb +1 -1
  66. data/lib/sequel/sql.rb +14 -14
  67. data/lib/sequel/version.rb +2 -2
  68. data/spec/adapters/mysql_spec.rb +25 -0
  69. data/spec/adapters/postgres_spec.rb +572 -28
  70. data/spec/adapters/sqlite_spec.rb +16 -1
  71. data/spec/core/database_spec.rb +61 -2
  72. data/spec/core/dataset_spec.rb +92 -0
  73. data/spec/core/expression_filters_spec.rb +12 -0
  74. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  75. data/spec/extensions/boolean_readers_spec.rb +25 -25
  76. data/spec/extensions/eval_inspect_spec.rb +58 -0
  77. data/spec/extensions/json_serializer_spec.rb +0 -6
  78. data/spec/extensions/list_spec.rb +1 -1
  79. data/spec/extensions/looser_typecasting_spec.rb +7 -7
  80. data/spec/extensions/many_through_many_spec.rb +81 -0
  81. data/spec/extensions/nested_attributes_spec.rb +21 -4
  82. data/spec/extensions/pg_array_ops_spec.rb +1 -11
  83. data/spec/extensions/pg_array_spec.rb +181 -90
  84. data/spec/extensions/pg_auto_parameterize_spec.rb +3 -3
  85. data/spec/extensions/pg_hstore_spec.rb +1 -3
  86. data/spec/extensions/pg_inet_spec.rb +6 -1
  87. data/spec/extensions/pg_interval_spec.rb +73 -0
  88. data/spec/extensions/pg_json_spec.rb +5 -9
  89. data/spec/extensions/pg_range_ops_spec.rb +49 -0
  90. data/spec/extensions/pg_range_spec.rb +372 -0
  91. data/spec/extensions/pg_statement_cache_spec.rb +1 -2
  92. data/spec/extensions/query_literals_spec.rb +1 -2
  93. data/spec/extensions/schema_dumper_spec.rb +48 -89
  94. data/spec/extensions/serialization_spec.rb +1 -5
  95. data/spec/extensions/server_block_spec.rb +2 -2
  96. data/spec/extensions/spec_helper.rb +12 -2
  97. data/spec/extensions/split_array_nil_spec.rb +24 -0
  98. data/spec/integration/associations_test.rb +4 -4
  99. data/spec/integration/database_test.rb +2 -2
  100. data/spec/integration/dataset_test.rb +4 -4
  101. data/spec/integration/eager_loader_test.rb +6 -6
  102. data/spec/integration/plugin_test.rb +2 -2
  103. data/spec/integration/spec_helper.rb +2 -2
  104. data/spec/model/association_reflection_spec.rb +5 -0
  105. data/spec/model/associations_spec.rb +156 -49
  106. data/spec/model/eager_loading_spec.rb +137 -2
  107. data/spec/model/model_spec.rb +10 -10
  108. 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.
@@ -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
- SQLTime.create(value.hour, value.min, value.sec, value.respond_to?(:nsec) ? value.nsec/1000.0 : value.usec)
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::Generator is an internal class that the user is not expected
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::Generator has some methods but also includes method_missing,
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 Generator
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 Generator#column for the available options.
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 Generator#constraint.
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 Generator#column for the available options.
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 Generator#index for available options.
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
- # Generator#index for available options.
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 Generator#column
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 Generator#index for available options.
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 ||= Schema::AlterTableGenerator.new(self, &block)
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::Generator)
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] || Schema::Generator.new(self, &block)
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.
@@ -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
@@ -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
- k = qualified_column_name(k, table_name) if k.is_a?(Symbol)
503
- v = qualified_column_name(v, last_alias) if v.is_a?(Symbol)
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
- # The pretty_table extension adds Sequel::Dataset#print and the
2
- # Sequel::PrettyTable class for creating nice-looking plain-text
3
- # tables.
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 extend the Database's connection pool with the
4
- # Sequel::ArbitraryServers module:
3
+ # To use it, you first load the extension into the Database object:
5
4
  #
6
- # Sequel.extension :arbitrary_servers
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
+
@@ -1,4 +1,8 @@
1
1
  # The blank extension adds the blank? method to all objects (e.g. Object#blank?).
2
+ #
3
+ # To load the extension:
4
+ #
5
+ # Sequel.extension :blank
2
6
 
3
7
  class FalseClass
4
8
  # false is always blank
@@ -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 enable this for a single dataset, extend the dataset with
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
+