Class: Flounder::Connection
- Inherits:
-
Object
- Object
- Flounder::Connection
- Includes:
- PostgresUtils
- Defined in:
- lib/flounder/connection.rb
Defined Under Namespace
Classes: Column
Constant Summary
Constants included from PostgresUtils
PostgresUtils::OID_BOOLEAN, PostgresUtils::OID_DATE, PostgresUtils::OID_FLOAT, PostgresUtils::OID_INTEGER, PostgresUtils::OID_SMALLINT, PostgresUtils::OID_TEXT, PostgresUtils::OID_TIME, PostgresUtils::OID_TIMESTAMP, PostgresUtils::OID_TIMESTAMPTZ, PostgresUtils::OID_VARCHAR
Instance Attribute Summary collapse
-
#pg ⇒ Object
readonly
Returns the value of attribute pg.
-
#visitor ⇒ Object
readonly
Returns the value of attribute visitor.
Instance Method Summary collapse
- #columns(name, message = nil) ⇒ Object
- #columns_hash(table_name) ⇒ Object
- #exec(*args, &block) ⇒ Object
-
#initialize(pg_conn_opts) ⇒ Connection
constructor
A new instance of Connection.
-
#objectify_result_row(ent, result, row_idx) ⇒ Hashie::Mash
Turns a PG result row into a hash-like object.
- #primary_key(name) ⇒ Object
- #quote(thing, column = nil) ⇒ Object
- #quote_column_name(name) ⇒ Object
- #quote_table_name(name) ⇒ Object
- #schema_cache ⇒ Object
- #table_exists?(table_name) ⇒ Boolean
- #transaction(&block) ⇒ Object
Methods included from PostgresUtils
#access_value, #each_field, #oid_hstore, #type_name, #type_oid_to_sym, #typecast
Constructor Details
#initialize(pg_conn_opts) ⇒ Connection
Returns a new instance of Connection.
7 8 9 10 11 12 13 14 15 16 |
# File 'lib/flounder/connection.rb', line 7 def initialize pg_conn_opts search_path = pg_conn_opts.delete(:search_path) @pg = PG.connect(pg_conn_opts) @visitor = Arel::Visitors::PostgreSQL.new(self) if search_path exec('set search_path=' + search_path) end end |
Instance Attribute Details
#pg ⇒ Object (readonly)
Returns the value of attribute pg.
4 5 6 |
# File 'lib/flounder/connection.rb', line 4 def pg @pg end |
#visitor ⇒ Object (readonly)
Returns the value of attribute visitor.
5 6 7 |
# File 'lib/flounder/connection.rb', line 5 def visitor @visitor end |
Instance Method Details
#columns(name, message = nil) ⇒ Object
59 60 61 |
# File 'lib/flounder/connection.rb', line 59 def columns name, = nil fail NotImplementedError end |
#columns_hash(table_name) ⇒ Object
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/flounder/connection.rb', line 27 def columns_hash table_name hash = {} pg.exec(%Q(select * from #{quote_table_name(table_name)} limit 0)) do |result| # TBD This is a duplicate from the code in Query. result.nfields.times do |idx| name = result.fname(idx) type_oid = result.ftype(idx) mod = result.fmod(idx) typesym = type_oid_to_sym(self, type_oid) unless typesym type_string = type_name(type_oid, mod) fail "No map for oid #{type_oid} found, type(#{type_string})." end hash[name] = Column.new(name, typesym) end end hash end |
#exec(*args, &block) ⇒ Object
21 22 23 |
# File 'lib/flounder/connection.rb', line 21 def exec *args, &block pg.exec *args, &block end |
#objectify_result_row(ent, result, row_idx) ⇒ Hashie::Mash
Turns a PG result row into a hash-like object. There are some transformation rules that govern this conversion:
-
All data types are converted to their closest Ruby equivalent (type conversion)
-
Fields from the main entity (the entity that started the select) are returned on the top level of the hash.
-
Fields from joined entities are returned in a subhash stored under the singular name of the joined entity.
Example:
row = users.join(posts).on(:id => :user_id).first
row[:id] # refers to users.id, also as row.id
row[:post][:id] # refers to posts.id, also as row.post.id
row.keys # hash keys of the row, not equal to row[:keys]!
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/flounder/connection.rb', line 106 def objectify_result_row ent, result, row_idx obj = Hashie::Mash.new each_field(ent, result, row_idx) do |entity, name, value, type_oid, binary, idx| # NOTE entity resolution is done both through aliasing and through # postgres column reporting. The above entity variable carries what # postgres reports to us; the block below resolves aliased entity # names: processed_entity, processed_name = yield name if block_given? entity = processed_entity if processed_entity name = processed_name if processed_name typecast_value = typecast(type_oid, value) # JOIN tables are available from the result using their singular # names. if entity obj[entity.singular] ||= {} sub_obj = obj[entity.singular] sub_obj[name] = typecast_value end # The main entity and custom fields (AS something) are available on the # top-level of the result. if !entity || entity == ent raise DuplicateField, "#{name.inspect} already defined in result set, aliasing occurs." \ if obj.has_key? name obj[name] = typecast_value end end return obj end |
#primary_key(name) ⇒ Object
50 51 52 |
# File 'lib/flounder/connection.rb', line 50 def primary_key name fail NotImplementedError end |
#quote(thing, column = nil) ⇒ Object
75 76 77 78 79 80 |
# File 'lib/flounder/connection.rb', line 75 def quote thing, column = nil # require 'pp ' # p [:quote, thing, column] # pp caller.first(10) pg.escape_literal(thing.to_s) end |
#quote_column_name(name) ⇒ Object
67 68 69 |
# File 'lib/flounder/connection.rb', line 67 def quote_column_name name pg.quote_ident name.to_s end |
#quote_table_name(name) ⇒ Object
63 64 65 |
# File 'lib/flounder/connection.rb', line 63 def quote_table_name name pg.quote_ident name.to_s end |
#schema_cache ⇒ Object
71 72 73 |
# File 'lib/flounder/connection.rb', line 71 def schema_cache self end |
#table_exists?(table_name) ⇒ Boolean
54 55 56 57 |
# File 'lib/flounder/connection.rb', line 54 def table_exists? table_name # TBD Centralize these direct SQL statements in some class ! pg.exec(%Q(select count(*) from pg_class where relname = #{quote(table_name)})).getvalue(0,0).nil? end |
#transaction(&block) ⇒ Object
18 19 20 |
# File 'lib/flounder/connection.rb', line 18 def transaction &block pg.transaction(&block) end |