only default in $_ if @_ is empty, not if $_[0] exists but is undef
[dbsrgits/Data-Query.git] / lib / Data / Query / Renderer / SQL / Naive.pm
index 6e16fb8..3f2c1a6 100644 (file)
@@ -2,12 +2,11 @@ package Data::Query::Renderer::SQL::Naive;
 
 use strictures 1;
 
-sub intersperse { my $i = shift; my @i = map +($_, $i), @_; pop @i; @i }
-
 use SQL::ReservedWords;
 use Data::Query::ExprHelpers;
 
 use Moo;
+use namespace::clean;
 
 has reserved_ident_parts => (
   is => 'ro', default => sub {
@@ -79,6 +78,9 @@ sub _flatten_structure {
 sub _format_keyword { $_[0]->lc_keywords ? lc($_[1]) : $_[1] }
 
 sub _render {
+  unless (ref($_[1]) eq 'HASH') {
+    die "Expected hashref, got ".(defined($_[1])?$_[1]:'undef');
+  }
   $_[0]->${\"_render_${\(lc($_[1]->{type})||'broken')}"}($_[1]);
 }
 
@@ -141,7 +143,7 @@ sub _render_operator {
 sub _maybe_parenthesise {
   my ($self, $dq) = @_;
   for ($dq) {
-    return is_Select() || is_Slice()
+    return is_Select() || is_Group() || is_Slice() || is_Having()
       ? [ '(', $self->_render($dq), ')' ]
       : $self->_render($dq);
   }
@@ -231,7 +233,7 @@ sub _handle_op_type_between {
   if (@args == 3) {
     my ($lhs, $rhs1, $rhs2) = (map $self->_maybe_parenthesise($_), @args);
     [ '(', $lhs, $op_name, $rhs1, 'AND', $rhs2, ')' ];
-  } elsif (@args == 2 and is_Literal $args[1]->{type}) {
+  } elsif (@args == 2 and is_Literal $args[1]) {
     my ($lhs, $rhs) = (map $self->_render($_), @args);
     [ '(', $lhs, $op_name, $rhs, ')' ];
   } else {
@@ -310,7 +312,7 @@ sub _render_alias {
   }
   return [
     $self->_maybe_parenthesise($dq->{from}),
-    $as || ' ',
+    $as || '',
     $self->_render_identifier({ elements => [ $dq->{to} ] })
   ];
 }
@@ -356,6 +358,10 @@ sub _render_join {
 sub _render_where {
   my ($self, $dq) = @_;
   my ($from, $where) = @{$dq}{qw(from where)};
+  while (is_Where $from) {
+    $where = Operator({ 'SQL.Naive' => 'and' }, [ $where, $from->{where} ]);
+    $from = $from->{from};
+  }
   my $keyword = (is_Group($from) ? 'HAVING' : 'WHERE');
   [
     ($from ? $self->_render($from) : ()),
@@ -364,14 +370,24 @@ sub _render_where {
   ]
 }
 
-sub _render_order {
+sub _order_chunk {
   my ($self, $dq) = @_;
-  my @ret = (
-    $self->_format_keyword('ORDER BY'),
+  return +(
     $self->_render($dq->{by}),
     ($dq->{reverse}
       ? $self->_format_keyword('DESC')
-      : ())
+      : ()),
+    ($dq->{nulls}
+      ? $self->_format_keyword('NULLS '.('', qw(FIRST LAST))[$dq->{nulls}])
+      : ()),
+  );
+}
+
+sub _render_order {
+  my ($self, $dq) = @_;
+  my @ret = (
+    $self->_format_keyword('ORDER BY'),
+    $self->_order_chunk($dq),
   );
   my $from;
   while ($from = $dq->{from}) {
@@ -379,10 +395,7 @@ sub _render_order {
     $dq = $from;
     push @ret, (
       ',',
-      $self->_render($dq->{by}),
-      ($dq->{reverse}
-        ? $self->_format_keyword('DESC')
-        : ())
+      $self->_order_chunk($dq),
     );
   }
   unshift @ret, $self->_render($from) if $from;
@@ -451,11 +464,13 @@ sub _render_insert {
     ($names
       ? ('(', intersperse(',', map $self->_render($_), @$names), ')')
       : ()),
-    $self->_format_keyword('VALUES'),
-    intersperse(',',
-      map [ '(', intersperse(',', map $self->_render($_), @$_), ')' ],
-        @$values
-    ),
+    (@$values && @{$values->[0]}
+      ? ($self->_format_keyword('VALUES'),
+         intersperse(',',
+           map [ '(', intersperse(',', map $self->_render($_), @$_), ')' ],
+             @$values
+         ))
+      : ($self->_insert_default_values)),
     ($returning
       ? ($self->_format_keyword('RETURNING'),
          intersperse(',', map $self->_render($_), @$returning))
@@ -463,4 +478,9 @@ sub _render_insert {
   ];
 }
 
+sub _insert_default_values {
+  my ($self) = @_;
+  $self->_format_keyword('DEFAULT VALUES'),
+}
+
 1;