Home » Database » SQL_Parser » Bug #6439
Improper handling of absolute column names eg: table.column
Details
| Submitted | 2006-01-07 20:52 UTC |
|---|---|
| From | shannah at sfu dot ca |
| Assigned | epte |
| Status | Closed |
| Package | SQL_Parser |
| PHP Version | 4.4.1 |
| OS | Solaris 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.