Skip to content

Correct Handling of Negative Numerical Literals #215

@dey4ss

Description

@dey4ss

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)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions