diff --git a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/IExecutionContext.java b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/IExecutionContext.java index 83782ea1..651f77ac 100644 --- a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/IExecutionContext.java +++ b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/IExecutionContext.java @@ -1,6 +1,5 @@ package se.kuseman.payloadbuilder.api.execution; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.execution.vector.IVectorFactory; import se.kuseman.payloadbuilder.api.expression.IExpressionFactory; @@ -20,5 +19,5 @@ public interface IExecutionContext IExpressionFactory getExpressionFactory(); /** Return value of provided variable name. */ - ValueVector getVariableValue(QualifiedName qname); + ValueVector getVariableValue(String name); } diff --git a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/ValueVector.java b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/ValueVector.java index 7dac5d1b..d69f066d 100644 --- a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/ValueVector.java +++ b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/execution/ValueVector.java @@ -27,6 +27,41 @@ public interface ValueVector /** Get string at provided row. */ default UTF8String getString(int row) { + Type type = type().getType(); + + // Implicit casts + if (type == Type.Boolean) + { + return UTF8String.from(getBoolean(row)); + } + else if (type == Type.DateTime) + { + return UTF8String.from(getDateTime(row)); + } + else if (type == Type.DateTimeOffset) + { + return UTF8String.from(getDateTimeOffset(row)); + } + else if (type == Type.Decimal) + { + return UTF8String.from(getDecimal(row)); + } + else if (type == Type.Double) + { + return UTF8String.from(getDouble(row)); + } + else if (type == Type.Float) + { + return UTF8String.from(getFloat(row)); + } + else if (type == Type.Int) + { + return UTF8String.from(getInt(row)); + } + else if (type == Type.Long) + { + return UTF8String.from(getInt(row)); + } return UTF8String.from(getAny(row)); } diff --git a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/expression/IVariableExpression.java b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/expression/IVariableExpression.java index 285b6588..c427917a 100644 --- a/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/expression/IVariableExpression.java +++ b/payloadbuilder-api/src/main/java/se/kuseman/payloadbuilder/api/expression/IVariableExpression.java @@ -1,12 +1,10 @@ package se.kuseman.payloadbuilder.api.expression; -import se.kuseman.payloadbuilder.api.QualifiedName; - /** Variable expression @var */ public interface IVariableExpression extends IExpression { /** Return name of variable */ - QualifiedName getName(); + String getName(); /** Return true if this is a system variable otherwise false */ boolean isSystem(); diff --git a/payloadbuilder-api/src/test/java/se/kuseman/payloadbuilder/test/ExpressionTestUtils.java b/payloadbuilder-api/src/test/java/se/kuseman/payloadbuilder/test/ExpressionTestUtils.java index d1f29f4e..3401b6e0 100644 --- a/payloadbuilder-api/src/test/java/se/kuseman/payloadbuilder/test/ExpressionTestUtils.java +++ b/payloadbuilder-api/src/test/java/se/kuseman/payloadbuilder/test/ExpressionTestUtils.java @@ -161,7 +161,7 @@ public static IVariableExpression var(String name, Object value) IVariableExpression mock = Mockito.mock(IVariableExpression.class); when(mock.eval(any(IExecutionContext.class))).thenReturn(VectorTestUtils.vv(Type.Any, new Object[] { value })); when(mock.accept(any(), any())).thenCallRealMethod(); - when(mock.getName()).thenReturn(QualifiedName.of(name)); + when(mock.getName()).thenReturn(name); when(mock.getType()).thenReturn(ResolvedType.of(Type.Any)); return mock; } diff --git a/payloadbuilder-catalog/src/main/java/se/kuseman/payloadbuilder/catalog/es/ElasticsearchMetaUtils.java b/payloadbuilder-catalog/src/main/java/se/kuseman/payloadbuilder/catalog/es/ElasticsearchMetaUtils.java index 374d64e6..ce48c4f1 100644 --- a/payloadbuilder-catalog/src/main/java/se/kuseman/payloadbuilder/catalog/es/ElasticsearchMetaUtils.java +++ b/payloadbuilder-catalog/src/main/java/se/kuseman/payloadbuilder/catalog/es/ElasticsearchMetaUtils.java @@ -196,6 +196,13 @@ private static void appendDataStreamMappings(IQuerySession session, String catal } catch (Exception e) { + // Skip logging error about alias + if (e.getMessage() + .toLowerCase() + .contains("specify the corresponding concrete indices instead")) + { + return; + } // Swallow this since all ES versions doesn't have datastreams LOGGER.error("Error fetching data stream mappings", e); } diff --git a/payloadbuilder-catalog/src/test/java/se/kuseman/payloadbuilder/catalog/es/ElasticQueryBuilderTest.java b/payloadbuilder-catalog/src/test/java/se/kuseman/payloadbuilder/catalog/es/ElasticQueryBuilderTest.java index 7908b595..05e8036d 100644 --- a/payloadbuilder-catalog/src/test/java/se/kuseman/payloadbuilder/catalog/es/ElasticQueryBuilderTest.java +++ b/payloadbuilder-catalog/src/test/java/se/kuseman/payloadbuilder/catalog/es/ElasticQueryBuilderTest.java @@ -360,8 +360,8 @@ public void test_collect() throws JsonMappingException, JsonProcessingException StringBuilder filter = new StringBuilder(); StringBuilder filterNot = new StringBuilder(); - context.setVariable(QualifiedName.of("var"), ValueVector.literalString("world", 1)); - context.setVariable(QualifiedName.of("int"), ValueVector.literalInt(1, 1)); + context.setVariable("var", ValueVector.literalString("world", 1)); + context.setVariable("int", ValueVector.literalInt(1, 1)); for (IPropertyPredicate pp : predicatesResult) { diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/CsvOutputWriter.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/CsvOutputWriter.java index bcabfd7b..fca23d5f 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/CsvOutputWriter.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/CsvOutputWriter.java @@ -8,8 +8,10 @@ import java.io.StringReader; import java.io.StringWriter; import java.io.Writer; +import java.util.Arrays; import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; import se.kuseman.payloadbuilder.api.OutputWriter; @@ -124,14 +126,18 @@ public void initResult(String[] columns) return; } - startRow(); - - for (String column : columns) + if (Arrays.stream(columns) + .anyMatch(StringUtils::isNotBlank)) { - writeValue(column); - } + startRow(); + + for (String column : columns) + { + writeValue(column); + } - endRow(); + endRow(); + } } @Override diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/JsonOutputWriter.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/JsonOutputWriter.java index ad279ea3..8af61d59 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/JsonOutputWriter.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/JsonOutputWriter.java @@ -108,7 +108,8 @@ public void flush() @Override public void close() { - if (settings.allResultSetsAsOneArray) + if (settings.allResultSetsAsOneArray + && !firstResultSet) { endArray(); } @@ -132,7 +133,8 @@ public void close() @Override public void endResult() { - if (settings.resultSetsAsArrays) + if (settings.resultSetsAsArrays + && !firstResultSet) { endArray(); } diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/QueryResultImpl.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/QueryResultImpl.java index c113ff0b..1dbca8a2 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/QueryResultImpl.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/QueryResultImpl.java @@ -227,37 +227,42 @@ private void writeInternal(IPhysicalPlan plan, OutputWriter writer) try { Schema schema = plan.getSchema(); - if (writer != null) - { - // Asterisk schema, then we cannot init the result with it since - // it's not the actual one that will come - if (SchemaUtils.isAsterisk(schema)) - { - writer.initResult(ArrayUtils.EMPTY_STRING_ARRAY); - } - else - { - writer.initResult(schema.getColumns() - .stream() - .filter(c -> !(c instanceof CoreColumn) - || !((CoreColumn) c).isInternal()) - .map(c -> - { - String outputName = c.getName(); - if (c instanceof CoreColumn) - { - outputName = ((CoreColumn) c).getOutputName(); - } - return outputName; - }) - .toArray(String[]::new)); - } - } statementContext.setOuterTupleVector(null); - + boolean initCompleted = false; iterator = plan.execute(context); while (iterator.hasNext()) { + if (!initCompleted) + { + if (writer != null) + { + // Asterisk schema, then we cannot init the result with it since + // it's not the actual one that will come + if (SchemaUtils.isAsterisk(schema)) + { + writer.initResult(ArrayUtils.EMPTY_STRING_ARRAY); + } + else + { + writer.initResult(schema.getColumns() + .stream() + .filter(c -> !(c instanceof CoreColumn) + || !((CoreColumn) c).isInternal()) + .map(c -> + { + String outputName = c.getName(); + if (c instanceof CoreColumn) + { + outputName = ((CoreColumn) c).getOutputName(); + } + return outputName; + }) + .toArray(String[]::new)); + } + } + initCompleted = true; + } + if (session.abortQuery()) { break; diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/catalog/system/SystemCatalog.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/catalog/system/SystemCatalog.java index 670b4561..4985eef9 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/catalog/system/SystemCatalog.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/catalog/system/SystemCatalog.java @@ -394,12 +394,12 @@ else if ("variables".equalsIgnoreCase(type)) { vector = ctx -> { - final List> variables = new ArrayList<>(((ExecutionContext) ctx).getVariables() + final List> variables = new ArrayList<>(((ExecutionContext) ctx).getVariables() .entrySet()); return new ObjectTupleVector(data.getSchema() .get(), variables.size(), (row, col) -> { - Entry e = variables.get(row); + Entry e = variables.get(row); if (col == 0) { return e.getKey(); diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/ExecutionContext.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/ExecutionContext.java index 55ef1a80..ef944dbb 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/ExecutionContext.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/ExecutionContext.java @@ -7,7 +7,6 @@ import java.util.HashMap; import java.util.Map; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.execution.IExecutionContext; import se.kuseman.payloadbuilder.api.execution.ValueVector; import se.kuseman.payloadbuilder.api.execution.vector.IVectorFactory; @@ -30,7 +29,7 @@ public class ExecutionContext implements IExecutionContext private final ExpressionFactory expressionFactory; /** Variables in context */ - private Map variables; + private Map variables; public ExecutionContext(QuerySession session) { @@ -77,13 +76,13 @@ public BufferAllocator getBufferAllocator() } /** Get variables map */ - public Map getVariables() + public Map getVariables() { return defaultIfNull(variables, emptyMap()); } /** Set variable to context */ - public void setVariable(QualifiedName name, ValueVector value) + public void setVariable(String name, ValueVector value) { if (variables == null) { @@ -94,7 +93,7 @@ public void setVariable(QualifiedName name, ValueVector value) /** Get variable from context */ @Override - public ValueVector getVariableValue(QualifiedName name) + public ValueVector getVariableValue(String name) { return variables != null ? variables.get(name) : null; diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/QuerySession.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/QuerySession.java index e6000ee3..a30745c0 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/QuerySession.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/QuerySession.java @@ -55,15 +55,15 @@ public class QuerySession implements IQuerySession { /* System properties */ /** Enable to print logical and physical plans to session print writer */ - public static final QualifiedName PRINT_PLAN = QualifiedName.of("printplan"); + public static final String PRINT_PLAN = "printplan"; /** Enable to print all logical plans for each optimisation rule. */ - public static final QualifiedName DEBUG_PLAN = QualifiedName.of("debugplan"); + public static final String DEBUG_PLAN = "debugplan"; /** Force a nested loop where default would have been a hash match */ - public static final QualifiedName FORCE_NESTED_LOOP = QualifiedName.of("force_nested_loop"); + public static final String FORCE_NESTED_LOOP = "force_nested_loop"; /** Force no inner cache for non correlated nested loops */ - public static final QualifiedName FORCE_NO_INNER_CACHE = QualifiedName.of("force_no_inner_cache"); + public static final String FORCE_NO_INNER_CACHE = "force_no_inner_cache"; /* End system properties */ /* Compile fields */ @@ -73,11 +73,11 @@ public class QuerySession implements IQuerySession /* Execution fields */ /** Variable values for {@link VariableExpression}'s */ - private final Map variables; + private final Map variables; /** Catalog properties by catalog alias */ private Map> catalogProperties; /** System properties */ - private Map systemProperties; + private Map systemProperties; private Writer printWriter; private ExceptionHandler exceptionHandler; private BooleanSupplier abortSupplier; @@ -99,8 +99,8 @@ public QuerySession(CatalogRegistry catalogRegistry, Map variabl this.catalogRegistry = requireNonNull(catalogRegistry, "catalogRegistry"); this.variables = requireNonNull(variables, "variables").entrySet() .stream() - .collect(toMap(k -> QualifiedName.of(k.getKey() - .toLowerCase()), v -> ValueVector.literalAny(v.getValue()))); + .collect(toMap(e -> e.getKey() + .toLowerCase(), v -> ValueVector.literalAny(v.getValue()))); } @Override @@ -299,7 +299,7 @@ public CatalogRegistry getCatalogRegistry() } /** Return variables map */ - Map getVariables() + Map getVariables() { return variables; } @@ -414,7 +414,7 @@ public ValueVector getCatalogProperty(String alias, String key) } /** Set system property */ - public void setSystemProperty(QualifiedName name, ValueVector value) + public void setSystemProperty(String name, ValueVector value) { requireNonNull(value); if (systemProperties == null) @@ -425,7 +425,7 @@ public void setSystemProperty(QualifiedName name, ValueVector value) } /** Get system property */ - public ValueVector getSystemProperty(QualifiedName name) + public ValueVector getSystemProperty(String name) { if (systemProperties == null) { diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/vector/MutableObjectVector.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/vector/MutableObjectVector.java index 6859e5d4..8d6d4ef0 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/vector/MutableObjectVector.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/execution/vector/MutableObjectVector.java @@ -33,6 +33,10 @@ public void setNull(int row) @Override public boolean isNull(int row) { + if (buffer == null) + { + return true; + } return buffer[row] == null; } diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/ARewriteExpressionVisitor.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/ARewriteExpressionVisitor.java index 201a8bd5..72aa94c5 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/ARewriteExpressionVisitor.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/ARewriteExpressionVisitor.java @@ -4,7 +4,6 @@ import java.util.List; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.expression.IArithmeticBinaryExpression; import se.kuseman.payloadbuilder.api.expression.IArithmeticUnaryExpression; import se.kuseman.payloadbuilder.api.expression.IAtTimeZoneExpression; @@ -68,20 +67,20 @@ public IExpression visit(AsteriskExpression expression, C context) { // Asterisk has no state return expression; - }; + } @Override public IExpression visit(UnresolvedColumnExpression expression, C context) { // Column doesn't have any child expressions return expression; - }; + } @Override public IExpression visit(AssignmentExpression expression, C context) { return new AssignmentExpression(expression.getExpression() - .accept(this, context), QualifiedName.of(expression.getVariable())); + .accept(this, context), expression.getVariable()); } @Override @@ -185,37 +184,37 @@ public IExpression visit(ILiteralObjectExpression expression, C context) public IExpression visit(ILogicalBinaryExpression expression, C context) { return new LogicalBinaryExpression(expression.getLogicalType(), visit(expression.getLeft(), context), visit(expression.getRight(), context)); - }; + } @Override public IExpression visit(ILogicalNotExpression expression, C context) { return new LogicalNotExpression(visit(expression.getExpression(), context)); - }; + } @Override public IExpression visit(INullPredicateExpression expression, C context) { return new NullPredicateExpression(visit(expression.getExpression(), context), expression.isNot()); - }; + } @Override public IExpression visit(IInExpression expression, C context) { return new InExpression(visit(expression.getExpression(), context), visit(expression.getArguments(), context), expression.isNot()); - }; + } @Override public IExpression visit(ILikeExpression expression, C context) { return new LikeExpression(visit(expression.getExpression(), context), visit(expression.getPatternExpression(), context), expression.isNot(), null); - }; + } @Override public IExpression visit(IArithmeticUnaryExpression expression, C context) { return new ArithmeticUnaryExpression(expression.getArithmeticType(), visit(expression.getExpression(), context)); - }; + } @Override public IExpression visit(ICaseExpression expression, C context) @@ -226,7 +225,7 @@ public IExpression visit(ICaseExpression expression, C context) .collect(toList()); return new CaseExpression(whenClauses, visit(expression.getElseExpression(), context)); - }; + } @Override public IExpression visit(IDereferenceExpression expression, C context) @@ -236,25 +235,25 @@ public IExpression visit(IDereferenceExpression expression, C context) return new DereferenceExpression(visit(expression.getExpression(), context), expression.getRight(), ((DereferenceExpression) expression).getOrdinal(), expression.getType()); } return new DereferenceExpression(visit(expression.getExpression(), context), expression.getRight()); - }; + } @Override public IExpression visit(INamedExpression expression, C context) { return new NamedExpression(expression.getName(), visit(expression.getExpression(), context)); - }; + } @Override public IExpression visit(INestedExpression expression, C context) { return new NestedExpression(visit(expression.getExpression(), context)); - }; + } @Override public IExpression visit(ISubscriptExpression expression, C context) { return new SubscriptExpression(visit(expression.getValue(), context), visit(expression.getSubscript(), context)); - }; + } @Override public IExpression visit(IVariableExpression expression, C context) diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/AssignmentExpression.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/AssignmentExpression.java index ca9a422e..8765e6a0 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/AssignmentExpression.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/AssignmentExpression.java @@ -5,7 +5,6 @@ import java.util.List; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.catalog.ResolvedType; import se.kuseman.payloadbuilder.api.catalog.Schema; import se.kuseman.payloadbuilder.api.execution.IExecutionContext; @@ -22,12 +21,12 @@ public class AssignmentExpression implements IExpression { private final IExpression expression; - private final QualifiedName variable; + private final String variable; - public AssignmentExpression(IExpression expression, QualifiedName qname) + public AssignmentExpression(IExpression expression, String variable) { this.expression = requireNonNull(expression, "expression"); - this.variable = requireNonNull(qname, "qname").toLowerCase(); + this.variable = requireNonNull(variable, "variable").toLowerCase(); } public IExpression getExpression() @@ -35,7 +34,7 @@ public IExpression getExpression() return expression; } - public QualifiedName getVariable() + public String getVariable() { return variable; } diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/VariableExpression.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/VariableExpression.java index b03407c7..d7e3c7c9 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/VariableExpression.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/expression/VariableExpression.java @@ -2,7 +2,6 @@ import static java.util.Objects.requireNonNull; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.catalog.Column.Type; import se.kuseman.payloadbuilder.api.catalog.ResolvedType; import se.kuseman.payloadbuilder.api.execution.IExecutionContext; @@ -17,25 +16,25 @@ /** A variable (@var) */ public class VariableExpression implements IVariableExpression, HasAlias { - private static final QualifiedName ROWCOUNT = QualifiedName.of("rowcount"); - private static final QualifiedName VERSION = QualifiedName.of("version"); + private static final String ROWCOUNT = "rowcount"; + private static final String VERSION = "version"; - private final QualifiedName name; + private final String name; private final boolean system; - public VariableExpression(QualifiedName qname) + public VariableExpression(String name) { - this(qname, false); + this(name, false); } - public VariableExpression(QualifiedName qname, boolean system) + public VariableExpression(String name, boolean system) { - this.name = requireNonNull(qname, "qname").toLowerCase(); + this.name = requireNonNull(name, "name").toLowerCase(); this.system = system; } @Override - public QualifiedName getName() + public String getName() { return name; } diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/parser/QueryParser.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/parser/QueryParser.java index c2c41c08..7b0fbdb2 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/parser/QueryParser.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/parser/QueryParser.java @@ -328,7 +328,7 @@ public Object visitSetStatement(SetStatementContext ctx) { boolean systemProperty = ctx.AT() .size() == 2; - return new SetStatement(getQualifiedName(ctx.qname()).toLowerCase(), getExpression(ctx.expression()), systemProperty); + return new SetStatement(getIdentifier(ctx.identifier()).toLowerCase(), getExpression(ctx.expression()), systemProperty); } @Override @@ -512,8 +512,8 @@ public Object visitSelectItem(SelectItemContext ctx) throw new ParseException("Cannot assign to system variables", ctx); } - return new AssignmentExpression(expression, getQualifiedName(ctx.variable() - .qname()).toLowerCase()); + return new AssignmentExpression(expression, getIdentifier(ctx.variable() + .identifier()).toLowerCase()); } if (ctx.ASTERISK() != null) @@ -651,10 +651,10 @@ else if (ctx.variable() != null) throw new ParseException("Variable scans cannot be a system variable", ctx.variable()); } - QualifiedName qname = getQualifiedName(ctx.variable() - .qname()); - IExpression expression = new VariableExpression(qname); - TableSourceReference tableSource = new TableSourceReference(tableSourceCounter++, TableSourceReference.Type.EXPRESSION, "", qname, alias); + String variable = getIdentifier(ctx.variable() + .identifier()); + IExpression expression = new VariableExpression(variable); + TableSourceReference tableSource = new TableSourceReference(tableSourceCounter++, TableSourceReference.Type.EXPRESSION, "", QualifiedName.of(variable), alias); return new ExpressionScan(tableSource, Schema.EMPTY, expression, Location.from(ctx.variable())); } else if (ctx.expression() != null) @@ -734,8 +734,8 @@ public Object visitFunctionCallExpression(FunctionCallExpressionContext ctx) @Override public Object visitVariableExpression(VariableExpressionContext ctx) { - IExpression result = new VariableExpression(getQualifiedName(ctx.variable() - .qname()), ctx.variable().system != null); + IExpression result = new VariableExpression(getIdentifier(ctx.variable() + .identifier()), ctx.variable().system != null); if (!ctx.indirection() .isEmpty()) diff --git a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/statement/SetStatement.java b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/statement/SetStatement.java index de79b372..6fa087d2 100644 --- a/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/statement/SetStatement.java +++ b/payloadbuilder-core/src/main/java/se/kuseman/payloadbuilder/core/statement/SetStatement.java @@ -2,7 +2,6 @@ import static java.util.Objects.requireNonNull; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.execution.IExecutionContext; import se.kuseman.payloadbuilder.api.execution.TupleVector; import se.kuseman.payloadbuilder.api.execution.ValueVector; @@ -13,11 +12,11 @@ /** Set statement */ public class SetStatement extends Statement { - private final QualifiedName name; + private final String name; private final IExpression expression; private final boolean systemProperty; - public SetStatement(QualifiedName name, IExpression expression, boolean systemProperty) + public SetStatement(String name, IExpression expression, boolean systemProperty) { this.name = requireNonNull(name, "name"); this.expression = requireNonNull(expression, "expression"); @@ -29,7 +28,7 @@ public boolean isSystemProperty() return systemProperty; } - public QualifiedName getName() + public String getName() { return name; } diff --git a/payloadbuilder-core/src/main/resources/antlr4/se/kuseman/payloadbuilder/core/parser/PayloadBuilderQueryParser.g4 b/payloadbuilder-core/src/main/resources/antlr4/se/kuseman/payloadbuilder/core/parser/PayloadBuilderQueryParser.g4 index 15ce4c7f..92ec4e93 100644 --- a/payloadbuilder-core/src/main/resources/antlr4/se/kuseman/payloadbuilder/core/parser/PayloadBuilderQueryParser.g4 +++ b/payloadbuilder-core/src/main/resources/antlr4/se/kuseman/payloadbuilder/core/parser/PayloadBuilderQueryParser.g4 @@ -35,7 +35,7 @@ miscStatement ; setStatement - : SET AT? AT? qname EQUALS expression + : SET AT? AT? identifier EQUALS expression ; useStatement @@ -321,7 +321,7 @@ templateStringAtom ; variable - : AT (system=AT)? qname + : AT (system=AT)? identifier ; compareOperator diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/CsvOutputWriterTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/CsvOutputWriterTest.java index 3b1bbfdd..16e27a25 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/CsvOutputWriterTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/CsvOutputWriterTest.java @@ -159,6 +159,22 @@ public void test() .toString()); } + @Test + public void test_empty_columns_dont_yield_initial_new_line() + { + CsvSettings settings = new CsvSettings(); + settings.setRowSeparator(System.lineSeparator()); + Pair p = writer(settings); + p.getValue() + .initResult(new String[] { "" }); + p.getValue() + .endResult(); + p.getValue() + .close(); + assertEquals("", p.getKey() + .toString()); + } + private Pair writer(CsvSettings settings) { StringWriter sw = new StringWriter(); diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/JsonOutputWriterTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/JsonOutputWriterTest.java index 1ac04e66..6def4f48 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/JsonOutputWriterTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/JsonOutputWriterTest.java @@ -42,6 +42,20 @@ public void test_outputstream_escape() } + @Test + public void test_allResultSetsAsOneArray_no_rows() + { + JsonSettings settings = new JsonSettings(); + settings.setAllResultSetsAsOneArray(true); + + Pair p = writer(settings); + p.getValue() + .close(); + + assertEquals("", p.getKey() + .toString()); + } + @Test public void test_allResultSetsAsOneArray() { diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/RangeFunctionTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/RangeFunctionTest.java index 42479294..f61048f4 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/RangeFunctionTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/RangeFunctionTest.java @@ -52,9 +52,9 @@ public void test() public void test_batch_size() { Schema schema = Schema.of(Column.of("Value", ResolvedType.of(Type.Int))); - context.setVariable(QualifiedName.of("batch"), ValueVector.literalInt(3, 1)); + context.setVariable("batch", ValueVector.literalInt(3, 1)); TupleIterator it = f.execute(context, "", Optional.of(schema), asList(intLit(1), intLit(11)), - new DatasourceOptions(asList(new Option(QualifiedName.of("batch_size"), new VariableExpression(QualifiedName.of("batch")))))); + new DatasourceOptions(asList(new Option(QualifiedName.of("batch_size"), new VariableExpression("batch"))))); int count = 0; while (it.hasNext()) diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/ToTableFunctionTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/ToTableFunctionTest.java index 97cebdf2..61fab549 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/ToTableFunctionTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/catalog/system/ToTableFunctionTest.java @@ -9,7 +9,6 @@ import org.junit.Test; -import se.kuseman.payloadbuilder.api.QualifiedName; import se.kuseman.payloadbuilder.api.catalog.Column; import se.kuseman.payloadbuilder.api.catalog.Column.Type; import se.kuseman.payloadbuilder.api.catalog.ResolvedType; @@ -34,7 +33,7 @@ public void test() { // "select * from open_map_collection((@col).attribute1.buckets)"; //@formatter:off - context.setVariable(QualifiedName.of("col"), + context.setVariable("col", ValueVector.literalAny( ofEntries( entry("attribute1", @@ -47,7 +46,7 @@ public void test() //@formatter:off IExpression arg = new DereferenceExpression( new DereferenceExpression( - new VariableExpression(QualifiedName.of("col")), + new VariableExpression("col"), "attribute1", -1, ResolvedType.of(Type.Any)), diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/expression/AExpressionTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/expression/AExpressionTest.java index 0aa35af6..629c4365 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/expression/AExpressionTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/expression/AExpressionTest.java @@ -413,8 +413,8 @@ protected void assertExpression(ExecutionContext context, Object expected, java. { for (Entry e : variables.entrySet()) { - context.setVariable(QualifiedName.of(e.getKey() - .toLowerCase()), ValueVector.literalAny(e.getValue())); + context.setVariable(e.getKey() + .toLowerCase(), ValueVector.literalAny(e.getValue())); } } diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/logicalplan/optimization/ColumnResolverTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/logicalplan/optimization/ColumnResolverTest.java index 02a2bcb6..49d80316 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/logicalplan/optimization/ColumnResolverTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/logicalplan/optimization/ColumnResolverTest.java @@ -254,7 +254,7 @@ public void test_expression_scan_table_variable_with_provided_schema() //@formatter:on //@formatter:off - context.setVariable(QualifiedName.of("tbl"), ValueVector.literalTable(TupleVector.of(Schema.of( + context.setVariable("tbl", ValueVector.literalTable(TupleVector.of(Schema.of( Column.of("col1", Type.Int), Column.of("col2", Type.Boolean) ), List.of( @@ -270,7 +270,7 @@ public void test_expression_scan_table_variable_with_provided_schema() Schema expectedSchema = Schema.of(col("col1", ResolvedType.of(Type.Int), expectedTable), col("col2", ResolvedType.of(Type.Boolean), expectedTable)); - ILogicalPlan expected = new ExpressionScan(expectedTable, expectedSchema, new VariableExpression(QualifiedName.of("tbl")), null); + ILogicalPlan expected = new ExpressionScan(expectedTable, expectedSchema, new VariableExpression("tbl"), null); //@formatter:off Assertions.assertThat(actual.getSchema()) diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/parser/QueryParserTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/parser/QueryParserTest.java index d65df6bf..aa237a90 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/parser/QueryParserTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/parser/QueryParserTest.java @@ -170,7 +170,7 @@ public void test_backwards_compability_functions() public void test_set() { assertQuery("set @var = 10"); - assertQuery("set @@system.prop = false"); + assertQuery("set @@system_prop = false"); } @Test @@ -221,12 +221,12 @@ public void test_not() @Test public void test_cast() { - assertExpression("cast(@var AS array)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.array(Type.Any))); - assertExpression("cast(@var AS int)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.of(Type.Int))); - assertExpression("cast(@var AS long)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.of(Type.Long))); - assertExpression("cast(@var AS float)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.of(Type.Float))); - assertExpression("cast(@var AS double)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.of(Type.Double))); - assertExpression("cast(@var AS boolean)", new CastExpression(new VariableExpression(QualifiedName.of("var")), ResolvedType.of(Type.Boolean))); + assertExpression("cast(@var AS array)", new CastExpression(new VariableExpression("var"), ResolvedType.array(Type.Any))); + assertExpression("cast(@var AS int)", new CastExpression(new VariableExpression("var"), ResolvedType.of(Type.Int))); + assertExpression("cast(@var AS long)", new CastExpression(new VariableExpression("var"), ResolvedType.of(Type.Long))); + assertExpression("cast(@var AS float)", new CastExpression(new VariableExpression("var"), ResolvedType.of(Type.Float))); + assertExpression("cast(@var AS double)", new CastExpression(new VariableExpression("var"), ResolvedType.of(Type.Double))); + assertExpression("cast(@var AS boolean)", new CastExpression(new VariableExpression("var"), ResolvedType.of(Type.Boolean))); // Test folding assertExpression("cast(null AS int)", new LiteralNullExpression(ResolvedType.of(Type.Int))); @@ -397,8 +397,7 @@ public void test_dereference() assertExpression("a.b.c", new UnresolvedColumnExpression(QualifiedName.of("a", "b", "c"), -1, null)); assertExpression("@list.filter(x -> x.value)", new UnresolvedFunctionCallExpression("", "filter", null, - asList(new VariableExpression(QualifiedName.of("list")), new LambdaExpression(asList("x"), new UnresolvedColumnExpression(QualifiedName.of("x", "value"), 0, null), new int[] { 0 })), - null)); + asList(new VariableExpression("list"), new LambdaExpression(asList("x"), new UnresolvedColumnExpression(QualifiedName.of("x", "value"), 0, null), new int[] { 0 })), null)); assertExpression("a.hash()", new UnresolvedFunctionCallExpression("", "hash", null, asList(new UnresolvedColumnExpression(QualifiedName.of("a"), -1, null)), null)); assertExpression("a.hash() + hash(a)", new ArithmeticBinaryExpression(IArithmeticBinaryExpression.Type.ADD, diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/planning/QueryPlannerTest.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/planning/QueryPlannerTest.java index 3af4741f..4d4f78d2 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/planning/QueryPlannerTest.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/planning/QueryPlannerTest.java @@ -2449,7 +2449,7 @@ public void test_predicate_pushdown() assertEquals(asList( Triple.of(QualifiedName.of("col5"), IPredicate.Type.FUNCTION_CALL, asList( new FunctionCallExpression(Catalog.SYSTEM_CATALOG_ALIAS, SystemCatalog.get().getScalarFunction("contains"), null, asList( - new VariableExpression(QualifiedName.of("var")), + new VariableExpression("var"), cre("col5", table))))), Triple.of(null, IPredicate.Type.FUNCTION_CALL, asList(new FunctionCallExpression("t", someFunc, null, asList()))), Triple.of(QualifiedName.of("col"), IPredicate.Type.COMPARISION, asList(intLit(10))) diff --git a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/test/TestHarnessRunner.java b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/test/TestHarnessRunner.java index ee07b3c8..78c11ef0 100644 --- a/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/test/TestHarnessRunner.java +++ b/payloadbuilder-core/src/test/java/se/kuseman/payloadbuilder/core/test/TestHarnessRunner.java @@ -459,7 +459,7 @@ public TupleIterator execute(IExecutionContext context, IDatasourceOptions optio ValueVector option = options.getOption(optionName, context); if (option != null) { - ((ExecutionContext) context).setVariable(optionName, option); + ((ExecutionContext) context).setVariable(optionName.getFirst(), option); } ObjectTupleVector tupleVector = new ObjectTupleVector(data.getSchema()