sequel 2.12.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. data/CHANGELOG +62 -0
  2. data/README.rdoc +3 -3
  3. data/Rakefile +7 -0
  4. data/doc/advanced_associations.rdoc +44 -0
  5. data/doc/release_notes/3.0.0.txt +221 -0
  6. data/lib/sequel/adapters/amalgalite.rb +208 -0
  7. data/lib/sequel/adapters/db2.rb +3 -0
  8. data/lib/sequel/adapters/dbi.rb +9 -0
  9. data/lib/sequel/adapters/do.rb +0 -4
  10. data/lib/sequel/adapters/firebird.rb +16 -18
  11. data/lib/sequel/adapters/informix.rb +5 -3
  12. data/lib/sequel/adapters/jdbc.rb +24 -20
  13. data/lib/sequel/adapters/jdbc/h2.rb +15 -4
  14. data/lib/sequel/adapters/mysql.rb +4 -8
  15. data/lib/sequel/adapters/odbc.rb +0 -4
  16. data/lib/sequel/adapters/oracle.rb +0 -4
  17. data/lib/sequel/adapters/shared/mssql.rb +16 -5
  18. data/lib/sequel/adapters/shared/mysql.rb +87 -86
  19. data/lib/sequel/adapters/shared/oracle.rb +92 -3
  20. data/lib/sequel/adapters/shared/postgres.rb +85 -29
  21. data/lib/sequel/adapters/shared/progress.rb +8 -3
  22. data/lib/sequel/adapters/shared/sqlite.rb +53 -23
  23. data/lib/sequel/adapters/sqlite.rb +4 -7
  24. data/lib/sequel/adapters/utils/unsupported.rb +3 -3
  25. data/lib/sequel/connection_pool.rb +18 -25
  26. data/lib/sequel/core.rb +2 -21
  27. data/lib/sequel/database.rb +60 -44
  28. data/lib/sequel/database/schema_generator.rb +26 -31
  29. data/lib/sequel/database/schema_methods.rb +8 -3
  30. data/lib/sequel/database/schema_sql.rb +114 -28
  31. data/lib/sequel/dataset.rb +14 -41
  32. data/lib/sequel/dataset/convenience.rb +31 -54
  33. data/lib/sequel/dataset/graph.rb +7 -13
  34. data/lib/sequel/dataset/sql.rb +43 -54
  35. data/lib/sequel/extensions/inflector.rb +0 -5
  36. data/lib/sequel/extensions/schema_dumper.rb +238 -0
  37. data/lib/sequel/metaprogramming.rb +0 -20
  38. data/lib/sequel/model.rb +1 -2
  39. data/lib/sequel/model/base.rb +18 -16
  40. data/lib/sequel/model/inflections.rb +6 -9
  41. data/lib/sequel/plugins/caching.rb +0 -6
  42. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  43. data/lib/sequel/sql.rb +2 -0
  44. data/lib/sequel/version.rb +2 -2
  45. data/spec/adapters/firebird_spec.rb +35 -8
  46. data/spec/adapters/mysql_spec.rb +173 -266
  47. data/spec/adapters/oracle_spec.rb +13 -0
  48. data/spec/adapters/postgres_spec.rb +127 -227
  49. data/spec/adapters/sqlite_spec.rb +13 -171
  50. data/spec/core/connection_pool_spec.rb +15 -4
  51. data/spec/core/core_sql_spec.rb +14 -170
  52. data/spec/core/database_spec.rb +50 -132
  53. data/spec/core/dataset_spec.rb +47 -930
  54. data/spec/core/expression_filters_spec.rb +12 -0
  55. data/spec/core/schema_generator_spec.rb +37 -45
  56. data/spec/core/schema_spec.rb +26 -16
  57. data/spec/core/spec_helper.rb +0 -25
  58. data/spec/extensions/inflector_spec.rb +0 -3
  59. data/spec/extensions/schema_dumper_spec.rb +292 -0
  60. data/spec/extensions/serialization_spec.rb +9 -0
  61. data/spec/extensions/single_table_inheritance_spec.rb +6 -1
  62. data/spec/extensions/spec_helper.rb +1 -3
  63. data/spec/extensions/validation_helpers_spec.rb +4 -4
  64. data/spec/integration/database_test.rb +18 -0
  65. data/spec/integration/dataset_test.rb +112 -1
  66. data/spec/integration/eager_loader_test.rb +70 -9
  67. data/spec/integration/prepared_statement_test.rb +2 -2
  68. data/spec/integration/schema_test.rb +76 -27
  69. data/spec/integration/spec_helper.rb +0 -14
  70. data/spec/integration/transaction_test.rb +27 -0
  71. data/spec/model/associations_spec.rb +0 -36
  72. data/spec/model/base_spec.rb +18 -123
  73. data/spec/model/hooks_spec.rb +2 -235
  74. data/spec/model/inflector_spec.rb +15 -115
  75. data/spec/model/model_spec.rb +0 -120
  76. data/spec/model/plugins_spec.rb +0 -70
  77. data/spec/model/record_spec.rb +35 -93
  78. data/spec/model/spec_helper.rb +0 -27
  79. data/spec/model/validations_spec.rb +0 -931
  80. metadata +9 -14
  81. data/lib/sequel/deprecated.rb +0 -593
  82. data/lib/sequel/deprecated_migration.rb +0 -91
  83. data/lib/sequel/model/deprecated.rb +0 -204
  84. data/lib/sequel/model/deprecated_hooks.rb +0 -103
  85. data/lib/sequel/model/deprecated_inflector.rb +0 -335
  86. data/lib/sequel/model/deprecated_validations.rb +0 -388
  87. data/spec/core/core_ext_spec.rb +0 -156
  88. data/spec/core/migration_spec.rb +0 -263
  89. data/spec/core/pretty_table_spec.rb +0 -58
  90. data/spec/model/caching_spec.rb +0 -217
  91. data/spec/model/schema_spec.rb +0 -92
