sequel 3.33.0 → 3.34.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 (152) hide show
  1. data/CHANGELOG +140 -0
  2. data/Rakefile +7 -0
  3. data/bin/sequel +22 -2
  4. data/doc/dataset_basics.rdoc +1 -1
  5. data/doc/mass_assignment.rdoc +3 -1
  6. data/doc/querying.rdoc +28 -4
  7. data/doc/reflection.rdoc +23 -3
  8. data/doc/release_notes/3.34.0.txt +671 -0
  9. data/doc/schema_modification.rdoc +18 -2
  10. data/doc/virtual_rows.rdoc +49 -0
  11. data/lib/sequel/adapters/do/mysql.rb +0 -5
  12. data/lib/sequel/adapters/ibmdb.rb +9 -4
  13. data/lib/sequel/adapters/jdbc.rb +9 -4
  14. data/lib/sequel/adapters/jdbc/h2.rb +8 -2
  15. data/lib/sequel/adapters/jdbc/mysql.rb +0 -5
  16. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -0
  17. data/lib/sequel/adapters/jdbc/sqlite.rb +19 -0
  18. data/lib/sequel/adapters/mock.rb +24 -3
  19. data/lib/sequel/adapters/mysql.rb +29 -50
  20. data/lib/sequel/adapters/mysql2.rb +13 -28
  21. data/lib/sequel/adapters/oracle.rb +8 -2
  22. data/lib/sequel/adapters/postgres.rb +115 -20
  23. data/lib/sequel/adapters/shared/db2.rb +1 -1
  24. data/lib/sequel/adapters/shared/mssql.rb +14 -3
  25. data/lib/sequel/adapters/shared/mysql.rb +59 -11
  26. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  27. data/lib/sequel/adapters/shared/oracle.rb +1 -1
  28. data/lib/sequel/adapters/shared/postgres.rb +127 -30
  29. data/lib/sequel/adapters/shared/sqlite.rb +55 -38
  30. data/lib/sequel/adapters/sqlite.rb +9 -3
  31. data/lib/sequel/adapters/swift.rb +2 -2
  32. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  33. data/lib/sequel/adapters/swift/postgres.rb +10 -0
  34. data/lib/sequel/ast_transformer.rb +4 -0
  35. data/lib/sequel/connection_pool.rb +8 -0
  36. data/lib/sequel/connection_pool/sharded_single.rb +5 -0
  37. data/lib/sequel/connection_pool/sharded_threaded.rb +17 -0
  38. data/lib/sequel/connection_pool/single.rb +5 -0
  39. data/lib/sequel/connection_pool/threaded.rb +14 -0
  40. data/lib/sequel/core.rb +24 -3
  41. data/lib/sequel/database/connecting.rb +24 -14
  42. data/lib/sequel/database/dataset_defaults.rb +1 -0
  43. data/lib/sequel/database/misc.rb +16 -25
  44. data/lib/sequel/database/query.rb +20 -2
  45. data/lib/sequel/database/schema_generator.rb +2 -2
  46. data/lib/sequel/database/schema_methods.rb +120 -23
  47. data/lib/sequel/dataset/actions.rb +91 -18
  48. data/lib/sequel/dataset/features.rb +5 -0
  49. data/lib/sequel/dataset/prepared_statements.rb +6 -2
  50. data/lib/sequel/dataset/sql.rb +68 -51
  51. data/lib/sequel/extensions/_pretty_table.rb +79 -0
  52. data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +18 -13
  53. data/lib/sequel/extensions/migration.rb +4 -0
  54. data/lib/sequel/extensions/null_dataset.rb +90 -0
  55. data/lib/sequel/extensions/pg_array.rb +460 -0
  56. data/lib/sequel/extensions/pg_array_ops.rb +220 -0
  57. data/lib/sequel/extensions/pg_auto_parameterize.rb +174 -0
  58. data/lib/sequel/extensions/pg_hstore.rb +296 -0
  59. data/lib/sequel/extensions/pg_hstore_ops.rb +259 -0
  60. data/lib/sequel/extensions/pg_statement_cache.rb +316 -0
  61. data/lib/sequel/extensions/pretty_table.rb +5 -71
  62. data/lib/sequel/extensions/query_literals.rb +79 -0
  63. data/lib/sequel/extensions/schema_caching.rb +76 -0
  64. data/lib/sequel/extensions/schema_dumper.rb +227 -31
  65. data/lib/sequel/extensions/select_remove.rb +35 -0
  66. data/lib/sequel/extensions/sql_expr.rb +4 -110
  67. data/lib/sequel/extensions/to_dot.rb +1 -1
  68. data/lib/sequel/model.rb +11 -2
  69. data/lib/sequel/model/associations.rb +35 -7
  70. data/lib/sequel/model/base.rb +159 -36
  71. data/lib/sequel/no_core_ext.rb +2 -0
  72. data/lib/sequel/plugins/caching.rb +25 -18
  73. data/lib/sequel/plugins/composition.rb +1 -1
  74. data/lib/sequel/plugins/hook_class_methods.rb +1 -1
  75. data/lib/sequel/plugins/identity_map.rb +11 -3
  76. data/lib/sequel/plugins/instance_filters.rb +10 -0
  77. data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
  78. data/lib/sequel/plugins/nested_attributes.rb +4 -3
  79. data/lib/sequel/plugins/prepared_statements.rb +3 -1
  80. data/lib/sequel/plugins/prepared_statements_associations.rb +5 -1
  81. data/lib/sequel/plugins/schema.rb +7 -2
  82. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  83. data/lib/sequel/plugins/static_cache.rb +99 -0
  84. data/lib/sequel/plugins/validation_class_methods.rb +1 -1
  85. data/lib/sequel/sql.rb +417 -7
  86. data/lib/sequel/version.rb +1 -1
  87. data/spec/adapters/firebird_spec.rb +1 -1
  88. data/spec/adapters/mssql_spec.rb +12 -15
  89. data/spec/adapters/mysql_spec.rb +81 -23
  90. data/spec/adapters/postgres_spec.rb +444 -77
  91. data/spec/adapters/spec_helper.rb +2 -0
  92. data/spec/adapters/sqlite_spec.rb +8 -8
  93. data/spec/core/connection_pool_spec.rb +85 -0
  94. data/spec/core/database_spec.rb +29 -5
  95. data/spec/core/dataset_spec.rb +171 -3
  96. data/spec/core/expression_filters_spec.rb +364 -0
  97. data/spec/core/mock_adapter_spec.rb +17 -3
  98. data/spec/core/schema_spec.rb +133 -0
  99. data/spec/extensions/association_dependencies_spec.rb +13 -13
  100. data/spec/extensions/caching_spec.rb +26 -3
  101. data/spec/extensions/class_table_inheritance_spec.rb +2 -2
  102. data/spec/{core/core_sql_spec.rb → extensions/core_extensions_spec.rb} +23 -94
  103. data/spec/extensions/force_encoding_spec.rb +4 -2
  104. data/spec/extensions/hook_class_methods_spec.rb +5 -2
  105. data/spec/extensions/identity_map_spec.rb +17 -0
  106. data/spec/extensions/instance_filters_spec.rb +1 -1
  107. data/spec/extensions/lazy_attributes_spec.rb +2 -2
  108. data/spec/extensions/list_spec.rb +4 -4
  109. data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
  110. data/spec/extensions/migration_spec.rb +6 -2
  111. data/spec/extensions/nested_attributes_spec.rb +20 -0
  112. data/spec/extensions/null_dataset_spec.rb +85 -0
  113. data/spec/extensions/optimistic_locking_spec.rb +2 -2
  114. data/spec/extensions/pg_array_ops_spec.rb +105 -0
  115. data/spec/extensions/pg_array_spec.rb +196 -0
  116. data/spec/extensions/pg_auto_parameterize_spec.rb +64 -0
  117. data/spec/extensions/pg_hstore_ops_spec.rb +136 -0
  118. data/spec/extensions/pg_hstore_spec.rb +195 -0
  119. data/spec/extensions/pg_statement_cache_spec.rb +209 -0
  120. data/spec/extensions/prepared_statements_spec.rb +4 -0
  121. data/spec/extensions/pretty_table_spec.rb +6 -0
  122. data/spec/extensions/query_literals_spec.rb +168 -0
  123. data/spec/extensions/schema_caching_spec.rb +41 -0
  124. data/spec/extensions/schema_dumper_spec.rb +231 -11
  125. data/spec/extensions/schema_spec.rb +14 -2
  126. data/spec/extensions/select_remove_spec.rb +38 -0
  127. data/spec/extensions/sharding_spec.rb +6 -6
  128. data/spec/extensions/skip_create_refresh_spec.rb +1 -1
  129. data/spec/extensions/spec_helper.rb +2 -1
  130. data/spec/extensions/sql_expr_spec.rb +28 -19
  131. data/spec/extensions/static_cache_spec.rb +145 -0
  132. data/spec/extensions/touch_spec.rb +1 -1
  133. data/spec/extensions/typecast_on_load_spec.rb +9 -1
  134. data/spec/integration/associations_test.rb +6 -6
  135. data/spec/integration/database_test.rb +1 -1
  136. data/spec/integration/dataset_test.rb +89 -26
  137. data/spec/integration/migrator_test.rb +2 -3
  138. data/spec/integration/model_test.rb +3 -3
  139. data/spec/integration/plugin_test.rb +85 -22
  140. data/spec/integration/prepared_statement_test.rb +28 -8
  141. data/spec/integration/schema_test.rb +78 -7
  142. data/spec/integration/spec_helper.rb +1 -0
  143. data/spec/integration/timezone_test.rb +1 -1
  144. data/spec/integration/transaction_test.rb +4 -6
  145. data/spec/integration/type_test.rb +2 -2
  146. data/spec/model/associations_spec.rb +94 -8
  147. data/spec/model/base_spec.rb +4 -4
  148. data/spec/model/hooks_spec.rb +2 -2
  149. data/spec/model/model_spec.rb +19 -7
  150. data/spec/model/record_spec.rb +135 -58
  151. data/spec/model/spec_helper.rb +1 -0
  152. metadata +35 -7
