sequel 3.0.0 → 3.1.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 (87) hide show
  1. data/CHANGELOG +100 -0
  2. data/README.rdoc +3 -3
  3. data/bin/sequel +102 -19
  4. data/doc/reflection.rdoc +83 -0
  5. data/doc/release_notes/3.1.0.txt +406 -0
  6. data/lib/sequel/adapters/ado.rb +11 -0
  7. data/lib/sequel/adapters/amalgalite.rb +5 -20
  8. data/lib/sequel/adapters/do.rb +44 -36
  9. data/lib/sequel/adapters/firebird.rb +29 -43
  10. data/lib/sequel/adapters/jdbc.rb +17 -27
  11. data/lib/sequel/adapters/mysql.rb +35 -40
  12. data/lib/sequel/adapters/odbc.rb +4 -23
  13. data/lib/sequel/adapters/oracle.rb +22 -19
  14. data/lib/sequel/adapters/postgres.rb +6 -15
  15. data/lib/sequel/adapters/shared/mssql.rb +1 -1
  16. data/lib/sequel/adapters/shared/mysql.rb +29 -10
  17. data/lib/sequel/adapters/shared/oracle.rb +6 -8
  18. data/lib/sequel/adapters/shared/postgres.rb +28 -72
  19. data/lib/sequel/adapters/shared/sqlite.rb +5 -3
  20. data/lib/sequel/adapters/sqlite.rb +5 -20
  21. data/lib/sequel/adapters/utils/savepoint_transactions.rb +80 -0
  22. data/lib/sequel/adapters/utils/unsupported.rb +0 -12
  23. data/lib/sequel/core.rb +12 -3
  24. data/lib/sequel/core_sql.rb +1 -8
  25. data/lib/sequel/database.rb +107 -43
  26. data/lib/sequel/database/schema_generator.rb +1 -0
  27. data/lib/sequel/database/schema_methods.rb +38 -4
  28. data/lib/sequel/dataset.rb +6 -0
  29. data/lib/sequel/dataset/convenience.rb +2 -2
  30. data/lib/sequel/dataset/graph.rb +2 -2
  31. data/lib/sequel/dataset/prepared_statements.rb +3 -8
  32. data/lib/sequel/dataset/sql.rb +93 -19
  33. data/lib/sequel/extensions/blank.rb +2 -1
  34. data/lib/sequel/extensions/inflector.rb +4 -3
  35. data/lib/sequel/extensions/migration.rb +13 -2
  36. data/lib/sequel/extensions/pagination.rb +4 -0
  37. data/lib/sequel/extensions/pretty_table.rb +4 -0
  38. data/lib/sequel/extensions/query.rb +4 -0
  39. data/lib/sequel/extensions/schema_dumper.rb +100 -24
  40. data/lib/sequel/extensions/string_date_time.rb +3 -4
  41. data/lib/sequel/model.rb +2 -1
  42. data/lib/sequel/model/associations.rb +96 -38
  43. data/lib/sequel/model/base.rb +14 -14
  44. data/lib/sequel/model/plugins.rb +32 -21
  45. data/lib/sequel/plugins/caching.rb +13 -15
  46. data/lib/sequel/plugins/identity_map.rb +107 -0
  47. data/lib/sequel/plugins/lazy_attributes.rb +65 -0
  48. data/lib/sequel/plugins/many_through_many.rb +188 -0
  49. data/lib/sequel/plugins/schema.rb +13 -0
  50. data/lib/sequel/plugins/serialization.rb +53 -37
  51. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  52. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  53. data/lib/sequel/plugins/validation_class_methods.rb +28 -7
  54. data/lib/sequel/plugins/validation_helpers.rb +31 -24
  55. data/lib/sequel/sql.rb +16 -0
  56. data/lib/sequel/version.rb +1 -1
  57. data/spec/adapters/ado_spec.rb +47 -1
  58. data/spec/adapters/firebird_spec.rb +39 -36
  59. data/spec/adapters/mysql_spec.rb +25 -9
  60. data/spec/adapters/postgres_spec.rb +11 -24
  61. data/spec/core/database_spec.rb +54 -13
  62. data/spec/core/dataset_spec.rb +147 -29
  63. data/spec/core/object_graph_spec.rb +6 -1
  64. data/spec/core/schema_spec.rb +34 -0
  65. data/spec/core/spec_helper.rb +0 -2
  66. data/spec/extensions/caching_spec.rb +7 -0
  67. data/spec/extensions/identity_map_spec.rb +158 -0
  68. data/spec/extensions/lazy_attributes_spec.rb +113 -0
  69. data/spec/extensions/many_through_many_spec.rb +813 -0
  70. data/spec/extensions/migration_spec.rb +4 -4
  71. data/spec/extensions/schema_dumper_spec.rb +114 -13
  72. data/spec/extensions/schema_spec.rb +19 -3
  73. data/spec/extensions/serialization_spec.rb +28 -0
  74. data/spec/extensions/single_table_inheritance_spec.rb +25 -1
  75. data/spec/extensions/spec_helper.rb +2 -7
  76. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  77. data/spec/extensions/validation_class_methods_spec.rb +10 -5
  78. data/spec/integration/dataset_test.rb +39 -6
  79. data/spec/integration/eager_loader_test.rb +7 -7
  80. data/spec/integration/spec_helper.rb +0 -1
  81. data/spec/integration/transaction_test.rb +28 -1
  82. data/spec/model/association_reflection_spec.rb +29 -3
  83. data/spec/model/associations_spec.rb +1 -0
  84. data/spec/model/eager_loading_spec.rb +70 -1
  85. data/spec/model/plugins_spec.rb +236 -50
  86. data/spec/model/spec_helper.rb +0 -2
  87. metadata +18 -5
