Pg(3)

πŸ’– Pg(3) β€” the DBD::Pg glow-up πŸ’–

User Contributed Perl Documentation Β· Pg(3)

okay bestie, sit down, hydrate, because we're about to talk about the PostgreSQL database driver for the DBI module and it's actually iconic.


✨ NAME ✨

DBD::Pg β€” PostgreSQL database driver for the DBI module. yes that's the whole name, short and slay.


✨ SYNOPSIS ✨

use DBI;

$dbh = DBI->connect("dbi:Pg:dbname=$dbname", '', '', {AutoCommit => 0});
# The AutoCommit attribute should always be explicitly set

# For some advanced uses you may need PostgreSQL type values:
use DBD::Pg qw(:pg_types);

$dbh->do('INSERT INTO mytable(a) VALUES (42)');

$sth = $dbh->prepare('INSERT INTO mytable(a) VALUES (?)');
$sth->execute(42);

✨ VERSION ✨

this doc is documenting version 3.21.2 of the DBD::Pg module. periodt.


✨ DESCRIPTION ✨

DBD::Pg is a Perl module that teams up with the DBI module so you can get access to PostgreSQL databases. it's giving dynamic duo. 🫢


✨ MODULE DOCUMENTATION ✨

this documentation is describing the driver-specific behavior and restrictions β€” the stuff that's uniquely Pg's business. it is not meant to be your only reference though, bestie. no cap. in any case, consult the DBI documentation first! πŸ’…

also: latest DBI documentation. go look at it.


✨ THE DBI CLASS ✨

🌸 DBI Class Methods 🌸

connect

this method creates a database handle by connecting to a database, and it's the DBI equivalent of the new method. to connect to a Postgres database with the minimum of parameters, use this syntax:

$dbh = DBI->connect("dbi:Pg:dbname=$dbname", '', '', {AutoCommit => 0});

this connects to the database named in the $dbname variable on the default port (usually 5432) without any user authentication. no password, no drama. πŸ™ˆ

the following connect statement shows almost all possible parameters:

$dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$host;port=$port;options=$options",
                    $username,
                    $password,
                    {AutoCommit => 0, RaiseError => 1, PrintError => 0}
                   );

parameters containing unusual characters such as spaces must be wrapped in single quotes around the value, and single quotes and backslashes can be escaped with a backslash, e.g. "dbi:Pg:dbname='\'spacey\' name';host=$host".

if a parameter is not given, the connect() method will first look for specific environment variables, and then fall back to hard-coded defaults:

parameter    environment variable    hard coded default
------------------------------------------------------
host         PGHOST                  local domain socket
hostaddr     PGHOSTADDR              local domain socket
port         PGPORT                  5432
dbname*      PGDATABASE              current userid
options      PGOPTIONS               (none)
service      PGSERVICE               (none)
sslmode      PGSSLMODE               (none)

$username    PGUSER                  current userid
$password    PGPASSWORD              (none)

* May also use the aliases db or database

if the username and password values passed via connect() are undefined (as opposed to merely being empty strings), DBI will use the environment variables DBI_USER and DBI_PASS if they exist.

