sequel 3.21.0 → 3.31.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 (225) hide show
  1. data/CHANGELOG +485 -3
  2. data/README.rdoc +20 -6
  3. data/Rakefile +37 -19
  4. data/bin/sequel +1 -5
  5. data/doc/association_basics.rdoc +249 -43
  6. data/doc/dataset_basics.rdoc +4 -4
  7. data/doc/dataset_filtering.rdoc +8 -0
  8. data/doc/mass_assignment.rdoc +54 -0
  9. data/doc/migration.rdoc +15 -538
  10. data/doc/model_hooks.rdoc +72 -27
  11. data/doc/opening_databases.rdoc +89 -50
  12. data/doc/prepared_statements.rdoc +40 -13
  13. data/doc/reflection.rdoc +8 -2
  14. data/doc/release_notes/3.22.0.txt +39 -0
  15. data/doc/release_notes/3.23.0.txt +172 -0
  16. data/doc/release_notes/3.24.0.txt +420 -0
  17. data/doc/release_notes/3.25.0.txt +88 -0
  18. data/doc/release_notes/3.26.0.txt +88 -0
  19. data/doc/release_notes/3.27.0.txt +82 -0
  20. data/doc/release_notes/3.28.0.txt +304 -0
  21. data/doc/release_notes/3.29.0.txt +459 -0
  22. data/doc/release_notes/3.30.0.txt +135 -0
  23. data/doc/release_notes/3.31.0.txt +146 -0
  24. data/doc/schema_modification.rdoc +547 -0
  25. data/doc/sharding.rdoc +7 -1
  26. data/doc/testing.rdoc +129 -0
  27. data/doc/transactions.rdoc +137 -0
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado/mssql.rb +18 -6
  30. data/lib/sequel/adapters/ado.rb +40 -18
  31. data/lib/sequel/adapters/amalgalite.rb +17 -9
  32. data/lib/sequel/adapters/db2.rb +175 -86
  33. data/lib/sequel/adapters/dbi.rb +15 -15
  34. data/lib/sequel/adapters/do/mysql.rb +5 -7
  35. data/lib/sequel/adapters/do/postgres.rb +0 -5
  36. data/lib/sequel/adapters/do/sqlite.rb +0 -5
  37. data/lib/sequel/adapters/do.rb +17 -36
  38. data/lib/sequel/adapters/firebird.rb +27 -208
  39. data/lib/sequel/adapters/ibmdb.rb +448 -0
  40. data/lib/sequel/adapters/informix.rb +6 -23
  41. data/lib/sequel/adapters/jdbc/as400.rb +16 -34
  42. data/lib/sequel/adapters/jdbc/db2.rb +45 -0
  43. data/lib/sequel/adapters/jdbc/derby.rb +247 -0
  44. data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
  45. data/lib/sequel/adapters/jdbc/h2.rb +56 -29
  46. data/lib/sequel/adapters/jdbc/hsqldb.rb +170 -0
  47. data/lib/sequel/adapters/jdbc/informix.rb +26 -0
  48. data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
  49. data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
  50. data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
  51. data/lib/sequel/adapters/jdbc/oracle.rb +81 -25
  52. data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
  53. data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
  54. data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
  55. data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
  56. data/lib/sequel/adapters/jdbc.rb +231 -78
  57. data/lib/sequel/adapters/mock.rb +335 -0
  58. data/lib/sequel/adapters/mysql.rb +82 -184
  59. data/lib/sequel/adapters/mysql2.rb +26 -25
  60. data/lib/sequel/adapters/odbc/db2.rb +17 -0
  61. data/lib/sequel/adapters/odbc/mssql.rb +1 -6
  62. data/lib/sequel/adapters/odbc.rb +28 -9
  63. data/lib/sequel/adapters/openbase.rb +3 -5
  64. data/lib/sequel/adapters/oracle.rb +351 -53
  65. data/lib/sequel/adapters/postgres.rb +194 -33
  66. data/lib/sequel/adapters/shared/access.rb +32 -9
  67. data/lib/sequel/adapters/shared/db2.rb +321 -0
  68. data/lib/sequel/adapters/shared/firebird.rb +221 -0
  69. data/lib/sequel/adapters/shared/informix.rb +53 -0
  70. data/lib/sequel/adapters/shared/mssql.rb +231 -106
  71. data/lib/sequel/adapters/shared/mysql.rb +181 -63
  72. data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +231 -41
  74. data/lib/sequel/adapters/shared/postgres.rb +214 -82
  75. data/lib/sequel/adapters/shared/progress.rb +4 -7
  76. data/lib/sequel/adapters/shared/sqlite.rb +201 -57
  77. data/lib/sequel/adapters/sqlite.rb +29 -21
  78. data/lib/sequel/adapters/swift/mysql.rb +12 -7
  79. data/lib/sequel/adapters/swift/postgres.rb +0 -5
  80. data/lib/sequel/adapters/swift/sqlite.rb +8 -6
  81. data/lib/sequel/adapters/swift.rb +5 -5
  82. data/lib/sequel/adapters/tinytds.rb +160 -19
  83. data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
  84. data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
  85. data/lib/sequel/ast_transformer.rb +190 -0
  86. data/lib/sequel/connection_pool/threaded.rb +3 -2
  87. data/lib/sequel/connection_pool.rb +1 -1
  88. data/lib/sequel/core.rb +46 -5
  89. data/lib/sequel/database/connecting.rb +5 -6
  90. data/lib/sequel/database/dataset.rb +4 -4
  91. data/lib/sequel/database/dataset_defaults.rb +59 -1
  92. data/lib/sequel/database/logging.rb +1 -1
  93. data/lib/sequel/database/misc.rb +104 -19
  94. data/lib/sequel/database/query.rb +153 -58
  95. data/lib/sequel/database/schema_generator.rb +17 -7
  96. data/lib/sequel/database/schema_methods.rb +59 -29
  97. data/lib/sequel/dataset/actions.rb +231 -76
  98. data/lib/sequel/dataset/features.rb +91 -8
  99. data/lib/sequel/dataset/graph.rb +38 -11
  100. data/lib/sequel/dataset/misc.rb +50 -23
  101. data/lib/sequel/dataset/mutation.rb +5 -6
  102. data/lib/sequel/dataset/prepared_statements.rb +48 -27
  103. data/lib/sequel/dataset/query.rb +236 -43
  104. data/lib/sequel/dataset/sql.rb +665 -253
  105. data/lib/sequel/dataset.rb +8 -0
  106. data/lib/sequel/exceptions.rb +4 -0
  107. data/lib/sequel/extensions/columns_introspection.rb +61 -0
  108. data/lib/sequel/extensions/migration.rb +6 -4
  109. data/lib/sequel/extensions/named_timezones.rb +5 -0
  110. data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
  111. data/lib/sequel/extensions/to_dot.rb +95 -83
  112. data/lib/sequel/model/associations.rb +1020 -337
  113. data/lib/sequel/model/base.rb +414 -132
  114. data/lib/sequel/model/errors.rb +1 -1
  115. data/lib/sequel/model/exceptions.rb +5 -1
  116. data/lib/sequel/model.rb +15 -8
  117. data/lib/sequel/plugins/association_pks.rb +22 -4
  118. data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
  119. data/lib/sequel/plugins/dataset_associations.rb +100 -0
  120. data/lib/sequel/plugins/defaults_setter.rb +58 -0
  121. data/lib/sequel/plugins/force_encoding.rb +6 -6
  122. data/lib/sequel/plugins/identity_map.rb +114 -7
  123. data/lib/sequel/plugins/many_through_many.rb +65 -7
  124. data/lib/sequel/plugins/prepared_statements.rb +151 -0
  125. data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
  126. data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
  127. data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
  128. data/lib/sequel/plugins/rcte_tree.rb +29 -15
  129. data/lib/sequel/plugins/serialization.rb +88 -44
  130. data/lib/sequel/plugins/serialization_modification_detection.rb +51 -0
  131. data/lib/sequel/plugins/sharding.rb +21 -54
  132. data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
  133. data/lib/sequel/plugins/typecast_on_load.rb +9 -12
  134. data/lib/sequel/plugins/update_primary_key.rb +2 -2
  135. data/lib/sequel/plugins/xml_serializer.rb +3 -3
  136. data/lib/sequel/sql.rb +109 -52
  137. data/lib/sequel/timezones.rb +57 -38
  138. data/lib/sequel/version.rb +1 -1
  139. data/spec/adapters/db2_spec.rb +146 -0
  140. data/spec/adapters/mssql_spec.rb +111 -29
  141. data/spec/adapters/mysql_spec.rb +135 -123
  142. data/spec/adapters/oracle_spec.rb +49 -77
  143. data/spec/adapters/postgres_spec.rb +267 -78
  144. data/spec/adapters/spec_helper.rb +6 -5
  145. data/spec/adapters/sqlite_spec.rb +35 -21
  146. data/spec/core/connection_pool_spec.rb +71 -92
  147. data/spec/core/core_sql_spec.rb +21 -30
  148. data/spec/core/database_spec.rb +788 -512
  149. data/spec/core/dataset_spec.rb +1073 -1053
  150. data/spec/core/expression_filters_spec.rb +159 -42
  151. data/spec/core/mock_adapter_spec.rb +419 -0
  152. data/spec/core/object_graph_spec.rb +86 -114
  153. data/spec/core/schema_generator_spec.rb +3 -3
  154. data/spec/core/schema_spec.rb +298 -38
  155. data/spec/core/spec_helper.rb +6 -48
  156. data/spec/extensions/association_autoreloading_spec.rb +1 -10
  157. data/spec/extensions/association_dependencies_spec.rb +2 -12
  158. data/spec/extensions/association_pks_spec.rb +66 -32
  159. data/spec/extensions/caching_spec.rb +23 -50
  160. data/spec/extensions/class_table_inheritance_spec.rb +31 -83
  161. data/spec/extensions/columns_introspection_spec.rb +91 -0
  162. data/spec/extensions/composition_spec.rb +18 -13
  163. data/spec/extensions/dataset_associations_spec.rb +199 -0
  164. data/spec/extensions/defaults_setter_spec.rb +64 -0
  165. data/spec/extensions/hook_class_methods_spec.rb +65 -91
  166. data/spec/extensions/identity_map_spec.rb +114 -22
  167. data/spec/extensions/instance_filters_spec.rb +11 -21
  168. data/spec/extensions/instance_hooks_spec.rb +53 -0
  169. data/spec/extensions/json_serializer_spec.rb +4 -5
  170. data/spec/extensions/lazy_attributes_spec.rb +16 -20
  171. data/spec/extensions/list_spec.rb +17 -39
  172. data/spec/extensions/many_through_many_spec.rb +283 -250
  173. data/spec/extensions/migration_spec.rb +35 -32
  174. data/spec/extensions/named_timezones_spec.rb +23 -3
  175. data/spec/extensions/nested_attributes_spec.rb +97 -88
  176. data/spec/extensions/optimistic_locking_spec.rb +9 -20
  177. data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
  178. data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
  179. data/spec/extensions/prepared_statements_spec.rb +53 -0
  180. data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
  181. data/spec/extensions/pretty_table_spec.rb +1 -6
  182. data/spec/extensions/rcte_tree_spec.rb +41 -43
  183. data/spec/extensions/schema_dumper_spec.rb +5 -8
  184. data/spec/extensions/schema_spec.rb +13 -21
  185. data/spec/extensions/serialization_modification_detection_spec.rb +37 -0
  186. data/spec/extensions/serialization_spec.rb +72 -43
  187. data/spec/extensions/sharding_spec.rb +66 -140
  188. data/spec/extensions/single_table_inheritance_spec.rb +18 -29
  189. data/spec/extensions/spec_helper.rb +13 -61
  190. data/spec/extensions/sql_expr_spec.rb +20 -60
  191. data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
  192. data/spec/extensions/thread_local_timezones_spec.rb +22 -2
  193. data/spec/extensions/timestamps_spec.rb +6 -6
  194. data/spec/extensions/to_dot_spec.rb +4 -7
  195. data/spec/extensions/touch_spec.rb +13 -14
  196. data/spec/extensions/tree_spec.rb +11 -26
  197. data/spec/extensions/typecast_on_load_spec.rb +1 -6
  198. data/spec/extensions/update_primary_key_spec.rb +30 -24
  199. data/spec/extensions/validation_class_methods_spec.rb +30 -51
  200. data/spec/extensions/validation_helpers_spec.rb +16 -35
  201. data/spec/extensions/xml_serializer_spec.rb +16 -4
  202. data/spec/integration/associations_test.rb +537 -21
  203. data/spec/integration/database_test.rb +4 -2
  204. data/spec/integration/dataset_test.rb +461 -65
  205. data/spec/integration/eager_loader_test.rb +19 -21
  206. data/spec/integration/model_test.rb +80 -1
  207. data/spec/integration/plugin_test.rb +304 -116
  208. data/spec/integration/prepared_statement_test.rb +212 -122
  209. data/spec/integration/schema_test.rb +161 -30
  210. data/spec/integration/spec_helper.rb +39 -30
  211. data/spec/integration/timezone_test.rb +38 -12
  212. data/spec/integration/transaction_test.rb +172 -5
  213. data/spec/integration/type_test.rb +17 -3
  214. data/spec/model/association_reflection_spec.rb +201 -7
  215. data/spec/model/associations_spec.rb +865 -662
  216. data/spec/model/base_spec.rb +275 -95
  217. data/spec/model/dataset_methods_spec.rb +7 -27
  218. data/spec/model/eager_loading_spec.rb +677 -676
  219. data/spec/model/hooks_spec.rb +309 -67
  220. data/spec/model/model_spec.rb +222 -168
  221. data/spec/model/plugins_spec.rb +24 -13
  222. data/spec/model/record_spec.rb +381 -218
  223. data/spec/model/spec_helper.rb +13 -71
  224. data/spec/model/validations_spec.rb +11 -0
  225. metadata +115 -73