@@ -143,9 +143,10 @@ as it's third argument. A simple example is:
143
143
  on most databases.
144
144
  :on_delete :: Specify the behavior of this foreign key column when the row with the primary key
145
145
  it references is deleted , can be :restrict, :cascade, :set_null, or :set_default.
146
+ You can also use a string, which is used literally.
146
147
  :on_update :: Specify the behavior of this foreign key column when the row with the primary key
147
- it references modifies the value of the primary key, can be
148
- :restrict, :cascade, :set_null, or :set_default.
148
+ it references modifies the value of the primary key. Takes the same options as
149
+ :on_delete.
149
150
 
150
151
  Like +primary_key+, if you provide +foreign_key+ with an array of symbols, it will not create a
151
152
  column, but create a foreign key constraint:
@@ -253,6 +254,21 @@ and it creates an unnamed constraint
253
254
  check{char_length(name) > 2}
254
255
  end
255
256
 
257
+ == +create_join_table+
258
+
259
+ +create_join_table+ is a shortcut that you can use to create simple many-to-many join tables:
260
+
261
+ create_join_table(:artist_id=>:artists, :album_id=>:albums)
262
+
263
+ which expands to:
264
+
265
+ create_table(:albums_artists) do
266
+ foreign_key :album_id, :albums, :null=>false
267
+ foreign_key :artist_id, :artists, :null=>false
268
+ primary_key [:album_id, :artist_id]
269
+ index [:artist_id, :album_id]
270
+ end
271
+
256
272
  == +alter_table+