@@ -1,8 +1,10 @@
1
- Sequel.require 'adapters/utils/unsupported'
1
+ Sequel.require %w'savepoint_transactions unsupported', 'adapters/utils'
2
2
 
3
3
  module Sequel
4
4
  module SQLite
5
5
  module DatabaseMethods
6
+ include Sequel::Database::SavepointTransactions
7
+
6
8
  AUTO_VACUUM = [:none, :full, :incremental].freeze
7
9
  PRIMARY_KEY_INDEX_RE = /\Asqlite_autoindex_/.freeze
8
10
  SYNCHRONOUS = [:off, :normal, :full].freeze
@@ -199,7 +201,7 @@ module Sequel
199
201
  row[:allow_null] = row.delete(:notnull).to_i == 0
200
202
  row[:default] = row.delete(:dflt_value)
201
203
  row[:primary_key] = row.delete(:pk).to_i == 1
202
- row[:default] = nil if blank_object?(row[:default])
204
+ row[:default] = nil if blank_object?(row[:default]) || row[:default] == 'NULL'
203
205
  row[:db_type] = row.delete(:type)
204
206
  row[:type] = schema_column_type(row[:db_type])
205
207
  row
@@ -264,7 +266,7 @@ module Sequel
264
266
  # Allow inserting of values directly from a dataset.
265
267
  def insert_sql(*values)
266
268
  if (values.size == 1) && values.first.is_a?(Sequel::Dataset)
267
- "INSERT INTO #{source_list(@opts[:from])} #{values.first.sql};"
269
+ "#{insert_sql_base}#{source_list(@opts[:from])} #{values.first.sql};"
268
270
  else
269
271
  super(*values)
270
272
  end
@@ -83,26 +83,6 @@ module Sequel
83
83
  _execute(sql, opts){|conn| conn.get_first_value(sql, opts[:arguments])}
84
84
  end
85
85
 
86
- # Use the native driver transaction method if there isn't already a transaction
87
- # in progress on the connection, always yielding a connection inside a transaction
88
- # transaction.
89
- def transaction(opts={})
90
- synchronize(opts[:server]) do |conn|
91
- return yield(conn) if conn.transaction_active?
92
- begin
93
- result = nil
94
- log_info('Transaction.begin')
95
- conn.transaction{result = yield(conn)}
96
- result
97
- rescue ::Exception => e
98
- log_info('Transaction.rollback')
99
- transaction_error(e, SQLite3::Exception)
100
- ensure
101
- log_info('Transaction.commit') unless e
102
- end
103
- end
104
- end
105
-
106
86
  private
107
87
 
108
88
  # Log the SQL and the arguments, and yield an available connection. Rescue
@@ -126,6 +106,11 @@ module Sequel
126
106
  o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database])
127
107
  o
128
108
  end
109
+
110
+ # The main error class that SQLite3 raises
111
+ def database_error_classes
112
+ [SQLite3::Exception]
113
+ end
129
114
 
130
115
  # Disconnect given connections from the database.
131
116
  def disconnect_connection(c)
@@ -0,0 +1,80 @@
1
+ # Module included in adapters that support savepoints, currently MySQL and PostgreSQL.
2
+ module Sequel
3
+ class Database
4
+ module SavepointTransactions
5
+ SQL_SAVEPOINT = 'SAVEPOINT autopoint_%d'.freeze
6
+ SQL_ROLLBACK_TO_SAVEPOINT = 'ROLLBACK TO SAVEPOINT autopoint_%d'.freeze
7
+ SQL_RELEASE_SAVEPOINT = 'RELEASE SAVEPOINT autopoint_%d'.freeze
8
+
9
+ # Any adapter that includes this module must support savepoints.
10
+ def supports_savepoints?
11
+ true
12
+ end
13
+
14
+ private
15
+
16
+ # Don't add the current thread to the list of threads with active
17
+ # connections if it is already in the list. If there isn't an
18
+ # active transaction on this thread, set the transaction depth to
19
+ # zero.
20
+ def add_transaction
21
+ th = Thread.current
22
+ unless @transactions.include?(th)
23
+ th[:sequel_transaction_depth] = 0
24
+ super
25
+ end
26
+ end
27
+
28
+ # If a savepoint is requested, don't reuse an existing transaction
29
+ def already_in_transaction?(conn, opts)
30
+ super and !opts[:savepoint]
31
+ end
32
+
33
+ # SQL to start a new savepoint
34
+ def begin_savepoint_sql(depth)
35
+ SQL_SAVEPOINT % depth
36
+ end
37
+
38
+ # If there is no active transaction, start a new transaction. Otherwise,
39
+ # start a savepoint inside the current transaction. Increment the
40
+ def begin_transaction(conn)
41
+ th = Thread.current
42
+ depth = th[:sequel_transaction_depth]
43
+ conn = transaction_statement_object(conn) if respond_to?(:transaction_statement_object, true)
44
+ log_connection_execute(conn, depth > 0 ? begin_savepoint_sql(depth) : begin_transaction_sql)
45
+ th[:sequel_transaction_depth] += 1
46
+ conn
47
+ end
48
+
49
+ # SQL to commit a savepoint
50
+ def commit_savepoint_sql(depth)
51
+ SQL_RELEASE_SAVEPOINT % depth
52
+ end
53
+
54
+ # If currently inside a savepoint, commit/release the savepoint.
55
+ # Otherwise, commit the transaction.
56
+ def commit_transaction(conn)
57
+ depth = Thread.current[:sequel_transaction_depth]
58
+ log_connection_execute(conn, depth > 1 ? commit_savepoint_sql(depth-1) : commit_transaction_sql)
59
+ end
60
+
61
+ # Decrement the current savepoint/transaction depth
62
+ def remove_transaction(conn)
63
+ depth = (Thread.current[:sequel_transaction_depth] -= 1)
64
+ super unless depth > 0
65
+ end
66
+
67
+ # SQL to rollback to a savepoint
68
+ def rollback_savepoint_sql(depth)
69
+ SQL_ROLLBACK_TO_SAVEPOINT % depth
70
+ end
71
+
72
+ # If currently inside a savepoint, rollback to the start of the savepoint.
73
+ # Otherwise, rollback the entire transaction.
74
+ def rollback_transaction(conn)
75
+ depth = Thread.current[:sequel_transaction_depth]
76
+ log_connection_execute(conn, depth > 1 ? rollback_savepoint_sql(depth-1) : rollback_transaction_sql)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -11,18 +11,6 @@ class Sequel::Dataset
11
11
  def intersect(ds, all=false)
12
12
  raise(Sequel::Error, "INTERSECT not supported")
13
13
  end
14
-
15
- private
16
-
17
- # Since EXCEPT and INTERSECT are not supported, and order shouldn't matter
18
- # when UNION is used, don't worry about parantheses. This may potentially
19
- # give incorrect results if UNION ALL is used.
20
- def select_compounds_sql(sql)
21
- return unless @opts[:compounds]
22
- @opts[:compounds].each do |type, dataset, all|
23
- sql << " #{type.to_s.upcase}#{' ALL' if all} #{subselect_sql(dataset)}"
24
- end
25
- end
26
14
  end
27
15
 
28
16
  # This module should be included in the dataset class for all databases that
data/lib/sequel/core.rb CHANGED
@@ -118,6 +118,15 @@ module Sequel
118
118
  Database.quote_identifiers = value
119
119
  end
120
120
 
