sequel 3.28.0 → 3.29.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 (148) hide show
  1. data/CHANGELOG +119 -3
  2. data/Rakefile +5 -3
  3. data/bin/sequel +1 -5
  4. data/doc/model_hooks.rdoc +9 -1
  5. data/doc/opening_databases.rdoc +49 -40
  6. data/doc/prepared_statements.rdoc +27 -6
  7. data/doc/release_notes/3.28.0.txt +2 -2
  8. data/doc/release_notes/3.29.0.txt +459 -0
  9. data/doc/sharding.rdoc +7 -1
  10. data/doc/testing.rdoc +18 -9
  11. data/doc/transactions.rdoc +41 -1
  12. data/lib/sequel/adapters/ado.rb +28 -17
  13. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  14. data/lib/sequel/adapters/amalgalite.rb +11 -7
  15. data/lib/sequel/adapters/db2.rb +122 -70
  16. data/lib/sequel/adapters/dbi.rb +15 -15
  17. data/lib/sequel/adapters/do.rb +5 -36
  18. data/lib/sequel/adapters/do/mysql.rb +0 -5
  19. data/lib/sequel/adapters/do/postgres.rb +0 -5
  20. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  21. data/lib/sequel/adapters/firebird.rb +3 -6
  22. data/lib/sequel/adapters/ibmdb.rb +24 -16
  23. data/lib/sequel/adapters/informix.rb +2 -4
  24. data/lib/sequel/adapters/jdbc.rb +47 -11
  25. data/lib/sequel/adapters/jdbc/as400.rb +5 -24
  26. data/lib/sequel/adapters/jdbc/db2.rb +0 -5
  27. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  28. data/lib/sequel/adapters/jdbc/firebird.rb +0 -5
  29. data/lib/sequel/adapters/jdbc/h2.rb +10 -12
  30. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  31. data/lib/sequel/adapters/jdbc/informix.rb +0 -5
  32. data/lib/sequel/adapters/jdbc/jtds.rb +0 -5
  33. data/lib/sequel/adapters/jdbc/mysql.rb +0 -10
  34. data/lib/sequel/adapters/jdbc/oracle.rb +70 -3
  35. data/lib/sequel/adapters/jdbc/postgresql.rb +0 -11
  36. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/jdbc/sqlserver.rb +0 -5
  38. data/lib/sequel/adapters/jdbc/transactions.rb +56 -7
  39. data/lib/sequel/adapters/mock.rb +315 -0
  40. data/lib/sequel/adapters/mysql.rb +64 -51
  41. data/lib/sequel/adapters/mysql2.rb +15 -9
  42. data/lib/sequel/adapters/odbc.rb +13 -6
  43. data/lib/sequel/adapters/odbc/db2.rb +0 -4
  44. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  45. data/lib/sequel/adapters/openbase.rb +2 -4
  46. data/lib/sequel/adapters/oracle.rb +333 -51
  47. data/lib/sequel/adapters/postgres.rb +80 -27
  48. data/lib/sequel/adapters/shared/access.rb +0 -6
  49. data/lib/sequel/adapters/shared/db2.rb +13 -15
  50. data/lib/sequel/adapters/shared/firebird.rb +6 -6
  51. data/lib/sequel/adapters/shared/mssql.rb +23 -18
  52. data/lib/sequel/adapters/shared/mysql.rb +6 -6
  53. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +6 -0
  54. data/lib/sequel/adapters/shared/oracle.rb +185 -30
  55. data/lib/sequel/adapters/shared/postgres.rb +35 -18
  56. data/lib/sequel/adapters/shared/progress.rb +0 -6
  57. data/lib/sequel/adapters/shared/sqlite.rb +116 -37
  58. data/lib/sequel/adapters/sqlite.rb +16 -8
  59. data/lib/sequel/adapters/swift.rb +5 -5
  60. data/lib/sequel/adapters/swift/mysql.rb +0 -5
  61. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  62. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  63. data/lib/sequel/adapters/tinytds.rb +13 -10
  64. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +8 -0
  65. data/lib/sequel/core.rb +40 -0
  66. data/lib/sequel/database/connecting.rb +1 -2
  67. data/lib/sequel/database/dataset.rb +3 -3
  68. data/lib/sequel/database/dataset_defaults.rb +58 -0
  69. data/lib/sequel/database/misc.rb +62 -2
  70. data/lib/sequel/database/query.rb +113 -49
  71. data/lib/sequel/database/schema_methods.rb +7 -2
  72. data/lib/sequel/dataset/actions.rb +37 -19
  73. data/lib/sequel/dataset/features.rb +24 -0
  74. data/lib/sequel/dataset/graph.rb +7 -6
  75. data/lib/sequel/dataset/misc.rb +11 -3
  76. data/lib/sequel/dataset/mutation.rb +2 -3
  77. data/lib/sequel/dataset/prepared_statements.rb +6 -4
  78. data/lib/sequel/dataset/query.rb +46 -15
  79. data/lib/sequel/dataset/sql.rb +28 -4
  80. data/lib/sequel/extensions/named_timezones.rb +5 -0
  81. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  82. data/lib/sequel/model.rb +2 -1
  83. data/lib/sequel/model/associations.rb +115 -33
  84. data/lib/sequel/model/base.rb +91 -31
  85. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  86. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  87. data/lib/sequel/plugins/force_encoding.rb +6 -6
  88. data/lib/sequel/plugins/identity_map.rb +1 -1
  89. data/lib/sequel/plugins/many_through_many.rb +6 -10
  90. data/lib/sequel/plugins/prepared_statements.rb +12 -1
  91. data/lib/sequel/plugins/prepared_statements_associations.rb +1 -1
  92. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  93. data/lib/sequel/plugins/serialization.rb +6 -1
  94. data/lib/sequel/plugins/sharding.rb +0 -5
  95. data/lib/sequel/plugins/single_table_inheritance.rb +1 -1
  96. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  97. data/lib/sequel/plugins/update_primary_key.rb +1 -1
  98. data/lib/sequel/timezones.rb +42 -42
  99. data/lib/sequel/version.rb +1 -1
  100. data/spec/adapters/mssql_spec.rb +29 -29
  101. data/spec/adapters/mysql_spec.rb +86 -104
  102. data/spec/adapters/oracle_spec.rb +48 -76
  103. data/spec/adapters/postgres_spec.rb +98 -33
  104. data/spec/adapters/spec_helper.rb +0 -5
  105. data/spec/adapters/sqlite_spec.rb +24 -21
  106. data/spec/core/connection_pool_spec.rb +9 -15
  107. data/spec/core/core_sql_spec.rb +20 -31
  108. data/spec/core/database_spec.rb +491 -227
  109. data/spec/core/dataset_spec.rb +638 -1051
  110. data/spec/core/expression_filters_spec.rb +0 -1
  111. data/spec/core/mock_adapter_spec.rb +378 -0
  112. data/spec/core/object_graph_spec.rb +48 -114
  113. data/spec/core/schema_generator_spec.rb +3 -3
  114. data/spec/core/schema_spec.rb +51 -114
  115. data/spec/core/spec_helper.rb +3 -90
  116. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  117. data/spec/extensions/dataset_associations_spec.rb +199 -0
  118. data/spec/extensions/instance_hooks_spec.rb +71 -0
  119. data/spec/extensions/named_timezones_spec.rb +22 -2
  120. data/spec/extensions/nested_attributes_spec.rb +3 -0
  121. data/spec/extensions/schema_spec.rb +1 -1
  122. data/spec/extensions/serialization_modification_detection_spec.rb +1 -0
  123. data/spec/extensions/serialization_spec.rb +5 -8
  124. data/spec/extensions/spec_helper.rb +4 -0
  125. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  126. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  127. data/spec/integration/associations_test.rb +123 -12
  128. data/spec/integration/dataset_test.rb +140 -47
  129. data/spec/integration/eager_loader_test.rb +19 -21
  130. data/spec/integration/model_test.rb +80 -1
  131. data/spec/integration/plugin_test.rb +179 -128
  132. data/spec/integration/prepared_statement_test.rb +92 -91
  133. data/spec/integration/schema_test.rb +42 -23
  134. data/spec/integration/spec_helper.rb +25 -31
  135. data/spec/integration/timezone_test.rb +38 -12
  136. data/spec/integration/transaction_test.rb +161 -34
  137. data/spec/integration/type_test.rb +3 -3
  138. data/spec/model/association_reflection_spec.rb +83 -7
  139. data/spec/model/associations_spec.rb +393 -676
  140. data/spec/model/base_spec.rb +186 -116
  141. data/spec/model/dataset_methods_spec.rb +7 -27
  142. data/spec/model/eager_loading_spec.rb +343 -867
  143. data/spec/model/hooks_spec.rb +160 -79
  144. data/spec/model/model_spec.rb +118 -165
  145. data/spec/model/plugins_spec.rb +7 -13
  146. data/spec/model/record_spec.rb +138 -207
  147. data/spec/model/spec_helper.rb +10 -73
  148. metadata +14 -8
@@ -63,10 +63,6 @@ module Sequel
63
63
  ::DBI.connect(dbname, opts[:user], opts[:password])
64
64
  end
65
65
 
66
- def dataset(opts = nil)
67
- DBI::Dataset.new(self, opts)
68
- end
69
-
70
66
  def execute(sql, opts={})
71
67
  synchronize(opts[:server]) do |conn|
72
68
  r = log_yield(sql){conn.execute(sql)}
@@ -88,26 +84,30 @@ module Sequel
88
84
  end
89
85
 
90
86
  class Dataset < Sequel::Dataset
87
+ Database::DatasetClass = self
88
+
91
89
  def fetch_rows(sql)
92
90
  execute(sql) do |s|
93
91
  begin
94
- @columns = s.column_names.map{|c| output_identifier(c)}
95
- s.fetch{|r| yield hash_row(s, r)}
92
+ columns = cols = s.column_names.map{|c| output_identifier(c)}
93
+ if opts[:offset] && offset_returns_row_number_column?
94
+ rn = row_number_column
95
+ columns = columns.dup
96
+ columns.delete(rn)
97
+ end
98
+ @columns = columns
99
+ s.fetch do |r|
100
+ row = {}
101
+ cols.each{|c| row[c] = r.shift}
102
+ row.delete(rn) if rn
103
+ yield row
104
+ end
96
105
  ensure
