sequel 3.21.0 → 3.32.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 (234) hide show
  1. data/CHANGELOG +539 -3
  2. data/MIT-LICENSE +1 -1
  3. data/README.rdoc +20 -6
  4. data/Rakefile +37 -19
  5. data/bin/sequel +1 -5
  6. data/doc/advanced_associations.rdoc +17 -0
  7. data/doc/association_basics.rdoc +293 -43
  8. data/doc/dataset_basics.rdoc +4 -4
  9. data/doc/dataset_filtering.rdoc +8 -0
  10. data/doc/mass_assignment.rdoc +54 -0
  11. data/doc/migration.rdoc +15 -538
  12. data/doc/model_hooks.rdoc +72 -27
  13. data/doc/opening_databases.rdoc +89 -50
  14. data/doc/prepared_statements.rdoc +40 -13
  15. data/doc/reflection.rdoc +8 -2
  16. data/doc/release_notes/3.22.0.txt +39 -0
  17. data/doc/release_notes/3.23.0.txt +172 -0
  18. data/doc/release_notes/3.24.0.txt +420 -0
  19. data/doc/release_notes/3.25.0.txt +88 -0
  20. data/doc/release_notes/3.26.0.txt +88 -0
  21. data/doc/release_notes/3.27.0.txt +82 -0
  22. data/doc/release_notes/3.28.0.txt +304 -0
  23. data/doc/release_notes/3.29.0.txt +459 -0
  24. data/doc/release_notes/3.30.0.txt +135 -0
  25. data/doc/release_notes/3.31.0.txt +146 -0
  26. data/doc/release_notes/3.32.0.txt +202 -0
  27. data/doc/schema_modification.rdoc +547 -0
  28. data/doc/sharding.rdoc +7 -1
  29. data/doc/testing.rdoc +129 -0
  30. data/doc/transactions.rdoc +137 -0
  31. data/doc/virtual_rows.rdoc +2 -2
  32. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  33. data/lib/sequel/adapters/ado.rb +40 -18
  34. data/lib/sequel/adapters/amalgalite.rb +17 -9
  35. data/lib/sequel/adapters/db2.rb +175 -86
  36. data/lib/sequel/adapters/dbi.rb +15 -15
  37. data/lib/sequel/adapters/do/mysql.rb +5 -7
  38. data/lib/sequel/adapters/do/postgres.rb +0 -5
  39. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  40. data/lib/sequel/adapters/do.rb +17 -36
  41. data/lib/sequel/adapters/firebird.rb +27 -208
  42. data/lib/sequel/adapters/ibmdb.rb +448 -0
  43. data/lib/sequel/adapters/informix.rb +6 -23
  44. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  45. data/lib/sequel/adapters/jdbc/db2.rb +52 -0
  46. data/lib/sequel/adapters/jdbc/derby.rb +260 -0
  47. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  48. data/lib/sequel/adapters/jdbc/h2.rb +66 -30
  49. data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
  50. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  51. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  52. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  53. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  54. data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
  55. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  58. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  59. data/lib/sequel/adapters/jdbc.rb +231 -78
  60. data/lib/sequel/adapters/mock.rb +339 -0
  61. data/lib/sequel/adapters/mysql.rb +85 -184
  62. data/lib/sequel/adapters/mysql2.rb +26 -25
  63. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  64. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  65. data/lib/sequel/adapters/odbc.rb +28 -9
  66. data/lib/sequel/adapters/openbase.rb +3 -5
  67. data/lib/sequel/adapters/oracle.rb +355 -53
  68. data/lib/sequel/adapters/postgres.rb +194 -33
  69. data/lib/sequel/adapters/shared/access.rb +32 -9
  70. data/lib/sequel/adapters/shared/db2.rb +328 -0
  71. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  72. data/lib/sequel/adapters/shared/informix.rb +53 -0
  73. data/lib/sequel/adapters/shared/mssql.rb +278 -107
  74. data/lib/sequel/adapters/shared/mysql.rb +203 -65
  75. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  76. data/lib/sequel/adapters/shared/oracle.rb +237 -46
  77. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  78. data/lib/sequel/adapters/shared/progress.rb +5 -8
  79. data/lib/sequel/adapters/shared/sqlite.rb +200 -50
  80. data/lib/sequel/adapters/sqlite.rb +29 -21
  81. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  82. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  83. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  84. data/lib/sequel/adapters/swift.rb +5 -5
  85. data/lib/sequel/adapters/tinytds.rb +160 -19
  86. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  87. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  88. data/lib/sequel/ast_transformer.rb +190 -0
  89. data/lib/sequel/connection_pool/threaded.rb +3 -2
  90. data/lib/sequel/connection_pool.rb +1 -1
  91. data/lib/sequel/core.rb +68 -5
  92. data/lib/sequel/database/connecting.rb +5 -6
  93. data/lib/sequel/database/dataset.rb +4 -4
  94. data/lib/sequel/database/dataset_defaults.rb +59 -1
  95. data/lib/sequel/database/logging.rb +1 -1
  96. data/lib/sequel/database/misc.rb +104 -19
  97. data/lib/sequel/database/query.rb +163 -59
  98. data/lib/sequel/database/schema_generator.rb +17 -7
  99. data/lib/sequel/database/schema_methods.rb +59 -29
  100. data/lib/sequel/dataset/actions.rb +240 -76
  101. data/lib/sequel/dataset/features.rb +91 -8
  102. data/lib/sequel/dataset/graph.rb +38 -11
  103. data/lib/sequel/dataset/misc.rb +50 -23
  104. data/lib/sequel/dataset/mutation.rb +12 -7
  105. data/lib/sequel/dataset/prepared_statements.rb +59 -27
  106. data/lib/sequel/dataset/query.rb +236 -43
  107. data/lib/sequel/dataset/sql.rb +676 -267
  108. data/lib/sequel/dataset.rb +8 -0
  109. data/lib/sequel/exceptions.rb +4 -0
  110. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  111. data/lib/sequel/extensions/migration.rb +6 -4
  112. data/lib/sequel/extensions/named_timezones.rb +5 -0
  113. data/lib/sequel/extensions/query.rb +1 -1
  114. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  115. data/lib/sequel/extensions/to_dot.rb +95 -83
  116. data/lib/sequel/model/associations.rb +1081 -344
  117. data/lib/sequel/model/base.rb +420 -133
  118. data/lib/sequel/model/errors.rb +1 -1
  119. data/lib/sequel/model/exceptions.rb +5 -1
  120. data/lib/sequel/model.rb +20 -10
  121. data/lib/sequel/plugins/active_model.rb +13 -1
  122. data/lib/sequel/plugins/association_pks.rb +22 -4
  123. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  124. data/lib/sequel/plugins/composition.rb +43 -10
  125. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  126. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  127. data/lib/sequel/plugins/force_encoding.rb +6 -6
  128. data/lib/sequel/plugins/identity_map.rb +114 -7
  129. data/lib/sequel/plugins/many_through_many.rb +68 -7
  130. data/lib/sequel/plugins/nested_attributes.rb +65 -10
  131. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  132. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  133. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  134. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  135. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  136. data/lib/sequel/plugins/serialization.rb +98 -49
  137. data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
  138. data/lib/sequel/plugins/sharding.rb +21 -54
  139. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  140. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  141. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  142. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  143. data/lib/sequel/sql.rb +109 -52
  144. data/lib/sequel/timezones.rb +57 -38
  145. data/lib/sequel/version.rb +1 -1
  146. data/spec/adapters/db2_spec.rb +146 -0
  147. data/spec/adapters/mssql_spec.rb +135 -30
  148. data/spec/adapters/mysql_spec.rb +244 -212
  149. data/spec/adapters/oracle_spec.rb +67 -77
  150. data/spec/adapters/postgres_spec.rb +267 -78
  151. data/spec/adapters/spec_helper.rb +6 -5
  152. data/spec/adapters/sqlite_spec.rb +35 -21
  153. data/spec/core/connection_pool_spec.rb +71 -92
  154. data/spec/core/core_sql_spec.rb +21 -30
  155. data/spec/core/database_spec.rb +789 -512
  156. data/spec/core/dataset_spec.rb +1176 -1061
  157. data/spec/core/expression_filters_spec.rb +159 -42
  158. data/spec/core/mock_adapter_spec.rb +419 -0
  159. data/spec/core/object_graph_spec.rb +86 -114
  160. data/spec/core/schema_generator_spec.rb +3 -3
  161. data/spec/core/schema_spec.rb +298 -38
  162. data/spec/core/spec_helper.rb +6 -48
  163. data/spec/extensions/active_model_spec.rb +13 -0
  164. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  165. data/spec/extensions/association_dependencies_spec.rb +2 -12
  166. data/spec/extensions/association_pks_spec.rb +66 -32
  167. data/spec/extensions/caching_spec.rb +23 -50
  168. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  169. data/spec/extensions/columns_introspection_spec.rb +91 -0
  170. data/spec/extensions/composition_spec.rb +18 -13
  171. data/spec/extensions/dataset_associations_spec.rb +199 -0
  172. data/spec/extensions/defaults_setter_spec.rb +64 -0
  173. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  174. data/spec/extensions/identity_map_spec.rb +114 -22
  175. data/spec/extensions/instance_filters_spec.rb +11 -21
  176. data/spec/extensions/instance_hooks_spec.rb +53 -0
  177. data/spec/extensions/json_serializer_spec.rb +4 -5
  178. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  179. data/spec/extensions/list_spec.rb +17 -39
  180. data/spec/extensions/many_through_many_spec.rb +283 -250
  181. data/spec/extensions/migration_spec.rb +35 -32
  182. data/spec/extensions/named_timezones_spec.rb +23 -3
  183. data/spec/extensions/nested_attributes_spec.rb +97 -88
  184. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  185. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  186. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  187. data/spec/extensions/prepared_statements_spec.rb +53 -0
  188. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  189. data/spec/extensions/pretty_table_spec.rb +1 -6
  190. data/spec/extensions/query_spec.rb +6 -0
  191. data/spec/extensions/rcte_tree_spec.rb +41 -43
  192. data/spec/extensions/schema_dumper_spec.rb +5 -8
  193. data/spec/extensions/schema_spec.rb +13 -21
  194. data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
  195. data/spec/extensions/serialization_spec.rb +81 -43
  196. data/spec/extensions/sharding_spec.rb +66 -140
  197. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  198. data/spec/extensions/spec_helper.rb +13 -61
  199. data/spec/extensions/sql_expr_spec.rb +20 -60
  200. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  201. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  202. data/spec/extensions/timestamps_spec.rb +6 -6
  203. data/spec/extensions/to_dot_spec.rb +4 -7
  204. data/spec/extensions/touch_spec.rb +13 -14
  205. data/spec/extensions/tree_spec.rb +11 -26
  206. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  207. data/spec/extensions/update_primary_key_spec.rb +30 -24
  208. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  209. data/spec/extensions/validation_helpers_spec.rb +16 -35
  210. data/spec/extensions/xml_serializer_spec.rb +16 -4
  211. data/spec/integration/associations_test.rb +661 -21
  212. data/spec/integration/database_test.rb +4 -2
  213. data/spec/integration/dataset_test.rb +500 -67
  214. data/spec/integration/eager_loader_test.rb +19 -21
  215. data/spec/integration/model_test.rb +80 -1
  216. data/spec/integration/plugin_test.rb +367 -119
  217. data/spec/integration/prepared_statement_test.rb +222 -125
  218. data/spec/integration/schema_test.rb +217 -39
  219. data/spec/integration/spec_helper.rb +39 -30
  220. data/spec/integration/timezone_test.rb +38 -12
  221. data/spec/integration/transaction_test.rb +182 -5
  222. data/spec/integration/type_test.rb +17 -3
  223. data/spec/model/association_reflection_spec.rb +201 -7
  224. data/spec/model/associations_spec.rb +955 -662
  225. data/spec/model/base_spec.rb +275 -95
  226. data/spec/model/dataset_methods_spec.rb +7 -27
  227. data/spec/model/eager_loading_spec.rb +677 -676
  228. data/spec/model/hooks_spec.rb +349 -67
  229. data/spec/model/model_spec.rb +222 -168
  230. data/spec/model/plugins_spec.rb +24 -13
  231. data/spec/model/record_spec.rb +381 -218
  232. data/spec/model/spec_helper.rb +13 -71
  233. data/spec/model/validations_spec.rb +11 -0
  234. metadata +117 -73
