Posts tagged with: #postgresql

How to use perl v5.40's boolean builtins in Mojo::Pg queries

2024-07-13

Perl v5.40 introduced native true and false keywords. Unfortunately not all CPAN modules are ready to use them. One of those not yet ready is Mojo::Pg.

Normally you'd want to pass booleans to your queries as just 1's and 0's. However, since Mojo::JSON's true & false stringify to 1 and 0, my 5.38-using codebase is full of Mojo::Pg queries with Mojo::JSON's true and false as arguments.

This is a problem if I want to upgrade the perl interpreter of that project to Perl v5.40, because if I write "use v5.40;" in the file that contains those boolean keywords, Perl's builtin booleans will be used instead, which don't stringify to 1 and 0, but to 1 and the empty string, which can't be used by DBD::Pg in boolean fields and makes DBD::Pg throw an exception.

The solution I found was to subclass Mojo::Pg::Database, and wrap the query method, so that if Perl's builtin booleans are found, they are replaced in the query with native Pg booleans.

This is the subclass:

package Local::My::Pg::Database;

use v5.40;
use Mojo::Base 'Mojo::Pg::Database';

use DBD::Pg ':pg_types';

use experimental 'builtin';

sub query {
    my ($self, $query) = (shift, shift);
    my $cb = ref $_[-1] eq 'CODE' ? pop : undef;
    my @args = map { builtin::is_bool($_) ? { type => PG_BOOL, value => $_ ? 1 : 0 } : $_ } @_;

    return $self->SUPER::query($query, @args, $cb // ());
}

...which requires the Mojo::Pg object to be told to use it:

$pg->database_class('Local::My::Pg::Database');

This solved my problem.

The other module I had problems with on Perl v5.40 is Mojolicious::Plugin::OpenAPI, which doesn't let the builtin booleans to be used in the API spec. I wrote a patch for that, and might submit it to the author.

Other than those, Mojo::JSON does not stringify builtin booleans to booleans, but to 1 and "" UNLESS Cpanel::JSON::XS is installed, then it works fine.

Have you found other CPAN modules that need to be updated for Perl v5.40's booleans?