Pg: Add perl2bin() and bin2perl() conversion methods
This commit is contained in:
parent
af9340f908
commit
beeefcf337
4 changed files with 69 additions and 2 deletions
8
FU.xs
8
FU.xs
|
|
@ -286,6 +286,14 @@ void _set_type(fupg_conn *c, SV *name, SV *sendsv, SV *recvsv)
|
|||
fupg_set_type(aTHX_ c, name, sendsv, recvsv);
|
||||
XSRETURN(1);
|
||||
|
||||
void perl2bin(fupg_conn *c, int oid, SV *sv)
|
||||
CODE:
|
||||
ST(0) = fupg_perl2bin(aTHX_ c, oid, sv);
|
||||
|
||||
void bin2perl(fupg_conn *c, int oid, SV *sv)
|
||||
CODE:
|
||||
ST(0) = fupg_bin2perl(aTHX_ c, oid, sv);
|
||||
|
||||
|
||||
MODULE = FU PACKAGE = FU::Pg::txn
|
||||
|
||||
|
|
|
|||
26
FU/Pg.pm
26
FU/Pg.pm
|
|
@ -758,7 +758,31 @@ C<set_type()> to configure appropriate conversions for these types.
|
|||
|
||||
=back
|
||||
|
||||
I<TODO:> Methods to convert between the various formats.
|
||||
Utility functions:
|
||||
|
||||
=over
|
||||
|
||||
=item $conn->perl2bin($oid, $val)
|
||||
|
||||
=item $conn->bin2perl($oid, $bin)
|
||||
|
||||
Convert the value for a specific type between the Perl representation and the
|
||||
PostgreSQL binary format, using the current type configuration of the
|
||||
connection. This is the same conversion used internally by this module to send
|
||||
bind parameters and receive query results, and map to the C<send> and C<recv>
|
||||
functions of C<< $conn->set_type() >>.
|
||||
|
||||
These methods throw an error if C<$oid> is not a known type or if the given
|
||||
data is not valid for the type. However, these methods should not be used for
|
||||
strict validation: the conversion routines are usually written under the
|
||||
assumption that the data has been received directly from Postgres or is about
|
||||
to be sent to (and further validated by) Postgres. For some types,
|
||||
C<perl2bin()> may return invalid data on invalid input and C<bin2perl()> may
|
||||
accept invalid binary data.
|
||||
|
||||
=back
|
||||
|
||||
I<TODO:> Methods to convert between bin and text formats.
|
||||
|
||||
I<TODO:> Methods to query type info.
|
||||
|
||||
|
|
|
|||
27
c/pgconn.c
27
c/pgconn.c
|
|
@ -626,3 +626,30 @@ static void fupg_tio_free(fupg_tio *tio) {
|
|||
safefree(tio->record.tio);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static SV *fupg_perl2bin(pTHX_ fupg_conn *conn, Oid oid, SV *sv) {
|
||||
int refresh_done = 0;
|
||||
fupg_tio tio;
|
||||
fustr buf;
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
fupg_tio_setup(aTHX_ conn, &tio, FUPGT_SEND, oid, &refresh_done);
|
||||
fustr_init(&buf, sv_newmortal(), SIZE_MAX);
|
||||
tio.send(aTHX_ &tio, sv, &buf); /* XXX: Leaks 'tio' on error */
|
||||
fupg_tio_free(&tio);
|
||||
return fustr_done(&buf);
|
||||
}
|
||||
|
||||
static SV *fupg_bin2perl(pTHX_ fupg_conn *conn, Oid oid, SV *sv) {
|
||||
int refresh_done = 0;
|
||||
fupg_tio tio;
|
||||
STRLEN len;
|
||||
const char *buf = SvPVbyte(sv, len);
|
||||
memset(&tio, 0, sizeof(tio));
|
||||
fupg_tio_setup(aTHX_ conn, &tio, FUPGT_RECV, oid, &refresh_done);
|
||||
SV *r = tio.recv(aTHX_ &tio, buf, len); /* XXX: Leaks 'tio' on error */
|
||||
fupg_tio_free(&tio);
|
||||
return r;
|
||||
}
|
||||
|
|
|
|||
10
t/pgtypes.t
10
t/pgtypes.t
|
|
@ -19,9 +19,12 @@ sub v($type, $p_in, @args) {
|
|||
my $s_out = @args > 2 && defined $args[2] ? $args[2] : $s_in;
|
||||
|
||||
my $test = "$type $s_in" =~ s/\n/\\n/rg;
|
||||
my $oid;
|
||||
utf8::encode($test);
|
||||
{
|
||||
my $array = $conn->q("SELECT \$1::$type", $s_in)->text_params->flat;
|
||||
my $st = $conn->q("SELECT \$1::$type", $s_in)->text_params;
|
||||
$oid = $st->param_types->[0];
|
||||
my $array = $st->flat;
|
||||
my $res = $array->[0];
|
||||
ok is_bool($res), "$test is bool" if $type eq 'bool';
|
||||
ok created_as_number($res), "$test is number" if $type =~ /^(int|float)\d/;
|
||||
|
|
@ -36,6 +39,11 @@ sub v($type, $p_in, @args) {
|
|||
my $res = $conn->q("SELECT \$1::$type", $p_in)->val;
|
||||
is_deeply $res, $p_out, "$test bin->bin";
|
||||
}
|
||||
{
|
||||
my $bin = $conn->perl2bin($oid, $p_in);
|
||||
ok defined $bin;
|
||||
is_deeply $conn->bin2perl($oid, $bin), $p_out if $type !~ /\(/;
|
||||
}
|
||||
}
|
||||
sub f($type, $p_in) {
|
||||
my $test = "$type $p_in" =~ s/\n/\\n/rg;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue