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

« back to all changes in this revision

Viewing changes to lib/sequel/dataset/sql.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:
40
40
      when 1
41
41
        case vals = values.at(0)
42
42
        when Hash
43
 
          vals = @opts[:defaults].merge(vals) if @opts[:defaults]
44
 
          vals = vals.merge(@opts[:overrides]) if @opts[:overrides]
45
43
          values = []
46
44
          vals.each do |k,v| 
47
45
            columns << k
49
47
          end
50
48
        when Dataset, Array, LiteralString
51
49
          values = vals
52
 
        else
53
 
          if vals.respond_to?(:values) && (v = vals.values).is_a?(Hash)
54
 
            return insert_sql(v) 
55
 
          end
56
50
        end
57
51
      when 2
58
52
        if (v0 = values.at(0)).is_a?(Array) && ((v1 = values.at(1)).is_a?(Array) || v1.is_a?(Dataset) || v1.is_a?(LiteralString))
154
148
      else
155
149
        check_truncation_allowed!
156
150
        raise(InvalidOperation, "Can't truncate filtered datasets") if opts[:where] || opts[:having]
157
 
        _truncate_sql(source_list(opts[:from]))
 
151
        t = ''
 
152
        source_list_append(t, opts[:from])
 
153
        _truncate_sql(t)
158
154
      end
159
155
    end
160
156
 
165
161
    #
166
162
    # Raises an +Error+ if the dataset is grouped or includes more
167
163
    # than one table.
168
 
    def update_sql(values = {})
 
164
    def update_sql(values = OPTS)
169
165
      return static_sql(opts[:sql]) if opts[:sql]
170
166
      check_modification_allowed!
171
167
      clone(:values=>values)._update_sql
182
178
      clauses.map{|clause| :"#{type}_#{clause}_sql"}.freeze
183
179
    end
184
180
 
 
181
    # Map of emulated function names to native function names.
 
182
    EMULATED_FUNCTION_MAP = {}
 
183
 
185
184
    WILDCARD = LiteralString.new('*').freeze
186
185
    ALL = ' ALL'.freeze
187
186
    AND_SEPARATOR = " AND ".freeze
190
189
    ARRAY_EMPTY = '(NULL)'.freeze
191
190
    AS = ' AS '.freeze
192
191
    ASC = ' ASC'.freeze
 
192
    BACKSLASH = "\\".freeze
193
193
    BOOL_FALSE = "'f'".freeze
194
194
    BOOL_TRUE = "'t'".freeze
195
195
    BRACKET_CLOSE =  ']'.freeze
200
200
    CASE_THEN = " THEN ".freeze
201
201
    CASE_WHEN = " WHEN ".freeze
202
202
    CAST_OPEN = 'CAST('.freeze
203
 
    COLUMN_REF_RE1 = /\A((?:(?!__).)+)__((?:(?!___).)+)___(.+)\z/.freeze
204
 
    COLUMN_REF_RE2 = /\A((?:(?!___).)+)___(.+)\z/.freeze
205
 
    COLUMN_REF_RE3 = /\A((?:(?!__).)+)__(.+)\z/.freeze
 
203
    COLON = ':'.freeze
 
204
    COLUMN_REF_RE1 = Sequel::COLUMN_REF_RE1
 
205
    COLUMN_REF_RE2 = Sequel::COLUMN_REF_RE2
 
206
    COLUMN_REF_RE3 = Sequel::COLUMN_REF_RE3
206
207
    COMMA = ', '.freeze
207
208
    COMMA_SEPARATOR = COMMA
208
209
    CONDITION_FALSE = '(1 = 0)'.freeze
209
210
    CONDITION_TRUE = '(1 = 1)'.freeze
210
 
    COUNT_FROM_SELF_OPTS = [:distinct, :group, :sql, :limit, :compounds]
 
211
    COUNT_FROM_SELF_OPTS = [:distinct, :group, :sql, :limit, :offset, :compounds]
211
212
    COUNT_OF_ALL_AS_COUNT = SQL::Function.new(:count, WILDCARD).as(:count)
212
213
    DATASET_ALIAS_BASE_NAME = 't'.freeze
213
214
    DEFAULT = LiteralString.new('DEFAULT').freeze
220
221
    DOUBLE_APOS = "''".freeze
221
222
    DOUBLE_QUOTE = '""'.freeze
222
223
    EQUAL = ' = '.freeze
 
