sequel 3.21.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 (200) hide show
  1. data/CHANGELOG +413 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +23 -16
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +210 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/mass_assignment.rdoc +54 -0
  8. data/doc/migration.rdoc +15 -538
  9. data/doc/model_hooks.rdoc +72 -27
  10. data/doc/opening_databases.rdoc +86 -50
  11. data/doc/prepared_statements.rdoc +40 -13
  12. data/doc/reflection.rdoc +8 -2
  13. data/doc/release_notes/3.22.0.txt +39 -0
  14. data/doc/release_notes/3.23.0.txt +172 -0
  15. data/doc/release_notes/3.24.0.txt +420 -0
  16. data/doc/release_notes/3.25.0.txt +88 -0
  17. data/doc/release_notes/3.26.0.txt +88 -0
  18. data/doc/release_notes/3.27.0.txt +82 -0
  19. data/doc/release_notes/3.28.0.txt +304 -0
  20. data/doc/release_notes/3.29.0.txt +459 -0
  21. data/doc/schema_modification.rdoc +547 -0
  22. data/doc/sharding.rdoc +7 -1
  23. data/doc/testing.rdoc +115 -0
  24. data/doc/transactions.rdoc +137 -0
  25. data/doc/virtual_rows.rdoc +2 -2
  26. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  27. data/lib/sequel/adapters/ado.rb +40 -18
  28. data/lib/sequel/adapters/amalgalite.rb +15 -7
  29. data/lib/sequel/adapters/db2.rb +175 -86
  30. data/lib/sequel/adapters/dbi.rb +15 -15
  31. data/lib/sequel/adapters/do/mysql.rb +0 -5
  32. data/lib/sequel/adapters/do/postgres.rb +0 -5
  33. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  34. data/lib/sequel/adapters/do.rb +17 -36
  35. data/lib/sequel/adapters/firebird.rb +27 -208
  36. data/lib/sequel/adapters/ibmdb.rb +448 -0
  37. data/lib/sequel/adapters/informix.rb +6 -23
  38. data/lib/sequel/adapters/jdbc/as400.rb +5 -31
  39. data/lib/sequel/adapters/jdbc/db2.rb +44 -0
  40. data/lib/sequel/adapters/jdbc/derby.rb +217 -0
  41. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  42. data/lib/sequel/adapters/jdbc/h2.rb +26 -17
  43. data/lib/sequel/adapters/jdbc/hsqldb.rb +166 -0
  44. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  45. data/lib/sequel/adapters/jdbc/jtds.rb +29 -0
  46. data/lib/sequel/adapters/jdbc/mssql.rb +0 -32
  47. data/lib/sequel/adapters/jdbc/mysql.rb +9 -10
  48. data/lib/sequel/adapters/jdbc/oracle.rb +67 -25
  49. data/lib/sequel/adapters/jdbc/postgresql.rb +6 -11
  50. data/lib/sequel/adapters/jdbc/sqlite.rb +0 -5
  51. data/lib/sequel/adapters/jdbc/sqlserver.rb +41 -0
  52. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  53. data/lib/sequel/adapters/jdbc.rb +107 -38
  54. data/lib/sequel/adapters/mock.rb +315 -0
  55. data/lib/sequel/adapters/mysql.rb +78 -182
  56. data/lib/sequel/adapters/mysql2.rb +24 -23
  57. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  58. data/lib/sequel/adapters/odbc/mssql.rb +0 -5
  59. data/lib/sequel/adapters/odbc.rb +28 -9
  60. data/lib/sequel/adapters/openbase.rb +2 -4
  61. data/lib/sequel/adapters/oracle.rb +349 -51
  62. data/lib/sequel/adapters/postgres.rb +169 -21
  63. data/lib/sequel/adapters/shared/access.rb +21 -6
  64. data/lib/sequel/adapters/shared/db2.rb +288 -0
  65. data/lib/sequel/adapters/shared/firebird.rb +214 -0
  66. data/lib/sequel/adapters/shared/informix.rb +45 -0
  67. data/lib/sequel/adapters/shared/mssql.rb +108 -65
  68. data/lib/sequel/adapters/shared/mysql.rb +56 -13
  69. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  70. data/lib/sequel/adapters/shared/oracle.rb +185 -34
  71. data/lib/sequel/adapters/shared/postgres.rb +107 -58
  72. data/lib/sequel/adapters/shared/progress.rb +0 -6
  73. data/lib/sequel/adapters/shared/sqlite.rb +168 -41
  74. data/lib/sequel/adapters/sqlite.rb +27 -18
  75. data/lib/sequel/adapters/swift/mysql.rb +9 -5
  76. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  77. data/lib/sequel/adapters/swift/sqlite.rb +6 -4
  78. data/lib/sequel/adapters/swift.rb +5 -5
  79. data/lib/sequel/adapters/tinytds.rb +152 -17
  80. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +63 -0
  81. data/lib/sequel/ast_transformer.rb +190 -0
  82. data/lib/sequel/connection_pool/threaded.rb +3 -2
  83. data/lib/sequel/connection_pool.rb +1 -1
  84. data/lib/sequel/core.rb +46 -5
  85. data/lib/sequel/database/connecting.rb +5 -6
  86. data/lib/sequel/database/dataset.rb +4 -4
  87. data/lib/sequel/database/dataset_defaults.rb +59 -1
  88. data/lib/sequel/database/logging.rb +1 -1
  89. data/lib/sequel/database/misc.rb +100 -19
  90. data/lib/sequel/database/query.rb +153 -58
  91. data/lib/sequel/database/schema_generator.rb +8 -5
  92. data/lib/sequel/database/schema_methods.rb +59 -29
  93. data/lib/sequel/dataset/actions.rb +194 -57
  94. data/lib/sequel/dataset/features.rb +81 -8
  95. data/lib/sequel/dataset/graph.rb +8 -7
  96. data/lib/sequel/dataset/misc.rb +50 -23
  97. data/lib/sequel/dataset/mutation.rb +5 -6
  98. data/lib/sequel/dataset/prepared_statements.rb +32 -15
  99. data/lib/sequel/dataset/query.rb +223 -42
  100. data/lib/sequel/dataset/sql.rb +58 -61
  101. data/lib/sequel/dataset.rb +8 -0
  102. data/lib/sequel/exceptions.rb +4 -0
  103. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  104. data/lib/sequel/extensions/migration.rb +6 -4
  105. data/lib/sequel/extensions/named_timezones.rb +5 -0
  106. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  107. data/lib/sequel/extensions/to_dot.rb +95 -83
  108. data/lib/sequel/model/associations.rb +997 -331
  109. data/lib/sequel/model/base.rb +386 -129
  110. data/lib/sequel/model/errors.rb +1 -1
  111. data/lib/sequel/model/exceptions.rb +5 -1
  112. data/lib/sequel/model.rb +15 -8
  113. data/lib/sequel/plugins/association_pks.rb +22 -4
  114. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  115. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  116. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  117. data/lib/sequel/plugins/force_encoding.rb +6 -6
  118. data/lib/sequel/plugins/identity_map.rb +114 -7
  119. data/lib/sequel/plugins/many_through_many.rb +65 -7
  120. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  121. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  122. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  123. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  124. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  125. data/lib/sequel/plugins/serialization.rb +6 -1
  126. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  127. data/lib/sequel/plugins/sharding.rb +12 -25
  128. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  129. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  130. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  131. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  132. data/lib/sequel/sql.rb +107 -51
  133. data/lib/sequel/timezones.rb +44 -35
  134. data/lib/sequel/version.rb +1 -1
  135. data/spec/adapters/db2_spec.rb +146 -0
  136. data/spec/adapters/mssql_spec.rb +65 -29
  137. data/spec/adapters/mysql_spec.rb +122 -123
  138. data/spec/adapters/oracle_spec.rb +48 -76
  139. data/spec/adapters/postgres_spec.rb +213 -61
  140. data/spec/adapters/spec_helper.rb +6 -5
  141. data/spec/adapters/sqlite_spec.rb +35 -21
  142. data/spec/core/connection_pool_spec.rb +71 -92
  143. data/spec/core/core_sql_spec.rb +20 -31
  144. data/spec/core/database_spec.rb +729 -508
  145. data/spec/core/dataset_spec.rb +980 -1044
  146. data/spec/core/expression_filters_spec.rb +159 -42
  147. data/spec/core/mock_adapter_spec.rb +378 -0
  148. data/spec/core/object_graph_spec.rb +48 -114
  149. data/spec/core/schema_generator_spec.rb +3 -3
  150. data/spec/core/schema_spec.rb +298 -38
  151. data/spec/core/spec_helper.rb +6 -48
  152. data/spec/extensions/association_pks_spec.rb +38 -0
  153. data/spec/extensions/class_table_inheritance_spec.rb +1 -1
  154. data/spec/extensions/columns_introspection_spec.rb +91 -0
  155. data/spec/extensions/dataset_associations_spec.rb +199 -0
  156. data/spec/extensions/defaults_setter_spec.rb +64 -0
  157. data/spec/extensions/identity_map_spec.rb +162 -0
  158. data/spec/extensions/instance_hooks_spec.rb +71 -0
  159. data/spec/extensions/many_through_many_spec.rb +195 -20
  160. data/spec/extensions/migration_spec.rb +17 -17
  161. data/spec/extensions/named_timezones_spec.rb +22 -2
  162. data/spec/extensions/nested_attributes_spec.rb +4 -0
  163. data/spec/extensions/prepared_statements_associations_spec.rb +126 -0
  164. data/spec/extensions/prepared_statements_safe_spec.rb +79 -0
  165. data/spec/extensions/prepared_statements_spec.rb +72 -0
  166. data/spec/extensions/prepared_statements_with_pk_spec.rb +38 -0
  167. data/spec/extensions/schema_dumper_spec.rb +2 -2
  168. data/spec/extensions/schema_spec.rb +13 -21
  169. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  170. data/spec/extensions/serialization_spec.rb +5 -8
  171. data/spec/extensions/single_table_inheritance_spec.rb +11 -0
  172. data/spec/extensions/spec_helper.rb +7 -1
  173. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  174. data/spec/extensions/to_dot_spec.rb +3 -5
  175. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  176. data/spec/extensions/xml_serializer_spec.rb +16 -4
  177. data/spec/integration/associations_test.rb +522 -21
  178. data/spec/integration/database_test.rb +4 -2
  179. data/spec/integration/dataset_test.rb +375 -62
  180. data/spec/integration/eager_loader_test.rb +19 -21
  181. data/spec/integration/model_test.rb +80 -1
  182. data/spec/integration/plugin_test.rb +304 -116
  183. data/spec/integration/prepared_statement_test.rb +200 -120
  184. data/spec/integration/schema_test.rb +161 -30
  185. data/spec/integration/spec_helper.rb +39 -30
  186. data/spec/integration/timezone_test.rb +38 -12
  187. data/spec/integration/transaction_test.rb +172 -5
  188. data/spec/integration/type_test.rb +17 -3
  189. data/spec/model/association_reflection_spec.rb +174 -7
  190. data/spec/model/associations_spec.rb +849 -661
  191. data/spec/model/base_spec.rb +255 -95
  192. data/spec/model/dataset_methods_spec.rb +7 -27
  193. data/spec/model/eager_loading_spec.rb +640 -676
  194. data/spec/model/hooks_spec.rb +309 -67
  195. data/spec/model/model_spec.rb +207 -167
  196. data/spec/model/plugins_spec.rb +24 -13
  197. data/spec/model/record_spec.rb +321 -218
  198. data/spec/model/spec_helper.rb +13 -71
  199. data/spec/model/validations_spec.rb +11 -0
  200. metadata +95 -38
