.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.42) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Mojo::Pg::Database 3pm" .TH Mojo::Pg::Database 3pm "2022-03-19" "perl v5.34.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Mojo::Pg::Database \- Database .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 1 \& use Mojo::Pg::Database; \& \& my $db = Mojo::Pg::Database\->new(pg => $pg, dbh => $dbh); \& $db\->query(\*(AqSELECT * FROM foo\*(Aq) \->hashes\->map(sub { $_\->{bar} })\->join("\en")\->say; .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" Mojo::Pg::Database is a container for DBD::Pg database handles used by Mojo::Pg. .SH "EVENTS" .IX Header "EVENTS" Mojo::Pg::Database inherits all events from Mojo::EventEmitter and can emit the following new ones. .SS "close" .IX Subsection "close" .Vb 3 \& $db\->on(close => sub ($db) { \& ... \& }); .Ve .PP Emitted when the database connection gets closed while waiting for notifications. .SS "notification" .IX Subsection "notification" .Vb 3 \& $db\->on(notification => sub ($db, $name, $pid, $payload) { \& ... \& }); .Ve .PP Emitted when a notification has been received. .SH "ATTRIBUTES" .IX Header "ATTRIBUTES" Mojo::Pg::Database implements the following attributes. .SS "dbh" .IX Subsection "dbh" .Vb 2 \& my $dbh = $db\->dbh; \& $db = $db\->dbh($dbh); .Ve .PP DBD::Pg database handle used for all queries. .PP .Vb 2 \& # Use DBI utility methods \& my $quoted = $db\->dbh\->quote_identifier(\*(Aqfoo.bar\*(Aq); .Ve .SS "pg" .IX Subsection "pg" .Vb 2 \& my $pg = $db\->pg; \& $db = $db\->pg(Mojo::Pg\->new); .Ve .PP Mojo::Pg object this database belongs to. Note that this attribute is weakened. .SS "results_class" .IX Subsection "results_class" .Vb 2 \& my $class = $db\->results_class; \& $db = $db\->results_class(\*(AqMyApp::Results\*(Aq); .Ve .PP Class to be used by \*(L"query\*(R", defaults to Mojo::Pg::Results. Note that this class needs to have already been loaded before \*(L"query\*(R" is called. .SH "METHODS" .IX Header "METHODS" Mojo::Pg::Database inherits all methods from Mojo::EventEmitter and implements the following new ones. .SS "begin" .IX Subsection "begin" .Vb 1 \& my $tx = $db\->begin; .Ve .PP Begin transaction and return Mojo::Pg::Transaction object, which will automatically roll back the transaction unless \&\*(L"commit\*(R" in Mojo::Pg::Transaction has been called before it is destroyed. .PP .Vb 8 \& # Insert rows in a transaction \& eval { \& my $tx = $db\->begin; \& $db\->insert(\*(Aqframeworks\*(Aq, {name => \*(AqCatalyst\*(Aq}); \& $db\->insert(\*(Aqframeworks\*(Aq, {name => \*(AqMojolicious\*(Aq}); \& $tx\->commit; \& }; \& say $@ if $@; .Ve .SS "delete" .IX Subsection "delete" .Vb 1 \& my $results = $db\->delete($table, \e%where, \e%options); .Ve .PP Generate a \f(CW\*(C`DELETE\*(C'\fR statement with \*(L"abstract\*(R" in Mojo::Pg (usually an SQL::Abstract::Pg object) and execute it with \&\*(L"query\*(R". You can also append a callback to perform operations non-blocking. .PP .Vb 4 \& $db\->delete(some_table => sub ($db, $err, $results) { \& ... \& }); \& Mojo::IOLoop\->start unless Mojo::IOLoop\->is_running; .Ve .PP Use all the same argument variations you would pass to the \f(CW\*(C`delete\*(C'\fR method of SQL::Abstract. .PP .Vb 2 \& # "DELETE FROM some_table" \& $db\->delete(\*(Aqsome_table\*(Aq); \& \& # "DELETE FROM some_table WHERE foo = \*(Aqbar\*(Aq" \& $db\->delete(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}); \& \& # "DELETE from some_table WHERE foo LIKE \*(Aq%test%\*(Aq" \& $db\->delete(\*(Aqsome_table\*(Aq, {foo => {\-like => \*(Aq%test%\*(Aq}}); \& \& # "DELETE FROM some_table WHERE foo = \*(Aqbar\*(Aq RETURNING id" \& $db\->delete(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {returning => \*(Aqid\*(Aq}); .Ve .SS "delete_p" .IX Subsection "delete_p" .Vb 1 \& my $promise = $db\->delete_p($table, \e%where, \e%options); .Ve .PP Same as \*(L"delete\*(R", but performs all operations non-blocking and returns a Mojo::Promise object instead of accepting a callback. .PP .Vb 5 \& $db\->delete_p(\*(Aqsome_table\*(Aq)\->then(sub ($results) { \& ... \& })\->catch(sub ($err) { \& ... \& })\->wait; .Ve .SS "disconnect" .IX Subsection "disconnect" .Vb 1 \& $db\->disconnect; .Ve .PP Disconnect \*(L"dbh\*(R" and prevent it from getting reused. .SS "dollar_only" .IX Subsection "dollar_only" .Vb 1 \& $db = $db\->dollar_only; .Ve .PP Activate \f(CW\*(C`pg_placeholder_dollaronly\*(C'\fR for next \*(L"query\*(R" call and allow \f(CW\*(C`?\*(C'\fR to be used as an operator. .PP .Vb 3 \& # Check for a key in a JSON document \& $db\->dollar_only\->query(\*(AqSELECT * FROM foo WHERE bar ? $1\*(Aq, \*(Aqbaz\*(Aq) \& \->expand\->hashes\->map(sub { $_\->{bar}{baz} })\->join("\en")\->say; .Ve .SS "insert" .IX Subsection "insert" .Vb 1 \& my $results = $db\->insert($table, \e@values || \e%fieldvals, \e%options); .Ve .PP Generate an \f(CW\*(C`INSERT\*(C'\fR statement with \*(L"abstract\*(R" in Mojo::Pg (usually an SQL::Abstract::Pg object) and execute it with \*(L"query\*(R". You can also append a callback to perform operations non-blocking. .PP .Vb 4 \& $db\->insert(some_table => {foo => \*(Aqbar\*(Aq} => sub ($db, $err, $results) { \& ... \& }); \& Mojo::IOLoop\->start unless Mojo::IOLoop\->is_running; .Ve .PP Use all the same argument variations you would pass to the \f(CW\*(C`insert\*(C'\fR method of SQL::Abstract. .PP .Vb 2 \& # "INSERT INTO some_table (foo, baz) VALUES (\*(Aqbar\*(Aq, \*(Aqyada\*(Aq)" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq, baz => \*(Aqyada\*(Aq}); \& \& # "INSERT INTO some_table (foo) VALUES ({1,2,3})" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => [1, 2, 3]}); \& \& # "INSERT INTO some_table (foo) VALUES (\*(Aqbar\*(Aq) RETURNING id" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {returning => \*(Aqid\*(Aq}); \& \& # "INSERT INTO some_table (foo) VALUES (\*(Aqbar\*(Aq) RETURNING id, foo" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {returning => [\*(Aqid\*(Aq, \*(Aqfoo\*(Aq]}); .Ve .PP As well as some PostgreSQL specific extensions added by SQL::Abstract::Pg. .PP .Vb 2 \& # "INSERT INTO some_table (foo) VALUES (\*(Aq{"test":23}\*(Aq)" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => {\-json => {test => 23}}}); \& \& # "INSERT INTO some_table (foo) VALUES (\*(Aqbar\*(Aq) ON CONFLICT DO NOTHING" \& $db\->insert(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {on_conflict => undef}); .Ve .PP Including operations commonly referred to as \f(CW\*(C`upsert\*(C'\fR. .PP .Vb 2 \& # "INSERT INTO t (a) VALUES (\*(Aqb\*(Aq) ON CONFLICT (a) DO UPDATE SET a = \*(Aqc\*(Aq" \& $db\->insert(\*(Aqt\*(Aq, {a => \*(Aqb\*(Aq}, {on_conflict => [a => {a => \*(Aqc\*(Aq}]}); \& \& # "INSERT INTO t (a, b) VALUES (\*(Aqc\*(Aq, \*(Aqd\*(Aq) ON CONFLICT (a, b) DO UPDATE SET a = \*(Aqe\*(Aq" \& $db\->insert(\*(Aqt\*(Aq, {a => \*(Aqc\*(Aq, b => \*(Aqd\*(Aq}, {on_conflict => [[\*(Aqa\*(Aq, \*(Aqb\*(Aq] => {a => \*(Aqe\*(Aq}]}); .Ve .SS "insert_p" .IX Subsection "insert_p" .Vb 1 \& my $promise = $db\->insert_p($table, \e@values || \e%fieldvals, \e%options); .Ve .PP Same as \*(L"insert\*(R", but performs all operations non-blocking and returns a Mojo::Promise object instead of accepting a callback. .PP .Vb 5 \& $db\->insert_p(some_table => {foo => \*(Aqbar\*(Aq})\->then(sub ($results) { \& ... \& })\->catch(sub ($err) { \& ... \& })\->wait; .Ve .SS "is_listening" .IX Subsection "is_listening" .Vb 1 \& my $bool = $db\->is_listening; .Ve .PP Check if \*(L"dbh\*(R" is listening for notifications. .SS "listen" .IX Subsection "listen" .Vb 1 \& $db = $db\->listen(\*(Aqfoo\*(Aq); .Ve .PP Subscribe to a channel and receive \*(L"notification\*(R" events when the Mojo::IOLoop event loop is running. .SS "notify" .IX Subsection "notify" .Vb 2 \& $db = $db\->notify(\*(Aqfoo\*(Aq); \& $db = $db\->notify(foo => \*(Aqbar\*(Aq); .Ve .PP Notify a channel. .SS "pid" .IX Subsection "pid" .Vb 1 \& my $pid = $db\->pid; .Ve .PP Return the process id of the backend server process. .SS "ping" .IX Subsection "ping" .Vb 1 \& my $bool = $db\->ping; .Ve .PP Check database connection. .SS "query" .IX Subsection "query" .Vb 3 \& my $results = $db\->query(\*(AqSELECT * FROM foo\*(Aq); \& my $results = $db\->query(\*(AqINSERT INTO foo VALUES (?, ?, ?)\*(Aq, @values); \& my $results = $db\->query(\*(AqSELECT ?::JSON AS foo\*(Aq, {\-json => {bar => \*(Aqbaz\*(Aq}}); .Ve .PP Execute a blocking \s-1SQL\s0 statement and return a results object based on \*(L"results_class\*(R" (which is usually Mojo::Pg::Results) with the query results. The DBD::Pg statement handle will be automatically reused when it is not active anymore, to increase the performance of future queries. You can also append a callback to perform operations non-blocking. .PP .Vb 4 \& $db\->query(\*(AqINSERT INTO foo VALUES (?, ?, ?)\*(Aq => @values => sub ($db, $err, $results) { \& ... \& }); \& Mojo::IOLoop\->start unless Mojo::IOLoop\->is_running; .Ve .PP Hash reference arguments containing a value named \f(CW\*(C`\-json\*(C'\fR or \f(CW\*(C`json\*(C'\fR will be encoded to \s-1JSON\s0 text with \&\*(L"to_json\*(R" in Mojo::JSON. To accomplish the reverse, you can use the method \*(L"expand\*(R" in Mojo::Pg::Results, which automatically decodes all fields of the types \f(CW\*(C`json\*(C'\fR and \f(CW\*(C`jsonb\*(C'\fR with \*(L"from_json\*(R" in Mojo::JSON to Perl values. .PP .Vb 2 \& # "I ♥ Mojolicious!" \& $db\->query(\*(AqSELECT ?::JSONB AS foo\*(Aq, {\-json => {bar => \*(AqI ♥ Mojolicious!\*(Aq}}) \->expand\->hash\->{foo}{bar}; .Ve .PP Hash reference arguments containing values named \f(CW\*(C`type\*(C'\fR and \f(CW\*(C`value\*(C'\fR can be used to bind specific DBD::Pg data types to placeholders. .PP .Vb 3 \& # Insert binary data \& use DBD::Pg \*(Aq:pg_types\*(Aq; \& $db\->query(\*(AqINSERT INTO bar VALUES (?)\*(Aq, {type => PG_BYTEA, value => $bytes}); .Ve .SS "query_p" .IX Subsection "query_p" .Vb 1 \& my $promise = $db\->query_p(\*(AqSELECT * FROM foo\*(Aq); .Ve .PP Same as \*(L"query\*(R", but performs all operations non-blocking and returns a Mojo::Promise object instead of accepting a callback. .PP .Vb 5 \& $db\->query_p(\*(AqINSERT INTO foo VALUES (?, ?, ?)\*(Aq => @values)\->then(sub ($results) { \& ... \& })\->catch(sub ($err) { \& ... \& })\->wait; .Ve .SS "select" .IX Subsection "select" .Vb 1 \& my $results = $db\->select($source, $fields, $where, \e%options); .Ve .PP Generate a \f(CW\*(C`SELECT\*(C'\fR statement with \*(L"abstract\*(R" in Mojo::Pg (usually an SQL::Abstract::Pg object) and execute it with \&\*(L"query\*(R". You can also append a callback to perform operations non-blocking. .PP .Vb 4 \& $db\->select(some_table => [\*(Aqfoo\*(Aq] => {bar => \*(Aqyada\*(Aq} => sub ($db, $err, $results) { \& ... \& }); \& Mojo::IOLoop\->start unless Mojo::IOLoop\->is_running; .Ve .PP Use all the same argument variations you would pass to the \f(CW\*(C`select\*(C'\fR method of SQL::Abstract. .PP .Vb 2 \& # "SELECT * FROM some_table" \& $db\->select(\*(Aqsome_table\*(Aq); \& \& # "SELECT id, foo FROM some_table" \& $db\->select(\*(Aqsome_table\*(Aq, [\*(Aqid\*(Aq, \*(Aqfoo\*(Aq]); \& \& # "SELECT * FROM some_table WHERE foo = \*(Aqbar\*(Aq" \& $db\->select(\*(Aqsome_table\*(Aq, undef, {foo => \*(Aqbar\*(Aq}); \& \& # "SELECT * FROM some_table WHERE foo LIKE \*(Aq%test%\*(Aq" \& $db\->select(\*(Aqsome_table\*(Aq, undef, {foo => {\-like => \*(Aq%test%\*(Aq}}); .Ve .PP As well as some PostgreSQL specific extensions added by SQL::Abstract::Pg. .PP .Vb 2 \& # "SELECT * FROM foo JOIN bar ON (bar.foo_id = foo.id)" \& $db\->select([\*(Aqfoo\*(Aq, [\*(Aqbar\*(Aq, foo_id => \*(Aqid\*(Aq]]); \& \& # "SELECT * FROM foo LEFT JOIN bar ON (bar.foo_id = foo.id)" \& $db\->select([\*(Aqfoo\*(Aq, [\-left => \*(Aqbar\*(Aq, foo_id => \*(Aqid\*(Aq]]); \& \& # "SELECT foo AS bar FROM some_table" \& $db\->select(\*(Aqsome_table\*(Aq, [[foo => \*(Aqbar\*(Aq]]); \& \& # "SELECT * FROM some_table WHERE foo = \*(Aq[1,2,3]\*(Aq" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, {foo => {\*(Aq=\*(Aq => {\-json => [1, 2, 3]}}}); \& \& # "SELECT EXTRACT(EPOCH FROM foo) AS foo, bar FROM some_table" \& $db\->select(\*(Aqsome_table\*(Aq, [\e\*(Aqextract(epoch from foo) AS foo\*(Aq, \*(Aqbar\*(Aq]); \& \& # "SELECT \*(Aqtest\*(Aq AS foo, bar FROM some_table" \& $db\->select(\*(Aqsome_table\*(Aq, [\e[\*(Aq? AS foo\*(Aq, \*(Aqtest\*(Aq], \*(Aqbar\*(Aq]); .Ve .PP Including a new last argument to pass many new options. .PP .Vb 2 \& # "SELECT * FROM some_table WHERE foo = \*(Aqbar\*(Aq ORDER BY id DESC" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, {foo => \*(Aqbar\*(Aq}, {order_by => {\-desc => \*(Aqid\*(Aq}}); \& \& # "SELECT * FROM some_table LIMIT 10 OFFSET 20" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, undef, {limit => 10, offset => 20}); \& \& # "SELECT * FROM some_table WHERE foo = 23 GROUP BY foo, bar" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, {foo => 23}, {group_by => [\*(Aqfoo\*(Aq, \*(Aqbar\*(Aq]}); \& \& # "SELECT * FROM t WHERE a = \*(Aqb\*(Aq GROUP BY c HAVING d = \*(Aqe\*(Aq" \& $db\->select(\*(Aqt\*(Aq, \*(Aq*\*(Aq, {a => \*(Aqb\*(Aq}, {group_by => [\*(Aqc\*(Aq], having => {d => \*(Aqe\*(Aq}}); \& \& # "SELECT * FROM some_table WHERE id = 1 FOR UPDATE" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, {id => 1}, {for => \*(Aqupdate\*(Aq}); \& \& # "SELECT * FROM some_table WHERE id = 1 FOR UPDATE SKIP LOCKED" \& $db\->select(\*(Aqsome_table\*(Aq, \*(Aq*\*(Aq, {id => 1}, {for => \e\*(Aqupdate skip locked\*(Aq}); .Ve .SS "select_p" .IX Subsection "select_p" .Vb 1 \& my $promise = $db\->select_p($source, $fields, $where, \e%options); .Ve .PP Same as \*(L"select\*(R", but performs all operations non-blocking and returns a Mojo::Promise object instead of accepting a callback. .PP .Vb 5 \& $db\->select_p(some_table => [\*(Aqfoo\*(Aq] => {bar => \*(Aqyada\*(Aq})\->then(sub ($results) { \& ... \& })\->catch(sub ($err) { \& ... \& })\->wait; .Ve .SS "tables" .IX Subsection "tables" .Vb 1 \& my $tables = $db\->tables; .Ve .PP Return table and view names for this database, that are visible to the current user and not internal, as an array reference. .PP .Vb 2 \& # Names of all tables \& say for @{$db\->tables}; .Ve .SS "unlisten" .IX Subsection "unlisten" .Vb 2 \& $db = $db\->unlisten(\*(Aqfoo\*(Aq); \& $db = $db\->unlisten(\*(Aq*\*(Aq); .Ve .PP Unsubscribe from a channel, \f(CW\*(C`*\*(C'\fR can be used to unsubscribe from all channels. .SS "update" .IX Subsection "update" .Vb 1 \& my $results = $db\->update($table, \e%fieldvals, \e%where, \e%options); .Ve .PP Generate an \f(CW\*(C`UPDATE\*(C'\fR statement with \*(L"abstract\*(R" in Mojo::Pg (usually an SQL::Abstract::Pg object) and execute it with \*(L"query\*(R". You can also append a callback to perform operations non-blocking. .PP .Vb 4 \& $db\->update(some_table => {foo => \*(Aqbaz\*(Aq} => {foo => \*(Aqbar\*(Aq} => sub ($db, $err, $results) { \& ... \& }); \& Mojo::IOLoop\->start unless Mojo::IOLoop\->is_running; .Ve .PP Use all the same argument variations you would pass to the \f(CW\*(C`update\*(C'\fR method of SQL::Abstract. .PP .Vb 2 \& # "UPDATE some_table SET foo = \*(Aqbar\*(Aq WHERE id = 23" \& $db\->update(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {id => 23}); \& \& # "UPDATE some_table SET foo = {1,2,3} WHERE id = 23" \& $db\->update(\*(Aqsome_table\*(Aq, {foo => [1, 2, 3]}, {id => 23}); \& \& # "UPDATE some_table SET foo = \*(Aqbar\*(Aq WHERE foo LIKE \*(Aq%test%\*(Aq" \& $db\->update(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {foo => {\-like => \*(Aq%test%\*(Aq}}); \& \& # "UPDATE some_table SET foo = \*(Aqbar\*(Aq WHERE id = 23 RETURNING id" \& $db\->update(\*(Aqsome_table\*(Aq, {foo => \*(Aqbar\*(Aq}, {id => 23}, {returning => \*(Aqid\*(Aq}); \& \& # "UPDATE some_table SET foo = \*(Aq[1,2,3]\*(Aq WHERE bar = 23" \& $db\->update(\*(Aqsome_table\*(Aq, {foo => {\-json => [1, 2, 3]}}, {bar => 23}); .Ve .SS "update_p" .IX Subsection "update_p" .Vb 1 \& my $promise = $db\->update_p($table, \e%fieldvals, \e%where, \e%options); .Ve .PP Same as \*(L"update\*(R", but performs all operations non-blocking and returns a Mojo::Promise object instead of accepting a callback. .PP .Vb 5 \& $db\->update_p(some_table => {foo => \*(Aqbaz\*(Aq} => {foo => \*(Aqbar\*(Aq})\->then(sub ($results) { \& ... \& })\->catch(sub ($err) { \& ... \& })\->wait; .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" Mojo::Pg, Mojolicious::Guides, .