@@ -13,20 +13,17 @@ module Sequel
13
13
  # Database instance methods for MSSQL databases accessed via JDBC.
14
14
  module DatabaseMethods
15
15
  PRIMARY_KEY_INDEX_RE = /\Apk__/i.freeze
16
+ ATAT_IDENTITY = 'SELECT @@IDENTITY'.freeze
17
+ SCOPE_IDENTITY = 'SELECT SCOPE_IDENTITY()'.freeze
16
18
 
17
19
  include Sequel::MSSQL::DatabaseMethods
18
20
 
19
- # Return instance of Sequel::JDBC::MSSQL::Dataset with the given opts.
20
- def dataset(opts=nil)
21
- Sequel::JDBC::MSSQL::Dataset.new(self, opts)
22
- end
23
-
24
21
  private
25
22
 
26
23
  # Get the last inserted id using SCOPE_IDENTITY().
27
24
  def last_insert_id(conn, opts={})
28
25
  statement(conn) do |stmt|
29
- sql = opts[:prepared] ? 'SELECT @@IDENTITY' : 'SELECT SCOPE_IDENTITY()'
26
+ sql = opts[:prepared] ? ATAT_IDENTITY : SCOPE_IDENTITY
30
27
  rs = log_yield(sql){stmt.executeQuery(sql)}
