<?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();
}
}
|