97
106
  s.finish rescue nil
98
107
  end
99
108
  end
100
109
  self
101
110
  end
102
-
103
- private
104
-
105
- def hash_row(stmt, row)
106
- @columns.inject({}) do |m, c|
107
- m[c] = row.shift
108
- m
109
- end
110
- end
111
111
  end
112
112
  end
113
113
  end
@@ -17,16 +17,19 @@ module Sequel
17
17
  Sequel.tsk_require 'do_postgres'
18
18
  Sequel.ts_require 'adapters/do/postgres'
19
19
  db.extend(Sequel::DataObjects::Postgres::DatabaseMethods)
20
+ db.dataset_class = Sequel::DataObjects::Postgres::Dataset
20
21
  end,
21
22
  :mysql=>proc do |db|
22
23
  Sequel.tsk_require 'do_mysql'
23
24
  Sequel.ts_require 'adapters/do/mysql'
24
25
  db.extend(Sequel::DataObjects::MySQL::DatabaseMethods)
26
+ db.dataset_class = Sequel::DataObjects::MySQL::Dataset
25
27
  end,
26
28
  :sqlite3=>proc do |db|
27
29
  Sequel.tsk_require 'do_sqlite3'
28
30
  Sequel.ts_require 'adapters/do/sqlite'
29
31
  db.extend(Sequel::DataObjects::SQLite::DatabaseMethods)
32
+ db.dataset_class = Sequel::DataObjects::SQLite::Dataset
30
33
  end
