sequel 4.11.0 → 4.12.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +32 -0
  3. data/Rakefile +1 -5
  4. data/doc/opening_databases.rdoc +5 -1
  5. data/doc/release_notes/4.12.0.txt +105 -0
  6. data/lib/sequel/adapters/jdbc.rb +1 -0
  7. data/lib/sequel/adapters/oracle.rb +1 -0
  8. data/lib/sequel/adapters/postgres.rb +17 -8
  9. data/lib/sequel/adapters/shared/cubrid.rb +2 -1
  10. data/lib/sequel/adapters/shared/db2.rb +1 -0
  11. data/lib/sequel/adapters/shared/mssql.rb +1 -0
  12. data/lib/sequel/adapters/shared/postgres.rb +23 -2
  13. data/lib/sequel/adapters/shared/sqlanywhere.rb +1 -0
  14. data/lib/sequel/adapters/sqlite.rb +11 -5
  15. data/lib/sequel/database/query.rb +14 -1
  16. data/lib/sequel/dataset/prepared_statements.rb +2 -1
  17. data/lib/sequel/dataset/query.rb +48 -37
  18. data/lib/sequel/dataset/sql.rb +0 -39
  19. data/lib/sequel/extensions/pg_interval.rb +1 -1
  20. data/lib/sequel/extensions/pg_static_cache_updater.rb +11 -5
  21. data/lib/sequel/model/associations.rb +2 -2
  22. data/lib/sequel/plugins/auto_validations.rb +16 -4
  23. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  24. data/lib/sequel/plugins/nested_attributes.rb +72 -59
  25. data/lib/sequel/plugins/prepared_statements.rb +16 -5
  26. data/lib/sequel/plugins/prepared_statements_associations.rb +14 -0
  27. data/lib/sequel/sql.rb +2 -43
  28. data/lib/sequel/version.rb +1 -1
  29. data/spec/adapters/postgres_spec.rb +49 -20
  30. data/spec/bin_spec.rb +2 -2
  31. data/spec/core/dataset_spec.rb +18 -6
  32. data/spec/core/schema_spec.rb +2 -1
  33. data/spec/extensions/auto_validations_spec.rb +23 -2
  34. data/spec/extensions/nested_attributes_spec.rb +32 -1
  35. data/spec/extensions/pg_static_cache_updater_spec.rb +12 -0
  36. data/spec/extensions/prepared_statements_associations_spec.rb +17 -17
  37. data/spec/extensions/prepared_statements_spec.rb +11 -8
  38. data/spec/integration/plugin_test.rb +43 -0
  39. data/spec/integration/schema_test.rb +7 -0
  40. data/spec/model/eager_loading_spec.rb +9 -0
  41. metadata +4 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ced6249de982434d96b02340853663f604357771
4
- data.tar.gz: 2f34bc5dff2cb2e0ffa1c613252291a52a0b5876
3
+ metadata.gz: b15d571f0ccc175749541cfee443b953dcd145fd
4
+ data.tar.gz: 9dec9dd2f6816432f511c0153737646e44da31a1
5
5
  SHA512:
6
- metadata.gz: 8df573b48f64deb1af7958cdf2d09e75a5f8adb2709519e04f51cabc2b18f7b08e3da857261b0faec876e476b1a3bd961517f82d79bfb33ee9a236dfc066d899
7
- data.tar.gz: becb87b9aecc164e06e48a4b5f86eb983ad9e3d09851155f50c935f0e17bccd26d57987dfdcc4635c4531d1cc07a1e753a20998b55c6fa9921e89c58310bc3dd
6
+ metadata.gz: ec94d8b6fcd34fecdb4d4c3cc4f2b4fb0277c8d7289baebde098b8b84cc99ab0bfd0ab28effa316df0a0fbba1a7bf2cc3bc0fbbfc682e68f6d50326652719306
7
+ data.tar.gz: 919e8651ded7808d66e95788af7993c4b13136487bed14b6e12db2150bca22ab166eef6e0eeb5350b2e2aebdb6f72c36f47ef7dfaef4e3eea2170c396f15f02c
data/CHANGELOG CHANGED
@@ -1,3 +1,35 @@
1
+ === 4.12.0 (2014-07-01)
2
+
3
+ * Support :readonly Database option in sqlite adapter (ippeiukai, jeremyevans) (#832)
4
+
5
+ * Automatically setup max_length validations for string columns in the auto_validations plugin (jeremyevans)
6
+
7
+ * Add :max_length entry to column schema hashes for string types (jeremyevans)
8
+
9
+ * Add :before_thread_exit option to Database#listen_for_static_cache_updates in pg_static_cache_updater extension (jeremyevans)
10
+
11
+ * Add Database#values on PostgreSQL to create a dataset that uses VALUES instead of SELECT (jeremyevans)
12
+
13
+ * Add Model#set_nested_attributes to nested_attributes, allowing setting nested attributes options per-call (jeremyevans)
14
+
15
+ * Use explicit columns when using automatically prepared SELECT statements in the prepared statement plugins (jeremyevans)
16
+
17
+ * Make Dataset#insert_select on PostgreSQL respect existing RETURNING clause (jeremyevans)
18
+
19
+ * Fix eager loading limited associations via a UNION when an association block is used (jeremyevans)
20
+
21
+ * Associate reciprocal object before saving associated object when creating new objects in nested_attributes (chanks, jeremyevans) (#831)
22
+
23
+ * Handle intervals containing more than 100 hours in the pg_interval extension's parser (will) (#827)
24
+
25
+ * Remove methods/class deprecated in 4.11.0 (jeremyevans)
26
+
27
+ * Allow Dataset#natural_join/cross_join and related methods to take a options hash passed to join_table (jeremyevans)
28
+
29
+ * Add :reset_implicit_qualifier option to Dataset#join_table, to set false to not reset the implicit qualifier (jeremyevans)
30
+
31
+ * Support :notice_receiver Database option when postgres adapter is used with pg driver (jeltz, jeremyevans) (#825)
32
+
1
33
  === 4.11.0 (2014-06-03)
2
34
 
3
35
  * Add :model_map option to class_table_inheritance plugin so class names don't need to be stored in the database (jeremyevans)
data/Rakefile CHANGED
@@ -33,10 +33,6 @@ RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Sequel: Th
33
33
 
34
34
  begin
35
35
  # Sequel uses hanna-nouveau for the website RDoc.
36
- # Due to bugs in older versions of RDoc, and the
37
- # fact that hanna-nouveau does not support RDoc 4,
38
- # a specific version of rdoc is required.
39
- gem 'rdoc', '= 3.12.2'
40
36
  gem 'hanna-nouveau'
41
37
  RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
42
38
  rescue Gem::LoadError
@@ -68,7 +64,7 @@ if rdoc_task_class
68
64
  rdoc_task_class.new(:website_rdoc_main) do |rdoc|
69
65
  rdoc.rdoc_dir = "www/public/rdoc"
70
66
  rdoc.options += RDOC_OPTS + %w'--no-ignore-invalid'
71
- rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb lib/sequel/extensions/core_extensions.rb"
67
+ rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
72
68
  end
73
69
 
74
70
  rdoc_task_class.new(:website_rdoc_adapters) do |rdoc|
@@ -373,9 +373,12 @@ The following additional options are supported:
373
373
  conversion is done, so an error is raised if you attempt to retrieve an infinite
374
374
  timestamp/date. You can set this to :nil to convert to nil, :string to leave
375
375
  as a string, or :float to convert to an infinite float.
376
- :encoding :: Set the client_encoding to the given string
377
376
  :connect_timeout :: Set the number of seconds to wait for a connection (default 20, only respected
378
377
  if using the pg library).
378
+ :encoding :: Set the client_encoding to the given string
379
+ :notice_receiver :: A proc that be called with the PGresult objects that have notice or warning messages.
380
+ The default notice receiver just prints the messages to stderr, but this can be used
381
+ to handle notice/warning messages differently. Only respected if using the pg library).
379
382
  :sslmode :: Set to 'disable', 'allow', 'prefer', 'require' to choose how to treat SSL (only
380
383
  respected if using the pg library)
381
384
  :use_iso_date_format :: This can be set to false to not force the ISO date format. Sequel forces
@@ -417,6 +420,7 @@ Examples:
417
420
 
418
421
  The following additional options are supported:
419
422
 
423
+ :readonly :: open database in read-only mode
420
424
  :timeout :: the busy timeout to use in milliseconds (default: 5000).
421
425
 
422
426
  === swift
@@ -0,0 +1,105 @@
1
+ = New Features
2
+
3
+ * Database#schema now includes :max_length entries for string
4
+ columns, specifying the size of the string field. The
5
+ auto_validations plugin now uses this information to
6
+ automatically set up max_length validations on those fields.
7
+
8
+ * The Dataset join methods now support a :reset_implicit_qualifier
9
+ option. If set to false, this makes the join not reset the
10
+ implicit qualifier, so that the next join will not consider this
11
+ table as the last table joined. Example:
12
+
13
+ DB[:a].join(:b, :c=>:d).
14
+ join(:e, :f=>:g)
15
+ # SELECT * FROM a
16
+ # INNER JOIN b ON (b.c = a.d)
17
+ # INNER JOIN e ON (e.f = b.g)
18
+
19
+ DB[:a].join(:b, {:c=>:d}, :reset_implicit_qualifier=>false).
20
+ join(:e, :f=>:g)
21
+ # SELECT * FROM a
22
+ # INNER JOIN b ON (b.c = a.d)
23
+ # INNER JOIN e ON (e.f = a.g)
24
+
25
+ * The Dataset cross and natural join methods now accept an options
26
+ hash. Example:
27
+
28
+ DB[:a].cross_join(:b, :table_alias=>:c)
29
+ # SELECT * FROM a CROSS JOIN b AS c
30
+
31
+ * Model#set_nested_attributes has been added to the nested_attributes
32
+ plugin, which allows you to to set the nested_attributes options to
33
+ use per-call. This is very helpful if you have multiple forms that
34
+ handle associated objects, but with different input fields used
35
+ for the associated objects depending on the form. Example:
36
+
37
+ album.set_nested_attributes(:tracks,
38
+ params[:track_attributes],
39
+ :fields=>[:a, :b, :c])
40
+
41
+ * Database#values has been added on PostgreSQL, which creates a
42
+ dataset that uses VALUES instead of SELECT. Just as PostgreSQL
43
+ allows, you can also use orders, limits, and offsets with this
44
+ dataset.
45
+
46
+ * A :notice_receiver option is now supported in the postgres adapter
47
+ if the pg driver is used. This should be a proc, which will be
48
+ passed to the pg connection's set_notice_receiver method.
49
+
50
+ * A Database :readonly option is now supported in the sqlite adapter,
51
+ which opens the database in a read-only mode, causing an error
52
+ if a query is issued that would modify the database.
53
+
54
+ * A :before_thread_exit option has been added to
55
+ Database#listen_for_static_cache_updates in the
56
+ pg_static_cache_updater extension, allowing you to run code before
57
+ the created thread exits.
58
+
59
+ = Other Improvements
60
+
61
+ * Eager loading limited associations using a UNION now works
62
+ correctly when an association block is used. This fixes a
63
+ regression that first occurred in 4.10.0, when the union
64
+ eager loader became the default eager loader.
65
+
66
+ * When creating a new associated object in the nested_attributes
67
+ plugin, where the reciprocal association is a many_to_one
68
+ association, set the cached reciprocal object in the new
69
+ associated object before saving it.
70
+
71
+ This fixes issues when validations in the associated object
72
+ require access to the current object, which may not yet be
73
+ saved in the database.
74
+
75
+ * The prepared_statements and prepared_statements_associations
76
+ plugins now automatically use explicit column references when
77
+ preparing statements. This fixes issues on PostgreSQL when a
78
+ column is added to a table while a prepared statement exists
79
+ that selects * from the table. Previously, all further attempts
80
+ to use the prepared statement will fail.
81
+
82
+ This allows you to run migrations that add columns to tables
83
+ while concurrently running an application that uses the
84
+ prepared statements plugins. Note that many other schema
85
+ modifications can cause issues when running migrations
86
+ while concurrently running an application, but most of those
87
+ are not specific to usage of prepared statements.
88
+
89
+ * Dataset#insert_select on PostgreSQL now respects an existing
90
+ RETURNING clause, and won't override it to use RETURNING *.
91
+
92
+ A similar fix was applied to the generalized prepared statements
93
+ support as well.
94
+
95
+ * The interval parser in the pg_interval extension now supports
96
+ intervals with 2-10 digits for hours. Previously, it only
97
+ supported using 2 digits for hours.
98
+
99
+ = Backwards Compatibility
100
+
101
+ * The methods and classes deprecated in 4.11.0 have been removed.
102
+
103
+ * The nested_attributes internal API has changed significantly. If
104
+ you were calling any private nested_attributes methods, you'll
105
+ probably need to update your code.
@@ -729,6 +729,7 @@ module Sequel
729
729
  metadata(:getColumns, nil, schema, table, nil) do |h|
730
730
  next if schema_parse_table_skip?(h, schema)
731
731
  s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
732
+ s[:max_length] = s[:column_size] if s[:type] == :string
732
733
  if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
733
734
  s[:type] = :integer
734
735
  end
@@ -305,6 +305,7 @@ module Sequel
305
305
  :allow_null => column.nullable?
306
306
  }
307
307
  h[:type] = oracle_column_type(h)
308
+ h[:max_length] = h[:char_size] if h[:type] == :string
308
309
  table_schema << [m.call(column.name), h]
309
310
  end
310
311
  table_schema
@@ -198,12 +198,13 @@ module Sequel
198
198
  # Connects to the database. In addition to the standard database
199
199
  # options, using the :encoding or :charset option changes the
200
200
  # client encoding for the connection, :connect_timeout is a
201
- # connection timeout in seconds, and :sslmode sets whether postgres's
202
- # sslmode. :connect_timeout and :ssl_mode are only supported if the pg
203
- # driver is used.
201
+ # connection timeout in seconds, :sslmode sets whether postgres's
202
+ # sslmode, and :notice_receiver handles server notices in a proc.
203
+ # :connect_timeout, :ssl_mode, and :notice_receiver are only supported
204
+ # if the pg driver is used.
204
205
  def connect(server)
205
206
  opts = server_opts(server)
206
- conn = if SEQUEL_POSTGRES_USES_PG
207
+ if SEQUEL_POSTGRES_USES_PG
207
208
  connection_params = {
208
209
  :host => opts[:host],
209
210
  :port => opts[:port] || 5432,
@@ -213,9 +214,15 @@ module Sequel
213
214
  :connect_timeout => opts[:connect_timeout] || 20,
214
215
  :sslmode => opts[:sslmode]
215
216
  }.delete_if { |key, value| blank_object?(value) }
216
- Adapter.connect(connection_params)
217
+ conn = Adapter.connect(connection_params)
218
+
219
+ conn.instance_variable_set(:@prepared_statements, {})
220
+
221
+ if receiver = opts[:notice_receiver]
222
+ conn.set_notice_receiver(&receiver)
223
+ end
217
224
  else
218
- Adapter.connect(
225
+ conn = Adapter.connect(
219
226
  (opts[:host] unless blank_object?(opts[:host])),
220
227
  opts[:port] || 5432,
221
228
  nil, '',
@@ -224,6 +231,9 @@ module Sequel
224
231
  opts[:password]
225
232
  )
226
233
  end
234
+
235
+ conn.instance_variable_set(:@db, self)
236
+
227
237
  if encoding = opts[:encoding] || opts[:charset]
228
238
  if conn.respond_to?(:set_client_encoding)
229
239
  conn.set_client_encoding(encoding)
@@ -231,8 +241,7 @@ module Sequel
231
241
  conn.async_exec("set client_encoding to '#{encoding}'")
232
242
  end
233
243
  end
234
- conn.instance_variable_set(:@db, self)
235
- conn.instance_variable_set(:@prepared_statements, {}) if SEQUEL_POSTGRES_USES_PG
244
+
236
245
  connection_configuration_sqls.each{|sql| conn.execute(sql)}
237
246
  conn
238
247
  end
@@ -51,12 +51,13 @@ module Sequel
51
51
  from(:db_attribute).
52
52
  where(:class_name=>m2.call(table_name)).
53
53
  order(:def_order).
54
- select(:attr_name, :data_type___db_type, :default_value___default, :is_nullable___allow_null).
54
+ select(:attr_name, :data_type___db_type, :default_value___default, :is_nullable___allow_null, :prec).
55
55
  map do |row|
56
56
  name = m.call(row.delete(:attr_name))
57
57
  row[:allow_null] = row[:allow_null] == 'YES'
58
58
  row[:primary_key] = pks.include?(name)
59
59
  row[:type] = schema_column_type(row[:db_type])
60
+ row[:max_length] = row[:prec] if row[:type] == :string
60
61
  [name, row]
61
62
  end
62
63
  end
@@ -42,6 +42,7 @@ module Sequel
42
42
  column[:allow_null] = column.delete(:nulls) == 'Y'
43
43
  column[:primary_key] = column.delete(:identity) == 'Y' || !column[:keyseq].nil?
44
44
  column[:type] = schema_column_type(column[:db_type])
45
+ column[:max_length] = column[:longlength] if column[:type] == :string
45
46
  [ m.call(column.delete(:name)), column]
46
47
  end
47
48
  end
@@ -457,6 +457,7 @@ module Sequel
457
457
  else
458
458
  schema_column_type(row[:db_type])
459
459
  end
460
+ row[:max_length] = row[:max_chars] if row[:type] == :string
460
461
  [m.call(row.delete(:column)), row]
461
462
  end
462
463
  end
@@ -524,6 +524,17 @@ module Sequel
524
524
  @supported_types.fetch(type){@supported_types[type] = (from(:pg_type).filter(:typtype=>'b', :typname=>type.to_s).count > 0)}
525
525
  end
526
526
 
527
+ # Creates a dataset that uses the VALUES clause:
528
+ #
529
+ # DB.values([[1, 2], [3, 4]])
530
+ # VALUES ((1, 2), (3, 4))
531
+ #
532
+ # DB.values([[1, 2], [3, 4]]).order(:column2).limit(1, 1)
533
+ # VALUES ((1, 2), (3, 4)) ORDER BY column2 LIMIT 1 OFFSET 1
534
+ def values(v)
535
+ @default_dataset.clone(:values=>v)
536
+ end
537
+
527
538
  # Array of symbols specifying view names in the current database.
528
539
  #
529
540
  # Options:
@@ -1147,12 +1158,13 @@ module Sequel
1147
1158
  CRLF = "\r\n".freeze
1148
1159
  BLOB_RE = /[\000-\037\047\134\177-\377]/n.freeze
1149
1160
  WINDOW = " WINDOW ".freeze
1161
+ SELECT_VALUES = "VALUES ".freeze
1150
1162
  EMPTY_STRING = ''.freeze
1151
1163
  LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each{|s| s.freeze}
1152
1164
 
1153
1165
  Dataset.def_sql_method(self, :delete, [['if server_version >= 90100', %w'with delete from using where returning'], ['else', %w'delete from using where returning']])
1154
1166
  Dataset.def_sql_method(self, :insert, [['if server_version >= 90100', %w'with insert into columns values returning'], ['else', %w'insert into columns values returning']])
1155
- Dataset.def_sql_method(self, :select, [['if server_version >= 80400', %w'with select distinct columns from join where group having window compounds order limit lock'], ['else', %w'select distinct columns from join where group having compounds order limit lock']])
1167
+ Dataset.def_sql_method(self, :select, [['if opts[:values]', %w'values order limit'], ['elsif server_version >= 80400', %w'with select distinct columns from join where group having window compounds order limit lock'], ['else', %w'select distinct columns from join where group having compounds order limit lock']])
1156
1168
  Dataset.def_sql_method(self, :update, [['if server_version >= 90100', %w'with update table set from where returning'], ['else', %w'update table set from where returning']])
1157
1169
 
1158
1170
  # Shared methods for prepared statements when used with PostgreSQL databases.
@@ -1285,7 +1297,10 @@ module Sequel
1285
1297
  # Insert a record returning the record inserted. Always returns nil without
1286
1298
  # inserting a query if disable_insert_returning is used.
1287
1299
  def insert_select(*values)
1288
- returning.insert(*values){|r| return r} unless @opts[:disable_insert_returning]
1300
+ unless @opts[:disable_insert_returning]
1301
+ ds = opts[:returning] ? self : returning
1302
+ ds.insert(*values){|r| return r}
1303
+ end
1289
1304
  end
1290
1305
 
1291
1306
  # Locks all tables in the dataset's FROM clause (but not in JOINs) with
@@ -1510,6 +1525,12 @@ module Sequel
1510
1525
  @opts[:lock] == :share ? (sql << FOR_SHARE) : super
1511
1526
  end
1512
1527
 
1528
+ # Support VALUES clause instead of the SELECT clause to return rows.
1529
+ def select_values_sql(sql)
1530
+ sql << SELECT_VALUES
1531
+ expression_list_append(sql, opts[:values])
1532
+ end
1533
+
1513
1534
  # SQL fragment for named window specifications
1514
1535
  def select_window_sql(sql)
1515
1536
  if ws = @opts[:window]
@@ -66,6 +66,7 @@ module Sequel
66
66
  else
67
67
  schema_column_type(row[:db_type])
68
68
  end
69
+ row[:max_length] = row[:width] if row[:type] == :string
69
70
  [m.call(row.delete(:name)), row]
70
71
  end
71
72
  end
@@ -91,14 +91,20 @@ module Sequel
91
91
  # The conversion procs to use for this database
92
92
  attr_reader :conversion_procs
93
93
 
94
- # Connect to the database. Since SQLite is a file based database,
95
- # the only options available are :database (to specify the database
96
- # name), and :timeout, to specify how long to wait for the database to
97
- # be available if it is locked, given in milliseconds (default is 5000).
94
+ # Connect to the database. Since SQLite is a file based database,
95
+ # available options are limited:
96
+ #
97
+ # :database :: database name (filename or ':memory:' or file: URI)
98
+ # :readonly :: open database in read-only mode; useful for reading
99
+ # static data that you do not want to modify
100
+ # :timeout :: how long to wait for the database to be available if it
101
+ # is locked, given in milliseconds (default is 5000)
98
102
  def connect(server)
99
103
  opts = server_opts(server)
100
104
  opts[:database] = ':memory:' if blank_object?(opts[:database])
101
- db = ::SQLite3::Database.new(opts[:database])
105
+ sqlite3_opts = {}
106
+ sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly)
107
+ db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts)
102
108
  db.busy_timeout(opts.fetch(:timeout, 5000))