@@ -0,0 +1,247 @@
1
+ Sequel.require 'adapters/jdbc/transactions'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset support for Derby databases accessed via JDBC.
6
+ module Derby
7
+ # Instance methods for Derby Database objects accessed via JDBC.
8
+ module DatabaseMethods
9
+ include ::Sequel::JDBC::Transactions
10
+
11
+ # Derby doesn't support casting integer to varchar, only integer to char,
12
+ # and char(254) appears to have the widest support (with char(255) failing).
13
+ # This does add a bunch of extra spaces at the end, but those will be trimmed
14
+ # elsewhere.
15
+ def cast_type_literal(type)
16
+ (type == String) ? 'CHAR(254)' : super
17
+ end
18
+
19
+ # Derby uses the :derby database type.
20
+ def database_type
21
+ :derby
22
+ end
23
+
24
+ # Derby uses an IDENTITY sequence for autoincrementing columns.
25
+ def serial_primary_key_options
26
+ {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
27
+ end
28
+
29
+ # The SVN version of the database.
30
+ def svn_version
31
+ @svn_version ||= begin
32
+ v = synchronize{|c| c.get_meta_data.get_database_product_version}
33
+ v =~ /\((\d+)\)\z/
34
+ $1.to_i
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ # Derby-specific syntax for renaming columns and changing a columns type/nullity.
41
+ def alter_table_sql(table, op)
42
+ case op[:op]
43
+ when :rename_column
44
+ "RENAME COLUMN #{quote_schema_table(table)}.#{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
45
+ when :set_column_type
46
+ # Derby is very limited in changing a columns type, so adding a new column and then dropping the existing column is
47
+ # the best approach, as mentioned in the Derby documentation.
48
+ temp_name = :x_sequel_temp_column_x
49
+ [alter_table_sql(table, op.merge(:op=>:add_column, :name=>temp_name)),
50
+ from(table).update_sql(temp_name=>::Sequel::SQL::Cast.new(op[:name], op[:type])),
51
+ alter_table_sql(table, op.merge(:op=>:drop_column)),
52
+ alter_table_sql(table, op.merge(:op=>:rename_column, :name=>temp_name, :new_name=>op[:name]))]
53
+ when :set_column_null
54
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
55
+ else
56
+ super
57
+ end
58
+ end
59
+
60
+ # Derby doesn't allow specifying NULL for columns, only NOT NULL.
61
+ def column_definition_null_sql(sql, column)
62
+ sql << " NOT NULL" if column.fetch(:null, column[:allow_null]) == false
63
+ end
64
+
65
+ # Temporary table creation on Derby use DECLARE instead of CREATE.
66
+ def create_table_sql(name, generator, options)
67
+ if options[:temp]
68
+ "DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)} (#{column_list_sql(generator)}) NOT LOGGED"
69
+ else
70
+ super
71
+ end
72
+ end
73
+
74
+ # Use IDENTITY_VAL_LOCAL() to get the last inserted id.
75
+ def last_insert_id(conn, opts={})
76
+ statement(conn) do |stmt|
77
+ sql = 'SELECT IDENTITY_VAL_LOCAL() FROM sysibm.sysdummy1'
78
+ rs = log_yield(sql){stmt.executeQuery(sql)}
79
+ rs.next
80
+ rs.getInt(1)
81
+ end
82
+ end
83
+
84
+ # Derby uses RENAME TABLE syntax to rename tables.
85
+ def rename_table_sql(name, new_name)
86
+ "RENAME TABLE #{quote_schema_table(name)} TO #{quote_schema_table(new_name)}"
87
+ end
88
+
89
+ # If an :identity option is present in the column, add the necessary IDENTITY SQL.
90
+ def type_literal(column)
91
+ if column[:identity]
92
+ sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
93
+ if sw = column[:start_with]
94
+ sql << " (START WITH #{sw.to_i}"
95
+ sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
96
+ sql << ")"
97
+ end
98
+ sql
99
+ else
100
+ super
101
+ end
102
+ end
103
+ end
104
+
105
+ # Dataset class for Derby datasets accessed via JDBC.
106
+ class Dataset < JDBC::Dataset
107
+ PAREN_CLOSE = Dataset::PAREN_CLOSE
108
+ PAREN_OPEN = Dataset::PAREN_OPEN
109
+ OFFSET = Dataset::OFFSET
110
+ CAST_STRING_OPEN = "RTRIM(".freeze
111
+ BITCOMP_OPEN = "((0 - ".freeze
112
+ BITCOMP_CLOSE = ") - 1)".freeze
113
+ BLOB_OPEN = "CAST(X'".freeze
114
+ BLOB_CLOSE = "' AS BLOB)".freeze
115
+ HSTAR = "H*".freeze
116
+ TIME_FORMAT = "'%H:%M:%S'".freeze
117
+ DEFAULT_FROM = " FROM sysibm.sysdummy1".freeze
118
+ ROWS = " ROWS".freeze
119
+ FETCH_FIRST = " FETCH FIRST ".freeze
120
+ ROWS_ONLY = " ROWS ONLY".freeze
121
+ BOOL_TRUE = '(1 = 1)'.freeze
122
+ BOOL_FALSE = '(1 = 0)'.freeze
123
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
124
+
125
+ # Derby doesn't support an expression between CASE and WHEN,
126
+ # so emulate it by using an equality statement for all of the
127
+ # conditions.
128
+ def case_expression_sql_append(sql, ce)
129
+ if ce.expression?
130
+ e = ce.expression
131
+ case_expression_sql_append(sql, ::Sequel::SQL::CaseExpression.new(ce.conditions.map{|c, r| [::Sequel::SQL::BooleanExpression.new(:'=', e, c), r]}, ce.default))
132
+ else
133
+ super
134
+ end
135
+ end
136
+
137
+ # If the type is String, trim the extra spaces since CHAR is used instead
138
+ # of varchar. This can cause problems if you are casting a char/varchar to
139
+ # a string and the ending whitespace is important.
140
+ def cast_sql_append(sql, expr, type)
141
+ if type == String
142
+ sql << CAST_STRING_OPEN
143
+ super
144
+ sql << PAREN_CLOSE
145
+ else
146
+ super
147
+ end
148
+ end
149
+
150
+ # Handle Derby specific LIKE, extract, and some bitwise compliment support.
151
+ def complex_expression_sql_append(sql, op, args)
152
+ case op
153
+ when :ILIKE
154
+ super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
155
+ when :"NOT ILIKE"
156
+ super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
157
+ when :&, :|, :^, :<<, :>>
158
+ raise Error, "Derby doesn't support the #{op} operator"
159
+ when :'B~'
160
+ sql << BITCOMP_OPEN
161
+ literal_append(sql, args.at(0))
162
+ sql << BITCOMP_CLOSE
163
+ when :extract
164
+ sql << args.at(0).to_s << PAREN_OPEN
165
+ literal_append(sql, args.at(1))
166
+ sql << PAREN_CLOSE
167
+ else
168
+ super
169
+ end
170
+ end
171
+
172
+ # Derby supports GROUP BY ROLLUP (but not CUBE)
173
+ def supports_group_rollup?
174
+ true
175
+ end
176
+
177
+ # Derby does not support IS TRUE.
178
+ def supports_is_true?
179
+ false
180
+ end
181
+
182
+ # Derby does not support IN/NOT IN with multiple columns
183
+ def supports_multiple_column_in?
184
+ false
185
+ end
186
+
187
+ private
188
+
189
+ # Derby needs a hex string casted to BLOB for blobs.
190
+ def literal_blob_append(sql, v)
191
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << BLOB_CLOSE
192
+ end
193
+
194
+ # Derby needs the standard workaround to insert all default values into
195
+ # a table with more than one column.
196
+ def insert_supports_empty_values?
197
+ false
198
+ end
199
+
200
+ # Derby uses an expression yielding false for false values.
201
+ # Newer versions can use the FALSE literal, but the latest gem version cannot.
202
+ def literal_false
203
+ BOOL_FALSE
204
+ end
205
+
206
+ # Derby handles fractional seconds in timestamps, but not in times
207
+ def literal_sqltime(v)
208
+ v.strftime(TIME_FORMAT)
209
+ end
210
+
211
+ # Derby uses an expression yielding true for true values.
212
+ # Newer versions can use the TRUE literal, but the latest gem version cannot.
213
+ def literal_true
214
+ BOOL_TRUE
215
+ end
216
+
217
+ # Derby doesn't support common table expressions.
218
+ def select_clause_methods
219
+ SELECT_CLAUSE_METHODS
220
+ end
221
+
222
+ # Use a default FROM table if the dataset does not contain a FROM table.
223
+ def select_from_sql(sql)
224
+ if @opts[:from]
225
+ super
226
+ else
227
+ sql << DEFAULT_FROM
228
+ end
229
+ end
230
+
231
+ # Offset comes before limit in Derby
232
+ def select_limit_sql(sql)
233
+ if o = @opts[:offset]
234
+ sql << OFFSET
235
+ literal_append(sql, o)
236
+ sql << ROWS
237
+ end
238
+ if l = @opts[:limit]
239
+ sql << FETCH_FIRST
240
+ literal_append(sql, l)
241
+ sql << ROWS_ONLY
242
+ end
243
+ end
244
+ end
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,29 @@
1
+ Sequel.require 'adapters/shared/firebird'
2
+ Sequel.require 'adapters/jdbc/transactions'
3
+
4
+ module Sequel
5
+ module JDBC
6
+ # Database and Dataset instance methods for Firebird specific
7
+ # support via JDBC.
8
+ module Firebird
9
+ # Database instance methods for Firebird databases accessed via JDBC.
10
+ module DatabaseMethods
11
+ include Sequel::Firebird::DatabaseMethods
12
+ include Sequel::JDBC::Transactions
13
+
14
+ # Add the primary_keys and primary_key_sequences instance variables,
15
+ # so we can get the correct return values for inserted rows.
16
+ def self.extended(db)
17
+ db.instance_eval do
18
+ @primary_keys = {}
19
+ end
20
+ end
21
+ end
22
+
23
+ # Dataset class for Firebird datasets accessed via JDBC.
24
+ class Dataset < JDBC::Dataset
25
+ include Sequel::Firebird::DatasetMethods
26
+ end
27
+ end
28
+ end
29
+ end
@@ -17,11 +17,6 @@ module Sequel
17
17
  :h2
18
18
  end
19
19
 
20
- # Return Sequel::JDBC::H2::Dataset object with the given opts.
21
- def dataset(opts=nil)
22
- Sequel::JDBC::H2::Dataset.new(self, opts)
23
- end
24
-
25
20
  # Rollback an existing prepared transaction with the given transaction
26
21
  # identifier string.
27
22
  def rollback_prepared_transaction(transaction_id)
@@ -33,6 +28,11 @@ module Sequel
33
28
  {:primary_key => true, :type => :identity}
34
29
  end
35
30
 
31
+ # H2 supports CREATE TABLE IF NOT EXISTS syntax.
32
+ def supports_create_table_if_not_exists?
33
+ true
34
+ end
35
+
36
36
  # H2 supports prepared transactions
37
37
  def supports_prepared_transactions?
38
38
  true
@@ -48,8 +48,8 @@ module Sequel
48
48
  # If the :prepare option is given and we aren't in a savepoint,
49
49
  # prepare the transaction for a two-phase commit.
50
50
  def commit_transaction(conn, opts={})
51
- if opts[:prepare] && Thread.current[:sequel_transaction_depth] <= 1
52
- log_connection_execute(conn, "PREPARE COMMIT #{opts[:prepare]}")
51
+ if (s = opts[:prepare]) && @transactions[conn][:savepoint_level] <= 1
52
+ log_connection_execute(conn, "PREPARE COMMIT #{s}")
53
53
  else
54
54
  super
55
55
  end
@@ -90,7 +90,8 @@ module Sequel
90
90
  # Use IDENTITY() to get the last inserted id.
91
91
  def last_insert_id(conn, opts={})
92
92
  statement(conn) do |stmt|
93
- rs = stmt.executeQuery('SELECT IDENTITY();')
93
+ sql = 'SELECT IDENTITY();'
94
+ rs = log_yield(sql){stmt.executeQuery(sql)}
94
95
  rs.next
95
96
  rs.getInt(1)
96
97
  end
@@ -99,28 +100,41 @@ module Sequel
99
100
  def primary_key_index_re
100
101
  PRIMARY_KEY_INDEX_RE
101
102
  end
103
+
104
+ # Treat clob as string instead of blob
105
+ def schema_column_type(db_type)
106
+ db_type == 'clob' ? :string : super
107
+ end
102
108
  end
103
109
 
104
110
  # Dataset class for H2 datasets accessed via JDBC.
105
111
  class Dataset < JDBC::Dataset
106
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit')
112
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
107
113
  BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
114
+ APOS = Dataset::APOS
115
+ HSTAR = "H*".freeze
116
+ BITCOMP_OPEN = "((0 - ".freeze
117
+ BITCOMP_CLOSE = ") - 1)".freeze
118
+ ILIKE_PLACEHOLDER = "CAST(? AS VARCHAR_IGNORECASE)".freeze
119
+ TIME_FORMAT = "'%H:%M:%S'".freeze
108
120
 
109
- # Work around H2's lack of a case insensitive LIKE operator
110
- def complex_expression_sql(op, args)
121
+ # Emulate the case insensitive LIKE operator and the bitwise operators.
122
+ def complex_expression_sql_append(sql, op, args)
111
123
  case op
112
- when :ILIKE
113
- super(:LIKE, [SQL::PlaceholderLiteralString.new("CAST(? AS VARCHAR_IGNORECASE)", [args.at(0)]), args.at(1)])
114
- when :"NOT ILIKE"
115
- super(:"NOT LIKE", [SQL::PlaceholderLiteralString.new("CAST(? AS VARCHAR_IGNORECASE)", [args.at(0)]), args.at(1)])
124
+ when :ILIKE, :"NOT ILIKE"
125
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::PlaceholderLiteralString.new(ILIKE_PLACEHOLDER, [args.at(0)]), args.at(1)])
116
126
  when :&, :|, :^
