PEAR is archived and read-only

This mirror preserves historical PEAR package releases and metadata so existing references remain available.

Home » Database » SQL_Parser » Bug #6439

Improper handling of absolute column names eg: table.column

Details

Submitted2006-01-07 20:52 UTC
Fromshannah at sfu dot ca
Assignedepte
StatusClosed
PackageSQL_Parser
PHP Version4.4.1
OSSolaris and OS X
Roadmaps(Not assigned)

Comments

[2006-01-07 20:52 UTC] shannah at sfu dot ca

Description:
------------
There is a section of code in SQL_Parser::parseSelect() that
is not functioning the way it appears to be intended. When
it tries to parse a column that contains a period (eg:
foo.a, foo.*, etc..) the code appears to be designed to
parse this, but it is not working. I'll give a concrete
example later in this post.

This has some consequences. If we fix this problem so that
it works the way it looks like it is intended to, then it
will change the output structure of parsed SQL (which will,
in turn break code that uses SQL_Parser).

Here is an example:

$struct = $parser->parse("select foo.a from foo");
print_r($struct);

Outputs:
Array
(
[command] => select
[column_tables] => Array
(
[0] =>
)

[column_names] => Array
(
[0] => foo.a
)

[column_aliases] => Array
(
[0] =>
)

[table_names] => Array
(
[0] => foo
)

[table_aliases] => Array
(
[0] =>
)

[table_join_clause] => Array
(
[0] =>
)

)

After looking at the code it appears that the author
intended this to output:

Array
(
[command] => select
[column_tables] => Array
(
[0] => foo
)

[column_names] => Array
(
[0] => a
)

[column_aliases] => Array
(
[0] =>
)

[table_names] => Array
(
[0] => foo
)

[table_aliases] => Array
(
[0] =>
)

[table_join_clause] => Array
(
[0] =>
)

)

Here is the suspect portion of code :

...
if ($this->token == 'ident' || $this->isFunc() || $this-
>token == '*') {
while ($this->token != 'from') {
if ($this->token == 'ident' || $this->token
== '*') {
$prevTok = $this->token;
$prevTokText = $this->lexer->tokText;
$this->getTok();
if ($this->token == '.') {
$columnTable = $prevTokText;
$this->getTok();
$prevTok = $this->token;
$prevTokText = $this->lexer-
>tokText;
} else {
$columnTable = '';
}

if ($prevTok == 'ident') {
$columnName = $prevTokText;
} else if ($prevTok == '*' ){
$columnName = $prevTok;
} else {
return $this->raiseError('Expected
column name');
}

if ($this->token == 'as') {
$this->getTok();
if ($this->token == 'ident' ) {
$columnAlias = $this->lexer-
>tokText;
} else {
return $this->raiseError
('Expected column alias');
}
} elseif ($this->token == 'ident') {
$columnAlias = $this->lexer-
>tokText;
} else {
$columnAlias = '';
}

$tree['column_tables'][] = $columnTable;
$tree['column_names'][] = $columnName;
$tree['column_aliases'][] =
$columnAlias;

...

And more specifically we can zero in on this portion of
code:

$prevTok = $this->token;
$prevTokText = $this->lexer->tokText;
$this->getTok();
if ($this->token == '.') {
$columnTable = $prevTokText;
$this->getTok();
$prevTok = $this->token;
$prevTokText = $this->lexer-
>tokText;

The lexer does not seem to regard a dot ('.') as a token,
and therefore the code inside the 'if' statement:
if ($this->token == '.'){
never evaluates to true.

This means that $columnTable will always be set to '' and
columnName will always be the full column name (including
the table name).

[2006-01-11 18:58 UTC] epte at php dot net

Yes, I was just noticing something like this before break. Thank you for the analysis. I'll try to get to this soon :-)

Did you happen to check the content of the tokens? Is the '.' being regarded as its own token?

Erich

[2006-01-11 19:06 UTC] shannah at sfu dot ca

No, '.' does not seem to be regarded as its own token. e.g.:
In the string "A foo.bar string" we would have tokens:
A
foo.bar
string

[2006-04-03 05:26 UTC] epte at php dot net

This bug has been fixed.