From: Dagfinn Ilmari Mannsåker Date: Thu, 9 Jan 2014 17:34:53 +0000 (+0000) Subject: Convert (in)equality with undef to (not) defined/IS NOT NULL ops X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=b01a36887e55fe21df87a25d8d6a7ae63f31d04c;p=dbsrgits%2FData-Query.git Convert (in)equality with undef to (not) defined/IS NOT NULL ops We can't overload defined(), so this is the only way to do it. We're not using IS NULL, since the converter can only hande 1:1 mapping between ops. --- diff --git a/lib/Data/Query/ExprBuilder.pm b/lib/Data/Query/ExprBuilder.pm index 35c0187..3c62973 100644 --- a/lib/Data/Query/ExprBuilder.pm +++ b/lib/Data/Query/ExprBuilder.pm @@ -32,11 +32,36 @@ use overload ( }); } } - qw(+ - * / % ** << >> . < > == != lt le gt ge eq ne), + qw(+ - * / % ** << >> . < > lt le gt ge ), # since 'and' and 'or' aren't operators we borrow the bitwise ops [ '&' => 'and' ], [ '|' => 'or' ], ), + + # equality operators (need undef maping) + (map { + my ($overload, $as) = ref($_) ? @$_ : ($_, $_); + $overload => sub { + Data::Query::ExprBuilder->new({ + expr => grep(!defined, @_[0,1]) + ? (map { $overload =~ /==|eq/ ? perl_operator(not => $_) : $_ } + perl_operator(defined => map { defined($_) ? $_->{expr} : () } @_[0,1])) + : perl_operator( + $as, + map { + (Scalar::Util::blessed($_) + && $_->isa('Data::Query::ExprBuilder')) + ? $_->{expr} + : perl_scalar_value($_) + # we're called with ($left, $right, 0) or ($right, $left, 1) + } $_[2] ? @_[1,0] : @_[0,1] + ) + }); + } + } + qw(== != eq ne) + + ), # unsupported (map { my $op = $_; diff --git a/lib/Data/Query/Renderer/SQL/Naive.pm b/lib/Data/Query/Renderer/SQL/Naive.pm index a84981b..82e4e16 100644 --- a/lib/Data/Query/Renderer/SQL/Naive.pm +++ b/lib/Data/Query/Renderer/SQL/Naive.pm @@ -268,6 +268,7 @@ sub _convert_op { $_ eq '==' and return '='; $_ eq 'eq' and return '='; $_ eq '!' and return 'NOT'; + $_ eq 'defined' and return 'IS NOT NULL'; } return uc $perl_op; # hope! } diff --git a/t/expr.t b/t/expr.t index f53f61f..15e87ce 100644 --- a/t/expr.t +++ b/t/expr.t @@ -103,3 +103,27 @@ expr_is { !$_->foo } args => [ expr { $_->foo } ], }, '! ok'; + +expr_is { $_->foo != undef } + { + type => DQ_OPERATOR, + operator => { Perl => 'defined' }, + args => [ expr { $_->foo } ], + }, + '!= undef => defined'; + +expr_is { $_->foo ne undef } + { + type => DQ_OPERATOR, + operator => { Perl => 'defined' }, + args => [ expr { $_->foo } ], + }, + 'ne undef => defined'; + +expr_is { $_->foo == undef } + expr { !($_->foo != undef) }, + '== undef => not defined'; + +expr_is { $_->foo eq undef } + expr { !($_->foo ne undef) }, + 'eq undef => not defined'; diff --git a/t/sql.t b/t/sql.t index 6bf46e8..b5c9294 100644 --- a/t/sql.t +++ b/t/sql.t @@ -49,6 +49,14 @@ expr_sql_is { !$_->foo } # XXX revisit this why are the parens here [ "( NOT foo )" ], "Unary expression ok"; +expr_sql_is { $_->foo != undef } + [ "foo IS NOT NULL" ], + "!= undef => IS NOT NULL"; + +expr_sql_is { $_->foo == undef } + [ "( NOT foo IS NOT NULL )" ], + "== undef => ( NOT foo IS NOT NULL )"; + expr_sql_is { SELECT { $_->foo } } [ "SELECT foo" ], "Simple identifier"; @@ -66,3 +74,4 @@ expr_sql_is { SELECT { $_->foo => AS("foom"), 1 } } expr_sql_is { SELECT { $_->foo => AS "foom", 1 } } [ "SELECT foo AS foom, ?", binding(1) ], "AS without parens"; +