224
    ESCAPE = " ESCAPE ".freeze
223
225
    EXTRACT = 'extract('.freeze
224
226
    EXISTS = ['EXISTS '.freeze].freeze
225
227
    FOR_UPDATE = ' FOR UPDATE'.freeze
240
242
    INTO = " INTO ".freeze
241
243
    IS_LITERALS = {nil=>'NULL'.freeze, true=>'TRUE'.freeze, false=>'FALSE'.freeze}.freeze
242
244
    IS_OPERATORS = ::Sequel::SQL::ComplexExpression::IS_OPERATORS
 
245
    LIKE_OPERATORS = ::Sequel::SQL::ComplexExpression::LIKE_OPERATORS
243
246
    LIMIT = " LIMIT ".freeze
244
247
    N_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::N_ARITY_OPERATORS
245
248
    NOT_SPACE = 'NOT '.freeze
272
275
    TIMESTAMP_FORMAT = "'%Y-%m-%d %H:%M:%S%N%z'".freeze
273
276
    STANDARD_TIMESTAMP_FORMAT = "TIMESTAMP #{TIMESTAMP_FORMAT}".freeze
274
277
    TWO_ARITY_OPERATORS = ::Sequel::SQL::ComplexExpression::TWO_ARITY_OPERATORS
 
278
    REGEXP_OPERATORS = ::Sequel::SQL::ComplexExpression::REGEXP_OPERATORS
275
279
    UNDERSCORE = '_'.freeze
276
280
    UPDATE = 'UPDATE'.freeze
277
281
    UPDATE_CLAUSE_METHODS = clause_methods(:update, %w'update table set where')
280
284
    V190 = '1.9.0'.freeze
281
285
    WHERE = " WHERE ".freeze
282
286
 
283
 
    PUBLIC_APPEND_METHODS = (<<-END).split.map{|x| x.to_sym}
284
 
      literal
285
 
      aliased_expression_sql
286
 
      array_sql
287
 
      boolean_constant_sql
288
 
      case_expression_sql
289
 
      cast_sql
290
 
      column_all_sql
291
 
      complex_expression_sql
292
 
      constant_sql
293
 
      function_sql
294
 
      join_clause_sql
295
 
      join_on_clause_sql
296
 
      join_using_clause_sql
297
 
      negative_boolean_constant_sql
298
 
      ordered_expression_sql
299
 
      placeholder_literal_string_sql
300
 
      qualified_identifier_sql
301
 
      quote_identifier
302
 
      quote_schema_table
303
 
      quoted_identifier
304
 
      subscript_sql
305
 
      window_sql
306
 
      window_function_sql
307
 
    END
308
 
    PRIVATE_APPEND_METHODS = (<<-END).split.map{|x| x.to_sym}
309
 
      argument_list
310
 
      as_sql
311
 
      column_list
312
 
      compound_dataset_sql
313
 
      expression_list
314
 
      literal_array
315
 
      literal_blob
316
 
      literal_dataset
317
 
      literal_expression
318
 
      literal_hash
319
 
      literal_other
320
 
      literal_string
321
 
      literal_symbol
322
 
      source_list
323
 
      subselect_sql
324
 
      table_ref
325
 
    END
326
 
    def self.def_append_methods(meths)
327
 
      meths.each do |meth|
328
 
        class_eval(<<-END, __FILE__, __LINE__ + 1)
329
 
          def #{meth}(*args, &block)
330
 
            s = ''
331
 
            #{meth}_append(s, *args, &block)
332
 
            s
333
 
          end
334
 
        END
335
 
      end
 
287
    [:literal, :quote_identifier, :quote_schema_table].each do |meth|
 
288
      class_eval(<<-END, __FILE__, __LINE__ + 1)
 
289
        def #{meth}(*args, &block)
 
290
          s = ''
 
291
          #{meth}_append(s, *args, &block)
 
292
          s
 
293
        end
 
294
      END
336
295
    end
337
 
    def_append_methods(PUBLIC_APPEND_METHODS + PRIVATE_APPEND_METHODS)
338
 
    private *PRIVATE_APPEND_METHODS
339
296
 
340
297
    # SQL fragment for AliasedExpression
341
298
    def aliased_expression_sql_append(sql, ae)
402
359
      when *IS_OPERATORS
403
360
        r = args.at(1)
404
361
        if r.nil? || supports_is_true?
