~ubuntu-branches/ubuntu/vivid/ruby-sequel/vivid

« back to all changes in this revision

Viewing changes to lib/sequel/adapters/shared/oracle.rb

  • Committer: Package Import Robot
  • Author(s): Dmitry Borodaenko, Dmitry Borodaenko, Cédric Boutillier
  • Date: 2013-08-10 18:38:17 UTC
  • mfrom: (1.1.8)
  • Revision ID: package-import@ubuntu.com-20130810183817-iqanz804j32i5myi
Tags: 4.1.1-1
[ Dmitry Borodaenko ]
* New upstream release.
* Standards-Version upgraded to 3.9.4 (no changes).
* Added Build-Depend on ruby-sqlite3.

[ Cédric Boutillier ]
* debian/control: remove obsolete DM-Upload-Allowed flag.
* use canonical URI in Vcs-* fields.
* debian/copyright: use DEP5 copyright-format/1.0 official URL for Format
  field.
* Update debian/watch. Thanks Bart Martens.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
module Sequel
4
4
  module Oracle
5
5
    module DatabaseMethods
 
6
      extend Sequel::Database::ResetIdentifierMangling
 
7
 
6
8
      TEMPORARY = 'GLOBAL TEMPORARY '.freeze
7
9
      AUTOINCREMENT = ''.freeze
8
10
 
9
11
      attr_accessor :autosequence
10
12
 
11
 
      def create_sequence(name, opts={})
 
13
      def create_sequence(name, opts=OPTS)
12
14
        self << create_sequence_sql(name, opts)
13
15
      end
14
16
 
34
36
        false
35
37
      end
36
38
 
37
 
      def tables(opts={})
 
39
      def tables(opts=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])}
40
42
      end
41
43
 
42
 
      def views(opts={}) 
 
44
      def views(opts=OPTS) 
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])}
45
47
      end 
49
51
        metadata_dataset.from(:tab).filter(:tname =>m.call(name), :tabtype => 'VIEW').count > 0 
50
52
      end 
51
53
 
 
54
      # Oracle supports deferrable constraints.
 
55
      def supports_deferrable_constraints?
 
56
        true
 
57
      end
 
58
 
 
59
      # DB2 supports transaction isolation levels.
 
60
      def supports_transaction_isolation_levels?
 
61
        true
 
62
      end
 
63
 
52
64
      private
53
65
 
54
66
      # Handle Oracle specific ALTER TABLE SQL
84
96
        AUTOINCREMENT
85
97
      end
86
98
 
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"
89
101
      end
90
102
 
94
106
        create_statements.each{|sql| execute_ddl(sql)}
95
107
      end
96
108
 
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]
121
133
      end
122
134
 
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]
125
137
        sql = <<-end_sql
126
138
          CREATE#{' OR REPLACE' if opts[:replace]} TRIGGER #{quote_identifier(name)}
131
143
        sql
132
144
      end
133
145
 
 
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,
 
152
      }.freeze
 
153
      def database_error_regexps
 
154
        DATABASE_ERROR_REGEXPS
 
155
      end
 
156
 
134
157
      def default_sequence_name(table, column)
135
158
        "seq_#{table}_#{column}"
136
159
      end
144
167
        super
145
168
      end
146
169
      
 
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]}"
 
178
      end
 
179
    
147
180
      def sequence_for_table(table)
148
181
        return nil unless autosequence
149
182
        @primary_key_sequences.fetch(table) do |key|
155
188
        end
156
189
      end
157
190
 
 
191
      # Oracle supports CREATE OR REPLACE VIEW.
 
192
      def supports_create_or_replace_view?
 
193
        true
 
194
      end
 
195
 
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.
178
216
      def temporary_table_sql
179
217
        TEMPORARY
180
218
      end
 
219
 
 
220
      # Oracle uses clob for text types.
 
221
      def uses_clob_for_text?
 
222
        true
 
223
      end
181
224
    end
182
225
 
183
226
    module DatasetMethods
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
199
 
      LIKE = 'LIKE'.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
207
244
 
208
 
      # Oracle needs to emulate bitwise operators and ILIKE/NOT ILIKE operators.
209
245
      def complex_expression_sql_append(sql, op, args)
210
246
        case op
211
247
        when :&
212
248
          sql << complex_expression_arg_pairs(args){|a, b| "CAST(BITAND(#{literal(a)}, #{literal(b)}) AS INTEGER)"}
213
249
        when :|
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|
 
251
            s1 = ''
 
252
            complex_expression_sql_append(s1, :&, [a, b])
 
253
            "(#{literal(a)} - #{s1} + #{literal(b)})"
 
254
          end
215
255
        when :^
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|
 
257
            s1 = ''
 
258
            s2 = ''
 
259
            complex_expression_sql_append(s1, :|, x)
 
260
            complex_expression_sql_append(s2, :&, x)
 
261
            "(#{s1} - #{s2})"
 
262
          end
217
263
        when :'B~'
218
264
          sql << BITCOMP_OPEN
219
265
          literal_append(sql, args.at(0))
220
266
          sql << BITCOMP_CLOSE
221
267
        when :<<
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)}))"}
223
269
        when :>>
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)}))"}
225
271
        when :%
226
272
          sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
227
 
        when :ILIKE, :'NOT ILIKE'
228
 
          sql << ILIKE_0
229
 
          literal_append(sql, args.at(0))
230
 
          sql << ILIKE_1
231
 
          sql << (op == :ILIKE ? LIKE : NOT_LIKE)
232
 
          sql<< ILIKE_2
233
 
          literal_append(sql, args.at(1))
234
 
          sql << ILIKE_3
235
273
        else
236
274
          super
237
275
        end
248
286
        end
249
287
      end
250
288
 
 
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)
 
295
        case f.f
 
296
        when :char_length
 
297
          literal_append(sql, Sequel::SQL::Function.new(:length, Sequel.join([f.args.first, 'x'])) - 1)
 
298
        else
 
299
          super
 
300
        end
 
301
      end
 
302
      
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)
256
307
      end
349
400
 
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)
353
404
        f = @opts[:from]
354
405
        super(sql, {:table=>(f.first if f), :sequence=>@opts[:sequence]}.merge(opts))
355
406
      end