diff --git a/doc/changes/changelog.md b/doc/changes/changelog.md index a2c1f91a..486e6797 100644 --- a/doc/changes/changelog.md +++ b/doc/changes/changelog.md @@ -1,5 +1,6 @@ # Changes +* [4.3.0](changes_4.3.0.md) * [4.2.0](changes_4.2.0.md) * [4.1.0](changes_4.1.0.md) * [4.0.0](changes_4.0.0.md) \ No newline at end of file diff --git a/doc/changes/changes_4.3.0.md b/doc/changes/changes_4.3.0.md new file mode 100644 index 00000000..10a27300 --- /dev/null +++ b/doc/changes/changes_4.3.0.md @@ -0,0 +1,7 @@ +# SQL Statement Builder 4.3.0, released 2020-XX-XX + +Code Name: CAST function support + +## Features / Enhancements + +* #94: Added CAST function support \ No newline at end of file diff --git a/pom.xml b/pom.xml index fc5e4bdb..84397082 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 com.exasol sql-statement-builder - 4.2.0 + 4.3.0 Exasol SQL Statement Builder This module provides a Builder for SQL statements that helps creating the correct structure and validates variable parts of the statements. diff --git a/src/main/java/com/exasol/sql/dql/select/Select.java b/src/main/java/com/exasol/sql/dql/select/Select.java index 48fb7f3f..8fa4cf8a 100644 --- a/src/main/java/com/exasol/sql/dql/select/Select.java +++ b/src/main/java/com/exasol/sql/dql/select/Select.java @@ -3,10 +3,15 @@ import java.util.ArrayList; import java.util.List; -import com.exasol.sql.*; +import com.exasol.datatype.type.DataType; +import com.exasol.sql.AbstractFragment; +import com.exasol.sql.ColumnsDefinition; +import com.exasol.sql.DerivedColumn; +import com.exasol.sql.SqlStatement; import com.exasol.sql.expression.*; import com.exasol.sql.expression.function.Function; import com.exasol.sql.expression.function.FunctionName; +import com.exasol.sql.expression.function.exasol.ExasolCastFunction; /** * This class implements an SQL {@link Select} statement. @@ -79,6 +84,32 @@ public Select function(final FunctionName functionName, final String derivedColu return this; } + /** + * Add a cast function. + * + * @param value value to cast + * @param type type to cast the value to + * @return this instance for fluent programming + */ + public Select cast(final ValueExpression value, final DataType type) { + return this.cast(value, type, ""); + } + + /** + * Add a cast function. + * + * @param value value to cast + * @param type type to cast the value to + * @param derivedColumnName name under which you can refer to the derived column + * @return this instance for fluent programming + */ + public Select cast(final ValueExpression value, final DataType type, final String derivedColumnName) { + final Function castFunction = ExasolCastFunction.of(value, type); + final DerivedColumn derivedColumn = new DerivedColumn(this, castFunction, derivedColumnName); + this.derivedColumns.add(derivedColumn); + return this; + } + /** * Add a User Defined Function. * diff --git a/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java b/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java index ec503aea..9a52bbf3 100644 --- a/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java +++ b/src/main/java/com/exasol/sql/expression/ValueExpressionVisitor.java @@ -1,6 +1,7 @@ package com.exasol.sql.expression; import com.exasol.sql.UnnamedPlaceholder; +import com.exasol.sql.expression.function.exasol.ExasolCastFunction; import com.exasol.sql.expression.function.exasol.ExasolFunction; import com.exasol.sql.expression.function.exasol.ExasolUdf; @@ -41,4 +42,6 @@ public interface ValueExpressionVisitor { public void visit(NullLiteral nullLiteral); public void visit(BooleanExpression booleanExpression); + + public void visit(ExasolCastFunction castFunction); } \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/function/exasol/ExasolCastFunction.java b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolCastFunction.java new file mode 100644 index 00000000..94ef4298 --- /dev/null +++ b/src/main/java/com/exasol/sql/expression/function/exasol/ExasolCastFunction.java @@ -0,0 +1,60 @@ +package com.exasol.sql.expression.function.exasol; + +import java.util.List; + +import com.exasol.datatype.type.DataType; +import com.exasol.sql.expression.ValueExpression; +import com.exasol.sql.expression.ValueExpressionVisitor; +import com.exasol.sql.expression.function.AbstractFunction; + +/** + * This class represents the Exasol CAST function. + */ +public class ExasolCastFunction extends AbstractFunction { + private static final String CAST_FUNCTION_NAME = "CAST"; + private final DataType type; + + private ExasolCastFunction(final ValueExpression value, final DataType type) { + super(CAST_FUNCTION_NAME, List.of(value)); + this.type = type; + } + + /** + * Create a new {@link ExasolCastFunction} instance. + * + * @param valueExpression value to cast + * @param type type to cast the value to + * @return new {@link ExasolCastFunction} + */ + public static ExasolCastFunction of(final ValueExpression valueExpression, final DataType type) { + return new ExasolCastFunction(valueExpression, type); + } + + /** + * Get the value to cast. + * + * @return value to cast + */ + public ValueExpression getValue() { + return this.valueExpressions.get(0); + } + + /** + * Get the type to cast the value to. + * + * @return type to cast the value to + */ + public DataType getType() { + return this.type; + } + + @Override + public boolean hasParenthesis() { + return true; + } + + @Override + public void accept(final ValueExpressionVisitor visitor) { + visitor.visit(this); + } +} \ No newline at end of file diff --git a/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java b/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java index 88065686..a9aeb816 100644 --- a/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java +++ b/src/main/java/com/exasol/sql/expression/rendering/ValueExpressionRenderer.java @@ -4,6 +4,7 @@ import com.exasol.sql.UnnamedPlaceholder; import com.exasol.sql.expression.*; import com.exasol.sql.expression.function.Function; +import com.exasol.sql.expression.function.exasol.ExasolCastFunction; import com.exasol.sql.expression.function.exasol.ExasolFunction; import com.exasol.sql.expression.function.exasol.ExasolUdf; import com.exasol.sql.rendering.ColumnsDefinitionRenderer; @@ -55,7 +56,7 @@ public void visit(final FloatLiteral literal) { } @Override - public void visit(BigDecimalLiteral literal) { + public void visit(final BigDecimalLiteral literal) { appendCommaWhenNeeded(literal); append(literal.toString()); setLastVisited(literal); @@ -165,4 +166,16 @@ public void visit(final BooleanExpression booleanExpression) { booleanExpression.accept(expressionRenderer); append(expressionRenderer.render()); } + + @Override + public void visit(final ExasolCastFunction castFunction) { + appendKeyword("CAST"); + startParenthesis(); + castFunction.getValue().accept(this); + appendKeyword(" AS"); + final ColumnsDefinitionRenderer columnsDefinitionRenderer = new ColumnsDefinitionRenderer(this.config); + castFunction.getType().accept(columnsDefinitionRenderer); + append(columnsDefinitionRenderer.render()); + endParenthesis(); + } } \ No newline at end of file diff --git a/src/test/java/com/exasol/sql/expression/function/exasol/ExasolCastFunctionTest.java b/src/test/java/com/exasol/sql/expression/function/exasol/ExasolCastFunctionTest.java new file mode 100644 index 00000000..7c8c5b07 --- /dev/null +++ b/src/test/java/com/exasol/sql/expression/function/exasol/ExasolCastFunctionTest.java @@ -0,0 +1,27 @@ +package com.exasol.sql.expression.function.exasol; + +import static com.exasol.hamcrest.SqlFragmentRenderResultMatcher.rendersTo; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +import com.exasol.datatype.type.Varchar; +import com.exasol.sql.StatementFactory; +import com.exasol.sql.dql.select.Select; +import com.exasol.sql.expression.NullLiteral; + +class ExasolCastFunctionTest { + + @Test + void testRendering() { + final Select select = StatementFactory.getInstance().select().cast(NullLiteral.nullLiteral(), new Varchar(254)); + assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254))")); + } + + @Test + void testRenderingWithName() { + final Select select = StatementFactory.getInstance().select().cast(NullLiteral.nullLiteral(), new Varchar(254), + "TEST"); + assertThat(select, rendersTo("SELECT CAST(NULL AS VARCHAR(254)) TEST")); + } +} \ No newline at end of file