sequel 4.34.0 → 4.35.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 (95) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +30 -0
  3. data/Rakefile +14 -17
  4. data/doc/object_model.rdoc +4 -4
  5. data/doc/release_notes/4.35.0.txt +130 -0
  6. data/doc/schema_modification.rdoc +8 -3
  7. data/doc/security.rdoc +3 -3
  8. data/lib/sequel/adapters/ado.rb +2 -2
  9. data/lib/sequel/adapters/ado/access.rb +6 -6
  10. data/lib/sequel/adapters/ado/mssql.rb +2 -2
  11. data/lib/sequel/adapters/amalgalite.rb +6 -6
  12. data/lib/sequel/adapters/cubrid.rb +4 -4
  13. data/lib/sequel/adapters/do.rb +2 -2
  14. data/lib/sequel/adapters/do/mysql.rb +1 -1
  15. data/lib/sequel/adapters/do/postgres.rb +1 -1
  16. data/lib/sequel/adapters/do/sqlite3.rb +1 -1
  17. data/lib/sequel/adapters/ibmdb.rb +6 -6
  18. data/lib/sequel/adapters/jdbc.rb +15 -15
  19. data/lib/sequel/adapters/jdbc/db2.rb +1 -1
  20. data/lib/sequel/adapters/jdbc/derby.rb +3 -3
  21. data/lib/sequel/adapters/jdbc/h2.rb +3 -3
  22. data/lib/sequel/adapters/jdbc/hsqldb.rb +2 -2
  23. data/lib/sequel/adapters/jdbc/mssql.rb +1 -1
  24. data/lib/sequel/adapters/jdbc/mysql.rb +1 -1
  25. data/lib/sequel/adapters/jdbc/oracle.rb +1 -1
  26. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -2
  27. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +1 -1
  28. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/sequel/adapters/jdbc/transactions.rb +10 -10
  30. data/lib/sequel/adapters/mock.rb +1 -1
  31. data/lib/sequel/adapters/mysql.rb +2 -2
  32. data/lib/sequel/adapters/mysql2.rb +2 -2
  33. data/lib/sequel/adapters/odbc.rb +2 -2
  34. data/lib/sequel/adapters/odbc/mssql.rb +2 -2
  35. data/lib/sequel/adapters/oracle.rb +9 -9
  36. data/lib/sequel/adapters/postgres.rb +3 -3
  37. data/lib/sequel/adapters/shared/mssql.rb +36 -8
  38. data/lib/sequel/adapters/shared/oracle.rb +15 -0
  39. data/lib/sequel/adapters/shared/postgres.rb +22 -1
  40. data/lib/sequel/adapters/sqlanywhere.rb +1 -1
  41. data/lib/sequel/adapters/sqlite.rb +7 -7
  42. data/lib/sequel/adapters/swift.rb +3 -3
  43. data/lib/sequel/adapters/swift/mysql.rb +1 -1
  44. data/lib/sequel/adapters/swift/postgres.rb +1 -1
  45. data/lib/sequel/adapters/swift/sqlite.rb +1 -1
  46. data/lib/sequel/adapters/tinytds.rb +5 -7
  47. data/lib/sequel/database/logging.rb +18 -3
  48. data/lib/sequel/database/misc.rb +19 -8
  49. data/lib/sequel/database/schema_generator.rb +7 -2
  50. data/lib/sequel/database/schema_methods.rb +9 -2
  51. data/lib/sequel/database/transactions.rb +52 -18
  52. data/lib/sequel/dataset/actions.rb +24 -19
  53. data/lib/sequel/dataset/features.rb +5 -0
  54. data/lib/sequel/dataset/query.rb +6 -0
  55. data/lib/sequel/extensions/_pretty_table.rb +1 -1
  56. data/lib/sequel/extensions/error_sql.rb +3 -3
  57. data/lib/sequel/extensions/pg_range.rb +10 -1
  58. data/lib/sequel/extensions/schema_dumper.rb +8 -5
  59. data/lib/sequel/extensions/server_logging.rb +61 -0
  60. data/lib/sequel/extensions/sql_comments.rb +91 -0
  61. data/lib/sequel/model/associations.rb +40 -8
  62. data/lib/sequel/model/base.rb +19 -5
  63. data/lib/sequel/plugins/class_table_inheritance.rb +12 -0
  64. data/lib/sequel/plugins/delay_add_association.rb +1 -0
  65. data/lib/sequel/plugins/json_serializer.rb +10 -2
  66. data/lib/sequel/version.rb +1 -1
  67. data/spec/adapter_spec.rb +4 -0
  68. data/spec/adapters/mysql_spec.rb +1 -1
  69. data/spec/adapters/postgres_spec.rb +3 -2
  70. data/spec/core/connection_pool_spec.rb +2 -0
  71. data/spec/core/database_spec.rb +49 -0
  72. data/spec/core/dataset_spec.rb +25 -1
  73. data/spec/core/mock_adapter_spec.rb +3 -1
  74. data/spec/core/schema_generator_spec.rb +1 -1
  75. data/spec/core_model_spec.rb +2 -0
  76. data/spec/core_spec.rb +1 -0
  77. data/spec/extensions/delay_add_association_spec.rb +22 -0
  78. data/spec/extensions/json_serializer_spec.rb +6 -0
  79. data/spec/extensions/pg_range_spec.rb +30 -2
  80. data/spec/extensions/schema_dumper_spec.rb +3 -2
  81. data/spec/extensions/server_logging_spec.rb +45 -0
  82. data/spec/extensions/sql_comments_spec.rb +27 -0
  83. data/spec/files/reversible_migrations/006_reversible.rb +10 -0
  84. data/spec/files/reversible_migrations/007_reversible.rb +10 -0
  85. data/spec/integration/dataset_test.rb +28 -2
  86. data/spec/integration/migrator_test.rb +23 -1
  87. data/spec/integration/schema_test.rb +12 -32
  88. data/spec/integration/transaction_test.rb +10 -0
  89. data/spec/integration/type_test.rb +1 -1
  90. data/spec/model/eager_loading_spec.rb +16 -0
  91. data/spec/model/record_spec.rb +9 -0
  92. data/spec/model_no_assoc_spec.rb +1 -0
  93. data/spec/model_spec.rb +1 -0
  94. data/spec/plugin_spec.rb +1 -0
  95. metadata +16 -2
