sequel 4.34.0 → 4.35.0

Sign up to get free protection for your applications and to get access to all the features.
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