121
+ # Load all Sequel extensions given. Only loads extensions included in this
122
+ # release of Sequel, doesn't load external extensions.
123
+ #
124
+ # Sequel.extension(:schema_dumper)
125
+ # Sequel.extension(:pagination, :query)
126
+ def self.extension(*extensions)
127
+ require(extensions, 'extensions')
128
+ end
129
+
121
130
  # Require all given files which should be in the same or a subdirectory of
122
131
  # this file. If a subdir is given, assume all files are in that subdir.
123
132
  def self.require(files, subdir=nil)
@@ -139,7 +148,7 @@ module Sequel
139
148
  begin
140
149
  Date.parse(s, Sequel.convert_two_digit_years)
141
150
  rescue => e
142
- raise InvalidValue, "Invalid Date value '#{self}' (#{e.message})"
151
+ raise InvalidValue, "Invalid Date value #{s.inspect} (#{e.message})"
143
152
  end
144
153
  end
145
154
 
@@ -153,7 +162,7 @@ module Sequel
153
162
  datetime_class.parse(s)
154
163
  end
155
164
  rescue => e
156
- raise InvalidValue, "Invalid #{datetime_class} value '#{self}' (#{e.message})"
165
+ raise InvalidValue, "Invalid #{datetime_class} value #{s.inspect} (#{e.message})"
157
166
  end
158
167
  end
159
168
 
@@ -162,7 +171,7 @@ module Sequel
162
171
  begin
163
172
  Time.parse(s)
164
173
  rescue => e
165
- raise InvalidValue, "Invalid Time value '#{self}' (#{e.message})"
174
+ raise InvalidValue, "Invalid Time value #{s.inspect} (#{e.message})"
166
175
  end
167
176
  end
168
177
 
@@ -210,6 +210,7 @@ class Symbol
210
210
  include Sequel::SQL::BooleanMethods
211
211
  include Sequel::SQL::NumericMethods
212
212
  include Sequel::SQL::StringMethods
213
+ include Sequel::SQL::SubscriptMethods
213
214
  include Sequel::SQL::ComplexExpressionMethods
214
215
  include Sequel::SQL::InequalityMethods if RUBY_VERSION < '1.9.0'
215
216
 
@@ -237,12 +238,4 @@ class Symbol
237
238
  Sequel::SQL::Function.new(self, *args)
238
239
  end
239
240
  alias_method(:[], :sql_function) if RUBY_VERSION < '1.9.0'
240
-
241
- # Return an SQL array subscript with the given arguments.
242
- #
243
- # :array.sql_subscript(1) # SQL: array[1]
244
- # :array.sql_subscript(1, 2) # SQL: array[1, 2]
245
- def sql_subscript(*sub)
246
- Sequel::SQL::Subscript.new(self, sub.flatten)
247
- end
248
241
  end
@@ -17,11 +17,15 @@ module Sequel
17
17
  include Metaprogramming
18
18
 
19
19
  # Array of supported database adapters
20
- ADAPTERS = %w'ado db2 dbi do firebird informix jdbc mysql odbc openbase oracle postgres sqlite'.collect{|x| x.to_sym}
20
+ ADAPTERS = %w'ado amalgalite db2 dbi do firebird informix jdbc mysql odbc openbase oracle postgres sqlite'.collect{|x| x.to_sym}
21
21
 
22
22
  SQL_BEGIN = 'BEGIN'.freeze
23
23
  SQL_COMMIT = 'COMMIT'.freeze
24
24
  SQL_ROLLBACK = 'ROLLBACK'.freeze
25
+
26
+ TRANSACTION_BEGIN = 'Transaction.begin'.freeze
27
+ TRANSACTION_COMMIT = 'Transaction.commit'.freeze
28
+ TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
25
29
 
26
30
  # The identifier input method to use by default
27
31
  @@identifier_input_method = nil
@@ -70,7 +74,7 @@ module Sequel
70
74
  @opts ||= opts
71
75
 
72
76
  @single_threaded = opts.include?(:single_threaded) ? opts[:single_threaded] : @@single_threaded
73
- @schemas = nil
77
+ @schemas = {}
74
78
  @default_schema = opts.include?(:default_schema) ? opts[:default_schema] : default_schema_default
75
79
  @prepared_statements = {}
76
80
  @transactions = []
@@ -438,13 +442,8 @@ module Sequel
438
442
  quoted_name = quote_schema_table(table)
