From a30bf7c60f07693ebad3876015c51c9fefef5335 Mon Sep 17 00:00:00 2001 From: Lars Kanis Date: Tue, 4 Aug 2020 18:51:22 +0200 Subject: [PATCH] Add PG::BasicTypeMapForQueries::BinaryData for encoding of bytea columns It has always been easy to register a binary encoder to PG::BasicTypeMapForQueries like so: class BinaryData < String; end tm[BinaryData] = PG::BinaryEncoder::Bytea.new However it might be more convenient to add a default class that can be used without registration. Related to #344 --- lib/pg/basic_type_mapping.rb | 16 ++++++++++++++++ spec/pg/basic_type_mapping_spec.rb | 7 +++++++ 2 files changed, 23 insertions(+) diff --git a/lib/pg/basic_type_mapping.rb b/lib/pg/basic_type_mapping.rb index fe4080c7b..c0921cc31 100644 --- a/lib/pg/basic_type_mapping.rb +++ b/lib/pg/basic_type_mapping.rb @@ -396,6 +396,21 @@ def initialize(connection) # # The format of the parameter is set to 0 (text) and the OID of this parameter is set to 20 (int8). # res = conn.exec_params( "SELECT $1", [5] ) class PG::BasicTypeMapForQueries < PG::TypeMapByClass + # Helper class for submission of binary strings into bytea columns. + # + # Since PG::BasicTypeMapForQueries chooses the encoder to be used by the class of the submitted value, + # it's necessary to send binary strings as BinaryData. + # That way they're distinct from text strings. + # Please note however that PG::BasicTypeMapForResults delivers bytea columns as plain String + # with binary encoding. + # + # conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn) + # conn.exec("CREATE TEMP TABLE test (data bytea)") + # bd = PG::BasicTypeMapForQueries::BinaryData.new("ab\xff\0cd") + # conn.exec_params("INSERT INTO test (data) VALUES ($1)", [bd]) + class BinaryData < String + end + include PG::BasicTypeRegistry def initialize(connection) @@ -506,6 +521,7 @@ def get_array_type(value) IPAddr => [0, 'inet'], Hash => [0, 'json'], Array => :get_array_type, + BinaryData => [1, 'bytea'], } DEFAULT_ARRAY_TYPE_MAP = { diff --git a/spec/pg/basic_type_mapping_spec.rb b/spec/pg/basic_type_mapping_spec.rb index be9c7c5cb..f29be279b 100644 --- a/spec/pg/basic_type_mapping_spec.rb +++ b/spec/pg/basic_type_mapping_spec.rb @@ -205,6 +205,13 @@ def to_s expect( result_typenames(res) ).to eq( ['text[]'] ) end + it "should take BinaryData for bytea columns" do + @conn.exec("CREATE TEMP TABLE IF NOT EXISTS bytea_test (data bytea)") + bd = PG::BasicTypeMapForQueries::BinaryData.new("ab\xff\0cd") + res = @conn.exec_params("INSERT INTO bytea_test (data) VALUES ($1) RETURNING data", [bd], nil, basic_type_mapping) + + expect( res.to_a ).to eq([{"data" => "\\x6162ff006364"}]) + end end