257
273
 
258
274
  +alter_table+ is used to alter existing tables, changing their columns, indexes,
@@ -205,6 +205,55 @@ call, with an optional hash as the second argument: Here are some examples of us
205
205
  ds.select{sum(:over, :args=>col1, :partition=>col2, :order=>col3){}}
206
206
  # SELECT sum(col1) OVER (PARTITION BY col2 ORDER BY col3)
207
207
 
208
+ == Operators
209
+
210
+ VirtualRows use method_missing to handle almost all method calls. However, they
211
+ have special handling of some operator methods to make certain things easier. The
212
+ operators all use a prefix form.
213
+
214
+ === Math Operators
215
+
216
+ The standard +, -, *, and / mathematical operators are defined:
217
+
218
+ ds.select{|o| o.-(1, o.a).as(b)}
219
+ ds.select{self.-(1, a).as(b)}
220
+ # SELECT (1 - a) AS b
221
+
222
+ === Boolean Operators
223
+
224
+ The & and | methods are defined to use AND and OR:
225
+
226
+ ds.where{|o| o.&({:a=>:b}, :c)}
227
+ ds.where{self.&({:a=>:b}, :c)}
228
+ # WHERE ((a = b) AND c)
229
+
230
+ The ~ method is defined to do inversion:
231
+
232
+ ds.where{|o| o.~({:a=>1, :b=>2})}
233
+ ds.where{self.~({:a=>1, :b=>2})}
234
+ # WHERE ((a != 1) OR (b != 2))
235
+
236
+ === Inequality Operators
237
+
238
+ The standard >, <, >=, and <= inequality operators are defined:
239
+
240
+ ds.where{|o| o.>(1, :c)}
241
+ ds.where{self.>(1, :c)}
242
+ # WHERE (1 > c)
243
+
244
+ == Literal Strings
245
+
246
+ The backtick operator can be used inside an instance-evaled
247
+ virtual row block to create a literal string:
248
+
249
+ ds.where{a > `some SQL`}
250
+ # WHERE (a > some SQL)
251
+
252
+ You can use this on a regular virtual row block too, but it
253
+ doesn't look as nice:
254
+
255
+ ds.where{|o| o.>(:a, o.`('some SQL')}
256
+
208
257
  == Returning multiple values
209
258
 
210
259
  It's common when using select and order virtual row blocks to want to
@@ -36,11 +36,6 @@ module Sequel
36
36
  false
37
37
  end
38
38
 
39
- # Use execute_insert to execute the replace_sql.
40
- def replace(*args)
41
- execute_insert(replace_sql(*args))
42
- end
43
-
44
39
  private
45
40
 
46
41
  # do_mysql sets NO_BACKSLASH_ESCAPES, so use standard SQL string escaping
@@ -174,7 +174,7 @@ module Sequel
174
174
  # REORG the related table whenever it is altered. This is not always
175
175
  # required, but it is necessary for compatibilty with other Sequel
176
176
  # code in many cases.
177
- def alter_table(name, generator=nil, &block)
177
+ def alter_table(name, generator=nil)
178
178
  res = super
179
179
  reorg(name)
180
180
  res
@@ -231,11 +231,16 @@ module Sequel
231
231
  sql = ps.prepared_sql
232
232
  synchronize(opts[:server]) do |conn|
233
233
  unless conn.prepared_statements.fetch(ps_name, []).first == sql
234
- log_yield("Preparing #{ps_name}: #{sql}"){conn.prepare(sql, ps_name)}
234
+ log_yield("PREPARE #{ps_name}: #{sql}"){conn.prepare(sql, ps_name)}
235
235
  end
236
236
  args = args.map{|v| v.nil? ? nil : prepared_statement_arg(v)}
237
- stmt = log_yield("Executing #{ps_name}: #{args.inspect}"){conn.execute_prepared(ps_name, *args)}
238
-
237
+ log_sql = "EXECUTE #{ps_name}"
238
+ if ps.log_sql
239
+ log_sql << " ("
240
+ log_sql << sql
241
+ log_sql << ")"
242
+ end
243
+ stmt = log_yield(log_sql, args){conn.execute_prepared(ps_name, *args)}
239
244
  if block_given?
240
245
  begin
241
246
  yield(stmt)
@@ -343,13 +343,18 @@ module Sequel
343
343
  if name and cps = conn.prepared_statements[name] and cps[0] == sql
344
344
  cps = cps[1]
345
345
  else
346
- log_yield("Closing #{name}"){cps[1].close} if cps
347
- cps = log_yield("Preparing#{" #{name}:" if name} #{sql}"){conn.prepareStatement(sql)}
346
+ log_yield("CLOSE #{name}"){cps[1].close} if cps
347
+ cps = log_yield("PREPARE#{" #{name}:" if name} #{sql}"){conn.prepareStatement(sql)}
348
348
  conn.prepared_statements[name] = [sql, cps] if name
349
349
  end
350
350
  i = 0
351
351
  args.each{|arg| set_ps_arg(cps, arg, i+=1)}
352
- msg = "Executing#{" #{name}" if name}"
352
+ msg = "EXECUTE#{" #{name}" if name}"
353
+ if ps.log_sql
354
+ msg << " ("
355
+ msg << sql
356
+ msg << ")"
357
+ end
353
358
  begin
354
359
  if block_given?
355
360
  yield log_yield(msg, args){cps.executeQuery}
@@ -623,7 +628,7 @@ module Sequel
623
628
  # Handle type conversions for common Java types.
624
629
  class TYPE_TRANSLATOR
625
630
  LF = "\n".freeze
626
- def time(v) Sequel.string_to_time(v.to_string) end
631
+ def time(v) Sequel.string_to_time(v.to_string) + v.getTime.divmod(1000).last/1000.0 end
627
632
  def date(v) Date.civil(v.getYear + 1900, v.getMonth + 1, v.getDate) end
628
633
  def decimal(v) BigDecimal.new(v.to_string) end
629
634
  def byte_array(v) Sequel::SQL::Blob.new(String.from_java_bytes(v)) end
@@ -25,7 +25,7 @@ module Sequel
25
25
 
26
26
  # H2 uses an IDENTITY type
27
27
  def serial_primary_key_options
28
- {:primary_key => true, :type => :identity}
28
+ {:primary_key => true, :type => :identity, :identity=>true}
29
29
  end
30
30
 
31
31
  # H2 supports CREATE TABLE IF NOT EXISTS syntax.
@@ -114,6 +114,12 @@ module Sequel
114
114
  def schema_column_type(db_type)
115
115
  db_type == 'clob' ? :string : super
116
116
  end
117
+
118
+ # Use BIGINT IDENTITY for identity columns that use bigint, fixes
119
+ # the case where primary_key :column, :type=>Bignum is used.
120
+ def type_literal_generic_bignum(column)
121
+ column[:identity] ? 'BIGINT IDENTITY' : super
122
+ end
117
123
  end
118
124
 
119
125
  # Dataset class for H2 datasets accessed via JDBC.
@@ -124,7 +130,7 @@ module Sequel
124
130
  HSTAR = "H*".freeze
125
131
  BITCOMP_OPEN = "((0 - ".freeze
126
132
  BITCOMP_CLOSE = ") - 1)".freeze
127
- ILIKE_PLACEHOLDER = "CAST(? AS VARCHAR_IGNORECASE)".freeze
133
+ ILIKE_PLACEHOLDER = ["CAST(".freeze, " AS VARCHAR_IGNORECASE)".freeze].freeze
128
134
  TIME_FORMAT = "'%H:%M:%S'".freeze
129
135
 
130
136
  # Emulate the case insensitive LIKE operator and the bitwise operators.
@@ -66,11 +66,6 @@ module Sequel
66
66
  # Dataset class for MySQL datasets accessed via JDBC.
67
67
  class Dataset < JDBC::Dataset
68
68
  include Sequel::MySQL::DatasetMethods
69
-
70
- # Use execute_insert to execute the replace_sql.
71
- def replace(*args)
72
- execute_insert(replace_sql(*args))
73
- end
74
69
  end
75
70
  end
76
71
  end
@@ -75,6 +75,49 @@ module Sequel
75
75
  include Sequel::Postgres::DatasetMethods
76
76
  APOS = Dataset::APOS
77
77
 
78
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
79
+ # Convert Java::OrgPostgresqlJdbc4::Jdbc4Array to ruby arrays
80
+ def pg_array(v)
81
+ _pg_array(v.array)
82
+ end
83
+
84
+ # Convert Java::OrgPostgresqlUtil::PGobject to ruby strings
85
+ def pg_object(v)
86
+ v.to_string
87
+ end
88
+
89
+ private
90
+
91
+ # Handle multi-dimensional Java arrays by recursively mapping them
92
+ # to ruby arrays.
93
+ def _pg_array(v)
94
+ v.to_ary.map do |i|
95
+ if i.respond_to?(:to_ary)
96
+ _pg_array(i)
97
+ else
98
+ i
99
+ end
100
+ end
101
+ end
102
+ end
103
+
104
+ PG_ARRAY_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_array)
105
+ PG_OBJECT_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:pg_object)
106
+
107
+ # Handle PostgreSQL array and object types. Object types are just
108
+ # turned into strings, similarly to how the native adapter treats
109
+ # the types.
110
+ def convert_type_proc(v)
111
+ case v
112
+ when Java::OrgPostgresqlJdbc4::Jdbc4Array
113
+ PG_ARRAY_METHOD
114
+ when Java::OrgPostgresqlUtil::PGobject
115
+ PG_OBJECT_METHOD
116
+ else
117
+ super
118
+ end
119
+ end
120
+
78
121
  # Add the shared PostgreSQL prepared statement methods
79
122
  def prepare(*args)
80
123
  ps = super
@@ -8,7 +8,26 @@ module Sequel
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
10
10
  LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
11
+ FOREIGN_KEY_ERROR_RE = /query does not return ResultSet/.freeze
11
12
 
13
+ # Swallow pointless exceptions when the foreign key list pragma
14
+ # doesn't return any rows.
15
+ def foreign_key_list(table, opts={})
16
+ super
17
+ rescue Sequel::DatabaseError => e
18
+ raise unless e.message =~ FOREIGN_KEY_ERROR_RE
19
+ []
20
+ end
21
+
22
+ # Swallow pointless exceptions when the index list pragma
23
+ # doesn't return any rows.
24
+ def indexes(table, opts={})
25
+ super
26
+ rescue Sequel::DatabaseError => e
27
+ raise unless e.message =~ FOREIGN_KEY_ERROR_RE
28
+ {}
29
+ end
30
+
12
31
  private
13
32
 
14
33
  # Use last_insert_rowid() to get the last inserted id.
@@ -44,6 +44,21 @@ module Sequel
44
44
  'sqlite'=>'SQLite'
45
45
  }
46
46
 
47
+ # Procs to run for specific database types to get the mock adapter
48
+ # to work with the shared adapter
49
+ SHARED_ADAPTER_SETUP = {
50
+ 'postgres' => lambda do |db|
51
+ db.instance_eval do
52
+ @server_version = 90103
53
+ @primary_keys = {}
54
+ @primary_key_sequences = {}
55
+ def primary_key(table)
56
+ :id
57
+ end
58
+ end
59
+ end
60
+ }
61
+
47
62
  # Set the autogenerated primary key integer
48
63
  # to be returned when running an insert query.
49
64
  # Argument types supported:
@@ -98,6 +113,9 @@ module Sequel
98
113
  # instance an raise it wrapped in a DatabaseError.
99
114
  attr_writer :numrows
100
115
 
116
+ # Mock the server version, useful when using the shared adapters
117
+ attr_accessor :server_version
118
+
101
119
  # Additional options supported:
102
120
  #
103
121
  # :autoid :: Call #autoid= with the value
@@ -114,6 +132,9 @@ module Sequel
114
132
  require "sequel/adapters/shared/#{opts[:host]}"
115
133
  extend Sequel.const_get(mod_name)::DatabaseMethods
116
134
  extend_datasets Sequel.const_get(mod_name)::DatasetMethods
135
+ if pr = SHARED_ADAPTER_SETUP[opts[:host]]
136
+ pr.call(self)
137
+ end
117
138
  end
118
139
  self.autoid = opts[:autoid]
119
140
  self.columns = opts[:columns]
@@ -186,12 +207,12 @@ module Sequel
186
207
  begin
187
208
  if block
188
209
  columns(ds, sql) if ds
189
- _fetch(sql, ds._fetch || @fetch, &block)
210
+ _fetch(sql, (ds._fetch if ds) || @fetch, &block)
190
211
  elsif meth = opts[:meth]
191
212
  if meth == :numrows
192
- _numrows(sql, ds.numrows || @numrows)
213
+ _numrows(sql, (ds.numrows if ds) || @numrows)
193
214
  else
194
- v = ds.autoid
215
+ v = ds.autoid if ds
195
216
  _autoid(sql, v || @autoid, (ds if v))
196
217
  end
197
218
  end
@@ -43,6 +43,10 @@ module Sequel
43
43
 
44
44
  # Mysql::Error messages that indicate the current connection should be disconnected
45
45
  MYSQL_DATABASE_DISCONNECT_ERRORS = /\A(Commands out of sync; you can't run this command now|Can't connect to local MySQL server through socket|MySQL server has gone away|Lost connection to MySQL server during query)/
46
+
47
+ # Regular expression used for getting accurate number of rows
48
+ # matched by an update statement.
49
+ AFFECTED_ROWS_RE = /Rows matched:\s+(\d+)\s+Changed:\s+\d+\s+Warnings:\s+\d+/.freeze
46
50
 
47
51
  set_adapter_scheme :mysql
48
52
 
@@ -155,6 +159,16 @@ module Sequel
155
159
  @convert_tinyint_to_bool = v
156
160
  end
157
161
 
162
+ # Return the number of matched rows when executing a delete/update statement.
163
+ def execute_dui(sql, opts={})
164
+ execute(sql, opts){|c| return affected_rows(c)}
165
+ end
166
+
167
+ # Return the last inserted id when executing an insert statement.
168
+ def execute_insert(sql, opts={})
169
+ execute(sql, opts){|c| return c.insert_id}
170
+ end
171
+
158
172
  # Return the version of the MySQL server two which we are connecting.
159
173
  def server_version(server=nil)
160
174
  @server_version ||= (synchronize(server){|conn| conn.server_version if conn.respond_to?(:server_version)} || super)
@@ -167,7 +181,7 @@ module Sequel
167
181
  # yield the connection if a block is given.
168
182
  def _execute(conn, sql, opts)
169
183
  begin
170
- r = log_yield(sql){conn.query(sql)}
184
+ r = log_yield((log_sql = opts[:log_sql]) ? sql + log_sql : sql){conn.query(sql)}
171
185
  if opts[:type] == :select
172
186
  yield r if r
173
187
  elsif block_given?
@@ -209,6 +223,18 @@ module Sequel
209
223
  end
210
224
  end
211
225
 
226
+ # Try to get an accurate number of rows matched using the query
227
+ # info. Fall back to affected_rows if there was no match, but
228
+ # that may be inaccurate.
229
+ def affected_rows(conn)
230
+ s = conn.info
231
+ if s && s =~ AFFECTED_ROWS_RE
232
+ $1.to_i
233
+ else
234
+ conn.affected_rows
235
+ end
236
+ end
237
+
212
238
  # MySQL connections use the query method to execute SQL without a result
213
239
  def connection_execute_method
214
240
  :query
@@ -269,19 +295,10 @@ module Sequel
269
295
 
270
296
  Database::DatasetClass = self
271
297
 
272
- # Regular expression used for getting accurate number of rows
273
- # matched by an update statement.
274
- AFFECTED_ROWS_RE = /Rows matched:\s+(\d+)\s+Changed:\s+\d+\s+Warnings:\s+\d+/.freeze
275
-
276
- # Delete rows matching this dataset
277
- def delete
278
- execute_dui(delete_sql){|c| return c.affected_rows}
279
- end
280
-
281
298
  # Yield all rows matching this dataset. If the dataset is set to
282
299
  # split multiple statements, yield arrays of hashes one per statement
283
300
  # instead of yielding results for all statements as hashes.
284
- def fetch_rows(sql, &block)
301
+ def fetch_rows(sql)
285
302
  execute(sql) do |r|
286
303
  i = -1
287
304
  cps = db.conversion_procs
@@ -298,7 +315,7 @@ module Sequel
298
315
  yield_rows(r, cols){|h| s << h}
299
316
  yield s
300
317
  else
301
- yield_rows(r, cols, &block)
318
+ yield_rows(r, cols){|h| yield h}
302
319
  end
303
320
  end
304
321
  self
@@ -310,22 +327,6 @@ module Sequel
310
327
  super
311
328
  end
312
329
 
313
- # Insert a new value into this dataset
314
- def insert(*values)
315
- execute_dui(insert_sql(*values)){|c| return c.insert_id}
316
- end
317
-
318
- # You can parse out the correct number of rows matched using the query info,
319
- # even though affected_rows doesn't provide an accurate number.
320
- def provides_accurate_rows_matched?
321
- true
322
- end
323
-
324
- # Replace (update or insert) the matching row.
325
- def replace(*args)
326
- execute_dui(replace_sql(*args)){|c| return c.insert_id}
327
- end
328
-
329
330
  # Makes each yield arrays of rows, with each array containing the rows
330
331
  # for a given result set. Does not work with graphing. So you can submit
331
332
  # SQL with multiple statements and easily determine which statement
@@ -342,35 +343,13 @@ module Sequel
342
343
  ds
343
344
  end
344
345
 
345
- # Update the matching rows.
346
- def update(values={})
347
- execute_dui(update_sql(values)){|c| return affected_rows(c)}
348
- end
349
-
350
346
  private
351
347
 
352
- # Try to get an accurate number of rows matched using the query
353
- # info. Fall back to affected_rows if there was no match, but
354
- # that may be inaccurate.
355
- def affected_rows(conn)
356
- s = conn.info
357
- if s && s =~ AFFECTED_ROWS_RE
358
- $1.to_i
359
- else
360
- conn.affected_rows
361
- end
362
- end
363
-
364
348
  # Set the :type option to :select if it hasn't been set.
365
349
  def execute(sql, opts={}, &block)
366
350
  super(sql, {:type=>:select}.merge(opts), &block)
367
351
  end
368
352
 
369
- # Set the :type option to :dui if it hasn't been set.
370
- def execute_dui(sql, opts={}, &block)
371
- super(sql, {:type=>:dui}.merge(opts), &block)
372
- end
373
-
374
353
  # Handle correct quoting of strings using ::MySQL.quote.
375
354
  def literal_string_append(sql, v)
376
355
  sql << "'"