405
 
          raise(InvalidOperation, 'Invalid argument used for IS operator') unless v = IS_LITERALS[r]
 
362
          raise(InvalidOperation, 'Invalid argument used for IS operator') unless val = IS_LITERALS[r]
406
363
          sql << PAREN_OPEN
407
364
          literal_append(sql, args.at(0))
408
365
          sql << SPACE << op.to_s << SPACE
409
 
          sql << v << PAREN_CLOSE
 
366
          sql << val << PAREN_CLOSE
410
367
        elsif op == :IS
411
368
          complex_expression_sql_append(sql, :"=", args)
412
369
        else
455
412
          literal_append(sql, vals)
456
413
          sql << PAREN_CLOSE
457
414
        end
 
415
      when :LIKE, :'NOT LIKE'
 
416
        sql << PAREN_OPEN
 
417
        literal_append(sql, args.at(0))
 
418
        sql << SPACE << op.to_s << SPACE
 
419
        literal_append(sql, args.at(1))
 
420
        sql << ESCAPE
 
421
        literal_append(sql, BACKSLASH)
 
422
        sql << PAREN_CLOSE
 
423
      when :ILIKE, :'NOT ILIKE'
 
424
        complex_expression_sql_append(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), args.map{|v| Sequel.function(:UPPER, v)})
458
425
      when *TWO_ARITY_OPERATORS
 
426
        if REGEXP_OPERATORS.include?(op) && !supports_regexp?
 
427
          raise InvalidOperation, "Pattern matching via regular expressions is not supported on #{db.database_type}"
 
428
        end
459
429
        sql << PAREN_OPEN
460
430
        literal_append(sql, args.at(0))
461
431
        sql << SPACE << op.to_s << SPACE
493
463
      sql << constant.to_s
494
464
    end
495
465
 
496
 
    # SQL fragment specifying an SQL function call
 
466
    # SQL fragment for delayed evaluations, evaluating the
 
467
    # object and literalizing the returned value.
 
468
    def delayed_evaluation_sql_append(sql, callable)
 
469
      literal_append(sql, callable.call)
 
470
    end
 
471
 
 
472
    # SQL fragment specifying an emulated SQL function call.
 
473
    # By default, assumes just the function name may need to
 
474
    # be emulated, adapters should set an EMULATED_FUNCTION_MAP
 
475
    # hash mapping emulated functions to native functions in
 
476
    # their dataset class to setup the emulation.
 
477
    def emulated_function_sql_append(sql, f)
 
478
      _function_sql_append(sql, native_function_name(f.f), f.args)
 
479
    end
 
480
 
 
481
    # SQL fragment specifying an SQL function call without emulation.
497
482
    def function_sql_append(sql, f)
498
 
      sql << f.f.to_s
499
 
      args = f.args
500
 
      if args.empty?
501
 
        sql << FUNCTION_EMPTY
502
 
      else
503
 
        literal_append(sql, args)
504
 
      end
 
483
      _function_sql_append(sql, f.f, f.args)
505
484
    end
506
485
 
507
486
    # SQL fragment specifying a JOIN clause without ON or USING.
567
546
          sql << s
568
547
          literal_append(sql, args[i]) unless i == len
569
548
        end
 
549
        unless str.length == args.length || str.length == args.length + 1
 
550
          raise Error, "Mismatched number of placeholders (#{str.length}) and placeholder arguments (#{args.length}) when using placeholder array"
 
551
        end
570
552
      else
571
553
        i = -1
 
554
        match_len = args.length - 1
572
555
        loop do
573
556
          previous, q, str = str.partition(QUESTION_MARK)
574
557
          sql << previous
575
 
           literal_append(sql, args.at(i+=1)) unless q.empty?
576
 
          break if str.empty?
 
558
          literal_append(sql, args.at(i+=1)) unless q.empty?
 
559
          if str.empty?
 
560
            unless i == match_len
 
561
              raise Error, "Mismatched number of placeholders (#{i+1}) and placeholder arguments (#{args.length}) when using placeholder array"
 
562
            end
 
563
            break
 
564
          end
577
565
        end
578
566
      end
579
567
      sql << PAREN_CLOSE if pls.parens
624
612
      sql << QUOTE << name.to_s.gsub(QUOTE_RE, DOUBLE_QUOTE) << QUOTE
625
613
    end
626
614
 
627
 
    # Split the schema information from the table
628
 
    def schema_and_table(table_name)
629
 
      sch = db.default_schema if db
 
615
    # Split the schema information from the table, returning two strings,
 
616
    # one for the schema and one for the table.  The returned schema may
 
617
    # be nil, but the table will always have a string value.
 
618
    #
 
619
    # Note that this function does not handle tables with more than one
 
620
    # level of qualification (e.g. database.schema.table on Microsoft
 
621
    # SQL Server).
 
622
    def schema_and_table(table_name, sch=nil)
 
623
      sch = sch.to_s if sch
630
624
      case table_name
631
625
      when Symbol
632
 
        s, t, a = split_symbol(table_name)
 
626
        s, t, _ = split_symbol(table_name)
633
627
        [s||sch, t]
634
628
      when SQL::QualifiedIdentifier
635
 
        [table_name.table, table_name.column]
 
629
        [table_name.table.to_s, table_name.column.to_s]
636
630
      when SQL::Identifier
637
 
        [sch, table_name.value]
 
631
        [sch, table_name.value.to_s]
638
632
      when String
639
633
        [sch, table_name]
640
634
      else
642
636
      end
643
637
    end
644
638
 
 
639
    # Splits table_name into an array of strings.
 
640
    #
 
641
    #   ds.split_qualifiers(:s) # ['s']
 
642
    #   ds.split_qualifiers(:t__s) # ['t', 's']
 
643
    #   ds.split_qualifiers(Sequel.qualify(:d, :t__s)) # ['d', 't', 's']
 
644
    #   ds.split_qualifiers(Sequel.qualify(:h__d, :t__s)) # ['h', 'd', 't', 's']
 
645
    def split_qualifiers(table_name, *args)
 
646
      case table_name
 
647
      when SQL::QualifiedIdentifier
 
648
        split_qualifiers(table_name.table, nil) + split_qualifiers(table_name.column, nil)
 
649
      else
 
650
        sch, table = schema_and_table(table_name, *args)
 
651
        sch ? [sch, table] : [table]
 
652
      end
 
653
    end
 
654
 
645
655
    # SQL fragment for specifying subscripts (SQL array accesses)
646
656
    def subscript_sql_append(sql, s)
647
657
      literal_append(sql, s.f)
648
658
      sql << BRACKET_OPEN
649
 
      expression_list_append(sql, s.sub)
 
659
      if s.sub.length == 1 && (range = s.sub.first).is_a?(Range)
 
660
        literal_append(sql, range.begin)
 
661
        sql << COLON
 
662
        e = range.end
 
663
        e -= 1 if range.exclude_end? && e.is_a?(Integer)
 
664
        literal_append(sql, e)
 
665
      else
 
666
        expression_list_append(sql, s.sub)
 
667
      end
650
668
      sql << BRACKET_CLOSE
651
669
    end
652
670
 
718
736
    
719
737
    private
720
738
 
 
739
    # Backbone of function_sql_append and emulated_function_sql_append.
 
740
    def _function_sql_append(sql, name, args)
 
741
      sql << name.to_s
 
742
      if args.empty?
 
743
        sql << FUNCTION_EMPTY
 
744
      else
 
745
        literal_append(sql, args)
 
746
      end
 
747
    end
 
748
 
721
749
    # Formats the truncate statement.  Assumes the table given has already been
722
750
    # literalized.
723
751
    def _truncate_sql(table)
767
795
      options_overlap(COUNT_FROM_SELF_OPTS) ? from_self : unordered
768
796
    end
769
797
 
770
 
    def argument_list_append(sql, args)
771
 
      c = false
772
 
      comma = COMMA
773
 
      args.each do |a|
774
 
        sql << comma if c
775
 
        sql << a.to_s
776
 
        c ||= true
777
 
      end
778
 
    end
779
 
 
780
798
    # SQL fragment for specifying an alias.  expression should already be literalized.
781
799
    def as_sql_append(sql, aliaz)
782
800
      sql << AS
865
883
      end
866
884
    end
867
885
 
 
886
    # An expression for how to handle an empty array lookup.
868
887
    def empty_array_value(op, cols)
869
 
      if Sequel.empty_array_handle_nulls
870
 
        c = Array(cols)
871
 
        SQL::BooleanExpression.from_value_pairs(c.zip(c), :AND, op == :IN)
872
 
      else
873
 
        {1 => ((op == :IN) ? 0 : 1)}
874
 
      end
 