31
34
  }
32
35
 
@@ -57,11 +60,6 @@ module Sequel
57
60
  setup_connection(::DataObjects::Connection.new(uri(server_opts(server))))
58
61
  end
59
62
 
60
- # Return a Sequel::DataObjects::Dataset object for this database.
61
- def dataset(opts = nil)
62
- DataObjects::Dataset.new(self, opts)
63
- end
64
-
65
63
  # Execute the given SQL. If a block is given, the DataObjects::Reader
66
64
  # created is yielded to it. A block should not be provided unless a
67
65
  # a SELECT statement is being used (or something else that returns rows).
@@ -116,31 +114,6 @@ module Sequel
116
114
 
117
115
  private
118
116
 
119
- # DataObjects uses a special transaction object to keep track of
120
- # transactions. Unfortunately, it tries to create a new connection
121
- # to do a transaction. So we close the connection created and
122
- # substitute our own.
123
- def begin_transaction(conn, opts={})
124
- return super if supports_savepoints?
125
- log_yield(TRANSACTION_BEGIN) do
126
- t = ::DataObjects::Transaction.create_for_uri(uri)
127
- t.instance_variable_get(:@connection).close
128
- t.instance_variable_set(:@connection, conn)
129
- t.begin
130
- t
131
- end
132
- end
133
-
134
- # DataObjects requires transactions be prepared before being
135
- # committed, so we do that.
136
- def commit_transaction(t, opts={})
137
- return super if supports_savepoints?
138
- log_yield(TRANSACTION_ROLLBACK) do
139
- t.prepare
140
- t.commit
141
- end
142
- end
143
-
144
117
  # Method to call on a statement object to execute SQL that does
145
118
  # not return any rows.
146
119
  def connection_execute_method
@@ -167,12 +140,6 @@ module Sequel
167
140
  log_yield(sql){conn.create_command(sql).execute_non_query}
168
141
  end
169
142
 
170
- # We use the transactions rollback method to rollback.
171
- def rollback_transaction(t, opts={})
172
- return super if supports_savepoints?
173
- log_yield(TRANSACTION_COMMIT){t.rollback}
174
- end
175
-
176
143
  # Allow extending the given connection when it is first created.
177
144
  # By default, just returns the connection.
178
145
  def setup_connection(conn)
@@ -182,6 +149,8 @@ module Sequel
182
149
 
183
150
  # Dataset class for Sequel::DataObjects::Database objects.
184
151
  class Dataset < Sequel::Dataset
152
+ Database::DatasetClass = self
153
+
185
154
  # Execute the SQL on the database and yield the rows as hashes
186
155
  # with symbol keys.
187
156
  def fetch_rows(sql)
@@ -9,11 +9,6 @@ module Sequel
9
9
  module DatabaseMethods
10
10
  include Sequel::MySQL::DatabaseMethods
11
11
 
12
- # Return instance of Sequel::DataObjects::MySQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::DataObjects::MySQL::Dataset.new(self, opts)
15
- end
16
-
17
12
  private
18
13
 
19
14
  # The database name for the given database. Need to parse it out
@@ -55,11 +55,6 @@ module Sequel
55
55
  end
56
56
  end
57
57
 
58
- # Return instance of Sequel::DataObjects::Postgres::Dataset with the given opts.
59
- def dataset(opts=nil)
60
- Sequel::DataObjects::Postgres::Dataset.new(self, opts)
61
- end
62
-
63
58
  # Run the INSERT sql on the database and return the primary key
64
59
  # for the record.
65
60
  def execute_insert(sql, opts={})
@@ -8,11 +8,6 @@ module Sequel
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
10
10
 
11
- # Return Sequel::DataObjects::SQLite::Dataset object with the given opts.
12
- def dataset(opts=nil)
13
- Sequel::DataObjects::SQLite::Dataset.new(self, opts)
14
- end
15
-
16
11
  private
17
12
 
18
13
  # Default to a single connection for a memory database.