103
109
 
104
110
  connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
@@ -157,7 +157,12 @@ module Sequel
157
157
 
158
158
  cols = schema_parse_table(table_name, opts)
159
159
  raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.nil? || cols.empty?
160
- cols.each{|_,c| c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type])}
160
+ cols.each do |_,c|
161
+ c[:ruby_default] = column_schema_to_ruby_default(c[:default], c[:type])
162
+ if !c[:max_length] && c[:type] == :string && (max_length = column_schema_max_length(c[:db_type]))
163
+ c[:max_length] = max_length
164
+ end
165
+ end
161
166
  Sequel.synchronize{@schemas[quoted_name] = cols} if cache_schema
162
167
  cols
163
168
  end
@@ -251,6 +256,14 @@ module Sequel
251
256
  column_schema_default_to_ruby_value(default, type) rescue nil
252
257
  end
253
258
 
259
+ # Look at the db_type and guess the maximum length of the column.
260
+ # This assumes types such as varchar(255).
261
+ def column_schema_max_length(db_type)
262
+ if db_type =~ /\((\d+)\)/
263
+ $1.to_i
264
+ end
265
+ end
266
+
254
267
  # Return a Method object for the dataset's output_identifier_method.
255
268
  # Used in metadata parsing to make sure the returned information is in the