@@ -1,4 +1,5 @@
1
1
  Sequel.require 'adapters/shared/oracle'
2
+ Sequel.require 'adapters/jdbc/transactions'
2
3
 
3
4
  module Sequel
4
5
  module JDBC
@@ -7,43 +8,84 @@ module Sequel
7
8
  # Instance methods for Oracle Database objects accessed via JDBC.
8
9
  module DatabaseMethods
9
10
  include Sequel::Oracle::DatabaseMethods
10
- TRANSACTION_BEGIN = 'Transaction.begin'.freeze
11
- TRANSACTION_COMMIT = 'Transaction.commit'.freeze
12
- TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
13
-
14
- # Return Sequel::JDBC::Oracle::Dataset object with the given opts.
15
- def dataset(opts=nil)
16
- Sequel::JDBC::Oracle::Dataset.new(self, opts)
11
+ include Sequel::JDBC::Transactions
12
+
13
+ def self.extended(db)
14
+ db.instance_eval do
15
+ @autosequence = opts[:autosequence]
16
+ @primary_key_sequences = {}
17
+ end
17
18
  end
18
19
 
19
20
  private
20
-
21
- # Use JDBC connection's setAutoCommit to false to start transactions
22
- def begin_transaction(conn, opts={})
23
- log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
24
- conn
21
+
22
+ def last_insert_id(conn, opts)
23
+ unless sequence = opts[:sequence]
24
+ if t = opts[:table]
25
+ sequence = sequence_for_table(t)
26
+ end
27
+ end
28
+ if sequence
29
+ sql = "SELECT #{literal(sequence)}.currval FROM dual"
30
+ statement(conn) do |stmt|
31
+ begin
32
+ rs = log_yield(sql){stmt.executeQuery(sql)}
33
+ rs.next
34
+ rs.getInt(1)
35
+ rescue java.sql.SQLException
36
+ nil
37
+ end
38
+ end
39
+ end
25
40
  end
