Class: MoSQL::SQLAdapter

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/mosql/sql.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

#log

Constructor Details

#initialize(schema, uri, pgschema = nil) ⇒ SQLAdapter

Returns a new instance of SQLAdapter.



7
8
9
10
11
# File 'lib/mosql/sql.rb', line 7

def initialize(schema, uri, pgschema=nil)
  @schema = schema
  connect_db(uri, pgschema)
  @db.extension :pg_array
end

Instance Attribute Details

#dbObject (readonly)

Returns the value of attribute db.



5
6
7
# File 'lib/mosql/sql.rb', line 5

def db
  @db
end

Class Method Details

.duplicate_column_error?(e) ⇒ Boolean

Returns:

  • (Boolean)


81
82
83
# File 'lib/mosql/sql.rb', line 81

def self.duplicate_column_error?(e)
  e.wrapped_exception.result.error_field(PG::Result::PG_DIAG_SQLSTATE) == "42701"
end

.duplicate_key_error?(e) ⇒ Boolean

Returns:

  • (Boolean)


72
73
74
75
76
77
78
79
# File 'lib/mosql/sql.rb', line 72

def self.duplicate_key_error?(e)
  # c.f. http://www.postgresql.org/docs/9.2/static/errcodes-appendix.html
  # for the list of error codes.
  #
  # No thanks to Sequel and pg for making it easy to figure out
  # how to get at this error code....
  e.wrapped_exception.result.error_field(PG::Result::PG_DIAG_SQLSTATE) == "23505"
end

Instance Method Details

#connect_db(uri, pgschema) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
# File 'lib/mosql/sql.rb', line 13

def connect_db(uri, pgschema)
  @db = Sequel.connect(uri, :after_connect => proc do |conn|
                         if pgschema
                           begin
                             conn.execute("CREATE SCHEMA \"#{pgschema}\"")
                           rescue PG::Error
                           end
                           conn.execute("SET search_path TO \"#{pgschema}\"")
                         end
                       end)
end

#delete_ns(ns, obj) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/mosql/sql.rb', line 42

def delete_ns(ns, obj)
  primary_sql_keys = @schema.primary_sql_key_for_ns(ns)
  h = transform_one_ns(ns, obj)
  query = {}
  primary_sql_keys.each do |key|
    raise "No #{primary_sql_keys} found in transform of #{obj.inspect}" if h[key].nil?
    query[key.to_sym] = h[key]
  end

  table_for_ns(ns).where(query).delete
end

#table_for_ns(ns) ⇒ Object



25
26
27
# File 'lib/mosql/sql.rb', line 25

def table_for_ns(ns)
  @db[@schema.table_for_ns(ns).intern]
end

#transform_one_ns(ns, obj) ⇒ Object



29
30
31
32
33
34
35
# File 'lib/mosql/sql.rb', line 29

def transform_one_ns(ns, obj)
  h = {}
  cols = @schema.all_columns(@schema.find_ns(ns))
  row  = @schema.transform(ns, obj)
  cols.zip(row).each { |k,v| h[k] = v }
  h
end

#upsert!(table, table_primary_keys, item) ⇒ Object



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/mosql/sql.rb', line 54

def upsert!(table, table_primary_keys, item)
  query = {}
  table_primary_keys.each do |key|
    query[key.to_sym] = item[key]
  end
  rows = table.where(query).update(item)
  if rows == 0
    begin
      table.insert(item)
    rescue Sequel::DatabaseError => e
      raise e unless self.class.duplicate_key_error?(e)
      log.info("RACE during upsert: Upserting #{item} into #{table}: #{e}")
    end
  elsif rows > 1
    log.warn("Huh? Updated #{rows} > 1 rows: upsert(#{table}, #{item})")
  end
end

#upsert_ns(ns, obj) ⇒ Object



37
38
39
40
# File 'lib/mosql/sql.rb', line 37

def upsert_ns(ns, obj)
  h = transform_one_ns(ns, obj)
  upsert!(table_for_ns(ns), @schema.primary_sql_key_for_ns(ns), h)
end