@@ -24,9 +24,9 @@ module Sequel
24
24
  def execute_insert(sql, opts=OPTS)
25
25
  synchronize(opts[:server]) do |conn|
26
26
  begin
27
- log_yield(sql){conn.do(sql)}
27
+ log_connection_yield(sql, conn){conn.do(sql)}
28
28
  begin
29
- s = log_yield(LAST_INSERT_ID_SQL){conn.run(LAST_INSERT_ID_SQL)}
29
+ s = log_connection_yield(LAST_INSERT_ID_SQL, conn){conn.run(LAST_INSERT_ID_SQL)}
30
30
  if (rows = s.fetch_all) and (row = rows.first) and (v = row.first)
31
31
  Integer(v)
32
32
  end
@@ -80,10 +80,10 @@ module Sequel
80
80
  if args = opts[:arguments]
81
81
  r = conn.parse(sql)
82
82
  args = cursor_bind_params(conn, r, args)
83
- nr = log_yield(sql, args){r.exec}
83
+ nr = log_connection_yield(sql, conn, args){r.exec}
84
84
  r = nr unless block_given?
85
85
  else
86
- r = log_yield(sql){conn.exec(sql)}
86
+ r = log_connection_yield(sql, conn){conn.exec(sql)}
87
87
  end
88
88
  if block_given?
89
89
  begin
@@ -172,7 +172,7 @@ module Sequel
172
172
  end
173
173
  end
174
174
  unless cursor
175
- cursor = log_yield("PREPARE #{name}: #{sql}"){conn.parse(sql)}
175
+ cursor = log_connection_yield("PREPARE #{name}: #{sql}", conn){conn.parse(sql)}
176
176
  conn.prepared_statements[name] = [cursor, sql]
177
177
  end