26
-
27
- # Use JDBC connection's commit method to commit transactions
28
- def commit_transaction(conn, opts={})
29
- log_yield(TRANSACTION_COMMIT){conn.commit}
41
+
42
+ def schema_parse_table(*)
43
+ sch = super
44
+ sch.each do |c, s|
45
+ if s[:type] == :decimal && s[:scale] == -127
46
+ s[:type] = :integer
47
+ elsif s[:db_type] == 'DATE'
48
+ s[:type] = :datetime
49
+ end
50
+ end
51
+ sch
30
52
  end
31
-
32
- # Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
33
- def remove_transaction(conn)
34
- conn.setAutoCommit(true) if conn
35
- @transactions.delete(Thread.current)
53
+
54
+ def schema_parse_table_skip?(h, schema)
55
+ super || (h[:table_schem] != current_user unless schema)
36
56
  end
37
-
38
- # Use JDBC connection's rollback method to rollback transactions
39
- def rollback_transaction(conn, opts={})
40
- log_yield(TRANSACTION_ROLLBACK){conn.rollback}
57
+
58
+ # As of Oracle 9.2, releasing savepoints is no longer supported.
59
+ def supports_releasing_savepoints?
60
+ false
41
61
  end
42
62
  end
43
63
 
44
64
  # Dataset class for Oracle datasets accessed via JDBC.
