5
5
module DatabaseMethods
6
extend Sequel::Database::ResetIdentifierMangling
6
8
TEMPORARY = 'GLOBAL TEMPORARY '.freeze
7
9
AUTOINCREMENT = ''.freeze
9
11
attr_accessor :autosequence
11
def create_sequence(name, opts={})
13
def create_sequence(name, opts=OPTS)
12
14
self << create_sequence_sql(name, opts)
38
40
m = output_identifier_meth
39
41
metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'TABLE').map{|r| m.call(r[:tname])}
43
45
m = output_identifier_meth
44
46
metadata_dataset.from(:tab).server(opts[:server]).select(:tname).filter(:tabtype => 'VIEW').map{|r| m.call(r[:tname])}
49
51
metadata_dataset.from(:tab).filter(:tname =>m.call(name), :tabtype => 'VIEW').count > 0
54
# Oracle supports deferrable constraints.
55
def supports_deferrable_constraints?
59
# DB2 supports transaction isolation levels.
60
def supports_transaction_isolation_levels?
54
66
# Handle Oracle specific ALTER TABLE SQL
87
def create_sequence_sql(name, opts={})
99
def create_sequence_sql(name, opts=OPTS)
88
100
"CREATE SEQUENCE #{quote_identifier(name)} start with #{opts [:start_with]||1} increment by #{opts[:increment_by]||1} nomaxvalue"
94
106
create_statements.each{|sql| execute_ddl(sql)}
97
def create_table_sql_list(name, generator, options={})
109
def create_table_sql_list(name, generator, options=OPTS)
98
110
statements = [create_table_sql(name, generator, options)]
99
111
drop_seq_statement = nil
100
112
generator.columns.each do |c|
120
132
[drop_seq_statement, statements]
123
def create_trigger_sql(table, name, definition, opts={})
135
def create_trigger_sql(table, name, definition, opts=OPTS)
124
136
events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
126
138
CREATE#{' OR REPLACE' if opts[:replace]} TRIGGER #{quote_identifier(name)}
146
DATABASE_ERROR_REGEXPS = {
147
/unique constraint .+ violated/ => UniqueConstraintViolation,
148
/integrity constraint .+ violated/ => ForeignKeyConstraintViolation,
149
/check constraint .+ violated/ => CheckConstraintViolation,
150
/cannot insert NULL into|cannot update .+ to NULL/ => NotNullConstraintViolation,
151
/can't serialize access for this transaction/ => SerializationFailure,
153
def database_error_regexps
154
DATABASE_ERROR_REGEXPS
134
157
def default_sequence_name(table, column)
135
158
"seq_#{table}_#{column}"
170
TRANSACTION_ISOLATION_LEVELS = {:uncommitted=>'READ COMMITTED'.freeze,
171
:committed=>'READ COMMITTED'.freeze,
172
:repeatable=>'SERIALIZABLE'.freeze,
173
:serializable=>'SERIALIZABLE'.freeze}
174
# Oracle doesn't support READ UNCOMMITTED OR REPEATABLE READ transaction
175
# isolation levels, so upgrade to the next highest level in those cases.
176
def set_transaction_isolation_sql(level)
177
"SET TRANSACTION ISOLATION LEVEL #{TRANSACTION_ISOLATION_LEVELS[level]}"
147
180
def sequence_for_table(table)
148
181
return nil unless autosequence
149
182
@primary_key_sequences.fetch(table) do |key|
191
# Oracle supports CREATE OR REPLACE VIEW.
192
def supports_create_or_replace_view?
158
196
# Oracle's integer/:number type handles larger values than
159
197
# most other databases's bigint types, so it should be
160
198
# safe to use for Bignum.
192
235
FROM = Dataset::FROM
193
236
BITCOMP_OPEN = "((0 - ".freeze
194
237
BITCOMP_CLOSE = ") - 1)".freeze
195
ILIKE_0 = "(UPPER(".freeze
196
ILIKE_1 = ") ".freeze
197
ILIKE_2 = ' UPPER('.freeze
198
ILIKE_3 = "))".freeze
200
NOT_LIKE = 'NOT LIKE'.freeze
201
238
TIMESTAMP_FORMAT = "TIMESTAMP '%Y-%m-%d %H:%M:%S%N %z'".freeze
202
239
TIMESTAMP_OFFSET_FORMAT = "%+03i:%02i".freeze
203
240
BOOL_FALSE = "'N'".freeze
205
242
HSTAR = "H*".freeze
206
243
DUAL = ['DUAL'.freeze].freeze
208
# Oracle needs to emulate bitwise operators and ILIKE/NOT ILIKE operators.
209
245
def complex_expression_sql_append(sql, op, args)
212
248
sql << complex_expression_arg_pairs(args){|a, b| "CAST(BITAND(#{literal(a)}, #{literal(b)}) AS INTEGER)"}
214
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} - #{complex_expression_sql(:&, [a, b])} + #{literal(b)})"}
250
sql << complex_expression_arg_pairs(args) do |a, b|
252
complex_expression_sql_append(s1, :&, [a, b])
253
"(#{literal(a)} - #{s1} + #{literal(b)})"
216
sql << complex_expression_arg_pairs(args){|*x| "(#{complex_expression_sql(:|, x)} - #{complex_expression_sql(:&, x)})"}
256
sql << complex_expression_arg_pairs(args) do |*x|
259
complex_expression_sql_append(s1, :|, x)
260
complex_expression_sql_append(s2, :&, x)
218
264
sql << BITCOMP_OPEN
219
265
literal_append(sql, args.at(0))
220
266
sql << BITCOMP_CLOSE
222
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal b}))"}
268
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} * power(2, #{literal(b)}))"}
224
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal b}))"}
270
sql << complex_expression_arg_pairs(args){|a, b| "(#{literal(a)} / power(2, #{literal(b)}))"}
226
272
sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
227
when :ILIKE, :'NOT ILIKE'
229
literal_append(sql, args.at(0))
231
sql << (op == :ILIKE ? LIKE : NOT_LIKE)
233
literal_append(sql, args.at(1))
289
# Oracle treats empty strings like NULL values, and doesn't support
290
# char_length, so make char_length use length with a nonempty string.
291
# Unfortunately, as Oracle treats the empty string as NULL, there is
292
# no way to get trim to return an empty string instead of nil if
293
# the string only contains spaces.
294
def emulated_function_sql_append(sql, f)
297
literal_append(sql, Sequel::SQL::Function.new(:length, Sequel.join([f.args.first, 'x'])) - 1)
251
303
# Oracle uses MINUS instead of EXCEPT, and doesn't support EXCEPT ALL
252
def except(dataset, opts={})
253
opts = {:all=>opts} unless opts.is_a?(Hash)
304
def except(dataset, opts=OPTS)
254
305
raise(Sequel::Error, "EXCEPT ALL not supported") if opts[:all]
255
306
compound_clone(:minus, dataset, opts)
350
401
# If this dataset is associated with a sequence, return the most recently
351
402
# inserted sequence value.
352
def execute_insert(sql, opts={})
403
def execute_insert(sql, opts=OPTS)
354
405
super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))