256
269
  # correct format.
@@ -86,7 +86,8 @@ module Sequel
86
86
  when :first
87
87
  clone(:limit=>1).select_sql
88
88
  when :insert_select
89
- returning.insert_sql(*@prepared_modify_values)
89
+ ds = opts[:returning] ? self : returning
90
+ ds.insert_sql(*@prepared_modify_values)
90
91
  when :insert
91
92
  insert_sql(*@prepared_modify_values)
92
93
  when :update
@@ -23,10 +23,9 @@ module Sequel
23
23
  # block from the method call.
24
24
  CONDITIONED_JOIN_TYPES = [:inner, :full_outer, :right_outer, :left_outer, :full, :right, :left]
25
25
 
26
- # These symbols have _join methods created (e.g. natural_join) that
27
- # call join_table with the symbol. They only accept a single table
28
- # argument which is passed to join_table, and they raise an error
29
- # if called with a block.
26
+ # These symbols have _join methods created (e.g. natural_join).
27
+ # They accept a table argument and options hash which is passed to join_table,
28
+ # and they raise an error if called with a block.
30
29
  UNCONDITIONED_JOIN_TYPES = [:natural, :natural_left, :natural_right, :natural_full, :cross]
31
30
 
32
31
  # All methods that return modified datasets with a joined table added.
@@ -387,37 +386,42 @@ module Sequel
387
386
  #
388
387
  # Takes the following arguments:
389
388
  #
390
- # * type - The type of join to do (e.g. :inner)
391
- # * table - Depends on type:
392
- # * Dataset - a subselect is performed with an alias of tN for some value of N
393
- # * String, Symbol: table
394
- # * expr - specifies conditions, depends on type:
395
- # * Hash, Array of two element arrays - Assumes key (1st arg) is column of joined table (unless already
396
- # qualified), and value (2nd arg) is column of the last joined or primary table (or the
397
- # :implicit_qualifier option).
398
- # To specify multiple conditions on a single joined table column, you must use an array.
399
- # Uses a JOIN with an ON clause.
400
- # * Array - If all members of the array are symbols, considers them as columns and
401
- # uses a JOIN with a USING clause. Most databases will remove duplicate columns from
402
- # the result set if this is used.
403
- # * nil - If a block is not given, doesn't use ON or USING, so the JOIN should be a NATURAL
404
- # or CROSS join. If a block is given, uses an ON clause based on the block, see below.
405
- # * Everything else - pretty much the same as a using the argument in a call to where,
406
- # so strings are considered literal, symbols specify boolean columns, and Sequel
407
- # expressions can be used. Uses a JOIN with an ON clause.
408
- # * options - a hash of options, with any of the following keys:
409
- # * :table_alias - the name of the table's alias when joining, necessary for joining
410
- # to the same table more than once. No alias is used by default.
411
- # * :implicit_qualifier - The name to use for qualifying implicit conditions. By default,
412
- # the last joined or primary table is used.
413
- # * :qualify - Can be set to false to not do any implicit qualification. Can be set
414
- # to :deep to use the Qualifier AST Transformer, which will attempt to qualify
415
- # subexpressions of the expression tree. Can be set to :symbol to only qualify
416
- # symbols. Defaults to the value of default_join_table_qualification.
417
- # * block - The block argument should only be given if a JOIN with an ON clause is used,
418
- # in which case it yields the table alias/name for the table currently being joined,
419
- # the table alias/name for the last joined (or first table), and an array of previous
420
- # SQL::JoinClause. Unlike +where+, this block is not treated as a virtual row block.
389
+ # type :: The type of join to do (e.g. :inner)
390
+ # table :: table to join into the current dataset. Generally one of the following types:
391
+ # String, Symbol :: identifier used as table or view name
392
+ # Dataset :: a subselect is performed with an alias of tN for some value of N
393
+ # SQL::Function :: set returning function
394
+ # SQL::AliasedExpression :: already aliased expression. Uses given alias unless
395
+ # overridden by the :table_alias option.
396
+ # expr :: conditions used when joining, depends on type:
397
+ # Hash, Array of pairs :: Assumes key (1st arg) is column of joined table (unless already
398
+ # qualified), and value (2nd arg) is column of the last joined or
399
+ # primary table (or the :implicit_qualifier option).
400
+ # To specify multiple conditions on a single joined table column,
401
+ # you must use an array. Uses a JOIN with an ON clause.
402
+ # Array :: If all members of the array are symbols, considers them as columns and
403
+ # uses a JOIN with a USING clause. Most databases will remove duplicate columns from
404
+ # the result set if this is used.
405
+ # nil :: If a block is not given, doesn't use ON or USING, so the JOIN should be a NATURAL
406
+ # or CROSS join. If a block is given, uses an ON clause based on the block, see below.
407
+ # otherwise :: Treats the argument as a filter expression, so strings are considered literal, symbols
408
+ # specify boolean columns, and Sequel expressions can be used. Uses a JOIN with an ON clause.
409
+ # options :: a hash of options, with the following keys supported:
410
+ # :table_alias :: Override the table alias used when joining. In general you shouldn't use this
411
+ # option, you should provide the appropriate SQL::AliasedExpression as the table
412
+ # argument.
413
+ # :implicit_qualifier :: The name to use for qualifying implicit conditions. By default,
414
+ # the last joined or primary table is used.
415
+ # :reset_implicit_qualifier :: Can set to false to ignore this join when future joins determine qualifier
416
+ # for implicit conditions.
417
+ # :qualify :: Can be set to false to not do any implicit qualification. Can be set
418
+ # to :deep to use the Qualifier AST Transformer, which will attempt to qualify
419
+ # subexpressions of the expression tree. Can be set to :symbol to only qualify
420
+ # symbols. Defaults to the value of default_join_table_qualification.
421
+ # block :: The block argument should only be given if a JOIN with an ON clause is used,
422
+ # in which case it yields the table alias/name for the table currently being joined,
423
+ # the table alias/name for the last joined (or first table), and an array of previous
424
+ # SQL::JoinClause. Unlike +where+, this block is not treated as a virtual row block.
421
425
  #