@@ -28,14 +28,10 @@ module Sequel
28
28
  :password => opts[:password]).connect
29
29
  end
30
30
 
31
- def dataset(opts = nil)
32
- Firebird::Dataset.new(self, opts)
33
- end
34
-
35
31
  def execute(sql, opts={})
36
32
  begin
37
33
  synchronize(opts[:server]) do |conn|
38
- if conn.transaction_started && !@transactions.include?(Thread.current)
34
+ if conn.transaction_started && !@transactions.has_key?(conn)
39
35
  conn.rollback
40
36
  raise DatabaseDisconnectError, "transaction accidently left open, rolling back and disconnecting"
41
37
  end
@@ -59,7 +55,6 @@ module Sequel
59
55
  raise_error(e, :disconnect=>true)
60
56
  end
61
57
  end
62
- conn
63
58
  end
64
59
 
65
60
  def commit_transaction(conn, opts={})
@@ -83,6 +78,8 @@ module Sequel
83
78
  class Dataset < Sequel::Dataset
84
79
  include Sequel::Firebird::DatasetMethods
85
80
 
81
+ Database::DatasetClass = self
82
+
86
83
  # Yield all rows returned by executing the given SQL and converting
87
84
  # the types.
88
85
  def fetch_rows(sql)
@@ -23,8 +23,7 @@ module Sequel
23
23
  :int => tt.method(:int),
24
24
  :blob => ::Sequel::SQL::Blob.method(:new),
25
25
  :time => ::Sequel.method(:string_to_time),
26
- :date => ::Sequel.method(:string_to_date),
27
- :timestamp => ::Sequel.method(:database_to_application_timestamp)
26
+ :date => ::Sequel.method(:string_to_date)
28
27
  }
29
28
  DB2_TYPES[:clob] = DB2_TYPES[:blob]
30
29
 
@@ -163,6 +162,15 @@ module Sequel
163
162
 
164
163
  set_adapter_scheme :ibmdb
165
164
 
165
+ # Hash of connection procs for converting
166
+ attr_reader :conversion_procs
167
+
168
+ def initialize(opts={})
169
+ super
170
+ @conversion_procs = DB2_TYPES.dup
171
+ @conversion_procs[:timestamp] = method(:to_application_timestamp)
172
+ end
173
+
166
174
  # REORG the related table whenever it is altered. This is not always
167
175
  # required, but it is necessary for compatibilty with other Sequel
168
176
  # code in many cases.
@@ -190,11 +198,6 @@ module Sequel
190
198
  Connection.new(connection_string)
191
199
  end
192
200
 
193
- # Return a related IBMDB::Dataset instance with the given options.
194
- def dataset(opts = nil)
195
- IBMDB::Dataset.new(self, opts)
196
- end
197
-
198
201
  # Execute the given SQL on the database.
199
202
  def execute(sql, opts={}, &block)
200
203
  if sql.is_a?(Symbol)
@@ -250,7 +253,7 @@ module Sequel
250
253
  if Sequel::IBMDB.convert_smallint_to_bool && db_type =~ /smallint/i
251
254
  :boolean
252
255
  else
253
- db_type =~ /[bc]lob/i ? :blob : super
256
+ super
254
257
  end
255
258
  end
256
259
 
@@ -293,15 +296,12 @@ module Sequel
293
296
  # So starting a transaction just turns autocommit off.
294
297
  def begin_transaction(conn, opts={})
295
298
  log_yield(TRANSACTION_BEGIN){conn.autocommit = false}
296
- conn
297
299
  end
298
300
 
299
301
  # This commits transaction in progress on the
300
302
  # connection and sets autocommit back on.
301
303
  def commit_transaction(conn, opts={})
302
- log_yield(TRANSACTION_COMMIT){conn.commit} if conn
303
- ensure
304
- conn.autocommit = true if conn
304
+ log_yield(TRANSACTION_COMMIT){conn.commit}
305
305
  end
306
306
 
307
307
  # Close the given connection.