45
65
  class Dataset < JDBC::Dataset
46
66
  include Sequel::Oracle::DatasetMethods
67
+
68
+ private
69
+
70
+ def convert_type(v)
71
+ case v
72
+ when Java::JavaMath::BigDecimal
73
+ if v.scale == 0
74
+ i = v.long_value
75
+ if v.equals(Java::JavaMath::BigDecimal.new(i))
76
+ i
77
+ else
78
+ super
79
+ end
80
+ else
81
+ super
82
+ end
83
+ when Java::OracleSql::TIMESTAMP
84
+ db.to_application_timestamp(v.to_string)
85
+ else
86
+ super
87
+ end
88
+ end
47
89
  end
48
90
  end
49
91
  end
@@ -47,19 +47,14 @@ module Sequel
47
47
  end
48
48
  end
49
49
 
50
- # Return instance of Sequel::JDBC::Postgres::Dataset with the given opts.
51
- def dataset(opts=nil)
52
- Sequel::JDBC::Postgres::Dataset.new(self, opts)
53
- end
54
-
55
- # Run the INSERT sql on the database and return the primary key
56
- # for the record.
57
- def execute_insert(sql, opts={})
58
- super(sql, {:type=>:insert}.merge(opts))
59
- end
60
-
61
50
  private
62
51
 
52
+ # Use setNull for nil arguments as the default behavior of setString
53
+ # with nil doesn't appear to work correctly on PostgreSQL.
54
+ def set_ps_arg(cps, arg, i)
55
+ arg.nil? ? cps.setNull(i, JavaSQL::Types::NULL) : super
56
+ end
57
+
63
58
  # Extend the adapter with the JDBC PostgreSQL AdapterMethods
64
59
  def setup_connection(conn)
65
60
  conn = super(conn)
@@ -8,11 +8,6 @@ module Sequel
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
10
10
 
11
- # Return Sequel::JDBC::SQLite::Dataset object with the given opts.
12
- def dataset(opts=nil)
13
- Sequel::JDBC::SQLite::Dataset.new(self, opts)
14
- end
15
-
16
11
  private