178
178
  args = cursor_bind_params(conn, cursor, opts[:arguments])
@@ -182,7 +182,7 @@ module Sequel
182
182
  log_sql << sql
183
183
  log_sql << ")"
184
184
  end
185
- r = log_yield(log_sql, args){cursor.exec}
185
+ r = log_connection_yield(log_sql, conn, args){cursor.exec}
186
186
  if block_given?
187
187
  yield(cursor)
188
188
  elsif type == :insert
@@ -201,7 +201,7 @@ module Sequel
201
201
  if sequence
202
202
  sql = "SELECT #{literal(sequence)}.currval FROM dual"
203
203
  begin
204
- cursor = log_yield(sql){conn.exec(sql)}
204
+ cursor = log_connection_yield(sql, conn){conn.exec(sql)}
205
205
  row = cursor.fetch
206
206
  row.each{|v| return (v.to_i if v)}
207
207
  rescue OCIError
@@ -213,12 +213,12 @@ module Sequel
213
213
  end
214
214
 
215
215
  def begin_transaction(conn, opts=OPTS)
216
- log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
216
+ log_connection_yield(TRANSACTION_BEGIN, conn){conn.autocommit = false}
217
217
  set_transaction_isolation(conn, opts)
218
218
  end
219
219
 
220
220
  def commit_transaction(conn, opts=OPTS)
221
- log_yield(TRANSACTION_COMMIT){conn.commit}
221
+ log_connection_yield(TRANSACTION_COMMIT, conn){conn.commit}
222
222
  end
223
223
 
224
224
  def disconnect_error?(e, opts)
@@ -250,7 +250,7 @@ module Sequel
250
250
  end
251
251
 
252
252
  def rollback_transaction(conn, opts=OPTS)
253
- log_yield(TRANSACTION_ROLLBACK){conn.rollback}
253
+ log_connection_yield(TRANSACTION_ROLLBACK, conn){conn.rollback}
254
254
  end
255
255
 
256
256
  def schema_parse_table(table, opts=OPTS)
@@ -283,7 +283,7 @@ module Sequel
283
283
 
284
284
  metadata = synchronize(opts[:server]) do |conn|
285
285
  begin
286
- log_yield("Connection.describe_table"){conn.describe_table(schema_and_table)}
286
+ log_connection_yield("Connection.describe_table", conn){conn.describe_table(schema_and_table)}
287
287
  rescue OCIError => e
288
288
  raise_error(e)
289
289
  end
@@ -183,7 +183,7 @@ module Sequel
183
183
  # Return the PGResult object that is returned by executing the given
184
184
  # sql and args.
185
185
  def execute_query(sql, args)
186
- @db.log_yield(sql, args){args ? async_exec(sql, args) : async_exec(sql)}
186
+ @db.log_connection_yield(sql, self, args){args ? async_exec(sql, args) : async_exec(sql)}
187
187
  end
188
188
  end
189
189
 
@@ -584,7 +584,7 @@ module Sequel
584
584
 
585
585
  unless conn.prepared_statements[ps_name] == sql
586
586
  conn.execute("DEALLOCATE #{ps_name}") if conn.prepared_statements.include?(ps_name)
587
- conn.check_disconnect_errors{log_yield("PREPARE #{ps_name} AS #{sql}"){conn.prepare(ps_name, sql)}}
587
+ conn.check_disconnect_errors{log_connection_yield("PREPARE #{ps_name} AS #{sql}", conn){conn.prepare(ps_name, sql)}}
588
588
  conn.prepared_statements[ps_name] = sql
589
589
  end
590
590
 
@@ -595,7 +595,7 @@ module Sequel
595
595
  log_sql << ")"
596
596
  end
597
597
 
598
- q = conn.check_disconnect_errors{log_yield(log_sql, args){_execute_prepared_statement(conn, ps_name, args, opts)}}
598
+ q = conn.check_disconnect_errors{log_connection_yield(log_sql, conn, args){_execute_prepared_statement(conn, ps_name, args, opts)}}
599
599
  begin
600
600
  block_given? ? yield(q) : q.cmd_tuples
601
601
  ensure