439
443
  opts = opts.merge(:schema=>sch) if sch && !opts.include?(:schema)
440
444
 
441
- @schemas.delete(quoted_name) if opts[:reload] && @schemas
442
- return @schemas[quoted_name] if @schemas && @schemas[quoted_name]
443
-
444
- @schemas ||= Hash.new do |h,k|
445
- quote_name = quote_schema_table(k)
446
- h[quote_name] if h.include?(quote_name)
447
- end
445
+ @schemas.delete(quoted_name) if opts[:reload]
446
+ return @schemas[quoted_name] if @schemas[quoted_name]
448
447
 
449
448
  cols = schema_parse_table(table_name, opts)
450
449
  raise(Error, 'schema parsing returned no columns, table probably doesn\'t exist') if cols.nil? || cols.empty?
@@ -460,20 +459,21 @@ module Sequel
460
459
  def synchronize(server=nil, &block)
461
460
  @pool.hold(server || :default, &block)
462
461
  end
462
+
463
+ # Whether the database and adapter support savepoints
464
+ def supports_savepoints?
465
+ false
466
+ end
463
467
 
464
468
  # Returns true if a table with the given name exists. This requires a query
465
469
  # to the database unless this database object already has the schema for
466
470
  # the given table name.
467
471
  def table_exists?(name)
468
- if @schemas && @schemas[name]
472
+ begin
473
+ from(name).first
469
474
  true
470
- else
471
- begin
472
- from(name).first
473
- true
474
- rescue
475
- false
476
- end
475
+ rescue
476
+ false
477
477
  end
478
478
  end
479
479
 
@@ -484,29 +484,21 @@ module Sequel
484
484
  true
485
485
  end
486
486
 
487
- # A simple implementation of SQL transactions. Nested transactions are not
488
- # supported - calling #transaction within a transaction will reuse the
489
- # current transaction. Should be overridden for databases that support nested
490
- # transactions.
491
- def transaction(opts={})
487
+ # Starts a database transaction. When a database transaction is used,
488
+ # either all statements are successful or none of the statements are
489
+ # successful. Note that MySQL MyISAM tabels do not support transactions.
490
+ #
491
+ # The following options are respected:
492
+ #
493
+ # * :server - The server to use for the transaction
494
+ # * :savepoint - Whether to create a new savepoint for this transaction,
495
+ # only respected if the database adapter supports savepoints. By
496
+ # default Sequel will reuse an existing transaction, so if you want to
497
+ # use a savepoint you must use this option.
498
+ def transaction(opts={}, &block)
492
499
  synchronize(opts[:server]) do |conn|
493
- return yield(conn) if @transactions.include?(Thread.current)
494
- log_info(begin_transaction_sql)
495
- conn.execute(begin_transaction_sql)
496
- begin
497
- @transactions << Thread.current
498
- yield(conn)
499
- rescue Exception => e
500
- log_info(rollback_transaction_sql)
501
- conn.execute(rollback_transaction_sql)
502
- transaction_error(e)
503
- ensure
504
- unless e
505
- log_info(commit_transaction_sql)
506
- conn.execute(commit_transaction_sql)
507
- end
508
- @transactions.delete(Thread.current)
509
- end
500
+ return yield(conn) if already_in_transaction?(conn, opts)
501
+ _transaction(conn, &block)
510
502
  end
511
503
  end
512
504
 
@@ -554,6 +546,45 @@ module Sequel
554
546
 
555
547
  private
556
548
 
549
+ # Internal generic transaction method. Any exception raised by the given
550
+ # block will cause the transaction to be rolled back. If the exception is
551
+ # not Sequel::Rollback, the error will be reraised. If no exception occurs
552
+ # inside the block, the transaction is commited.
553
+ def _transaction(conn)
554
+ begin
555
+ add_transaction
556
+ t = begin_transaction(conn)
557
+ yield(conn)
558
+ rescue Exception => e
559
+ rollback_transaction(t)
560
+ transaction_error(e)
561
+ ensure
562
+ begin
563
+ commit_transaction(t) unless e
564
+ rescue Exception => e
565
+ raise_error(e, :classes=>database_error_classes)
566
+ ensure
567
+ remove_transaction(t)
568
+ end
569
+ end
570
+ end
571
+
572
+ # Add the current thread to the list of active transactions
573
+ def add_transaction
574
+ @transactions << Thread.current
575
+ end
576
+
577
+ # Whether the current thread/connection is already inside a transaction
578
+ def already_in_transaction?(conn, opts)
579
+ @transactions.include?(Thread.current)
580
+ end
581
+
582
+ # Start a new database transaction on the given connection.
583
+ def begin_transaction(conn)
584
+ log_connection_execute(conn, begin_transaction_sql)
585
+ conn
586
+ end
587
+
557
588
  # SQL to BEGIN a transaction.
