package FU::PG 0.1; use v5.36; use FU::XS; _load_libpq(); package FU::PG::conn { sub lib_version { FU::PG::lib_version() } }; package FU::PG::error { use overload '""' => sub($e, @) { $e->{verbose_message} || "$e->{severity}: $e->{message}\n"; }; } 1; __END__ =head1 NAME FU::PG - Another PostgreSQL client module =head1 SYNOPSYS my $conn = FU::PG->connect("dbname=test user=test password=nottest"); $conn->exec('CREATE TABLE books (id SERIAL, title text)'); $conn->q('INSERT INTO books (title) VALUES ($1)', 'Revelation Space')->exec; for my ($id, $title) ($conn->q('SELECT * FROM books')->flat) { print "$id: $title\n"; } =head1 DESCRIPTION FU::PG is a PostgreSQL client module that (attempts) to set itself apart from the existing alternatives by offering the following features: =over =item * Automatic conversion of complex types (like JSON, hstore, records, etc) to and from convenient corresponding perl values. =item * Support for custom types. =item * Configurable Perl representation of timestamp values (or, well, really for any type). =item * Data is transfered in the binary format (which may or may not be more efficient, need benchmarks). =item * Convenient and high-level API. =back =head2 Connection setup =over =item B<< FU::PG->connect($string) >> Connect to the PostgreSQL server and return a new C object. C<$string> can either be in key=value format or a URI, refer to L for the full list of supported formats and options. You may also pass an empty string and leave the configuration up L. =item B<< $conn->server_version >> Returns the version of the PostgreSQL server as an integer in the format of C<$major * 10000 + $minor>. For example, returns 170002 for PostgreSQL 17.2. =item B<< $conn->lib_version >> Returns the libpq version in the same format as the C method. Also available directly as C. =back =head2 Querying =over =item B<< $conn->exec($sql) >> Execute one or more SQL commands, separated by a semicolon. Returns the number of rows affected by the last statement or I if that information is not available for the given command (like `CREATE TABLE`). =item B<< $conn->q($sql, @params) >> Create a new SQL statement with the given C<$sql> string and an optional list of bind parameters. C<$sql> can only hold a single statement. Parameters can be referenced from C<$sql> with numbered placeholders, where C<$1> refers to the first parameter, C<$2> to the second, etc. Be careful to not accidentally interpolate perl's C<$1> and C<$2>. Using a question mark for placeholders, as is common with L, is not supported. If a placeholder mentioned in C<$sql> is not present in C<@params>, I is assumed instead. Excess C<@params> that are not referenced by C<$sql> are ignored. Note that this method just creates a statement object, the given query is not prepared or executed until the appropriate statement methods (see below) are used. =back Statement objects returned by C<< $conn->q() >> support the following methods: =over =item B<< $st->params >> Returns an arrayref of hashrefs describing each parameter in the given C<$sql> string. Each parameter only has a single key for now: C, indicating the type Oid. Example: my $params = $conn->q('SELECT id FROM books WHERE id = $1')->params; # $params = [ { oid => 23 } ] my $params = $conn->q('SELECT id FROM books')->params; # $params = [] I =item B<< $st->columns >> Returns an arrayref of hashrefs describing each column that the statement returns. my $cols = $conn->q('SELECT id, title FROM books')->columns; # $cols = [ # { name => 'id', oid => 23 }, # { name => 'title', oid => 25 }, # ] =back =head2 Transactions I =head2 Errors I =head1 LIMITATIONS =over =item * Does not support older versions of libpq or PostgreSQL. Currently only tested with version 17, but versions a bit older than that ought to work fine as well. Much older versions will certainly not work fine. =item * (Probably) not thread-safe. =item * Only supports the UTF-8 encoding for string columns (text, char, varchar, etc). When using the binary format (the default) this only works if your database encoding is UTF-8. Non-UTF-8 databases are still supported with the text format by setting `client_encoding=utf8` as part of the connection string or by manually switching to it after C: my $conn = FU::PG->connect(""); $conn->exec('SET client_encoding=utf8'); (But you're missing out on most features this module has to offer if you're stuck with the text format, so L might be a better choice in that case) =item * Only works with blocking (synchronous) calls, not very suitable for use in asynchronous frameworks unless you know your queries are fast and you have a low-latency connection with the Postgres server. =back Missing features (for now): I. =head1 SEE ALSO =over =item L The venerable Postgres driver for DBI. More stable, portable and battle-tested than this module, but type conversions may leave things to be desired. =item L A thin wrapper around libpq. Lacks many higher-level conveniences and does not support binary transfers (at the time of writing, but then again there's little benefit in dealing with the binary format in pure perl anyway). =back