sequel 3.0.0 → 3.1.0

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