[#5955] Improved error messages

This commit is contained in:
lukaseder 2017-04-19 16:02:18 +02:00
parent ea75cfca5f
commit 93b9ff7fc1

View File

@ -340,7 +340,7 @@ class ParserImpl implements Parser {
while (parseIf(ctx, ";"));
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of queries input");
return new QueriesImpl(result);
}
@ -351,7 +351,7 @@ class ParserImpl implements Parser {
Query result = parseQuery(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of query input");
return result;
}
@ -362,7 +362,7 @@ class ParserImpl implements Parser {
Table<?> result = parseTable(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of table input");
return result;
}
@ -373,7 +373,7 @@ class ParserImpl implements Parser {
Field<?> result = parseField(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of field input");
return result;
}
@ -384,7 +384,7 @@ class ParserImpl implements Parser {
RowN result = parseRow(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of row input");
return result;
}
@ -395,7 +395,7 @@ class ParserImpl implements Parser {
Condition result = parseCondition(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of condition input");
return result;
}
@ -406,7 +406,7 @@ class ParserImpl implements Parser {
Name result = parseName(ctx);
if (!ctx.done())
throw ctx.exception();
throw ctx.exception("Unexpected content after end of name input");
return result;
}
@ -508,7 +508,7 @@ class ParserImpl implements Parser {
throw ctx.unexpectedToken();
}
throw ctx.exception();
throw ctx.exception("Unsupported query type");
}
// -----------------------------------------------------------------------------------------------------------------
@ -708,7 +708,7 @@ class ParserImpl implements Parser {
List<Field<?>> select = parseSelectList(ctx);
if (degree != null && select.size() != degree)
throw ctx.exception();
throw ctx.exception("Select list must contain " + degree + " columns. Got: " + select.size());
Table<?> into = null;
List<Table<?>> from = null;
@ -879,7 +879,7 @@ class ParserImpl implements Parser {
List<Field<?>> values = parseFields(ctx);
if (fields != null && fields.length != values.size())
throw ctx.exception();
throw ctx.exception("Insert field size (" + fields.length + ") must match values size (" + values.size() + ")");
allValues.add(values);
parse(ctx, ')');
@ -910,7 +910,7 @@ class ParserImpl implements Parser {
}
else if (parseKeywordIf(ctx, "DEFAULT VALUES")) {
if (fields != null)
throw ctx.exception();
throw ctx.notImplemented("DEFAULT VALUES without INSERT field list");
else
returning = onDuplicate = ctx.dsl.insertInto(tableName).defaultValues();
}
@ -989,7 +989,7 @@ class ParserImpl implements Parser {
Field<?> field = parseFieldName(ctx);
if (map.containsKey(field))
throw ctx.exception();
throw ctx.exception("Duplicate column in set clause list: " + field);
parse(ctx, '=');
Field<?> value = parseField(ctx);
@ -1032,14 +1032,14 @@ class ParserImpl implements Parser {
parse(ctx, ')');
if (insertColumns.length != insertValues.size())
throw ctx.exception();
throw ctx.exception("Insert column size (" + insertColumns.length + ") must match values size (" + insertValues.size() + ")");
}
else
break;
}
if (!update && !insert)
throw ctx.exception();
throw ctx.exception("At least one of UPDATE or INSERT clauses is required");
// TODO support WHERE
// TODO support multi clause MERGE
@ -1154,7 +1154,7 @@ class ParserImpl implements Parser {
Select<?> select = parseSelect(ctx);
if (fields.length > 0 && fields.length != select.getSelect().size())
throw ctx.exception();
throw ctx.exception("Select list size (" + select.getSelect().size() + ") must match declared field size (" + fields.length + ")");
return ifNotExists
@ -1320,7 +1320,7 @@ class ParserImpl implements Parser {
if (parseKeywordIf(ctx, "PRIMARY KEY")) {
if (primary) {
throw ctx.exception();
throw ctx.exception("Duplicate primary key specification");
}
else {
primary = true;
@ -1353,7 +1353,7 @@ class ParserImpl implements Parser {
parse(ctx, ')');
if (referencing.length != referencedFields.length)
throw ctx.exception();
throw ctx.exception("Number of referencing columns (" + referencing.length + ") must match number of referenced columns (" + referencedFields.length + ")");
constraints.add(constraint == null
? foreignKey(referencing).references(referencedTable, referencedFields)
@ -1437,7 +1437,7 @@ class ParserImpl implements Parser {
parse(ctx, ')');
if (referencing.length != referencedFields.length)
throw ctx.exception();
throw ctx.exception("Number of referencing columns must match number of referenced columns");
return constraint == null
? s1.add(foreignKey(referencing).references(referencedTable, referencedFields))
@ -1858,7 +1858,7 @@ class ParserImpl implements Parser {
// TODO: Support this for ROW as well
if (((Field) left) == null)
throw ctx.exception();
throw ctx.notImplemented("DISTINCT predicate for rows");
Field right = toField(ctx, parseConcat(ctx, null));
return not ? ((Field) left).isNotDistinctFrom(right) : ((Field) left).isDistinctFrom(right);
@ -1968,7 +1968,7 @@ class ParserImpl implements Parser {
}
else if (parseKeywordIf(ctx, "UNNEST")) {
// TODO
throw ctx.exception();
throw ctx.notImplemented("UNNEST");
}
else if (parseIf(ctx, '(')) {
if (peekKeyword(ctx, "SELECT")) {
@ -2153,10 +2153,10 @@ class ParserImpl implements Parser {
else if (fieldsOrRows.size() == 1)
row = (RowN) fieldsOrRows.get(0);
else
throw ctx.exception();
throw ctx.exception("Unsupported row size");
if (degree != null && row.size() != degree)
throw ctx.exception();
throw ctx.exception("Expected row of degree: " + degree + ". Got: " + row.size());
parse(ctx, ')');
return row;
@ -2380,9 +2380,9 @@ class ParserImpl implements Parser {
if (((Field) part).getDataType().getType() == Boolean.class)
return condition((Field) part);
else
throw ctx.exception();
throw ctx.expected("Boolean field");
else
throw ctx.exception();
throw ctx.expected("Condition");
}
private static final FieldOrRow toFieldOrRow(ParserContext ctx, QueryPart part) {
@ -2395,7 +2395,7 @@ class ParserImpl implements Parser {
else if (part instanceof Row)
return (Row) part;
else
throw ctx.exception();
throw ctx.expected("Field or row");
}
private static final Field<?> toField(ParserContext ctx, QueryPart part) {
@ -2406,7 +2406,7 @@ class ParserImpl implements Parser {
else if (part instanceof Condition)
return field((Condition) part);
else
throw ctx.exception();
throw ctx.expected("Field");
}
private static final FieldOrRow parseConcat(ParserContext ctx, Type type) {
@ -2477,7 +2477,7 @@ class ParserImpl implements Parser {
for (;;)
if (parseIf(ctx, '+'))
sign = 1;
sign = sign == null ? 1 : sign;
else if (parseIf(ctx, '-'))
sign = sign == null ? -1 : -sign;
else
@ -2872,7 +2872,7 @@ class ParserImpl implements Parser {
if (peekKeyword(ctx, "SELECT")) {
SelectQueryImpl<Record> select = parseSelect(ctx);
if (select.getSelect().size() > 1)
throw ctx.exception();
throw ctx.exception("Select list must contain at least one column");
field = field((Select) select);
parse(ctx, ')');
@ -3082,7 +3082,7 @@ class ParserImpl implements Parser {
return Timestamp.valueOf(parseStringLiteral(ctx));
}
catch (IllegalArgumentException e) {
throw ctx.exception();
throw ctx.exception("Illegal timestamp literal");
}
}
@ -3109,7 +3109,7 @@ class ParserImpl implements Parser {
return Time.valueOf(parseStringLiteral(ctx));
}
catch (IllegalArgumentException e) {
throw ctx.exception();
throw ctx.exception("Illegal time literal");
}
}
@ -3133,7 +3133,7 @@ class ParserImpl implements Parser {
return Date.valueOf(parseStringLiteral(ctx));
}
catch (IllegalArgumentException e) {
throw ctx.exception();
throw ctx.exception("Illegal date literal");
}
}
@ -3722,7 +3722,7 @@ class ParserImpl implements Parser {
case NULL:
return inline((Boolean) null);
default:
throw ctx.exception();
throw ctx.exception("Truth value not supported: " + truth);
}
}
@ -4186,7 +4186,7 @@ class ParserImpl implements Parser {
case REGR_SYY:
return regrSYY(arg1, arg2);
default:
throw ctx.exception();
throw ctx.exception("Binary set function not supported: " + type);
}
}
@ -4450,7 +4450,7 @@ class ParserImpl implements Parser {
do {
if (!result.add(parseIdentifier(ctx)))
throw ctx.exception();
throw ctx.exception("Duplicate identifier encountered");
}
while (parseIf(ctx, ','));
return new ArrayList<Name>(result);
@ -4460,7 +4460,7 @@ class ParserImpl implements Parser {
Name result = parseIdentifierIf(ctx);
if (result == null)
throw ctx.exception();
throw ctx.expected("Identifier");
return result;
}
@ -4486,14 +4486,11 @@ class ParserImpl implements Parser {
if (ctx.position == start)
return null;
if (ctx.position - start < 0)
throw ctx.exception();
String result = new String(ctx.sql, start, ctx.position - start);
if (quoteEnd != 0) {
if (ctx.character() != quoteEnd)
throw ctx.exception();
throw ctx.exception("Quoted identifier must terminate in " + quoteEnd);
ctx.position = ctx.position + 1;
return DSL.quotedName(result);
@ -4584,7 +4581,7 @@ class ParserImpl implements Parser {
return DSL.param(parseIdentifier(ctx).last());
default:
throw ctx.exception();
throw ctx.exception("Illegal bind variable character");
}
}
@ -4607,11 +4604,18 @@ class ParserImpl implements Parser {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
char c1 = 0;
char c2 = 0;
int i = ctx.position;
do {
c1 = ctx.character(i);
c2 = ctx.character(i + 1);
for (;;) {
c1 = ctx.character(ctx.position);
if (c1 == ' ')
ctx.position = ctx.position + 1;
else
break;
}
c2 = ctx.character(ctx.position + 1);
if (c1 == '\'')
break;
@ -4622,17 +4626,17 @@ class ParserImpl implements Parser {
buffer.write(Integer.parseInt("" + c1 + c2, 16));
}
catch (NumberFormatException e) {
throw ctx.exception();
throw ctx.exception("Illegal character for binary literal");
}
}
while ((i = i + 2) < ctx.sql.length);
while ((ctx.position = ctx.position + 2) < ctx.sql.length);
if (c1 == '\'') {
ctx.position = i + 1;
ctx.position = ctx.position + 1;
return buffer.toByteArray();
}
throw ctx.exception();
throw ctx.exception("Binary literal not terminated");
}
return null;
@ -4651,7 +4655,7 @@ class ParserImpl implements Parser {
case '(': end = ')'; ctx.position = ctx.position + 1; break;
case '<': end = '>'; ctx.position = ctx.position + 1; break;
default:
throw ctx.exception();
throw ctx.exception("Illegal quote string character");
}
StringBuilder sb = new StringBuilder();
@ -4670,7 +4674,7 @@ class ParserImpl implements Parser {
sb.append(c);
}
throw ctx.exception();
throw ctx.exception("Quoted string literal not terminated");
}
private static final String parseUnquotedStringLiteral(ParserContext ctx) {
@ -4693,7 +4697,7 @@ class ParserImpl implements Parser {
sb.append(c);
}
throw ctx.exception();
throw ctx.exception("String literal not terminated");
}
private static final Field<Number> parseFieldUnsignedNumericLiteral(ParserContext ctx, boolean minus) {
@ -4767,7 +4771,7 @@ class ParserImpl implements Parser {
Long result = parseUnsignedIntegerIf(ctx);
if (result == null)
throw ctx.exception();
throw ctx.expected("Unsigned integer");
return result;
}
@ -5168,11 +5172,19 @@ class ParserImpl implements Parser {
}
ParserException internalError() {
return new ParserException(mark(), "Internal Error");
return exception("Internal Error");
}
ParserException exception() {
return new ParserException(mark());
ParserException expected(String object) {
return new ParserException(mark(), object + " expected");
}
ParserException notImplemented(String feature) {
return new ParserException(mark(), feature + " not yet implemented");
}
ParserException exception(String message) {
return new ParserException(mark(), message);
}
ParserException unexpectedToken() {