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
@@ -0,0 +1,260 @@
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
+ PRIMARY_KEY_INDEX_RE = /\Asql\d+\z/i.freeze
10
+
11
+ include ::Sequel::JDBC::Transactions
12
+
13
+ # Derby doesn't support casting integer to varchar, only integer to char,
14
+ # and char(254) appears to have the widest support (with char(255) failing).
15
+ # This does add a bunch of extra spaces at the end, but those will be trimmed
16
+ # elsewhere.
17
+ def cast_type_literal(type)
18
+ (type == String) ? 'CHAR(254)' : super
19
+ end
20
+
21
+ # Derby uses the :derby database type.
22
+ def database_type
23
+ :derby
24
+ end
25
+
26
+ # Derby uses an IDENTITY sequence for autoincrementing columns.
27
+ def serial_primary_key_options
28
+ {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
29
+ end
30
+
31
+ # The SVN version of the database.
32
+ def svn_version
33
+ @svn_version ||= begin
34
+ v = synchronize{|c| c.get_meta_data.get_database_product_version}
35
+ v =~ /\((\d+)\)\z/
36
+ $1.to_i
37
+ end
38
+ end
39
+
40
+ private
41
+
42
+ # Derby optimizes away Sequel's default check of SELECT NULL FROM table,
43
+ # so use a SELECT * FROM table there.
44
+ def _table_exists?(ds)
45
+ ds.first
46
+ end
47
+
48
+ # Derby-specific syntax for renaming columns and changing a columns type/nullity.
49
+ def alter_table_sql(table, op)
50
+ case op[:op]
51
+ when :rename_column
52
+ "RENAME COLUMN #{quote_schema_table(table)}.#{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
53
+ when :set_column_type
54
+ # Derby is very limited in changing a columns type, so adding a new column and then dropping the existing column is
55
+ # the best approach, as mentioned in the Derby documentation.
56
+ temp_name = :x_sequel_temp_column_x
57
+ [alter_table_sql(table, op.merge(:op=>:add_column, :name=>temp_name)),
58
+ from(table).update_sql(temp_name=>::Sequel::SQL::Cast.new(op[:name], op[:type])),
59
+ alter_table_sql(table, op.merge(:op=>:drop_column)),
60
+ alter_table_sql(table, op.merge(:op=>:rename_column, :name=>temp_name, :new_name=>op[:name]))]
61
+ when :set_column_null
62
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
63
+ else
64
+ super
65
+ end
66
+ end
67
+
68
+ # Derby doesn't allow specifying NULL for columns, only NOT NULL.
69
+ def column_definition_null_sql(sql, column)
70
+ sql << " NOT NULL" if column.fetch(:null, column[:allow_null]) == false
71
+ end
72
+
73
+ # Temporary table creation on Derby use DECLARE instead of CREATE.
74
+ def create_table_sql(name, generator, options)
75
+ if options[:temp]
76
+ "DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)} (#{column_list_sql(generator)}) NOT LOGGED"
77
+ else
78
+ super
79
+ end
80
+ end
81
+
82
+ # Use IDENTITY_VAL_LOCAL() to get the last inserted id.
83
+ def last_insert_id(conn, opts={})
84
+ statement(conn) do |stmt|
85
+ sql = 'SELECT IDENTITY_VAL_LOCAL() FROM sysibm.sysdummy1'
86
+ rs = log_yield(sql){stmt.executeQuery(sql)}
87
+ rs.next
88
+ rs.getInt(1)
89
+ end
90
+ end
91
+
92
+ # Derby uses RENAME TABLE syntax to rename tables.
93
+ def rename_table_sql(name, new_name)
94
+ "RENAME TABLE #{quote_schema_table(name)} TO #{quote_schema_table(new_name)}"
95
+ end
96
+
97
+ # Primary key indexes appear to be named sqlNNNN on Derby
98
+ def primary_key_index_re
99
+ PRIMARY_KEY_INDEX_RE
100
+ end
101
+
102
+ # If an :identity option is present in the column, add the necessary IDENTITY SQL.
103
+ def type_literal(column)
104
+ if column[:identity]
105
+ sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
106
+ if sw = column[:start_with]
107
+ sql << " (START WITH #{sw.to_i}"
108
+ sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
109
+ sql << ")"
110
+ end
111
+ sql
112
+ else
113
+ super
114
+ end
115
+ end
116
+ end
117
+
118
+ # Dataset class for Derby datasets accessed via JDBC.
119
+ class Dataset < JDBC::Dataset
120
+ PAREN_CLOSE = Dataset::PAREN_CLOSE
121
+ PAREN_OPEN = Dataset::PAREN_OPEN
122
+ OFFSET = Dataset::OFFSET
123
+ CAST_STRING_OPEN = "RTRIM(".freeze
124
+ BITCOMP_OPEN = "((0 - ".freeze
125
+ BITCOMP_CLOSE = ") - 1)".freeze
126
+ BLOB_OPEN = "CAST(X'".freeze
127
+ BLOB_CLOSE = "' AS BLOB)".freeze
128
+ HSTAR = "H*".freeze
129
+ TIME_FORMAT = "'%H:%M:%S'".freeze
130
+ DEFAULT_FROM = " FROM sysibm.sysdummy1".freeze
131
+ ROWS = " ROWS".freeze
132
+ FETCH_FIRST = " FETCH FIRST ".freeze
133
+ ROWS_ONLY = " ROWS ONLY".freeze
134
+ BOOL_TRUE = '(1 = 1)'.freeze
135
+ BOOL_FALSE = '(1 = 0)'.freeze
136
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
137
+
138
+ # Derby doesn't support an expression between CASE and WHEN,
139
+ # so emulate it by using an equality statement for all of the
140
+ # conditions.
141
+ def case_expression_sql_append(sql, ce)
142
+ if ce.expression?
143
+ e = ce.expression
144
+ case_expression_sql_append(sql, ::Sequel::SQL::CaseExpression.new(ce.conditions.map{|c, r| [::Sequel::SQL::BooleanExpression.new(:'=', e, c), r]}, ce.default))
145
+ else
146
+ super
147
+ end
148
+ end
149
+
150
+ # If the type is String, trim the extra spaces since CHAR is used instead
151
+ # of varchar. This can cause problems if you are casting a char/varchar to
152
+ # a string and the ending whitespace is important.
153
+ def cast_sql_append(sql, expr, type)
154
+ if type == String
155
+ sql << CAST_STRING_OPEN
156
+ super
157
+ sql << PAREN_CLOSE
158
+ else
159
+ super
160
+ end
161
+ end
162
+
163
+ # Handle Derby specific LIKE, extract, and some bitwise compliment support.
164
+ def complex_expression_sql_append(sql, op, args)
165
+ case op
166
+ when :ILIKE
167
+ super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
168
+ when :"NOT ILIKE"
169
+ super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
170
+ when :&, :|, :^, :<<, :>>
171
+ raise Error, "Derby doesn't support the #{op} operator"
172
+ when :'B~'
173
+ sql << BITCOMP_OPEN
174
+ literal_append(sql, args.at(0))
175
+ sql << BITCOMP_CLOSE
176
+ when :extract
177
+ sql << args.at(0).to_s << PAREN_OPEN
178
+ literal_append(sql, args.at(1))
179
+ sql << PAREN_CLOSE
180
+ else
181
+ super
182
+ end
183
+ end
184
+
185
+ # Derby supports GROUP BY ROLLUP (but not CUBE)
186
+ def supports_group_rollup?
187
+ true
188
+ end
189
+
190
+ # Derby does not support IS TRUE.
191
+ def supports_is_true?
192
+ false
193
+ end
194
+
195
+ # Derby does not support IN/NOT IN with multiple columns
196
+ def supports_multiple_column_in?
197
+ false
198
+ end
199
+
200
+ private
201
+
202
+ # Derby needs a hex string casted to BLOB for blobs.
203
+ def literal_blob_append(sql, v)
204
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << BLOB_CLOSE
205
+ end
206
+
207
+ # Derby needs the standard workaround to insert all default values into
208
+ # a table with more than one column.
209
+ def insert_supports_empty_values?
210
+ false
211
+ end
212
+
213
+ # Derby uses an expression yielding false for false values.
214
+ # Newer versions can use the FALSE literal, but the latest gem version cannot.
215
+ def literal_false
216
+ BOOL_FALSE
217
+ end
218
+
219
+ # Derby handles fractional seconds in timestamps, but not in times
220
+ def literal_sqltime(v)
221
+ v.strftime(TIME_FORMAT)
222
+ end
223
+
224
+ # Derby uses an expression yielding true for true values.
225
+ # Newer versions can use the TRUE literal, but the latest gem version cannot.
226
+ def literal_true
227
+ BOOL_TRUE
228
+ end
229
+
230
+ # Derby doesn't support common table expressions.
231
+ def select_clause_methods
232
+ SELECT_CLAUSE_METHODS
233
+ end
234
+
235
+ # Use a default FROM table if the dataset does not contain a FROM table.
236
+ def select_from_sql(sql)
237
+ if @opts[:from]
238
+ super
239
+ else
240
+ sql << DEFAULT_FROM
241
+ end
242
+ end
243
+
244
+ # Offset comes before limit in Derby
245
+ def select_limit_sql(sql)
246
+ if o = @opts[:offset]
247
+ sql << OFFSET
248
+ literal_append(sql, o)
249
+ sql << ROWS
250
+ end
251
+ if l = @opts[:limit]
252
+ sql << FETCH_FIRST
253
+ literal_append(sql, l)
254
+ sql << ROWS_ONLY
255
+ end
256
+ end
257
+ end
258
+ end
259
+ end
260
+ 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
@@ -75,7 +75,16 @@ module Sequel
75
75
  when :set_column_null
76
76
  "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET#{' NOT' unless op[:null]} NULL"
77
77
  when :set_column_type
78
- "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(op)}"
78
+ if sch = schema(table)
79
+ if cs = sch.each{|k, v| break v if k == op[:name]; nil}
80
+ cs = cs.dup
81
+ cs[:default] = cs[:ruby_default]
82
+ op = cs.merge!(op)
83
+ end
84
+ end
85
+ sql = "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{type_literal(op)}"
86
+ column_definition_order.each{|m| send(:"column_definition_#{m}_sql", sql, op)}
87
+ sql
79
88
  else
80
89
  super(table, op)
81
90
  end
@@ -90,7 +99,8 @@ module Sequel
90
99
  # Use IDENTITY() to get the last inserted id.
91
100
  def last_insert_id(conn, opts={})
92
101
  statement(conn) do |stmt|
93
- rs = stmt.executeQuery('SELECT IDENTITY();')
102
+ sql = 'SELECT IDENTITY();'
103
+ rs = log_yield(sql){stmt.executeQuery(sql)}
94
104
  rs.next
95
105
  rs.getInt(1)
96
106
  end
@@ -99,28 +109,41 @@ module Sequel
99
109
  def primary_key_index_re
100
110
  PRIMARY_KEY_INDEX_RE
101
111
  end
112
+
113
+ # Treat clob as string instead of blob
114
+ def schema_column_type(db_type)
115
+ db_type == 'clob' ? :string : super
116
+ end
102
117
  end
103
118
 
104
119
  # Dataset class for H2 datasets accessed via JDBC.
105
120
  class Dataset < JDBC::Dataset
106
- SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit')
121
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
107
122
  BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
123
+ APOS = Dataset::APOS
124
+ HSTAR = "H*".freeze
125
+ BITCOMP_OPEN = "((0 - ".freeze
126
+ BITCOMP_CLOSE = ") - 1)".freeze
127
+ ILIKE_PLACEHOLDER = "CAST(? AS VARCHAR_IGNORECASE)".freeze
128
+ TIME_FORMAT = "'%H:%M:%S'".freeze
108
129
 
109
- # Work around H2's lack of a case insensitive LIKE operator
110
- def complex_expression_sql(op, args)
130
+ # Emulate the case insensitive LIKE operator and the bitwise operators.
131
+ def complex_expression_sql_append(sql, op, args)
111
132
  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)])