you can also connect by using a service connection file. πŸŽ€ service names can be defined in either a per-user service file or a system-wide file. if the same service name exists in both the user and the system file, the user file takes precedence. by default, the per-user service file is named ~/.pg_service.conf. on Microsoft Windows, it is named %APPDATA%\postgresql\.pg_service.conf (where %APPDATA% refers to the Application Data subdirectory in the user's profile). a different file name can be specified by setting the environment variable PGSERVICEFILE. the system-wide file is named pg_service.conf. the location of this file can be controlled by setting the PGSYSCONFDIR environment variable. to use one of the named services within the file, set the name by using either the service parameter or the environment variable PGSERVICE. note that when connecting this way, only the minimum parameters should be used. for example, to connect to a service named zephyr, you could use:

$dbh = DBI->connect("dbi:Pg:service=zephyr", '', '');

you could also set $ENV{PGSERVICE} to zephyr and connect like this:

$dbh = DBI->connect("dbi:Pg:", '', '');

the format of the pg_service.conf file is simply a bracketed service name, followed by one parameter per line in the format name=value. for example:

[zephyr]
dbname=winds
user=wisp
password=W$2Hc00YSgP
port=6543

there are four valid arguments to the sslmode parameter, which controls whether to use SSL to connect to the database:

  • disable: SSL connections are never used
  • allow: try non-SSL, then SSL
  • prefer: try SSL, then non-SSL
  • require: connect only with SSL
  • verify-ca: connect only with SSL and verify that the server certificate is issued by a trusted certificate authority (CA)
  • verify-full: connect only with SSL, verify that the server certificate is issued by a trusted CA, and verify that the server host name matches that in the certificate

the latter two options are only supported on Postgres version 8.4 or higher. πŸ‘‘

the sslrootcert parameter can be used to specify the complete path to a file containing the root certificate for the server (sslrootcert=/path/to/root.crt) or to use the certificates trusted by your OS (sslrootcert=system). other SSL-related connection parameters also can be specified and may need to be. refer to the PostgreSQL libpq SSL documentation at https://www.postgresql.org/docs/current/libpq-ssl.html for the complete list and the latest details on how to configure SSL connections.

for example, to specify that SSL is required for connecting to a host over the network and and to do full verification of the server's certificate, you might specify this:

$dbh = DBI->connect('dbi:Pg:dbname=foo;host=example.com;' .
  'sslmode=verify-full;sslrootcert=system',
  $username,
  $password,
  {AutoCommit => 0, RaiseError => 1});

you can also connect using sockets in a specific directory. πŸ¦‹ this may be needed if the server you are connecting to has a different default socket directory from the one used to compile DBD::Pg. use the complete path to the socket directory as the name of the host, like this:

$dbh = DBI->connect('dbi:Pg:dbname=foo;host=/var/tmp/socket',
  $username,
  $password,
  {AutoCommit => 0, RaiseError => 1});

the attribute hash can also contain a key named dbd_verbose, which simply calls $dbh->trace('DBD') after the handle is created. this attribute is not recommended, as it is clearer to simply explicitly call trace explicitly in your script. πŸ™…

connect_cached

$dbh = DBI->connect_cached("dbi:Pg:dbname=$dbname", $username, $password, \%options);

implemented by DBI, no driver-specific impact. it's just vibing in the background.

data_sources

@data_sources = $dbh->data_sources('Pg', \%attr);
@data_sources = DBI->data_sources('Pg', \%attr);

returns a list of available databases as DBI connection strings. πŸ’œ

unless the environment variable DBI_DSN is set, a connection will be attempted to the database postgres. the normal connection environment variables also apply, such as PGHOST, PGPORT, DBI_USER, DBI_PASS, and PGSERVICE.

the first argument should always be 'Pg'

the second argument is a list of options to append to the resulting connection strings.

for example, to specify an alternate port and host:

@data_sources = DBI->data_sources('Pg', 'port=5824;host=example.com');

🌸 Methods Common To All Handles 🌸

for all of the methods below, $h can be either a database handle ($dbh) or a statement handle ($sth). note that $dbh and $sth can be replaced with any variable name you choose: these are just the names most often used. another common variable used in this documentation is $rv, which stands for "return value". so when you see $rv, that's your lil return value bestie. 🫢

err

$rv = $h->err;

returns the error code from the last method called. for the connect method it returns PQstatus, which is a number used by libpq (the Postgres connection library). a value of 0 indicates no error (CONNECTION_OK), while any other number indicates a failed connection. the only other number commonly seen is 1 (CONNECTION_BAD). see the libpq documentation for the complete list of return codes.

in all other non-connect methods $h->err returns the PQresultStatus of the current handle. this is a number used by libpq and is one of:

0  Empty query string
1  A command that returns no data successfully completed.
2  A command that returns data successfully completed.
3  A COPY OUT command is still in progress.
4  A COPY IN command is still in progress.
5  A bad response was received from the backend.
6  A nonfatal error occurred (a notice or warning message)
7  A fatal error was returned: the last query failed.

errstr

$str = $h->errstr;

returns the last error that was reported by Postgres. this message is affected by the pg_errorlevel setting. 😭

state

$str = $h->state;

returns a five-character SQLSTATE code. success is indicated by a 00000 code, which gets mapped to an empty string by DBI. a code of S8006 indicates a connection failure, usually because the connection to the Postgres server has been lost. πŸ’€

while this method can be called as either $sth->state or $dbh->state, it is usually clearer to always use $dbh->state.

the list of codes used by PostgreSQL can be found at: http://www.postgresql.org/docs/current/static/errcodes-appendix.html

note that these codes are part of the SQL standard and only a small number of them will be used by PostgreSQL.

common codes:

00000 Successful completion
25P01 No active SQL transaction
25P02 In failed SQL transaction
S8006 Connection failure

trace

$h->trace($trace_settings);
$h->trace($trace_settings, $trace_filename);
$trace_settings = $h->trace;

changes the trace settings on a database or statement handle. the optional second argument specifies a file to write the trace information to. if no filename is given, the information is written to STDERR. note that tracing can be set globally as well by setting DBI->trace, or by using the environment variable DBI_TRACE. ✨

the value is either a numeric level or a named flag. for the flags that DBD::Pg uses, see parse_trace_flag.

trace_msg

$h->trace_msg($message_text);
$h->trace_msg($message_text, $min_level);

writes a message to the current trace output (as set by the trace method). if a second argument is given, the message is only written if the current tracing level is equal to or greater than the $min_level. conditional queen. πŸ’…

parse_trace_flag and parse_trace_flags

$h->trace($h->parse_trace_flags('SQL|pglibpq'));
$h->trace($h->parse_trace_flags('1|pgstart'));

## Simpler:
$h->trace('SQL|pglibpq');
$h->trace('1|pgstart');
my $value = DBD::Pg->parse_trace_flag('pglibpq');
DBI->trace($value);

The parse_trace_flags method is the girl who translates for you πŸ’… β€” she takes one or more named flags and turns them into a number you can hand straight to the "trace" method. DBD::Pg currently supports the DBI-specific flag, "SQL", plus all the ones listed below. No cap.

And bestie, you can combine flags with parse_trace_flags, which literally just calls "parse_trace_flag" on each item and smooshes the results together. Iconic.

Sometimes you wanna turn tracing on before you even connect to the database πŸ‘€ and the second example up there shows exactly how: "DBD::Pg->parse_trace_flags" hands you a number you can feed to "DBI->trace" before you've even made a database handle. Main character prep energy.

DBD::Pg supports the following trace flags:

  • SQL β€” Outputs all SQL statements. ⚠️ Note that the output provided will not necessarily be in a form suitable to passing directly to Postgres, because server-side prepared statements are used extensively by DBD::Pg. For maximum portability of output (but with a potential performance hit), use it with $dbh->{pg_server_prepare} = 0.
  • DBD β€” Turns on all non-DBI flags, aka only the ones that are specific to DBD::Pg (all those below which start with the letters 'pg').
  • pglibpq β€” Outputs the name of each libpq function (without arguments) immediately before running it. This is a great way to trace the flow of your program at a low level. This information is also output if the trace level is set to 4 or greater.
  • pgstart β€” Outputs the name of each internal DBD::Pg function, and other information such as the function arguments or important global variables, as each function starts. This information is also output if the trace level is set to 4 or greater.
  • pgend β€” Outputs a simple message at the very end of each internal DBD::Pg function. This is also output if the trace level is set to 4 or greater.
  • pgprefix β€” Forces each line of trace output to begin with the string "dbdpg: ". This helps to differentiate it from the normal DBI trace output.
  • pglogin β€” Outputs a message showing the connection string right before a new database connection is attempted, a message when the connection was successful, and a message right after the database has been disconnected. Also output if trace level is 5 or greater.

See the DBI section on TRACING for more information. 🫢


πŸ¦‹ func πŸ¦‹

DBD::Pg uses the "func" method to support a variety of functions. And psst β€” note that the name of the function comes last, after the arguments. Weird order, I know, but she's built different πŸ’…

🌸 table_attributes 🌸

$attrs = $dbh->func($table, 'table_attributes');

Use of the tables_attributes function is no longer recommended, bestie. Instead, you can use the more portable "column_info" and "primary_key" methods to access the same information.

The table_attributes method returns, for the given table argument, a reference to an array of hashes, each of which contains the following keys:

NAME        attribute name
TYPE        attribute type
SIZE        attribute size (-1 for variable size)
NULLABLE    flag nullable
DEFAULT     default value
CONSTRAINT  constraint
PRIMARY_KEY flag is_primary_key
REMARKS     attribute description

πŸ“ pg_lo_creat πŸ“

$lobjId = $dbh->pg_lo_creat($mode);

Creates a new large object and returns the object-id. $mode is a bitmask describing read and write access to the new object. This setting is ignored since Postgres version 8.1. But for backwards compatibility, however, you should set a valid mode anyway (see "pg_lo_open" for a list of valid modes).

Upon failure it returns "undef". This function cannot be used if AutoCommit is enabled. 🚨

The old way of calling large objects functions is deprecated: $dbh->func(.., 'lo_);

🌈 pg_lo_open 🌈

$lobj_fd = $dbh->pg_lo_open($lobjId, $mode);

Opens an existing large object and returns an object-descriptor for use in subsequent "pg_lo_*" calls. $mode is a bitmask describing read and write access to the opened object. It may be one of:

$dbh->{pg_INV_READ}
$dbh->{pg_INV_WRITE}
$dbh->{pg_INV_READ} | $dbh->{pg_INV_WRITE}

"pg_INV_WRITE" and "pg_INV_WRITE | pg_INV_READ" modes are identical β€” in both modes, the large object can be read from or written to. Reading from the object will provide the object as written in other committed transactions, along with any writes performed by the current transaction. Objects opened with "pg_INV_READ" cannot be written to. Reading from this object will provide the stored data at the time of the transaction snapshot which was active when "pg_lo_write" was called.

Returns "undef" upon failure. And bestie, listen: 0 is a perfectly correct (and common) object descriptor! 😭 So don't go treating a zero like it's a failure, it's literally fine. This function cannot be used if AutoCommit is enabled.

πŸ’œ pg_lo_write πŸ’œ

$nbytes = $dbh->pg_lo_write($lobj_fd, $buffer, $len);

Writes $len bytes of $buffer into the large object $lobj_fd. Returns the number of bytes written and "undef" upon failure. This function cannot be used if AutoCommit is enabled.

✨ pg_lo_read ✨

$nbytes = $dbh->pg_lo_read($lobj_fd, $buffer, $len);

Reads $len bytes into $buffer from large object $lobj_fd. Returns the number of bytes read and "undef" upon failure. This function cannot be used if AutoCommit is enabled.

πŸŽ€ pg_lo_lseek πŸŽ€

$loc = $dbh->pg_lo_lseek($lobj_fd, $offset, $whence);

Changes the current read or write location on the large object $obj_id. Currently $whence can only be 0 (which is L_SET). Returns the current location and "undef" upon failure. This function cannot be used if AutoCommit is enabled.

πŸ’… pg_lo_lseek64 πŸ’…

Backwards compatible alias for "pg_lo_lseek". Since DBD::Pg 3.16, that method handles 64-bit offsets if supported by the Perl and PostgreSQL versions in use. She grew up πŸ₯Ή

πŸ¦‹ pg_lo_tell πŸ¦‹

$loc = $dbh->pg_lo_tell($lobj_fd);

Returns the current read or write location on the large object $lobj_fd and "undef" upon failure. This function cannot be used if AutoCommit is enabled.

πŸ‘‘ pg_lo_tell64 πŸ‘‘

Backwards compatible alias for "pg_lo_tell". Since DBD::Pg 3.16, that method handles 64-bit offsets if supported by the Perl and PostgreSQL versions in use.

🌸 pg_lo_truncate 🌸

$loc = $dbh->pg_lo_truncate($lobj_fd, $len);

Truncates the given large object to the new size. Returns "undef" on failure, and 0 on success. This function cannot be used if AutoCommit is enabled.

πŸ“ pg_lo_truncate64 πŸ“

Backwards compatible alias for "pg_lo_truncate". Since DBD::Pg 3.16, that method handles 64-bit offsets if supported by the Perl and PostgreSQL versions in use.

πŸ”₯ pg_lo_close πŸ”₯

$lobj_fd = $dbh->pg_lo_close($lobj_fd);

Closes an existing large object. Returns true upon success and false upon failure. This function cannot be used if AutoCommit is enabled.

$ret = $dbh->pg_lo_unlink($lobjId);

Deletes an existing large object. Returns true upon success and false upon failure. This function cannot be used if AutoCommit is enabled.

🌈 pg_lo_import 🌈

$lobjId = $dbh->pg_lo_import($filename);

Imports a Unix file as a large object and returns the object id of the new object or "undef" upon failure.

⭐ pg_lo_import_with_oid ⭐

$lobjId = $dbh->pg_lo_import($filename, $OID);

Same as pg_lo_import, but attempts to use the supplied OID as the large object number. If this number is 0, it falls back to the behavior of pg_lo_import (which assigns the next available OID).

This is only available when DBD::Pg is compiled against a Postgres server version 8.4 or later. iykyk πŸ’…

🧚 pg_lo_export 🧚

$ret = $dbh->pg_lo_export($lobjId, $filename);

Exports a large object into a Unix file. Returns false upon failure, true otherwise.

πŸ’€ getfd πŸ’€

$fd = $dbh->func('getfd');

Deprecated, use $dbh->{pg_socket} instead. She's retired, let her rest πŸ™ˆ

πŸ’œ private_attribute_info πŸ’œ

$hashref = $dbh->private_attribute_info();
$hashref = $sth->private_attribute_info();

Returns a hash of all private attributes used by DBD::Pg, for either a database or a statement handle. Currently, all the hash values are undef. That's it, that's the whole vibe πŸŽ€

InactiveDestroy (boolean)

okay so bestie, if you set this to true, then the disconnect method will not be automatically called when the database handle goes out of scope. πŸ’…

This one is required if you're forking, and even then you have to tread so carefully, like walking in heels on ice πŸ₯Ώ β€” you must make sure that either the parent or the child (but not both!) handles all database calls from that point forwards, so that messages from the Postgres backend are only handled by one of the processes. If you don't set things up properly, you'll be seeing messages like "server closed the connection unexpectedly" and "message type 0x32 arrived from server while idle". 😭

The best solution is either to have the child process reconnect to the database with a fresh database handle, or to rewrite your application so it doesn't use forking at all. See the section on "Asynchronous Queries" for a way to have your script keep working while the database is processing a request. ✨

AutoInactiveDestroy (boolean)

The InactiveDestroy attribute (the one right above, yes that one) needs to be explicitly set in the child process after a fork. But if the code doing the forking lives in a third party module like Sys::Syslog, that's a whole problem. 😩 Use AutoInactiveDestroy to get around it. 🫢

RaiseError (boolean, inherited)

Forces errors to always raise an exception. It defaults to off, but it's highly recommended you turn it on, because the alternative is checking the return value of every single method (prepare, execute, fetch, etc.) manually, and bestie, that is so easy to forget. πŸ™ˆ

PrintError (boolean, inherited)

Forces database errors to also generate warnings, which you can then filter with methods such as locally redefining $SIG{__WARN__} or by using modules like "CGI::Carp". This attribute is on by default. πŸ‘‘

ShowErrorStatement (boolean, inherited)

Appends info about the current statement to error messages. If placeholder information is available, it adds that too. Defaults to false.

Heads up: this will not work when using "do" without any arguments.

Warn (boolean, inherited)

Enables warnings. This is on by default, and it should only be turned off inside a local block for a short time, and only when it's absolutely needed. πŸ’€

Executed (boolean, read-only)

Tells you if a handle has been executed. For database handles, this value is true after the "do" method has been called, or when one of the child statement handles has issued an "execute". Issuing a "commit" or "rollback" always resets the attribute to false for database handles. For statement handles, any call to "execute" or its variants flips the value to true for the lifetime of the statement handle. πŸ”₯

TraceLevel (integer, inherited)

Sets the trace level, just like the "trace" method. See the sections on "trace" and parse_trace_flag for more deets. ✨

Active (boolean, read-only)

Tells you if a handle is active or not. For database handles, it tells you if the database has been disconnected or not. For statement handles, it tells you if all the data has been fetched yet or not. Use of this attribute is not encouraged. πŸ™…

Kids (integer, read-only)

Returns the number of child processes created for each handle type. For a driver handle, it tells you the number of database handles created. For a database handle, it tells you the number of statement handles created. For statement handles, it always returns zero, because statement handles do not create kids. 🧚

ActiveKids (integer, read-only)

Same as "Kids", but it only returns the ones that are active. ⭐

CachedKids (hash ref)

Returns a hashref of handles. If you call it on a database handle, it returns all statement handles created by use of the "prepare_cached" method. If you call it on a driver handle, it returns all database handles created by the "connect_cached" method. 🌸

ChildHandles (array ref)

Implemented by DBI, no driver-specific impact. πŸ’œ

PrintWarn (boolean, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

HandleError (boolean, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

HandleSetErr (code ref, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

ErrCount (unsigned integer)

Implemented by DBI, no driver-specific impact. πŸ’œ

FetchHashKeyName (string, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

ChopBlanks (boolean, inherited)

Supported by DBD::Pg as proposed by DBI. This method is similar to the SQL function "RTRIM". βœ‚οΈ

Taint (boolean, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

TaintIn (boolean, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

TaintOut (boolean, inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

Profile (inherited)

Implemented by DBI, no driver-specific impact. πŸ’œ

Type (scalar)

Returns "dr" for a driver handle, "db" for a database handle, and "st" for a statement handle. You should rarely need this. 🀷

LongReadLen

Not used by DBD::Pg 🚫

LongTruncOk

Not used by DBD::Pg 🚫

CompatMode

Not used by DBD::Pg 🚫


🌈 DBI DATABASE HANDLE OBJECTS 🌈

Database Handle Methods

selectall_arrayref

$ary_ref = $dbh->selectall_arrayref($sql);
$ary_ref = $dbh->selectall_arrayref($sql, \%attr);
$ary_ref = $dbh->selectall_arrayref($sql, \%attr, @bind_values);

Returns a reference to an array containing the rows returned by preparing and executing the SQL string. See the DBI documentation for the full details, bestie. πŸ“š

selectall_hashref

$hash_ref = $dbh->selectall_hashref($sql, $key_field);

Returns a reference to a hash containing the rows returned by preparing and executing the SQL string. See the DBI documentation for the full details. πŸ“š

selectcol_arrayref

$ary_ref = $dbh->selectcol_arrayref($sql, \%attr, @bind_values);

Returns a reference to an array containing the first column from each of the rows returned by preparing and executing the SQL string. It's possible to specify exactly which columns to return. See the DBI documentation for the full details. πŸ“š

prepare

$sth = $dbh->prepare($statement, \%attr);
WARNING: DBD::Pg now (as of version 1.40) uses true prepared statements by sending them to the backend to be prepared by the Postgres server. Statements that were legal before may no longer work. See below for details. 😱

The prepare method prepares a statement for later execution. PostgreSQL supports prepared statements, which lets DBD::Pg send the query only once and then simply send the arguments for every subsequent call to "execute". DBD::Pg can use these server-side prepared statements, or it can just send the entire query to the server every single time. The best way is automatically chosen for each query. For most users this is gonna be enough: keep reading if you want a more detailed explanation and some optional flags. ✨

Queries that do not begin with the word "SELECT", "INSERT", "UPDATE", or "DELETE" are never sent as server-side prepared statements.

Deciding whether or not to use prepared statements depends on a bunch of factors, but you can force them to be used or not used by using the pg_server_prepare attribute when calling "prepare". Setting it to false means to never use prepared statements. Setting pg_server_prepare to true means that prepared statements should be used whenever possible. This is the default. πŸ’…

The pg_server_prepare attribute can also be set at connection time, like so:

$dbh = DBI->connect($DBNAME, $DBUSER, $DBPASS,
                    { AutoCommit => 0,
                      RaiseError => 1,
                      pg_server_prepare => 0,
                    });

or you can set it after your database handle is created:

$dbh->{pg_server_prepare} = 1;

To enable it for just one particular statement:

$sth = $dbh->prepare("SELECT id FROM mytable WHERE val = ?",
                     { pg_server_prepare => 1 });

You can even toggle between the two as you go:

$sth->{pg_server_prepare} = 1;
$sth->execute(22);
$sth->{pg_server_prepare} = 0;
$sth->execute(44);
$sth->{pg_server_prepare} = 1;
$sth->execute(66);

In the example above, the first execute will use the previously prepared statement. The second execute will not, but it'll build the query into a single string and send it to the server. The third one acts like the first and only sends the arguments. Even if you toggle back and forth, a statement is only prepared once. πŸ”

Using prepared statements is, in theory, quite a bit faster: not only does the PostgreSQL backend only have to prepare the query once, but DBD::Pg no longer has to worry about quoting each value before sending it to the server. ⚑

However, there are some drawbacks. The server cannot always choose the ideal parse plan, because it won't know the arguments beforehand. But for most situations where you'll be executing similar data many times, the default plan will probably work out fine. Programs such as PgBouncer which cache connections at a low level should not use prepared statements via DBD::Pg, or they must take extra care in the application to account for the fact that prepared statements are not shared across database connections. Further discussion on this subject is beyond the scope of this documentation: please consult the pgsql-performance mailing list, <http://archives.postgresql.org/pgsql-performance/> πŸ“¬

Only certain commands will be sent to a server-side prepare: currently these include "SELECT", "INSERT", "UPDATE", and "DELETE". DBD::Pg uses a simple naming scheme for the prepared statements themselves: dbdpg_XY_Z, where Y is the current PID, X is either 'p' or 'n' (depending on if the PID is a positive or negative number), and Z is a number that starts at 1 and increases each time a new statement is prepared. This number is tracked at the database handle level, so multiple statement handles will not collide. πŸ”’

You cannot send more than one command at a time in the same prepare command (by separating them with semi-colons) when using server-side prepares. 🚫

The actual "PREPARE" is usually not performed until the first execute is called, because information on the data types (provided by "bind_param") may be provided after the prepare but before the execute. πŸ•

A server-side prepare may happen before the first "execute", but only if the server can handle the server-side prepare, and the statement contains no placeholders. It will also be prepared if the pg_prepare_now attribute is passed in and set to a true value. Similarly, the pg_prepare_now attribute can be set to 0 to ensure that the statement is not prepared immediately, although the cases in which you'd want this are very rare. Finally, you can set the default behavior of all prepare statements by setting the pg_prepare_now attribute on the database handle:

$dbh->{pg_prepare_now} = 1;

The next two examples? Oh they get prepped immediately, no waiting:

$sth->prepare("SELECT 123"); ## no placeholders

$sth->prepare("SELECT 123, ?", {pg_prepare_now => 1});

And these two? Yeah no, they do not get prepared right away:

$sth->prepare("SELECT 123, ?"); ## has a placeholder

$sth->prepare("SELECT 123", {pg_prepare_now => 0});

Sometimes you're just gonna wanna prepare a statement yourself, bestie, and that's valid πŸ’…. Just send the PREPARE statement straight to the server (like, with the do method, easy). Make a statement handle and set the prepared name through the pg_prepare_name attribute. The statement handle can be built with a dummy statement since it won't actually get executed β€” but heads up, it needs to have the same number of placeholders as your prepared statement. Example time:

$dbh->do('PREPARE mystat AS SELECT COUNT(*) FROM pg_class WHERE reltuples < ?');
$sth = $dbh->prepare('SELECT ?');
$sth->bind_param(1, 1, SQL_INTEGER);
$sth->{pg_prepare_name} = 'mystat';
$sth->execute(123);

That runs the equivalent of this on the backend:

EXECUTE mystat(123);

which is the same vibe as:

SELECT COUNT(*) FROM pg_class WHERE reltuples < 123;

You can also force DBD::Pg to yeet your query straight at the server by adding the pg_direct attribute to your prepare call. It's not recommended, but it's there in case you need it, iykyk.


✨ Placeholders ✨

So there are three types of placeholders you can use in DBD::Pg, and let's go through them 🫢

The first one is the "question mark" type β€” every placeholder is just a single question mark character. This is the method the DBI specs recommend, it's the most portable, chef's kiss. Each question mark gets internally swapped for a "dollar sign number" in the order they show up in the query (super important when you're using bind_param).

The second type is "dollar sign numbers". This is what Postgres uses internally and honestly it's probably the best method overall if you don't need compatibility with other database systems. DBD::Pg, just like PostgreSQL, lets you use the same number more than once in the query. Numbers must start with 1 and go up by one value (but they can show up in any order in the query). If the same number appears more than once in a query, it's treated as a single parameter and all the instances get replaced at once. Examples, bestie:

Not legal πŸ‘Ž:

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages > $2'; # Does not start with 1

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages BETWEEN $1 AND $3'; # Missing 2

Legal βœ…:

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages > $1';

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages BETWEEN $1 AND $2';

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages BETWEEN $2 AND $1'; # legal but confusing

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages BETWEEN $1 AND $2 AND reltuples > $1';

$SQL = 'SELECT count(*) FROM pg_class WHERE relpages > $1 AND reltuples > $1';

In that last statement up there, DBI thinks there's only one placeholder, so this statement replaces both of them:

$sth->bind_param(1, 2045);

And a simple execute with no bind_param calls needs just a single argument too:

$sth->execute(2045);

The final placeholder type is "named parameters" in the format :foo. DBD::Pg does support this syntax, but ngl, its use is discouraged β€” dollar-sign numbers are the move.

The different types of placeholders cannot be mixed within a statement, but you can use different ones for each statement handle you have. That's confusing at best though, so just stick to one style throughout your program, periodt.

Now β€” if your queries use operators that contain question marks (like some of the native Postgres geometric operators and JSON operators) or array slices (like data[100:300]), there are methods to tell DBD::Pg not to treat some symbols as placeholders. First one: you can just slap a backslash before the start of a placeholder, and DBD::Pg will strip that backslash and not treat the character as a placeholder. Slay.

You can also tell DBD::Pg to ignore any non-dollar-sign placeholders by setting the pg_placeholder_dollaronly attribute at either the database handle or the statement handle level. Examples:

$dbh->{pg_placeholder_dollaronly} = 1;
$sth = $dbh->prepare(q{SELECT * FROM mytable WHERE lseg1 ?# lseg2 AND name = $1});
$sth->execute('segname');

Or you can set it at prepare time instead:

$sth = $dbh->prepare(q{SELECT * FROM mytable WHERE lseg1 ?-| lseg2 AND name = $1},
  {pg_placeholder_dollaronly => 1});
$sth->execute('segname');

If your queries use array slices but you still wanna use question marks as placeholders, you can tell DBD::Pg to ignore just the colon placeholders by setting the pg_placeholder_nocolons attribute the same way. Examples:

$dbh->{pg_placeholder_nocolons} = 1;
$sth = $dbh->prepare(q{SELECT array[1:2] FROM mytable WHERE id = ?});
$sth->execute(1);

And again, you can set it at prepare time too:

$sth = $dbh->prepare(q{SELECT array[1:2] FROM mytable WHERE id = ?},
  {pg_placeholder_nocolons => 1});
$sth->execute(1);
It should be noted that placeholders only work when used outside of a literal string context β€” like, the following examples will not define or use any placeholders because they show up inside strings within the SQL:
$sth = $dbh->prepare(q{SELECT id FROM mytable WHERE text LIKE '%?'});
$dbh->do(q{DO LANGUAGE plpgsql $$ BEGIN RAISE NOTICE ?; END $$}, undef, $message);

See the DBI placeholder documentation for more details. πŸ¦‹


🌸 prepare_cached 🌸

$sth = $dbh->prepare_cached($statement, \%attr);

Implemented by DBI, so there's no driver-specific impact here. This method is most useful when you're using a server that supports server-side prepares, and you've asked the prepare to happen immediately via the pg_prepare_now attribute. πŸ’–


πŸŽ€ do πŸŽ€

$rv = $dbh->do($statement);
$rv = $dbh->do($statement, \%attr);
$rv = $dbh->do($statement, \%attr, @bind_values);

Prepare and execute a single statement. Returns the number of rows affected if the query was successful, returns undef if an error happened, and returns -1 if the number of rows is unknown or not available. Little detail: this method returns 0E0 instead of 0 for "no rows were affected" β€” that's so it always returns a true value when no error occurred. Cute, right?

If neither \%attr nor @bind_values is given, the query gets sent straight to the server without the overhead of internally creating a statement handle and running prepare and execute β€” for a measurable speed increase. πŸ”₯

Note that an empty statement (a string with no length) will not be passed to the server. If you want a simple test, use SELECT 123 or the ping method.

πŸ’œ last_insert_id πŸ’œ

$rv = $dbh->last_insert_id(undef, $schema, $table, undef);
$rv = $dbh->last_insert_id(undef, $schema, $table, undef, {sequence => $seqname});

Attempts to return the id of the last value inserted into a table. You can either give a sequence name (preferred, bestie) or give a table name with an optional schema, and DBD::Pg will attempt to find the sequence itself. The current value of the sequence comes back from a call to the CURRVAL() PostgreSQL function. Heads up though: this will fail if the sequence hasn't been used yet in the current database connection. 😭

If you don't know the name of the sequence, you can hand over a table name and DBD::Pg will try to return the correct value. For that to work, there needs to be at least one column in the table with a NOT NULL constraint that has a unique constraint, and which uses a sequence as a default value (either manually, or via the SERIAL pseudotype or GENERATED ... AS IDENTITY). If more than one column meets these conditions, the primary key gets used. This involves some looking-up of things in the system table, so DBD::Pg will cache the sequence name for subsequent calls. If you need to disable this caching for some reason (like the sequence name changing), you can control it by adding pg_cache => 0 to the final (hashref) argument for last_insert_id.

Please keep in mind that this method is far from foolproof, so make your script use it properly. Specifically, make sure it's called immediately after the insert, and that the insert doesn't add a value to the column that's using the sequence as a default value. That said, because we're using sequences, you can be sure the value you got back hasn't been used by any other process. πŸ‘‘

Some examples:

$dbh->do('CREATE SEQUENCE lii_seq START 1');
$dbh->do(q{CREATE TABLE lii (
  foobar INTEGER NOT NULL UNIQUE DEFAULT nextval('lii_seq'),
  baz VARCHAR)});
$SQL = 'INSERT INTO lii(baz) VALUES (?)';
$sth = $dbh->prepare($SQL);
for (qw(uno dos tres cuatro)) {
  $sth->execute($_);
  my $newid = $dbh->last_insert_id(undef,undef,undef,undef,{sequence=>'lii_seq'});
  print "Last insert id was $newid\n";
}

If you did not want to worry about the sequence name:

$dbh->do('CREATE TABLE lii2 (
  foobar SERIAL UNIQUE,
  baz VARCHAR)');
$SQL = 'INSERT INTO lii2(baz) VALUES (?)';
$sth = $dbh->prepare($SQL);
for (qw(uno dos tres cuatro)) {
  $sth->execute($_);
  my $newid = $dbh->last_insert_id(undef,undef,"lii2",undef);
  print "Last insert id was $newid\n";
}

Alternatively, using RETURNING:

$dbh->do('CREATE TABLE lii2 (
  foobar SERIAL UNIQUE,
  baz VARCHAR)');
$SQL = 'INSERT INTO lii2(baz) VALUES (?) RETURNING foobar';
$sth = $dbh->prepare($SQL);
for (qw(uno dos tres cuatro)) {
  $sth->execute($_);
  my ($newid) = $sth->fetchrow_array;
  print "Last insert id was $newid\n";
}

🌈 commit 🌈

$rv = $dbh->commit;

Issues a COMMIT to the server, signalling that the current transaction is done and that all changes made will be visible to other processes. If AutoCommit is enabled, then a warning is given and no COMMIT is issued. Returns true on success, false on error. See also the section on Transactions. ✨


⭐ rollback ⭐

$rv = $dbh->rollback;

Issues a ROLLBACK to the server, which discards any changes made in the current transaction. If AutoCommit is enabled, then a warning is given and no ROLLBACK is issued. Returns true on success, and false on error. See also the section on Transactions.


🧚 begin_work 🧚

This method turns on transactions until the next call to commit or rollback, if AutoCommit is currently enabled. If it's not enabled, calling begin_work will issue an error. Note that the transaction won't actually begin until the first statement after begin_work is called. Example:

         $dbh->{AutoCommit} = 1;
         $dbh->do('INSERT INTO foo VALUES (123)'); ## Changes committed immediately
         $dbh->begin_work();
         ## Not in a transaction yet, but AutoCommit is set to 0

         $dbh->do("INSERT INTO foo VALUES (345)");
         ## DBD::PG actually issues two statements here:
         ## BEGIN;
         ## INSERT INTO foo VALUES (345)
         ## We are now in a transaction

         $dbh->commit();
         ## AutoCommit is now set to 1 again

πŸ’… disconnect

$rv = $dbh->disconnect;

okay so this one dips out of the Postgres database entirely. and bestie, heads up: any uncommitted changes get rolled back the second you disconnect. the vibe is β€” always, ALWAYS explicitly call commit or rollback at some point before you disconnect. don't just trust the default rollback behavior to save you, that's giving "I'll do it tomorrow" energy and tomorrow never comes. 🫠

this method might hit you with a warning like "disconnect invalidates X active statement handle(s)". what that means is you called $sth->execute() but never finished fetching all the rows from them. to make the warning go away, either fetch every last row or call $sth->finish() on each executed statement handle. no cap. πŸ’…

and if your script just exits before disconnect gets called β€” or more precisely, if the database handle is no longer referenced by anything β€” then the database handle's DESTROY method will call the rollback() and disconnect() methods automatically. but like… explicitly disconnect instead of relying on that. it's the difference between leaving the party properly and just vanishing. 🌈


πŸŽ€ quote

$rv = $dbh->quote($value, $data_type);

this module implements its own quote method, she's independent like that ✨. for simple string types, both backslashes and single quotes get doubled. you can also quote arrayrefs and receive a string suitable for passing into Postgres array columns. iconic behavior honestly. πŸ’–

if the value contains backslashes, and the server is version 8.1 or higher, then the escaped string syntax will be used β€” which places a capital E before the first single quote. this syntax is always used when quoting bytea values on servers 8.1 and higher.

the data_type argument is optional and should be one of the type constants exported by DBD::Pg (such as PG_BYTEA). in addition to string, bytea, char, bool, and other standard types, the following geometric types are supported: point, line, lseg, box, path, polygon, and circle β€” that's PG_POINT, PG_LINE, PG_LSEG, PG_BOX, PG_PATH, PG_POLYGON, and PG_CIRCLE respectively. 🌸 to quote a Postgres-specific data type, you MUST use a 'hashref' argument like so:

my $quotedval = $dbh->quote($value, { pg_type => PG_VARCHAR });
NOTE: the undocumented (and invalid) support for the SQL_BINARY data type is officially deprecated. use PG_BYTEA with bind_param() instead: $rv = $sth->bind_param($param_num, $bind_value, { pg_type => PG_BYTEA });

πŸ¦‹ quote_identifier

$string = $dbh->quote_identifier( $name );
$string = $dbh->quote_identifier( undef, $schema, $table);

returns a quoted version of the supplied string, which is commonly a schema, table, or column name. the three argument form will return the schema and the table together, separated by a dot. examples, because examples are everything:

print $dbh->quote_identifier('grapefruit'); ## Prints: "grapefruit"

print $dbh->quote_identifier('juicy fruit'); ## Prints: "juicy fruit"

print $dbh->quote_identifier(undef, 'public', 'pg_proc');
## Prints: "public"."pg_proc"

🧚 pg_notifies

$ret = $dbh->pg_notifies;

looks for any asynchronous notifications received and returns either undef or a reference to a three-element array consisting of an event name, the PID of the backend that sent the NOTIFY command, and the optional payload string. πŸ’œ

ngl, important caveat: this does not check if the connection to the database is still valid first β€” for that, use the ping method. and you may need to commit if you're not in autocommit mode, because new notices will not be picked up while you're in the middle of a transaction. πŸ™ˆ an example:

$dbh->do("LISTEN abc");
$dbh->do("LISTEN def");

## Hang around until we get the message we want
LISTENLOOP: {
  while (my $notify = $dbh->pg_notifies) {
    my ($name, $pid, $payload) = @$notify;
    print qq{I received notice "$name" from PID $pid, payload was "$payload"\n};
    ## Do something based on the notice received
  }
  $dbh->ping() or die qq{Ping failed!};
  $dbh->commit();
  sleep(5);
  redo;
}

payloads will always be an empty string unless you're connecting to a Postgres server version 9.0 or higher. just so you know bestie πŸ’–


⭐ ping

$rv = $dbh->ping;

the ping method determines if there is a working connection to an active database server. it does this by sending a small query to the server, currently 'DBD::Pg ping test v3.21.2'. it returns 0 (false) if the connection is not valid, otherwise it returns a positive number (true). it should never throw an exception, periodt. πŸ”₯

the value returned indicates the current state:

  • 1 β€” database is idle (not in a transaction)
  • 2 β€” database is active, there is a command in progress (usually seen after a COPY command)
  • 3 β€” database is idle within a transaction
  • 4 β€” database is idle, within a failed transaction

want extra info on why a handle isn't valid? use the pg_ping method. πŸ‘‘


🌈 pg_ping

$rv = $dbh->pg_ping;

this is a DBD::Pg-specific extension to the ping method. it checks the validity of a database handle in exactly the same way as ping, but instead of returning a 0 for an invalid connection, it returns a negative number. so in addition to returning the positive numbers documented for ping, it may also return the following:

  • -1 β€” there is no connection to the database at all (e.g. after disconnect)
  • -2 β€” an unknown transaction status was returned (e.g. after forking)
  • -3 β€” the test query failed (PQexec returned null)
  • -4 β€” PQstatus returned a CONNECTION_BAD

πŸ’€ pg_error_field

$value = $dbh->pg_error_field('context');

pg_error_field returns specific information about the last error that occurred. it needs to be called as soon as possible after an error occurs, because any other query sent to Postgres (via $dbh or $sth) will reset all the error information. gone. poof. 😭

note that this is called at the database handle ($dbh) level, but it can return errors that occurred via both database handles (e.g. $dbh->do) and statement handles (e.g. $sth->execute). it takes a single argument, indicating which field to return. the value returned will be undef if the previous command was not an error, or if the field is not applicable to the current error.

the canonical list of field types can be found at:

https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQRESULTERRORFIELD

the literal names on that page can be used (e.g. PG_DIAG_STATEMENT_HINT), but lowercase is accepted too, as well as the following abbreviated forms:

  • severity
  • severity_nonlocal (only for Postgres 10 and above)
  • state
  • primary
  • detail (does not work well for Postgres < 9.2)
  • hint
  • statement_position
  • internal_position
  • internal_query
  • context
  • schema (only for Postgres 9.3 and above)
  • table (only for Postgres 9.3 and above)
  • column (only for Postgres 9.3 and above)
  • type (only for Postgres 9.3 and above)
  • constraint (only for Postgres 9.3 and above)
  • source_file
  • source_line
  • source_function

πŸ’… get_info

$value = $dbh->get_info($info_type);

supports a very large set (> 250) of the information types, including the minimum recommended by DBI. she's thorough like that. πŸŽ€

items of note:

SQL_KEYWORDS

this returns all items reserved by Postgres but NOT reserved by SQL:2011 standard. see:

http://www.postgresql.org/docs/current/static/sql-keywords-appendix.htm


πŸ“ table_info

$sth = $dbh->table_info(undef, $schema, $table, $type);

returns all tables and views visible to the current user. the schema and table arguments will do a "LIKE" search if a percent sign ("%") or an underscore ("_") is detected in the argument. the $type argument accepts any comma-separated combination of "TABLE", "VIEW", "SYSTEM TABLE", "SYSTEM VIEW", "MATERIALIZED VIEW", "SYSTEM MATERIALIZED VIEW", "FOREIGN TABLE", "SYSTEM FOREIGN TABLE", or "LOCAL TEMPORARY". (using all is the default action.)

note that a statement handle is returned, and not a direct list of tables. see the examples below for ways to handle this. 🫢

the following fields are returned:

  • TABLE_CAT: the name of the database that the table or view is in (always the current database).
  • TABLE_SCHEM: the name of the schema that the table or view is in.
  • TABLE_NAME: the name of the table or view.
  • TABLE_TYPE: the type of object returned. will be one of "TABLE", "VIEW", "MATERIALIZED VIEW", "SYSTEM VIEW", "SYSTEM MATERIALIZED VIEW", "SYSTEM TABLE", "FOREIGN TABLE", "SYSTEM FOREIGN TABLE", or "LOCAL TEMPORARY".

the TABLE_SCHEM and TABLE_NAME will be quoted via quote_ident().

four additional fields specific to DBD::Pg are returned:

  • pg_schema: the unquoted name of the schema
  • pg_table: the unquoted name of the table
  • pg_tablespace_name: the name of the tablespace the table is in
  • pg_tablespace_location: the location of the tablespace the table is in

tables that have not been assigned to a particular tablespace (or views) will return NULL ("undef") for both of the above field. πŸ’œ

rows are returned alphabetically, with all tables first, and then all views.

examples of use:

## Display all tables and views in the public schema:
$sth = $dbh->table_info('', 'public', undef, undef);
for my $rel (@{$sth->fetchall_arrayref({})}) {
  print "$rel->{TABLE_TYPE} name is $rel->{TABLE_NAME}\n";
}

# Display the schema of all tables named 'foo':
$sth = $dbh->table_info('', undef, 'foo', 'TABLE');
for my $rel (@{$sth->fetchall_arrayref({})}) {
  print "Table name is $rel->{TABLE_SCHEM}.$rel->{TABLE_NAME}\n";
}

🌸 column_info

$sth = $dbh->column_info( undef, $schema, $table, $column );

supported by this driver as proposed by DBI, with the following exceptions. these fields always return NULL ("undef"):

  • BUFFER_LENGTH
  • NUM_PREC_RADIX
  • SQL_DATA_TYPE
  • SQL_DATETIME_SUB
  • CHAR_OCTET_LENGTH

seven additional non-standard fields are returned:

  • pg_type: data type with additional info i.e. "character varying(20)"
  • pg_constraint: shows CHECK constraints which reference the column (multiple constraints are newline separated)
  • pg_database: the unquoted name of the database
  • pg_schema: the unquoted name of the schema
  • pg_table: the unquoted name of the table
  • pg_column: the unquoted name of the column
  • pg_enum_values: an array reference of allowed values for an enum column

Quick note before we go any further, bestie: the TABLE_CAT, TABLE_SCHEM, TABLE_NAME, and COLUMN_NAME fields all come back to you wrapped in quote_ident(). If you want the unquoted version, reach for the pg_ fields above instead. That's the whole vibe. πŸ’…


πŸŽ€ primary_key_info πŸŽ€

$sth = $dbh->primary_key_info( undef, $schema, $table, \%attr );

Supported by this driver as proposed by DBI. So here's the deal: no search patterns allowed, but if you leave the $schema argument blank, it'll just use the first table it finds in the schema search path. Iconic, honestly. There's an extra field, "DATA_TYPE", that gets returned and shows the data type for each of the arguments in the "COLUMN_NAME" field.

This method will also hand you tablespace information for servers that support tablespaces. Peep the "table_info" entry for more on that. πŸ¦‹

Five additional fields come back too, slay:

  • pg_tablespace_name β€” name of the tablespace, if any
  • pg_tablespace_location β€” location of the tablespace
  • pg_schema β€” the unquoted name of the schema
  • pg_table β€” the unquoted name of the table
  • pg_column β€” the unquoted name of the column or columns

On top of the standard format of returning one row for each column found for the primary key, you can pass the "pg_onerow" attribute to force a single row to be used. If the primary key has multiple columns, the "KEY_SEQ", "COLUMN_NAME", and "DATA_TYPE" fields will return a comma-delimited string. And if the "pg_onerow" attribute is set to "2", those fields get returned as an arrayref, which is lowkey useful when multiple columns are involved:

$sth = $dbh->primary_key_info('', '', 'dbd_pg_test', {pg_onerow => 2});
if (defined $sth) {
  my $pk = $sth->fetchall_arrayref()->[0];
  print "Table $pk->[2] has a primary key on these columns:\n";
  for (my $x=0; defined $pk->[3][$x]; $x++) {
    print "Column: $pk->[3][$x]  (data type: $pk->[6][$x])\n";
  }
}

πŸ’– primary_key πŸ’–

@key_column_names = $dbh->primary_key(undef, $schema, $table);

Simple little interface to the "primary_key_info" method. Returns a list of the column names that make up the primary key of the specified table. The list is in primary key column sequence order, no cap. And if there's no primary key? You get an empty list back. That's it, that's the whole method. 🫢


✨ foreign_key_info ✨

$sth = $dbh->foreign_key_info( $pk_catalog, $pk_schema, $pk_table,
                               $fk_catalog, $fk_schema, $fk_table );

Supported by this driver as proposed by DBI, using the SQL/CLI variant. Again: no search patterns allowed, but leaving the $schema argument blank will cause the first table found in the schema search path to be used. Two additional fields, "UK_DATA_TYPE" and "FK_DATA_TYPE", get returned to show the data type for the unique and foreign key columns. And heads up β€” foreign keys that have no named constraint (where the referenced column only has an unique index) will return "undef" for the "UK_NAME" field. πŸ’€


🌈 statistics_info 🌈

$sth = $dbh->statistics_info( undef, $schema, $table, $unique_only, $quick );

Returns a statement handle you can fetch from to get statistics information on a specific table and its indexes. The $table argument is mandatory. The $schema argument is optional but recommended (do it, bestie). The $unique_only argument, if true, makes it so only information about unique indexes comes back. The $quick argument is not used by DBD::Pg. For the format of the standard rows returned, please see the DBI documentation β€” the DBI section on statistics_info, iykyk.

On top of all that, these Postgres-specific columns also get returned:

pg_expression

Postgres allows indexes on functions and scalar expressions based on one or more columns. This field will always be populated if this is an index row. The lack of an entry in the COLUMN_NAME should indicate that this is an index expression.

pg_is_key_column

Postgres (since version 11) allows including non-key columns in indexes so they can be retrieved by index-only scans. This field will be false for such columns, and true for normal index columns.

pg_null_ordering

In addition to "ASC" and "DESC", Postgres supports specifying "NULLS FIRST" or "NULLS LAST" for index columns. For columns of indexes that support ordering, this field will be "first" or "last", otherwise it will be "undef";


πŸ¦‹ tables πŸ¦‹

@names = $dbh->tables( undef, $schema, $table, $type, \%attr );

Supported by this driver as proposed by DBI. This method returns all tables and/or views (including foreign tables and materialized views) which are visible to the current user: see "table_info" for more info about the arguments. The name of the schema appears before the table or view name. You can turn that off by adding in the "pg_noprefix" attribute:

my @tables = $dbh->tables( '', '', 'dbd_pg_test', '', {pg_noprefix => 1} );

πŸ’œ type_info_all πŸ’œ

$type_info_all = $dbh->type_info_all;

Supported by this driver as proposed by DBI. Information is only provided for SQL datatypes and for frequently used datatypes. The mapping between the PostgreSQL typename and the SQL92 datatype (if possible) has been done according to this list right here β€” mapping the typname on the left to the SQL92 type on the right:

  • bool β†’ BOOL
  • text β†’ /
  • bpchar β†’ CHAR(n)
  • varchar β†’ VARCHAR(n)
  • int2 β†’ SMALLINT
  • int4 β†’ INT
  • int8 β†’ BIGINT
  • money β†’ /
  • float4 β†’ FLOAT(p) p<7=float4, p<16=float8
  • float8 β†’ REAL
  • abstime β†’ /
  • reltime β†’ /
  • tinterval β†’ /
  • date β†’ /
  • time β†’ /
  • datetime β†’ /
  • timespan β†’ TINTERVAL
  • timestamp β†’ TIMESTAMP

🌸 type_info 🌸

@type_info = $dbh->type_info($data_type);

Returns a list of hash references holding information about one or more variants of $data_type. See the DBI documentation for more details, bestie.


⭐ pg_server_trace ⭐

$dbh->pg_server_trace($filehandle);

Writes debugging information from the PostgreSQL backend to a file. This is not related to the DBI "trace" method, and you should not use this method unless you know what you are doing. And if you do enable it, be aware that the file will grow very large, very quick. To stop logging to the file, use the "pg_server_untrace" method. The first argument must be a file handle, not a filename. Example:

my $pid = $dbh->{pg_pid};
my $file = "pgbackend.$pid.debug.log";
open(my $fh, ">$file") or die qq{Could not open "$file": $!\n};
$dbh->pg_server_trace($fh);
## Run code you want to trace here
$dbh->pg_server_untrace;
close($fh);

πŸŽ€ pg_server_untrace πŸŽ€

$dbh->pg_server_untrace;

Stop server logging to a previously opened file. Short, sweet, iconic. πŸ’…


πŸ“ selectrow_array πŸ“

@row_ary = $dbh->selectrow_array($sql);
@row_ary = $dbh->selectrow_array($sql, \%attr);
@row_ary = $dbh->selectrow_array($sql, \%attr, @bind_values);

Returns an array of row information after preparing and executing the provided SQL string. The rows come back by calling "fetchrow_array". The string can also be a statement handle generated by a previous prepare. Now listen β€” only the first row of data is returned. And if you call it in a scalar context, only the first column of the first row comes back. Because this is not portable, it's not recommended that you use this method that way. fr fr.


🧚 selectrow_arrayref 🧚

$ary_ref = $dbh->selectrow_arrayref($statement);
$ary_ref = $dbh->selectrow_arrayref($statement, \%attr);
$ary_ref = $dbh->selectrow_arrayref($statement, \%attr, @bind_values);

Exactly the same as "selectrow_array", except that it returns a reference to an array, by internal use of the "fetchrow_arrayref" method. Chef's kiss.


πŸ’– selectrow_hashref πŸ’–

$hash_ref = $dbh->selectrow_hashref($sql);
$hash_ref = $dbh->selectrow_hashref($sql, \%attr);
$hash_ref = $dbh->selectrow_hashref($sql, \%attr, @bind_values);

Exactly the same as "selectrow_array", except that it returns a reference to an hash, by internal use of the "fetchrow_hashref" method. 🫢


✨ clone ✨

$other_dbh = $dbh->clone();

Creates a copy of the database handle by connecting with the same parameters as the original handle, then trying to merge the attributes. See the DBI documentation for complete usage.


πŸ‘‘ pg_continue_connect πŸ‘‘

$rc = $dbh->pg_continue_connect();

Continues an asynchronous connect operation. See Asynchronous Connect below. After an asynchronous connect was initiated, this method must be called in a loop for as long as it returns either 1 or 2, indicating a desire to read or write data, respectively. Afterwards, the next call to pg_continue_connect must not take place until an indication that data can either be read or written on the current pg_socket was obtained (e.g. via select).

The method returns -1 if no asynchronous connect was in progress, -2 to indicate that an asynchronous connect failed, and 0 if the connection was successfully established. The socket may have changed after each call to the method, so don't get too attached. 🌈


πŸ’… Database Handle Attributes πŸ’…

AutoCommit (boolean)

Supported by DBD::Pg as proposed by DBI. According to the classification of DBI, PostgreSQL is a database in which a transaction must be explicitly started. Without starting a transaction, every change to the database becomes immediately permanent. The default of AutoCommit is on, but this may change in the future, so it's highly recommended that you explicitly set it when calling "connect". For details, see the notes about "Transactions" elsewhere in this document.

ParamValues (hash ref, read-only)

Ignored unless inside a "do" method call. There it is temporarily aliased to the "ParamValues" hash from the temporary statement handle inside an internal "prepare / execute / fetch" routine, invisible from outside, and is treated correspondingly (see "ParamValues" in "Statement Handle Attributes"). This allows for correct reporting of values bound to placeholders to the caller, should the query fail (see "ShowErrorStatement").

pg_bool_tf (boolean)

  • the next one up β€” when it's true, boolean values come back as the characters 't' and 'f' instead of '1' and '0'. And on Perl 5.36 and newer, distinguished boolean values (peep "is_bool" in builtin, bestie) also get sent as 't' and 'f' when you use them as placeholder values. glow up fr ✨
  • ReadOnly (boolean) β€” okay so:
$dbh->{ReadOnly} = 1;

This one decides whether your current database connection is in read-only mode or not. In read-only mode, changes that change the database are not allowed and will throw an error. πŸ’€ Heads up though: this method will not work if "AutoCommit" is true. The read-only effect gets accomplished by sending a SET TRANSACTION READ ONLY after every begin. For more details, please see:

http://www.postgresql.org/docs/current/interactive/sql-set-transaction.html

And please note that this method is not foolproof β€” there are still ways to update the database. Consider it a safety net to catch applications that should not be issuing commands such as INSERT, UPDATE, or DELETE. πŸ₯…

This method requires DBI version 1.55 or better.

  • pg_server_prepare (boolean) β€” DBD::Pg specific attribute. Tells you whether DBD::Pg should attempt to use server-side prepared statements. The default value, true, means prepared statements should be used whenever possible. See the section on the "prepare" method for more info. πŸ‘‘
  • pg_switch_prepared (integer) β€” DBD::Pg specific attribute. Says when DBD::Pg will internally switch from using PQexecParams to PQexecPrepared. In other words, when it starts using server-side prepared statements (assuming all the other requirements for them are met, obviously). The default value, 2, means a prepared statement will be prepared and used the second and subsequent time execute is called. To always use PQexecPrepared instead of PQexecParams, set pg_switch_prepared to 1 (this was the default behavior in earlier versions, iykyk). Setting pg_switch_prepared to 0 will force DBD::Pg to always use PQexecParams. πŸ”€
  • pg_placeholder_dollaronly (boolean) β€” DBD::Pg specific attribute. Defaults to false. When true, question marks inside of statements are not treated as placeholders. Useful for statements that contain unquoted question marks, like geometric operators. Note that you may also simply escape question marks with a backslash to prevent them from being treated as placeholders. πŸ™ˆ
  • pg_placeholder_nocolons (boolean) β€” DBD::Pg specific attribute. Defaults to false. When true, colons inside of statements are not treated as placeholders. Useful for statements that contain an array slice. You may also place a backslash directly before the colon to prevent it from being treated as a placeholder. 🫢
  • pg_enable_utf8 (integer) β€” DBD::Pg specific attribute. The behavior of DBD::Pg with regards to this flag has changed as of version 3.0.0. The default value for this attribute, -1, tells DBD::Pg to UTF8-decode all strings coming back from the database if the client_encoding is set to "UTF8". Use of this default is highly encouraged πŸ’–. If your code was previously using pg_enable_utf8, you can probably remove mention of it entirely.

If this attribute is set to 0, then DBD::Pg will never UTF8-decode returned data, regardless of the current client_encoding.

If this attribute is set to 1, then DBD::Pg will always UTF8-decode returned data, regardless of the current client_encoding (with the exception of bytea data).

Note that the value of client_encoding is only checked on connection time. If you change the client_encoding to/from 'UTF8' after connecting, you can set pg_enable_utf8 to -1 to force DBD::Pg to read in the new client_encoding and act accordingly. πŸŒ€

  • pg_int8_as_string (integer) β€” DBD::Pg specific attribute. Since version 3.0.0 the processing of SQL_INT8 has changed; before that, 64 bit values were returned as strings, and starting from version 3.0.0 64 bit values are returned as numbers. This flag makes it possible to return the old behavior. The old behavior is useful when encoding the results of a call in JSON format and passing it to JavaScript for processing, where integer values have a precision of no more than 53 bits. the more you know 🌈
  • pg_skip_deallocate (integer) β€” DBD::Pg specific attribute. By default this is false, and causes prepared statements created by us to be deallocated when no longer needed (i.e. when the handle is destroyed). By setting this to true, this deallocation is skipped entirely. This is useful when there is something else taking over responsibility for prepared statements. 🧹
  • pg_errorlevel (integer) β€” DBD::Pg specific attribute. Sets the amount of information returned by the server's error messages. Valid entries are 0, 1, and 2. Any other number will be forced to the default value of 1.

A value of 0 ("TERSE") will show severity, primary text, and position only and will usually fit on a single line. A value of 1 ("DEFAULT") will also show any detail, hint, or context fields. A value of 2 ("VERBOSE") will show all available information. πŸ“’

  • pg_lib_version (integer, read-only) β€” DBD::Pg specific attribute. Indicates which version of PostgreSQL that DBD::Pg was compiled against. In other words, which libraries were used. Returns a number with major, minor, and revision together; version 8.1.4 would be returned as 80104. πŸ”’
  • pg_server_version (integer, read-only) β€” DBD::Pg specific attribute. Indicates which version of PostgreSQL that the current database handle is connected to. Returns a number with major, minor, and revision together; version 8.0.1 would be 80001.
  • Name (string, read-only) β€” Returns the name of the current database. This is the same as the DSN, without the "dbi:Pg:" part. Before version 2.0.0, this only returned the bare database name (e.g. 'foo'). From version 2.0.0 onwards, it returns the more correct output (e.g. 'dbname=foo'). growth πŸ’…
  • Username (string, read-only) β€” Returns the name of the user connected to the database.
  • pg_db (string, read-only) β€” DBD::Pg specific attribute. Returns the name of the current database.
  • pg_user (string, read-only) β€” DBD::Pg specific attribute. Returns the name of the user that connected to the server.
  • pg_host (string, read-only) β€” DBD::Pg specific attribute. Returns the host of the current server connection. Locally connected hosts will return an empty string. 🏠
  • pg_port (integer, read-only) β€” DBD::Pg specific attribute. Returns the port of the connection to the server.
  • pg_socket (integer, read-only) β€” DBD::Pg specific attribute. Returns the file description number of the connection socket to the server. πŸ”Œ
  • pg_pass (string, read-only) β€” DBD::Pg specific attribute. Returns the password used to connect to the server. 🀫
  • pg_options (string, read-only) β€” DBD::Pg specific attribute. Returns the command-line options passed to the server. May be an empty string.
  • pg_default_port (integer, read-only) β€” DBD::Pg specific attribute. Returns the default port used if none is specifically given.
  • pg_pid (integer, read-only) β€” DBD::Pg specific attribute. Returns the process id (PID) of the backend server process handling the connection. πŸ†”
  • pg_prepare_now (boolean) β€” DBD::Pg specific attribute. Default is off. If true, then the "prepare" method will immediately prepare commands, rather than waiting until the first execute. ⏱️
  • pg_expand_array (boolean) β€” DBD::Pg specific attribute. Defaults to true. If false, arrays returned from the server will not be changed into a Perl arrayref, but remain as a string. 🧺
  • pg_async_status (integer, read-only) β€” DBD::Pg specific attribute. Returns the current status of an asynchronous command. 0 indicates no asynchronous command is in progress, 1 indicates that an asynchronous command has started and -1 indicated that an asynchronous command has been cancelled. 🚦
  • pg_standard_conforming_strings (boolean, read-only) β€” DBD::Pg specific attribute. Returns true if the server is currently using standard conforming strings. Only available if the target server is version 8.2 or better.
  • pg_INV_READ (integer, read-only) β€” Constant to be used for the mode in "pg_lo_creat" and "pg_lo_open".
  • pg_INV_WRITE (integer, read-only) β€” Constant to be used for the mode in "pg_lo_creat" and "pg_lo_open".
  • Driver (handle, read-only) β€” Holds the handle of the parent driver. The only recommended use for this is to find the name of the driver using:
$dbh->{Driver}->{Name}
  • pg_protocol (integer, read-only) β€” DBD::Pg specific attribute. Returns the version of the PostgreSQL server. If DBD::Pg is unable to figure out the version, it will return a "0". Otherwise, a "3" is returned.
  • RowCacheSize β€” Not used by DBD::Pg. literally just vibing there, ignore her πŸ«₯

πŸŽ€ DBI STATEMENT HANDLE OBJECTS πŸŽ€

✨ Statement Handle Methods ✨

bind_param πŸͺ’

$rv = $sth->bind_param($param_num, $bind_value);
$rv = $sth->bind_param($param_num, $bind_value, $bind_type);
$rv = $sth->bind_param($param_num, $bind_value, \%attr);

Allows the user to bind a value and/or a data type to a placeholder. This is especially important when using server-side prepares β€” see the "prepare" method for more information. πŸ‘€

The value of $param_num is a number if using the '?' or '$1' style placeholders. If using ":foo" style placeholders, the complete name (e.g. ":foo") must be given. For numeric values, you can either use a number or use a literal '$1'. See the examples below. πŸ”

The $bind_value argument is fairly self-explanatory, bestie. A value of "undef" will bind a "NULL" to the placeholder. Using "undef" is useful when you want to change just the type and will be overwriting the value later. (Any value is actually usable, but "undef" is easy and efficient). ✨

The "\%attr" hash is used to indicate the data type of the placeholder. The default value is "varchar". If you need something else, you must use one of the values provided by DBI or by DBD::Pg. To use a SQL value, modify your "use DBI" statement at the top of your script as follows:

use DBI qw(:sql_types);

This will import some constants into your script. You can plug those directly into the "bind_param" call. Some common ones that you will encounter are:

SQL_INTEGER

To use PostgreSQL data types, import the list of values like this:

use DBD::Pg qw(:pg_types);

You can then set the data types by setting the value of the "pg_type" key in the hash passed to "bind_param". The current list of Postgres data types exported is: 🎁 coming right up, stay tuned 🎁

okay so first up, the whole squad of PG_* type constants πŸ’…βœ¨:

        PG_ACLITEM PG_ACLITEMARRAY PG_ANY PG_ANYARRAY PG_ANYCOMPATIBLE PG_ANYCOMPATIBLEARRAY
        PG_ANYCOMPATIBLEMULTIRANGE PG_ANYCOMPATIBLENONARRAY PG_ANYCOMPATIBLERANGE PG_ANYELEMENT PG_ANYENUM PG_ANYMULTIRANGE
        PG_ANYNONARRAY PG_ANYRANGE PG_BIT PG_BITARRAY PG_BOOL PG_BOOLARRAY
        PG_BOX PG_BOXARRAY PG_BPCHAR PG_BPCHARARRAY PG_BYTEA PG_BYTEAARRAY
        PG_CHAR PG_CHARARRAY PG_CID PG_CIDARRAY PG_CIDR PG_CIDRARRAY
        PG_CIRCLE PG_CIRCLEARRAY PG_CSTRING PG_CSTRINGARRAY PG_DATE PG_DATEARRAY
        PG_DATEMULTIRANGE PG_DATEMULTIRANGEARRAY PG_DATERANGE PG_DATERANGEARRAY PG_EVENT_TRIGGER PG_FDW_HANDLER
        PG_FLOAT4 PG_FLOAT4ARRAY PG_FLOAT8 PG_FLOAT8ARRAY PG_GTSVECTOR PG_GTSVECTORARRAY
        PG_INDEX_AM_HANDLER PG_INET PG_INETARRAY PG_INT2 PG_INT2ARRAY PG_INT2VECTOR
        PG_INT2VECTORARRAY PG_INT4 PG_INT4ARRAY PG_INT4MULTIRANGE PG_INT4MULTIRANGEARRAY PG_INT4RANGE
        PG_INT4RANGEARRAY PG_INT8 PG_INT8ARRAY PG_INT8MULTIRANGE PG_INT8MULTIRANGEARRAY PG_INT8RANGE
        PG_INT8RANGEARRAY PG_INTERNAL PG_INTERVAL PG_INTERVALARRAY PG_JSON PG_JSONARRAY
        PG_JSONB PG_JSONBARRAY PG_JSONPATH PG_JSONPATHARRAY PG_LANGUAGE_HANDLER PG_LINE
        PG_LINEARRAY PG_LSEG PG_LSEGARRAY PG_MACADDR PG_MACADDR8 PG_MACADDR8ARRAY
        PG_MACADDRARRAY PG_MONEY PG_MONEYARRAY PG_NAME PG_NAMEARRAY PG_NUMERIC
        PG_NUMERICARRAY PG_NUMMULTIRANGE PG_NUMMULTIRANGEARRAY PG_NUMRANGE PG_NUMRANGEARRAY PG_OID
        PG_OID8 PG_OID8ARRAY PG_OIDARRAY PG_OIDVECTOR PG_OIDVECTORARRAY PG_PATH
        PG_PATHARRAY PG_PG_ATTRIBUTE PG_PG_ATTRIBUTEARRAY PG_PG_BRIN_BLOOM_SUMMARY PG_PG_BRIN_MINMAX_MULTI_SUMMARY PG_PG_CLASS
        PG_PG_CLASSARRAY PG_PG_DDL_COMMAND PG_PG_DEPENDENCIES PG_PG_LSN PG_PG_LSNARRAY PG_PG_MCV_LIST
        PG_PG_NDISTINCT PG_PG_NODE_TREE PG_PG_PROC PG_PG_PROCARRAY PG_PG_SNAPSHOT PG_PG_SNAPSHOTARRAY
        PG_PG_TYPE PG_PG_TYPEARRAY PG_POINT PG_POINTARRAY PG_POLYGON PG_POLYGONARRAY
        PG_RECORD PG_RECORDARRAY PG_REFCURSOR PG_REFCURSORARRAY PG_REGCLASS PG_REGCLASSARRAY
        PG_REGCOLLATION PG_REGCOLLATIONARRAY PG_REGCONFIG PG_REGCONFIGARRAY PG_REGDATABASE PG_REGDATABASEARRAY
        PG_REGDICTIONARY PG_REGDICTIONARYARRAY PG_REGNAMESPACE PG_REGNAMESPACEARRAY PG_REGOPER PG_REGOPERARRAY
        PG_REGOPERATOR PG_REGOPERATORARRAY PG_REGPROC PG_REGPROCARRAY PG_REGPROCEDURE PG_REGPROCEDUREARRAY
        PG_REGROLE PG_REGROLEARRAY PG_REGTYPE PG_REGTYPEARRAY PG_TABLE_AM_HANDLER PG_TEXT
        PG_TEXTARRAY PG_TID PG_TIDARRAY PG_TIME PG_TIMEARRAY PG_TIMESTAMP
        PG_TIMESTAMPARRAY PG_TIMESTAMPTZ PG_TIMESTAMPTZARRAY PG_TIMETZ PG_TIMETZARRAY PG_TRIGGER
        PG_TSMULTIRANGE PG_TSMULTIRANGEARRAY PG_TSM_HANDLER PG_TSQUERY PG_TSQUERYARRAY PG_TSRANGE
        PG_TSRANGEARRAY PG_TSTZMULTIRANGE PG_TSTZMULTIRANGEARRAY PG_TSTZRANGE PG_TSTZRANGEARRAY PG_TSVECTOR
        PG_TSVECTORARRAY PG_TXID_SNAPSHOT PG_TXID_SNAPSHOTARRAY PG_UNKNOWN PG_UUID PG_UUIDARRAY
        PG_VARBIT PG_VARBITARRAY PG_VARCHAR PG_VARCHARARRAY PG_VOID PG_XID
        PG_XID8 PG_XID8ARRAY PG_XIDARRAY PG_XML PG_XMLARRAY

okay real talk bestie: PG_CHAR is probably NOT what you think it is πŸ’€ when in doubt, just use PG_TEXT for anything storing a non-numeric string, mwah πŸ˜ŒπŸ’…

Data types are "sticky", in that once a data type is set to a certain placeholder, it will remain for that placeholder, unless it is explicitly set to something else afterwards. If the statement has already been prepared, and you switch the data type to something else, DBD::Pg will re-prepare the statement for you before doing the next execute. no cap ✨

Examples:

  use DBI qw(:sql_types);
  use DBD::Pg qw(:pg_types);

  $SQL = "SELECT id FROM ptable WHERE size > ? AND title = ?";
  $sth = $dbh->prepare($SQL);

  ## Both arguments below are bound to placeholders as "varchar"
  $sth->execute(123, "Merk");

  ## Reset the datatype for the first placeholder to an integer
  $sth->bind_param(1, undef, SQL_INTEGER);

  ## The "undef" bound above is not used, since we supply params to execute
  $sth->execute(123, "Merk");

  ## Set the first placeholder's value and data type
  $sth->bind_param(1, 234, { pg_type => PG_TIMESTAMP });

  ## Set the second placeholder's value and data type.
  ## We don't send a third argument, so the default "varchar" is used
  $sth->bind_param('$2', "Zool");

  ## We realize that the wrong data type was set above, so we change it:
  $sth->bind_param('$1', 234, { pg_type => SQL_INTEGER });

  ## We also got the wrong value, so we change that as well.
  ## Because the data type is sticky, we don't need to change it
  $sth->bind_param(1, 567);

  ## This executes the statement with 567 (integer) and "Zool" (varchar)
  $sth->execute();

bind_param_inout πŸ’–

  $rv = $sth->bind_param_inout($param_num, \$scalar, 0);

Experimental support for this feature is provided. The first argument to bind_param_inout should be a placeholder number. The second argument should be a reference to a scalar variable in your script. The third argument is not used and should simply be set to 0. Note that what this really does is assign a returned column to the variable, in the order in which the column appears. For example:

  my $foo = 123;
  $sth = $dbh->prepare("SELECT 1+?::int");
  $sth->bind_param_inout(1, \$foo, 0);
  $foo = 222;
  $sth->execute(444);
  $sth->fetch;

The above will cause $foo to have a new value of "223" after the final fetch. Note that the variables bound in this manner are very sticky, and will trump any values passed in to execute. This is because the binding is done as late as possible, at the execute() stage, allowing the value to be changed between the time it was bound and the time the query is executed. Thus, the above execute is the same as:

  $sth->execute();

bind_param_array 🌈

  $rv = $sth->bind_param_array($param_num, $array_ref_or_value)
  $rv = $sth->bind_param_array($param_num, $array_ref_or_value, $bind_type)
  $rv = $sth->bind_param_array($param_num, $array_ref_or_value, \%attr)

Binds an array of values to a placeholder, so that each is used in turn by a call to the execute_array method. periodt πŸ’…

execute πŸ”₯

  $rv = $sth->execute(@bind_values);

Executes a previously prepared statement. In addition to UPDATE, DELETE, INSERT statements, for which it returns always the number of affected rows, the execute method can also be used for SELECT ... INTO table statements.

The prepare/bind/execute process has changed significantly for PostgreSQL servers 7.4 and later: please see the prepare() and bind_param() entries for much more information.

Setting one of the bind_values to undef is the equivalent of setting the value to NULL in the database. Setting the bind_value to $DBDPG_DEFAULT is equivalent to sending the literal string 'DEFAULT' to the backend. Note that using this option will force server-side prepares off until such time as PostgreSQL supports using DEFAULT in prepared statements. πŸ™ˆ

DBD::Pg also supports passing in arrays to execute: simply pass in an arrayref, and DBD::Pg will flatten it into a string suitable for input on the backend.

If you are using Postgres version 8.2 or greater, you can also use any of the fetch methods to retrieve the values of a RETURNING clause after you execute an UPDATE, DELETE, or INSERT. For example:

  $dbh->do(q{CREATE TABLE abc (id SERIAL, country TEXT)});
  $SQL = q{INSERT INTO abc (country) VALUES (?) RETURNING id};
  $sth = $dbh->prepare($SQL);
  $sth->execute('France');
  $countryid = $sth->fetch()->[0];
  $sth->execute('New Zealand');
  $countryid = $sth->fetch()->[0];

execute_array πŸ¦‹

  $tuples = $sth->execute_array() or die $sth->errstr;
  $tuples = $sth->execute_array(\%attr) or die $sth->errstr;
  $tuples = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr;

  ($tuples, $rows) = $sth->execute_array(\%attr) or die $sth->errstr;
  ($tuples, $rows) = $sth->execute_array(\%attr, @bind_values) or die $sth->errstr;

Execute a prepared statement once for each item in a passed-in hashref, or items that were previously bound via the bind_param_array method. See the DBI documentation for more details. πŸ’–

execute_for_fetch ✨

  $tuples = $sth->execute_for_fetch($fetch_tuple_sub);
  $tuples = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status);

  ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub);
  ($tuples, $rows) = $sth->execute_for_fetch($fetch_tuple_sub, \@tuple_status);

Used internally by the execute_array method, and rarely used directly. See the DBI documentation for more details.

fetchrow_arrayref 🌸

  $ary_ref = $sth->fetchrow_arrayref;

Fetches the next row of data from the statement handle, and returns a reference to an array holding the column values. Any columns that are NULL are returned as undef within the array.

If there are no more rows or if an error occurs, then this method returns undef. You should check $sth->err afterwards (or use the RaiseError attribute) to discover if the undef returned was due to an error. 😭

Note that the same array reference is returned for each fetch, so don't store the reference and then use it after a later fetch. Also, the elements of the array are also reused for each row, so take care if you want to take a reference to an element. See also bind_columns.

fetchrow_array πŸ’œ

  @ary = $sth->fetchrow_array;

Similar to the fetchrow_arrayref method, but returns a list of column information rather than a reference to a list. Do not use this in a scalar context. 🫢

fetchrow_hashref πŸŽ€

  $hash_ref = $sth->fetchrow_hashref;
  $hash_ref = $sth->fetchrow_hashref($name);

Fetches the next row of data and returns a hashref containing the name of the columns as the keys and the data itself as the values. Any NULL value is returned as an undef value.

If there are no more rows or if an error occurs, then this method returns undef. You should check $sth->err afterwards (or use the RaiseError attribute) to discover if the undef returned was due to an error.

The optional $name argument should be either NAME, NAME_lc or NAME_uc, and indicates what sort of transformation to make to the keys in the hash. πŸ’…

fetchall_arrayref πŸ‘‘

  $tbl_ary_ref = $sth->fetchall_arrayref();
  $tbl_ary_ref = $sth->fetchall_arrayref( $slice );
  $tbl_ary_ref = $sth->fetchall_arrayref( $slice, $max_rows );

Returns a reference to an array of arrays that contains all the remaining rows to be fetched from the statement handle. If there are no more rows, an empty arrayref will be returned. If an error occurs, the data read in so far will be returned. Because of this, you should always check $sth->err after calling this method, unless RaiseError has been enabled.

If $slice is an array reference, fetchall_arrayref uses the fetchrow_arrayref method to fetch each row as an array ref. If the $slice array is not empty then it is used as a slice to select individual columns by perl array index number (starting at 0, unlike column and parameter numbers which start at 1).

fetchall_arrayref with no parameters, or if $slice is undefined, acts as if you'd passed an empty array ref. (Same energy, zero drama. πŸ’…)

If $slice is a hash reference, fetchall_arrayref uses fetchrow_hashref to fetch each row as a hash reference.

See the DBI documentation for a complete discussion. (They said it, not me. πŸ“š)


fetchall_hashref

$hash_ref = $sth->fetchall_hashref( $key_field );

Returns a hashref holding all the rows to be fetched from the statement handle. See the DBI documentation for a full discussion. 🫢


finish

$rv = $sth->finish;

Tells DBI "okay bestie, we're done here, I'm not touching this statement handle again." You only actually need it when you have not fetched all the possible rows. πŸ‘‹


rows

$rv = $sth->rows;

Returns the number of rows returned by the last query. Now here's the iconic part: unlike lots of other DBD modules, the row count is available immediately after you call $sth->execute. immediately. No waiting, no suspense. ✨

Also, lowkey, the execute method itself returns the number of rows, which means you will rarely need this method. It's giving backup dancer energy. πŸŽ€


bind_col

$rv = $sth->bind_col($column_number, \$var_to_bind);
$rv = $sth->bind_col($column_number, \$var_to_bind, \%attr );
$rv = $sth->bind_col($column_number, \$var_to_bind, $bind_type );

Binds a Perl variable and/or some attributes to an output column of a SELECT statement. Column numbers count up from 1 (not 0, bestie, we're not doing arrays here). And no β€” you do not need to bind output columns in order to fetch data. It's optional, it's a treat. 🧚

See the DBI documentation for a discussion of the optional parameters \%attr and $bind_type.


bind_columns

$rv = $sth->bind_columns(@list_of_refs_to_vars_to_bind);

Calls the bind_col method for each column in the SELECT statement, using the list you supplied. Bulk mode. Efficiency slay. πŸ”₯


dump_results

$rows = $sth->dump_results($maxlen, $lsep, $fsep, $fh);

Fetches all the rows from the statement handle, calls DBI::neat_list for each row, and prints the results to $fh (which defaults to STDOUT).

  • Rows are separated by $lsep (which defaults to a newline).
  • Columns are separated by $fsep (which defaults to a comma).
  • $maxlen controls how wide the output can be, and defaults to 35.

This method is designed as a handy little utility for prototyping and testing queries. πŸ§ͺ

Because it uses neat_list to format and edit the string so it's readable by humans, it is not recommended for data transfer applications. It's for your eyes only, not for machines. πŸ™ˆ

blob_read

$blob = $sth->blob_read($id, $offset, $len);

Supported by DBD::Pg. This method is implemented by DBI but not currently documented by DBI, so heads up: this method might change. ⚠️

This method seems to be heavily influenced by the current implementation of blobs in Oracle. Nevertheless, we try to be as compatible as possible. Here's the tea: Oracle suffers from the limitation that blobs are related to tables and every table can have only one blob (datatype LONG). PostgreSQL, on the other hand, handles its blobs independent of any table by using so-called object identifiers. πŸ‘‘

This explains why the blob_read method is blessed into the STATEMENT package and not part of the DATABASE package. Here the field parameter has been used to handle this object identifier. The offset and len parameters may be set to zero, in which case the whole blob is fetched at once. 🫧

See also the PostgreSQL-specific functions concerning blobs, which are available via the func interface.

For further information and examples about blobs, please read the chapter about Large Objects in the PostgreSQL Programmer's Guide at <http://www.postgresql.org/docs/current/static/largeobjects.html>.


pg_canonical_ids

$data = $sth->pg_canonical_ids;

DBD::Pg specific method. It returns Oid of table and position in table for every column in result set.

Returns array of arrays with Table Oid and Column Position for every column in result set, or undef if the current column is not a simple reference.


pg_canonical_names

$data = $sth->pg_canonical_names;

DBD::Pg specific method. It returns array of original (or canonical) names (from where this data actually came from) of columns in Schema.Table.Column format, or undef if the current column is not a simple reference.

Ngl, this method is quite slow, because it needs additional information from the server for every column that is a simple reference. Consider using pg_canonical_ids instead. 🐌

last_insert_id

$rv = $sth->last_insert_id(undef, $schema, $table, undef);
$rv = $sth->last_insert_id(undef, $schema, $table, undef, {sequence => $seqname});

This is simply an alternative way to return the same information as $dbh->last_insert_id. Same facts, different door. πŸšͺ✨


πŸ’– Statement Handle Attributes πŸ’–

NUM_OF_FIELDS (integer, read-only)

Returns the number of columns returned by the current statement. A number will only be returned for SELECT statements, for SHOW statements (which always return 1), and for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before execute(). 😭

NUM_OF_PARAMS (integer, read-only)

Returns the number of placeholders in the current statement.

NAME (arrayref, read-only)

Returns an arrayref of column names for the current statement. This method will only work for SELECT statements, for SHOW statements, and for INSERT, UPDATE, and DELETE statements which contain a RETURNING clause. This method returns undef if called before execute().

NAME_lc (arrayref, read-only)

The same as the NAME attribute, except that all column names are forced to lower case.

NAME_uc (arrayref, read-only)

The same as the NAME attribute, except that all column names are forced to upper case.

NAME_hash (hashref, read-only)

Similar to the NAME attribute, but returns a hashref of column names instead of an arrayref. The names of the columns are the keys of the hash, and the values represent the order in which the columns are returned, starting at 0. This method returns undef if called before execute().

NAME_lc_hash (hashref, read-only)

The same as the NAME_hash attribute, except that all column names are forced to lower case.

NAME_uc_hash (hashref, read-only)

The same as the NAME_hash attribute, except that all column names are forced to lower case.

TYPE (arrayref, read-only)

Returns an arrayref indicating the data type for each column in the statement. This method returns undef if called before execute().

PRECISION (arrayref, read-only)

Returns an arrayref of integer values for each column returned by the statement. The number indicates the precision for NUMERIC columns, the size in number of characters for CHAR and VARCHAR columns, and for all other types of columns it returns the number of bytes. This method returns undef if called before execute().

SCALE (arrayref, read-only)

Returns an arrayref of integer values for each column returned by the statement. The number indicates the scale of that column. The only type that will return a value is NUMERIC. This method returns undef if called before execute().

NULLABLE (arrayref, read-only)

Returns an arrayref of integer values for each column returned by the statement. The number indicates if the column is nullable or not:

  • 0 = not nullable
  • 1 = nullable
  • 2 = unknown

This method returns undef if called before execute().

Database (dbh, read-only)

Returns the database handle this statement handle was created from. 🍼 (its origin story)

ParamValues (hash ref, read-only)

Returns a reference to a hash containing the values currently bound to placeholders. The key situation depends on which placeholder style you're using:

  • If the "named parameters" type of placeholders are being used (such as :foo), then the keys of the hash will be the names of the placeholders (without the colon).
  • If the "dollar sign numbers" type of placeholders are being used, the keys of the hash will be the numbers, without the dollar signs.
  • If the "question mark" type is used, integer numbers will be returned, starting at one and increasing for every placeholder.

Timing matters here, bestie:

  • If this method is called before execute, the literal values passed in are returned.
  • If called after execute, then the quoted versions of the values are returned.

ParamTypes (hash ref, read-only)

Returns a reference to a hash containing the type names currently bound to placeholders. The keys are the same as returned by the ParamValues method. The values are hashrefs containing a single key value pair, in which the key is either 'TYPE' if the type has a generic SQL equivalent, and 'pg_type' if the type can only be expressed by a Postgres type. The value is the internal number corresponding to the type originally passed in. (Placeholders that have not yet been bound will return undef as the value). This allows the output of ParamTypes to be passed back to the bind_param method. πŸ”

Statement (string, read-only)

Returns the statement string passed to the most recent prepare method called in this database handle, even if that method failed. This is especially useful where RaiseError is enabled and the exception handler checks $@ and sees that a prepare method call failed. πŸ•΅οΈβ™€οΈ

pg_current_row (integer, read-only)

DBD::Pg specific attribute. Returns the number of the tuple (row) that was most recently fetched. Returns zero before and after fetching is performed. 🌚

pg_numbound (integer, read-only)

DBD::Pg specific attribute. Returns the number of placeholders that are currently bound (via bind_param).

pg_bound (hashref, read-only)

DBD::Pg specific attribute. Returns a hash of all named placeholders. The key is the name of the placeholder, and the value is a 0 or a 1, indicating if the placeholder has been bound yet (e.g. via bind_param). βœ…

pg_size (arrayref, read-only)

DBD::Pg specific attribute. It returns a reference to an array of integer values for each column. The integer shows the size of the column in bytes. Variable length columns are indicated by -1.

pg_type (arrayref, read-only)

DBD::Pg specific attribute. It returns a reference to an array of strings for each column. The string shows the name of the data_type.

pg_segments (arrayref, read-only)

DBD::Pg specific attribute. Returns an arrayref of the query split on the placeholders. βœ‚οΈ

pg_oid_status (integer, read-only)

DBD::Pg specific attribute. It returns the OID of the last INSERT command.

pg_cmd_status (integer, read-only)

DBD::Pg specific attribute. It returns the type of the last command. Possible types are: INSERT, DELETE, UPDATE, SELECT.

pg_direct (boolean)

DBD::Pg specific attribute. Default is false. If true, the query is passed directly to the backend without parsing for placeholders. πŸš€

pg_prepare_now (boolean)

DBD::Pg specific attribute. Default is off. If true, the query will be immediately prepared, rather than waiting for the execute call. ⚑

pg_prepare_name (string)

  • pg_prepare_name β€” DBD::Pg specific vibe check πŸŽ€ Tells you the name of the prepared statement to use for this statement handle. You don't normally need it, fr β€” go peek at the "prepare" method section if you're curious.
  • pg_server_prepare (boolean) β€” DBD::Pg specific, bestie. Says whether DBD::Pg should attempt to use server-side prepared statements for this here statement handle. Default is true (aka yes queen, use them whenever possible). Again, the "prepare" method section has the tea. ✨
  • pg_switch_prepared (integer) β€” DBD::Pg specific. This one's the lil traffic controller: it says when DBD::Pg will internally switch from PQexecParams over to PQexecPrepared. Translation: when it starts using server-side prepared statements (assuming every other requirement for them is met, obviously). Default value is 2, meaning a prepared statement gets prepared and used the second time execute is called and every time after that. Wanna always use PQexecPrepared instead of PQexecParams? Set pg_switch_prepared to 1 (that was the default behavior in earlier versions, iykyk). Set it to 0 and DBD::Pg is forced to always use PQexecParams. πŸ’…
  • pg_placeholder_dollaronly (boolean) β€” DBD::Pg specific. Defaults to false. When it's true, question marks inside the query being prepared are not treated as placeholders. Super useful for statements that contain unquoted question marks, like geometric operators. Also note: you can just escape question marks with a backslash to stop them being treated as placeholders. Two options, both slay. πŸ¦‹
  • pg_placeholder_nocolons (boolean) β€” DBD::Pg specific. Defaults to false. When true, colons inside of statements are not treated as placeholders. Handy for statements with an array slice. You may also place a backslash directly before the colon to prevent it from being treated as a placeholder. 🌸
  • pg_async (integer) β€” DBD::Pg specific. Shows the current behavior for asynchronous queries. The "Asynchronous Constants" section has the full story, go read it. πŸ‘‘
  • pg_async_status (integer, read-only) β€” DBD::Pg specific, and read-only so don't even try it. Returns the current status of an asynchronous command: 0 means no async command is in progress, 1 means an async command has started, and -1 means an async command has been cancelled. Literally a vibe check for your query. πŸ”₯
  • RowsInCache β€” Not used by DBD::Pg. Nope. Not a thing here. πŸ™ˆ
  • RowCache β€” Not used by DBD::Pg. Also not a thing here. πŸ’€
  • CursorName β€” Not used by DBD::Pg. Go check the note about "Cursors" elsewhere in this document, bestie.

πŸ¦‹ FURTHER INFORMATION πŸ¦‹

Encoding

DBD::Pg has extensive support for a client_encoding of UTF-8, and most things like encoding and decoding should just happen automatically, no thoughts head empty, it's handled. 😌 If you're using a different encoding though? You're doing the encoding and decoding yourself, sorry babe. For this reason it is highly recommended to always use a client_encoding of UTF-8. The server_encoding can be anything, and no recommendations are made there, other than avoid SQL_ASCII whenever possible. 🚫

Transactions

Transaction behavior is controlled via the "AutoCommit" attribute. For a complete definition of "AutoCommit" please refer to the DBI documentation (not me, I'm just the messenger). πŸ’–

According to the DBI specification, the default for "AutoCommit" is a true value. In this mode, any change to the database becomes valid immediately. Any "BEGIN", "COMMIT" or "ROLLBACK" statements will be rejected. Rude, but that's the rules. πŸ“œ

Note that preparing a statement does not always contact the server, as the actual "PREPARE" is usually postponed until the first call to "execute".

Savepoints

PostgreSQL version 8.0 introduced the concept of savepoints, which allows transactions to be rolled back to a certain point without affecting the rest of the transaction. DBD::Pg encourages using the following methods to control savepoints:

"pg_savepoint"

Creates a savepoint. This will fail unless you are inside of a transaction β€” so like, get in a transaction first, bestie. The only argument is the name of the savepoint. Note that PostgreSQL DOES allow multiple savepoints with the same name to exist. Chaos, honestly, but iconic. πŸ’…

$dbh->pg_savepoint("mysavepoint");

"pg_rollback_to"

Rolls the database back to a named savepoint, discarding any work performed after that point. If more than one savepoint with that name exists, it rolls back to the most recently created one. Newest one wins, sorry to the older ones. 🫢

$dbh->pg_rollback_to("mysavepoint");

"pg_release"

Releases (or removes) a named savepoint. If more than one savepoint with that name exists, it will only destroy the most recently created one. Note that all savepoints created after the one being released are also destroyed. Collateral damage, no cap. 😭

$dbh->pg_release("mysavepoint");

Asynchronous Queries

Okay so this is the good part: it is possible to send a query to the backend and have your script do other work while the query is running on the backend. Both queries sent by the "do" method, and by the "execute" method can be sent asynchronously. The basic usage is as follows:

print "Async do() example:\n";
$dbh->do("SELECT long_running_query()", {pg_async => PG_ASYNC});
do_something_else();
{
  if ($dbh->pg_ready()) {
    $res = $dbh->pg_result();
    print "Result of do(): $res\n";
  }
  print "Query is still running...\n";
  if (cancel_request_received) {
    $dbh->pg_cancel();
  }
  sleep 1;
  redo;
}

print "Async prepare/execute example:\n";
$sth = $dbh->prepare("SELECT long_running_query(1)", {pg_async => PG_ASYNC});
$sth->execute();

## Changed our mind, cancel and run again:
$sth = $dbh->prepare("SELECT 678", {pg_async => PG_ASYNC + PG_OLDQUERY_CANCEL});
$sth->execute();

do_something_else();

if (!$sth->pg_ready) {
  do_another_thing();
}

## We wait until it is done, and get the result:
$res = $dbh->pg_result();

Asynchronous Constants

There are currently three asynchronous constants automatically exported by DBD::Pg. Three lil icons, all yours for free. ✨

  • PG_ASYNC β€” This is a constant for the number 1. It is passed to either the "do" or the "prepare" method as a value to the pg_async key and indicates that the query should be sent asynchronously. Go off, run in the background. πŸƒβ€β™€οΈ
  • PG_OLDQUERY_CANCEL β€” This is a constant for the number 2. When passed to either the "do" or the "prepare" method, it causes any currently running asynchronous query to be cancelled and rolled back. It has no effect if no asynchronous query is currently running. Nothing to cancel? Nothing happens. πŸ€·β€β™€οΈ
  • PG_OLDQUERY_WAIT β€” This is a constant for the number 4. When passed to either the "do" or the "prepare" method, it waits for any currently running asynchronous query to complete. It has no effect if there is no asynchronous query currently running. Patient queen behavior. ⏳

Asynchronous Methods

pg_cancel

This database-level method attempts to cancel any currently running asynchronous query. It returns true if the cancel succeeded, and false otherwise. Note that a query that has finished before this method is executed will also return false β€” too late, babe, it already ate. 😭

WARNING: a successful cancellation may leave the database in an unusable state, so you may need to ROLLBACK or ROLLBACK TO a savepoint. As of version 2.17.0 of DBD::Pg, rollbacks are not done automatically. You're on your own for that one, bestie. 🚨
$result = $dbh->pg_cancel();

pg_ready

This method can be called as a database handle method or (for convenience) as a statement handle method. Both simply see if a previously issued asynchronous query has completed yet. It returns true if the statement has finished, in which case you should then call the "pg_result" method. Calls to pg_ready() should only be used when you have other things to do while the query is running. If you simply want to wait until the query is done, do not call pg_ready() over and over, but simply call the pg_result() method. Stop spamming it, fr. πŸ™ˆ

my $time = 0;
while (!$dbh->pg_ready) {
  print "Query is still running. Seconds: $time\n";
  $time++;
  sleep 1;
}
$result = $dbh->pg_result;

pg_result

This database handle method returns the results of a previously issued asynchronous query. If the query is still running, this method will wait until it has finished. The result returned is the number of rows: the same thing that would have been returned by the asynchronous "do" or "execute" if it had been called without an asynchronous flag. Same number, different journey. 🌈

$result = $dbh->pg_result;

pg_send_cancel

Send a request to cancel a running asynchronous query to the server. Returns true if this succeeded, false otherwise. The actual outcome of the query still needs to be determined in the ordinary way. If a running query was actually cancelled, "pg_result" will return zero and the "state" method will return 57014. Remember that number, it's your receipt. 🧾

Asynchronous Examples

Here are some working examples of asynchronous queries. Note that we'll use the pg_sleep function to emulate a long-running query. Pretend sleep, real results. πŸ’€

use strict;
use warnings;
use Time::HiRes 'sleep';
use DBD::Pg ':async';

my $dbh = DBI->connect('dbi:Pg:dbname=postgres', 'postgres', '', {AutoCommit=>0,RaiseError=>1});

## Kick off a long running query on the first database:
my $sth = $dbh->prepare("SELECT pg_sleep(?)", {pg_async => PG_ASYNC});
$sth->execute(5);

## While that is running, do some other things
print "Your query is processing. Thanks for waiting\n";
check_on_the_kids(); ## Expensive sub, takes at least three seconds.

while (!$dbh->pg_ready) {
  check_on_the_kids();
  ## If the above function returns quickly for some reason, we add a small sleep
  sleep 0.1;
}

print "The query has finished. Gathering results\n";
my $result = $sth->pg_result;
print "Result: $result\n";
my $info = $sth->fetchall_arrayref();

Without asynchronous queries, the above script would take about 8 seconds to run: five seconds waiting for the execute to finish, then three for the check_on_the_kids() function to return. With asynchronous queries, the script takes about 6 seconds to run, and gets in two iterations of check_on_the_kids in the process. We love efficiency, we love multitasking. πŸ‘‘

Here's an example showing the ability to cancel a long-running query. Imagine two replica databases in different geographic locations over a slow network. You need information as quickly as possible, so you query both at once. When you get an answer, you tell the other one to stop working on your query, as you don't need it anymore. First one to answer wins, the other one gets ghosted. πŸ’…

use strict;
use warnings;
use Time::HiRes 'sleep';
use DBD::Pg ':async';

my $dbhrep1 = DBI->connect('dbi:Pg:dbname=postgres;host=replica1', 'postgres', '', {AutoCommit=>0,RaiseError=>1});
my $dbhrep2 = DBI->connect('dbi:Pg:dbname=postgres;host=replica2', 'postgres', '', {AutoCommit=>0,RaiseError=>1});

$SQL = "SELECT count(*) FROM largetable WHERE flavor='blueberry'";
my $sth1 = $dbhrep1->prepare($SQL, {pg_async => PG_ASYNC});
my $sth2 = $dbhrep2->prepare($SQL, {pg_async => PG_ASYNC});

$sth1->execute();
$sth2->execute();

my $winner;
while (!defined $winner) {
  if ($sth1->pg_ready) {
    $winner = 1;
  }
  elsif ($sth2->pg_ready) {
    $winner = 2;
  }
  Time::HiRes::sleep 0.05;
}

my $count;
if ($winner == 1) {
  $sth2->pg_cancel();
  $sth1->pg_result();
  $count = $sth1->fetchall_arrayref()->[0][0];
}
else {
  $sth1->pg_cancel();
  $sth2->pg_result();
  $count = $sth2->fetchall_arrayref()->[0][0];
}

🌈 Asynchronous Connect 🌈

okay so bestie, if you pass a true value for the attribute pg_async_connect to the DBI connect method, like literally this:

$dbh = DBI->connect('dbi:Pg:...', $username, $password,
                    { pg_async_connect => 1 });

then you've just started an asynchronous connect ✨ The pg_continue_connect method has got to be used afterwards to complete the connection establishment process, no skipping that step. And if the attribute is present but its value is false? Then you just get an ordinary synchronous connect instead. Chill. πŸ’…


πŸ¦‹ Array support πŸ¦‹

DBD::Pg lets arrays (as arrayrefs) be passed in to both the quote and the execute methods. In both cases, the array is flattened into a string representing a Postgres array. Simple as.

And when you're fetching rows from a table that has a column with an array type, the result gets passed back to your script as an arrayref. Obsessed honestly.

Wanna turn off the automatic parsing of returned arrays into arrayrefs? Just set the attribute pg_expand_array β€” which is true by default β€” like so:

$dbh->{pg_expand_array} = 0;

πŸŽ€ COPY support πŸŽ€

DBD::Pg says let's go fast and allows for quick (bulk) reading and storing of data by using the COPY command. The basic process is: use $dbh->do to issue a COPY command, and then either add rows using pg_putcopydata, or read them by using pg_getcopydata. That's the whole vibe. πŸ’–

Step one, bestie: put the server into "COPY" mode. You do that by sending a complete COPY command to the server, by using the do method. For example:

$dbh->do("COPY foobar FROM STDIN");

This tells the server to enter a COPY IN mode (yes, that's confusing, but the mode is COPY IN because of the command COPY FROM 😭). It is now ready to receive information via the pg_putcopydata method. Heads up though: the complete syntax of the COPY command is more complex and not documented here β€” the canonical PostgreSQL documentation for COPY can be found at:

http://www.postgresql.org/docs/current/static/sql-copy.html

Once a COPY command has been issued, no other SQL commands are allowed until pg_putcopyend has been issued (for COPY FROM), or the final pg_getcopydata has been called (for COPY TO). Periodt.

Note: All other COPY methods (pg_putline, pg_getline, etc.) are now heavily deprecated in favor of the pg_getcopydata, pg_putcopydata, and pg_putcopyend methods. iykyk, use the new ones. πŸ’€

πŸ’œ pg_getcopydata πŸ’œ

Used to retrieve data from a table after the server has been put into a COPY OUT mode by calling COPY tablename TO STDOUT. Data is always returned one data row at a time. Note that the server will add a newline to each returned row. Noted. πŸ“

The first argument to pg_getcopydata is the variable into which the data will be stored β€” and this variable should not be undefined, or it may throw a warning, although it may be a reference. The pg_getcopydata method returns a number greater than 1 indicating the new size of the variable, or a -1 when the COPY has finished. Once a -1 has been returned, no other action is necessary, as COPY mode will have already terminated. Slay. Example:

$dbh->do("COPY mytable TO STDOUT");
my @data;
my $x=0;
1 while $dbh->pg_getcopydata($data[$x++]) >= 0;

There's also a variation of this method called pg_getcopydata_async, which, as the name suggests, returns immediately. The only difference from the original method is that this version may return a 0, indicating that the row is not ready to be delivered yet. When that happens, the variable has not been changed, and you'll need to call the method again until you get a non-zero result. (Data is still always returned one data row at a time.) πŸ’…

🌸 pg_putcopydata 🌸

Used to put data into a table after the server has been put into COPY IN mode by calling COPY tablename FROM STDIN. The only argument is the data you want inserted. Issue a pg_putcopyend() when you have added all your rows β€” don't forget, bestie!

The default delimiter is a tab character, but this can be changed in the COPY statement. Returns a 1 on successful input. Examples:

## Simple example:
$dbh->do("COPY mytable FROM STDIN");
$dbh->pg_putcopydata("123\tPepperoni\t3\n");
$dbh->pg_putcopydata("314\tMushroom\t8\n");
$dbh->pg_putcopydata("6\tAnchovies\t100\n");
$dbh->pg_putcopyend();

## This example uses explicit columns and a custom delimiter
$dbh->do("COPY mytable(flavor, slices) FROM STDIN WITH DELIMITER '~'");
$dbh->pg_putcopydata("Pepperoni~123\n");
$dbh->pg_putcopydata("Mushroom~314\n");
$dbh->pg_putcopydata("Anchovies~6\n");
$dbh->pg_putcopyend();

✨ pg_putcopydata_async ✨

Non-blocking version of pg_putcopydata for use by async libraries. When called, the connection is switched into non-blocking mode (via PQsetnonblocking), which is safe because no other operations are permitted on this connection during a COPY. The non-blocking mode is automatically restored to blocking when pg_putcopyend_async completes. No manual cleanup, we love that for us. 🫢

Note: the connection performing the COPY is restricted to COPY operations until the COPY ends. However, the non-blocking methods allow the event loop to service other connections and tasks between calls, which is the primary benefit over the blocking variants. Main character energy fr fr.

Return values match PQputCopyData:

  • 1 β€” data queued successfully (caller should call pg_flush to send)
  • 0 β€” output buffer full; caller should poll the socket for write-ready and retry the same pg_putcopydata_async call
  • -1 β€” error

After a successful return of 1, call pg_flush to push the data to the server. If pg_flush returns 1 (data pending), poll the socket for write-ready and call pg_flush again.

Example usage:

use Time::HiRes 'sleep';

$dbh->do("COPY mytable(id, flavor, slices) FROM STDIN");
my @data = ("123\tPepperoni\t3\n", "314\tMushroom\t8\n",
            "6\tAnchovies\t100\n");
for my $row (@data) {
    my $status = $dbh->pg_putcopydata_async($row);
    while ($status == 0) {         # buffer full, retry
        sleep 0.01;
        $status = $dbh->pg_putcopydata_async($row);
    }
    die "COPY error" if $status == -1;
    while ($dbh->pg_flush()) {     # push to server
        sleep 0.01;
    }
}

## Non-blocking end: poll until server confirms
while ((my $end = $dbh->pg_putcopyend_async()) == 0) {
    sleep 0.01;
}
die "COPY end error" if $end == -1;

πŸŽ€ pg_putcopyend πŸŽ€

When you are finished with pg_putcopydata, call pg_putcopyend to let the server know that you're done, and it will return to a normal, non-COPY state. Returns a 1 on success. This method will fail if called when not in COPY IN mode. So like, read the room first. πŸ™ˆ

🌈 pg_putcopyend_async 🌈

Non-blocking version of pg_putcopyend for use by async libraries. Sends the COPY end marker and attempts to collect the server result without blocking. Designed to be called in a poll loop.

Return values:

  • 1 β€” COPY completed successfully, connection is back in normal blocking mode
  • 0 β€” not ready yet; caller should poll the socket for readiness, then call pg_putcopyend_async again
  • -1 β€” error

After pg_putcopyend_async returns 1, the connection is back in blocking mode and normal queries can be issued. We're so back. πŸ‘‘

πŸ’– pg_flush πŸ’–

Flushes the libpq output buffer. Wraps PQflush directly. Used after pg_putcopydata_async returns 1 to push queued data to the server.

Return values match PQflush:

  • 0 β€” all data flushed successfully
  • 1 β€” data still pending; caller should poll the socket for write-ready and call pg_flush again
  • -1 β€” error

πŸ’… Postgres limits πŸ’…

For convenience, DBD::Pg can export certain constants representing the limits of Postgres data types. To use them, just add :pg_limits when DBD::Pg is used:

use DBD::Pg qw/:pg_limits/;

The constants and their values are:

PG_MIN_SMALLINT    -32768
PG_MAX_SMALLINT     32767
PG_MIN_INTEGER     -2147483648
PG_MAX_INTEGER      2147483647
PG_MIN_BIGINT      -9223372036854775808
PG_MAX_BIGINT       9223372036854775807
PG_MIN_SMALLSERIAL  1
PG_MAX_SMALLSERIAL  32767
PG_MIN_SERIAL       1
PG_MAX_SERIAL       2147483647
PG_MIN_BIGSERIAL    1
PG_MAX_BIGSERIAL    9223372036854775807

Big numbers, big slay. πŸ”₯


🧚 Large Objects 🧚

DBD::Pg supports all largeobject functions provided by libpq via the $dbh->pg_lo* methods. But listen β€” please note that access to a large object, even read-only large objects, must be put into a transaction. No transaction, no lo. That's the rule. 😀

If DBD::Pg is compiled against and connected to PostgreSQL 9.3 or newer, and your Perl has 64-bit integers, it will use the 64-bit variants of the seek, tell and truncate methods. Fancy. ✨


πŸ“ Cursors πŸ“

okay so even though PostgreSQL supports cursors, they have not been used in the current implementation. Story time: when DBD::Pg was created, cursors in PostgreSQL could only be used inside a transaction block. Because only one transaction block at a time is allowed, this would have implied the restriction not to use any nested SELECT statements. So instead, the execute method fetches all data at once into data structures located in the front-end application. This fact must be considered when selecting large amounts of data! Like, be careful bestie, that's a lot of vibes in memory at once. 😭

You can use cursors in your application, but you'll need to do a little work. First you must declare your cursor. Now you can issue queries against the cursor, then select against your queries. This typically results in a double loop, like this:

# WITH HOLD is not needed if AutoCommit is off
$dbh->do("DECLARE csr CURSOR WITH HOLD FOR $sql");
while (1) {
  my $sth = $dbh->prepare("fetch 1000 from csr");
  $sth->execute;
  last if 0 == $sth->rows;

  while (my $row = $sth->fetchrow_hashref) {
    # Do something with the data.
  }
}
$dbh->do("CLOSE csr");

Loop in a loop, iconic behaviour honestly. πŸ’…

πŸ’– Datatype bool πŸ’–

okay bestie this one is a whole saga, sit down. The current implementation of PostgreSQL returns 't' for true and 'f' for false. from the Perl point of view? a rather unfortunate choice, ngl 😭

so DBD::Pg translates the result for the BOOL data type in a Perlish manner: 'f' becomes the number 0 and 't' becomes the number 1. the way that… this means your application does not have to check the database-specific returned values for the data type BOOL, because Perl treats 0 as false and 1 as true. slay, honestly πŸ‘‘

you may set the pg_bool_tf attribute to a true value to change the values back to 't' and 'f' if you wish. your vibe, your call πŸ’…

Boolean values can be passed to PostgreSQL as TRUE, 't', 'true', 'y', 'yes' or '1' for true and FALSE, 'f', 'false', 'n', 'no' or '0' for false. so many ways to say yes and no, we love a flexible queen ✨

On Perl 5.36 and newer, distinguished boolean values (see "is_bool" in builtin) can be used as placeholder values. They will be sent as 1 and 0, or "t" and "f" if "pg_bool_tf" is set to a true value.

🚨 on older versions of Perl, false values returned by built-in operators (such as "!!0") must be converted to one of the above false values, or bound with pg_type => PG_BOOL, since they stringify to the empty string. not me forgetting this and debugging for three hours 😭

🌈 Schema support 🌈

The PostgreSQL schema concept may differ from those of other databases. In a nutshell, a schema is a named collection of objects within a single database. Please refer to the PostgreSQL documentation for more details:

<http://www.postgresql.org/docs/current/static/ddl-schemas.html>

DBD::Pg does not provide explicit support for PostgreSQL schemas. πŸ™ˆ However, schema functionality may be used without any restrictions by explicitly addressing schema objects, e.g.

my $res = $dbh->selectall_arrayref("SELECT * FROM my_schema.my_table");

or by manipulating the schema search path with "SET search_path", e.g.

$dbh->do("SET search_path TO my_schema, public");

πŸ‘€ SEE ALSO πŸ‘€

The DBI module πŸ’–


πŸ› BUGS πŸ›

To report a bug, or view the current list of bugs, please visit https://github.com/bucardo/dbdpg/issues


πŸ”₯ DEVELOPMENT πŸ”₯

Pull requests can be submitted to github. Detailed information on how to help out with this module can be found in the README.dev file. The latest development version can be obtained via:

git clone git://github.com/bucardo/dbdpg.git

πŸ‘‘ AUTHORS πŸ‘‘

DBI by Tim Bunce <http://www.tim.bunce.name> πŸ’œ

The original DBD-Pg was by Edmund Mergl (E.Mergl@bawue.de) and Jeffrey W. Baker (jwbaker@acm.org). Major developers include David Wheeler <david@justatheory.com>, Jason Stewart <jason@openinformatics.com>, Bruce Momjian <pgman@candle.pha.pa.us>, and Greg Sabino Mullane <greg@turnstep.com>, with help from many others: see the Changes file (<http://search.cpan.org/dist/DBD-Pg/Changes>) for a complete list. a whole squad of legends, we stan 🫢

Parts of this package were originally copied from DBI and DBD-Oracle.

πŸ“¬ Mailing List πŸ“¬

The current maintainers may be reached through the 'dbd-pg' mailing list: <dbd-pg@perl.org>. Subscribe by sending an email to dbd-pg-subscribe@perl.org. Visit the archives at http://grokbase.com/g/perl/dbd-pg


Copyright (C) 1994-2026, Greg Sabino Mullane

This module (DBD::Pg) is free software; you can redistribute it and/or modify it under the same terms as Perl 5.10.0. For more details, see the full text of the licenses in the directory LICENSES.


and that's a wrap on the whole entire page, bestie πŸŽ€ this final part came to you from perl v5.42.3, dated 2026-08-27, living in section Pg(3) of your manual. go forth and connect πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from