@@ -53,10 +53,15 @@ module Sequel
53
53
  # index :title
54
54
  # end
55
55
  #
56
+ # Options:
57
+ # * :temp - Create the table as a temporary table.
58
+ #
56
59
  # See Schema::Generator.
57
60
  def create_table(name, options={}, &block)
58
61
  options = {:generator=>options} if options.is_a?(Schema::Generator)
59
- create_table_sql_list(name, *((options[:generator] || Schema::Generator.new(self, &block)).create_info << options)).flatten.each {|sql| execute_ddl(sql)}
62
+ generator = options[:generator] || Schema::Generator.new(self, &block)
63
+ execute_ddl(create_table_sql(name, generator, options))
64
+ index_sql_list(name, generator.indexes).each{|sql| execute_ddl(sql)}
60
65
  end
61
66
 
62
67
  # Forcibly creates a table, attempting to drop it unconditionally (and catching any errors), then creating it.
@@ -99,8 +104,8 @@ module Sequel
99
104
  # DB.drop_index :posts, [:author, :title]
100
105
  #
101
106
  # See alter_table.
102
- def drop_index(table, columns)
103
- alter_table(table) {drop_index(columns)}
107
+ def drop_index(table, columns, options={})
108
+ alter_table(table){drop_index(columns, options)}
104
109
  end
105
110
 
106
111
  # Drops one or more tables corresponding to the given names:
@@ -10,12 +10,7 @@ module Sequel
10
10
  RESTRICT = 'RESTRICT'.freeze
11
11
  SET_DEFAULT = 'SET DEFAULT'.freeze
12
12
  SET_NULL = 'SET NULL'.freeze
13
- TYPES = Hash.new {|h, k| k}
14
- TYPES.merge!(:double=>'double precision', String=>'varchar(255)',
15
- Integer=>'integer', Fixnum=>'integer', Bignum=>'bigint',
16
- Float=>'double precision', BigDecimal=>'numeric', Numeric=>'numeric',
17
- Date=>'date', DateTime=>'timestamp', Time=>'timestamp', File=>'blob',
18
- TrueClass=>'boolean', FalseClass=>'boolean')
13
+ TEMPORARY = 'TEMPORARY '.freeze
19
14
  UNDERSCORE = '_'.freeze
20
15
  UNIQUE = ' UNIQUE'.freeze
21
16
  UNSIGNED = ' UNSIGNED'.freeze
@@ -72,7 +67,6 @@ module Sequel
72
67
 
73
68
  # SQL DDL fragment containing the column creation SQL for the given column.
74
69
  def column_definition_sql(column)
75
- return constraint_definition_sql(column) if column[:type] == :check
76
70
  sql = "#{quote_identifier(column[:name])} #{type_literal(column)}"
77
71
  sql << UNIQUE if column[:unique]
78
72
  sql << NOT_NULL if column[:null] == false
@@ -86,8 +80,8 @@ module Sequel
86
80
 
87
81
  # SQL DDL fragment containing the column creation
88
82
  # SQL for all given columns, used inside a CREATE TABLE block.
89
- def column_list_sql(columns)
90
- columns.map{|c| column_definition_sql(c)}.join(COMMA_SEPARATOR)
83
+ def column_list_sql(generator)
84
+ (generator.columns.map{|c| column_definition_sql(c)} + generator.constraints.map{|c| constraint_definition_sql(c)}).join(COMMA_SEPARATOR)
91
85
  end
92
86
 
93
87
  # SQL DDL fragment for column foreign key references
@@ -102,7 +96,10 @@ module Sequel
102
96
  # SQL DDL fragment specifying a constraint on a table.
103
97
  def constraint_definition_sql(constraint)
104
98
  sql = constraint[:name] ? "CONSTRAINT #{quote_identifier(constraint[:name])} " : ""
105
- case constraint[:constraint_type]
99
+ case constraint[:type]
100
+ when :check
101
+ check = constraint[:check]
102
+ sql << "CHECK #{filter_expr((check.is_a?(Array) && check.length == 1) ? check.first : check)}"
106
103
  when :primary_key
107
104
  sql << "PRIMARY KEY #{literal(constraint[:columns])}"
108
105
  when :foreign_key
@@ -111,21 +108,16 @@ module Sequel
111
108
  when :unique
112
109
  sql << "UNIQUE #{literal(constraint[:columns])}"
113
110
  else
114
- check = constraint[:check]
115
- sql << "CHECK #{filter_expr((check.is_a?(Array) && check.length == 1) ? check.first : check)}"
111
+ raise Error, "Invalid constriant type #{constraint[:type]}, should be :check, :primary_key, :foreign_key, or :unique"
116
112
  end
117
113
  sql
118
114
  end
119
115
 
120
- # Array of SQL DDL statements, the first for creating a table with the given
121
- # name and column specifications, and the others for specifying indexes on
122
- # the table.
123
- def create_table_sql_list(name, columns, indexes = nil, options = {})
124
- sql = ["CREATE TABLE #{quote_schema_table(name)} (#{column_list_sql(columns)})"]
125
- sql.concat(index_list_sql_list(name, indexes)) if indexes && !indexes.empty?
126
- sql
116
+ # DDL statement for creating a table with the given name, columns, and options
117
+ def create_table_sql(name, generator, options)
118
+ "CREATE #{temporary_table_sql if options[:temp]}TABLE #{quote_schema_table(name)} (#{column_list_sql(generator)})"
127
119
  end
128
-
120
+
129
121
  # Default index name for the table and columns, may be too long
130
122
  # for certain databases.
131
123
  def default_index_name(table_name, columns)
@@ -163,7 +155,7 @@ module Sequel
163
155
 
164
156
  # Array of SQL DDL statements, one for each index specification,
165
157
  # for the given table.
166
- def index_list_sql_list(table_name, indexes)
158
+ def index_sql_list(table_name, indexes)
167
159
  indexes.map{|i| index_definition_sql(table_name, i)}
168
160
  end
169
161
 
@@ -207,18 +199,112 @@ module Sequel
207
199
  "ALTER TABLE #{quote_schema_table(name)} RENAME TO #{quote_schema_table(new_name)}"
208
200
  end
209
201
 
202
+ # SQL DDL fragment for temporary table
203
+ def temporary_table_sql
204
+ self.class.const_get(:TEMPORARY)
205
+ end
206
+
210
207
  # SQL fragment specifying the type of a given column.
211
208
  def type_literal(column)
212
- type = type_literal_base(column)
209
+ column[:type].is_a?(Class) ? type_literal_generic(column) : type_literal_specific(column)
210
+ end
211
+
212
+ # SQL fragment specifying the full type of a column,
213
+ # consider the type with possible modifiers.
214
+ def type_literal_generic(column)
215
+ meth = "type_literal_generic_#{column[:type].name.to_s.downcase}"
216
+ if respond_to?(meth, true)
217
+ send(meth, column)
218
+ else
219
+ raise Error, "Unsupported ruby class used as database type: #{column[:type]}"
220
+ end
221
+ end
222
+
223
+ # Alias for type_literal_generic_numeric, to make overriding in a subclass easier.
224
+ def type_literal_generic_bigdecimal(column)
225
+ type_literal_generic_numeric(column)
226
+ end
227
+
228
+ # Sequel uses the bigint type by default for Bignums.
229
+ def type_literal_generic_bignum(column)
230
+ :bigint
231
+ end
232
+
233
+ # Sequel uses the date type by default for Dates.
234
+ def type_literal_generic_date(column)
235
+ :date
236
+ end
237
+
238
+ # Sequel uses the timestamp type by default for DateTimes.
239
+ def type_literal_generic_datetime(column)
240
+ :timestamp
241
+ end
242
+
243
+ # Alias for type_literal_generic_trueclass, to make overriding in a subclass easier.
244
+ def type_literal_generic_falseclass(column)
245
+ type_literal_generic_trueclass(column)
246
+ end
247
+
248
+ # Sequel uses the blob type by default for Files.
249
+ def type_literal_generic_file(column)
250
+ :blob
251
+ end
252
+
253
+ # Alias for type_literal_generic_integer, to make overriding in a subclass easier.
254
+ def type_literal_generic_fixnum(column)
255
+ type_literal_generic_integer(column)
256
+ end
257
+
258
+ # Sequel uses the double precision type by default for Floats.
259
+ def type_literal_generic_float(column)
260
+ :"double precision"
261
+ end
262
+
263
+ # Sequel uses the integer type by default for integers
264
+ def type_literal_generic_integer(column)
265
+ :integer
266
+ end
267
+
268
+ # Sequel uses the numeric type by default for Numerics and BigDecimals.
269
+ # If a size is given, it is used, otherwise, it will default to whatever
270
+ # the database default is for an unsized value.
271
+ def type_literal_generic_numeric(column)
272
+ column[:size] ? "numeric(#{Array(column[:size]).join(', ')})" : :numeric
273
+ end
274
+
275
+ # Sequel uses the varchar type by default for Strings. If a
276
+ # size isn't present, Sequel assumes a size of 255. If the
277
+ # :fixed option is used, Sequel uses the char type. If the
278
+ # :text option is used, Sequel uses the :text type.
279
+ def type_literal_generic_string(column)
280
+ if column[:text]
281
+ :text
282
+ elsif column[:fixed]
283
+ "char(#{column[:size]||255})"
284
+ else
285
+ "varchar(#{column[:size]||255})"
286
+ end
287
+ end
288
+
289
+ # Sequel uses the timestamp type by default for Time values.
290
+ # If the :only_time option is used, the time type is used.
291
+ def type_literal_generic_time(column)
292
+ column[:only_time] ? :time : :timestamp
293
+ end
294
+
295
+ # Sequel uses the boolean type by default for TrueClass and FalseClass.
296
+ def type_literal_generic_trueclass(column)
297
+ :boolean
298
+ end
299
+
300
+ # SQL fragment for the given type of a column if the column is not one of the
301
+ # generic types specified with a ruby class.
302
+ def type_literal_specific(column)
303
+ type = column[:type]
304
+ type = "double precision" if type.to_s == 'double'
213
305
  column[:size] ||= 255 if type.to_s == 'varchar'
214
306
  elements = column[:size] || column[:elements]
215
307
  "#{type}#{literal(Array(elements)) if elements}#{UNSIGNED if column[:unsigned]}"
216
308
  end
217
-
218
- # SQL fragment specifying the base type of a given column,
219
- # without the size or elements.
220
- def type_literal_base(column)
221
- TYPES[column[:type]]
222
- end
223
309
  end
224
310
  end