@@ -516,8 +516,10 @@ module Sequel
516
516
  BOOL_TRUE = '1'.freeze
517
517
  BOOL_FALSE = '0'.freeze
518
518
  COMMA_SEPARATOR = ', '.freeze
519
- NOLOCK = ' WITH (NOLOCK)'.freeze
520
- UPDLOCK = ' WITH (UPDLOCK)'.freeze
519
+ TABLE_HINT = " WITH (".freeze
520
+ READPAST = "READPAST".freeze
521
+ NOLOCK = 'NOLOCK'.freeze
522
+ UPDLOCK = 'UPDLOCK'.freeze
521
523
  WILDCARD = LiteralString.new('*').freeze
522
524
  CONSTANT_MAP = {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}
523
525
  EXTRACT_MAP = {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}
@@ -732,7 +734,7 @@ module Sequel
732
734
  is_2005_or_later?
733
735
  end
734
736
 
735
- # MSSQL 2005+ supports GROUPING SETS
737
+ # MSSQL 2008+ supports GROUPING SETS
736
738
  def supports_grouping_sets?
737
739
  is_2008_or_later?
738
740
  end
@@ -782,6 +784,11 @@ module Sequel
782
784
  supports_insert_select?
783
785
  end
784
786
 
787
+ # MSSQL uses READPAST to skip locked rows.
788
+ def supports_skip_locked?
789
+ true
790
+ end
791
+
785
792
  # MSSQL 2005+ supports window functions
786
793
  def supports_window_functions?
787
794
  true
@@ -965,11 +972,32 @@ module Sequel
965
972
 
966
973
  # Support different types of locking styles
967
974
  def select_lock_sql(sql)
968
- case @opts[:lock]
969
- when :update
970
- sql << UPDLOCK
971
- when :dirty
972
- sql << NOLOCK
975
+ lock = @opts[:lock]
976
+ skip_locked = @opts[:skip_locked]
977
+ for_update = lock == :update
978
+ dirty = lock == :dirty
979
+ lock_hint = for_update || dirty
980
+
981
+ if lock_hint || skip_locked
982
+ sql << TABLE_HINT
983
+
984
+ if lock_hint
985
+ sql << if for_update
986
+ UPDLOCK
987
+ else
988
+ NOLOCK
989
+ end
990
+ end
991
+
992
+ if lock_hint && skip_locked
993
+ sql << COMMA_SEPARATOR
994
+ end
995
+
996
+ if skip_locked
997
+ sql << READPAST
998
+ end
999
+
1000
+ sql << PAREN_CLOSE
973
1001
  else
974
1002
  super
975
1003
  end
@@ -287,6 +287,7 @@ module Sequel
287
287
  HSTAR = "H*".freeze
288
288
  DUAL = ' FROM DUAL'.freeze
289
289
  BITAND_PROC = lambda{|a, b| Sequel.lit(["CAST(BITAND(", ", ", ") AS INTEGER)"], a, b)}
290
+ SKIP_LOCKED = " SKIP LOCKED".freeze
290
291
 