422
426
  # Examples:
423
427
  #
@@ -505,7 +509,8 @@ module Sequel
505
509
  SQL::JoinOnClause.new(expr, type, table_expr)
506
510
  end
507
511
 
508
- opts = {:join => (@opts[:join] || []) + [join], :last_joined_table => table_name}
512
+ opts = {:join => (@opts[:join] || []) + [join]}
513
+ opts[:last_joined_table] = table_name unless options[:reset_implicit_qualifier] == false
509
514
  opts[:num_dataset_sources] = table_alias_num if table_alias_num
510
515
  clone(opts)
511
516
  end
@@ -514,7 +519,13 @@ module Sequel
514
519
  class_eval("def #{jtype}_join(*args, &block); join_table(:#{jtype}, *args, &block) end", __FILE__, __LINE__)
515
520
  end
516
521
  UNCONDITIONED_JOIN_TYPES.each do |jtype|
517
- class_eval("def #{jtype}_join(table); raise(Sequel::Error, '#{jtype}_join does not accept join table blocks') if block_given?; join_table(:#{jtype}, table) end", __FILE__, __LINE__)
522
+ class_eval(<<-END, __FILE__, __LINE__+1)
523
+ def #{jtype}_join(table, opts=Sequel::OPTS)
524
+ raise(Sequel::Error, '#{jtype}_join does not accept join table blocks') if block_given?
525
+ raise(Sequel::Error, '#{jtype}_join 2nd argument should be an options hash, not conditions') unless opts.is_a?(Hash)
526
+ join_table(:#{jtype}, table, nil, opts)
527
+ end
528
+ END
518
529
  end
519
530
 
520
531
  # Marks this dataset as a lateral dataset. If used in another dataset's FROM