As mentioned by @JoyBinY in #213, the parser does not handle negative numerical literals correctly in all cases, especially for INSERT statements.
Code for Reproduction:
INSERT INTO foo VALUES (1, 'bar', -2);
^=== ERROR HERE!
An INSERT INTO ... VALUES statement has a literal list to represent the values. A literal is defined as
literal : string_literal | bool_literal | num_literal | null_literal | date_literal | interval_literal | param_expr;
The numeric literal can be either an integer or a float (both parsed from unsigned values by the lexer). We represent a negative number as unary - operator expression with the numeric literal as input in other cases, which is not a literal anymore.
However, the solution suggested in #213 is not sufficient either, as allowing negative values for all integers also enables, e.g., the following statements:
CREATE TABLE foo (bar VARCHAR(-5));
SELECT TOP -3 bar FROM foo;
A possible solution (option 1) could be to expand the num_literal definition from:
num_literal : FLOATVAL { $$ = Expr::makeLiteral($1); }
| int_literal;
to something like:
num_literal : FLOATVAL { $$ = Expr::makeLiteral($1); }
| int_literal;
| '-' FLOATVAL { $$ = Expr::makeOpUnary(kOpUnaryMinus, Expr::makeLiteral($2)); }
| '-' int_literal { $$ = Expr::makeOpUnary(kOpUnaryMinus, $2); };
or:
unsigned_num_literal: FLOATVAL { $$ = Expr::makeLiteral($1); }
| int_literal;
num_literal : unsigned_num_literal
| '-' unsigned_num_literal {
$2->ival = $2->ival * -1;
$2->fval = $2->fval * -1;
$$ = $2; // or just $$ = Expr::makeOpUnary(kOpUnaryMinus, $2);
};
As the num_literal, in contrast to [INT|FLOAT]VAL and int_literal, is only used in the literal definition, we should not interfere with the definitions requesting unsigned integers.
An alternative (option 2) could be to define unsigned and signed versions of [INT|FLOAT]VAL in the lexer and use these versions accordingly in all definitions.
@Bouncner @klauck @mweisgut what are your opinions on this topic?
Furthermore, I noticed that INSERT statements are not properly tested in the SQL tests, negative numbers in INSERT statement do not appear in our test queries (queries_good.sql), and neither do the permitted examples from above (queries_bad.sql)
As mentioned by @JoyBinY in #213, the parser does not handle negative numerical literals correctly in all cases, especially for
INSERTstatements.Code for Reproduction:
An
INSERT INTO ... VALUESstatement has a literal list to represent the values. A literal is defined asThe numeric literal can be either an integer or a float (both parsed from unsigned values by the lexer). We represent a negative number as unary
-operator expression with the numeric literal as input in other cases, which is not a literal anymore.However, the solution suggested in #213 is not sufficient either, as allowing negative values for all integers also enables, e.g., the following statements:
A possible solution (option 1) could be to expand the
num_literaldefinition from:to something like:
or:
As the
num_literal, in contrast to[INT|FLOAT]VALandint_literal, is only used in theliteraldefinition, we should not interfere with the definitions requesting unsigned integers.An alternative (option 2) could be to define unsigned and signed versions of
[INT|FLOAT]VALin the lexer and use these versions accordingly in all definitions.@Bouncner @klauck @mweisgut what are your opinions on this topic?
Furthermore, I noticed that
INSERTstatements are not properly tested in the SQL tests, negative numbers inINSERTstatement do not appear in our test queries (queries_good.sql), and neither do the permitted examples from above (queries_bad.sql)