LibSQL: Gracefully react to unimplemented valid SQL

Fixes a crash that was caused by a syntax error which is difficult to
catch by the parser: usually identifiers are accepted in column lists,
but they are not in a list of column values to be inserted in an INSERT.

Fixed this by putting in a heuristic check; we probably need a better
way to do this.

Included tests for this case.

Also introduced a new SQL Error code, `NotYetImplemented`, and return
that instead of crashing when encountering unimplemented SQL.
This commit is contained in:
Jan de Visser 2021-11-13 17:30:29 -05:00 committed by Ali Mohammad Pur
parent 001949d77a
commit c369626ac1
Notes: sideshowbarker 2024-07-17 23:11:28 +09:00
2 changed files with 26 additions and 0 deletions

View file

@ -137,6 +137,28 @@ TEST_CASE(insert_wrong_number_of_values)
EXPECT(result->inserted() == 0);
}
TEST_CASE(insert_identifier_as_value)
{
ScopeGuard guard([]() { unlink(db_name); });
auto database = SQL::Database::construct(db_name);
EXPECT(!database->open().is_error());
create_table(database);
auto result = execute(database, "INSERT INTO TestSchema.TestTable VALUES ( identifier, 42 );");
EXPECT(result->error().code == SQL::SQLErrorCode::SyntaxError);
EXPECT(result->inserted() == 0);
}
TEST_CASE(insert_quoted_identifier_as_value)
{
ScopeGuard guard([]() { unlink(db_name); });
auto database = SQL::Database::construct(db_name);
EXPECT(!database->open().is_error());
create_table(database);
auto result = execute(database, "INSERT INTO TestSchema.TestTable VALUES ( \"QuotedIdentifier\", 42 );");
EXPECT(result->error().code == SQL::SQLErrorCode::SyntaxError);
EXPECT(result->inserted() == 0);
}
TEST_CASE(insert_without_column_names)
{
ScopeGuard guard([]() { unlink(db_name); });

View file

@ -169,6 +169,10 @@ Value UnaryOperatorExpression::evaluate(ExecutionContext& context) const
Value ColumnNameExpression::evaluate(ExecutionContext& context) const
{
if (!context.current_row) {
context.result->set_error(SQLErrorCode::SyntaxError, column_name());
return Value::null();
}
auto& descriptor = *context.current_row->descriptor();
VERIFY(context.current_row->size() == descriptor.size());
Optional<size_t> index_in_row;