@@ -87,7 +87,6 @@ module Sequel
87
87
  @identifier_output_method = db.identifier_output_method if db.respond_to?(:identifier_output_method)
88
88
  @opts = opts || {}
89
89
  @row_proc = nil
90
- @transform = nil
91
90
  end
92
91
 
93
92
  ### Class Methods ###
@@ -118,10 +117,9 @@ module Sequel
118
117
 
119
118
  # Returns an array with all records in the dataset. If a block is given,
120
119
  # the array is iterated over after all items have been loaded.
121
- def all(opts = (defarg=true;nil), &block)
122
- Deprecation.deprecate("Calling Dataset#all with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).all.") unless defarg
120
+ def all(&block)
123
121
  a = []
124
- defarg ? each{|r| a << r} : each(opts){|r| a << r}
122
+ each{|r| a << r}
125
123
  post_load(a)
126
124
  a.each(&block) if block
127
125
  a
@@ -170,24 +168,21 @@ module Sequel
170
168
 
171
169
  # Deletes the records in the dataset. The returned value is generally the
172
170
  # number of records deleted, but that is adapter dependent.
173
- def delete(opts=(defarg=true;nil))
174
- Deprecation.deprecate("Calling Dataset#delete with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).delete.") unless defarg
175
- execute_dui(defarg ? delete_sql : delete_sql(opts))
171
+ def delete
172
+ execute_dui(delete_sql)
176
173
  end
177
174
 
178
175
  # Iterates over the records in the dataset as they are yielded from the
179
176
  # database adapter, and returns self.
180
- def each(opts = (defarg=true;nil), &block)
181
- Deprecation.deprecate("Calling Dataset#each with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).each.") unless defarg
182
- if opts && opts.keys.any?{|o| COLUMN_CHANGE_OPTS.include?(o)}
183
- prev_columns = @columns
184
- begin
185
- defarg ? _each(&block) : _each(opts, &block)
186
- ensure
187
- @columns = prev_columns
188
- end
177
+ def each(&block)
178
+ if @opts[:graph]
179
+ graph_each(&block)
189
180
  else
190
- defarg ? _each(&block) : _each(opts, &block)
181
+ if row_proc = @row_proc
182
+ fetch_rows(select_sql){|r| yield row_proc.call(r)}
183
+ else
184
+ fetch_rows(select_sql, &block)
185
+ end
191
186
  end
192
187
  self
193
188
  end
@@ -250,9 +245,8 @@ module Sequel
250
245
 
251
246
  # Updates values for the dataset. The returned value is generally the
252
247
  # number of rows updated, but that is adapter dependent.
253
- def update(values={}, opts=(defarg=true;nil))
254
- Deprecation.deprecate("Calling Dataset#update with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).update.") unless defarg
255
- execute_dui(defarg ? update_sql(values) : update_sql(value, opts))
248
+ def update(values={})
249
+ execute_dui(update_sql(values))
256
250
  end
257
251
 
258
252
  # Add the mutation methods via metaprogramming
@@ -267,23 +261,6 @@ module Sequel
267
261
 
268
262
  private
269
263
 
270
- # Runs #graph_each if graphing. Otherwise, iterates through the records
271
- # yielded by #fetch_rows, applying any row_proc or transform if necessary,
272
- # and yielding the result.
273
- def _each(opts=(defarg=true;nil), &block)
274
- if @opts[:graph] and !(opts && opts[:graph] == false)
275
- defarg ? graph_each(&block) : graph_each(opts, &block)
276
- else
277
- row_proc = @row_proc unless opts && opts[:naked]
278
- transform = @transform
279
- fetch_rows(defarg ? select_sql : select_sql(opts)) do |r|
280
- r = transform_load(r) if transform
281
- r = row_proc[r] if row_proc
282
- yield r
283
- end
284
- end
285
- end
286
-
287
264
  # Set the server to use to :default unless it is already set in the passed opts
288
265
  def default_server_opts(opts)
289
266
  {:server=>@opts[:server] || :default}.merge(opts)
@@ -338,10 +315,6 @@ module Sequel
338
315
  # VirtualRow instance.
339
316
  def virtual_row_block_call(block)
340
317
  return unless block