31
28
  rs.next
32
29
  rs.getInt(1)
@@ -43,33 +40,6 @@ module Sequel
43
40
  def primary_key_index_re
44
41
  PRIMARY_KEY_INDEX_RE
45
42
  end
46
-
47
- def metadata_dataset
48
- ds = super
49
- # Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
50
- # for the getColumns result set specifies an incorrect type for the
51
- # IS_AUTOINCREMENT column. The column is a string, but the type is
52
- # specified as a short. This causes getObject() to throw a
53
- # com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
54
- # from char to SMALLINT is unsupported." Using getString() rather
55
- # than getObject() for this column avoids the problem.
56
- # Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
57
- def ds.result_set_object_getter
58
- lambda do |result, n, i|
59
- if n == :is_autoincrement
60
- @convert_types ? convert_type(result.getString(i)) : result.getString(i)
61
- else
62
- @convert_types ? convert_type(result.getObject(i)) : result.getObject(i)
63
- end
64
- end
65
- end
66
- ds
67
- end
68
- end
69
-
70
- # Dataset class for MSSQL datasets accessed via JDBC.
71
- class Dataset < JDBC::Dataset
72
- include Sequel::MSSQL::DatasetMethods
73
43
  end
74
44
  end
75
45
  end
@@ -8,11 +8,7 @@ module Sequel
8
8
  # Database instance methods for MySQL databases accessed via JDBC.