17
12
 
18
13
  # Use last_insert_rowid() to get the last inserted id.
@@ -0,0 +1,41 @@
1
+ Sequel.require 'adapters/jdbc/mssql'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for SQLServer specific
6
+ # support via JDBC.
7
+ module SQLServer
8
+ # Database instance methods for SQLServer databases accessed via JDBC.
9
+ module DatabaseMethods
10
+ include Sequel::JDBC::MSSQL::DatabaseMethods
11
+
12
+ def metadata_dataset
13
+ ds = super
14
+ # Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
15
+ # for the getColumns result set specifies an incorrect type for the
16
+ # IS_AUTOINCREMENT column. The column is a string, but the type is
17
+ # specified as a short. This causes getObject() to throw a
18
+ # com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
19
+ # from char to SMALLINT is unsupported." Using getString() rather
20
+ # than getObject() for this column avoids the problem.
21
+ # Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
22
+ def ds.result_set_object_getter
23
+ lambda do |result, n, i|
24
+ if n == :is_autoincrement
25
+ @convert_types ? convert_type(result.getString(i)) : result.getString(i)
26
+ else
27
+ @convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
28
+ end
29
+ end
30
+ end
31
+ ds
32
+ end
33
+ end
34
+
35
+ # Dataset class for SQLServer datasets accessed via JDBC.
36
+ class Dataset < JDBC::Dataset
37
+ include Sequel::MSSQL::DatasetMethods
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,83 @@
1
+ module Sequel
2
+ module JDBC
3
+ module Transactions
4
+ TRANSACTION_BEGIN = 'Transaction.begin'.freeze
5
+ TRANSACTION_COMMIT = 'Transaction.commit'.freeze
6
+ TRANSACTION_RELEASE_SP = 'Transaction.release_savepoint'.freeze
7
+ TRANSACTION_ROLLBACK = 'Transaction.rollback'.freeze
8
+ TRANSACTION_ROLLBACK_SP = 'Transaction.rollback_savepoint'.freeze
9
+ TRANSACTION_SAVEPOINT= 'Transaction.savepoint'.freeze
10
+
11
+ # Check the JDBC DatabaseMetaData for savepoint support
12
+ def supports_savepoints?
13
+ return @supports_savepoints if defined?(@supports_savepoints)
14
+ @supports_savepoints = synchronize{|c| c.get_meta_data.supports_savepoints}
15
+ end
16
+
17
+ private
18
+
19
+ # Most JDBC drivers that support savepoints support releasing them.
20
+ def supports_releasing_savepoints?
21
+ true
22
+ end
23
+
24
+ # Use JDBC connection's setAutoCommit to false to start transactions
25
+ def begin_transaction(conn, opts={})
26
+ if supports_savepoints?
27
+ th = @transactions[conn]
28
+ if sps = th[:savepoints]
29
+ sps << log_yield(TRANSACTION_SAVEPOINT){conn.set_savepoint}
30
+ else
31
+ log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
32
+ th[:savepoints] = []
33
+ end
34
+ th[:savepoint_level] += 1
35
+ else
36
+ log_yield(TRANSACTION_BEGIN){conn.setAutoCommit(false)}
37
+ end
38
+ end
39
+
40
+ # Use JDBC connection's commit method to commit transactions
41
+ def commit_transaction(conn, opts={})
42
+ if supports_savepoints?
43
+ sps = @transactions[conn][:savepoints]
44
+ if sps.empty?
45
+ log_yield(TRANSACTION_COMMIT){conn.commit}
46
+ elsif supports_releasing_savepoints?
47
+ log_yield(TRANSACTION_RELEASE_SP){supports_releasing_savepoints? ? conn.release_savepoint(sps.last) : sps.last}
48
+ end
49
+ else
50
+ log_yield(TRANSACTION_COMMIT){conn.commit}
51
+ end
52
+ end
53
+
54
+ # Use JDBC connection's setAutoCommit to true to enable non-transactional behavior
55
+ def remove_transaction(conn, committed)
56
+ if supports_savepoints?
57
+ sps = @transactions[conn][:savepoints]
58
+ conn.setAutoCommit(true) if sps.empty?
59
+ sps.pop
60
+ else
61
+ conn.setAutoCommit(true)
62
+ end
63
+ ensure
64
+ super
65
+ end
66
+
67
+ # Use JDBC connection's rollback method to rollback transactions
68
+ def rollback_transaction(conn, opts={})
69
+ if supports_savepoints?
70
+ sps = @transactions[conn][:savepoints]
71
+ if sps.empty?
72
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
73
+ else
74
+ log_yield(TRANSACTION_ROLLBACK_SP){conn.rollback(sps.last)}
75
+ end
76
+ else
77
+ log_yield(TRANSACTION_ROLLBACK){conn.rollback}
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+
@@ -32,47 +32,89 @@ 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
- Sequel.ts_require 'adapters/jdbc/mssql'
57
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
60
+ Sequel.ts_require 'adapters/jdbc/sqlserver'
61
+ db.extend(Sequel::JDBC::SQLServer::DatabaseMethods)
62
+ db.dataset_class = Sequel::JDBC::SQLServer::Dataset
63
+ db.send(:set_mssql_unicode_strings)
58
64
  com.microsoft.sqlserver.jdbc.SQLServerDriver