133
+ when :ILIKE, :"NOT ILIKE"
134
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::PlaceholderLiteralString.new(ILIKE_PLACEHOLDER, [args.at(0)]), args.at(1)])
116
135
  when :&, :|, :^
117
- literal(SQL::Function.new(BITWISE_METHOD_MAP[op], *args))
136
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
118
137
  when :<<
119
- "(#{literal(args[0])} * POWER(2, #{literal(args[1])}))"
138
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
120
139
  when :>>
121
- "(#{literal(args[0])} / POWER(2, #{literal(args[1])}))"
140
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
141
+ when :'B~'
142
+ sql << BITCOMP_OPEN
143
+ literal_append(sql, args.at(0))
144
+ sql << BITCOMP_CLOSE
122
145
  else
123
- super(op, args)
146
+ super
124
147
  end
125
148
  end
126
149
 
@@ -145,21 +168,34 @@ module Sequel
145
168
  end
146
169
 
147
170
  private
148
-
149
- # H2 expects hexadecimal strings for blob values
150
- def literal_blob(v)
151
- literal_string v.unpack("H*").first
171
+
172
+ #JAVA_H2_CLOB = Java::OrgH2Jdbc::JdbcClob
173
+
174
+ class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
175
+ def h2_clob(v) v.getSubString(1, v.length) end
152
176
  end
153
-
154
- def convert_type(v)
155
- case v
156
- when Java::OrgH2Jdbc::JdbcClob
157
- convert_type(v.getSubString(1, v.length))
177
+
178
+ H2_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:h2_clob)
179
+
180
+ # Handle H2 specific clobs as strings.
181
+ def convert_type_proc(v)
182
+ if v.is_a?(Java::OrgH2Jdbc::JdbcClob)
183
+ H2_CLOB_METHOD
158
184
  else
159
- super(v)
185
+ super
160
186
  end
161
187
  end
162
188
 
189
+ # H2 expects hexadecimal strings for blob values
190
+ def literal_blob_append(sql, v)
191
+ sql << APOS << v.unpack(HSTAR).first << APOS
192
+ end
193
+
194
+ # H2 handles fractional seconds in timestamps, but not in times
195
+ def literal_sqltime(v)
196
+ v.strftime(TIME_FORMAT)
197
+ end
198
+
163
199
  def select_clause_methods
164
200
  SELECT_CLAUSE_METHODS
165
201
  end
@@ -0,0 +1,177 @@
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
+ PRIMARY_KEY_INDEX_RE = /\Asys_idx_sys_pk_/i.freeze
10
+
11
+ include ::Sequel::JDBC::Transactions
12
+
13
+ # HSQLDB uses the :hsqldb database type.
14
+ def database_type
15
+ :hsqldb
16
+ end
17
+
18
+ # HSQLDB uses an IDENTITY sequence as the default value for primary
19
+ # key columns.
20
+ def serial_primary_key_options
21
+ {:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
22
+ end
23
+
24
+ # The version of the database, as an integer (e.g 2.2.5 -> 20205)
25
+ def db_version
26
+ @db_version ||= begin
27
+ v = get{DATABASE_VERSION(){}}
28
+ if v =~ /(\d+)\.(\d+)\.(\d+)/
29
+ $1.to_i * 10000 + $2.to_i * 100 + $3.to_i
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ # HSQLDB specific SQL for renaming columns, and changing column types and/or nullity.
37
+ def alter_table_sql(table, op)
38
+ case op[:op]
39
+ when :rename_column
40
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} RENAME TO #{quote_identifier(op[:new_name])}"
41
+ when :set_column_type
42
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET DATA TYPE #{type_literal(op)}"
43
+ when :set_column_null
44
+ "ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} SET #{op[:null] ? 'NULL' : 'NOT NULL'}"
45
+ else
46
+ super
47
+ end
48
+ end
49
+
50
+ # Use IDENTITY() to get the last inserted id.
51
+ def last_insert_id(conn, opts={})
52
+ statement(conn) do |stmt|
53
+ sql = 'CALL IDENTITY()'
54
+ rs = log_yield(sql){stmt.executeQuery(sql)}
55
+ rs.next
56
+ rs.getInt(1)
57
+ end
58
+ end
59
+
60
+ # Primary key indexes appear to start with sys_idx_sys_pk_ on HSQLDB
61
+ def primary_key_index_re
62
+ PRIMARY_KEY_INDEX_RE
63
+ end
64
+
65
+ # If an :identity option is present in the column, add the necessary IDENTITY SQL.
66
+ # It's possible to use an IDENTITY type, but that defaults the sequence to start
67
+ # at 0 instead of 1, and we don't want that.
68
+ def type_literal(column)
69
+ if column[:identity]
70
+ sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
71
+ if sw = column[:start_with]
72
+ sql << " (START WITH #{sw.to_i}"
73
+ sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
74
+ sql << ")"
75
+ end
76
+ sql
77
+ else
78
+ super
79
+ end
80
+ end
81
+ end
82
+
83
+ # Dataset class for HSQLDB datasets accessed via JDBC.
84
+ class Dataset < JDBC::Dataset
85
+ BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
86
+ BOOL_TRUE = 'TRUE'.freeze
87
+ BOOL_FALSE = 'FALSE'.freeze
88
+ # HSQLDB does support common table expressions, but the support is broken.
89
+ # CTEs operate more like temprorary tables or views, lasting longer than the duration of the expression.
90
+ # CTEs in earlier queries might take precedence over CTEs with the same name in later queries.
91
+ # Also, if any CTE is recursive, all CTEs must be recursive.
92
+ # If you want to use CTEs with HSQLDB, you'll have to manually modify the dataset to allow it.
93
+ SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
94
+ SQL_WITH_RECURSIVE = "WITH RECURSIVE ".freeze
95
+ APOS = Dataset::APOS
96
+ HSTAR = "H*".freeze
97
+ BLOB_OPEN = "X'".freeze
98
+ BITCOMP_OPEN = "((0 - ".freeze
99
+ BITCOMP_CLOSE = ") - 1)".freeze
100
+ DEFAULT_FROM = " FROM (VALUES (0))".freeze
101
+ TIME_FORMAT = "'%H:%M:%S'".freeze
102
+
103
+ # Handle HSQLDB specific case insensitive LIKE and bitwise operator support.
104
+ def complex_expression_sql_append(sql, op, args)
105
+ case op
106
+ when :ILIKE, :"NOT ILIKE"
107
+ super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
108
+ when :&, :|, :^
109
+ op = BITWISE_METHOD_MAP[op]
110
+ sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
111
+ when :<<
112
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
113
+ when :>>
114
+ sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
115
+ when :'B~'
116
+ sql << BITCOMP_OPEN
117
+ literal_append(sql, args.at(0))
118
+ sql << BITCOMP_CLOSE
119
+ else
120
+ super
121
+ end
122
+ end
123
+
124
+ # HSQLDB requires recursive CTEs to have column aliases.
125
+ def recursive_cte_requires_column_aliases?
126
+ true
127
+ end
128
+
129
+ # HSQLDB does not support IS TRUE.
130
+ def supports_is_true?
131
+ false
132
+ end
133
+
134
+ private
135
+
136
+ # Use string in hex format for blob data.
137
+ def literal_blob_append(sql, v)
138
+ sql << BLOB_OPEN << v.unpack(HSTAR).first << APOS
139
+ end
140
+
141
+ # HSQLDB uses FALSE for false values.
142
+ def literal_false
143
+ BOOL_FALSE
144
+ end
145
+
146
+ # HSQLDB handles fractional seconds in timestamps, but not in times
147
+ def literal_sqltime(v)
148
+ v.strftime(TIME_FORMAT)
149
+ end
150
+
151
+ # HSQLDB uses TRUE for true values.
152
+ def literal_true
153
+ BOOL_TRUE
154
+ end
155
+
156
+ # HSQLDB does not support CTEs well enough for Sequel to enable support for them.
157
+ def select_clause_methods
158
+ SELECT_CLAUSE_METHODS
159
+ end
160
+
161
+ # Use a default FROM table if the dataset does not contain a FROM table.
162
+ def select_from_sql(sql)
163
+ if @opts[:from]
164
+ super
165
+ else
166
+ sql << DEFAULT_FROM
167
+ end
168
+ end
169
+
170
+ # Use WITH RECURSIVE instead of WITH if any of the CTEs is recursive
171
+ def select_with_sql_base
172
+ opts[:with].any?{|w| w[:recursive]} ? SQL_WITH_RECURSIVE : super
173
+ end
174
+ end
175
+ end
176
+ end
177
+ 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