SQL/YASP version 0.10
========================

NAME
    SQL::YASP - SQL parser and evaluater

SYNOPSIS
     use SQL::YASP;
     my ($sql, $stmt, $dbrec, $params);

     $sql = <<'(SQL)';
        select 
            -- supports single and multi-line comments
            -- supports "as fieldname" format for select clauses
            first ||| last as fullname

        from members

        where
            /*
            over 100 built in SQL functions and operators
            including most MySQL functions and operators
            */
            ucase(first) ilike 'Joe' and

            -- Perl-like regular expressions
            first =~ m/ (Joe) | (Steve) /ix and

            -- handles quoted strings and escapes in quotes
            last = 'O''Sullivan' and

            -- any level of nested parens
            -- full support for placeholders
            ((rank >= ?) and (rank <= ?))
     (SQL)
 
     # get statement object
     $stmt = SQL::YASP::Statement->new($sql);

     # database record: populate this hash from your database
     $dbrec = 
        {
        first=>'Joe',
        last=>'Smith',
        email=>'joe@idocs.com',
        rank=>10,
        };

     # input parameters
     $params = [10, 20];

     # test if this record passes the where clause
     if ($stmt->{'where'}->evalexpr(db_record=>$dbrec, params=>$params)) {
         # get the record as indicated by the select clause
         my $retrec = $stmt->select_fields(db_record=>$dbrec);
         print $retrec->{'fullname'}, "\n";
     }

INSTALLATION
    SQL::YASP can be installed with the usual routine:

        perl Makefile.PL
        make
        make test
        make install

    You can also just copy Eval.pm into the SQL/ directory of one of your
    library trees.

A NOTE ABOUT THE STATE OF DOCUMENTATION
    I'm still working on the documentaton for YASP. Documenting everything
    YASP does has proved a daunting task. In the spirit of Eric Raymond's
    motto "Release Early, Release Often" I decided to go ahead and release
    YASP before I finish the docs.

    Sections that are not completed are noted with [*] in the title.