59
65
  end,
60
66
  :jtds=>proc do |db|
61
- Sequel.ts_require 'adapters/jdbc/mssql'
62
- db.extend(Sequel::JDBC::MSSQL::DatabaseMethods)
67
+ Sequel.ts_require 'adapters/jdbc/jtds'
68
+ db.extend(Sequel::JDBC::JTDS::DatabaseMethods)
69
+ db.dataset_class = Sequel::JDBC::JTDS::Dataset
70
+ db.send(:set_mssql_unicode_strings)
63
71
  JDBC.load_gem('jtds')
64
72
  Java::net.sourceforge.jtds.jdbc.Driver
65
73
  end,
66
74
  :h2=>proc do |db|
67
75
  Sequel.ts_require 'adapters/jdbc/h2'
68
76
  db.extend(Sequel::JDBC::H2::DatabaseMethods)
77
+ db.dataset_class = Sequel::JDBC::H2::Dataset
69
78
  JDBC.load_gem('h2')
70
79
  org.h2.Driver
71
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,
72
95
  :as400=>proc do |db|
73
96
  Sequel.ts_require 'adapters/jdbc/as400'
74
97
  db.extend(Sequel::JDBC::AS400::DatabaseMethods)
98
+ db.dataset_class = Sequel::JDBC::AS400::Dataset
75
99
  com.ibm.as400.access.AS400JDBCDriver
100
+ end,
101
+ :"informix-sqli"=>proc do |db|
102
+ Sequel.ts_require 'adapters/jdbc/informix'
103
+ db.extend(Sequel::JDBC::Informix::DatabaseMethods)
104
+ db.dataset_class = Sequel::JDBC::Informix::Dataset
105
+ com.informix.jdbc.IfxDriver
106
+ end,
107
+ :db2=>proc do |db|
108
+ Sequel.ts_require 'adapters/jdbc/db2'
109
+ db.extend(Sequel::JDBC::DB2::DatabaseMethods)
110
+ db.dataset_class = Sequel::JDBC::DB2::Dataset
111
+ com.ibm.db2.jcc.DB2Driver
112
+ end,
113
+ :firebirdsql=>proc do |db|
114
+ Sequel.ts_require 'adapters/jdbc/firebird'
115
+ db.extend(Sequel::JDBC::Firebird::DatabaseMethods)
116
+ db.dataset_class = Sequel::JDBC::Firebird::Dataset
117
+ org.firebirdsql.jdbc.FBDriver
76
118
  end
77
119
  }
78
120
 
@@ -101,7 +143,7 @@ module Sequel
101
143
  # True by default, can be set to false to roughly double performance when
102
144
  # fetching rows.
103
145
  attr_accessor :convert_types
104
-
146
+
105
147
  # Call the DATABASE_SETUP proc directly after initialization,
106
148
  # so the object always uses sub adapter specific code. Also,
107
149
  # raise an error immediately if the connection doesn't have a
@@ -180,11 +222,6 @@ module Sequel
180
222
  setup_connection(conn)
181
223
  end
182
224
 
183
- # Return instances of JDBC::Dataset with the given opts.
184
- def dataset(opts = nil)
185
- JDBC::Dataset.new(self, opts)
186
- end
187
-
188
225
  # Execute the given SQL. If a block is given, if should be a SELECT