291
292
  include(Module.new do
292
293
  Dataset.def_sql_method(self, :select, %w'with select distinct columns from join where group having compounds order lock')
@@ -431,6 +432,11 @@ module Sequel
431
432
  false
432
433
  end
433
434
 
435
+ # Oracle supports SKIP LOCKED.
436
+ def supports_skip_locked?
437
+ true
438
+ end
439
+
434
440
  # Oracle supports timezones in literal timestamps.
435
441
  def supports_timestamp_timezones?
436
442
  true
@@ -536,6 +542,15 @@ module Sequel
536
542
  :union
537
543
  end
538
544
 
545
+ # Use SKIP LOCKED if skipping locked rows.
546
+ def select_lock_sql(sql)
547
+ super
548
+
549
+ if @opts[:skip_locked]
550
+ sql << SKIP_LOCKED
551
+ end
552
+ end
553
+
539
554
  # Oracle supports quoted function names.
540
555
  def supports_quoted_function_names?
541
556
  true
@@ -1214,6 +1214,7 @@ module Sequel
1214
1214
  SELECT_VALUES = "VALUES ".freeze
1215
1215
  EMPTY_STRING = ''.freeze
1216
1216
  LOCK_MODES = ['ACCESS SHARE', 'ROW SHARE', 'ROW EXCLUSIVE', 'SHARE UPDATE EXCLUSIVE', 'SHARE', 'SHARE ROW EXCLUSIVE', 'EXCLUSIVE', 'ACCESS EXCLUSIVE'].each(&:freeze)
1217
+ SKIP_LOCKED = " SKIP LOCKED".freeze
1217
1218
 
1218
1219
  Dataset.def_sql_method(self, :delete, [['if server_version >= 90100', %w'with delete from using where returning'], ['else', %w'delete from using where returning']])
1219
1220
  Dataset.def_sql_method(self, :insert, [['if server_version >= 90500', %w'with insert into columns values conflict returning'], ['elsif server_version >= 90100', %w'with insert into columns values returning'], ['else', %w'insert into columns values returning']])
@@ -1305,6 +1306,8 @@ module Sequel
1305
1306
  # of any of the terms in any of the cols.
1306
1307
  #
1307
1308
  # Options:
1309
+ # :headline :: Append a expression to the selected columns aliased to headline that
1310
+ # contains an extract of the matched text.
1308
1311
  # :language :: The language to use for the search (default: 'simple')
1309
1312
  # :plain :: Whether a plain search should be used (default: false). In this case,
1310
1313
  # terms should be a single string, and it will do a search where cols
@@ -1341,6 +1344,10 @@ module Sequel
1341
1344
  ds = ds.reverse{ts_rank_cd(cols, terms)}
1342
1345
  end
1343
1346
 
1347
+ if opts[:headline]
1348
+ ds = ds.select_append{ts_headline(lang, phrase_cols, terms).as(:headline)}
1349
+ end
1350
+
1344
1351
  ds
1345
1352
  end
1346
1353
 
@@ -1504,6 +1511,11 @@ module Sequel
1504
1511
  true
1505
1512
  end
1506
1513
 
1514
+ # PostgreSQL 9.5+ supports SKIP LOCKED.
1515
+ def supports_skip_locked?
1516
+ server_version >= 90500
1517
+ end
1518
+
1507
1519
  # PostgreSQL supports timezones in literal timestamps
1508
1520
  def supports_timestamp_timezones?
1509
1521
  true
@@ -1684,8 +1696,17 @@ module Sequel
1684
1696
  end
1685
1697
 
1686
1698
  # Support FOR SHARE locking when using the :share lock style.
1699
+ # Use SKIP LOCKED if skipping locked rows.
1687
1700
  def select_lock_sql(sql)
1688
- @opts[:lock] == :share ? (sql << FOR_SHARE) : super
1701
+ if @opts[:lock] == :share
1702
+ sql << FOR_SHARE
1703
+ else
1704
+ super
1705
+ end
1706
+
1707
+ if @opts[:skip_locked]
1708
+ sql << SKIP_LOCKED
1709
+ end
1689
1710
  end
1690
1711
 
1691
1712
  # Support VALUES clause instead of the SELECT clause to return rows.
@@ -102,7 +102,7 @@ module Sequel
102
102
 
103
103
  LAST_INSERT_ID = 'SELECT @@IDENTITY'.freeze
104
104
  def _execute(conn, type, sql, opts)
105
- unless rs = log_yield(sql){@api.sqlany_execute_direct(conn, sql)}
105
+ unless rs = log_connection_yield(sql, conn){@api.sqlany_execute_direct(conn, sql)}
106
106
  result, errstr = @api.sqlany_error(conn)
107
107
  raise_error(SQLAnywhereException.new(errstr, result, sql))
108
108
  end
@@ -109,7 +109,7 @@ module Sequel
109
109
  db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts)
110
110
  db.busy_timeout(opts.fetch(:timeout, 5000))
111
111
 
112
- connection_pragmas.each{|s| log_yield(s){db.execute_batch(s)}}
112
+ connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}}
113
113
 
114
114
  class << db
