Class: Sequel::Postgres::Dataset

Inherits:
Dataset show all
Defined in:
lib/sequel_core/adapters/postgres.rb

Constant Summary collapse

PG_TIMESTAMP_FORMAT =
"TIMESTAMP '%Y-%m-%d %H:%M:%S".freeze
BOOL_FALSE =
'false'.freeze
BOOL_TRUE =
'true'.freeze
FOR_UPDATE =
' FOR UPDATE'.freeze
FOR_SHARE =
' FOR SHARE'.freeze
EXPLAIN =
'EXPLAIN '.freeze
EXPLAIN_ANALYZE =
'EXPLAIN ANALYZE '.freeze
QUERY_PLAN =
'QUERY PLAN'.to_sym
LOCK =
'LOCK TABLE %s IN %s MODE'.freeze
ACCESS_SHARE =
'ACCESS SHARE'.freeze
ROW_SHARE =
'ROW SHARE'.freeze
ROW_EXCLUSIVE =
'ROW EXCLUSIVE'.freeze
SHARE_UPDATE_EXCLUSIVE =
'SHARE UPDATE EXCLUSIVE'.freeze
SHARE =
'SHARE'.freeze
SHARE_ROW_EXCLUSIVE =
'SHARE ROW EXCLUSIVE'.freeze
EXCLUSIVE =
'EXCLUSIVE'.freeze
ACCESS_EXCLUSIVE =
'ACCESS EXCLUSIVE'.freeze

Constants inherited from Dataset

Dataset::AND_SEPARATOR, Dataset::COLUMN_CHANGE_OPTS, Dataset::COLUMN_REF_RE1, Dataset::COLUMN_REF_RE2, Dataset::COLUMN_REF_RE3, Dataset::COMMA_SEPARATOR, Dataset::COUNT_FROM_SELF_OPTS, Dataset::COUNT_OF_ALL_AS_COUNT, Dataset::DATASET_CLASSES, Dataset::DATE_FORMAT, Dataset::MUTATION_METHODS, Dataset::NOTIMPL_MSG, Dataset::NULL, Dataset::N_ARITY_OPERATORS, Dataset::QUESTION_MARK, Dataset::STOCK_COUNT_OPTS, Dataset::STOCK_TRANSFORMS, Dataset::TIMESTAMP_FORMAT, Dataset::TWO_ARITY_OPERATORS, Dataset::WILDCARD

Instance Attribute Summary

Attributes inherited from Dataset

#db, #opts, #quote_identifiers, #row_proc

Instance Method Summary collapse

Methods inherited from Dataset

#<<, #[], #[]=, #aliased_expression_sql, #all, #and, #as, #avg, #case_expression_sql, #clone, #column_all_sql, #columns, #columns!, #complex_expression_sql, #count, #create_or_replace_view, #create_view, dataset_classes, #def_mutation_method, def_mutation_method, #delete_sql, #each, #each_page, #empty?, #except, #exclude, #exists, #filter, #first, #first_source, #from, #from_self, #function_sql, #get, #graph, #grep, #group, #group_and_count, #having, inherited, #initialize, #insert_multiple, #insert_sql, #inspect, #intersect, #interval, #invert, #irregular_function_sql, #join_clause_sql, #join_on_clause_sql, #join_table, #join_using_clause_sql, #last, #limit, #map, #max, #min, #model_classes, #multi_insert, #naked, #or, #order, #order_more, #ordered_expression_sql, #paginate, #polymorphic_key, #print, #qualified_identifier_sql, #query, #quote_identifier, #quote_identifiers?, #range, #reverse_order, #select, #select_all, #select_more, #set, #set_graph_aliases, #set_model, #single_record, #single_value, #subscript_sql, #sum, #symbol_to_column_ref, #table_exists?, #to_csv, #to_hash, #transform, #transform_load, #transform_save, #unfiltered, #union, #uniq, #unordered, #update_sql

Methods included from Enumerable

#send_each

Constructor Details

This class inherits a constructor from Sequel::Dataset

Instance Method Details

#analyze(opts = nil) ⇒ Object



485
486
487
488
489
490
491
# File 'lib/sequel_core/adapters/postgres.rb', line 485

def analyze(opts = nil)
  analysis = []
  fetch_rows(EXPLAIN_ANALYZE + select_sql(opts)) do |r|
    analysis << r[QUERY_PLAN]
  end
  analysis.join("\r\n")
end

#delete(opts = nil) ⇒ Object



535
536
537
# File 'lib/sequel_core/adapters/postgres.rb', line 535

def delete(opts = nil)
  @db.execute(delete_sql(opts))
end

#explain(opts = nil) ⇒ Object



477
478
479
480
481
482
483
# File 'lib/sequel_core/adapters/postgres.rb', line 477

def explain(opts = nil)
  analysis = []
  fetch_rows(EXPLAIN + select_sql(opts)) do |r|
    analysis << r[QUERY_PLAN]
  end
  analysis.join("\r\n")
end

#fetch_rows(sql, &block) ⇒ Object



539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/sequel_core/adapters/postgres.rb', line 539

def fetch_rows(sql, &block)
  @columns = []
  @db.execute(sql) do |res|
    (0...res.ntuples).each do |recnum|
      converted_rec = {}
      (0...res.nfields).each do |fieldnum|
        fieldsym = res.fname(fieldnum).to_sym
        @columns << fieldsym
        converted_rec[fieldsym] = if value = res.getvalue(recnum,fieldnum)
          (PG_TYPES[res.ftype(fieldnum)] || lambda{|s| s.to_s}).call(value)
        else
          value
        end
      end
      yield converted_rec
    end
  end
end

#for_shareObject



469
470
471
# File 'lib/sequel_core/adapters/postgres.rb', line 469

def for_share
  clone(:lock => :share)
end

#for_updateObject



465
466
467
# File 'lib/sequel_core/adapters/postgres.rb', line 465

def for_update
  clone(:lock => :update)
end

#full_text_search(cols, terms, opts = {}) ⇒ Object



443
444
445
446
447
448
# File 'lib/sequel_core/adapters/postgres.rb', line 443

def full_text_search(cols, terms, opts = {})
  lang = opts[:language] ? "#{literal(opts[:language])}, " : ""
  cols = cols.is_a?(Array) ? cols.map {|c| literal(c)}.join(" || ") : literal(cols)
  terms = terms.is_a?(Array) ? literal(terms.join(" | ")) : literal(terms)
  filter("to_tsvector(#{lang}#{cols}) @@ to_tsquery(#{lang}#{terms})")
end

#insert(*values) ⇒ Object



526
527
528
529
# File 'lib/sequel_core/adapters/postgres.rb', line 526

def insert(*values)
  @db.execute_insert(insert_sql(*values), source_list(@opts[:from]),
    values.size == 1 ? values.first : values)
end

#literal(v) ⇒ Object



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
# File 'lib/sequel_core/adapters/postgres.rb', line 413

def literal(v)
  case v
  when LiteralString
    v
  when String
    db.synchronize{|c| "'#{SQL::Blob === v ? c.escape_bytea(v) : c.escape_string(v)}'"}
  when Time
    "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d",v.usec)}'"
  when DateTime
    "#{v.strftime(PG_TIMESTAMP_FORMAT)}.#{sprintf("%06d", (v.sec_fraction * 86400000000).to_i)}'"
  when TrueClass
    BOOL_TRUE
  when FalseClass
    BOOL_FALSE
  else
    super
  end
end

#lock(mode, &block) ⇒ Object

Locks the table with the specified mode.



505
506
507
508
509
510
511
512
513
514
515
# File 'lib/sequel_core/adapters/postgres.rb', line 505

def lock(mode, &block)
  sql = LOCK % [source_list(@opts[:from]), mode]
  @db.synchronize do
    if block # perform locking inside a transaction and yield to block
      @db.transaction {@db.execute(sql); yield}
    else
      @db.execute(sql) # lock without a transaction
      self
    end
  end
end

#match_expr(l, r) ⇒ Object



432
433
434
435
436
437
438
439
440
441
# File 'lib/sequel_core/adapters/postgres.rb', line 432

def match_expr(l, r)
  case r
  when Regexp
    r.casefold? ? \
      "(#{literal(l)} ~* #{literal(r.source)})" :
      "(#{literal(l)} ~ #{literal(r.source)})"
  else
    super
  end
end

#multi_insert_sql(columns, values) ⇒ Object



517
518
519
520
521
522
523
524
# File 'lib/sequel_core/adapters/postgres.rb', line 517

def multi_insert_sql(columns, values)
  return super if @db.server_version < 80200
  
  # postgresql 8.2 introduces support for multi-row insert
  columns = column_list(columns)
  values = values.map {|r| literal(Array(r))}.join(COMMA_SEPARATOR)
  ["INSERT INTO #{source_list(@opts[:from])} (#{columns}) VALUES #{values}"]
end

#quoted_identifier(c) ⇒ Object



405
406
407
# File 'lib/sequel_core/adapters/postgres.rb', line 405

def quoted_identifier(c)
  "\"#{c}\""
end

#select_sql(opts = nil) ⇒ Object



453
454
455
456
457
458
459
460
461
462
463
# File 'lib/sequel_core/adapters/postgres.rb', line 453

def select_sql(opts = nil)
  row_lock_mode = opts ? opts[:lock] : @opts[:lock]
  sql = super
  case row_lock_mode
  when :update
    sql << FOR_UPDATE
  when :share
    sql << FOR_SHARE
  end
  sql
end

#update(*args, &block) ⇒ Object



531
532
533
# File 'lib/sequel_core/adapters/postgres.rb', line 531

def update(*args, &block)
  @db.execute(update_sql(*args, &block))
end