<?php 
 
/** 
 * 
 * Sql_ParserSelect 
 * @package Sql 
 * @subpackage Sql_Parser 
 * @author Thomas Schaefer 
 * @since 30.11.2008  
 * @desc parses a sql select into object 
 */ 
 
/** 
 * 
 * Sql_ParserSelect 
 * @package Sql 
 * @subpackage Sql_Parser 
 * @author Thomas Sch�fer 
 * @since 30.11.2008 07:49:30 
 * @desc parses a sql select into object 
 */ 
class Sql_ParserSelect { 
 
    /** 
     * parse select 
     * 
     * @param bool $subSelect 
     * @return array 
     */ 
    public static function doParse($subSelect = false)  
    { 
        $tree = array('Command' => 'select'); 
         
        Sql_Parser::getTok(); 
                 
        if ((Sql_Object::token() == 'distinct') || (Sql_Object::token() == 'all')) { 
            $tree['Quantifier'] = Sql_Object::token(); 
            Sql_Parser::getTok(); 
        } 
 
        $tree = Sql_Parser::parseColumns($tree); 
                 
        if (Sql_Object::token() != 'from') { 
            return Sql_Parser::raiseError('Expected "from"', __LINE__); 
        } 
 
        #################### 
                 
        Sql_Parser::getTok(); 
        $tree['TableNames'] = array(); 
         
        while (Sql_Object::token() == 'ident')  
        { 
            $tableNameToken = Sql_Object::lexer()->tokText; 
            // added 2008-01-16 
            if(strpos($tableNameToken,".")>0) 
            { 
                $arrTableNameToken = explode(".",$tableNameToken); 
                switch(count($arrTableNameToken)) { 
                    case 2: 
                        if(empty($tree['DatabaseNames'])) $tree['DatabaseNames'] = array(); 
                        $tree['DatabaseNames'][] = $arrTableNameToken[0]; 
                        $tree['TableNames'][] = $arrTableNameToken[1]; 
                    break; 
                    default: 
                       $tree['TableNames'][] = Sql_Object::lexer()->tokText; 
                        break; 
                } 
            }  
            else  
            { 
                $tree['TableNames'][] = Sql_Object::lexer()->tokText; 
            } 
             
            Sql_Parser::getTok(); 
             
            if (Sql_Object::token() == 'ident')  
            { 
                $tree['TableAliases'][] = Sql_Object::lexer()->tokText; 
                Sql_Parser::getTok(); 
            }  
            elseif (Sql_Object::token() == 'as')  
            { 
                Sql_Parser::getTok(); 
                if (Sql_Object::token() == 'ident')  
                { 
                    $tree['TableAliases'][] = Sql_Object::lexer()->tokText; 
                }  
                else  
                { 
                    return Sql_Parser::raiseError('Expected table alias', __LINE__); 
                } 
                 
                Sql_Parser::getTok(); 
                 
            } else { 
                $tree['TableAliases'][] = ''; 
            } 
             
            if (Sql_Object::token() == 'on')  
            { 
                $clause = Sql_Parser::parseSearchClause(); 
             
                if (Sql_Parser::isError($clause))  
                { 
                    return $clause; 
                } 
                 
                $tree['Joins'][] = $clause; 
            }  
            else  
            { 
                $tree['Joins'][] = ''; 
            } 
             
            if (Sql_Object::token() == ',')  
            { 
                $tree['Join'][] = ','; 
                Sql_Parser::getTok(); 
            }  
            elseif (Sql_Object::token() == 'join')  
            { 
                $tree['Join'][] = 'JOIN'; 
                Sql_Parser::getTok(); 
            }  
            elseif ((Sql_Object::token() == 'cross') or (Sql_Object::token() == 'inner'))  
            { 
                $join = Sql_Object::lexer()->tokText; 
                Sql_Parser::getTok(); 
                if (Sql_Object::token() != 'join') { 
                    return Sql_Parser::raiseError('Expected token "join"', __LINE__); 
                } 
                $tree['Join'][] = strtoupper($join).' JOIN'; 
             
                Sql_Parser::getTok(); 
            }  
            elseif ((Sql_Object::token() == 'left') or (Sql_Object::token() == 'right'))  
            { 
                $join = Sql_Object::lexer()->tokText; 
             
                Sql_Parser::getTok(); 
             
                if (Sql_Object::token() == 'join')  
                { 
                    $tree['Join'][] = strtoupper($join).' JOIN'; 
                }  
                elseif (Sql_Object::token() == 'outer')  
                { 
                    $join .= ' outer'; 
                    Sql_Parser::getTok(); 
                    if (Sql_Object::token() == 'join') { 
                        $tree['Join'][] = strtoupper($join).' JOIN'; 
                    } else { 
                        return Sql_Parser::raiseError('Expected token "join"', __LINE__); 
                    } 
                }  
                else  
                { 
                    return Sql_Parser::raiseError('Expected token "outer" or "join"', __LINE__); 
                } 
                 
                Sql_Parser::getTok(); 
                 
            }  
            elseif (Sql_Object::token() == 'natural')  
            { 
                $join = Sql_Object::lexer()->tokText; 
             
                Sql_Parser::getTok(); 
             
                if (Sql_Object::token() == 'join')  
                { 
                    $tree['Join'][] = strtoupper($join).' JOIN'; 
                }  
                elseif ((Sql_Object::token() == 'left') or (Sql_Object::token() == 'right'))  
                { 
                    $join .= ' '. Sql_Object::token(); 
                     
                    Sql_Parser::getTok(); 
                     
                    if (Sql_Object::token() == 'join')  
                    { 
                        $tree['Join'][] = strtoupper($join).' JOIN'; 
                    }  
                    elseif (Sql_Object::token() == 'outer')  
                    { 
                        $join .= ' '.Sql_Object::token(); 
                        Sql_Parser::getTok(); 
                        if (Sql_Object::token() == 'join')  
                        { 
                            $tree['Join'][] = strtoupper($join).' JOIN'; 
                        }  
                        else  
                        { 
                            return Sql_Parser::raiseError('Expected token "join" or "outer"', __LINE__); 
                        } 
                    }  
                    else  
                    { 
                        return Sql_Parser::raiseError('Expected token "join" or "outer"', __LINE__); 
                    } 
                }  
                else  
                { 
                    return Sql_Parser::raiseError('Expected token "left", "right" or "join"', __LINE__); 
                } 
                 
                Sql_Parser::getTok(); 
                 
            }  
            elseif ((Sql_Object::token() == 'where') or 
            (Sql_Object::token() == 'order') or 
            (Sql_Object::token() == 'limit') or 
            (is_null(Sql_Object::token())))  
            { 
                break; 
            } 
        } 
         
        ############################### 
        while ( 
            !is_null(Sql_Object::token()) and  
            (!$subSelect or Sql_Object::token() != Sql_Parser::OPENBRACE) and  
            Sql_Object::token() != Sql_Parser::CLOSEBRACE and  
            Sql_Object::token() != Sql_Parser::SEMICOLON 
        ) { 
             
            switch (Sql_Object::token())  
            { 
                case 'where': 
                    $clause = Sql_Parser::parseSearchClause(); 
                     
                    if (Sql_Parser::isError($clause))  
                    { 
                        return $clause; 
                    } 
                     
                    $tree['Where'] = $clause; 
                     
                    break; 
                case 'order': 
                     
                    Sql_Parser::getTok(); 
                     
                    if (Sql_Object::token() != 'by')  
                    { 
                        return Sql_Parser::raiseError('Expected "by"', __LINE__); 
                    } 
                     
                    Sql_Parser::getTok(); 
                     
                    while (Sql_Object::token() == 'ident')  
                    { 
                        $col = Sql_Object::lexer()->tokText; 
                         
                        Sql_Parser::getTok(); 
                         
                        if (Sql_Object::has("synonyms.".Sql_Object::token()))  
                        { 
                            $order = Sql_Object::get("synonyms.".Sql_Object::token()); 
                            if (($order != 'asc') && ($order != 'desc'))  
                            { 
                                return Sql_Parser::raiseError('Unexpected token', __LINE__); 
                            } 
                            Sql_Parser::getTok(); 
                        }  
                        else  
                        { 
                            $order = 'ASC'; 
                        } 
                         
                        if (Sql_Object::token() == ',')  
                        { 
                            Sql_Parser::getTok(); 
                        } 
                         
                        $tree['SortOrder'][$col] = strtoupper($order); 
                    } 
                    break; 
                case 'limit': 
                     
                    Sql_Parser::getTok(); 
                     
                    if (Sql_Object::token() != 'int_val')  
                    { 
                        return Sql_Parser::raiseError('Expected an integer value', __LINE__); 
                    } 
                     
                    $length = Sql_Object::lexer()->tokText; 
                    $start = 0; 
                     
                    Sql_Parser::getTok(); 
                     
                    if (Sql_Object::token() == ',')  
                    { 
                        Sql_Parser::getTok(); 
                     
                        if (Sql_Object::token() != 'int_val')  
                        { 
                            return Sql_Parser::raiseError('Expected an integer value', __LINE__); 
                        } 
                     
                        $start = $length; 
                        $length = Sql_Object::lexer()->tokText; 
                     
                        Sql_Parser::getTok(); 
                     
                    } 
                    $tree['Limit'] = array('Start'=>$start, 'Length'=>$length); 
                    break; 
                case 'group': 
                     
                    Sql_Parser::getTok(); 
                     
                    if (Sql_Object::token() != 'by')  
                    { 
                        return Sql_Parser::raiseError('Expected "by"', __LINE__); 
                    } 
                     
                    Sql_Parser::getTok(); 
                     
                    while (Sql_Object::token() == 'ident')  
                    { 
                        $col = Sql_Object::lexer()->tokText; 
                     
                        Sql_Parser::getTok(); 
                     
                        if (Sql_Object::token() == ',')  
                        { 
                            Sql_Parser::getTok(); 
                        } 
                         
                        $tree['GroupBy'][] = $col; 
                         
                    } 
                    break; 
                case 'having': 
                     
                    $clause = Sql_Parser::parseSearchClause(); 
                     
                    if (Sql_Parser::isError($clause))  
                    { 
                        return $clause; 
                    } 
                     
                    $tree['Having'] = $clause; 
                     
                    break; 
                default: 
                    return Sql_Parser::raiseError('Unexpected clause', __LINE__); 
            } 
        } 
         
         
        // added due to Alireza Eliaderani's mail from 2008-01-16  
        if(isset($tree['ColumnTables']) and count($tree['ColumnTables']) )  
        { 
            $tree['ColumnTableAliases'] = array(); 
            foreach($tree['ColumnTables'] as &$colTbls){ 
                if(in_array($colTbls,$tree['TableAliases'])){ 
                    $tree['ColumnTableAliases'][]=$colTbls; 
                    $index=array_search($colTbls,$tree['TableAliases']); 
                    $colTbls=$tree['TableNames'][$index]; 
                }else{ 
                    $tree['ColumnTableAliases'][]=""; 
                } 
            }             
             
        } 
        return $tree; 
    } 
 
    public static function parse(){ 
        return self::doParse(); 
    } 
} 
 
 
 |