9
9
  module DatabaseMethods
10
10
  include Sequel::MySQL::DatabaseMethods
11
-
12
- # Return instance of Sequel::JDBC::MySQL::Dataset with the given opts.
13
- def dataset(opts=nil)
14
- Sequel::JDBC::MySQL::Dataset.new(self, opts)
15
- end
11
+ LAST_INSERT_ID = 'SELECT LAST_INSERT_ID()'.freeze
16
12
 
17
13
  private
18
14
 
@@ -39,7 +35,7 @@ module Sequel
39
35
  end
40
36
  else
41
37
  statement(conn) do |stmt|
42
- rs = stmt.executeQuery('SELECT LAST_INSERT_ID()')
38
+ rs = stmt.executeQuery(LAST_INSERT_ID)
43
39
  rs.next
44
40
  rs.getInt(1)
45
41
  end
@@ -56,17 +52,21 @@ module Sequel
56
52
  def schema_column_type(db_type)
57
53
  db_type == 'tinyint(1)' ? :boolean : super
58
54
  end
55
+
56
+ # By default, MySQL 'where id is null' selects the last inserted id.
57
+ # Turn that off unless explicitly enabled.
58
+ def setup_connection(conn)
59
+ super
60
+ sql = "SET SQL_AUTO_IS_NULL=0"
61
+ statement(conn){|s| log_yield(sql){s.execute(sql)}} unless opts[:auto_is_null]
62
+ conn
63
+ end
59
64
  end
