diff --git a/doc/dialects/oracle.md b/doc/dialects/oracle.md index 439427dc3..f48f2245f 100644 --- a/doc/dialects/oracle.md +++ b/doc/dialects/oracle.md @@ -137,6 +137,8 @@ CREATE VIRTUAL SCHEMA The Oracle dialect does not support all capabilities. A complete list can be found in [OracleSqlDialect.getCapabilities()](../../jdbc-adapter/virtualschema-jdbc-adapter/src/main/java/com/exasol/adapter/dialects/oracle/OracleSqlDialect.java). +## Type Mappings and Limitations + Oracle data types are mapped to their equivalents in Exasol. The following exceptions apply: - `NUMBER`, `NUMBER with precision > 36` and `LONG` are casted to `VARCHAR` to prevent a loss of precision. @@ -147,8 +149,12 @@ Oracle data types are mapped to their equivalents in Exasol. The following excep This will cast NUMBER with precision > 36, NUMBER without precision and LONG to DECIMAL(36,20). Keep in mind that this will yield errors if the data in the Oracle database does not fit into the specified DECIMAL type. + - `DATE` is casted to `TIMESTAMP`. This data type is only supported for positive year values, i.e., years > 0001. - `TIMESTAMP WITH [LOCAL] TIME ZONE` is casted to `TIMESTAMP`. - `INTERVAL` is casted to `VARCHAR`. -- `CLOB` are `NCLOB` are treated as `VARCHAR`. +- `CLOB` and `NCLOB` values are supported up to the maximum size of an Exasol [`VARCHAR`](https://docs.exasol.com/sql_references/data_types/datatypedetails.htm#StringDataType). + + By default an error will be thrown if you try to import a value that is larger. If you want to import from tables which contain bigger values, you need to truncate the values. + - `BLOB`, `RAW` and `LONG RAW` are not supported. \ No newline at end of file diff --git a/jdbc-adapter/virtualschema-jdbc-adapter/src/main/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitor.java b/jdbc-adapter/virtualschema-jdbc-adapter/src/main/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitor.java index 62bf42025..07ed13393 100644 --- a/jdbc-adapter/virtualschema-jdbc-adapter/src/main/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitor.java +++ b/jdbc-adapter/virtualschema-jdbc-adapter/src/main/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitor.java @@ -19,7 +19,7 @@ public class OracleSqlGenerationVisitor extends SqlGenerationVisitor { private boolean requiresSelectListAliasesForLimit = false; private static final String TIMESTAMP_FORMAT = "'YYYY-MM-DD HH24:MI:SS.FF3'"; private static final List TYPE_NAMES_REQUIRING_CAST = List.of("TIMESTAMP", "INTERVAL", "BINARY_FLOAT", - "BINARY_DOUBLE", "CLOB", "NCLOB", "ROWID", "UROWID", "BLOB"); + "BINARY_DOUBLE", "ROWID", "UROWID", "BLOB"); private final Set aggregateFunctionsCast = EnumSet.noneOf(AggregateFunction.class); private final Set scalarFunctionsCast = EnumSet.noneOf(ScalarFunction.class); @@ -62,7 +62,7 @@ Set getScalarFunctionsCast() { * SELECT c1, c2, ... FROM ( SELECT LIMIT_SUBSELECT.*, ROWNUM ROWNUM_SUB FROM ( <query-with-aliases> ) * LIMIT_SUBSELECT WHERE ROWNUM <= 30 ) WHERE ROWNUM_SUB > 20 * - * The rownum filter is evaluated before ORDER BY, which is why we need subselects + * The rownum filter is evaluated before ORDER BY, which is why we need sub-selects */ @Override public String visit(final SqlStatementSelect select) throws AdapterException { @@ -261,11 +261,10 @@ private String getProjectionString(final SqlColumn column, final String projecti final AbstractSqlDialect dialect = (AbstractSqlDialect) getDialect(); final String typeName = ColumnAdapterNotes .deserialize(column.getMetadata().getAdapterNotes(), column.getMetadata().getName()).getTypeName(); - if (typeName.startsWith("INTERVAL") || typeName.equals("BINARY_FLOAT") || typeName.equals("BINARY_DOUBLE") - || typeName.equals("CLOB") || typeName.equals("NCLOB")) { + if (typeName.startsWith("INTERVAL") || typeName.equals("BINARY_FLOAT") || typeName.equals("BINARY_DOUBLE")) { return "TO_CHAR(" + projectionString + ")"; } else if (typeName.startsWith("TIMESTAMP") - && ((OracleSqlDialect) dialect).getImportType() == ImportType.JDBC) { + && (((OracleSqlDialect) dialect).getImportType() == ImportType.JDBC)) { return "TO_TIMESTAMP(TO_CHAR(" + projectionString + ", " + TIMESTAMP_FORMAT + "), " + TIMESTAMP_FORMAT + ")"; } else if (typeName.equals("NUMBER")) { diff --git a/jdbc-adapter/virtualschema-jdbc-adapter/src/test/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitorTest.java b/jdbc-adapter/virtualschema-jdbc-adapter/src/test/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitorTest.java index ac05fb5c5..3e5435f7e 100644 --- a/jdbc-adapter/virtualschema-jdbc-adapter/src/test/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitorTest.java +++ b/jdbc-adapter/virtualschema-jdbc-adapter/src/test/java/com/exasol/adapter/dialects/oracle/OracleSqlGenerationVisitorTest.java @@ -122,7 +122,7 @@ void testVisitSqlSelectListSelectStar() throws AdapterException { assertSqlNodeConvertedToAsterisk(selectList, this.visitor); } - @CsvSource({ "NUMBER", "INTERVAL", "BINARY_FLOAT", "BINARY_DOUBLE", "CLOB", "NCLOB" }) + @CsvSource({ "NUMBER", "INTERVAL", "BINARY_FLOAT", "BINARY_DOUBLE" }) @ParameterizedTest void testVisitSqlSelectListSelectStarCastToChar(final String dataType) throws AdapterException { final SqlSelectList selectList = createSqlSelectStarListWithOneColumn(