117
- literal(SQL::Function.new(BITWISE_METHOD_MAP[op], *args))
127
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
118
128
  when :<<
119
- "(#{literal(args[0])} * POWER(2, #{literal(args[1])}))"
129
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
120
130
  when :>>
121
- "(#{literal(args[0])} / POWER(2, #{literal(args[1])}))"
131
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
132
+ when :'B~'
133
+ sql << BITCOMP_OPEN
134
+ literal_append(sql, args.at(0))
135
+ sql << BITCOMP_CLOSE
122
136
  else
123
- super(op, args)
137
+ super
124
138
  end
125
139
  end
126
140
 
@@ -145,21 +159,34 @@ module Sequel
145
159
  end
146
160
 
147
161
  private
148
-
149
- # H2 expects hexadecimal strings for blob values
150
- def literal_blob(v)
151
- literal_string v.unpack("H*").first
162
+
163
+ #JAVA_H2_CLOB = Java::OrgH2Jdbc::JdbcClob
164
+
165
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
166
+ def h2_clob(v) v.getSubString(1, v.length) end
152
167
  end
153
-
154
- def convert_type(v)
155
- case v
156
- when Java::OrgH2Jdbc::JdbcClob
157
- convert_type(v.getSubString(1, v.length))
168
+
169
+ H2_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:h2_clob)
170
+
171
+ # Handle H2 specific clobs as strings.
172
+ def convert_type_proc(v)
173
+ if v.is_a?(Java::OrgH2Jdbc::JdbcClob)
174
+ H2_CLOB_METHOD
158
175
  else