558
589
  def begin_transaction_sql
559
590
  SQL_BEGIN
@@ -576,17 +607,33 @@ module Sequel
576
607
  obj.respond_to?(:empty?) ? obj.empty? : false
577
608
  end
578
609
  end
610
+
611
+ # Commit the active transaction on the connection
612
+ def commit_transaction(conn)
613
+ log_connection_execute(conn, commit_transaction_sql)
614
+ end
579
615
 
580
616
  # SQL to COMMIT a transaction.
581
617
  def commit_transaction_sql
582
618
  SQL_COMMIT
583
619
  end
620
+
621
+ # Method called on the connection object to execute SQL on the database,
622
+ # used by the transaction code.
623
+ def connection_execute_method
624
+ :execute
625
+ end
584
626
 
585
627
  # The default options for the connection pool.
586
628
  def connection_pool_default_options
587
629
  {}
588
630
  end
589
631
 
632
+ # Which transaction errors to translate, blank by default.
633
+ def database_error_classes
634
+ []
635
+ end
636
+
590
637
  # The default value for default_schema.
591
638
  def default_schema_default
592
639
  nil
@@ -614,6 +661,13 @@ module Sequel
614
661
  def input_identifier_meth
615
662
  dataset.method(:input_identifier)
616
663
  end
664
+
665
+ # Log the given SQL and then execute it on the connection, used by
666
+ # the transaction code.
667
+ def log_connection_execute(conn, sql)
668
+ log_info(sql)
669
+ conn.send(connection_execute_method, sql)
670
+ end
617
671
 
618
672
  # Return a dataset that uses the default identifier input and output methods
619
673
  # for this database. Used when parsing metadata so that column symbols are
@@ -648,7 +702,7 @@ module Sequel
648
702
  # and traceback.
649
703
  def raise_error(exception, opts={})
650
704
  if !opts[:classes] || Array(opts[:classes]).any?{|c| exception.is_a?(c)}
651
- e = DatabaseError.new("#{exception.class} #{exception.message}")
705
+ e = (opts[:disconnect] ? DatabaseDisconnectError : DatabaseError).new("#{exception.class}: #{exception.message}")
652
706
  e.set_backtrace(exception.backtrace)
653
707
  raise e
654
708
  else
@@ -660,12 +714,22 @@ module Sequel
660
714
  def remove_cached_schema(table)
661
715
  @schemas.delete(quote_schema_table(table)) if @schemas
662
716
  end
717
+
718
+ # Remove the current thread from the list of active transactions
719
+ def remove_transaction(conn)
720
+ @transactions.delete(Thread.current)
721
+ end
663
722
 
664
723
  # Remove the cached schema_utility_dataset, because the identifier
665
724
  # quoting has changed.
666
725
  def reset_schema_utility_dataset
667
726
  @schema_utility_dataset = nil
668
727
  end
728
+
729
+ # Rollback the active transaction on the connection
730
+ def rollback_transaction(conn)
731
+ log_connection_execute(conn, rollback_transaction_sql)
732
+ end
669
733
 
670
734
  # Split the schema information from the table
671
735
  def schema_and_table(table_name)
@@ -686,7 +750,7 @@ module Sequel
686
750
  Sequel.convert_tinyint_to_bool ? :boolean : :integer
687
751
  when /\Ainterval\z/io
688
752
  :interval
689
- when /\A(character( varying)?|varchar|text)/io
753
+ when /\A(character( varying)?|(var)?char|text)/io
690
754
  :string
691
755
  when /\A(int(eger)?|bigint|smallint)/io
692
756
  :integer
@@ -733,8 +797,8 @@ module Sequel
733
797
  end
734
798
 
735
799
  # Raise a database error unless the exception is an Rollback.
736
- def transaction_error(e, *classes)
737
- raise_error(e, :classes=>classes) unless Rollback === e
800
+ def transaction_error(e)
801
+ raise_error(e, :classes=>database_error_classes) unless Rollback === e
738
802
  end
739
803
 
740
804
  # Typecast the value to an SQL::Blob