lib/pg_conn.rb in pg_conn-0.26.0 vs lib/pg_conn.rb in pg_conn-0.26.1

- old
+ new

@@ -313,45 +313,25 @@ def quote_tuples(tuples, elem_types: nil) tuples.map { |tuple| "(#{quote_tuple(tuple, elem_types: elem_types)})" }.join(", ") end # Quote a record and cast it into the given type, the type can also be a - # table or view. 'data' is a hash or struct representation of the record + # table or view. 'data' is an array, hash, or struct representation of the + # record # # Note that the fields are retrived from the database so this method is not # as fast as the other quote-methods. It is however very convenient when # you're testing and need a composite type because record-quoting can # easily become unwieldly - def quote_record(schema_name = nil, type, data, elem_types: nil) - qual_name = [schema_name, type].compact .join('.') - - fields = self.values(%( - select attname - from pg_attribute - where - attrelid = '#{qual_name}'::regclass - and attnum > 0 - and not attisdropped - order by attnum - )).map(&:to_sym) - - values = - case data - when Hash; fields.map { |f| data[f] } - when OpenStruct; fields.map { |f| data.send(f) } - when Array; data - else - raise Error, "Illegal value #{data.inspect}" - end - - "(#{quote_tuple(values, elem_types: elem_types)})::#{qual_name}" + def quote_record(data, schema_name = nil, type, elem_types: nil) + quote_record_impl(data, schema_name, type, elem_types: elem_types, array: false) end - def quote_records(schema_name = nil, type, datas, elem_types: nil) - qual_name = [schema_name, type].compact .join('.') + "[]" - records = datas.map { |data| quote_record(schema_name, type, data, elem_types: elem_types) } - "array[#{records.join(", ")}]::#{qual_name}" + # Quote an array of records. The type is the record type, not the type of + # the enclosing array + def quote_records(data, schema_name = nil, type, elem_types: nil) + quote_record_impl(data, schema_name, type, elem_types: elem_types, array: true) end # :call-seq: # exist?(query) # exist?(table, id) @@ -975,9 +955,45 @@ Process::Sys.seteuid 0 Process::Sys.setguid 0 end else PG::Connection.new *args, **opts + end + end + + # Common implementation for #quote_record and #quote_records that avoids + # query the database multiple times while not duplication the code. the + # :array flag controls the mode + def quote_record_impl(datas, schema_name = nil, type, elem_types: nil, array: nil) + pg_type = [schema_name, type].compact.join('.') + fields = self.values(%( + select attname + from pg_attribute + where + attrelid = '#{pg_type}'::regclass + and attnum > 0 + and not attisdropped + order by attnum + )).map(&:to_sym) + + datas = [datas] if !array + + literals = datas.map { |data| + values = + case data + when Hash; fields.map { |f| data[f] } + when OpenStruct; fields.map { |f| data.send(f) } + when Array; data + else + raise Error, "Illegal value #{data.inspect}" + end + "(#{quote_tuple(values, elem_types: elem_types)})::#{pg_type}" + } + + if array + "array[#{literals.join(', ')}]::#{pg_type}[]" + else + literals.first end end # :call-seq: # pg_exec(string)