A GUIDED TOUR OF YASP
    YASP is an SQL parser and evaluator for Perl. It parses SQL statements,
    allows you to discover various properties of them, and helps evaluate
    expressions in the statement. Let's look at some code that provides an
    example of the features of YASP.

        1   $sql = <<'(SQL)';
        2   select
        3      rank,
        4      first ||| last as fullname
        5   from members
        6   where first=?
        7   (SQL)
        8  
        9   $stmt = SQL::YASP->parse($sql);
        10  $dbrec = {first=>'Starflower', last=>"O'Sullivan", rank=>10};
        11  $params = ['Starflower'];
        12  
        13  if ($stmt->{'where'}->evalexpr(db_record=>$dbrec, params=>$params)) {
        14     my $calcrec = $stmt->select_fields(db_record=>$dbrec);
        15     print $calcrec->{'rank'}, "\t", $calcrec->{'fullname'}, "\n";
        16  }

    Lines 1- 7 create the SQL Select statement string we're going to parse.
    Line 2 begins the select statement. Line 3 indicates that the "rank"
    field should be returned. Line 4 indicates that the "first" and "last"
    fields should be concatenated together using "|||" operator (see
    operator documentation below), and the results should be named
    "fullname".

    Line 5 indicates that the fields should be selected from the "members"
    table. The name of the table is given by the "from" property of the
    statement object. Line 6 gives the where clause, which will be revealed
    by the "where" clause of the statement object.

    Line 9 creates statement object, passing the SQL string as the only
    argument. Line 10 create an anonymous hash will store data from the
    database. Your application can retrieve and populate this data in
    whatever manner you choose. Line 11 creates an anonymous array of
    parameters that will be used to evaluate the where clause.

    Line 13 evaluates the where clause, using the database record and
    parameters. If the expression returns true, then 14 calls the
    select_fields(, again using the database record hash, to return an
    anonymous hash of the database fields as indicated by the expressions in
    the select clause. Line 15 outputs the results.

  Lukasiewiczian Algebra

    By default, YASP implements Lukasiewiczian algebra in evaluating SQL
    expressions. If you would prefer to turn off Lukasiewiczian then set the
    parser's "lukas" property to false.

    Lukasiewiczian algebra is the standard in most databases such as MySql
    and Oracle. Lukasiewiczian algebra is a variation on Boolean Algebra
    invented by Jan Lukasiewicz. In Boolean algreba there are two values:
    true and false. Lukasiewiczian algrebra adds a third possible value:
    unknown, also known as null. If an expression depends on null, than the
    expression evaluates to null. If the expression can be determined as
    true or false even though it contains nulls, it returns true or false.

    For example, consider the following AND expression:

        null AND true

    We don't know if the expression is true because we don't know if the
    first argument is true. Ergo, the expression evaluates to null. However,
    in this expression...

        null AND false

    ... we know that the expression is false, because we know that the
    second argument is false (and therefore we know that it's not true that
    both arguments are true). Ergo the expression evaluates to false. In a
    similar way, the expression "true or x" evaluates to true because only
    one of the arguments needs to be true in an OR, and we know the first
    argument is true.

    One of the funkiest ways that Lukasiewiczian algrebra is different from
    Boolean is in the NOT operator. Not true is false. Not false is true.
    Not null is ... null. That's because we don't know the negation of a
    value we don't know.

SQL COMMANDS [*]
    YASP currently recognizes five SQL commands: CREATE, SELECT, DELETE,
    UPDATE, and INSERT. The statement object returned by the parser contains
    properties of the command. We'll start by looking at properties common
    to all types of commands, then describe properties specific to each of
    the commands listed above.

    Each statement object has the following properties.

    command (scalar)
        The command being run. E.g., "select", "create", "inset"

    placeholders (array)
        Array of information about the placeholders in the command

    placeholder_count (scalar)
        how many placeholders were in the command

    Now let's look at properties specific to each command.

  CREATE

    table_name (scalar)
        Name of the object being created

    create_type (scalar)
        The type of object being created. Right now only "table" is handled

    fields (hash)
        An array of information about the fields being created. The key for
        each hash element is the name of the field. The hash is indexed, so
        each element is returned in the order it is defined in the SQL
        command.

        Each field definition (i.e. each element in the fields hash) has two
        elements. "data_type" is the parsed command indicating the data type
        of the field. "modifiers" is an array of all other options defining
        the field, e.g. "unique", "undef", etc.

  SELECT

    where
        An expression object. See the documentation for expression objects
        objects below.

    from
        This property is a hash of information about the tables from which
        records should be selected. The key of each element is the alias of
        the table if an alias is used, or the name of the table itself. The
        value is the name of the table. For example, this SQL command:

         select name, payment from members, registrations reg where members.id=reg.id

        produces a "from" clause with these keys and values:

          KEY       VALUE
          reg       registrations
          members   members

    fields
        An indexed hash describing each field that should be returned by the
        select statement. The key of each hash element is the alias of the
        field (if an alias was given), the name of the field (if only a
        single field is requested, or the full expression. The value of each
        element is an Expression object. See the documentation for
        expression objects below.

  DELETE

    Statement objects for the DELETE command have "where" and "from"
    properties like SELECT statements.

  UPDATE

    table_name
        This property holds the name of the table being updated.

    set An indexed hash describing which fields should be updated and what
        they should be updated to. The key of each hash element is the name
        of the field to be updated. The value of each element is an
        Expression object. See the documentation for expression objects
        below.

  INSERT

    Statement objects for the INSERT command have "set" and "table_name"
    properties like UPDATE statements.

EXPRESSION OBJECTS
    Expression objects allow you to evaluate an SQL expression against one
    or more database records. Expression objects only have one public
    method, "evalexpr", so let's get right to looking at how that method
    works.

    Consider the following code:

     1   $sql = 'select name from members where id=?';
     2   $dbrec = { id=>10, name => 'Starflower'};
     3   $params = [10];
     4   $stmt = SQL::YASP->parse($sql);
     5   
     6   if ($stmt->{'where'}->evalexpr(db_record=>$dbrec, params=>$params))
     7       {print $dbrec->{'name'}, "\n"}

    Line 1 creates an SQL statement to select the name field from the
    members table. Notice that the where clause uses a placeholder instead
    of a hardcoded values. Line 2 creates a hash reference that represents a
    database record. Line 3 creates an array reference that is a list of
    parameters that will be substituted for placeholders in the SQL
    statement. Line 4 creates an SQL statement object.

    In Line 6 we use the expression object that is stored as the "where"
    property of the statement. We pass in the database record and the
    parameter list, and get back true or false.

EXTENDING YASP
    YASP is designed to simplify overriding any of its functionality.
    Although YASP works out-of-the box, developers may want to tune it to
    parse and interpret specific flavors of SQL.

  The Basic Concepts

    The first and only required step for extending YASP is to create a new
    package and set its @ISA to point to YASP. Let's say you want to call
    you package "Extended", and that you want to put it in a file named
    "Extended.pm". The following code at the top of the package does the
    extending:

        package Extended;
        use strict;
        use SQL::YASP ':all';
        @Extended::ISA = 'SQL::YASP';

    As always, be sure that the last line in Extended.pm is 1 so that you
    can load it into a script. You're now ready to use your new package.
    First, load the package:

        use Extended;

    then use it to parse SQL:

        $stmt = Extended->parse($sql);

    Of course, the point of extending is to change the default
    functionality. Generally this is done in three ways for YASP: modifying
    the parsing options, modifying the operators and functions, and
    overriding object methods.

    Except for overriding methods, all of these options and properties
    should be set in the "new" function. Any of the options that are not
    explicitly set in "new" are set in "after_new", which should *always* be
    called at the end of "new". So, for example, suppose you wanted to
    remove Perl-style regexes and /* style comments. Your "new" function
    could look like this:

        sub new {
            my ($class) = @_;
            my $self = bless({}, $class);
        
            # parsing options
            $self->{'star_comments'} = 0;
            $self->{'perl_regex'} = 0;
        
            # always call after_new just before
            # returning new parser
            $self->after_new;
        
            return $self;
        }

  Parsing Options

    The following options can be set in the "new" function. See their
    documentation for specifics about what each property does.

        !_is_not
        backslash_escape
        dash_comments
        dquote_escape
        lukas
        perl_regex
        pound_comments
        quotes
        star_comments

  DEFINING SQL OPERATORS

    SQL operators are stored as a set sub references in the parser object.
    The parser's "ops" property is an array. Each element of the array is a
    hash, and each element of the hash is a hash of information about a
    specific operator. Was that a little confusing? Here's an example.
    Suppose we only wanted the parser to recognize four operators: =, >, *,
    and +. We would set the "ops" property in "new" like this:

        sub new {
            my ($class) = @_;
            my $self = bless({}, $class);
        
            # operators
            $self->{'ops'} = [
                # comparison operators
                {
                '='  => { s=>sub{$_[0] eq $_[1]} }, 
                '>' => { s=>sub{$_[0] > $_[1]} }, 
                },
            
                # mathematical operators
                {
                '*'  => { s=>sub{$_[0] eq $_[1]},  args=>ARG_NUMERIC} ,  
                '+' => { s=>sub{$_[0] > $_[1]},    args=>ARG_NUMERIC}, 
                },
            ];
        
            # always call after_new just
            # before returning new parser
            $self->after_new;
        
            return $self;
        }

    Let's look at how the ops property is constructed. Each element in the
    array represents a level of operator precedence. Loosest bound operators
    are in the first element, and ops of increasingly tighter binding are in
    higher array elements. Operators in the same array element have equal
    precedence.

    Each array element is itself a hash of operator definitions. The hash
    key is the name of operator itself. Where letters are part of the
    operator name, always use lowercase.

    The operator definition itself is a hash of properties about the
    operator. Only one property is required, the "s" (for "sub") property.
    The "s" property should reference the subroutine that actually performs
    the operation. For short subs it is usually easiest to simply use an
    anonymous subroutine, as in the example above. By default, the
    subroutine receives two arguments: the value on the left and the value
    on the right. The sub should return whatever the result of the operation
    is.

    In a moment we'll look at how each op function is contructed, as well as
    the other properties of the operator definition, but first a note about
    the operations that are available by default from YASP. Constructing all
    of your operators in a long array like above could get pretty obnoxious,
    especially considering that a good portion of the operators you are
    likely to want are already available by default from YASP. Let's suppose
    that you only wanted to make one change in the default operators: you
    want to change "||" from a concatenator to an "or" as it is in MySql.
    You could do that in the "new" function like this:

        sub new {
            my ($class) = @_;
            my $self = bless({}, $class);
        
            # get default operators
            $self->{'ops'} = SQL::YASP::default_ops();
        
            # get rid of the default || operator
            delete $self->{'ops'}->[OP_MISC]->{'||'};
        
            # alias || to or
            $self->{'ops'}->[OP_LOGICAL]->{'||'} = $self->{'ops'}->[OP_LOGICAL]->{'or'};
        
            # always call after_new just
            # before returning new parser
            $self->after_new;
        
            return $self;
        }

    After blessing the object, the function sets its "ops" property to the
    default YASP operators using the SQL::YASP::default_ops() function,
    which returns an anonymous array of operator definitions. Next, it
    removes the "||" definition from the "OP_MISC" level of operators. There
    are six operator precedence levels in the default definitions:
    "OP_BETWEEN", "OP_LOGICAL", "OP_ADD", "OP_MULT", "OP_EXP", and
    "OP_MISC". The sub then redefines "||" into the OP_LOGICAL level,
    setting its definition to the same as the "or" operator.

    Turning our attention back to the other properties of an operator
    definition, the other property is "args", which indicates what kind of
    arguments the sub expects. There are four possible values. "ARG_STRING"
    (which is the default, so you can leave it out) indicates that the sub
    expects two strings. "ARG_STRING" is null-safe: YASP will send empty
    strings instead of spaces to such subs. If you want your operator to see
    nulls when they are indicated, set "args" to "ARG_SENDNULLS".
    "ARG_NUMERIC" indicates that the sub expects numbers. For "ARG_NUMERIC"
    operators, zero will be sent instead of null.

    "ARG_RAW" is for the situation where you don't want YASP to evaluate the
    expressions on the left and right of the operator, but instead to allow
    your sub to decide how to interpret the expressions. "ARG_RAW" subs
    receieve three arguments. The first two are anonymous arrays of the
    expressions to the left and right of the operator. The third argument,
    $opts, is a hash of values passed through the recursion of the
    "evalexpr" ("evaluate expression") sub.

    To evalute one of the expressions, call "evalexpr" passing three value:
    $opts, the expression, and a variable into which the results will be
    stored. Contrary to what might be expected, "evalexpr" does *not* return
    the results of the expression when called in this manner. The results of
    the expression are stored in the third argument. The *success* of the
    evaulation is returned by "evalexpr". If "evalexpr" returns false then
    there was a fatal error in the SQL expression (e.g. a divide by zero)
    and your function should proceed no further.

    For example, YASP's default "and" operator looks like this:

        $dbin[OP_LOGICAL]{'and'}  = {args=>ARG_RAW, s=>sub{
            my ($left, $right, $opts) = @_;
            my ($val);
        
            evalexpr($left, $opts, $val) or return;
            $val or return 0;
        
            evalexpr($right, $opts, $val) or return;
            return $val;
        }};

    In the first call to "evalexpr" passes $left, $opts, and $val. The
    results of the expression are stored in $val. If "evalexpr" returns
    false then the function returns, proceeding no further.

    "and" is an "ARG_RAW" operator so that it short ciruits: the right
    expression is never evaluted if the left argument is false. That's why
    Cand> is an "ARG_RAW" operator: so that it never has to evaluate the
    second expression if the first is false.

    If your code discovers that the expression is invalid in some way, you
    can throw an error to indicate that the SQL is invalid. To do so, set
    $SQL::YASP::err to true, set $SQL::YASP::errstr to a description of the
    error, and return undef from the function. For example, dividing by zero
    is an error, so your "/" operator could look like this:

        $dbin[OP_MULT]{'/'} = {args=>ARG_NUMERIC, s=>sub{
            unless ($_[1]) {
                $SQL::YASP::err = 1;
                $SQL::YASP::errstr = 'divide by zero';
                return undef;
            }
        
            $_[0] / $_[1];
        }};

    Putting all of that code in your function can become burdensome, so you
    can also just return the results of the "set_err" function in a single
    line. "set_err" sets $SQL::YASP::err to true, set $SQL::YASP::errstr to
    its single argument, and returns undef. So, for example, the divide
    operator function can look like this:

        $dbin[OP_MULT]{'/'} = {args=>ARG_NUMERIC, s=>sub{
            $_[1] or return set_err('divide by zero');
            $_[0] / $_[1];
        }};

    Be sure to *return* the results of "set_err", not just call it.

  A NOTE ABOUT THE "NOT" OPERATOR

    Any operator is negated by preceding it with "not". For example, our "="
    operator above can be negated like this:

        where first not = 'Joe"

    If the parser's "!_is_not" property is true (which it is by default),
    then "!" can be used as an alias for "not". Because "!" does not require
    any space after it to be parsed out, we already have a not-equals
    operator without having to define one:

        where first != 'Joe"

  Defining SQL Functions

    Like operators, SQL functions are stored as a set sub references in the
    parser object. The parser's "functions" property is a hash of function
    definitions. Suppose, for example, that you want your parser to
    recognize two functions: "upper", which uppercases its argument, and
    "larger", which returns the larger of its two arguments. We would set
    the "functions" property in "new" like this:

        sub new {
            my ($class) = @_;
            my $self = bless({}, $class);
        
            # operators
            $self->{'functions'} = 
                {
                'upper'  => { s=>sub{uc $_[0]} },
                'larger' => { s=>sub{$_[0]>$_[1] ? $_[0] : $_[1]}}, 
                };
        
            # always call after_new just
            # before returning new parser
            $self->after_new;
        
            return $self;
        }

    Each hash key is the name of the functon itself. Functions may consist
    of letters, numbers, and underscores, and must start with a letter. Use
    lowercase letters only. The value of the hash element is a function
    definition much like the operator definitions above. The only required
    property is "s" which references the subroutine to process the function.
    For short functions it is usually easiest to reference an anonymous
    subroutine. The "args" property can take the same values as for
    operators: "ARG_STRING", "ARG_RAW", "ARG_NUMERIC", and "ARG_SENDNULLS".
    For any of those type the subroutine will receive one argument: the
    value of the expression within the parens. There are also one other
    argument types for functions: "ARG_NONE", which means that the function
    takes no arguments.

    You might prefer to set your functions by grabbing a hash of all of the
    default functions, then adding to and deleting from the hash as needed.
    For example, suppose you wanted use all of the default functions, except
    that you want to delete the "trim" and "reverse" functions. You could do
    that with a "new" method like this:

        sub new {
            my ($class) = @_;
            my $self = bless({}, $class);
        
            # get default operators
            $self->{'functions'} = SQL::YASP::default_functions();
        
            # delete some functions we don't want
            delete $self->{'functions'}->{'trim'};
            delete $self->{'functions'}->{'reverse'};
        
            # always call after_new just
            # before returning new parser
            $self->after_new;
        
            return $self;
        }

    This code loads the defaults into the "functions" property by calling
    SQL::YASP::default_functions(), which returns an anonymous hash of all
    the default functions. Then it simply deletes "trim" and "reverse" from
    the hash.

  OVERRIDING OBJECT METHODS

    Your extending class can override any method, but there are several
    methods that were particularly designed for overriding. Those methods
    are described in more detail in the "Overrideable Methods" section
    below.

PARSER OBJECT [*]
  Properties [*]

    ops This property provides a set of SQL operators. See "Setting SQL
        Operators" for more details.

    functions
        This property provides a set of SQL functions. See "Setting SQL
        Functions" for more details.

    lukas [*]
    star_comments
        If true, the parser recognizes comments that begin with /* and end
        with */. Defaults to true.

    dash_comments
        If true, the parser recognizes comments that begin with -- and
        continue for the rest of the line. Defaults to true.

    pound_comments
        If true, the parser recognizes comments that begin with # and
        continue for the rest of the line. Defaults to true.

    quotes
        An array of which characters are recognized as quotes. Defaults to
        single and double quotes. Other characters are not currently
        supported. This property is changed from an array to a hash in
        after_new().

    !_is_not
        If true, the parser aliases the bang (aka the exclamation point: !)
        to the word "not". Defaults to true.

    perl_regex
        If true, the parser allows Perl-style regular expressions in the
        SQL. For example, the following code would be allowed:

            where
                first =~ m/ (Miko) | (Starflower) /ix

        Defaults to true.

    keep_org_sql
        If true, statement objects hold on to the original SQL string in the
        org_sql property. Defaults to false.

    dquote_escape
        If true, quotes inside quotes can be escaped by putting two quotes
        in a row. For example, the following expression set name to
        O'Sullivan:

            name='O''Sullivan'

        Defaults to true.

    backslash_escape
        If true, quotes inside quotes can be escaped by putting a backslash
        in front of the quote. For example, the following expression set
        name to O'Sullivan:

            name='O\'Sullivan'

        Defaults to true.

    commands
        This hash of hashes is used for specific situations where it may be
        ambiguous if the set of arguments is intended to be interpreted as a
        command or as an a field or table name. Currently, this property is
        only used in CREATE TABLE commands to interpret which in the list of
        arguments is a field name and which is a qualifier for the command.

    double_word_tokens
        A hash of tokens that consist of two words. Each key of the hash
        should be the first word of the token. The value of each element
        should be another hash, each key of which consists of a second word
        in the token, and each value of which consists of any true string.
        The default double_word_tokens property is created with code like
        this:

            $self->{'double_word_tokens'} ||= {
                primary  =>  {key=>1},
                current  =>  {date=>1},
                order    =>  {by=>1},
            };

  OVERRIDEABLE METHODS [*]

    new
    build_tree
    tree_create
    tree_create_table
    tree_select
    tree_delete
    tree_insert
    tree_update
    get_sections
    select_fields
    field_set_list
    UTILITY FUNCTIONS add_args sql_split arr_split comma_split object_list
    get_ixhash deref_args

STATEMENT OBJECT [*]
BINARY OPERATORS
    Here's a quick list of operators before we get to the full
    documentation:

        -
        %
        &&
        *
        /
        ^
        ||
        +
        <
        <=
        <=>
        <>
        =
        ==
        >
        >=
        and
        between
        eq
        eqi
        gt
        gti
        iin
        ilike
        in
        is
        like
        lt
        lti
        nand
        ne
        nei
        nor
        or
        xnor
        xor

  -

    Unary minus. Changes positive arguments to negative, negative arguments
    to positive.

        - 4

    returns

        -4

  %

    Modulus. Returns the remainder from dividing the first argument by the
    second.

        11 % 3

    returns

        2

  *

    Multiplication. Multiplies the numeric value of the first argument by
    the numeric value of the second.

        2*3

    returns

        6

  /

    Division. Divides the numeric value of the first argument by the numeric
    value of the second.

        6/3

    returns

        2

  ^

    Exponentiation. Raises the numeric value of the first argument by the
    numeric value of the second.

        2^3

    returns

        8

  ||

    Concatenation. Returns the first argument concatenated with the second
    argument.

        'x' || 'y'

    returns

        xy

  |||

    Concatenate with space in between.

        'x' ||| 'y'

    returns

        x y

    If either of the arguments is null then the space is not added. So, this
    expression

        'x' ||| null

    returns a string consisting solely of 'x'. Also, the first expression
    must end with a non-space and the second expression must begin with a
    non-space, or the operator returns the strings concatenated directly
    without an extra space in between them.

  +

    Addition. Adds the numeric value of the first argument to the numeric
    value of the second.

        5-3

    returns

        2

  <

    Numeric less-than. Returns true if the numeric value of the first
    argument is less than the numeric value of the second.

        5 < 3

    returns false.

  <=

    Numeric less-than-or-equal-to. Returns true if the numeric value of the
    first argument is less than or equal to the numeric value of the second.

        3<=5

    returns true.

  <=>

    Same as =.

  <>

    Numeric not-equal. Returns true if the numeric value of the first
    argument is not equal to the numeric value of the second.

        1 <> 0

    returns true.

  =

    String equality. Returns true if the two arguments are identical
    strings.

        'Joe'='Joe'

    returns true. This operator is case sensitive, so

        'Joe'='joe'

    returns false. This operator does *not* compare numerically, so

        '1.0' = '1'

    returns false. However, unquoted numbers are always normalized, so

        1.0 = 1

    returns true.

  ==

    Numeric equality. Returns true if the numeric value of the first
    argument is equal to the numeric value of the second.

        '1.0' == '1'

    returns true.

  =~

    Good old fashioned Perl regular expression matches. This operator allows
    you to do test if a string matches using familiar regex syntax. For
    example:

        name =~ m/
            (Joe) |   # regexes can include Perl-style 
            (Steve)   # comments if you use the x param
            /xis

    returns true if name contains the strings "Joe" or "Steve", case
    insensitively. Like in Perl, the x param means to ignore whitespace, the
    i means case-insensitive, and the s means to treat the entire expression
    like a single line.

  >

    Numeric greater-than. Returns true if the numeric value of the first
    argument is greater than the numeric value of the second.

        5 < 3

    returns true.

  >=

    Numeric greater-than-or-equal-to. Returns true if the numeric value of
    the first argument is greater than or equal to the numeric value of the
    second.

        5<=3

    returns true.

  AND

    Logical and. Identical to &&.

  BETWEEN

    Syntax: number_A BETWEEN number_B AND number_C

    Returns true if the number_A is greater than or equal to number_B and is
    also less than or equal to number_C.

        1 between -3 and 10

    returns true.

  EQ

    Case sensitive string equality.

        'Joe' eq 'Joe'

    returns true.

  EQI

    Case insensitive string equality.

        'JOE' eq 'joe'

    returns true.

  GT

    Case-sensitive string greater-than. Returns true if the first string is
    alphabetically after the second string.

        'pear' gt 'apple'

    returns true. Because it is a case-sensitive comparison, lower-case
    characters are greater then upper case characters:

        'Pear' gt 'apple'

    returns false.

  GTI

    Case-insensitive string greater-than. Returns true if the first string
    is alphabetically after the second string on a case-insensitive basis.

        'Pear' gti 'apple'

    returns true.

  IIN

    Case-insensitive version of IN. See IN below.

  ILIKE

    Case-insensitive version of LIKE. See LIKE below.

  IN

    Returns true if the argument before IN is in the list of arguments after
    IN.

        'Joe' in 'Steve', 'Joe', 'Fred'

    returns true. IN is case-sensitive. Use IIN for case-insensitivity.

  IREGEXP

    Case-insensitive version of REGEXP.

  IS NULL, IS NOT NULL

    "IS NULL" returns true of the preceding argument is null (that's undef
    to us Perl folk). An empty string is *not* null. "IS NOT NULL" return
    true if the preceding argument is not null.

  LIKE

    Like, y'know, returns true if the second argument can be found anywhere
    in the first argument.

        'Hi there Joey!' like 'there'

    returns true. LIKE recognizes two special characters. "_" means "any one
    character", and "%" means "zero or more of any character". So, for
    example, the following expression matches if NAME contains a string that
    begins with "J", then any one character, then "e". So "Hi Joe!", "Yo,
    Jae!", and "Jxe" would all match, but not "Jake".

        NAME like 'J_e'

    For another example, the following expression returns true if NAME
    contains a string that starts with "J", then zero or more characters,
    then "e". So "Je", and "Yo, Jack, how are ya?" would both match:

        NAME like 'J%e'

    ILIKE works just like LIKE, but is case-insensitive.

  LT

    String less-than.

        'apple' lt 'pear'

    returns true.

  LTI

    Case-insensitive string less-than.

        'apple' lt 'Pear'

    returns true.

  NAND

    Logical NAND. Returns true unless *both* arguments are true.

        true  nand true    -- returns false
        true  nand false   -- returns true
        false nand true    -- returns true
        false nand false   -- returns true

  NE

    String not-equal. Returns true if the string values of the two arguments
    are not the same.

        'Joe' ne 'Fred'

    returns true. This function is case-sensitive.

  NEI

    Case-insensitive string not-equal. Returns true if the string values of
    the two arguments are case-insensitively not the same.

        'Joe' nei 'Fred'

    returns true, whereas

        'JOE' nei 'joe'

    returns false.

  NOR

    Logical NOR. Returns true if *both* arguments are false.

        true  nor true    -- returns false
        true  nor false   -- returns false
        false nor true    -- returns false
        false nor false   -- returns true

  OR

    Logical OR. Returns true if either of the arguments is true.

        true  or true    -- returns true
        true  or false   -- returns true
        false or true    -- returns true
        false or false   -- returns false

  REGEXP

    Regular expression. Returns the results of matching the first argument
    against the second. Uses plain old Perl regular expression syntax.

        'whatever' regexp 'e*v'

    returns true. This operator is case sensitive. Use IREGEXP for a
    case-insensitivity.

    See also the "=~" operator for regexes that work like good old fashioned
    Perl regexes.

  XNOR

    Logical XNOR. Returns true if the truth of both arguments is equal.

        true  xnor true    -- returns true
        true  xnor false   -- returns false
        false xnor true    -- returns false
        false xnor false   -- returns true

  XOR

    Logical XOR. Returns true if the truth of both arguments is *not* equal.

        true  xor true    -- returns false
        true  xor false   -- returns true
        false xor true    -- returns true
        false xor false   -- returns false

FUNCTIONS [*]
    I'm still working on documenting all the functions. Here's a list of
    implemented functions so far to tide you over until I've gotten them all
    properly documented.

        -
        +
        abs
        cat
        cat_ws
        ceil
        ceiling
        char
        cmp
        coalesce
        concat
        concat_ws
        crunch
        defined
        elt
        err
        false
        field
        floor
        hascontent
        hasnull
        hex
        if
        insert
        instr
        int
        isnull
        lcase
        left
        length
        load_file
        locate
        lower
        lpad
        ltrim
        mid
        mod
        not
        null
        oct
        ord
        position
        pow
        power
        repeat
        replace
        reverse
        right
        rpad
        rtrim
        sign
        soundex
        space
        square
        squared
        strcmp
        substr
        substring
        substring_index
        tcase
        title
        tolower
        totitle
        toupper
        trim
        true
        ucase
        undef
        upper

TO DO
    Operators I haven't implemented yet: ascii conv bin octet_length
    char_length character_length bit_length

        find_in_set
        make_set
        export_set
    
        many math functions

TERMS AND CONDITIONS
    Copyright (c) 2003 by Miko O'Sullivan. All rights reserved. This program
    is free software; you can redistribute it and/or modify it under the
    same terms as Perl itself. This software comes with NO WARRANTY of any
    kind.

AUTHOR
    Miko O'Sullivan miko@idocs.com

VERSION
    Version 0.10 June 12, 2003
        Initial release

