+sub ParseSQL {
+ my $self = shift;
+ my %args = (
+ Query => '',
+ CurrentUser => '', #XXX: Hack
+ @_
+ );
+ my $string = $args{'Query'};
+
+ my @results;
+
+ my %field = %{ RT::Tickets->new( $args{'CurrentUser'} )->FIELDS };
+ my %lcfield = map { ( lc($_) => $_ ) } keys %field;
+
+ my $node = $self;
+
+ my %callback;
+ $callback{'OpenParen'} = sub {
+ $node = __PACKAGE__->new( 'AND', $node );
+ };
+ $callback{'CloseParen'} = sub { $node = $node->getParent };
+ $callback{'EntryAggregator'} = sub { $node->setNodeValue( $_[0] ) };
+ $callback{'Condition'} = sub {
+ my ($key, $op, $value) = @_;
+
+ my ($main_key) = split /[.]/, $key;
+
+ my $class;
+ if ( exists $lcfield{ lc $main_key } ) {
+ $class = $field{ $main_key }->[0];
+ $key =~ s/^[^.]+/ $lcfield{ lc $main_key } /e;
+ }
+ unless( $class ) {
+ push @results, [ $args{'CurrentUser'}->loc("Unknown field: [_1]", $key), -1 ]
+ }
+
+ $value =~ s/'/\\'/g;
+ $value = "'$value'" if $value =~ /[^0-9]/;
+ $key = "'$key'" if $key =~ /^CF./;
+
+ my $clause = { Key => $key, Op => $op, Value => $value };
+ $node->addChild( __PACKAGE__->new( $clause ) );
+ };
+ $callback{'Error'} = sub { push @results, @_ };
+
+ require RT::SQL;
+ RT::SQL::Parse($string, \%callback);
+ return @results;
+}