159
- super(v)
176
+ super
160
177
  end
161
178
  end
162
179
 
180
+ # H2 expects hexadecimal strings for blob values
181
+ def literal_blob_append(sql, v)
182
+ sql << APOS << v.unpack(HSTAR).first << APOS
183
+ end
184
+
185
+ # H2 handles fractional seconds in timestamps, but not in times
186
+ def literal_sqltime(v)
187
+ v.strftime(TIME_FORMAT)
188
+ end
189
+
163
190
  def select_clause_methods
164
191
  SELECT_CLAUSE_METHODS
165
192
  end
@@ -0,0 +1,170 @@
1
+ Sequel.require 'adapters/jdbc/transactions'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset support for HSQLDB databases accessed via JDBC.
6
+ module HSQLDB
7
+ # Instance methods for HSQLDB Database objects accessed via JDBC.
8
+ module DatabaseMethods
9
+ include ::Sequel::JDBC::Transactions
10
+
11
+ # HSQLDB uses the :hsqldb database type.
12
+ def database_type
13
+ :hsqldb
14
+ end
15
+
16
+ # HSQLDB uses an IDENTITY sequence as the default value for primary
17
+ # key columns.
18
+ def serial_primary_key_options
19
+ {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
20
+ end
21
+
22
+ # The version of the database, as an integer (e.g 2.2.5 -> 20205)
23
+ def db_version
24
+ @db_version ||= begin
25
+ v = get{DATABASE_VERSION(){}}
26
+ if v =~ /(\d+)\.(\d+)\.(\d+)/
27
+ $1.to_i * 10000 + $2.to_i * 100 + $3.to_i
28
+ end
29
+ end
30
+ end
31
+
32
+ private
33
+
34
+ # HSQLDB specific SQL for renaming columns, and changing column types and/or nullity.
35
+ def alter_table_sql(table, op)
36
+ case op[:op]
37
+ when :rename_column
38
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} RENAME TO #{quote_identifier(op[:new_name])}"
39
+ when :set_column_type
40
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET DATA TYPE #{type_literal(op)}"
41
+ when :set_column_null
42
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET #{op[:null] ? 'NULL' : 'NOT NULL'}"
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ # Use IDENTITY() to get the last inserted id.
49
+ def last_insert_id(conn, opts={})
50
+ statement(conn) do |stmt|
51
+ sql = 'CALL IDENTITY()'
52
+ rs = log_yield(sql){stmt.executeQuery(sql)}
53
+ rs.next
54
+ rs.getInt(1)
55
+ end
56
+ end
57
+
58
+ # If an :identity option is present in the column, add the necessary IDENTITY SQL.
59
+ # It's possible to use an IDENTITY type, but that defaults the sequence to start
60
+ # at 0 instead of 1, and we don't want that.
61
+ def type_literal(column)
62
+ if column[:identity]
63
+ sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
64
+ if sw = column[:start_with]
65
+ sql << " (START WITH #{sw.to_i}"
66
+ sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
67
+ sql << ")"
68
+ end
69
+ sql
70
+ else
71
+ super
72
+ end
73
+ end
74
+ end
75
+
76
+ # Dataset class for HSQLDB datasets accessed via JDBC.
77
+ class Dataset < JDBC::Dataset
78
+ BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
79
+ BOOL_TRUE = 'TRUE'.freeze
80
+ BOOL_FALSE = 'FALSE'.freeze
81
+ # HSQLDB does support common table expressions, but the support is broken.
82
+ # CTEs operate more like temprorary tables or views, lasting longer than the duration of the expression.
83
+ # CTEs in earlier queries might take precedence over CTEs with the same name in later queries.
84
+ # Also, if any CTE is recursive, all CTEs must be recursive.
85
+ # If you want to use CTEs with HSQLDB, you'll have to manually modify the dataset to allow it.
86
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
87
+ SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
88
+ APOS = Dataset::APOS
89
+ HSTAR = "H*".freeze
90
+ BLOB_OPEN = "X'".freeze
91
+ BITCOMP_OPEN = "((0 - ".freeze
92
+ BITCOMP_CLOSE = ") - 1)".freeze
93
+ DEFAULT_FROM = " FROM (VALUES (0))".freeze
94
+ TIME_FORMAT = "'%H:%M:%S'".freeze
95
+
96
+ # Handle HSQLDB specific case insensitive LIKE and bitwise operator support.
97
+ def complex_expression_sql_append(sql, op, args)
98
+ case op
99
+ when :ILIKE, :"NOT ILIKE"
100
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
101
+ when :&, :|, :^
102
+ op = BITWISE_METHOD_MAP[op]
103
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
104
+ when :<<
105
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
106
+ when :>>
107
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
108
+ when :'B~'
109
+ sql << BITCOMP_OPEN
110
+ literal_append(sql, args.at(0))
111
+ sql << BITCOMP_CLOSE
112
+ else
113
+ super
114
+ end
115
+ end
116
+
117
+ # HSQLDB requires recursive CTEs to have column aliases.
118
+ def recursive_cte_requires_column_aliases?
119
+ true
120
+ end
121
+
122
+ # HSQLDB does not support IS TRUE.
123
+ def supports_is_true?
124
+ false
125
+ end
126
+
127
+ private
128
+
129
+ # Use string in hex format for blob data.
130
+ def literal_blob_append(sql, v)
131
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << APOS
132
+ end
133
+
134
+ # HSQLDB uses FALSE for false values.
135
+ def literal_false
136
+ BOOL_FALSE
137
+ end
138
+
139
+ # HSQLDB handles fractional seconds in timestamps, but not in times
140
+ def literal_sqltime(v)
141
+ v.strftime(TIME_FORMAT)
142
+ end
143
+
144
+ # HSQLDB uses TRUE for true values.
145
+ def literal_true
146
+ BOOL_TRUE
147
+ end
148
+
149
+ # HSQLDB does not support CTEs well enough for Sequel to enable support for them.
150
+ def select_clause_methods
151
+ SELECT_CLAUSE_METHODS
152
+ end
153
+
154
+ # Use a default FROM table if the dataset does not contain a FROM table.
155
+ def select_from_sql(sql)
156
+ if @opts[:from]
157
+ super
158
+ else
159
+ sql << DEFAULT_FROM
160
+ end
161
+ end
162
+
163
+ # Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
164
+ def select_with_sql_base
165
+ opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super
166
+ end
167
+ end
168
+ end
169
+ end
170
+ end
@@ -0,0 +1,26 @@
1
+ Sequel.require 'adapters/shared/informix'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for Informix specific
6
+ # support via JDBC.
7
+ module Informix
8
+ # Database instance methods for Informix databases accessed via JDBC.
9
+ module DatabaseMethods
10
+ include Sequel::Informix::DatabaseMethods
11
+
12
+ private
13
+
14
+ # TODO: implement
15
+ def last_insert_id(conn, opts={})
16
+ nil
17
+ end
18
+ end
19
+
20
+ # Dataset class for Informix datasets accessed via JDBC.
21
+ class Dataset < JDBC::Dataset
22
+ include Sequel::Informix::DatasetMethods
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ Sequel.require 'adapters/jdbc/mssql'
2
+
3
+ module Sequel
4
+ module JDBC
5
+ # Database and Dataset instance methods for JTDS specific
6
+ # support via JDBC.
7
+ module JTDS
8
+ # Database instance methods for JTDS databases accessed via JDBC.
9
+ module DatabaseMethods
10
+ include Sequel::JDBC::MSSQL::DatabaseMethods
11
+ end
12
+
13
+ # Dataset class for JTDS datasets accessed via JDBC.
14
+ class Dataset < JDBC::Dataset
15
+ include Sequel::MSSQL::DatasetMethods
16
+
17
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
18
+ def jtds_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
19
+ end
20
+
21
+ JTDS_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:jtds_clob)
22
+
23
+ # Handle CLOB types retrieved via JTDS.
24
+ def convert_type_proc(v)
25
+ if v.is_a?(Java::NetSourceforgeJtdsJdbc::ClobImpl)
26
+ JTDS_CLOB_METHOD
27
+ else
28
+ super
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end