189
226
  # statement or something else that returns rows.
190
227
  def execute(sql, opts={}, &block)
@@ -246,12 +283,14 @@ module Sequel
246
283
  indexes
247
284
  end
248
285
 
286
+ # Whether or not JNDI is being used for this connection.
287
+ def jndi?
288
+ !!(uri =~ JNDI_URI_REGEXP)
289
+ end
290
+
249
291
  # All tables in this database
250
292
  def tables(opts={})
251
- ts = []
252
- m = output_identifier_meth
253
- metadata(:getTables, nil, nil, nil, ['TABLE'].to_java(:string)){|h| ts << m.call(h[:table_name])}
254
- ts
293
+ get_tables('TABLE', opts)
255
294
  end
256
295
 
257
296
  # The uri for this connection. You can specify the uri
@@ -264,11 +303,11 @@ module Sequel
264
303
  ur =~ /^\Ajdbc:/ ? ur : "jdbc:#{ur}"
265
304
  end
266
305
 
267
- # Whether or not JNDI is being used for this connection.
268
- def jndi?
269
- !!(uri =~ JNDI_URI_REGEXP)
306
+ # All views in this database
307
+ def views(opts={})
308
+ get_tables('VIEW', opts)
270
309
  end
271
-
310
+
272
311
  private
273
312
 
274
313
  # Close given adapter connections
@@ -276,6 +315,12 @@ module Sequel
276
315
  c.close
277
316
  end
278
317
 
318
+ # Raise a disconnect error if the SQL state of the cause of the exception indicates so.
319
+ def disconnect_error?(exception, opts)
320
+ cause = exception.respond_to?(:cause) ? exception.cause : exception
321
+ super || (cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/)
322
+ end
323
+
279
324
  # Execute the prepared statement. If the provided name is a
280
325
  # dataset, use that as the prepared statement, otherwise use
281
326
  # it as a key to look it up in the prepared_statements hash.
@@ -325,6 +370,12 @@ module Sequel
325
370
  end
326
371
  end
327
372
 
373
+ # Gets the connection from JNDI.
374
+ def get_connection_from_jndi
375
+ jndi_name = JNDI_URI_REGEXP.match(uri)[1]
376
+ JavaxNaming::InitialContext.new.lookup(jndi_name).connection
377
+ end
378
+
328
379
  # Gets the JDBC connection uri from the JNDI resource.
329
380
  def get_uri_from_jndi
330
381
  conn = get_connection_from_jndi
@@ -333,12 +384,14 @@ module Sequel
333
384
  conn.close if conn
334
385
  end
335
386
 
336
- # Gets the connection from JNDI.
337
- def get_connection_from_jndi
338
- jndi_name = JNDI_URI_REGEXP.match(uri)[1]
339
- JavaxNaming::InitialContext.new.lookup(jndi_name).connection
387
+ # Backbone of the tables and views support.
388
+ def get_tables(type, opts)
389
+ ts = []
390
+ m = output_identifier_meth
391
+ metadata(:getTables, nil, nil, nil, [type].to_java(:string)){|h| ts << m.call(h[:table_name])}
392
+ ts
340
393
  end
341
-
394
+
342
395
  # Support Date objects used in bound variables
343
396
  def java_sql_date(date)
344
397
  java.sql.Date.new(Time.local(date.year, date.month, date.day).to_i * 1000)
@@ -383,12 +436,6 @@ module Sequel
383
436
  end
384
437
  end
385
438
 
386
- # Treat SQLExceptions with a "Connection Error" SQLState as disconnects
387
- def raise_error(exception, opts={})
388
- cause = exception.respond_to?(:cause) ? exception.cause : exception
389
- super(exception, {:disconnect => cause.respond_to?(:getSQLState) && cause.getSQLState =~ /^08/}.merge(opts))
390
- end
391
-
392
439
  # Java being java, you need to specify the type of each argument
393
440
  # for the prepared statement, and bind it individually. This
394
441
  # guesses which JDBC method to use, and hopefully JRuby will convert
@@ -405,8 +452,8 @@ module Sequel
405
452
  cps.setDouble(i, arg)
406
453
  when TrueClass, FalseClass
407
454
  cps.setBoolean(i, arg)
