sequel 3.28.0 → 3.29.0

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