60
65
 
61
66
  # Dataset class for MySQL datasets accessed via JDBC.
62
67
  class Dataset < JDBC::Dataset
63
68
  include Sequel::MySQL::DatasetMethods
64
69
 
65
- # Use execute_insert to execute the insert_sql.
66
- def insert(*values)
67
- execute_insert(insert_sql(*values))
68
- end
69
-
70
70
  # Use execute_insert to execute the replace_sql.
71
71
  def replace(*args)
72
72
  execute_insert(replace_sql(*args))
@@ -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
@@ -6,44 +7,106 @@ module Sequel
6
7
  module Oracle
7
8
  # Instance methods for Oracle Database objects accessed via JDBC.
8
9
  module DatabaseMethods
10
+ PRIMARY_KEY_INDEX_RE = /\Asys_/i.freeze
11
+
9
12
  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)
13
+ include Sequel::JDBC::Transactions
14
+
15
+ def self.extended(db)
16
+ db.instance_eval do
17
+ @autosequence = opts[:autosequence]
18
+ @primary_key_sequences = {}
19
+ end
17
20
  end
18
21
 
19
22
  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
23
+
24
+ def last_insert_id(conn, opts)
25
+ unless sequence = opts[:sequence]
26
+ if t = opts[:table]
27
+ sequence = sequence_for_table(t)
28
+ end
29
+ end
30
+ if sequence
31
+ sql = "SELECT #{literal(sequence)}.currval FROM dual"
32
+ statement(conn) do |stmt|
33
+ begin
34
+ rs = log_yield(sql){stmt.executeQuery(sql)}
35
+ rs.next
36
+ rs.getInt(1)
37
+ rescue java.sql.SQLException
38
+ nil
39
+ end
40
+ end
41
+ end
25
42
  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}
43
+
44
+ # Primary key indexes appear to start with sys_ on Oracle
45
+ def primary_key_index_re
46
+ PRIMARY_KEY_INDEX_RE
30
47
  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)
48
+
49
+ def schema_parse_table(*)
50
+ sch = super
51
+ sch.each do |c, s|
52
+ if s[:type] == :decimal && s[:scale] == -127
53
+ s[:type] = :integer
54
+ elsif s[:db_type] == 'DATE'
55
+ s[:type] = :datetime
56
+ end
57
+ end
58
+ sch
36
59
  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}
60
+
61
+ def schema_parse_table_skip?(h, schema)
62
+ super || (h[:table_schem] != current_user unless schema)
63
+ end
64
+
65
+ # As of Oracle 9.2, releasing savepoints is no longer supported.
66
+ def supports_releasing_savepoints?
67
+ false
41
68
  end
42
69
  end
43
70
 
44
71
  # Dataset class for Oracle datasets accessed via JDBC.
45
72
  class Dataset < JDBC::Dataset
46
73
  include Sequel::Oracle::DatasetMethods
74
+
75
+ private
76
+
77
+ JAVA_BIG_DECIMAL = ::Sequel::JDBC::Dataset::JAVA_BIG_DECIMAL
78
+
79
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
80
+ def oracle_decimal(v)
81
+ if v.scale == 0
82
+ i = v.long_value
83
+ if v.equals(JAVA_BIG_DECIMAL.new(i))
84
+ i
85
+ else
86
+ decimal(v)
87
+ end
88
+ else
89
+ decimal(v)
90
+ end
91
+ end
92
+ end
93
+
94
+ ORACLE_DECIMAL_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:oracle_decimal)
95
+
96
+ def convert_type_oracle_timestamp(v)
97
+ db.to_application_timestamp(v.to_string)
98
+ end
99
+
100
+ def convert_type_proc(v)
101
+ case v
102
+ when JAVA_BIG_DECIMAL
103
+ ORACLE_DECIMAL_METHOD
104
+ when Java::OracleSql::TIMESTAMP
105
+ method(:convert_type_oracle_timestamp)
106
+ else
107
+ super
108
+ end
109
+ end
47
110
  end
