home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / Statement.pm < prev    next >
Encoding:
Perl POD Document  |  2002-10-26  |  83.4 KB  |  2,583 lines

  1. package SQL::Statement;
  2. #########################################################################
  3. #
  4. # This module is copyright (c), 2001 by Jeff Zucker, All Rights Reserved
  5. #
  6. # It may be freely distributed under the same terms as Perl itself.
  7. #
  8. # See below for help (search for SYNOPSIS)
  9. #########################################################################
  10.  
  11. use strict;
  12. use SQL::Parser;
  13. use SQL::Eval;
  14. use vars qw($VERSION $numexp $s2pops $arg_num $dlm);
  15. #use locale;
  16.  
  17. $VERSION = '1.005';
  18.  
  19. $dlm = '~';
  20. $arg_num=0;
  21. $s2pops = {
  22.               'LIKE'   => {'s'=>'LIKE',n=>'LIKE'},
  23.               'CLIKE'  => {'s'=>'CLIKE',n=>'CLIKE'},
  24.               'RLIKE'  => {'s'=>'RLIKE',n=>'RLIKE'},
  25.               '<'  => {'s'=>'lt',n=>'<'},
  26.               '>'  => {'s'=>'gt',n=>'>'},
  27.               '>=' => {'s'=>'ge',n=>'>='},
  28.               '<=' => {'s'=>'le',n=>'<='},
  29.               '='  => {'s'=>'eq',n=>'=='},
  30.               '<>' => {'s'=>'ne',n=>'!='},
  31. };
  32. BEGIN {
  33.   if ($] < 5.005 ) {
  34.     sub qr {}
  35.   }
  36. }
  37. sub new {
  38.     my $class  = shift;
  39.     my $sql    = shift;
  40.     my $flags  = shift;
  41.     #
  42.     # IF USER DEFINED extend_csv IN SCRIPT
  43.     # USE THE ANYDATA DIALECT RATHER THAN THE CSV DIALECT
  44.     # WITH DBD::CSV
  45.     #
  46.     if ($main::extend_csv or $main::extend_sql ) {
  47.        $flags = SQL::Parser->new('AnyData');
  48.     }
  49.     my $parser = $flags;
  50.     my $self   = new2($class);
  51.     $flags->{"PrintError"}    = 1 unless defined $flags->{"PrintError"};
  52.     $flags->{"text_numbers"}  = 1 unless defined $flags->{"text_numbers"};
  53.     $flags->{"alpha_compare"} = 1 unless defined $flags->{"alpha_compare"};
  54.     for (keys %$flags) {
  55.         $self->{$_}=$flags->{$_};
  56.     }
  57.     my $parser_dialect = $flags->{"dialect"} || 'AnyData';
  58.     $parser_dialect = 'AnyData' if $parser_dialect =~ /^(CSV|Excel)$/;
  59.  
  60.     if (!ref($parser) or (ref($parser) and ref($parser) !~ /^SQL::Parser/)) {
  61.  #   if (!ref($parser)) {
  62. #         print "NEW PARSER\n";
  63.         $parser = new SQL::Parser($parser_dialect,$flags);
  64.     }
  65. #       unless ref $parser and ref $parser =~ /^SQL::Parser/;
  66. #    $parser = new SQL::Parser($parser_dialect,$flags) ;
  67.  
  68.     if ($] < 5.005 ) {
  69.     $numexp = exists $self->{"text_numbers"}
  70.         ? '^([+-]?|\s+)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$'
  71.         : '^\s*[+-]?\s*\.?\s*\d';
  72.   }
  73.     else {
  74.     $numexp = exists $self->{"text_numbers"}
  75. ###new
  76. #        ? qr/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/
  77.         ? qr/^([+-]?|\s+)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/
  78. ###endnew
  79.         : qr/^\s*[+-]?\s*\.?\s*\d/;
  80.     }
  81. #use mylibs; zwarn $self; exit;
  82.     $self->prepare($sql,$parser);
  83.     return $self;
  84. }
  85.  
  86. sub new2 {
  87.     my $class  = shift;
  88.     my $self   = {};
  89.     return bless $self, $class;
  90. }
  91.  
  92. sub prepare {
  93.     my $self   = shift;
  94.     my $sql    = shift;
  95.     return $self if $self->{"already_prepared"}->{"$sql"};
  96.     my $parser =  shift;
  97.     my $rv;
  98.     if( $rv = $parser->parse($sql) ) {
  99.        %$self = (%$self,%{$parser->{"struct"}});
  100.        my $tables  = $self->{"table_names"};
  101.        my $columns = $parser->{"struct"}->{"column_names"};
  102.        if ($columns and scalar @$columns == 1 and $columns->[0] eq '*') {
  103.         $self->{"asterisked_columns"} = 1;
  104.        }
  105.        undef $self->{"columns"};
  106.        my $values  = $self->{"values"};
  107.        my $param_num = -1;
  108.        if ($self->{"limit_clause"}) {
  109.      $self->{"limit_clause"} =
  110.              SQL::Statement::Limit->new( $self->{"limit_clause"} );
  111.        }
  112.        my $max_placeholders = $self->{num_placeholders} || 0;
  113.        #print $self->command, " [$max_placeholders]\n";
  114.        if ($max_placeholders) {
  115.            for my $i(0..$max_placeholders-1) {
  116.                $self->{"params"}->[$i] = SQL::Statement::Param->new($i);
  117.            }
  118.        }
  119.        if ($self->{"sort_spec_list"}) {
  120.            for my $i(0..scalar @{$self->{"sort_spec_list"}} -1 ) {
  121.                 my($col,$direction) = each %{ $self->{"sort_spec_list"}->[$i] };
  122.                 my $tname;
  123.                  if ($col && $col=~/(.*)\.(.*)/) {
  124.                     $tname = $1; $col=$2;
  125.                 }
  126.                undef $direction unless $direction && $direction eq 'DESC';
  127.                $self->{"sort_spec_list"}->[$i] =
  128.                     SQL::Statement::Order->new(
  129.                         col   => SQL::Statement::Column->new($col,[$tname]),
  130.                         desc  => $direction,
  131.                     );
  132.            }
  133.        }
  134.        for (@$columns) {
  135.            push @{ $self->{"columns"} },
  136.                 SQL::Statement::Column->new($_,$tables);
  137.        }
  138.        for (@$tables) {
  139.            push @{ $self->{"tables"} },
  140.                 SQL::Statement::Table->new($_);
  141.        }
  142.        if ($self->{"where_clause"}) {
  143.            if ($self->{"where_clause"}->{"combiners"}) {
  144.                for ( @{ $self->{"where_clause"}->{"combiners"} } ) {
  145.                    if(/OR/i) { $self->{"has_OR"} = 1; last;}
  146.                }
  147.            }
  148.        }
  149.        $self->{"already_prepared"}->{"$sql"}++;
  150.        return $self;
  151.     }
  152.     else {
  153.        $self->{"errstr"} =  $parser->errstr;
  154.        $self->{"already_prepared"}->{"$sql"}++;
  155.        return undef;
  156.     }
  157. }
  158.  
  159. sub execute {
  160.     my($self, $data, $params) = @_;
  161.     $self->{'params'}= $params;
  162.     my($table, $msg);
  163.     my($command) = $self->command();
  164.     return DBI::set_err($self, 1, 'No command found!') unless $command;
  165.     ($self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'},
  166.           $self->{'data'}) = $self->$command($data, $params);
  167.     my $tables;
  168.     my $names = $self->{NAME};
  169.     @{$self->{NAME}} = map {
  170.         my $org = $self->{ORG_NAME}->{$_};
  171.         $org =~ s/^"//;
  172.         $org =~ s/"$//;
  173.         $org =~ s/""/"/g;
  174.         $org;
  175.     } @$names;
  176.     @$tables = map {$_->{"name"}} @{ $self->{"tables"} };
  177.     delete $self->{'tables'};  # Force closing the tables
  178.     for (@$tables) {
  179.         push @{ $self->{"tables"} }, SQL::Statement::Table->new($_);
  180.     }
  181.     $self->{'NUM_OF_ROWS'} || '0E0';
  182. }
  183.  
  184.  
  185. sub CREATE ($$$) {
  186.     my($self, $data, $params) = @_;
  187.     my($eval,$foo) = $self->open_tables($data, 1, 1);
  188.     return undef unless $eval;
  189.     $eval->params($params);
  190.     my($row) = [];
  191.     my($col);
  192.     my($table) = $eval->table($self->tables(0)->name());
  193.     foreach $col ($self->columns()) {
  194.         push(@$row, $col->name());
  195.     }
  196.     $table->push_names($data, $row);
  197.     (0, 0);
  198. }
  199.  
  200. sub DROP ($$$) {
  201.     my($self, $data, $params) = @_;
  202. #use mylibs; zwarn $self; exit;
  203.     if ($self->{ignore_missing_table}) {
  204.          undef $@;
  205.          eval { $self->open_tables($data,0,0) };
  206.          if ($@ and $@ =~ /no such (table|file)/i ) {
  207.              return (-1,0);
  208.      }
  209.     }
  210.     my($eval) = $self->open_tables($data, 0, 1);
  211. #    return undef unless $eval;
  212.     return (-1,0) unless $eval;
  213. #    $eval->params($params);
  214.     my($table) = $eval->table($self->tables(0)->name());
  215.     $table->drop($data);
  216. #use mylibs; zwarn $self->{f_stmt};
  217.     (-1, 0);
  218. }
  219.  
  220. sub INSERT ($$$) {
  221.     my($self, $data, $params) = @_;
  222.     my($eval,$all_cols) = $self->open_tables($data, 0, 1);
  223.     return undef unless $eval;
  224.     $eval->params($params);
  225.     $self->verify_columns($eval, $all_cols) if scalar ($self->columns());
  226.     my($table) = $eval->table($self->tables(0)->name());
  227.     $table->seek($data, 0, 2);
  228.     my($array) = [];
  229.     my($val, $col, $i);
  230. ###    my($columns) = $table->{'colNums'};
  231.     my($cNum) = scalar($self->columns());
  232.     my $param_num = 0;
  233.     if ($cNum) {
  234.         # INSERT INTO $table (row, ...) VALUES (value, ...)
  235.         for ($i = 0;  $i < $cNum;  $i++) {
  236.             $col = $self->columns($i);
  237.             $val = $self->row_values($i);
  238.             if ($val and ref($val) eq 'SQL::Statement::Param') {
  239.                 $val = $eval->param($val->num());
  240.             }
  241.             elsif ($val and $val->{type} eq 'placeholder') {
  242.                 $val = $eval->param($param_num++);
  243.         }
  244.             else {
  245.              $val = $self->get_row_value($val,$eval);
  246.         }
  247. #print $col->name."~".$self->{ORG_NAME}->{$col->name}."\n";
  248. #        my $ccnum = $table->column_num($col->name);
  249. #        if (!defined $ccnum) {
  250. #                $ccnum = $table->column_num(qq/"$col->name"/);
  251. #        }
  252. #            $array->[$ccnum] = $val;
  253.             $array->[$table->column_num($col->name())] = $val;
  254. #            $array->[$table->column_num(lc $col->name())] = $val;
  255.  
  256. #if ( $self->{ORG_NAME}->{$col->name} ) {
  257. #    $col = qq/"/.$self->{ORG_NAME}->{$col}.qq/"/;
  258. #} 
  259. #            $array->[$table->column_num($col->name())] = $val;
  260.         }
  261.     } else {
  262.         return $self->do_err("Bad col names in INSERT");
  263.         # INSERT INTO $table VALUES (value, ...)
  264.         # NOT USED BECAUSE $cNum automatically assigned
  265. #        $cNum = scalar($self->row_values());
  266. #        for ($i = 0;  $i < $cNum;  $i++) {
  267. #            $val = $self->row_values($i);
  268. #            $val = $self->get_row_value($val);
  269. #            if (ref($val) eq 'SQL::Statement::Param') {
  270. #                $val = $eval->param($val->num());
  271. #            }
  272. #            $array->[$i] = $val;
  273. #        }
  274.     }
  275.     $table->push_row($data, $array);
  276.     (1, 0);
  277. }
  278.  
  279. sub DELETE ($$$) {
  280.     my($self, $data, $params) = @_;
  281.     my($eval,$all_cols) = $self->open_tables($data, 0, 1);
  282.     return undef unless $eval;
  283.     $eval->params($params);
  284.     $self->verify_columns($eval, $all_cols);
  285.     my($table) = $eval->table($self->tables(0)->name());
  286.     my($affected) = 0;
  287.     my(@rows, $array);
  288.     while ($array = $table->fetch_row($data)) {
  289.         if ($self->eval_where($eval,'',$array)) {
  290.             ++$affected;
  291.         } else {
  292.             push(@rows, $array);
  293.         }
  294.     }
  295.     $table->seek($data, 0, 0);
  296.     foreach $array (@rows) {
  297.         $table->push_row($data, $array);
  298.     }
  299.     $table->truncate($data);
  300.     ($affected, 0);
  301. }
  302.  
  303. sub UPDATE ($$$) {
  304.     my($self, $data, $params) = @_;
  305.     my $valnum = $self->{num_val_placeholders};
  306. #print "@$params -- $valnum\n";
  307.     if ($valnum) {
  308. #print "[$valnum]";
  309. #my @val_params;
  310.         my @val_params   = splice @$params, 0,$valnum;
  311.         @$params = (@$params,@val_params);
  312. #        my @where_params = $params->[$valnum+1..scalar @$params-1];
  313. #        @$params = (@where_params,@val_params);
  314.     }
  315. #print "@$params\n"; exit;
  316.     my($eval,$all_cols) = $self->open_tables($data, 0, 1);
  317.     return undef unless $eval;
  318.     $eval->params($params);
  319.     $self->verify_columns($eval, $all_cols);
  320.     my($table) = $eval->table($self->tables(0)->name());
  321.     my $tname = $self->tables(0)->name();
  322.     my($affected) = 0;
  323.     my(@rows, $array, $val, $col, $i);
  324.     while ($array = $table->fetch_row($data)) {
  325.         if ($self->eval_where($eval,$tname,$array)) {
  326.         my $param_num =$arg_num;
  327.         #print $param_num;
  328.         #print $eval->param($param_num); print "@$params"; exit;
  329.         #$arg_num = 0;
  330.     my $col_nums = $eval->{"tables"}->{"$tname"}->{"col_nums"} ;
  331.     my $cols;
  332.     %$cols   = reverse %{ $col_nums };
  333.     my $rowhash;
  334.     #print "$tname -- @$rowary\n";
  335.     for (sort keys %$cols) {
  336.         $rowhash->{$cols->{$_}} = $array->[$_];
  337.     }
  338.             for ($i = 0;  $i < $self->columns();  $i++) {
  339.                 $col = $self->columns($i);
  340.                 $val = $self->row_values($i);
  341.                 if (ref($val) eq 'SQL::Statement::Param') {
  342.                     $val = $eval->param($val->num());
  343.                 }
  344.                 elsif ($val->{type} eq 'placeholder') {
  345.                     $val = $eval->param($param_num++);
  346.             }
  347.                 else {
  348.                      $val = $self->get_row_value($val,$eval,$rowhash);
  349.             }
  350.                 $array->[$table->column_num($col->name())] = $val;
  351.             }
  352.             ++$affected;
  353.         }
  354.         push(@rows, $array);
  355.     }
  356.     $table->seek($data, 0, 0);
  357.     foreach $array (@rows) {
  358.         $table->push_row($data, $array);
  359.     }
  360.     $table->truncate($data);
  361.     ($affected, 0);
  362. }
  363.  
  364. sub find_join_columns {
  365.     my $self = shift;
  366.     my @all_cols = @_;
  367.     my $display_combine = 'NONE';
  368.     $display_combine = 'NATURAL' if $self->{"join"}->{"type"} =~ /NATURAL/;
  369.     $display_combine = 'USING'   if $self->{"join"}->{"clause"} =~ /USING/;
  370.     $display_combine = 'NAMED' if !$self->{"asterisked_columns"};
  371.     my @display_cols;
  372.     my @keycols = ();
  373.     @keycols = @{ $self->{"join"}->{"keycols"} } if $self->{"join"}->{"keycols"};
  374.     @keycols  = map {s/\./$dlm/; $_} @keycols;
  375.     my %is_key_col;
  376.     %is_key_col = map { $_=> 1 } @keycols;
  377.  
  378.     # IF NAMED COLUMNS, USE NAMED COLUMNS
  379.     #
  380.     if ($display_combine eq 'NAMED') {
  381.         @display_cols =  $self->columns;
  382.         @display_cols = map {$_->table . $dlm . $_->name} @display_cols;
  383.     }
  384.  
  385.     # IF ASTERISKED COLUMNS AND NOT NATURAL OR USING
  386.     # USE ALL COLUMNS, IN ORDER OF NAMING OF TABLES
  387.     #
  388.     elsif ($display_combine eq 'NONE') {
  389.         @display_cols =  @all_cols;
  390.     }
  391.  
  392.     # IF NATURAL, COMBINE ALL SHARED COLUMNS
  393.     # IF USING, COMBINE ALL KEY COLUMNS
  394.     #
  395.     else  {
  396.         my %is_natural;
  397.         for my $full_col(@all_cols) {
  398.             my($table,$col) = $full_col =~ /^([^$dlm]+)$dlm(.+)$/;
  399.             next if $display_combine eq 'NATURAL' and $is_natural{$col};
  400.             next if $display_combine eq 'USING' and $is_natural{$col} and
  401.                  $is_key_col{$col};
  402.             push @display_cols,  $full_col;
  403.             $is_natural{$col}++;
  404.         }
  405.     }
  406.     my @shared = ();
  407.     my %is_shared;
  408.     if ($self->{"join"}->{"type"} =~ /NATURAL/ ) {
  409.         for my $full_col(@all_cols) {
  410.             my($table,$col) = $full_col =~ /^([^$dlm]+)$dlm(.+)$/;
  411.             push @shared, $col if  $is_shared{$col}++;
  412.         }
  413.     }
  414.     else {
  415.         @shared = @keycols;
  416.         # @shared = map {s/^[^_]*_(.+)$/$1/; $_} @keycols;
  417.         # @shared = grep !$is_shared{$_}++, @shared
  418.     }
  419.     #print "<@display_cols>\n";
  420.     $self->{"join"}->{"shared_cols"} = \@shared;
  421.     $self->{"join"}->{"display_cols"} = \@display_cols;
  422.     # print "@shared : @display_cols\n";
  423. }
  424.  
  425. sub JOIN {
  426.     my($self, $data, $params) = @_;
  427.     if ($self->{"join"}->{"type"} =~ /RIGHT/ ) {
  428.         my @tables = $self->tables;
  429.         $self->{"tables"}->[0] = $tables[1];
  430.         $self->{"tables"}->[1] = $tables[0];
  431.     }
  432.     my($eval,$all_cols) = $self->open_tables($data, 0, 0);
  433.     return undef unless $eval;
  434.     $eval->params($params);
  435.     $self->verify_columns( $eval, $all_cols );
  436. ###new
  437.     if ($self->{"join"}->{"keycols"} 
  438.      and $self->{"join"}->{"table_order"}
  439.      and scalar @{$self->{"join"}->{"table_order"}} == 0
  440.     ) {
  441.         $self->{"join"}->{"table_order"} = $self->order_joins(
  442.             $self->{"join"}->{"keycols"}
  443.         );
  444.     }
  445. ###newend
  446.     my @tables = $self->tables;
  447.     @tables = map {$_->name} @tables;
  448.  
  449.     # GET THE LIST OF QUALIFIED COLUMN NAMES FOR DISPLAY
  450.     # *IN ORDER BY NAMING OF TABLES*
  451.     #
  452.     my @all_cols;
  453.     for my $table(@tables) {
  454.         my @cols = @{ $eval->table($table)->col_names };
  455. #@cols = map {lc $_} @cols;
  456.         for (@cols) {
  457.             push @all_cols, $table . $dlm . $_;
  458.     }
  459.     }
  460.     $self->find_join_columns(@all_cols);
  461.  
  462.     # JOIN THE TABLES
  463.     # *IN ORDER *BY JOINS*
  464.     #
  465.     @tables = @{ $self->{"join"}->{"table_order"} }
  466.            if $self->{"join"}->{"table_order"}
  467.            and $self->{"join"}->{"type"} !~ /RIGHT/;
  468.     my $tableA;
  469.     my $tableB;
  470.     $tableA = shift @tables;
  471.     $tableB = shift @tables;
  472.     my $tableAobj = $eval->table($tableA);
  473.     my $tableBobj = $eval->table($tableB);
  474. #use mylibs; print $tableA; zwarn $tableAobj; exit;
  475.     $tableAobj->{"REAL_NAME"} = $tableAobj->{"NAME"} ||= $tableA;
  476.     $tableBobj->{"REAL_NAME"} = $tableBobj->{"NAME"} ||= $tableB;
  477.     if (my $aliasA = $self->{table_alias}->{$tableA}) {
  478.         $tableAobj->{"NAME"} = shift @{$self->{table_alias}->{$tableA}};
  479.     }
  480.     if (my $aliasB = $self->{table_alias}->{$tableB}) {
  481.         $tableBobj->{"NAME"} =  shift @{$self->{table_alias}->{$tableB}} ;
  482.     }
  483.  
  484. #use mylibs; zwarn $self;
  485. #die "$tableA,$tableB";
  486.     $self->join_2_tables($data,$params,$tableAobj,$tableBobj);
  487.     for my $next_table(@tables) {
  488.         $tableAobj = $self->{"join"}->{"table"};
  489.         $tableBobj = $eval->table($next_table);
  490.         $tableBobj->{"NAME"} ||= $next_table;
  491.         $self->join_2_tables($data,$params,$tableAobj,$tableBobj);
  492.         $self->{"cur_table"} = $next_table;
  493.     }
  494.     return $self->SELECT($data,$params);
  495. }
  496.  
  497. sub join_2_tables {
  498.     my($self, $data, $params, $tableAobj, $tableBobj) = @_;
  499.     #print "<< ".$self->{"cur_table"}." >>\n" if $self->{"cur_table"};
  500.     my $tableA = $tableAobj->{"NAME"};
  501.     my $tableB = $tableBobj->{"NAME"};
  502.     my $share_type = 'IMPLICIT';
  503.     $share_type    = 'NATURAL' if $self->{"join"}->{"type"} =~ /NATURAL/;
  504.     $share_type    = 'USING'   if $self->{"join"}->{"clause"} =~ /USING/;
  505.     $share_type    = 'ON' if $self->{"join"}->{"clause"} =~ /ON/;
  506.     my $join_type  = 'INNER';
  507.     $join_type     = 'LEFT'  if $self->{"join"}->{"type"} =~ /LEFT/;
  508.     $join_type     = 'RIGHT' if $self->{"join"}->{"type"} =~ /RIGHT/;
  509.     $join_type     = 'FULL'  if $self->{"join"}->{"type"} =~ /FULL/;
  510.     my @colsA = @{$tableAobj->col_names};
  511.     my @colsB = @{$tableBobj->col_names};
  512.     my %iscolA = map { $_=>1} @colsA;
  513.     my %iscolB = map { $_=>1} @colsB;
  514.     my %isunqualA = map { $_=>1} @colsA;
  515.     my %isunqualB = map { $_=>1} @colsB;
  516.     my @shared_cols;
  517.     my %is_shared;
  518.     my @tmpshared = @{ $self->{"join"}->{"shared_cols"} };
  519.     if ($share_type eq 'ON' and $join_type eq 'RIGHT') {
  520.         @tmpshared = reverse @tmpshared;
  521.     }
  522.     if ($share_type eq 'USING') {
  523.         for (@tmpshared) {
  524.              push @shared_cols, $tableA . $dlm . $_;
  525.              push @shared_cols, $tableB . $dlm . $_;
  526.         }
  527.     }
  528.     if ($share_type eq 'NATURAL') {
  529.         for my $c(@colsA) {
  530.             $c =~ s/^[^$dlm]+$dlm(.+)$/$1/ if $tableA eq "${dlm}tmp";
  531.          if ($iscolB{$c}) {
  532.                 push @shared_cols, $tableA . $dlm . $c;
  533.                 push @shared_cols, $tableB . $dlm . $c;
  534.         }
  535.         }
  536.     }
  537.     my @all_cols = map { $tableA . $dlm . $_ } @colsA;
  538.     @all_cols = ( @all_cols, map { $tableB . $dlm . $_ } @colsB);
  539.     @all_cols = map { s/${dlm}tmp$dlm//; $_; } @all_cols;
  540.     if ($tableA eq "${dlm}tmp") {
  541.         #@colsA = map {s/^[^_]+_(.+)$/$1/; $_; } @colsA;
  542.     }
  543.     else {
  544.         @colsA = map { $tableA . $dlm . $_ } @colsA;
  545.     }
  546.     @colsB = map { $tableB . $dlm . $_ } @colsB;
  547.     my %isa;
  548.     my $i=0;
  549.     my $col_numsA = { map { $_=>$i++}  @colsA };
  550.     $i=0;
  551.     my $col_numsB = { map { $_=>$i++} @colsB };
  552.     %iscolA = map { $_=>1} @colsA;
  553.     %iscolB = map { $_=>1} @colsB;
  554.     my @blankA = map {undef} @colsA;
  555.     my @blankB = map {undef} @colsB;
  556.     if ($share_type =~/^(ON|IMPLICIT)$/ ) {
  557.         while (@tmpshared) {
  558.             my $k1 = shift @tmpshared;
  559.             my $k2 = shift @tmpshared;
  560.             next unless ($iscolA{$k1} or $iscolB{$k1});
  561.             next unless ($iscolA{$k2} or $iscolB{$k2});
  562.             next if !$iscolB{$k1} and !$iscolB{$k2};
  563.             my($t,$c) = $k1 =~ /^([^$dlm]+)$dlm(.+)$/;
  564. ###new
  565.             next if !$isunqualA{$c};
  566. #            next if !$isunqualB{$c};
  567. ###newend
  568.             push @shared_cols, $k1 unless $is_shared{$k1}++;
  569.             ($t,$c) = $k2 =~ /^([^$dlm]+)$dlm(.+)$/;
  570.             next if !$isunqualB{$c};
  571.             push @shared_cols, $k2 if !$is_shared{$k2}++;
  572.         }
  573.     }
  574.     %is_shared = map {$_=>1} @shared_cols;
  575. #    $self->do_err("Can't find shared columns!") unless @shared_cols;
  576.     for my $c(@shared_cols) {
  577.       if ( !$iscolA{$c} and !$iscolB{$c} ) {
  578.           $self->do_err("Can't find shared columns!");
  579.       }
  580.     }
  581.     my($posA,$posB)=([],[]);
  582.     for my $f(@shared_cols) {
  583.          push @$posA, $col_numsA->{$f} if $iscolA{$f};
  584.          push @$posB, $col_numsB->{$f} if $iscolB{$f};
  585.     }
  586.     if ($share_type eq 'ON') {
  587. }
  588.  
  589.     # CYCLE THROUGH TABLE B, CREATING A HASH OF ITS VALUES
  590.     #
  591.     my $hashB={};
  592.     while (my $array = $tableBobj->fetch_row($data)) {
  593.         my $has_null_key=0;
  594.         my @key_vals = @$array[@$posB];
  595.         for (@key_vals) { next if defined $_; $has_null_key++; last; }
  596.         next if $has_null_key and  $join_type eq 'INNER';
  597.         my $hashkey = join ' ',@key_vals;
  598.         push @{$hashB->{"$hashkey"}}, $array;
  599.     }
  600.  
  601.     # CYCLE THROUGH TABLE A
  602.     #
  603.     my $joined_table;
  604.     my %visited;
  605.     while (my $arrayA = $tableAobj->fetch_row($data)) {
  606.         my $has_null_key = 0;
  607.         my @key_vals = @$arrayA[@$posA];
  608.         for (@key_vals) { next if defined $_; $has_null_key++; last; }
  609.         next if ($has_null_key and  $join_type eq 'INNER');
  610.         my $hashkey = join ' ',@key_vals;
  611.         my $rowsB = $hashB->{"$hashkey"};
  612.         if (!defined $rowsB and $join_type ne 'INNER' ) {
  613.             push @$rowsB, \@blankB;
  614.     }
  615.         for my $arrayB(@$rowsB) {
  616.             my @newRow = (@$arrayA,@$arrayB);
  617.             if ($join_type ne 'UNION' ) {
  618.                  push @$joined_table,\@newRow;
  619.              }
  620.         }
  621.         $visited{$hashkey}++; #        delete $hashB->{"$hashkey"};
  622.     }
  623.  
  624.     # ADD THE LEFTOVER B ROWS IF NEEDED
  625.     #
  626.     if ($join_type=~/(FULL|UNION)/) {
  627.       while (my($k,$v)= each%$hashB) {
  628.          next if $visited{$k};
  629.       for my $rowB(@$v) {
  630.              my @arrayA;
  631.              my @tmpB;
  632.              my $rowhash;
  633.              @{$rowhash}{@colsB}=@$rowB;
  634.              for my $c(@all_cols) {
  635.                  my($table,$col) = $c =~ /^([^$dlm]+)$dlm(.+)/;
  636.                  push @arrayA,undef if $table eq $tableA;
  637.                  push @tmpB,$rowhash->{$c} if $table eq $tableB;
  638.          }
  639.              @arrayA[@$posA]=@tmpB[@$posB] if $share_type =~ /(NATURAL|USING)/;
  640.              my @newRow = (@arrayA,@tmpB);
  641.              push @$joined_table, \@newRow;
  642.      }
  643.       }
  644.     }
  645.     undef $hashB;
  646.     undef $tableAobj;
  647.     undef $tableBobj;
  648.     $self->{"join"}->{"table"} =
  649.         SQL::Statement::TempTable->new(
  650.             $dlm . 'tmp',
  651.             \@all_cols,
  652.             $self->{"join"}->{"display_cols"},
  653.             $joined_table
  654.     );
  655. }
  656.  
  657. sub SELECT ($$) {
  658.     my($self, $data, $params) = @_;
  659.     $self->{"params"} ||= $params;
  660.     my($eval,$all_cols,$tableName,$table);
  661.     if (defined $self->{"join"}) {
  662.         return $self->JOIN($data,$params) if !defined $self->{"join"}->{"table"};
  663.         $tableName = $dlm . 'tmp';
  664.         $table     = $self->{"join"}->{"table"};
  665.     }
  666.     else {
  667.         ($eval,$all_cols) = $self->open_tables($data, 0, 0);
  668.         return undef unless $eval;
  669.         $eval->params($params);
  670.         $self->verify_columns( $eval, $all_cols );
  671.         $tableName = $self->tables(0)->name();
  672.         $table = $eval->table($tableName);
  673.     }
  674.     my $rows = [];
  675.  
  676.     # In a loop, build the list of columns to retrieve; this will be
  677.     # used both for fetching data and ordering.
  678.     my($cList, $col, $tbl, $ar, $i, $c);
  679.     my $numFields = 0;
  680.     my %columns;
  681.     my @names;
  682.     if ($self->{"join"}) {
  683.           @names = @{ $table->col_names };
  684.           for my $col(@names) {
  685.              $columns{$tableName}->{"$col"} = $numFields++;
  686.              push(@$cList, $table->column_num($col));
  687.           }
  688.     }
  689.     else {
  690.         foreach my $column ($self->columns()) {
  691.             #next unless defined $column and ref $column;
  692.             if (ref($column) eq 'SQL::Statement::Param') {
  693.                 my $val = $eval->param($column->num());
  694.                 if ($val =~ /(.*)\.(.*)/) {
  695.                     $col = $1;
  696.                     $tbl = $2;
  697.                 } else {
  698.                     $col = $val;
  699.                     $tbl = $tableName;
  700.                 }
  701.             } else {
  702.                 ($col, $tbl) = ($column->name(), $column->table());
  703.         }
  704.         if ($col eq '*') {
  705.             $ar = $table->col_names();
  706. #@$ar = map {lc $_} @$ar;
  707.             for ($i = 0;  $i < @$ar;  $i++) {
  708.                 my $cName = $ar->[$i];
  709.                 $columns{$tbl}->{"$cName"} = $numFields++;
  710.                 $c = SQL::Statement::Column->new({'table' => $tableName,
  711.                                                   'column' => $cName});
  712.                 push(@$cList, $i);
  713.                 push(@names, $cName);
  714.             }
  715.         } else {
  716.             $columns{$tbl}->{"$col"} = $numFields++;
  717.             push(@$cList, $table->column_num($col));
  718.             push(@names, $col);
  719.         }
  720.     }
  721.     }
  722.     $cList = [] unless defined $cList;
  723.     $self->{'NAME'} = \@names;
  724.     if ($self->{"join"}) {
  725.         @{$self->{'NAME'}} = map { s/^[^$dlm]+$dlm//; $_} @names;
  726.     }
  727.     $self->verify_order_cols($table);
  728.     my @order_by = $self->order();
  729.     my @extraSortCols = ();
  730.     my $distinct = $self->distinct();
  731.     if ($distinct) {
  732.         # Silently extend the ORDER BY clause to the full list of
  733.         # columns.
  734.         my %ordered_cols;
  735.         foreach my $column (@order_by) {
  736.             ($col, $tbl) = ($column->column(), $column->table());
  737.             $tbl ||= $self->colname2table($col);
  738.             $ordered_cols{$tbl}->{"$col"} = 1;
  739.         }
  740.         while (my($tbl, $cref) = each %columns) {
  741.             foreach my $col (keys %$cref) {
  742.                 if (!$ordered_cols{$tbl}->{"$col"}) {
  743.                     $ordered_cols{$tbl}->{"$col"} = 1;
  744.                     push(@order_by,
  745.                          SQL::Statement::Order->new
  746.                          ('col' => SQL::Statement::Column->new
  747.                           ({'table' => $tbl,
  748.                             'column' => $col}),
  749.                           'desc' => 0));
  750.                 }
  751.             }
  752.         }
  753.     }
  754.     if (@order_by) {
  755.         my $nFields = $numFields;
  756.         # It is possible that the user gave an ORDER BY clause with columns
  757.         # that are not part of $cList yet. These columns will need to be
  758.         # present in the array of arrays for sorting, but will be stripped
  759.         # off later.
  760.         my $i=-1;
  761.         foreach my $column (@order_by) {
  762.             $i++;
  763.             ($col, $tbl) = ($column->column(), $column->table());
  764.             my $pos;
  765.             if ($self->{"join"}) {
  766.                   $tbl ||= $self->colname2table($col);
  767.                   $pos = $table->column_num($tbl."$dlm$col");
  768.                   if (!defined $pos) {
  769.                   $tbl = $self->colname2table($col);
  770.                   $pos = $table->column_num($tbl."_$col");
  771.           }
  772.         }
  773.             $tbl ||= $self->colname2table($col);
  774.             #print "$tbl~\n";
  775.             next if exists($columns{$tbl}->{"$col"});
  776.             $pos = $table->column_num($col) unless defined $pos;
  777.             push(@extraSortCols, $pos);
  778.             $columns{$tbl}->{"$col"} = $nFields++;
  779.         }
  780.     }
  781.     my $e = $eval;
  782.     if ($self->{"join"}) {
  783.           $e = $table;
  784.     }
  785.     while (my $array = $table->fetch_row($data)) {
  786.         if ($self->eval_where($e,$tableName,$array)) {
  787.             # Note we also include the columns from @extraSortCols that
  788.             # have to be ripped off later!
  789.             my @row;
  790.             #            if (!scalar @$cList or !scalar @extraSortCols) {
  791.             #               @row = @$array;
  792.             #        }
  793.             #            else {
  794.                 @extraSortCols = () unless @extraSortCols;
  795.             #print "[$_]" for @$cList; print "\n";
  796. ###new
  797.             @row = map { defined $_ and defined $array->[$_] ? $array->[$_] : undef } (@$cList, @extraSortCols);
  798.             #        }
  799.             push(@$rows, \@row);
  800.         }
  801.     }
  802.     if (@order_by) {
  803.         my @sortCols = map {
  804.             my $col = $_->column();
  805.             my $tbl = $_->table();
  806.          if ($self->{"join"}) {
  807.                $tbl = 'shared' if $table->is_shared($col);
  808.                $tbl ||= $self->colname2table($col);
  809.         }
  810.             #print $table->col_table(0),'~',$tbl,'~',$_->column(); exit;
  811.              $tbl ||= $self->colname2table($col);
  812.              ($columns{$tbl}->{"$col"}, $_->desc())
  813.         } @order_by;
  814.         #die "\n<@sortCols>@order_by\n";
  815.         my($c, $d, $colNum, $desc);
  816.         my $sortFunc = sub {
  817.             my $result;
  818.             $i = 0;
  819.             do {
  820.                 $colNum = $sortCols[$i++];
  821.                 $desc = $sortCols[$i++];
  822.                 $c = $a->[$colNum];
  823.                 $d = $b->[$colNum];
  824.                 if (!defined($c)) {
  825.                     $result = defined $d ? -1 : 0;
  826.                 } elsif (!defined($d)) {
  827.                     $result = 1;
  828. #            } elsif ( is_number($c) && is_number($d) ) {
  829.             } elsif ( $c =~ $numexp && $d =~ $numexp ) {
  830.                     $result = ($c <=> $d);
  831.                 } else {
  832.               if ($self->{"case_fold"}) {
  833.                         $result = lc $c cmp lc $d || $c cmp $d;
  834.             }
  835.                     else {
  836.                         $result = $c cmp $d;
  837.             }
  838.                 }
  839.                 if ($desc) {
  840.                     $result = -$result;
  841.                 }
  842.             } while (!$result  &&  $i < @sortCols);
  843.             $result;
  844.         };
  845.         if ($distinct) {
  846.             my $prev;
  847.             @$rows = map {
  848.                 if ($prev) {
  849.                     $a = $_;
  850.                     $b = $prev;
  851.                     if (&$sortFunc() == 0) {
  852.                         ();
  853.                     } else {
  854.                         $prev = $_;
  855.                     }
  856.                 } else {
  857.                     $prev = $_;
  858.                 }
  859.             } ($] > 5.00504 ?
  860.                sort $sortFunc @$rows :
  861.                sort { &$sortFunc } @$rows);
  862.         } else {
  863.             @$rows = $] > 5.00504 ?
  864.                 (sort $sortFunc @$rows) :
  865.                 (sort { &$sortFunc } @$rows)
  866.         }
  867.  
  868.         # Rip off columns that have been added for @extraSortCols only
  869.         if (@extraSortCols) {
  870.             foreach my $row (@$rows) {
  871.                 splice(@$row, $numFields, scalar(@extraSortCols));
  872.             }
  873.         }
  874.     }
  875.     if ($self->{"join"}) {
  876.         my @final_cols = @{$self->{"join"}->{"display_cols"}};
  877.         @final_cols = map {$table->column_num($_)} @final_cols;
  878.         my @names = map { $self->{"NAME"}->[$_]} @final_cols;
  879. #        my @names = map { $self->{"REAL_NAME"}->[$_]} @final_cols;
  880.         $numFields = scalar @names;
  881.         $self->{"NAME"} = \@names;
  882.         my $i = -1;
  883.         for my $row(@$rows) {
  884.             $i++;
  885.             @{ $rows->[$i] } = @$row[@final_cols];
  886.         }
  887.     }
  888.     if (defined $self->{"limit_clause"}) {
  889.         my $offset = $self->{"limit_clause"}->offset || 0;
  890.         my $limit  = $self->{"limit_clause"}->limit  || 0;
  891.         @$rows = splice @$rows, $offset, $limit;
  892.     }
  893.     if ($self->{"set_function"}) {
  894.         my $numrows = scalar( @$rows );
  895.         my $numcols = scalar @{ $self->{"NAME"} };
  896.         my $i=0;
  897.         my %colnum = map {$_=>$i++} @{ $self->{"NAME"} };
  898.         for my $i(0 .. scalar @{$self->{"set_function"}} -1 ) {
  899.             my $arg = $self->{"set_function"}->[$i]->{"arg"};
  900.             $self->{"set_function"}->[$i]->{"sel_col_num"} = $colnum{$arg} if defined $colnum{$arg};
  901.         }
  902.         my($name,$arg,$sel_col_num);
  903.         my @set;
  904.         my $final=0;
  905.         $numrows=0;
  906.         my @final_row = map {undef} @{$self->{"set_function"}};
  907.   #      my $start;
  908.         for my $c(@$rows) {
  909.             $numrows++;
  910.             my $sf_index = -1;
  911.          for my $sf(@{$self->{"set_function"}}) {
  912.               $sf_index++;
  913.           if ($sf->{"arg"} eq '*') {
  914.                   $final_row[$sf_index]++;
  915.           }
  916.               else {
  917.                 my $v = $c->[$sf->{"sel_col_num"}];
  918.                 my $name = $sf->{"name"};
  919.                 next unless defined $v;
  920.                 my $final = $final_row[$sf_index];
  921.                 $final++      if $name =~ /COUNT/;
  922. #                $final += $v  if $name =~ /SUM|AVG/;
  923.                 if( $name =~ /SUM|AVG/) {
  924.                     return $self->do_err("Can't use $name on a string!")
  925.                       unless $v =~ $numexp;
  926.                     $final += $v;
  927.                 }
  928.                 #
  929.                 # Thanks Dean Kopesky dean.kopesky@reuters.com
  930.                 # submitted patch to make MIN/MAX do cmp on strings
  931.                 # and == on numbers
  932.                 #
  933.                 # but thanks also to Michael Kovacs mkovacs@turing.une.edu.au
  934.                 # for catching a problem when a MAX column is 0
  935.                 # necessitating !$final instead of ! defined $final
  936.                 #
  937.                 $final  = $v  if !$final
  938.                               or ( $name eq 'MAX'
  939.                                    and $v
  940.                                    and $final
  941.                                    and anycmp($v,$final) > 0
  942.                                  );
  943.                 $final  = $v  if !$final
  944.                               or ( $name eq 'MIN' 
  945.                                    and defined $v
  946.                                    and anycmp($v,$final) < 0
  947.                                   );
  948.                 $final_row[$sf_index] = $final;
  949.           }
  950.         }
  951.     }
  952.         for my $i(0..$#final_row) {
  953.       if ($self->{"set_function"}->[$i]->{"name"} eq 'AVG') {
  954.               $final_row[$i] = $final_row[$i]/$numrows;
  955.       }
  956.     }
  957.         return ( $numrows, scalar @final_row, [\@final_row]);
  958.     }
  959.     (scalar(@$rows), $numFields, $rows);
  960. }
  961.  
  962. sub anycmp($$) {
  963.     my ($a,$b) = @_;
  964.     $a = '' unless defined $a;
  965.     $b = '' unless defined $b;
  966.     return ($a =~ $numexp && $b =~ $numexp)
  967.         ? ($a <=> $b)
  968.         : ($a cmp $b);
  969. }
  970.  
  971.  
  972. sub eval_where {
  973.     my $self   = shift;
  974.     my $eval   = shift;
  975.     my $tname  = shift;
  976.     my $rowary = shift;
  977.     $tname ||= $self->tables(0)->name();
  978.     my $where = $self->{"where_clause"} || return 1;
  979.     my $cols;
  980.     my $col_nums;
  981.     if ($self->{"join"}) {
  982.         $col_nums = $eval->{"col_nums"};
  983.     }
  984.     else {
  985.         $col_nums = $eval->{"tables"}->{"$tname"}->{"col_nums"} ;
  986.     }
  987.     %$cols   = reverse %{ $col_nums };
  988.     my $rowhash;
  989.     #print "$tname -- @$rowary\n";
  990.     for (sort keys %$cols) {
  991.         $rowhash->{$cols->{$_}} = $rowary->[$_];
  992.     }
  993.     my @truths;
  994.     $arg_num=0;
  995.     return $self->process_predicate ($where,$eval,$rowhash);
  996. }
  997.  
  998. sub process_predicate {
  999.     my($self,$pred,$eval,$rowhash) = @_;
  1000.     if ($pred->{op} eq 'OR') {
  1001.         my $match1 = $self->process_predicate($pred->{"arg1"},$eval,$rowhash);
  1002.         return 1 if $match1 and !$pred->{"neg"};
  1003.         my $match2 = $self->process_predicate($pred->{"arg2"},$eval,$rowhash);
  1004.         if ($pred->{"neg"}) {
  1005.             return (!$match1 and !$match2) ? 1 : 0;
  1006.         }
  1007.         else {
  1008.         return $match2 ? 1 : 0;
  1009.     }
  1010.     }
  1011.     elsif ($pred->{op} eq 'AND') {
  1012.         my $match1 = $self->process_predicate($pred->{"arg1"},$eval,$rowhash);
  1013.         if ($pred->{"neg"}) {
  1014.         return 1 unless $match1;
  1015.         }
  1016.         else {
  1017.         return 0 unless $match1;
  1018.     }
  1019.         my $match2 = $self->process_predicate($pred->{"arg2"},$eval,$rowhash);
  1020.         if ($pred->{"neg"}) {
  1021.             return $match2 ? 0 : 1;
  1022.         }
  1023.         else {
  1024.         return $match2 ? 1 : 0;
  1025.     }
  1026.     }
  1027.     else {
  1028.         my $val1 = $self->get_row_value( $pred->{"arg1"}, $eval, $rowhash );
  1029.         my $val2 = $self->get_row_value( $pred->{"arg2"}, $eval, $rowhash );
  1030.         my $op   = $pred->{op};
  1031.         if ("DBD or AnyData") {
  1032.           if ( $op !~ /^IS/i and (
  1033.               !defined $val1 or $val1 eq '' or
  1034.               !defined $val2 or $val2 eq '' 
  1035.             )) {
  1036.                   $op = $s2pops->{"$op"}->{'s'};
  1037.         }
  1038.             else {
  1039.                 if (defined $val1 and defined $val2 and $op !~ /^IS/i ) {
  1040.                     $op = ( $val1 =~ $numexp && $val2 =~ $numexp )
  1041.                         ? $s2pops->{"$op"}->{'n'}
  1042.                         : $s2pops->{"$op"}->{'s'};
  1043.                 }
  1044.         }
  1045.     }
  1046.         else {
  1047.             if (defined $val1 and defined $val2 and $op !~ /^IS/i ) {
  1048.                 $op = ( $val1 =~ $numexp && $val2 =~ $numexp )
  1049.                     ? $s2pops->{"$op"}->{'n'}
  1050.                     : $s2pops->{"$op"}->{'s'};
  1051.         }
  1052.         }
  1053. #        print "[$val1] [$op] [$val2]\n";
  1054.         my $match = $self->is_matched($val1,$op,$val2) || 0;
  1055.         if ($pred->{"neg"}) {
  1056.            $match = $match ? 0 : 1;
  1057.         }
  1058.         return $match;
  1059.     }
  1060. }
  1061.  
  1062. sub is_number {
  1063.     my $x=shift;
  1064.     return 0 if !defined $x;
  1065.     return 1 if $x =~ /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/;
  1066.     return 0;
  1067. }
  1068. sub is_matched {
  1069.     my($self,$val1,$op,$val2)=@_;
  1070.     #print "[$val1] [$op] [$val2]\n";
  1071.  
  1072.     # if DBD::CSV or AnyData
  1073.         if ($op eq 'IS') {
  1074.             return 1 if (!defined $val1 or $val1 eq '');
  1075.             return 0;
  1076.         }
  1077.         $val1 = '' unless defined $val1;
  1078.         $val2 = '' unless defined $val2;
  1079.     # else
  1080. #print "$val1 ~ $op ~ $val2\n";
  1081.         if ($op eq 'IS') {
  1082.             return defined $val1 ? 0 : 1;
  1083.         }
  1084.     return undef if !defined $val1 or !defined $val2;
  1085.     if ($op =~ /LIKE|CLIKE/i) {
  1086.         $val2 = quotemeta($val2);
  1087.         $val2 =~ s/\\%/.*/g;
  1088.         $val2 =~ s/_/./g;
  1089.     }
  1090.     if ( !$self->{"alpha_compare"} && $op =~ /lt|gt|le|ge/ ) {
  1091.         return 0;
  1092.     }
  1093.     # print "[$val1] [$val2]\n";
  1094.     if ($op eq 'LIKE' )  { return $val1 =~ /^$val2$/s;  }
  1095.     if ($op eq 'CLIKE' ) { return $val1 =~ /^$val2$/si; }
  1096.     if ($op eq 'RLIKE' ) { return $val1 =~ /$val2/is;   }
  1097.     if ($op eq '<' ) { return $val1 <  $val2; }
  1098.     if ($op eq '>' ) { return $val1 >  $val2; }
  1099.     if ($op eq '==') { return $val1 == $val2; }
  1100.     if ($op eq '!=') { return $val1 != $val2; }
  1101.     if ($op eq '<=') { return $val1 <= $val2; }
  1102.     if ($op eq '>=') { return $val1 >= $val2; }
  1103.     if ($op eq 'lt') { return $val1 lt $val2; }
  1104.     if ($op eq 'gt') { return $val1 gt $val2; }
  1105.     if ($op eq 'eq') { return $val1 eq $val2; }
  1106.     if ($op eq 'ne') { return $val1 ne $val2; }
  1107.     if ($op eq 'le') { return $val1 le $val2; }
  1108.     if ($op eq 'ge') { return $val1 ge $val2; }
  1109. }
  1110.  
  1111. sub open_tables {
  1112.     my($self, $data, $createMode, $lockMode) = @_;
  1113.     my @call = caller 4;
  1114.     my $caller = $call[3];
  1115.     if ($caller) {
  1116.         $caller =~ s/^([^:]*::[^:]*)::.*$/$1/;
  1117.     }
  1118.     my @c;
  1119.     my $t;
  1120.     my $is_col;
  1121.     my @tables = $self->tables;
  1122.     my $count=-1;
  1123.     for ( @tables) {
  1124.         $count++;
  1125.         my $name = $_->{"name"};
  1126.         undef $@;
  1127.         eval{
  1128.             my $open_name = $name;
  1129.             $open_name = $self->{org_table_names}->[$count];
  1130. #print "[$topen_name]";
  1131.            if ($caller && $caller =~ /^DBD::AnyData/) {
  1132.                $caller .= '::Statement' if $caller !~ /::Statement/;
  1133.                $t->{"$name"} = $caller->open_table($data, $open_name,
  1134.                                                    $createMode, $lockMode);
  1135.        }
  1136.            else {
  1137.                $t->{"$name"} = $self->open_table($data, $open_name,
  1138.                                                  $createMode, $lockMode);
  1139.        }
  1140.  
  1141.     };
  1142.         my $err = $t->{"$name"}->{errstr};
  1143.         return $self->do_err($err) if $err;
  1144.         return $self->do_err($@) if $@;
  1145.         return(SQL::Eval->new({'tables' => $t}), [])
  1146.             if $self->command eq 'DROP';
  1147. my @cnames;
  1148. for my $c(@{$t->{"$name"}->{"col_names"}}) {
  1149.   my $newc;
  1150.   if ($c =~ /^"/) {
  1151.  #    $c =~ s/^"(.+)"$/$1/;
  1152.      $newc = $c;
  1153.   }
  1154.   else {
  1155. #     $newc = lc $c;
  1156.      $newc = uc $c;
  1157.   }
  1158.    push @cnames, $newc;
  1159.    $self->{ORG_NAME}->{$newc}=$c;
  1160. #   push @{$self->{ORG_NAME}},$c;
  1161.  
  1162. }
  1163. my $col_nums;
  1164. my $i=0;
  1165. for (@cnames) {
  1166.   $col_nums->{$_} = $i++;
  1167. }
  1168. $t->{"$name"}->{"col_nums"}  = $col_nums;
  1169. $t->{"$name"}->{"col_names"} = \@cnames;
  1170. #use mylibs; zwarn $t->{$name};
  1171.         my $tcols = $t->{"$name"}->col_names;
  1172. # @$tcols = map{lc $_} @$tcols ;
  1173.     ###z        @$tcols = map{$name.'.'.$_} @$tcols ;
  1174.         my @newcols;
  1175.         for (@$tcols) {
  1176.             next unless defined $_;
  1177.             my $ncol = $_;
  1178.             $ncol = $name.'.'.$ncol unless $ncol =~ /\./;
  1179.             push @newcols, $ncol;
  1180.     }
  1181.         @c = ( @c, @newcols );
  1182.     }
  1183.     my $all_cols = $self->{all_cols} || [];
  1184.     @$all_cols = (@$all_cols,@c);
  1185.     $self->{all_cols} = $all_cols;
  1186.     return SQL::Eval->new({'tables' => $t}), \@c;
  1187. }
  1188.  
  1189. sub verify_columns {
  1190.     my( $self, $eval, $all_cols )  = @_;
  1191.     $all_cols ||= [];
  1192.     my @tmp_cols  = @$all_cols;
  1193. #    my @tmp_cols  = map{lc $_} @$all_cols;
  1194.     my $usr_cols;
  1195.     my $cnum=0;
  1196.     my @tmpcols = $self->columns;
  1197.  
  1198. ###z
  1199. #    for (@tmpcols) {
  1200. #        $_->{"table"} = lc $_->{"table"};
  1201. #    }
  1202. #use mylibs; print $self->command; zwarn \@tmpcols;
  1203. ###z
  1204.     for my $c(@tmpcols) {
  1205.        if ($c->{"name"} eq '*' and defined $c->{"table"}) {
  1206.           return $self->do_err("Can't find table ". $c->{"table"})
  1207.               unless $eval->{"tables"}->{$c->{"table"}};
  1208.           my $tcols = $eval->{"tables"}->{$c->{"table"}}->col_names;
  1209. # @$tcols = map{lc $_} @$tcols ;
  1210.           return $self->do_err("Couldn't find column names!")
  1211.               unless $tcols and ref $tcols eq 'ARRAY' and @$tcols;
  1212.           for (@$tcols) {
  1213.               push @$usr_cols, SQL::Statement::Column->new( $_,
  1214.                                                             [$c->{"table"}]
  1215.                                                           );
  1216.       }
  1217.        }
  1218.        else {
  1219.       push @$usr_cols, SQL::Statement::Column->new( $c->{"name"},
  1220.                                                         [$c->{"table"}]
  1221.                                                       );
  1222.        }
  1223.     }
  1224.     $self->{"columns"} = $usr_cols;
  1225.     @tmpcols = map {$_->{name}} @$usr_cols;
  1226. #     @tmpcols = map {lc $_->{name}} @$usr_cols;
  1227.     my $fully_qualified_cols=[];
  1228.  
  1229.     my %col_exists   = map {$_=>1} @tmp_cols;
  1230.  
  1231.  
  1232.     my %short_exists = map {s/^([^.]*)\.(.*)/$1/; $2=>$1} @tmp_cols;
  1233.     my(%is_member,@duplicates,%is_duplicate);
  1234.     @duplicates = map {s/[^.]*\.(.*)/$1/; $_} @$all_cols;
  1235.     @duplicates = grep($is_member{$_}++, @duplicates);
  1236.     %is_duplicate = map { $_=>1} @duplicates;
  1237.     my $is_fully;
  1238.     my $i=-1;
  1239.     my $num_tables = $self->tables;
  1240.     for my $c(@tmpcols) {
  1241.        my($table,$col);
  1242.        if ($c =~ /(\S+)\.(\S+)/) {
  1243.            $table = $1;
  1244.            $col   = $2;
  1245.        }
  1246.        else {
  1247.        $i++;
  1248.        ($table,$col) = ( $usr_cols->[$i]->{"table"},
  1249.                          $usr_cols->[$i]->{"name"}
  1250.                        );
  1251.        }
  1252.        next unless $col;
  1253. ###new
  1254.        if (ref $table eq 'SQL::Statement::Table') {
  1255.           $table = $table->name;
  1256.        }
  1257. ###endnew
  1258. #print "Content-type: text/html\n\n"; print $self->command; print "$col!!!<p>";
  1259.        if ( $col eq '*' and $num_tables == 1) {
  1260.           $table ||= $self->tables->[0]->{"name"};
  1261.           if (ref $table eq 'SQL::Statement::Table') {
  1262.             $table = $table->name;
  1263.           }
  1264.           my @table_names = $self->tables;
  1265.           my $tcols = $eval->{"tables"}->{"$table"}->col_names;
  1266. # @$tcols = map{lc $_} @$tcols ;
  1267.           return $self->do_err("Couldn't find column names!")
  1268.               unless $tcols and ref $tcols eq 'ARRAY' and @$tcols;
  1269.           for (@$tcols) {
  1270.               push @{ $self->{"columns"} },
  1271.                     SQL::Statement::Column->new($_,\@table_names);
  1272.           }
  1273.           $fully_qualified_cols = $tcols;
  1274.           my @newcols;
  1275.       for (@{$self->{"columns"}}) {
  1276.               push @newcols,$_ unless $_->{"name"} eq '*';
  1277.       }
  1278.           $self->{"columns"} = \@newcols;
  1279.        }
  1280.        elsif ( $col eq '*' and defined $table) {
  1281.               $table = $table->name if ref $table eq 'SQL::Statement::Table';
  1282.               my $tcols = $eval->{"tables"}->{"$table"}->col_names;
  1283. # @$tcols = map{lc $_} @$tcols ;
  1284.           return $self->do_err("Couldn't find column names!")
  1285.               unless $tcols and ref $tcols eq 'ARRAY' and @$tcols;
  1286.               for (@$tcols) {
  1287.                   push @{ $self->{"columns"} },
  1288.                         SQL::Statement::Column->new($_,[$table]);
  1289.               }
  1290.               @{$fully_qualified_cols} = (@{$fully_qualified_cols}, @$tcols);
  1291.        }
  1292.        elsif ( $col eq '*' and $num_tables > 1) {
  1293.           my @table_names = $self->tables;
  1294.           for my $table(@table_names) {
  1295.               $table = $table->name if ref $table eq 'SQL::Statement::Table';
  1296.               my $tcols = $eval->{"tables"}->{"$table"}->col_names;
  1297. # @$tcols = map{lc $_} @$tcols ;
  1298.           return $self->do_err("Couldn't find column names!")
  1299.               unless $tcols and ref $tcols eq 'ARRAY' and @$tcols;
  1300.               for (@$tcols) {
  1301.                   push @{ $self->{"columns"} },
  1302.                         SQL::Statement::Column->new($_,[$table]);
  1303.               }
  1304.               @{$fully_qualified_cols} = (@{$fully_qualified_cols}, @$tcols);
  1305.               my @newcols;
  1306.             for (@{$self->{"columns"}}) {
  1307.                   push @newcols,$_ unless $_->{"name"} eq '*';
  1308.           }
  1309.               $self->{"columns"} = \@newcols;
  1310.       }
  1311.        }
  1312.        else {
  1313. #print "[$c~$col]\n";
  1314. #use mylibs; zwarn \%col_exists;
  1315.            if (!$table) {
  1316.                return $self->do_err("Ambiguous column name '$c'")
  1317.                    if $is_duplicate{$c};
  1318.                return $self->do_err("No such column '$c'")
  1319.                       unless $short_exists{"$c"} or ($c !~ /^"/ and $short_exists{"\U$c"});
  1320.                $table = $short_exists{"$c"};
  1321.                $col   = $c;
  1322.            }
  1323.            else {
  1324.          if ($self->command eq 'SELECT') {
  1325. #print "$table.$col\n";
  1326. #if ($col_exists{qq/$table."/.$self->{ORG_NAME}->{$col}.qq/"/}) {
  1327. #    $col = q/"/.$self->{ORG_NAME}->{$col}.q/"/;
  1328. #} 
  1329. #print qq/$table."$col"/;
  1330. # use mylibs; zwarn $self->{ORG_NAME};
  1331.          }
  1332. #use mylibs; zwarn \%col_exists;
  1333. #print "<$table . $col>";
  1334.                return $self->do_err("No such column '$table.$col'")
  1335. #                     unless $col_exists{"\L$table.$col"};
  1336.                      unless $col_exists{"$table.$col"}
  1337.                       or $col_exists{"\L$table.".$col};
  1338. ;#                         or $col_exists{qq/$table."/.$self->{ORG_NAME}->{$col}.qq/"/}
  1339. ;
  1340.            }
  1341.            next if $is_fully->{"$table.$col"};
  1342. ####
  1343.   $self->{"columns"}->[$i]->{"name"} = $col;
  1344. ####
  1345.            $self->{"columns"}->[$i]->{"table"} = $table;
  1346.            push @$fully_qualified_cols, "$table.$col";
  1347.            $is_fully->{"$table.$col"}++;
  1348.        }
  1349.        if ( $col eq '*' and defined $table) {
  1350.               my @newcols;
  1351.             for (@{$self->{"columns"}}) {
  1352.                   push @newcols,$_ unless $_->{"name"} eq '*';
  1353.           }
  1354.               $self->{"columns"} = \@newcols;
  1355.        }
  1356.     }
  1357. #use mylibs; zwarn $fully_qualified_cols;
  1358.  
  1359.     return $fully_qualified_cols;
  1360. }
  1361.  
  1362. sub distinct {
  1363.     my $self = shift;
  1364.     return 1 if $self->{"set_quantifier"}
  1365.        and $self->{"set_quantifier"} eq 'DISTINCT';
  1366.     return 0;
  1367. }
  1368.  
  1369.  
  1370. sub command { shift->{"command"} }
  1371.  
  1372. sub params {
  1373.     my $self = shift;
  1374.     my $val_num = shift;
  1375.     if (!$self->{"params"}) { return 0; }
  1376.     if (defined $val_num) {
  1377.         return $self->{"params"}->[$val_num];
  1378.     }
  1379.     if (wantarray) {
  1380.         return @{$self->{"params"}};
  1381.     }
  1382.     else {
  1383.         return scalar @{ $self->{"params"} };
  1384.     }
  1385.  
  1386. }
  1387. sub row_values {
  1388.     my $self = shift;
  1389.     my $val_num = shift;
  1390.     if (!$self->{"values"}) { return 0; }
  1391.     if (defined $val_num) {
  1392.         #        return $self->{"values"}->[$val_num]->{"value"};
  1393.         return $self->{"values"}->[$val_num];
  1394.     }
  1395.     if (wantarray) {
  1396.         return map{$_->{"values"} } @{$self->{"values"}};
  1397.     }
  1398.     else {
  1399.         return scalar @{ $self->{"values"} };
  1400.     }
  1401.  
  1402. }
  1403.  
  1404. sub get_row_value {
  1405.     my($self,$structure,$eval,$rowhash) = @_;
  1406.     my $type = $structure->{"type"};
  1407.     $type = $structure->{"name"} if $type and $type eq 'function';
  1408.     return undef unless $type;
  1409.     for ( $type ) {
  1410.         /string|number|null/      &&do { return $structure->{"value"} };
  1411.         /column/                  &&do {
  1412.                 my $val = $structure->{"value"};
  1413.                 my $tbl;
  1414.              if ($val =~ /^(.+)\.(.+)$/ ) {
  1415.                       ($tbl,$val) = ($1,$2);
  1416.             }
  1417.                 if ($self->{"join"}) {
  1418.                     # $tbl = 'shared' if $eval->is_shared($val);
  1419.                     $tbl ||= $self->colname2table($val);
  1420.                     $val = $tbl . "$dlm$val";
  1421.         }
  1422.                 return $rowhash->{"$val"};
  1423.     };
  1424.         /placeholder/             &&do {
  1425.            my $val;
  1426.            if ($self->{"join"}) {
  1427.                $val = $self->params($arg_num);
  1428.              }
  1429.            else {
  1430.                 $val = $eval->param($arg_num);  
  1431.            }
  1432.  
  1433.          #my @params = $self->params;
  1434.          #die "@params";
  1435.          #print "$val ~ $arg_num\n";
  1436.                 $arg_num++;
  1437. #print "<$arg_num>";
  1438.                 return $val;
  1439.         };
  1440.         /str_concat/              &&do {
  1441.                 my $valstr ='';
  1442.             for (@{ $structure->{"value"} }) {
  1443.                     my $newval = $self->get_row_value($_,$eval,$rowhash);
  1444.                     return undef unless defined $newval;
  1445.                     $valstr .= $newval;
  1446.             }
  1447.                 return $valstr;
  1448.         };
  1449.         /numeric_exp/             &&do {
  1450.            my @vals = @{ $structure->{"vals"} };
  1451.            my $str  = $structure->{"str"};
  1452.            for my $i(0..$#vals) {
  1453. #         use mylibs; zwarn $rowhash;
  1454.                my $val = $self->get_row_value($vals[$i],$eval,$rowhash);
  1455.                return $self->do_err(
  1456.                    qq{Bad numeric expression '$vals[$i]->{"value"}'!}
  1457.                ) unless defined $val and $val =~ $numexp;
  1458.                $str =~ s/\?$i\?/$val/;
  1459.        }
  1460.            $str =~ s/\s//g;
  1461.            $str =~ s/^([\)\(+\-\*\/0-9]+)$/$1/; # untaint
  1462.            return eval $str;
  1463.         };
  1464.  
  1465. #z      my $vtype = $structure->{"value"}->{"type"};
  1466.         my $vtype = $structure->{"type"};
  1467. #z
  1468.  
  1469.         my $value = $structure->{"value"}->{"value"};
  1470.         $value = $self->get_row_value($structure->{"value"},$eval,$rowhash)
  1471.                if $vtype eq 'function';
  1472.         /UPPER/                   &&do {
  1473.                 return uc $value;
  1474.         };
  1475.         /LOWER/                   &&do {
  1476.                 return lc $value;
  1477.         };
  1478.         /TRIM/                    &&do {
  1479.                 my $trim_char = $structure->{"trim_char"} || ' ';
  1480.                 my $trim_spec = $structure->{"trim_spec"} || 'BOTH';
  1481.                 $trim_char = quotemeta($trim_char);
  1482.                 if ($trim_spec =~ /LEADING|BOTH/ ) {
  1483.                     $value =~ s/^$trim_char+(.*)$/$1/;
  1484.         }
  1485.                 if ($trim_spec =~ /TRAILING|BOTH/ ) {
  1486.                     $value =~ s/^(.*[^$trim_char])$trim_char+$/$1/;
  1487.         }
  1488.                 return $value;
  1489.             };
  1490.         /SUBSTRING/                   &&do {
  1491.                 my $start  = $structure->{"start"}->{"value"} || 1;
  1492.                 my $offset = $structure->{"length"}->{"value"} || length $value;
  1493.                 $value ||= '';
  1494.                 return substr($value,$start-1,$offset)
  1495.                    if length $value >= $start-2+$offset;
  1496.         };
  1497.     }
  1498. }
  1499.  
  1500. sub columns {
  1501.     my $self = shift;
  1502.     my $col_num = shift;
  1503.     if (!$self->{"columns"}) { return 0; }
  1504.     if (defined $col_num ) {
  1505.         return $self->{"columns"}->[$col_num];
  1506.     }
  1507.     if (wantarray) {
  1508.         return @{$self->{"columns"}};
  1509.     }
  1510.     else {
  1511.         return scalar @{ $self->{"columns"} };
  1512.     }
  1513.  
  1514. }
  1515.  
  1516. sub colname2table {
  1517.     my $self = shift;
  1518.     my $col_name = shift;
  1519.     return undef unless defined $col_name;
  1520.     my $found_table;
  1521.     for my $full_col(@{$self->{all_cols}}) {
  1522.         my($table,$col) = $full_col =~ /^(.+)\.(.+)$/;
  1523.         next unless $col eq $col_name;
  1524.         $found_table = $table;
  1525.         last;
  1526.     }
  1527.     return $found_table;
  1528. }
  1529.  
  1530. sub colname2tableOLD {
  1531.     my $self = shift;
  1532.     my $col_name = shift;
  1533.     return undef unless defined $col_name;
  1534.     my $found;
  1535.     my $table;
  1536.     my $name;
  1537.     my @cur_cols;
  1538. print "<$col_name>";
  1539.     for my $c(@{$self->{"columns"}}) {
  1540.          $name  = $c->{"name"};
  1541. print "[$name]\n";
  1542.          $table = $c->{"table"};
  1543.          push @cur_cols,$name;
  1544.          next unless $name eq $col_name;
  1545.          $found++;
  1546.          last;
  1547.     }
  1548.     #print "$table - $name - $col_name\n";
  1549.     undef $table unless $found;
  1550.     return $table;
  1551.     #print "$col_name $table @cur_cols\n";
  1552.     if ($found and $found > 1) {
  1553.         for (@{$self->{"join"}->{"keycols"}}) {
  1554.             return 'shared' if /^$col_name$/;
  1555.         }
  1556.         # return $self->do_err("Ambiguous column name '$col_name'!");
  1557.     }
  1558.  
  1559.     #    print "$table ~ $col_name ~ @cur_cols\n";
  1560.     return $table;
  1561. }
  1562.  
  1563. sub verify_order_cols {
  1564.     my $self  = shift;
  1565.     my $table = shift;
  1566.     return unless $self->{"sort_spec_list"};
  1567.     my @ocols = $self->order;
  1568.     my @tcols = @{$table->col_names};
  1569.     my @n_ocols;
  1570. #die "@ocols";
  1571. #use mylibs; zwarn \@ocols; exit;
  1572.     for my $colnum(0..$#ocols) {
  1573.         my $col = $self->order($colnum);
  1574. #        if (!defined $col->table and defined $self->columns($colnum)) {
  1575.         if (!defined $col->table ) {
  1576.             my $cname = $ocols[$colnum]->{col}->name;
  1577.             my $tname = $self->colname2table($cname);
  1578.             return $self->do_err("No such column '$cname'.") unless $tname;
  1579.             $self->{"sort_spec_list"}->[$colnum]->{"col"}->{"table"}=$tname;
  1580.             push @n_ocols,$tname;
  1581.         }
  1582.     }
  1583. #    for (@n_ocols) {
  1584. #        die "$_" unless colname2table($_);
  1585. #    }
  1586. #use mylibs; zwarn $self->{"sort_spec_list"}; exit;
  1587. }
  1588.  
  1589. sub order {
  1590.     my $self = shift;
  1591.     my $o_num = shift;
  1592.     if (!defined $self->{"sort_spec_list"}) { return (); }
  1593.     if (defined $o_num) {
  1594.         return $self->{"sort_spec_list"}->[$o_num];
  1595.     }
  1596.     if (wantarray) {
  1597.         return @{$self->{"sort_spec_list"}};
  1598.     }
  1599.     else {
  1600.         return scalar @{ $self->{"sort_spec_list"} };
  1601.     }
  1602.  
  1603. }
  1604. sub tables {
  1605.     my $self = shift;
  1606.     my $table_num = shift;
  1607.     if (defined $table_num) {
  1608.         return $self->{"tables"}->[$table_num];
  1609.     }
  1610.     if (wantarray) {
  1611.         return @{ $self->{"tables"} };
  1612.     }
  1613.     else {
  1614. #        return scalar @{ $self->{"table_names"} };
  1615.         return scalar @{ $self->{"tables"} };
  1616.     }
  1617.  
  1618. }
  1619. sub order_joins {
  1620.     my $self = shift;
  1621.     my $links = shift;
  1622.     my @new_keycols;
  1623.     for (@$links) {
  1624.        push @new_keycols, $self->colname2table($_) . ".$_";
  1625.     }
  1626.     my @tmp = @new_keycols;
  1627.     @tmp = map { s/\./$dlm/g; $_ } @tmp;
  1628.     $self->{"join"}->{"keycols"}  = \@tmp;
  1629.     @$links = map { s/^(.+)\..*$/$1/; $_; } @new_keycols;
  1630.     my @all_tables;
  1631.     my %relations;
  1632.     my %is_table;
  1633.     while (@$links) {
  1634.         my $t1 = shift @$links;
  1635.         my $t2 = shift @$links;
  1636.         return undef unless defined $t1 and defined $t2;
  1637.         push @all_tables, $t1 unless $is_table{$t1}++;
  1638.         push @all_tables, $t2 unless $is_table{$t2}++;
  1639.         $relations{$t1}{$t2}++;
  1640.         $relations{$t2}{$t1}++;
  1641.     }
  1642.     my @tables = @all_tables;
  1643.     my @order = shift @tables;
  1644.     my %is_ordered = ( $order[0] => 1 );
  1645.     my %visited;
  1646.     while(@tables) {
  1647.         my $t = shift @tables;
  1648.         my @rels = keys %{$relations{$t}};
  1649.         for my $t2(@rels) {
  1650.             next unless $is_ordered{$t2};
  1651.             push @order, $t;
  1652.             $is_ordered{$t}++;
  1653.             last;
  1654.         }
  1655.         if (!$is_ordered{$t}) {
  1656.             push @tables, $t if $visited{$t}++ < @all_tables;
  1657.         }
  1658.     }
  1659.     return $self->do_err(
  1660.         "Unconnected tables in equijoin statement!"
  1661.     ) if @order < @all_tables;
  1662.     $self->{"join"}->{"table_order"} = \@order;
  1663.     return \@order;
  1664. }
  1665.  
  1666. sub do_err {
  1667.     my $self = shift;
  1668.     my $err  = shift;
  1669.     my $errtype  = shift;
  1670.     my @c = caller 6;
  1671.     #$err = "[" . $self->{"original_string"} . "]\n$err\n\n";
  1672.     #    $err = "$err\n\n";
  1673.     my $prog = $c[1];
  1674.     my $line = $c[2];
  1675.     $prog = defined($prog) ? " called from $prog" : '';
  1676.     $prog .= defined($line) ? " at $line" : '';
  1677.     $err =  "\nExecution ERROR: $err$prog.\n\n";
  1678.  
  1679.     $self->{"errstr"} = $err;
  1680.     warn $err if $self->{"PrintError"};
  1681.     # print $err if $self->{"PrintError"};
  1682. #    die "\n" if $self->{"RaiseError"};
  1683.     die "$err" if $self->{"RaiseError"};
  1684.     return undef;
  1685. }
  1686.  
  1687. sub errstr {
  1688.     my $self = shift;
  1689.     $self->{"errstr"};
  1690. }
  1691.  
  1692. package SQL::Statement::TempTable;
  1693.  
  1694. sub new {
  1695.     my $class      = shift;
  1696.     my $name       = shift;
  1697.     my $col_names  = shift;
  1698.     my $table_cols = shift;
  1699.     my $table      = shift;
  1700.     my $col_nums;
  1701.     for my $i(0..scalar @$col_names -1) {
  1702.       $col_nums->{"$col_names->[$i]"}=$i;
  1703.     }
  1704.     my @display_order = map { $col_nums->{$_} } @$table_cols;
  1705.     my $self = {
  1706.         col_names  => $col_names,
  1707.         table_cols => \@display_order,
  1708.         col_nums   => $col_nums,
  1709.         table      => $table,
  1710.         NAME       => $name,
  1711.     };
  1712.     return bless $self, $class;
  1713. }
  1714. sub is_shared {my($s,$colname)=@_;return $s->{"is_shared"}->{"$colname"}}
  1715. sub col_nums { shift->{"col_nums"} }
  1716. sub col_names { shift->{"col_names"} }
  1717. sub column_num  { 
  1718.     my($s,$col) = @_;
  1719.     my $new_col = $s->{"col_nums"}->{"$col"};
  1720.     if (! defined $new_col) {
  1721.         my @tmp = split '~',$col;
  1722.         $new_col = lc($tmp[0]) . '~' . uc($tmp[1]);
  1723.         $new_col = $s->{"col_nums"}->{"$new_col"};
  1724.     }
  1725.     return $new_col
  1726. }
  1727. sub fetch_row { my $s=shift; return shift @{ $s->{"table"} } }
  1728.  
  1729. package SQL::Statement::Order;
  1730.  
  1731. sub new ($$) {
  1732.     my $proto = shift;
  1733.     my $self = {@_};
  1734.     bless($self, (ref($proto) || $proto));
  1735. }
  1736. sub table ($) { shift->{'col'}->table(); }
  1737. sub column ($) { shift->{'col'}->name(); }
  1738. sub desc ($) { shift->{'desc'}; }
  1739.  
  1740.  
  1741. package SQL::Statement::Limit;
  1742.  
  1743. sub new ($$) {
  1744.     my $proto = shift;
  1745.     my $self  = shift;
  1746.     bless($self, (ref($proto) || $proto));
  1747. }
  1748. sub limit ($) { shift->{'limit'}; }
  1749. sub offset ($) { shift->{'offset'}; }
  1750.  
  1751. package SQL::Statement::Param;
  1752.  
  1753. sub new {
  1754.     my $class = shift;
  1755.     my $num   = shift;
  1756.     my $self = { 'num' => $num };
  1757.     return bless $self, $class;
  1758. }
  1759.  
  1760. sub num ($) { shift->{'num'}; }
  1761.  
  1762.  
  1763. package SQL::Statement::Column;
  1764.  
  1765. sub new {
  1766.     my $class = shift;
  1767.     my $col_name = shift;
  1768.     my $tables = shift;
  1769.     my $table_name = $col_name;
  1770.     #my @c = caller 0; print $c[2];
  1771.     if (ref $col_name eq 'HASH') {
  1772.         $tables   = [ $col_name->{"table"} ];
  1773.         $col_name = $col_name->{"column"}  ;
  1774.     }
  1775.     # print " $col_name !\n";
  1776.     my $num_tables = scalar @{ $tables };
  1777.     if ($table_name && (
  1778.            $table_name =~ /^(".+")\.(.*)$/
  1779.         or $table_name =~ /^([^.]*)\.(.*)$/
  1780.         )) {
  1781.             $table_name = $1;
  1782.             $col_name = $2;
  1783.     }
  1784.     elsif ($num_tables == 1) {
  1785.         $table_name = $tables->[0];
  1786.     }
  1787.     else {
  1788.         undef $table_name;
  1789.     }
  1790.     my $self = {
  1791.         name => $col_name,
  1792.         table => $table_name,
  1793.     };
  1794.     return bless $self, $class;
  1795. }
  1796.  
  1797. sub name  { shift->{"name"} }
  1798. sub table { shift->{"table"} }
  1799.  
  1800. package SQL::Statement::Table;
  1801.  
  1802. sub new {
  1803.     my $class = shift;
  1804.     my $table_name = shift;
  1805.     my $self = {
  1806.         name => $table_name,
  1807.     };
  1808.     return bless $self, $class;
  1809. }
  1810.  
  1811. sub name  { shift->{"name"} }
  1812. 1;
  1813. __END__
  1814.  
  1815. =head1 NAME
  1816.  
  1817. SQL::Statement - SQL parsing and processing engine
  1818.  
  1819. =head1 SYNOPSIS
  1820.  
  1821.     require SQL::Statement;
  1822.  
  1823.     # Create a parser
  1824.     my($parser) = SQL::Parser->new('Ansi');
  1825.  
  1826.     # Parse an SQL statement
  1827.     $@ = '';
  1828.     my ($stmt) = eval {
  1829.         SQL::Statement->new("SELECT id, name FROM foo WHERE id > 1",
  1830.                             $parser);
  1831.     };
  1832.     if ($@) {
  1833.         die "Cannot parse statement: $@";
  1834.     }
  1835.  
  1836.     # Query the list of result columns;
  1837.     my $numColums = $stmt->columns();  # Scalar context
  1838.     my @columns = $stmt->columns();    # Array context
  1839.     # @columns now contains SQL::Statement::Column instances
  1840.  
  1841.     # Likewise, query the tables being used in the statement:
  1842.     my $numTables = $stmt->tables();   # Scalar context
  1843.     my @tables = $stmt->tables();      # Array context
  1844.     # @tables now contains SQL::Statement::Table instances
  1845.  
  1846.     # Query the WHERE clause; this will retrieve an
  1847.     # SQL::Statement::Op instance
  1848.     my $where = $stmt->where();
  1849.  
  1850.     # Evaluate the WHERE clause with concrete data, represented
  1851.     # by an SQL::Eval object
  1852.     my $result = $stmt->eval_where($eval);
  1853.  
  1854.     # Execute a statement:
  1855.     $stmt->execute($data, $params);
  1856.  
  1857.  
  1858. =head1 DESCRIPTION
  1859.  
  1860. For installing the module, see L<"INSTALLATION"> below.
  1861.  
  1862. At the moment this POD is lifted straight from Jochen
  1863. Wiedmann's SQL::Statement with the exception of the
  1864. section labeled L<"PURE PERL VERSION"> below which is
  1865. a must read.
  1866.  
  1867. The SQL::Statement module implements a small, abstract SQL engine. This
  1868. module is not usefull itself, but as a base class for deriving concrete
  1869. SQL engines. The implementation is designed to work fine with the
  1870. DBI driver DBD::CSV, thus probably not so well suited for a larger
  1871. environment, but I'd hope it is extendable without too much problems.
  1872.  
  1873. By parsing an SQL query you create an SQL::Statement instance. This
  1874. instance offers methods for retrieving syntax, for WHERE clause and
  1875. statement evaluation.
  1876.  
  1877. =head1 PURE PERL VERSION
  1878.  
  1879. This version is a pure perl version of Jochen's original SQL::Statement.  Eventually I will re-write the POD but for now I will document in this section the ways it differs from Jochen's version only and you can assume that things not mentioned in this section remain as described in the rest of this POD.
  1880.  
  1881. =head2 Dialect Files
  1882.  
  1883. In the ...SQL/Dialect directory are files that define the valid types, reserved words, and other features of the dialects.  Currently the ANSI dialect is available only for prepare() not execute() while the CSV and AnyData dialect support both prepare() and execute().
  1884.  
  1885. =head2 New flags
  1886.  
  1887. In addition to the dialect files, features of SQL::Statement can be defined by flags sent by subclasses in the call to new, for example:
  1888.  
  1889.    my $stmt = SQL::Statement->new($sql_str,$flags);
  1890.  
  1891.    my $stmt = SQL::Statement->new($sql_str, {text_numbers=>1});
  1892.  
  1893. =over
  1894.  
  1895. =item  dialect
  1896.  
  1897.  Dialect is one of 'ANSI', 'CSV', or 'AnyData'; the default is CSV,
  1898.  i.e. the behaviour of the original XS SQL::Statement.
  1899.  
  1900. =item  text_numbers
  1901.  
  1902.  If true, this allows texts that look like numbers (e.g. 2001-01-09
  1903.  or 15.3.2) to be sorted as text.  In the original version these
  1904.  were treated as numbers and threw warnings as well as failed to sort
  1905.  as text.  The default is false, i.e. the original behaviour.  The
  1906.  AnyData dialect sets this to true by default, i.e. it allows sorting
  1907.  of these kinds of columns.
  1908.  
  1909. =item alpha_compare
  1910.  
  1911.  If true this allows alphabetic comparison.  The original version would
  1912.  ignore SELECT statements with clauses like "WHERE col3 < 'c'".  The
  1913.  default is false, i.e. the original style.  The AnyData dialect sets
  1914.  this to true by default, i.e. it allows such comparisons.
  1915.  
  1916. =item LIMIT
  1917.  
  1918.  The LIMIT clause as described by Jochen below never actually made it
  1919.  into the execute() portion of his SQL::Statement, it is now supported.
  1920.  
  1921. =item RLIKE
  1922.  
  1923.  There is an experimental RLIKE operator similar to LIKE but takes a
  1924.  perl regular expression, e.g.
  1925.  
  1926.       SELECT * FROM foo WHERE bar RLIKE '^\s*Baz[^:]*:$'
  1927.  
  1928.  Currently this is only available in the AnyData dialect.
  1929.  
  1930. =back
  1931.  
  1932. =head2 It's Pure Perl
  1933.  
  1934. All items in the pod referring to yacc, C, bison, etc. are now only historical since this version has ported all of those portions into perl.
  1935.  
  1936. =head2 Creating a parser object
  1937.  
  1938. What's accepted as valid SQL, depends on the parser object. There is
  1939. a set of so-called features that the parsers may have or not. Usually
  1940. you start with a builtin parser:
  1941.  
  1942.     my $parser = SQL::Parser->new($name, [ \%attr ]);
  1943.  
  1944. Currently two parsers are builtin: The I<Ansi> parser implements a proper
  1945. subset of ANSI SQL. (At least I hope so. :-) The I<SQL::Statement> parser
  1946. is used by the DBD:CSV driver.
  1947.  
  1948. You can query or set individual features. Currently available are:
  1949.  
  1950. =over 8
  1951.  
  1952. =item create.type_blob
  1953.  
  1954. =item create.type_real
  1955.  
  1956. =item create.type_text
  1957.  
  1958. These enable the respective column types in a I<CREATE TABLE> clause.
  1959. They are all disabled in the I<Ansi> parser, but enabled in the
  1960. I<SQL::Statement> parser. Example:
  1961.  
  1962. =item select.join
  1963.  
  1964. This enables the use of multiple tables in a SELECT statement, for
  1965. example
  1966.  
  1967.   SELECT a.id, b.name FROM a, b WHERE a.id = b.id AND a.id = 2
  1968.  
  1969. =back
  1970.  
  1971. To enable or disable a feature, for example I<select.join>, use the
  1972. following:
  1973.  
  1974.   # Enable feature
  1975.   $parser->feature("select", "join", 1);
  1976.   # Disable feature
  1977.   $parser->feature("select", "join", 0);
  1978.  
  1979. Of course you can query features:
  1980.  
  1981.   # Query feature
  1982.   my $haveSelectJoin = $parser->feature("select", "join");
  1983.  
  1984. The C<new> method allows a shorthand for setting features. For example,
  1985. the following is equivalent to the I<SQL::Statement> parser:
  1986.  
  1987.   $parser = SQL::Statement->new('Ansi',
  1988.                                 { 'create' => { 'type_text' => 1,
  1989.                                                 'type_real' => 1,
  1990.                                                 'type_blob' => 1 },
  1991.                                   'select' => { 'join' => 0 }});
  1992.  
  1993.  
  1994. =head2 Parsing a query
  1995.  
  1996. A statement can be parsed with
  1997.  
  1998.     my $stmt = SQL::Statement->new($query, $parser);
  1999.  
  2000. In case of syntax errors or other problems, the method throws a Perl
  2001. exception. Thus, if you want to catch exceptions, the above becomes
  2002.  
  2003.     $@ = '';
  2004.     my $stmt = eval { SQL::Statement->new($query, $parser) };
  2005.     if ($@) { print "An error occurred: $@"; }
  2006.  
  2007. The accepted SQL syntax is restricted, though easily extendable. See
  2008. L<SQL syntax> below. See L<Creating a parser object> above.
  2009.  
  2010.  
  2011. =head2 Retrieving query information
  2012.  
  2013. The following methods can be used to obtain information about a
  2014. query:
  2015.  
  2016. =over 8
  2017.  
  2018. =item command
  2019.  
  2020. Returns the SQL command, currently one of I<SELECT>, I<INSERT>, I<UPDATE>,
  2021. I<DELETE>, I<CREATE> or I<DROP>, the last two referring to
  2022. I<CREATE TABLE> and I<DROP TABLE>. See L<SQL syntax> below. Example:
  2023.  
  2024.     my $command = $stmt->command();
  2025.  
  2026. =item columns
  2027.  
  2028.     my $numColumns = $stmt->columns();  # Scalar context
  2029.     my @columnList = $stmt->columns();  # Array context
  2030.     my($col1, $col2) = ($stmt->columns(0), $stmt->columns(1));
  2031.  
  2032. This method is used to retrieve column lists. The meaning depends on
  2033. the query command:
  2034.  
  2035.     SELECT $col1, $col2, ... $colN FROM $table WHERE ...
  2036.     UPDATE $table SET $col1 = $val1, $col2 = $val2, ...
  2037.         $colN = $valN WHERE ...
  2038.     INSERT INTO $table ($col1, $col2, ..., $colN) VALUES (...)
  2039.  
  2040. When used without arguments, the method returns a list of the
  2041. columns $col1, $col2, ..., $colN, you may alternatively use a
  2042. column number as argument. Note that the column list may be
  2043. empty, like in
  2044.  
  2045.     INSERT INTO $table VALUES (...)
  2046.  
  2047. and in I<CREATE> or I<DROP> statements.
  2048.  
  2049. But what does "returning a column" mean? It is returning an
  2050. SQL::Statement::Column instance, a class that implements the
  2051. methods C<table> and C<name>, both returning the respective
  2052. scalar. For example, consider the following statements:
  2053.  
  2054.     INSERT INTO foo (bar) VALUES (1)
  2055.     SELECT bar FROM foo WHERE ...
  2056.     SELECT foo.bar FROM foo WHERE ...
  2057.  
  2058. In all these cases exactly one column instance would be returned
  2059. with
  2060.  
  2061.     $col->name() eq 'bar'
  2062.     $col->table() eq 'foo'
  2063.  
  2064. =item tables
  2065.  
  2066.     my $tableNum = $stmt->tables();  # Scalar context
  2067.     my @tables = $stmt->tables();    # Array context
  2068.     my($table1, $table2) = ($stmt->tables(0), $stmt->tables(1));
  2069.  
  2070. Similar to C<columns>, this method returns instances of
  2071. C<SQL::Statement::Table>.  For I<UPDATE>, I<DELETE>, I<INSERT>,
  2072. I<CREATE> and I<DROP>, a single table will always be returned.
  2073. I<SELECT> statements can return more than one table, in case
  2074. of joins. Table objects offer a single method, C<name> which
  2075.  
  2076. returns the table name.
  2077.  
  2078. =item params
  2079.  
  2080.     my $paramNum = $stmt->params();  # Scalar context
  2081.     my @params = $stmt->params();    # Array context
  2082.     my($p1, $p2) = ($stmt->params(0), $stmt->params(1));
  2083.  
  2084. The C<params> method returns information about the input parameters
  2085. used in a statement. For example, consider the following:
  2086.  
  2087.     INSERT INTO foo VALUES (?, ?)
  2088.  
  2089. This would return two instances of SQL::Statement::Param. Param objects
  2090. implement a single method, C<$param->num()>, which retrieves the
  2091. parameter number. (0 and 1, in the above example). As of now, not very
  2092. usefull ... :-)
  2093.  
  2094. =item row_values
  2095.  
  2096.     my $rowValueNum = $stmt->row_values(); # Scalar context
  2097.     my @rowValues = $stmt->row_values();   # Array context
  2098.     my($rval1, $rval2) = ($stmt->row_values(0),
  2099.                           $stmt->row_values(1));
  2100.  
  2101. This method is used for statements like
  2102.  
  2103.     UPDATE $table SET $col1 = $val1, $col2 = $val2, ...
  2104.         $colN = $valN WHERE ...
  2105.     INSERT INTO $table (...) VALUES ($val1, $val2, ..., $valN)
  2106.  
  2107. to read the values $val1, $val2, ... $valN. It returns scalar values
  2108. or SQL::Statement::Param instances.
  2109.  
  2110. =item order
  2111.  
  2112.     my $orderNum = $stmt->order();   # Scalar context
  2113.     my @order = $stmt->order();      # Array context
  2114.     my($o1, $o2) = ($stmt->order(0), $stmt->order(1));
  2115.  
  2116. In I<SELECT> statements you can use this for looking at the ORDER
  2117. clause. Example:
  2118.  
  2119.     SELECT * FROM FOO ORDER BY id DESC, name
  2120.  
  2121. In this case, C<order> could return 2 instances of SQL::Statement::Order.
  2122. You can use the methods C<$o-E<gt>table()>, C<$o-E<gt>column()> and
  2123. C<$o-E<gt>desc()> to examine the order object.
  2124.  
  2125. =item limit
  2126.  
  2127.     my $l = $stmt->limit();
  2128.     if ($l) {
  2129.       my $offset = $l->offset();
  2130.       my $limit = $l->limit();
  2131.     }
  2132.  
  2133. In a SELECT statement you can use a C<LIMIT> clause to implement
  2134. cursoring:
  2135.  
  2136.     SELECT * FROM FOO LIMIT 5
  2137.     SELECT * FROM FOO LIMIT 5, 5
  2138.     SELECT * FROM FOO LIMIT 10, 5
  2139.  
  2140. These three statements would retrieve the rows 0..4, 5..9, 10..14
  2141. of the table FOO, respectively. If no C<LIMIT> clause is used, then
  2142. the method C<$stmt-E<gt>limit> returns undef. Otherwise it returns
  2143. an instance of SQL::Statement::Limit. This object has the methods
  2144. C<offset> and C<limit> to retrieve the index of the first row and
  2145. the maximum number of rows, respectively.
  2146.  
  2147. =item where
  2148.  
  2149.     my $where = $stmt->where();
  2150.  
  2151. This method is used to examine the syntax tree of the C<WHERE> clause.
  2152. It returns undef (if no WHERE clause was used) or an instance of
  2153. SQL::Statement::Op. The Op instance offers 4 methods:
  2154.  
  2155. =over 12
  2156.  
  2157. =item op
  2158.  
  2159. returns the operator, one of C<AND>, C<OR>, C<=>, C<E<lt>E<gt>>, C<E<gt>=>,
  2160. C<E<gt>>, C<E<lt>=>, C<E<lt>>, C<LIKE>, C<CLIKE> or C<IS>.
  2161.  
  2162. =item arg1
  2163.  
  2164. =item arg2
  2165.  
  2166. returns the left-hand and right-hand sides of the operator. This can be a
  2167. scalar value, an SQL::Statement::Param object or yet another
  2168. SQL::Statement::Op instance.
  2169.  
  2170. =item neg
  2171.  
  2172. returns a TRUE value, if the operation result must be negated after
  2173. evalution.
  2174.  
  2175. =back
  2176.  
  2177. To evaluate the I<WHERE> clause, fetch the topmost Op instance with
  2178. the C<where> method. Then evaluate the left-hand and right-hand side
  2179. of the operation, perhaps recursively. Once that is done, apply the
  2180. operator and finally negate the result, if required.
  2181.  
  2182. =back
  2183.  
  2184. To illustrate the above, consider the following WHERE clause:
  2185.  
  2186.     WHERE NOT (id > 2 AND name = 'joe') OR name IS NULL
  2187.  
  2188. We can represent this clause by the following tree:
  2189.  
  2190.               (id > 2)   (name = 'joe')
  2191.                      \   /
  2192.           NOT         AND
  2193.                          \      (name IS NULL)
  2194.                           \    /
  2195.                             OR
  2196.  
  2197. Thus the WHERE clause would return an SQL::Statement::Op instance with
  2198. the op() field set to 'OR'. The arg2() field would return another
  2199. SQL::Statement::Op instance with arg1() being the SQL::Statement::Column
  2200. instance representing id, the arg2() field containing the value undef
  2201. (NULL) and the op() field being 'IS'.
  2202.  
  2203. The arg1() field of the topmost Op instance would return an Op instance
  2204. with op() eq 'AND' and neg() returning TRUE. The arg1() and arg2()
  2205. fields would be Op's representing "id > 2" and "name = 'joe'".
  2206.  
  2207. Of course there's a ready-for-use method for WHERE clause evaluation:
  2208.  
  2209.  
  2210. =head2 Evaluating a WHERE clause
  2211.  
  2212. The WHERE clause evaluation depends on an object being used for
  2213. fetching parameter and column values. Usually this can be an
  2214. SQL::Eval object, but in fact it can be any object that supplies
  2215. the methods
  2216.  
  2217.     $val = $eval->param($paramNum);
  2218.     $val = $eval->column($table, $column);
  2219.  
  2220. See L<SQL::Eval> for a detailed description of these methods.
  2221. Once you have such an object, you can call a
  2222.  
  2223.     $match = $stmt->eval_where($eval);
  2224.  
  2225.  
  2226. =head2 Evaluating queries
  2227.  
  2228. So far all methods have been concrete. However, the interface for
  2229. executing and evaluating queries is abstract. That means, for using
  2230. them you have to derive a subclass from SQL::Statement that implements
  2231. at least certain missing methods and/or overwrites others. See the
  2232. C<test.pl> script for an example subclass.
  2233.  
  2234. Something that all methods have in common is that they simply throw
  2235. a Perl exception in case of errors.
  2236.  
  2237.  
  2238. =over 8
  2239.  
  2240. =item execute
  2241.  
  2242. After creating a statement, you must execute it by calling the C<execute>
  2243. method. Usually you put an eval statement around this call:
  2244.  
  2245.     $@ = '';
  2246.     my $rows = eval { $self->execute($data); };
  2247.     if ($@) { die "An error occurred!"; }
  2248.  
  2249. In case of success the method returns the number of affected rows or -1,
  2250. if unknown. Additionally it sets the attributes
  2251.  
  2252.     $self->{'NUM_OF_FIELDS'}
  2253.     $self->{'NUM_OF_ROWS'}
  2254.     $self->{'data'}
  2255.  
  2256. the latter being an array ref of result rows. The argument $data is for
  2257. private use by concrete subclasses and will be passed through to all
  2258. methods. (It is intentionally not implemented as attribute: Otherwise
  2259. we might well become self referencing data structures which could
  2260. prevent garbage collection.)
  2261.  
  2262.  
  2263. =item CREATE
  2264.  
  2265. =item DROP
  2266.  
  2267. =item INSERT
  2268.  
  2269. =item UPDATE
  2270.  
  2271. =item DELETE
  2272.  
  2273. =item SELECT
  2274.  
  2275. Called by C<execute> for doing the real work. Usually they create an
  2276. SQL::Eval object by calling C<$self-E<gt>open_tables()>, call
  2277. C<$self-E<gt>verify_columns()> and then do their job. Finally they return
  2278. the triple
  2279.  
  2280.     ($self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'},
  2281.      $self->{'data'})
  2282.  
  2283. so that execute can setup these attributes. Example:
  2284.  
  2285.     ($self->{'NUM_OF_ROWS'}, $self->{'NUM_OF_FIELDS'},
  2286.      $self->{'data'}) = $self->SELECT($data);
  2287.  
  2288.  
  2289. =item verify_columns
  2290.  
  2291. Called for verifying the row names that are used in the statement.
  2292. Example:
  2293.  
  2294.     $self->verify_columns($eval, $data);
  2295.  
  2296.  
  2297. =item open_tables
  2298.  
  2299. Called for creating an SQL::Eval object. In fact what it returns
  2300. doesn't need to be derived from SQL::Eval, it's completely sufficient
  2301. to implement the same interface of methods. See L<SQL::Eval> for
  2302. details. The arguments C<$data>, C<$createMode> and C<$lockMode>
  2303. are corresponding to those of SQL::Eval::Table::open_table and
  2304. usually passed through. Example:
  2305.  
  2306.     my $eval = $self->open_tables($data, $createMode, $lockMode);
  2307.  
  2308. The eval object can be used for calling C<$self->verify_columns> or
  2309. C<$self->eval_where>.
  2310.  
  2311. =item open_table
  2312.  
  2313. This method is completely abstract and *must* be implemented by subclasses.
  2314. The default implementation of C<$self->open_tables> calls this method for
  2315. any table used by the statement. See the C<test.pl> script for an example
  2316. of imlplementing a subclass.
  2317.  
  2318. =back
  2319.  
  2320.  
  2321. =head1 SQL syntax
  2322.  
  2323. The SQL::Statement module is far away from ANSI SQL or something similar,
  2324. it is designed for implementing the DBD::CSV module. See L<DBD::CSV(3)>.
  2325.  
  2326. I do not want to give a formal grammar here, more an informal
  2327. description: Read the statement definition in sql_yacc.y, if you need
  2328. something precise.
  2329.  
  2330. The main lexical elements of the grammar are:
  2331.  
  2332. =over 8
  2333.  
  2334. =item Integers
  2335.  
  2336. =item Reals
  2337.  
  2338. Syntax obvious
  2339.  
  2340. =item Strings
  2341.  
  2342. Surrounded by either single or double quotes; some characters need to
  2343. be escaped with a backslash, in particular the backslash itself (\\),
  2344. the NUL byte (\0), Line feeds (\n), Carriage return (\r), and the
  2345. quotes (\' or \").
  2346.  
  2347. =item Parameters
  2348.  
  2349. Parameters represent scalar values, like Integers, Reals and Strings
  2350. do. However, their values are read inside Execute() and not inside
  2351. Prepare(). Parameters are represented by question marks (?).
  2352.  
  2353. =item Identifiers
  2354.  
  2355. Identifiers are table or column names. Syntactically they consist of
  2356. alphabetic characters, followed by an arbitrary number of alphanumeric
  2357. characters. Identifiers like SELECT, INSERT, INTO, ORDER, BY, WHERE,
  2358. ... are forbidden and reserved for other tokens.
  2359.  
  2360. =back
  2361.  
  2362. What it offers is the following:
  2363.  
  2364. =head2 CREATE
  2365.  
  2366. This is the CREATE TABLE command:
  2367.  
  2368.     CREATE TABLE $table ( $col1 $type1, ..., $colN $typeN,
  2369.                           [ PRIMARY KEY ($col1, ... $colM) ] )
  2370.  
  2371. The column names are $col1, ... $colN. The column types can be
  2372. C<INTEGER>, C<CHAR(n)>, C<VARCHAR(n)>, C<REAL> or C<BLOB>. These
  2373. types are currently completely ignored. So is the (optional)
  2374. C<PRIMARY KEY> clause.
  2375.  
  2376. =head2 DROP
  2377.  
  2378. Very simple:
  2379.  
  2380.     DROP TABLE $table
  2381.  
  2382. =head2 INSERT
  2383.  
  2384. This can be
  2385.  
  2386.     INSERT INTO $table [ ( $col1, ..., $colN ) ]
  2387.         VALUES ( $val1, ... $valN )
  2388.  
  2389. =head2 DELETE
  2390.  
  2391.     DELETE FROM $table [ WHERE $where_clause ]
  2392.  
  2393. See L<SELECT> below for a decsription of $where_clause
  2394.  
  2395. =head2 UPDATE
  2396.  
  2397.     UPDATE $table SET $col1 = $val1, ... $colN = $valN
  2398.         [ WHERE $where_clause ]
  2399.  
  2400. See L<SELECT> below for a decsription of $where_clause
  2401.  
  2402. =head2 SELECT
  2403.  
  2404.     SELECT [DISTINCT] $col1, ... $colN FROM $table
  2405.         [ WHERE $where_clause ] [ ORDER BY $ocol1, ... $ocolM ]
  2406.  
  2407. The $where_clause is based on boolean expressions of the form
  2408. $val1 $op $val2, with $op being one of '=', '<>', '>', '<', '>=',
  2409. '<=', 'LIKE', 'CLIKE' or IS. You may use OR, AND and brackets to combine
  2410. such boolean expressions or NOT to negate them.
  2411.  
  2412.  
  2413. =head1 INSTALLATION
  2414.  
  2415. For the moment, just unpack the tarball in a private directory.  For the moment, I suggest this be somewhere other than where you store your current SQL::Statement and you use this version by a "use lib" referencing the private directory where you unpack it.
  2416.  
  2417. There's no Makefile at this time.
  2418.  
  2419.  
  2420. =head1 INTERNALS
  2421.  
  2422. Internally the module is splitted into three parts:
  2423.  
  2424.  
  2425. =head2 Perl-independent C part
  2426.  
  2427. This part, contained in the files C<sql_yacc.y>, C<sql_data.h>,
  2428. C<sql_data.c> and C<sql_op.c>, is completely independent from Perl.
  2429. It might well be used from within another script language, Tcl say,
  2430. or from a true C application.
  2431.  
  2432. You probably ask, why Perl independence? Well, first of all, I
  2433. think this is a valuable target in itself. But the main reason was
  2434. the impossibility to use the Perl headers inside bison generated
  2435. code. The Perl headers export almost the complete Yacc interface
  2436. to XS, for whatever reason, thus redefining constants and structures
  2437. created by your own bison code. :-(
  2438.  
  2439.  
  2440. =head2 Perl-dependent C part
  2441.  
  2442. This is contained in C<Statement.xs>. The both C parts communicate via
  2443. a C structure sql_stmt_t. In fact, an SQL::Statement object is nothing
  2444. else than a pointer to such a structure. The XS calls columns(), Table(),
  2445. where(), ... do nothing more than fetching data from this structure
  2446. and converting it to Perl objects. See L<The sql_stmt_t structure>
  2447. below for details on the structure.
  2448.  
  2449.  
  2450. =head2 Perl part
  2451.  
  2452. Besides some stub functions for retrieving statement data, this is
  2453. mainly the query processing with the exception of WHERE clause
  2454. evaluation.
  2455.  
  2456.  
  2457. =head2 The sql_stmt_t structure
  2458.  
  2459. This structure is designed for optimal performance. A typical query
  2460. will be parsed with only 4 or 5 malloc() calls; in particular no
  2461. memory will be aquired for storing strings; only pointers into the
  2462. query string are used.
  2463.  
  2464. The statement stores its tokens in the values array. The array elements
  2465. are of type sql_val_t, a union, that can represent the most interesting
  2466. tokens; for example integers and reals are stored in the data.i and
  2467. data.d parts of the union, strings are stored in the data.str part,
  2468. columns in the data.col part and so on. Arrays are allocated in chunks
  2469. of 64 elements, thus a single malloc() will be usually sufficient for
  2470. allocating the complete array. Some types use pointers into the values
  2471. array: For example, operations are stored in an sql_op_t structure that
  2472. containes elements arg1 and arg2 which are pointers into the value
  2473. table, pointing to other operations or scalars. These pointers are
  2474. stored as indices, so that the array can be extended using realloc().
  2475.  
  2476. The sql_stmt_t structure contains other arrays: columns, tables,
  2477. rowvals, order, ... representing the data returned by the columns(),
  2478. tables(), row_values() and order() methods. All of these contain
  2479. pointers into the values array, again stored as integers.
  2480.  
  2481. Arrays are initialized with the _InitArray call in SQL_Statement_Prepare
  2482. and deallocated with _DestroyArray in SQL_Statement_Destroy. Array
  2483. elements are obtained by calling _AllocData, which returns an index.
  2484. The number -1 is used for errors or as a NULL value.
  2485.  
  2486.  
  2487. =head2 The WHERE clause evaluation
  2488.  
  2489. A WHERE clause is evaluated by calling SQL_Statement_EvalWhere(). This
  2490. function is in the Perl independent part, but it needs the possibility
  2491. to retrieve data from the Perl part, for example column or parameter
  2492. values. These values are retrieved via callbacks, stored in the
  2493. sql_eval_t structure. The field stmt->evalData points to such a
  2494. structure. Of course the calling method can extend the sql_eval_t
  2495. structure (like eval_where in Statement.xs does) to include private data
  2496. not used by SQL_Statement_EvalWhere.
  2497.  
  2498.  
  2499. =head2 Features
  2500.  
  2501. Different parsers are implemented via the sql_parser_t structure. This
  2502. is mainly a set of yes/no flags. If you'd like to add features, do
  2503. the following:
  2504.  
  2505. First of all, extend the sql_parser_t structure. If your feature is
  2506. part of a certain statement, place it into the statements section,
  2507. for example "select.join". Otherwise choose a section like "misc"
  2508. or "general". (There's no particular for the section design, but
  2509. structure never hurts.)
  2510.  
  2511. Second, add your feature to sql_yacc.y. If your feature needs to
  2512. extend the lexer, do it like this:
  2513.  
  2514.     if (FEATURE(misc, myfeature) {
  2515.         /*  Scan your new symbols  */
  2516.         ...
  2517.     }
  2518.  
  2519. See the I<BOOL> symbol as an example.
  2520.  
  2521. If you need to extend the parser, do it like this:
  2522.  
  2523.     my_new_rule:
  2524.         /*  NULL, old behaviour, doesn't use my feature  */
  2525.         | my_feature
  2526.             { YFEATURE(misc, myfeature); }
  2527.     ;
  2528.  
  2529. Thus all parsers not having FEATURE(misc, myfeature) set will produce
  2530. a parse error here. Again, see the BOOL symbol for an example.
  2531.  
  2532. Third thing is to extend the builtin parsers. If they support your
  2533. feature, add a 1, otherwise a 0. Currently there are two builtin
  2534. parsers: The I<ansiParser> in sql_yacc.y and the sqlEvalParser in
  2535. Statement.xs.
  2536.  
  2537. Finally add support for your feature to the C<feature> method in
  2538. Statement.xs. That's it!
  2539.  
  2540.  
  2541. =head1 MULTITHREADING
  2542.  
  2543. The complete module code is reentrant. In particular the parser is
  2544. created with C<%pure_parser>. See L<bison(1)> for details on
  2545. reentrant parsers. That means, the module is ready for multithreading,
  2546. as long as you don't share handles between threads. Read-only handles,
  2547. for example parsers, can even be shared.
  2548.  
  2549. Statement handles cannot be shared among threads, at least not, if
  2550. you don't grant serialized access. Per-thread handles are always safe.
  2551.  
  2552.  
  2553. =head1 AUTHOR AND COPYRIGHT
  2554.  
  2555. The original version of this module is Copyright (C) 1998 by
  2556.  
  2557.     Jochen Wiedmann
  2558.     Am Eisteich 9
  2559.     72555 Metzingen
  2560.     Germany
  2561.  
  2562.     Email: joe@ispsoft.de
  2563.     Phone: +49 7123 14887
  2564.  
  2565. The current version is Copyright (c) 2001 by
  2566.  
  2567.     Jeff Zucker
  2568.  
  2569.     Email: jeff@vpservices.com
  2570.  
  2571. All rights reserved.
  2572.  
  2573. You may distribute this module under the terms of either the GNU
  2574. General Public License or the Artistic License, as specified in
  2575. the Perl README file. 
  2576.  
  2577.  
  2578. =head1 SEE ALSO
  2579.  
  2580. L<DBI(3)>, L<DBD::CSV(3)>, L<DBD::AnyData>
  2581.  
  2582. =cut
  2583.