@@ -332,18 +332,25 @@ module Sequel
332
332
  end
333
333
  end
334
334
 
335
+ # Set autocommit back on
336
+ def remove_transaction(conn, committed)
337
+ conn.autocommit = true
338
+ ensure
339
+ super
340
+ end
341
+
335
342
  # This rolls back the transaction in progress on the
336
343
  # connection and sets autocommit back on.
337
344
  def rollback_transaction(conn, opts={})
338
- log_yield(TRANSACTION_ROLLBACK){conn.rollback} if conn
339
- ensure
340
- conn.autocommit = true if conn
345
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
341
346
  end
342
347
  end
343
348
 
344
349
  class Dataset < Sequel::Dataset
345
350
  include Sequel::DB2::DatasetMethods
346
351
 
352
+ Database::DatasetClass = self
353
+
347
354
  module CallableStatementMethods
348
355
  # Extend given dataset with this module so subselects inside subselects in
349
356
  # prepared statements work.
@@ -400,13 +407,14 @@ module Sequel
400
407
  offset = @opts[:offset]
401
408
  columns = []
402
409
  convert = convert_smallint_to_bool
410
+ cps = db.conversion_procs
403
411
  stmt.num_fields.times do |i|
404
412
  k = stmt.field_name i
405
413
  key = output_identifier(k)
406
414
  type = stmt.field_type(k).downcase.to_sym
407
415
  # decide if it is a smallint from precision
408
416
  type = :boolean if type ==:int && convert && stmt.field_precision(k) < 8
409
- columns << [key, DB2_TYPES[type]]
417
+ columns << [key, cps[type]]
410
418
  end
411
419
  cols = columns.map{|c| c.at(0)}
412
420
  cols.delete(row_number_column) if offset
@@ -13,10 +13,6 @@ module Sequel
13
13
  ::Informix.connect(opts[:database], opts[:user], opts[:password])
14
14
  end
15
15
 
16
- def dataset(opts = nil)
17
- Sequel::Informix::Dataset.new(self, opts)
18
- end
19
-
20
16
  # Returns number of rows affected
21
17
  def execute_dui(sql, opts={})
22
18
  synchronize(opts[:server]){|c| log_yield(sql){c.immediate(sql)}}
@@ -38,6 +34,8 @@ module Sequel
38
34
  class Dataset < Sequel::Dataset
39
35
  include DatasetMethods
40
36
 
37
+ Database::DatasetClass = self
38
+
41
39
  def fetch_rows(sql)
42
40
  execute(sql) do |cursor|
43
41
  begin
@@ -32,35 +32,41 @@ module Sequel
32
32
  DATABASE_SETUP = {:postgresql=>proc do |db|
33
33
  Sequel.ts_require 'adapters/jdbc/postgresql'
34
34
  db.extend(Sequel::JDBC::Postgres::DatabaseMethods)
35
+ db.dataset_class = Sequel::JDBC::Postgres::Dataset
35
36
  JDBC.load_gem('postgres')
36
37
  org.postgresql.Driver
37
38
  end,
38
39
  :mysql=>proc do |db|
39
40
  Sequel.ts_require 'adapters/jdbc/mysql'
40
41
  db.extend(Sequel::JDBC::MySQL::DatabaseMethods)
42
+ db.dataset_class = Sequel::JDBC::MySQL::Dataset
41
43
  JDBC.load_gem('mysql')
42
44
  com.mysql.jdbc.Driver
43
45
  end,
44
46
  :sqlite=>proc do |db|
45
47
  Sequel.ts_require 'adapters/jdbc/sqlite'
46
48
  db.extend(Sequel::JDBC::SQLite::DatabaseMethods)
49
+ db.dataset_class = Sequel::JDBC::SQLite::Dataset
47
50
  JDBC.load_gem('sqlite3')
48
51
  org.sqlite.JDBC
49
52
  end,
50
53
  :oracle=>proc do |db|
51
54
  Sequel.ts_require 'adapters/jdbc/oracle'
52
55
  db.extend(Sequel::JDBC::Oracle::DatabaseMethods)
56
+ db.dataset_class = Sequel::JDBC::Oracle::Dataset
53
57
  Java::oracle.jdbc.driver.OracleDriver
54
58
  end,
55
59
  :sqlserver=>proc do |db|
56
60
  Sequel.ts_require 'adapters/jdbc/sqlserver'
57
61
  db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
62
+ db.dataset_class = Sequel::JDBC::SQLServer::Dataset
58
63
  db.send(:set_mssql_unicode_strings)
59
64
  com.microsoft.sqlserver.jdbc.SQLServerDriver
60
65
  end,
61
66
  :jtds=>proc do |db|
62
67
  Sequel.ts_require 'adapters/jdbc/jtds'
63
68
  db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
69
+ db.dataset_class = Sequel::JDBC::JTDS::Dataset
64
70
  db.send(:set_mssql_unicode_strings)
65
71
  JDBC.load_gem('jtds')
66
72
  Java::net.sourceforge.jtds.jdbc.Driver
@@ -68,27 +74,46 @@ module Sequel
68
74
  :h2=>proc do |db|
69
75
  Sequel.ts_require 'adapters/jdbc/h2'
70
76
  db.extend(Sequel::JDBC::H2::DatabaseMethods)
77
+ db.dataset_class = Sequel::JDBC::H2::Dataset
71
78
  JDBC.load_gem('h2')
72
79
  org.h2.Driver
73
80
  end,
81
+ :hsqldb=>proc do |db|
82
+ Sequel.ts_require 'adapters/jdbc/hsqldb'
83
+ db.extend(Sequel::JDBC::HSQLDB::DatabaseMethods)
84
+ db.dataset_class = Sequel::JDBC::HSQLDB::Dataset
85
+ # Current gem is 1.8.1.3, but Sequel supports 2.2.5
86
+ org.hsqldb.jdbcDriver
87
+ end,
88
+ :derby=>proc do |db|
89
+ Sequel.ts_require 'adapters/jdbc/derby'
90
+ db.extend(Sequel::JDBC::Derby::DatabaseMethods)
91
+ db.dataset_class = Sequel::JDBC::Derby::Dataset
92
+ JDBC.load_gem('derby')
93
+ org.apache.derby.jdbc.EmbeddedDriver
94
+ end,
74
95
  :as400=>proc do |db|
75
96
  Sequel.ts_require 'adapters/jdbc/as400'
76
97
  db.extend(Sequel::JDBC::AS400::DatabaseMethods)
98
+ db.dataset_class = Sequel::JDBC::AS400::Dataset
77
99
  com.ibm.as400.access.AS400JDBCDriver
78
100
  end,
79
101
  :"informix-sqli"=>proc do |db|
80
102
  Sequel.ts_require 'adapters/jdbc/informix'
81
103
  db.extend(Sequel::JDBC::Informix::DatabaseMethods)
104
+ db.dataset_class = Sequel::JDBC::Informix::Dataset
82
105
  com.informix.jdbc.IfxDriver
83
106
  end,
84
107
  :db2=>proc do |db|
85
108
  Sequel.ts_require 'adapters/jdbc/db2'
86
109
  db.extend(Sequel::JDBC::DB2::DatabaseMethods)
110
+ db.dataset_class = Sequel::JDBC::DB2::Dataset
87
111
  com.ibm.db2.jcc.DB2Driver
88
112
  end,
89
113
  :firebirdsql=>proc do |db|
90
114
  Sequel.ts_require 'adapters/jdbc/firebird'
91
115
  db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
116
+ db.dataset_class = Sequel::JDBC::Firebird::Dataset
92
117
  org.firebirdsql.jdbc.FBDriver
93
118
  end
94
119
  }
@@ -197,11 +222,6 @@ module Sequel
197
222
  setup_connection(conn)
198
223
  end
199
224
 