48
111
  end
49
112
  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)
@@ -78,6 +73,7 @@ module Sequel
78
73
  # Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
79
74
  class Dataset < JDBC::Dataset
80
75
  include Sequel::Postgres::DatasetMethods
76
+ APOS = Dataset::APOS
81
77
 
82
78
  # Add the shared PostgreSQL prepared statement methods
83
79
  def prepare(*args)
@@ -87,8 +83,8 @@ module Sequel
87
83
  end
88
84
 
89
85
  # Literalize strings similar to the native postgres adapter
90
- def literal_string(v)
91
- db.synchronize{|c| "'#{c.escape_string(v)}'"}
86
+ def literal_string_append(sql, v)
87
+ sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
92
88
  end
93
89
  end
94
90
  end
@@ -7,18 +7,14 @@ module Sequel
7
7
  # Instance methods for SQLite Database objects accessed via JDBC.
8
8
  module DatabaseMethods
9
9
  include Sequel::SQLite::DatabaseMethods
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
10
+ LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
15
11
 
16
12
  private
17
13
 
18
14
  # Use last_insert_rowid() to get the last inserted id.
19
15
  def last_insert_id(conn, opts={})
20
16
  statement(conn) do |stmt|
21
- rs = stmt.executeQuery('SELECT last_insert_rowid()')
17
+ rs = stmt.executeQuery(LAST_INSERT_ROWID)
22
18
  rs.next
23
19
  rs.getInt(1)
24
20
  end
@@ -0,0 +1,71 @@
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
+ # Work around a bug in SQL Server JDBC Driver 3.0, where the metadata
13
+ # for the getColumns result set specifies an incorrect type for the
14
+ # IS_AUTOINCREMENT column. The column is a string, but the type is
15
+ # specified as a short. This causes getObject() to throw a
16
+ # com.microsoft.sqlserver.jdbc.SQLServerException: "The conversion
17
+ # from char to SMALLINT is unsupported." Using getString() rather
18
+ # than getObject() for this column avoids the problem.
19
+ # Reference: http://social.msdn.microsoft.com/Forums/en/sqldataaccess/thread/20df12f3-d1bf-4526-9daa-239a83a8e435
20
+ module MetadataDatasetMethods
21
+ def process_result_set_convert(cols, result, rn)
22
+ while result.next
23
+ row = {}
24
+ cols.each do |n, i, p|
25
+ v = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
26
+ row[n] = if v
27
+ if p
28
+ p.call(v)
29
+ elsif p.nil?
30
+ cols[i-1][2] = p = convert_type_proc(v)
31
+ if p
32
+ p.call(v)
33
+ else
34
+ v
35
+ end
36
+ else
37
+ v
38
+ end
39
+ else
40
+ v
41
+ end
42
+ end
43
+ row.delete(rn) if rn
44
+ yield row
45
+ end
46
+ end
47
+
48
+ def process_result_set_no_convert(cols, result, rn)
49
+ while result.next
50
+ row = {}
51
+ cols.each do |n, i|
52
+ row[n] = (n == :is_autoincrement ? result.getString(i) : result.getObject(i))
53
+ end
54
+ row.delete(rn) if rn
55
+ yield row
56
+ end
57
+ end
58
+ end
59
+
60
+ def metadata_dataset
61
+ super.extend(MetadataDatasetMethods)
62
+ end
63
+ end
64
+
65
+ # Dataset class for SQLServer datasets accessed via JDBC.
66
+ class Dataset < JDBC::Dataset
67
+ include Sequel::MSSQL::DatasetMethods
68
+ end
69
+ end
70
+ end
71
+ 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
+