408
- when nil
409
- cps.setNull(i, JavaSQL::Types::NULL)
455
+ when NilClass
456
+ cps.setString(i, nil)
410
457
  when DateTime
411
458
  cps.setTimestamp(i, java_sql_datetime(arg))
412
459
  when Date
@@ -435,8 +482,8 @@ module Sequel
435
482
 
436
483
  # Parse the table schema for the given table.
437
484
  def schema_parse_table(table, opts={})
438
- m = output_identifier_meth
439
- im = input_identifier_meth
485
+ m = output_identifier_meth(opts[:dataset])
486
+ im = input_identifier_meth(opts[:dataset])
440
487
  ds = dataset
441
488
  schema, table = schema_and_table(table)
442
489
  schema ||= opts[:schema]
@@ -444,9 +491,11 @@ module Sequel
444
491
  table = im.call(table)
445
492
  pks, ts = [], []
446
493
  metadata(:getPrimaryKeys, nil, schema, table) do |h|
494
+ next if schema_parse_table_skip?(h, schema)
447
495
  pks << h[:column_name]
448
496
  end
449
497
  metadata(:getColumns, nil, schema, table, nil) do |h|
498
+ next if schema_parse_table_skip?(h, schema)
450
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]}
451
500
  if s[:db_type] =~ DECIMAL_TYPE_RE && s[:scale] == 0
452
501
  s[:type] = :integer
@@ -456,6 +505,12 @@ module Sequel
456
505
  ts
457
506
  end
458
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
+
459
514
  # Yield a new statement object, and ensure that it is closed before returning.
460
515
  def statement(conn)
461
516
  stmt = conn.createStatement
@@ -476,6 +531,8 @@ module Sequel
476
531
 
477
532
  class Dataset < Sequel::Dataset
478
533
  include StoredProcedures
534
+
535
+ Database::DatasetClass = self
479
536
 
480
537
  # Use JDBC PreparedStatements instead of emulated ones. Statements
481
538
  # created using #prepare are cached at the connection level to allow
@@ -530,8 +587,8 @@ module Sequel
530
587
  # Uses the database's setting by default, can be set to false to roughly
531
588
  # double performance when fetching rows.
532
589
  attr_accessor :convert_types
533
-
534
- # Use the convert_types default setting from the database
590
+
591
+ # Use the convert_types default setting from the database.
535
592
  def initialize(db, opts={})
536
593
  @convert_types = db.convert_types
537
594
  super
@@ -560,8 +617,10 @@ module Sequel
560
617
  # Convert the type. Used for converting Java types to ruby types.
561
618
  def convert_type(v)
562
619
  case v
563
- when Java::JavaSQL::Timestamp, Java::JavaSQL::Time
564
- Sequel.database_to_application_timestamp(v.to_string)
620
+ when Java::JavaSQL::Timestamp
621
+ db.to_application_timestamp(v.to_string)
622
+ when Java::JavaSQL::Time
623
+ Sequel.string_to_time(v.to_string)
565
624
  when Java::JavaSQL::Date
566
625
  Sequel.string_to_date(v.to_string)
567
626
  when Java::JavaIo::BufferedReader
@@ -574,6 +633,8 @@ module Sequel
574
633
  Sequel::SQL::Blob.new(String.from_java_bytes(v))
575
634
  when Java::JavaSQL::Blob
576
635
  convert_type(v.getBytes(1, v.length))
636
+ when Java::JavaSQL::Clob
637
+ Sequel::SQL::Blob.new(v.getSubString(1, v.length))
577
638
  else
578
639
  v
579
640
  end
@@ -592,7 +653,12 @@ module Sequel
592
653
  cols = []
593
654
  i = 0
594
655
  meta.getColumnCount.times{cols << [output_identifier(meta.getColumnLabel(i+=1)), i]}
595
- @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
596
662
  blk = result_set_object_getter
597
663
  # get rows
598
664
  while result.next
@@ -600,8 +666,11 @@ module Sequel
600
666
  cols.each do |n, i|
601
667
  row[n] = blk.call(result, n, i)
602
668
  end
669
+ row.delete(rn) if rn
603
670
  yield row
604
671
  end
672
+ ensure
673
+ result.close
605
674
  end
606
675
 
607
676
  # Proc that takes the ResultSet and an integer field number and returns