Author: spadkins
Date: Thu Nov  6 10:42:45 2008
New Revision: 12052

Added:
   p5ee/trunk/App-Repository/lib/App/SessionObject/SQLTranslator.pm

Log:
New file

Added: p5ee/trunk/App-Repository/lib/App/SessionObject/SQLTranslator.pm
==============================================================================
--- (empty file)
+++ p5ee/trunk/App-Repository/lib/App/SessionObject/SQLTranslator.pm    Thu Nov 
 6 10:42:45 2008
@@ -0,0 +1,210 @@
+
+#############################################################################
+## $Id: SQLTranslator.pm 9934 2007-09-11 18:04:00Z spadkins $
+#############################################################################
+
+package App::SessionObject::SQLTranslator;
+$VERSION = (q$Revision: 9934 $ =~ /(\d[\d\.]*)/)[0];  # VERSION numbers 
generated by svn
+
+use App;
+use App::SessionObject;
+
[EMAIL PROTECTED] = ( "App::SessionObject" );
+
+use strict;
+use warnings;
+use Parse::RecDescent;
+
+sub _init {
+    &App::sub_entry if ($App::trace);
+    my ($self, $args) = @_;
+    $self->SUPER::_init();
+    my $grammar = <<'EOF';
+sqlstatement: expression(s) #{ ['EXPR', map {$_->[0]} @item[1..$#item] ] }
+
+expression  : '{' sub_var '}' { ['EXPR', $item[2] ]}
+            | '{' function '}' { ['EXPR', $item[2] ]}
+            | '{' group '}' { ['EXPR', $item[2] ]}
+            | freetext {['FREETEXT', $item[1]]}
+            | '{' subex '}' {['EXPR', $item[2] ] }
+            | '{' freetext {['FREETEXT', [$item[1].$item[2][0]] ]}
+            | '{' {['FREETEXT', $item[1]]}
+
+sub1        : <leftop: group multop group> {['SUBEX', $item[1]]}
+
+sub2        : <leftop: sub1  addop sub1> {['SUBEX', $item[1]]}
+sub3        : <leftop: sub2  boolop sub2> {['SUBEX', $item[1]]}
+sub4        : <leftop: sub3  setop list> {['SUBEX', $item[1]]}
+
+subex       : case | sub4
+
+function    : identifier '(' args ')' {['FUNCTION', $item[1], $item[3]]}
+            | identifier '(' ')'      {['FUNCTION', $item[1] ]}
+
+case        : /case/i subex (when)(s) /else/i subex /end/i
+              {['CASE', $item[2], $item[3], $item[5]]}
+            | /case/i (when)(s) /else/i subex /end/i
+              {['CASE', [SUBEX => [[LITERAL => '']]], $item[2], $item[4]]}
+
+when        :  /when/i subex /then/i subex {[WHEN => [$item[2], $item[4]]]}
+
+list        : '(' args ')'  {['LIST', $item[2]]}
+
+group       : '(' flit ')'  {['GROUP', $item[2]]}
+            | '(' subex ')' {['GROUP', $item[2]]}
+            | '(' args ')'  {['GROUP', $item[2]]}
+            | flit          {$item[1]}
+            | '(' group ')' {['GROUP', $item[2]]}
+
+addop       : /[-+]/        { ['OP', $item[1]] }
+multop      : /[\/*%]/      { ['OP', $item[1]] }
+boolop      : /!=|==?|>=?|<=?|is|or|and|regexp|like/i  {['OP', $item[1]]}
+setop       : /in/i         { ['OP', $item[1]]}
+
+freetext    :<skip: qr//> (/[^\{]+/)(s)
+
+args        : <leftop: subex ',' subex>
+
+flit        : function | literal | expression
+
+sub_var     : variable ':' literal {['SUBSTITUTION', $item[1], $item[3]]}
+            | variable {['SUBSTITUTION', $item[1]]}
+
+literal     : /-?\d*\.\d+/ {['LITERAL', $item[1]]}
+            | /-?\d+/  {['LITERAL', $item[1]]}
+            | <perl_quotelike>
+              {['LITERAL', $item[1][0].$item[1][1].$item[1][2].$item[1][3]]}
+            | /[[:alnum:]\._]+/ {['LITERAL', $item[1]]}
+
+variable    : /[_[:alpha:]][[:alnum:]_]*/ {['VAR', $item[1]]}
+
+identifier  : /[_[:alpha:]][[:alnum:]_]*/ {['IDENTIFIER', $item[1] ]}
+
+EOF
+
+    $self->{parser} = Parse::RecDescent->new($grammar);
+    $self->_init_operator_table();
+    $self->_init_function_table();
+    &App::sub_exit() if ($App::trace);
+}
+
+sub _init_operator_table {
+    my ($self) = @_;
+    $self->{operator_table} = {
+    };
+}
+
+sub _init_function_table {
+    my ($self) = @_;
+    $self->{function_table} = {
+    };
+}
+
+sub translate {
+    my ($self, $expr) = @_;
+    return $self->evaluate($self->{parser}->sqlstatement($expr));
+}
+
+sub evaluate {
+    my ($self, $tree) = @_;
+    my (@args, $ret, @ret);
+
+    my %jump_table  = (
+        FUNCTION => sub { shift->function(@{$_[0]}[1,2]) },
+        LITERAL => sub {shift; $_[0]->[1]},
+        OP => sub {shift; $_[0]->[1]},
+        IDENTIFIER => sub {shift; $_[0]->[1]},
+        EXPR => sub {$_[1] = $_[1]->[1];goto &evaluate},
+        SUBSTITUTION => sub { shift->substitution(@{$_[0]}[1,2]) },
+        SUBEX => sub { shift->subex(@[EMAIL PROTECTED]) },
+        GROUP => sub { shift->group($_[0][1]) },
+        LIST => sub { shift->list($_[0][1]) },
+        FREETEXT => sub {shift;  $_[0]->[1][0] },
+        VAR => sub {shift; $_[0]->[1] },
+        WHEN => sub { $self = shift;
+          join "", ' WHEN ', $self->evaluate($_[0][1][0]),
+          ' THEN ', $self->evaluate($_[0][1][1])
+        },
+        CASE => sub { my $self = shift; join "",
+            ' CASE ', $self->evaluate($_[0][1]),
+                      $self->evaluate($_[0][2]),
+            ' ELSE ', $self->evaluate( $_[0][3]),
+            ' END'
+        },
+    );
+
+    if (ref($tree->[0]) eq 'ARRAY') {
+        for my $tre (@{$tree}) {
+            push (@ret,  $jump_table{$tre->[0]}->($self,$tre));
+            #print STDERR "evaluate(): tree : [EMAIL PROTECTED] => 
$ret[$#ret]\n";
+        }
+    }
+    else {
+        push (@ret,  $jump_table{$tree->[0]}->($self, $tree));
+        #print STDERR "evaluate(): tree : [EMAIL PROTECTED] => $ret[$#ret]\n";
+    }
+    return join("", @ret);
+}
+
+sub function {
+    my ($self, $name, $args) = @_;
+    my @fargs  = map { $self->evaluate( $_) } @{$args || []};
+
+    my $function_table = $self->{function_table};
+    return(defined $function_table->{lc($name->[1])} ?
+             $function_table->{lc($name->[1])}->(@fargs) :
+             $name->[1]."(".(join ",", @fargs).")");
+}
+
+sub substitution {
+    my ($self, $var, $value) = @_;
+
+    my $name = $var->[1];
+    my $default = defined $value->[1] ? $value->[1] : '';
+
+    return qq{$default};
+}
+
+sub subex {
+    my $self = shift;
+
+    my @arr = @_;
+
+    my $operator_table = $self->{operator_table};
+    for my $op (split /\|/, q(in|!=|==|=|>|<|>=|<=|is|or|and|regexp)) {
+        $operator_table->{$op} = sub {my @arg = @_;return "$arg[0] $op 
$arg[1]"};
+    }
+    return $self->evaluate( $arr[0]) if !$arr[1];
+    my @ret;
+    push @ret, $self->evaluate(shift @arr);
+    while (my $op = shift @arr) {
+       if (exists($operator_table->{$op->[1]})) {
+           push (@ret, $operator_table->{$op->[1]}->(pop @ret, 
$self->evaluate( shift @arr)));
+       } else {
+           push (@ret, $op->[1], $self->evaluate(shift @arr));
+       }
+    }
+    return @ret;
+}
+
+sub group {
+    my ($self, $first, $op, $second) = @_;
+
+    my @group = $self->evaluate($first);
+
+    # If the number of elements were not reduced to 1. Add () and stringify as
+    # an element. Otherwise return our element. () not needed for single value.
+    if (@group > 1) {
+        return "(". (join "",@group). ")";
+    }
+    return @group;
+}
+
+sub list {
+    my ($self, $subex) = @_;
+    my @list = $self->evaluate($subex);
+    return "(". (join ",",@list). ")";
+}
+
+1;
+

Reply via email to