341
- unless Sequel.virtual_row_instance_eval
342
- Deprecation.deprecate('Using a VirtualRow block without an argument is deprecated, and its meaning will change in Sequel 3.0. Add a block argument to keep the old semantics, or set Sequel.virtual_row_instance_eval = true to use instance_eval for VirtualRow blocks without arguments.') unless block.arity == 1
343
- return block.call(SQL::VirtualRow.new)
344
- end
345
318
  case block.arity
346
319
  when -1, 0
347
320
  SQL::VirtualRow.new.instance_eval(&block)
@@ -2,13 +2,16 @@ module Sequel
2
2
  class Dataset
3
3
  COMMA_SEPARATOR = ', '.freeze
4
4
  COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count, LiteralString.new('*'.freeze)).as(:count)
5
+ ARRAY_ACCESS_ERROR_MSG = 'You cannot call Dataset#[] with an integer or with no arguments.'.freeze
6
+ MAP_ERROR_MSG = 'Using Dataset#map with an argument and a block is not allowed'.freeze
7
+ GET_ERROR_MSG = 'must provide argument or block to Dataset#get, not both'.freeze
8
+ IMPORT_ERROR_MSG = 'Using Sequel::Dataset#import an empty column array is not allowed'.freeze
5
9
 
6
10
  # Returns the first record matching the conditions. Examples:
7
11
  #
8
12
  # ds[:id=>1] => {:id=1}
9
13
  def [](*conditions)
10
- Deprecation.deprecate('Using an Integer argument to Dataset#[] is deprecated and will raise an error in Sequel 3.0. Use Dataset#first.') if conditions.length == 1 and conditions.is_a?(Integer)
11
- Deprecation.deprecate('Using Dataset#[] without an argument is deprecated and will raise an error in Sequel 3.0. Use Dataset#first.') if conditions.length == 0
14
+ raise(Error, ARRAY_ACCESS_ERROR_MSG) if (conditions.length == 1 and conditions.is_a?(Integer)) or conditions.length == 0
12
15
  first(*conditions)
13
16
  end
14
17
 
@@ -70,8 +73,12 @@ module Sequel
70
73
  # ds.get(:id)
71
74
  # ds.get{|o| o.sum(:id)}
72
75
  def get(column=nil, &block)
73
- raise(Error, 'must provide argument or block to Dataset#get, not both') if column && block
74
- (column ? select(column) : select(&block)).single_value
76
+ if column
77
+ raise(Error, GET_ERROR_MSG) if block
78
+ select(column).single_value
79
+ else
80
+ select(&block).single_value
81
+ end
75
82
  end
76
83
 
77
84
  # Returns a dataset grouped by the given column with count by group,
@@ -101,31 +108,18 @@ module Sequel
101
108
  #
102
109
  # # this will commit every 50 records
103
110
  # dataset.import([:x, :y], [[1, 2], [3, 4], ...], :slice => 50)
104
- def import(*args)
105
- if args.empty?
106
- Sequel::Deprecation.deprecate('Calling Sequel::Dataset#import with no arguments', 'Use dataset.multi_insert([])')
107
- return
108
- elsif args[0].is_a?(Array) && args[1].is_a?(Array)
109
- columns, values, opts = *args
110
- elsif args[0].is_a?(Array) && args[1].is_a?(Dataset)
111
- table = @opts[:from].first
112
- columns, dataset = *args
113
- sql = "INSERT INTO #{quote_identifier(table)} (#{identifier_list(columns)}) VALUES #{literal(dataset)}"
114
- return @db.transaction{execute_dui(sql)}
115
- else
116
- Sequel::Deprecation.deprecate('Calling Sequel::Dataset#import with hashes', 'Use Sequel::Dataset#multi_insert')
117
- return multi_insert(*args)
118
- end
119
- # make sure there's work to do
120
- Sequel::Deprecation.deprecate('Calling Sequel::Dataset#import an empty column array is deprecated and will raise an error in Sequel 3.0.') if columns.empty?
121
- return if columns.empty? || values.empty?
122
-
123
- slice_size = opts && (opts[:commit_every] || opts[:slice])
111
+ def import(columns, values, opts={})
112
+ return @db.transaction{execute_dui("INSERT INTO #{quote_schema_table(@opts[:from].first)} (#{identifier_list(columns)}) VALUES #{literal(values)}")} if values.is_a?(Dataset)
113
+
114
+ return if values.empty?
115
+ raise(Error, IMPORT_ERROR_MSG) if columns.empty?
124
116
 