200
- # Return instances of JDBC::Dataset with the given opts.
201
- def dataset(opts = nil)
202
- JDBC::Dataset.new(self, opts)
203
- end
204
-
205
225
  # Execute the given SQL. If a block is given, if should be a SELECT
206
226
  # statement or something else that returns rows.
207
227
  def execute(sql, opts={}, &block)
@@ -462,8 +482,8 @@ module Sequel
462
482
 
463
483
  # Parse the table schema for the given table.
464
484
  def schema_parse_table(table, opts={})
465
- m = output_identifier_meth
466
- im = input_identifier_meth
485
+ m = output_identifier_meth(opts[:dataset])
486
+ im = input_identifier_meth(opts[:dataset])
467
487
  ds = dataset
468
488
  schema, table = schema_and_table(table)
469
489
  schema ||= opts[:schema]
@@ -471,11 +491,11 @@ module Sequel
471
491
  table = im.call(table)
472
492
  pks, ts = [], []
473
493
  metadata(:getPrimaryKeys, nil, schema, table) do |h|
474
- next if h[:table_schem] == 'INFORMATION_SCHEMA'
494
+ next if schema_parse_table_skip?(h, schema)
475
495
  pks << h[:column_name]
476
496
  end
477
497
  metadata(:getColumns, nil, schema, table, nil) do |h|
478
- next if h[:table_schem] == 'INFORMATION_SCHEMA'
498
+ next if schema_parse_table_skip?(h, schema)
479
499
  s = {:type=>schema_column_type(h[:type_name]), :db_type=>h[:type_name], :default=>(h[:column_def] == '' ? nil : h[:column_def]), :allow_null=>(h[:nullable] != 0), :primary_key=>pks.include?(h[:column_name]), :column_size=>h[:column_size], :scale=>h[:decimal_digits]}
480
500
  if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
481
501
  s[:type] = :integer
@@ -485,6 +505,12 @@ module Sequel
485
505
  ts
486
506
  end
487
507
 
508
+ # Whether schema_parse_table should skip the given row when
509
+ # parsing the schema.
510
+ def schema_parse_table_skip?(h, schema)
511
+ h[:table_schem] == 'INFORMATION_SCHEMA'
512
+ end
513
+
488
514
  # Yield a new statement object, and ensure that it is closed before returning.
489
515
  def statement(conn)
490
516
  stmt = conn.createStatement
@@ -505,6 +531,8 @@ module Sequel
505
531
 
506
532
  class Dataset < Sequel::Dataset
507
533
  include StoredProcedures
534
+
535
+ Database::DatasetClass = self
508
536
 
509
537
  # Use JDBC PreparedStatements instead of emulated ones. Statements
510
538
  # created using #prepare are cached at the connection level to allow
@@ -590,7 +618,7 @@ module Sequel
590
618
  def convert_type(v)
591
619
  case v
592
620
  when Java::JavaSQL::Timestamp
593
- Sequel.database_to_application_timestamp(v.to_string)
621
+ db.to_application_timestamp(v.to_string)
594
622
  when Java::JavaSQL::Time
595
623
  Sequel.string_to_time(v.to_string)
596
624
  when Java::JavaSQL::Date
@@ -625,7 +653,12 @@ module Sequel
625
653
  cols = []
626
654
  i = 0
627
655
  meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
628
- @columns = cols.map{|c| c.at(0)}
656
+ columns = cols.map{|c| c.at(0)}
657
+ if opts[:offset] && offset_returns_row_number_column?
658
+ rn = row_number_column
659
+ columns.delete(rn)
660
+ end
661
+ @columns = columns
629
662
  blk = result_set_object_getter
630
663
  # get rows
631
664
  while result.next
@@ -633,8 +666,11 @@ module Sequel
633
666
  cols.each do |n, i|
634
667
  row[n] = blk.call(result, n, i)
635
668
  end
669
+ row.delete(rn) if rn
636
670
  yield row
637
671
  end
672
+ ensure
673
+ result.close
638
674
  end
639
675
 
640
676
  # Proc that takes the ResultSet and an integer field number and returns