@@ -346,6 +346,39 @@ public function lex()
346346
347347 // Saving the tokens list.
348348 $ this ->list = $ list ;
349+
350+ $ this ->solveAmbiguityOnStarOperator ();
351+ }
352+
353+ /**
354+ * Resolves the ambiguity when dealing with the "*" operator.
355+ *
356+ * In SQL statements, the "*" operator can be an arithmetic operator (like in 2*3) or an SQL wildcard (like in
357+ * SELECT a.* FROM ...). To solve this ambiguity, the solution is to find the next token, excluding whitespaces and
358+ * comments, right after the "*" position. The "*" is for sure an SQL wildcard if the next token found is any of:
359+ * - "FROM" (the FROM keyword like in "SELECT * FROM...");
360+ * - "USING" (the USING keyword like in "DELETE table_name.* USING...");
361+ * - "," (a comma separator like in "SELECT *, field FROM...");
362+ * - ")" (a closing parenthesis like in "COUNT(*)").
363+ * This methods will change the flag of the "*" tokens when any of those condition above is true. Otherwise, the
364+ * default flag (arithmetic) will be kept.
365+ *
366+ * @return void
367+ */
368+ private function solveAmbiguityOnStarOperator ()
369+ {
370+ $ iBak = $ this ->list ->idx ;
371+ while (null !== ($ starToken = $ this ->list ->getNextOfTypeAndValue (Token::TYPE_OPERATOR , '* ' ))) {
372+ // ::getNext already gets rid of whitespaces and comments.
373+ if (($ next = $ this ->list ->getNext ()) !== null ) {
374+ if (($ next ->type === Token::TYPE_KEYWORD && in_array ($ next ->value , ['FROM ' , 'USING ' ], true ))
375+ || ($ next ->type === Token::TYPE_OPERATOR && in_array ($ next ->value , [', ' , ') ' ], true ))
376+ ) {
377+ $ starToken ->flags = Token::FLAG_OPERATOR_SQL ;
378+ }
379+ }
380+ }
381+ $ this ->list ->idx = $ iBak ;
349382 }
350383
351384 /**
@@ -842,6 +875,7 @@ public function parseNumber()
842875 * @param string $quote additional starting symbol
843876 *
844877 * @return null|Token
878+ * @throws LexerException
845879 */
846880 public function parseString ($ quote = '' )
847881 {
@@ -889,6 +923,7 @@ public function parseString($quote = '')
889923 * Parses a symbol.
890924 *
891925 * @return null|Token
926+ * @throws LexerException
892927 */
893928 public function parseSymbol ()
894929 {
@@ -914,7 +949,7 @@ public function parseSymbol()
914949 $ str = null ;
915950
916951 if ($ this ->last < $ this ->len ) {
917- if (($ str = $ this ->parseString (' ` ' )) === null ) {
952+ if (($ str = $ this ->parseString (Context:: getIdentifierQuote () )) === null ) {
918953 if (($ str = $ this ->parseUnknown ()) === null ) {
919954 $ this ->error (
920955 'Variable name was expected. ' ,
0 commit comments