sequel 3.29.0 → 3.30.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +35 -3
- data/Rakefile +2 -1
- data/doc/association_basics.rdoc +11 -0
- data/doc/opening_databases.rdoc +2 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/testing.rdoc +17 -3
- data/lib/sequel/adapters/amalgalite.rb +2 -2
- data/lib/sequel/adapters/do/mysql.rb +5 -2
- data/lib/sequel/adapters/ibmdb.rb +2 -2
- data/lib/sequel/adapters/jdbc.rb +126 -43
- data/lib/sequel/adapters/jdbc/as400.rb +11 -3
- data/lib/sequel/adapters/jdbc/db2.rb +2 -1
- data/lib/sequel/adapters/jdbc/derby.rb +44 -19
- data/lib/sequel/adapters/jdbc/h2.rb +32 -19
- data/lib/sequel/adapters/jdbc/hsqldb.rb +21 -17
- data/lib/sequel/adapters/jdbc/jtds.rb +9 -4
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -1
- data/lib/sequel/adapters/jdbc/mysql.rb +2 -1
- data/lib/sequel/adapters/jdbc/oracle.rb +21 -7
- data/lib/sequel/adapters/jdbc/postgresql.rb +3 -2
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -1
- data/lib/sequel/adapters/jdbc/sqlserver.rb +48 -18
- data/lib/sequel/adapters/mock.rb +2 -1
- data/lib/sequel/adapters/mysql.rb +4 -2
- data/lib/sequel/adapters/mysql2.rb +2 -2
- data/lib/sequel/adapters/odbc/mssql.rb +1 -1
- data/lib/sequel/adapters/openbase.rb +1 -1
- data/lib/sequel/adapters/oracle.rb +6 -6
- data/lib/sequel/adapters/postgres.rb +25 -12
- data/lib/sequel/adapters/shared/access.rb +14 -6
- data/lib/sequel/adapters/shared/db2.rb +36 -13
- data/lib/sequel/adapters/shared/firebird.rb +12 -5
- data/lib/sequel/adapters/shared/informix.rb +11 -3
- data/lib/sequel/adapters/shared/mssql.rb +94 -47
- data/lib/sequel/adapters/shared/mysql.rb +107 -49
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +2 -2
- data/lib/sequel/adapters/shared/oracle.rb +54 -27
- data/lib/sequel/adapters/shared/postgres.rb +65 -26
- data/lib/sequel/adapters/shared/progress.rb +4 -1
- data/lib/sequel/adapters/shared/sqlite.rb +36 -20
- data/lib/sequel/adapters/sqlite.rb +2 -3
- data/lib/sequel/adapters/swift/mysql.rb +3 -2
- data/lib/sequel/adapters/swift/sqlite.rb +2 -2
- data/lib/sequel/adapters/tinytds.rb +14 -8
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +7 -4
- data/lib/sequel/database/misc.rb +6 -2
- data/lib/sequel/dataset/graph.rb +33 -7
- data/lib/sequel/dataset/prepared_statements.rb +19 -5
- data/lib/sequel/dataset/sql.rb +611 -201
- data/lib/sequel/model/associations.rb +12 -5
- data/lib/sequel/model/base.rb +20 -5
- data/lib/sequel/plugins/sharding.rb +9 -29
- data/lib/sequel/sql.rb +2 -1
- data/lib/sequel/timezones.rb +14 -4
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/mysql_spec.rb +10 -0
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/core/core_sql_spec.rb +3 -1
- data/spec/core/database_spec.rb +42 -0
- data/spec/core/dataset_spec.rb +10 -3
- data/spec/core/mock_adapter_spec.rb +4 -0
- data/spec/core/object_graph_spec.rb +38 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +35 -39
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +30 -82
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +33 -103
- data/spec/extensions/instance_filters_spec.rb +10 -21
- data/spec/extensions/instance_hooks_spec.rb +6 -24
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +135 -277
- data/spec/extensions/migration_spec.rb +18 -15
- data/spec/extensions/named_timezones_spec.rb +1 -1
- data/spec/extensions/nested_attributes_spec.rb +97 -92
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +22 -37
- data/spec/extensions/prepared_statements_safe_spec.rb +9 -27
- data/spec/extensions/prepared_statements_spec.rb +11 -30
- data/spec/extensions/prepared_statements_with_pk_spec.rb +6 -13
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +3 -6
- data/spec/extensions/serialization_spec.rb +20 -32
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +14 -36
- data/spec/extensions/spec_helper.rb +10 -64
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +1 -2
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/integration/dataset_test.rb +16 -4
- data/spec/integration/prepared_statement_test.rb +4 -2
- data/spec/model/eager_loading_spec.rb +16 -0
- data/spec/model/model_spec.rb +15 -1
- data/spec/model/record_spec.rb +60 -0
- metadata +23 -40
@@ -39,6 +39,9 @@ module Sequel
|
|
39
39
|
# Dataset class for AS400 datasets accessed via JDBC.
|
40
40
|
class Dataset < JDBC::Dataset
|
41
41
|
WILDCARD = Sequel::LiteralString.new('*').freeze
|
42
|
+
FETCH_FIRST_ROW_ONLY = " FETCH FIRST ROW ONLY".freeze
|
43
|
+
FETCH_FIRST = " FETCH FIRST ".freeze
|
44
|
+
ROWS_ONLY = " ROWS ONLY".freeze
|
42
45
|
|
43
46
|
# AS400 needs to use a couple of subselects for queries with offsets.
|
44
47
|
def select_sql
|
@@ -60,9 +63,14 @@ module Sequel
|
|
60
63
|
|
61
64
|
# Modify the sql to limit the number of rows returned
|
62
65
|
def select_limit_sql(sql)
|
63
|
-
if @opts[:limit]
|
64
|
-
|
65
|
-
|
66
|
+
if l = @opts[:limit]
|
67
|
+
if l == 1
|
68
|
+
sql << FETCH_FIRST_ROW_ONLY
|
69
|
+
elsif l > 1
|
70
|
+
sql << FETCH_FIRST
|
71
|
+
literal_append(sql, l)
|
72
|
+
sql << ROWS_ONLY
|
73
|
+
end
|
66
74
|
end
|
67
75
|
end
|
68
76
|
|
@@ -18,6 +18,7 @@ module Sequel
|
|
18
18
|
module DatabaseMethods
|
19
19
|
include Sequel::DB2::DatabaseMethods
|
20
20
|
include Sequel::JDBC::Transactions
|
21
|
+
IDENTITY_VAL_LOCAL = "SELECT IDENTITY_VAL_LOCAL() FROM SYSIBM.SYSDUMMY1".freeze
|
21
22
|
|
22
23
|
%w'schema_parse_table tables views indexes'.each do |s|
|
23
24
|
class_eval("def #{s}(*a) jdbc_#{s}(*a) end", __FILE__, __LINE__)
|
@@ -27,7 +28,7 @@ module Sequel
|
|
27
28
|
|
28
29
|
def last_insert_id(conn, opts={})
|
29
30
|
statement(conn) do |stmt|
|
30
|
-
sql =
|
31
|
+
sql = IDENTITY_VAL_LOCAL
|
31
32
|
rs = log_yield(sql){stmt.executeQuery(sql)}
|
32
33
|
rs.next
|
33
34
|
rs.getInt(1)
|
@@ -104,17 +104,31 @@ module Sequel
|
|
104
104
|
|
105
105
|
# Dataset class for Derby datasets accessed via JDBC.
|
106
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
|
107
121
|
BOOL_TRUE = '(1 = 1)'.freeze
|
108
122
|
BOOL_FALSE = '(1 = 0)'.freeze
|
109
|
-
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit lock')
|
123
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
|
110
124
|
|
111
125
|
# Derby doesn't support an expression between CASE and WHEN,
|
112
126
|
# so emulate it by using an equality statement for all of the
|
113
127
|
# conditions.
|
114
|
-
def
|
128
|
+
def case_expression_sql_append(sql, ce)
|
115
129
|
if ce.expression?
|
116
130
|
e = ce.expression
|
117
|
-
|
131
|
+
case_expression_sql_append(sql, ::Sequel::SQL::CaseExpression.new(ce.conditions.map{|c, r| [::Sequel::SQL::BooleanExpression.new(:'=', e, c), r]}, ce.default))
|
118
132
|
else
|
119
133
|
super
|
120
134
|
end
|
@@ -123,27 +137,33 @@ module Sequel
|
|
123
137
|
# If the type is String, trim the extra spaces since CHAR is used instead
|
124
138
|
# of varchar. This can cause problems if you are casting a char/varchar to
|
125
139
|
# a string and the ending whitespace is important.
|
126
|
-
def
|
140
|
+
def cast_sql_append(sql, expr, type)
|
127
141
|
if type == String
|
128
|
-
|
142
|
+
sql << CAST_STRING_OPEN
|
143
|
+
super
|
144
|
+
sql << PAREN_CLOSE
|
129
145
|
else
|
130
146
|
super
|
131
147
|
end
|
132
148
|
end
|
133
149
|
|
134
150
|
# Handle Derby specific LIKE, extract, and some bitwise compliment support.
|
135
|
-
def
|
151
|
+
def complex_expression_sql_append(sql, op, args)
|
136
152
|
case op
|
137
153
|
when :ILIKE
|
138
|
-
super(:LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))
|
154
|
+
super(sql, :LIKE, [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
|
139
155
|
when :"NOT ILIKE"
|
140
|
-
super(:"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))
|
156
|
+
super(sql, :"NOT LIKE", [SQL::Function.new(:upper, args.at(0)), SQL::Function.new(:upper, args.at(1))])
|
141
157
|
when :&, :|, :^, :<<, :>>
|
142
158
|
raise Error, "Derby doesn't support the #{op} operator"
|
143
159
|
when :'B~'
|
144
|
-
|
160
|
+
sql << BITCOMP_OPEN
|
161
|
+
literal_append(sql, args.at(0))
|
162
|
+
sql << BITCOMP_CLOSE
|
145
163
|
when :extract
|
146
|
-
|
164
|
+
sql << args.at(0).to_s << PAREN_OPEN
|
165
|
+
literal_append(sql, args.at(1))
|
166
|
+
sql << PAREN_CLOSE
|
147
167
|
else
|
148
168
|
super
|
149
169
|
end
|
@@ -162,11 +182,8 @@ module Sequel
|
|
162
182
|
private
|
163
183
|
|
164
184
|
# Derby needs a hex string casted to BLOB for blobs.
|
165
|
-
def
|
166
|
-
|
167
|
-
v.each_byte{|x| blob << sprintf('%02x', x)}
|
168
|
-
blob << "' AS BLOB)"
|
169
|
-
blob
|
185
|
+
def literal_blob_append(sql, v)
|
186
|
+
sql << BLOB_OPEN << v.unpack(HSTAR).first << BLOB_CLOSE
|
170
187
|
end
|
171
188
|
|
172
189
|
# Derby needs the standard workaround to insert all default values into
|
@@ -183,7 +200,7 @@ module Sequel
|
|
183
200
|
|
184
201
|
# Derby handles fractional seconds in timestamps, but not in times
|
185
202
|
def literal_sqltime(v)
|
186
|
-
v.strftime(
|
203
|
+
v.strftime(TIME_FORMAT)
|
187
204
|
end
|
188
205
|
|
189
206
|
# Derby uses an expression yielding true for true values.
|
@@ -202,14 +219,22 @@ module Sequel
|
|
202
219
|
if @opts[:from]
|
203
220
|
super
|
204
221
|
else
|
205
|
-
sql <<
|
222
|
+
sql << DEFAULT_FROM
|
206
223
|
end
|
207
224
|
end
|
208
225
|
|
209
226
|
# Offset comes before limit in Derby
|
210
227
|
def select_limit_sql(sql)
|
211
|
-
|
212
|
-
|
228
|
+
if o = @opts[:offset]
|
229
|
+
sql << OFFSET
|
230
|
+
literal_append(sql, o)
|
231
|
+
sql << ROWS
|
232
|
+
end
|
233
|
+
if l = @opts[:limit]
|
234
|
+
sql << FETCH_FIRST
|
235
|
+
literal_append(sql, l)
|
236
|
+
sql << ROWS_ONLY
|
237
|
+
end
|
213
238
|
end
|
214
239
|
end
|
215
240
|
end
|
@@ -104,26 +104,32 @@ module Sequel
|
|
104
104
|
|
105
105
|
# Dataset class for H2 datasets accessed via JDBC.
|
106
106
|
class Dataset < JDBC::Dataset
|
107
|
-
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'distinct columns from join where group having compounds order limit')
|
107
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit')
|
108
108
|
BITWISE_METHOD_MAP = {:& =>:BITAND, :| => :BITOR, :^ => :BITXOR}
|
109
|
+
APOS = Dataset::APOS
|
110
|
+
HSTAR = "H*".freeze
|
111
|
+
BITCOMP_OPEN = "((0 - ".freeze
|
112
|
+
BITCOMP_CLOSE = ") - 1)".freeze
|
113
|
+
ILIKE_PLACEHOLDER = "CAST(? AS VARCHAR_IGNORECASE)".freeze
|
114
|
+
TIME_FORMAT = "'%H:%M:%S'".freeze
|
109
115
|
|
110
116
|
# Emulate the case insensitive LIKE operator and the bitwise operators.
|
111
|
-
def
|
117
|
+
def complex_expression_sql_append(sql, op, args)
|
112
118
|
case op
|
113
|
-
when :ILIKE
|
114
|
-
super(:LIKE, [SQL::PlaceholderLiteralString.new(
|
115
|
-
when :"NOT ILIKE"
|
116
|
-
super(:"NOT LIKE", [SQL::PlaceholderLiteralString.new("CAST(? AS VARCHAR_IGNORECASE)", [args.at(0)]), args.at(1)])
|
119
|
+
when :ILIKE, :"NOT ILIKE"
|
120
|
+
super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), [SQL::PlaceholderLiteralString.new(ILIKE_PLACEHOLDER, [args.at(0)]), args.at(1)])
|
117
121
|
when :&, :|, :^
|
118
|
-
complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
|
122
|
+
sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(BITWISE_METHOD_MAP[op], a, b))}
|
119
123
|
when :<<
|
120
|
-
complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
|
124
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
|
121
125
|
when :>>
|
122
|
-
complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
|
126
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
|
123
127
|
when :'B~'
|
124
|
-
|
128
|
+
sql << BITCOMP_OPEN
|
129
|
+
literal_append(sql, args.at(0))
|
130
|
+
sql << BITCOMP_CLOSE
|
125
131
|
else
|
126
|
-
super
|
132
|
+
super
|
127
133
|
end
|
128
134
|
end
|
129
135
|
|
@@ -148,25 +154,32 @@ module Sequel
|
|
148
154
|
end
|
149
155
|
|
150
156
|
private
|
157
|
+
|
158
|
+
#JAVA_H2_CLOB = Java::OrgH2Jdbc::JdbcClob
|
159
|
+
|
160
|
+
class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
|
161
|
+
def h2_clob(v) Sequel::SQL::Blob.new(v.getSubString(1, v.length)) end
|
162
|
+
end
|
163
|
+
|
164
|
+
H2_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:h2_clob)
|
151
165
|
|
152
166
|
# Handle H2 specific clobs as strings.
|
153
|
-
def
|
154
|
-
|
155
|
-
|
156
|
-
convert_type(v.getSubString(1, v.length))
|
167
|
+
def convert_type_proc(v)
|
168
|
+
if v.is_a?(Java::OrgH2Jdbc::JdbcClob)
|
169
|
+
H2_CLOB_METHOD
|
157
170
|
else
|
158
|
-
super
|
171
|
+
super
|
159
172
|
end
|
160
173
|
end
|
161
174
|
|
162
175
|
# H2 expects hexadecimal strings for blob values
|
163
|
-
def
|
164
|
-
|
176
|
+
def literal_blob_append(sql, v)
|
177
|
+
sql << APOS << v.unpack(HSTAR).first << APOS
|
165
178
|
end
|
166
179
|
|
167
180
|
# H2 handles fractional seconds in timestamps, but not in times
|
168
181
|
def literal_sqltime(v)
|
169
|
-
v.strftime(
|
182
|
+
v.strftime(TIME_FORMAT)
|
170
183
|
end
|
171
184
|
|
172
185
|
def select_clause_methods
|
@@ -83,25 +83,32 @@ module Sequel
|
|
83
83
|
# CTEs in earlier queries might take precedence over CTEs with the same name in later queries.
|
84
84
|
# Also, if any CTE is recursive, all CTEs must be recursive.
|
85
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'distinct columns from join where group having compounds order limit lock')
|
86
|
+
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
|
87
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
|
88
95
|
|
89
96
|
# Handle HSQLDB specific case insensitive LIKE and bitwise operator support.
|
90
|
-
def
|
97
|
+
def complex_expression_sql_append(sql, op, args)
|
91
98
|
case op
|
92
|
-
when :ILIKE
|
93
|
-
super(:LIKE, [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
|
94
|
-
when :"NOT ILIKE"
|
95
|
-
super(:"NOT LIKE", [SQL::Function.new(:ucase, args.at(0)), SQL::Function.new(:ucase, args.at(1)) ])
|
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)) ])
|
96
101
|
when :&, :|, :^
|
97
102
|
op = BITWISE_METHOD_MAP[op]
|
98
|
-
complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
|
103
|
+
sql << complex_expression_arg_pairs(args){|a, b| literal(SQL::Function.new(op, a, b))}
|
99
104
|
when :<<
|
100
|
-
complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
|
105
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * POWER(2, #{literal(b)}))"}
|
101
106
|
when :>>
|
102
|
-
complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
|
107
|
+
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / POWER(2, #{literal(b)}))"}
|
103
108
|
when :'B~'
|
104
|
-
|
109
|
+
sql << BITCOMP_OPEN
|
110
|
+
literal_append(sql, args.at(0))
|
111
|
+
sql << BITCOMP_CLOSE
|
105
112
|
else
|
106
113
|
super
|
107
114
|
end
|
@@ -120,11 +127,8 @@ module Sequel
|
|
120
127
|
private
|
121
128
|
|
122
129
|
# Use string in hex format for blob data.
|
123
|
-
def
|
124
|
-
|
125
|
-
v.each_byte{|x| blob << sprintf('%02x', x)}
|
126
|
-
blob << "'"
|
127
|
-
blob
|
130
|
+
def literal_blob_append(sql, v)
|
131
|
+
sql << BLOB_OPEN << v.unpack(HSTAR).first << APOS
|
128
132
|
end
|
129
133
|
|
130
134
|
# HSQLDB uses FALSE for false values.
|
@@ -134,7 +138,7 @@ module Sequel
|
|
134
138
|
|
135
139
|
# HSQLDB handles fractional seconds in timestamps, but not in times
|
136
140
|
def literal_sqltime(v)
|
137
|
-
v.strftime(
|
141
|
+
v.strftime(TIME_FORMAT)
|
138
142
|
end
|
139
143
|
|
140
144
|
# HSQLDB uses TRUE for true values.
|
@@ -152,7 +156,7 @@ module Sequel
|
|
152
156
|
if @opts[:from]
|
153
157
|
super
|
154
158
|
else
|
155
|
-
sql <<
|
159
|
+
sql << DEFAULT_FROM
|
156
160
|
end
|
157
161
|
end
|
158
162
|
|
@@ -14,11 +14,16 @@ module Sequel
|
|
14
14
|
class Dataset < JDBC::Dataset
|
15
15
|
include Sequel::MSSQL::DatasetMethods
|
16
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
|
+
|
17
23
|
# Handle CLOB types retrieved via JTDS.
|
18
|
-
def
|
19
|
-
|
20
|
-
|
21
|
-
convert_type(v.getSubString(1, v.length))
|
24
|
+
def convert_type_proc(v)
|
25
|
+
if v.is_a?(Java::NetSourceforgeJtdsJdbc::ClobImpl)
|
26
|
+
JTDS_CLOB_METHOD
|
22
27
|
else
|
23
28
|
super
|
24
29
|
end
|
@@ -13,6 +13,8 @@ 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
|
|
@@ -21,7 +23,7 @@ module Sequel
|
|
21
23
|
# Get the last inserted id using SCOPE_IDENTITY().
|
22
24
|
def last_insert_id(conn, opts={})
|
23
25
|
statement(conn) do |stmt|
|
24
|
-
sql = opts[:prepared] ?
|
26
|
+
sql = opts[:prepared] ? ATAT_IDENTITY : SCOPE_IDENTITY
|
25
27
|
rs = log_yield(sql){stmt.executeQuery(sql)}
|
26
28
|
rs.next
|
27
29
|
rs.getInt(1)
|
@@ -8,6 +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
|
+
LAST_INSERT_ID = 'SELECT LAST_INSERT_ID()'.freeze
|
11
12
|
|
12
13
|
private
|
13
14
|
|
@@ -34,7 +35,7 @@ module Sequel
|
|
34
35
|
end
|
35
36
|
else
|
36
37
|
statement(conn) do |stmt|
|
37
|
-
rs = stmt.executeQuery(
|
38
|
+
rs = stmt.executeQuery(LAST_INSERT_ID)
|
38
39
|
rs.next
|
39
40
|
rs.getInt(1)
|
40
41
|
end
|
@@ -67,21 +67,35 @@ module Sequel
|
|
67
67
|
|
68
68
|
private
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
70
|
+
JAVA_BIG_DECIMAL = ::Sequel::JDBC::Dataset::JAVA_BIG_DECIMAL
|
71
|
+
|
72
|
+
class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
|
73
|
+
def oracle_decimal(v)
|
73
74
|
if v.scale == 0
|
74
75
|
i = v.long_value
|
75
|
-
if v.equals(
|
76
|
+
if v.equals(JAVA_BIG_DECIMAL.new(i))
|
76
77
|
i
|
77
78
|
else
|
78
|
-
|
79
|
+
decimal(v)
|
79
80
|
end
|
80
81
|
else
|
81
|
-
|
82
|
+
decimal(v)
|
82
83
|
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
ORACLE_DECIMAL_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:oracle_decimal)
|
88
|
+
|
89
|
+
def convert_type_oracle_timestamp(v)
|
90
|
+
db.to_application_timestamp(v.to_string)
|
91
|
+
end
|
92
|
+
|
93
|
+
def convert_type_proc(v)
|
94
|
+
case v
|
95
|
+
when JAVA_BIG_DECIMAL
|
96
|
+
ORACLE_DECIMAL_METHOD
|
83
97
|
when Java::OracleSql::TIMESTAMP
|
84
|
-
|
98
|
+
method(:convert_type_oracle_timestamp)
|
85
99
|
else
|
86
100
|
super
|
87
101
|
end
|
@@ -73,6 +73,7 @@ module Sequel
|
|
73
73
|
# Dataset subclass used for datasets that connect to PostgreSQL via JDBC.
|
74
74
|
class Dataset < JDBC::Dataset
|
75
75
|
include Sequel::Postgres::DatasetMethods
|
76
|
+
APOS = Dataset::APOS
|
76
77
|
|
77
78
|
# Add the shared PostgreSQL prepared statement methods
|
78
79
|
def prepare(*args)
|
@@ -82,8 +83,8 @@ module Sequel
|
|
82
83
|
end
|
83
84
|
|
84
85
|
# Literalize strings similar to the native postgres adapter
|
85
|
-
def
|
86
|
-
db.synchronize{|c|
|
86
|
+
def literal_string_append(sql, v)
|
87
|
+
sql << APOS << db.synchronize{|c| c.escape_string(v)} << APOS
|
87
88
|
end
|
88
89
|
end
|
89
90
|
end
|
@@ -7,13 +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
|
+
LAST_INSERT_ROWID = 'SELECT last_insert_rowid()'.freeze
|
10
11
|
|
11
12
|
private
|
12
13
|
|
13
14
|
# Use last_insert_rowid() to get the last inserted id.
|
14
15
|
def last_insert_id(conn, opts={})
|
15
16
|
statement(conn) do |stmt|
|
16
|
-
rs = stmt.executeQuery(
|
17
|
+
rs = stmt.executeQuery(LAST_INSERT_ROWID)
|
17
18
|
rs.next
|
18
19
|
rs.getInt(1)
|
19
20
|
end
|