First try to implement <group> and <member> directives found in Cocoon.
Sugestions, corrections etc very wellcome.

--- ESQL.pm.R   Tue Jun  5 14:45:05 2001
+++ ESQL.pm     Fri Jul 26 10:28:20 2002
@@ -2,7 +2,7 @@
 
 package AxKit::XSP::ESQL;
 use strict;
-use vars qw/@ISA $VERSION $NS @RESULTS @NAMES @STH @COUNT/;
+use vars qw/@ISA $VERSION $NS @RESULTS @NAMES @STH @COUNT @RESULTS0 @RV/;
 
 @ISA = ('Apache::AxKit::Language::XSP');
 
@@ -13,24 +13,32 @@
 use DBI;
 use AxKit::XSP::Util;
 
+my $groupNumber;
+my @subGroups;
+my @groupStack;
+
 AxKit::XSP::Util->register();
 
 # DBI->trace(1);
 
 sub new_query {
     unshift @RESULTS, {};
+    unshift @RESULTS0, {};
     unshift @NAMES, [];
     unshift @STH, undef;
     unshift @COUNT, 0;
+    unshift @RV, undef;
 #    warn "new_query: ", scalar @STH, "\n";
 }
 
 sub end_query {
     shift @RESULTS;
+    shift @RESULTS0;
     shift @NAMES;
     my $sth = shift @STH;
     $sth->finish();
     shift @COUNT;
+    shift @RV;
 #    warn "end_query: ", scalar @STH, "\n";
 }
 
@@ -43,9 +51,10 @@
     my (@params) = set_null_params(@_);
     my $rv = $STH[0]->execute(@params);
     $NAMES[0] = $STH[0]->{NAME_lc};
-    my %hash;
+    my (%hash, %hash2);
     my $rc = $STH[0]->bind_columns(\@hash{ @{$NAMES[0]} });
-    $RESULTS[0] = \%hash;
+    $RESULTS0[0] = \%hash;
+    $RESULTS[0] = \%hash2;
     return $rv;
 }
 
@@ -67,19 +76,38 @@
 sub get_row {
     my ($ancestor) = @_;
     $ancestor ||= 0;
-    my $res = $STH[$ancestor]->fetch;
-    $COUNT[$ancestor]++ if $res;
+    if ($RV[$ancestor] == 1) { return ();}
+    if (! defined $RV[$ancestor]){
+        $RV[$ancestor] = $STH[$ancestor]->fetch;
+    }
+    %{$RESULTS[$ancestor]} = %{$RESULTS0[$ancestor]};
+    my $res = $RV[$ancestor];
+    if ($res) {
+        $COUNT[$ancestor]++;
+        $RV[$ancestor] = $STH[$ancestor]->fetch;
+       if (! defined $RV[$ancestor]) { $RV[$ancestor]=1;}
+    }
+    else {
+       %{$RESULTS0[$ancestor]} = ();
+    }
     return $res;
 }
 
 sub get_column {
-    my ($column, $ancestor) = @_;
+    my ($column, $ancestor, $next) = @_;
     $ancestor ||= 0;
+    my $r;
+    if (defined $next){
+       $r = \@AxKit::XSP::ESQL::RESULTS0;
+    }
+    else {
+       $r = \@AxKit::XSP::ESQL::RESULTS;
+    }
     if (DBI::looks_like_number($column)) {
-        return $RESULTS[$ancestor]{ $NAMES[$ancestor][$column - 1] };
+        return $$r[$ancestor]{ $NAMES[$ancestor][$column - 1] };
     }
     else {
-        return $RESULTS[$ancestor]{$column};
+        return $$r[$ancestor]{$column};
     }
 }
 
@@ -118,6 +146,25 @@
     return $COUNT[$ancestor];
 }
 
+sub start_document {
+  $groupNumber = 0;
+  @subGroups = ();
+  @groupStack = (0);
+
+    return << 'EOT';
+my (@member_sub, @member_end_sub);
+my @group_value;
+
+sub clean_group_values{
+  foreach my $i (@_) {
+    delete $group_value[$i];
+  }
+  return 1;
+}
+
+EOT
+}
+
 sub parse_char {
     my ($e, $text) = @_;
 
@@ -327,6 +374,25 @@
 if ($rv) {
 EOT
     }
+    elsif ($tag eq 'group') {
+       my $parentGrpNo = $groupStack[-1];
+       $groupNumber++;
+       push(@groupStack, $groupNumber);
+       push(@{$subGroups[$parentGrpNo]}, $groupNumber);
+
+       return '{ my $groupNumber = '.$groupNumber.";\n".
+              '  my $col = "'. $attribs{'group-on'}.'";'.
+               'if ($group_value[$groupNumber] ne 
+        AxKit::XSP::ESQL::get_column($col, $ancestor)){ 
+       $group_value[$groupNumber]=AxKit::XSP::ESQL::get_column($col, $ancestor);
+       do {'."\n";
+    }
+    elsif ($tag eq 'member') {
+       return  << 'EOC';
+if (!defined $member_sub[$groupNumber]) {
+    $member_sub[$groupNumber] = sub {
+EOC
+    }
     else {
         die "Unknown ESQL tag: $tag";
     }
@@ -482,6 +548,30 @@
 $dbh->commit if $transactions;
 EOT
     }
+    elsif ($tag eq 'group') {
+       my $curGroupNumber = pop(@groupStack);
+       return '}}} if (&clean_group_values('.
+               join(',', @subGroups[$curGroupNumber]). << 'EOC';
+)); # cleaning grouping values for subgroups
+} else {
+  if (defined $member_sub[$groupNumber]){
+       &{$member_sub[$groupNumber]}();
+  };
+};
+if ($group_value[$groupNumber] ne AxKit::XSP::ESQL::get_column($col, $ancestor, 1)){ 
+       &{$member_end_sub[$groupNumber]}();
+};
+};
+EOC
+    }
+    elsif ($tag eq 'member') {
+       return << 'EOC';
+}}; 
+&{$member_sub[$groupNumber]}(); # 
+if (!defined $member_end_sub[$groupNumber]) {
+    $member_end_sub[$groupNumber] = sub {
+EOC
+    }
     
     return ";";
 }      
@@ -705,6 +795,25 @@
 
 The contents of this element are executed when the SQL was an update
 statement. The number of rows updated are in the C<$rv> variable.
+
+=head2 C<<esql:group>>
+
+  parent: <esql:row-results>
+
+This tag together with <esql:member> tag provides a way to group
+results the same as in ESQL logicsheet found in Cocoon. The attribute
+"group-on" should contain name of column on which sorting of query 
+results was done. Contents found between <esql:group> and <esql:member>
+is inserted into result document just once for group of rows where
+grouping column's value remains the same. <esql:member> is inserted 
+once for every row. Groups could be nested.
+
+=head2 C<<esql:member>>
+
+  parent: <esql:group>
+
+This tag describes content what should be inserted into document for
+every member of row group. See description of <esql:group>.
 
 =head1 Nested Results
 
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to