888
      c = Array(cols)
 
889
      SQL::BooleanExpression.from_value_pairs(c.zip(c), :AND, op == :IN)
875
890
    end
876
891
    
877
892
    # Format the timestamp based on the default_timestamp_format, with a couple
922
937
        literal_append(sql, v)
923
938
      end
924
939
    end
925
 
    alias table_ref_append identifier_append 
926
 
    
 
940
 
 
941
    # Append all identifiers in args interspersed by commas.
 
942
    def identifier_list_append(sql, args)
 
943
      c = false
 
944
      comma = COMMA
 
945
      args.each do |a|
 
946
        sql << comma if c
 
947
        identifier_append(sql, a)
 
948
        c ||= true
 
949
      end
 
950
    end
 
951
 
927
952
    # Modify the identifier returned from the database based on the
928
953
    # identifier_output_method.
929
954
    def input_identifier(v)
946
971
      columns = opts[:columns]
947
972
      if columns && !columns.empty?
948
973
        sql << PAREN_SPACE_OPEN
949
 
        c = false
950
 
        co = COMMA
951
 
        columns.each do |col|
952
 
          sql << co if c
953
 
          identifier_append(sql, col)
954
 
          c ||= true
955
 
        end
 
974
        identifier_list_append(sql, columns)
956
975
        sql << PAREN_CLOSE
957
976
      end 
958
977
    end
1127
1146
      BOOL_TRUE
1128
1147
    end
1129
1148
 
 
1149
    # Get the native function name given the emulated function name.
 
1150
    def native_function_name(emulated_function)
 
1151
      self.class.const_get(:EMULATED_FUNCTION_MAP).fetch(emulated_function, emulated_function)
 
1152
    end
 
1153
 
1130
1154
    # Returns a qualified column name (including a table name) if the column
1131
1155
    # name isn't already qualified.
1132
1156
    def qualified_column_name(column, table)
1133
 
      if Symbol === column 
1134
 
        c_table, column, c_alias = split_symbol(column)
 
1157
      if column.is_a?(Symbol)
 
1158
        c_table, column, _ = split_symbol(column)
1135
1159
        unless c_table
1136
1160
          case table
1137
1161
          when Symbol
1290
1314
        quote_identifier_append(sql, w[:name])
1291
1315
        if args = w[:args]
1292
1316
         sql << PAREN_OPEN
1293
 
         argument_list_append(sql, args)
 
1317
         identifier_list_append(sql, args)
1294
1318
         sql << PAREN_CLOSE
1295
1319
        end
1296
1320
        sql << AS
1311
1335
    # Converts an array of source names into into a comma separated list.
1312
1336
    def source_list_append(sql, sources)
1313
1337
      raise(Error, 'No source specified for query') if sources.nil? || sources == []
1314
 
      c = false
1315
 
      co = COMMA
1316
 
      sources.each do |s|
1317
 
        sql << co if c
1318
 
        identifier_append(sql, s)
1319
 
        c ||= true
1320
 
      end
 
1338
      identifier_list_append(sql, sources)
1321
1339
    end
1322
1340
    
1323
 
    # Splits the symbol into three parts.  Each part will
1324
 
    # either be a string or nil.
1325
 
    #
1326
 
    # For columns, these parts are the table, column, and alias.
1327
 
    # For tables, these parts are the schema, table, and alias.
 
1341
    # Delegate to Sequel.split_symbol.
1328
1342
    def split_symbol(sym)
1329
 
      case s = sym.to_s
1330
 
      when COLUMN_REF_RE1
1331
 
        [$1, $2, $3]
1332
 
      when COLUMN_REF_RE2
1333
 
        [nil, $1, $2]
1334
 
      when COLUMN_REF_RE3
1335
 
        [$1, $2, nil]
1336
 
      else
1337
 
        [nil, s, nil]
1338
 
      end
 
1343
      Sequel.split_symbol(sym)
1339
1344
    end
1340
1345
 
1341
1346
    # The string that is appended to to create the SQL query, the empty
1386
1391
      values = opts[:values]
1387
1392
      sql << SET
1388
1393
      if values.is_a?(Hash)
1389
 
        values = opts[:defaults].merge(values) if opts[:defaults]
1390
 
        values = values.merge(opts[:overrides]) if opts[:overrides]
1391
1394
        c = false
1392
1395
        eq = EQUAL
1393
1396
        values.each do |k, v|