require 'pg' class MicroSql::PgAdapter < MicroSql def initialize(url) uri = URI.parse(url) @impl = PG.connect :host => uri.host, :port => uri.port || 5433, :user => uri.user, :password => uri.password, :dbname => uri.path[1..-1] end def tables exec("SELECT tablename FROM pg_tables WHERE tablename NOT LIKE 'pg_%' AND tablename NOT LIKE 'sql_%'").map(&:first) end def execute_batch(sql) sql.split(";").each { exec(part) } end private def execute(flag, sql, *args) statement = prepare(sql) if flag == :prepare result = if statement @impl.exec_prepared(statement, args) else @impl.exec(sql, args) end if sql =~ /^\s*(UPDATE|DELETE|INSERT)/i return result.cmd_tuples end types = (0 ... result.num_fields).map do |i| # Get the type of the second column of the result 'res' @impl.exec( "SELECT format_type($1,$2)", [result.ftype(i), result.fmod(i)] ).getvalue( 0, 0 ) end result.values.map do |rec| types.each_with_index do |type, idx| case type when "text", "name" then :nop when "integer", "bigint" then rec[idx] = rec[idx] && rec[idx].to_i else raise "Unknown column type #{type}: #{rec[idx].inspect}" end end rec end end def prepare_query(key, sql) idx = 0 query = sql.gsub("?") do idx += 1 "$#{idx}" end return nil if idx == 0 @impl.prepare(key, query) key end end