Pg: Support custom type overrides with callbacks

This commit is contained in:
Yorhel 2025-02-28 11:23:37 +01:00
parent 327fd9ea50
commit 4686097d00
6 changed files with 227 additions and 85 deletions

View file

@ -9,6 +9,7 @@ plan skip_all => 'Please set FU_TEST_DB to a PostgreSQL connection string to run
my $conn = FU::Pg->connect($ENV{FU_TEST_DB});
$conn->_debug_trace(0);
is_deeply $conn->Q('SELECT', 1, '::int')->param_types, [23];
is_deeply $conn->Q('SELECT 1', IN([1,2,3]))->param_types, [1007];
is $conn->Q('SELECT 1', IN([1,2,3]))->val, 1;
@ -17,30 +18,48 @@ ok !eval { $conn->q('SELECT $1::aclitem', '')->exec; 1 };
like $@, qr/Unable to send type/;
$conn->set_type(int4 => recv => 'bytea');
is $conn->q('SELECT 5::int4')->val, "\0\0\0\5";
is_deeply $conn->q('SELECT ARRAY[5::int4]')->val, ["\0\0\0\5"];
subtest 'type overrides', sub {
$conn->set_type(int4 => recv => 'bytea');
is $conn->q('SELECT 5::int4')->val, "\0\0\0\5";
is_deeply $conn->q('SELECT ARRAY[5::int4]')->val, ["\0\0\0\5"];
$conn->set_type(int4 => send => 'bytea');
is $conn->q('SELECT $1::int4', "\0\0\0\5")->val, 5;
is_deeply $conn->q('SELECT $1::int4[]', ["\0\0\0\5"])->val, [5];
$conn->set_type(int4 => send => 'bytea');
is $conn->q('SELECT $1::int4', "\0\0\0\5")->val, 5;
is_deeply $conn->q('SELECT $1::int4[]', ["\0\0\0\5"])->val, [5];
$conn->set_type(int4 => 'int2');
ok !eval { $conn->q('SELECT 5::int4')->val };
like $@, qr/Error parsing value/;
ok !eval { $conn->q('SELECT $1::int4', 5)->val };
like $@, qr/insufficient data left in message/;
$conn->set_type(int4 => 'int2');
ok !eval { $conn->q('SELECT 5::int4')->val };
like $@, qr/Error parsing value/;
ok !eval { $conn->q('SELECT $1::int4', 5)->val };
like $@, qr/insufficient data left in message/;
$conn->set_type(int4 => undef);
is $conn->q('SELECT 5::int4')->val, 5;
$conn->set_type(int4 => undef);
is $conn->q('SELECT 5::int4')->val, 5;
ok !eval { $conn->set_type(int4 => 1007); };
like $@, qr/Cannot set a type to array/;
ok !eval { $conn->set_type(int4 => 1007); };
like $@, qr/Cannot set a type to array/;
ok !eval { $conn->set_type(int4 => 1); };
like $@, qr/No builtin type found/;
ok !eval { $conn->set_type(int4 => 1); };
like $@, qr/No builtin type found/;
};
{
subtest 'type override callback', sub {
$conn->set_type(text => recv => sub { length $_[0] });
is $conn->q('SELECT $1', 'a')->val, 1;
is $conn->q('SELECT $1', 'ab')->val, 2;
is $conn->q('SELECT $1', 'abc')->val, 3;
is $conn->q('SELECT $1', 'abcd')->val, 4;
$conn->set_type(text => send => sub { 'l'.length $_[0] });
is $conn->q('SELECT $1', 'a')->val, 'l1';
is $conn->q('SELECT $1', 'ab')->val, 'l2';
is $conn->q('SELECT $1', 'abc')->val, 'l3';
is $conn->q('SELECT $1', 'abcd')->val, 'l4';
};
subtest 'custom types', sub {
my $txn = $conn->txn;
is $txn->Q('SELECT 1', IN([1,2,3]))->val, 1;
@ -100,6 +119,6 @@ like $@, qr/No builtin type found/;
is $txn->q("SELECT dom FROM fupg_test_table")->val, 'bb';
$conn->set_type(fupg_test_enum => 21);
is $txn->q("SELECT dom FROM fupg_test_table")->val, 0x6262;
}
};
done_testing;