125
- if slice_size
126
- values.each_slice(slice_size) do |slice|
127
- statements = multi_insert_sql(columns, slice)
128
- @db.transaction(opts){statements.each{|st| execute_dui(st)}}
117
+ if slice_size = opts[:commit_every] || opts[:slice]
118
+ offset = 0
119
+ loop do
120
+ @db.transaction(opts){multi_insert_sql(columns, values[offset, slice_size]).each{|st| execute_dui(st)}}
121
+ offset += slice_size
122
+ break if offset >= values.length
129
123
  end
130
124
  else
131
125
  statements = multi_insert_sql(columns, values)
@@ -155,8 +149,8 @@ module Sequel
155
149
  # ds.map(:id) => [1, 2, 3, ...]
156
150
  # ds.map{|r| r[:id] * 2} => [2, 4, 6, ...]
157
151
  def map(column=nil, &block)
158
- Deprecation.deprecate('Using Dataset#map with an argument and a block is deprecated and will raise an error in Sequel 3.0. Use an argument or a block, not both.') if column && block
159
152
  if column
153
+ raise(Error, MAP_ERROR_MSG) if block
160
154
  super(){|r| r[column]}
161
155
  else
162
156
  super(&block)
@@ -183,22 +177,10 @@ module Sequel
183
177
  # values.
184
178
  #
185
179
  # You can also use the :slice or :commit_every option that import accepts.
186
- def multi_insert(*args)
187
- if args.empty?
188
- Sequel::Deprecation.deprecate('Calling Sequel::Dataset#multi_insert with no arguments', 'Use dataset.multi_insert([])')
189
- return
190
- elsif args[0].is_a?(Array) && (args[1].is_a?(Array) || args[1].is_a?(Dataset))
191
- Sequel::Deprecation.deprecate('Calling Sequel::Dataset#multi_insert with an array of columns and an array of arrays of values', 'Use Sequel::Dataset#import')
192
- return import(*args)
193
- else
194
- # we assume that an array of hashes is given
195
- hashes, opts = *args
196
- return if hashes.empty?
197
- columns = hashes.first.keys
198
- # convert the hashes into arrays
199
- values = hashes.map {|h| columns.map {|c| h[c]}}
200
- end
201
- import(columns, values, opts)
180
+ def multi_insert(hashes, opts={})
181
+ return if hashes.empty?
182
+ columns = hashes.first.keys
183
+ import(columns, hashes.map{|h| columns.map{|c| h[c]}}, opts)
202
184
  end
203
185
 
204
186
  # Returns a Range object made from the minimum and maximum values for the
@@ -210,20 +192,15 @@ module Sequel
210
192
  end
211
193
 
212
194
  # Returns the first record in the dataset.
213
- def single_record(opts = (defarg=true;nil))
214
- Deprecation.deprecate("Calling Dataset#single_record with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).single_record.") unless defarg
215
- ds = clone(:limit=>1)
216
- opts = opts.merge(:limit=>1) if opts and opts[:limit]
217
- defarg ? ds.each{|r| return r} : ds.each(opts){|r| return r}
195
+ def single_record
196
+ clone(:limit=>1).each{|r| return r}
218
197
  nil
219
198
  end
220
199
 
221
200
  # Returns the first value of the first record in the dataset.
222
201
  # Returns nil if dataset is empty.
223
- def single_value(opts = (defarg=true;nil))
224
- Deprecation.deprecate("Calling Dataset#single_value with an argument is deprecated and will raise an error in Sequel 3.0. Use dataset.clone(opts).single_value.") unless defarg
225
- ds = naked.clone(:graph=>false)
226
- if r = (defarg ? ds.single_record : ds.single_record(opts))
202
+ def single_value
203
+ if r = naked.clone(:graph=>false).single_record
227
204
  r.values.first
228
205
  end
229
206
  end