Package home | Report new bug | New search | Development Roadmap Status: Open | Feedback | All | Closed Since Version 0.7.0

Bug #6439 Improper handling of absolute column names eg: table.column
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)    
Subscription  


 [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).

Comments

 [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 (Erich Enke)
This bug has been fixed.