115
115
  attr_reader :prepared_statements
@@ -184,12 +184,12 @@ module Sequel
184
184
  opts.fetch(:arguments, {}).each{|k, v| args[k] = prepared_statement_argument(v)}
185
185
  case type
186
186
  when :select
187
- log_yield(sql, log_args){conn.query(sql, args, &block)}
187
+ log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)}
188
188
  when :insert
189
- log_yield(sql, log_args){conn.execute(sql, args)}
189
+ log_connection_yield(sql, conn, log_args){conn.execute(sql, args)}
190
190
  conn.last_insert_row_id
191
191
  when :update
192
- log_yield(sql, log_args){conn.execute_batch(sql, args)}
192
+ log_connection_yield(sql, conn, log_args){conn.execute_batch(sql, args)}
193
193
  conn.changes
194
194
  end
195
195
  end
@@ -241,7 +241,7 @@ module Sequel
241
241
  end
242
242
  end
243
243
  unless cps
244
- cps = log_yield("PREPARE #{name}: #{sql}"){conn.prepare(sql)}
244
+ cps = log_connection_yield("PREPARE #{name}: #{sql}", conn){conn.prepare(sql)}
245
245
  conn.prepared_statements[name] = [cps, sql]
246
246
  end
247
247
  log_sql = String.new
@@ -252,9 +252,9 @@ module Sequel
252
252
  log_sql << ")"
253
253
  end
254
254
  if block
255
- log_yield(log_sql, args){cps.execute(ps_args, &block)}
255
+ log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)}
256
256
  else
257
- log_yield(log_sql, args){cps.execute!(ps_args){|r|}}
257
+ log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}}
258
258
  case type
259
259
  when :insert
260
260
  conn.last_insert_row_id
@@ -50,7 +50,7 @@ module Sequel
50
50
  def execute(sql, opts=OPTS)
51
51
  synchronize(opts[:server]) do |conn|
52
52
  begin
53
- res = log_yield(sql){conn.execute(sql)}
53
+ res = log_connection_yield(sql, conn){conn.execute(sql)}
54
54
  yield res if block_given?
55
55
  nil
56
56
  rescue ::Swift::Error => e
@@ -64,7 +64,7 @@ module Sequel
64
64
  def execute_dui(sql, opts=OPTS)
65
65
  synchronize(opts[:server]) do |conn|
66
66
  begin
67
- log_yield(sql){conn.execute(sql).affected_rows}
67
+ log_connection_yield(sql, conn){conn.execute(sql).affected_rows}
68
68
  rescue ::Swift::Error => e
69
69
  raise_error(e)
70
70
  end
@@ -76,7 +76,7 @@ module Sequel
76
76
  def execute_insert(sql, opts=OPTS)
77
77
  synchronize(opts[:server]) do |conn|
78
78
  begin
79
- log_yield(sql){conn.execute(sql).insert_id}
79
+ log_connection_yield(sql, conn){conn.execute(sql).insert_id}
80
80
  rescue ::Swift::Error => e
81
81
  raise_error(e)
82
82
  end
@@ -27,7 +27,7 @@ module Sequel
27
27
 
28
28
  # Apply the connectiong setting SQLs for every new connection.
29
29
  def setup_connection(conn)
30
- mysql_connection_setting_sqls.each{|sql| log_yield(sql){conn.execute(sql)}}
30
+ mysql_connection_setting_sqls.each{|sql| log_connection_yield(sql, conn){conn.execute(sql)}}
31
31
  super
32
32
  end
33
33
  end
@@ -38,7 +38,7 @@ module Sequel
38
38
  def setup_connection(conn)
39
39
  conn = super(conn)
40
40
  conn.native_bind_format = true
41
- connection_configuration_sqls.each{|sql| log_yield(sql){conn.execute(sql)}}
41
+ connection_configuration_sqls.each{|sql| log_connection_yield(sql, conn){conn.execute(sql)}}
42
42
  conn
43
43
  end
44
44
  end
@@ -28,7 +28,7 @@ module Sequel
28
28
  # Set the correct pragmas on the connection.
29
29
  def connect(opts)
30
30
  c = super
31
- connection_pragmas.each{|s| log_yield(s){c.execute(s)}}
31
+ connection_pragmas.each{|s| log_connection_yield(s, c){c.execute(s)}}
32
32
  c
33
33
  end
34
34
  end
@@ -18,7 +18,7 @@ module Sequel
18
18
 
19
19
  if (ts = opts[:textsize])
20
20
  sql = "SET TEXTSIZE #{typecast_value_integer(ts)}"
21
- log_yield(sql){c.execute(sql)}
21
+ log_connection_yield(sql, c){c.execute(sql)}
22
22
  end
23
23
 
24
24
  c
@@ -52,12 +52,12 @@ module Sequel
52
52
  single_value = true
53
53
  end
54
54
  sql = "EXEC sp_executesql N'#{c.escape(sql)}', N'#{c.escape(types.join(', '))}', #{values.join(', ')}"
55
- log_yield(sql) do
55
+ log_connection_yield(sql, c) do
56
56
  r = c.execute(sql)
57
57
  r.each{|row| return row.values.first} if single_value
58
58
  end
59
59
  else
60
- log_yield(sql) do
60
+ log_connection_yield(sql, c) do
61
61
  r = c.execute(sql)
62
62
  return r.send(m) if m
63
63
  end
@@ -139,16 +139,14 @@ module Sequel
139
139
 
140
140
  # Dispose of any possible results of execution.
141
141
  def log_connection_execute(conn, sql)
142
- log_yield(sql){conn.execute(sql).each}
142
+ log_connection_yield(sql, conn){conn.execute(sql).each}
143
143
  end
144
144
 
145
145
  # Return a 2 element array with the literal value and type to use
146
146
  # in the prepared statement call for the given value and connection.
147
147
  def ps_arg_type(v)
148
148
  case v
149
- when Fixnum
150
- [v, 'int']
151
- when Bignum
149
+ when Integer
152
150
  [v, 'bigint']
153
151
  when Float
154
152
  [v, 'double precision']
@@ -14,6 +14,9 @@ module Sequel
14
14
  # Array of SQL loggers to use for this database.
15
15
  attr_accessor :loggers
16
16
 
17
+ # Whether to include information about the connection in use when logging queries.
18
+ attr_accessor :log_connection_info
19
+
17
20
  # Log level at which to log SQL queries. This is actually the method
18
21
  # sent to the logger, so it should be the method name symbol. The default
19
22
  # is :info, it can be set to :debug to log at DEBUG level.
@@ -31,9 +34,15 @@ module Sequel
31
34
 
32
35
  # Yield to the block, logging any errors at error level to all loggers,
33
36
  # and all other queries with the duration at warn or info level.
34
- def log_yield(sql, args=nil)
37
+ def log_yield(sql, args=nil, &block)
38
+ log_connection_yield(sql, nil, args, &block)
39
+ end
40
+
41
+ # Yield to the block, logging any errors at error level to all loggers,
42
+ # and all other queries with the duration at warn or info level.
43
+ def log_connection_yield(sql, conn, args=nil)
35
44
  return yield if @loggers.empty?
36
- sql = "#{sql}; #{args.inspect}" if args
45
+ sql = "#{connection_info(conn) if conn && log_connection_info}#{sql}#{"; #{args.inspect}" if args}"
37
46
  start = Time.now
38
47
  begin
39
48
  yield
@@ -53,11 +62,17 @@ module Sequel
53
62
  end
54
63
 
55
64
  private
65
+
66
+ # String including information about the connection, for use when logging
67
+ # connection info.
68
+ def connection_info(conn)
69
+ "(conn: #{conn.__id__}) "
70
+ end
56
71
 
57
72
  # Log the given SQL and then execute it on the connection, used by
58
73
  # the transaction code.
59
74
  def log_connection_execute(conn, sql)
60
- log_yield(sql){conn.send(connection_execute_method, sql)}
75
+ log_connection_yield(sql, conn){conn.send(connection_execute_method, sql)}
61
76
  end
62
77
 
63
78
  # Log message with message prefixed by duration at info level, or