Skip to content

Commit

Permalink
#120: Supported using the push down request to specify the datatypes…
Browse files Browse the repository at this point in the history
… of result set.
  • Loading branch information
ckunki committed Sep 12, 2022
1 parent 0ead426 commit 9b3f0f2
Show file tree
Hide file tree
Showing 19 changed files with 146 additions and 59 deletions.
11 changes: 11 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
dependencies.md linguist-generated=true
doc/changes/changelog.md linguist-generated=true
pk_generated_parent.pom linguist-generated=true
.github/workflows/broken_links_checker.yml linguist-generated=true
.github/workflows/ci-build-next-java.yml linguist-generated=true
.github/workflows/ci-build.yml linguist-generated=true
.github/workflows/dependencies_check.yml linguist-generated=true
.github/workflows/release_droid_prepare_original_checksum.yml linguist-generated=true
.github/workflows/release_droid_print_quick_checksum.yml linguist-generated=true
.github/workflows/release_droid_release_on_maven_central.yml linguist-generated=true
.github/workflows/release_droid_upload_github_release_assets.yml linguist-generated=true
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ pom.xml.versionsBackup
*.orig
*.old
*.md.html
*.flattened-pom.xml
*.flattened-pom.xml
/.apt_generated/
/.apt_generated_tests/
1 change: 1 addition & 0 deletions doc/changes/changelog.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions doc/changes/changes_10.0.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Virtual Schema Common JDBC 10.0.0, released 2022-??-??

Code name: Read Expected Datatypes From Request

## Summary

Starting with major version 8 Exasol database uses the capabilities reported by each virtual schema to provide select list data types for each push down request. Based on this information the JDBC virtual schemas no longer need to infer the data types of the result set by inspecting its values. Instead the JDBC virtual schemas can now use the information provided by the database.

## Features

* #120: Supported using the push down request to specify the datatypes of result set.

## Dependency Updates

### Compile Dependency Updates

* Updated `com.exasol:virtual-schema-common-java:15.3.2` to `16.0.0`
2 changes: 1 addition & 1 deletion pk_generated_parent.pom

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 4 additions & 5 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.exasol</groupId>
<artifactId>virtual-schema-common-jdbc</artifactId>
<version>9.0.5</version>
<version>10.0.0</version>
<name>Virtual Schema Common JDBC</name>
<description>Common module for JDBC-based data access from Virtual Schemas.</description>
<url>https://github.com/exasol/virtual-schema-common-jdbc/</url>
Expand All @@ -28,7 +27,7 @@
<dependency>
<groupId>com.exasol</groupId>
<artifactId>virtual-schema-common-java</artifactId>
<version>15.3.2</version>
<version>16.0.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
Expand Down Expand Up @@ -144,7 +143,7 @@
<parent>
<artifactId>virtual-schema-common-jdbc-generated-parent</artifactId>
<groupId>com.exasol</groupId>
<version>9.0.5</version>
<version>10.0.0</version>
<relativePath>pk_generated_parent.pom</relativePath>
</parent>
</project>
19 changes: 10 additions & 9 deletions src/main/java/com/exasol/adapter/dialects/AbstractSqlDialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.exasol.adapter.dialects.rewriting.SqlGenerationVisitor;
import com.exasol.adapter.jdbc.ConnectionFactory;
import com.exasol.adapter.jdbc.RemoteMetadataReader;
import com.exasol.adapter.metadata.DataType;
import com.exasol.adapter.metadata.SchemaMetadata;
import com.exasol.adapter.sql.*;
import com.exasol.errorreporting.ExaError;
Expand Down Expand Up @@ -134,9 +135,9 @@ public Map<ScalarFunction, String> getPrefixFunctionAliases() {
}

@Override
public String rewriteQuery(final SqlStatement statement, final ExaMetadata exaMetadata)
throws AdapterException, SQLException {
return createQueryRewriter().rewrite(statement, exaMetadata, this.properties);
public String rewriteQuery(final SqlStatement statement, final List<DataType> selectListDataTypes,
final ExaMetadata exaMetadata) throws AdapterException, SQLException {
return createQueryRewriter().rewrite(statement, selectListDataTypes, exaMetadata, this.properties);
}

@Override
Expand All @@ -151,7 +152,7 @@ public SchemaMetadata readSchemaMetadata(final List<String> tables) {

/**
* Quote a string literal with single quotes.
*
*
* @param value string literal
* @return quoted string
*/
Expand All @@ -165,7 +166,7 @@ public String quoteLiteralStringWithSingleQuote(final String value) {

/**
* Quote an identifier with double quotes.
*
*
* @param identifier identifier to quote
* @return quoted identifier
*/
Expand All @@ -185,7 +186,7 @@ public void validateProperties() throws PropertyValidationException {

/**
* Validate that all given properties are supported by the dialect.
*
*
* @throws PropertyValidationException if validation fails
*/
protected void validateSupportedPropertiesList() throws PropertyValidationException {
Expand All @@ -199,7 +200,7 @@ protected void validateSupportedPropertiesList() throws PropertyValidationExcept

/**
* Create an exception for an unsupported property.
*
*
* @param unsupportedElement unsupported property name.
* @param property unsupported property name
* @return exception
Expand Down Expand Up @@ -236,7 +237,7 @@ private void validateSchemaNameProperty() throws PropertyValidationException {

/**
* Validate the input of a boolean property.
*
*
* @param property property name
* @throws PropertyValidationException if validation fails
*/
Expand Down Expand Up @@ -339,7 +340,7 @@ protected void checkImportPropertyConsistency(final String importFromProperty, f

/**
* Validate the value of the castNumberToDecimalProperty.
*
*
* @param castNumberToDecimalProperty property name
* @throws PropertyValidationException if validation fails
*/
Expand Down
13 changes: 8 additions & 5 deletions src/main/java/com/exasol/adapter/dialects/QueryRewriter.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.exasol.adapter.dialects;

import java.sql.SQLException;
import java.util.List;

import com.exasol.ExaMetadata;
import com.exasol.adapter.AdapterException;
import com.exasol.adapter.AdapterProperties;
import com.exasol.adapter.metadata.DataType;
import com.exasol.adapter.sql.SqlStatement;

/**
Expand All @@ -28,13 +30,14 @@ public interface QueryRewriter {
/**
* Set the original push-down statement.
*
* @param statement SQL statement that represents the original push-down query
* @param properties user-defined adapter properties
* @param exaMetadata Exasol metadata
* @param statement SQL statement that represents the original push-down query
* @param selectListDataTypes expected data types of result set
* @param properties user-defined adapter properties
* @param exaMetadata Exasol metadata
* @return rewritten query
* @throws AdapterException if rewriting fails
* @throws SQLException if any SQL commands executed on the remote data source failed during rewriting
*/
public String rewrite(final SqlStatement statement, final ExaMetadata exaMetadata,
final AdapterProperties properties) throws AdapterException, SQLException;
public String rewrite(final SqlStatement statement, List<DataType> selectListDataTypes,
final ExaMetadata exaMetadata, final AdapterProperties properties) throws AdapterException, SQLException;
}
9 changes: 6 additions & 3 deletions src/main/java/com/exasol/adapter/dialects/SqlDialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.exasol.adapter.AdapterException;
import com.exasol.adapter.capabilities.Capabilities;
import com.exasol.adapter.dialects.rewriting.SqlGenerationContext;
import com.exasol.adapter.metadata.DataType;
import com.exasol.adapter.metadata.SchemaMetadata;
import com.exasol.adapter.sql.*;

Expand Down Expand Up @@ -239,11 +240,13 @@ public enum NullSorting {
* Rewrite the given query so that data from the remote data source is imported into Exasol when that query is
* executed on the Virtual Schema frontend.
*
* @param statement original query as sent by the Virtual Schema frontend
* @param exaMetadata Exasol metadata
* @param statement original query as sent by the Virtual Schema frontend
* @param selectListDataTypes expected datatypes of the result set
* @param exaMetadata Exasol metadata
* @return rewritten query
* @throws SQLException if execution of any SQL command on the remote data source failed
* @throws AdapterException if rewriting the query failed
*/
public String rewriteQuery(SqlStatement statement, ExaMetadata exaMetadata) throws AdapterException, SQLException;
public String rewriteQuery(SqlStatement statement, List<DataType> selectListDataTypes, ExaMetadata exaMetadata)
throws AdapterException, SQLException;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.exasol.adapter.dialects.rewriting;

import java.sql.SQLException;
import java.util.List;
import java.util.logging.Logger;

import com.exasol.*;
Expand All @@ -9,6 +10,7 @@
import com.exasol.adapter.dialects.*;
import com.exasol.adapter.jdbc.ConnectionDefinitionBuilder;
import com.exasol.adapter.jdbc.RemoteMetadataReader;
import com.exasol.adapter.metadata.DataType;
import com.exasol.adapter.sql.SqlStatement;
import com.exasol.errorreporting.ExaError;

Expand Down Expand Up @@ -39,13 +41,14 @@ protected AbstractQueryRewriter(final SqlDialect dialect, final RemoteMetadataRe
}

@Override
public String rewrite(final SqlStatement statement, final ExaMetadata exaMetadata,
final AdapterProperties properties) throws AdapterException, SQLException {
public String rewrite(final SqlStatement statement, final List<DataType> selectListDataTypes,
final ExaMetadata exaMetadata, final AdapterProperties properties) throws AdapterException, SQLException {
final String pushdownQuery = createPushdownQuery(statement, properties);
final ExaConnectionInformation exaConnectionInformation = getConnectionInformation(exaMetadata, properties);
final String connectionDefinition = this.connectionDefinitionBuilder.buildConnectionDefinition(properties,
exaConnectionInformation);
final String importStatement = generateImportStatement(connectionDefinition, pushdownQuery);
final String importStatement = generateImportStatement(connectionDefinition, selectListDataTypes,
pushdownQuery);
LOGGER.finer(() -> "Import push-down statement:\n" + importStatement);
return importStatement;
}
Expand All @@ -63,7 +66,7 @@ private String createPushdownQuery(final SqlStatement statement, final AdapterPr

/**
* Read the connection information from the metadata.
*
*
* @param exaMetadata metadata
* @param properties adapter properties
* @return connection information
Expand All @@ -90,10 +93,11 @@ protected ExaConnectionInformation getConnectionInformation(final ExaMetadata ex
* executed in the external source be as source data.
*
* @param connectionDefinition connection definition to be used when connecting to the external source
* @param selectListDataTypes TODO
* @param pushdownQuery source data for the `IMPORT...FROM` statement
* @return IMPORT statement to be executed on the Exasol database
* @throws SQLException if any problem occurs
*/
protected abstract String generateImportStatement(final String connectionDefinition, final String pushdownQuery)
throws SQLException;
protected abstract String generateImportStatement(final String connectionDefinition,
List<DataType> selectListDataTypes, final String pushdownQuery) throws SQLException;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.exasol.adapter.dialects.rewriting;

import java.sql.SQLException;
import java.util.List;

import com.exasol.adapter.dialects.SqlDialect;
import com.exasol.adapter.jdbc.*;
import com.exasol.adapter.metadata.DataType;

/**
* Implementation of {@link AbstractQueryRewriter} to generate {@code IMPORT FROM JDBC} queries.
Expand Down Expand Up @@ -34,7 +36,7 @@ public ImportFromJDBCQueryRewriter(final SqlDialect dialect, final RemoteMetadat
}

@Override
protected String generateImportStatement(final String connectionDefinition, final String pushdownQuery)
protected String generateImportStatement(final String connectionDefinition, List<DataType> selectListDataTypes, final String pushdownQuery)
throws SQLException {
return "IMPORT FROM JDBC " + connectionDefinition + " STATEMENT '" + pushdownQuery.replace("'", "''") + "'";
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
package com.exasol.adapter.dialects.rewriting;

import java.sql.SQLException;
import java.util.List;
import java.util.logging.Logger;

import com.exasol.adapter.dialects.SqlDialect;
import com.exasol.adapter.jdbc.*;
import com.exasol.adapter.metadata.DataType;

/**
* Implementation of {@link AbstractQueryRewriter} to generate {@code IMPORT INTO (<columns description>) FROM JDBC}
* queries.
*
*
* @see <a href="https://docs.exasol.com/sql/import.htm">https://docs.exasol.com/sql/import.htm</a>
*/
public class ImportIntoTemporaryTableQueryRewriter extends AbstractQueryRewriter {
Expand Down Expand Up @@ -44,20 +46,42 @@ public ImportIntoTemporaryTableQueryRewriter(final SqlDialect dialect,
this.connectionFactory = connectionFactory;
}

/*
* If selectListDataTypes is provided then use columns description from there otherwise infer columns description
* from query.
*/
@Override
protected String generateImportStatement(final String connectionDefinition, final String pushdownQuery)
throws SQLException {
final String columnDescription = this.createImportColumnsDescription(pushdownQuery);
return "IMPORT INTO (" + columnDescription + ") FROM JDBC " + connectionDefinition + " STATEMENT '"
protected String generateImportStatement(final String connectionDefinition,
final List<DataType> selectListDataTypes, final String pushdownQuery) throws SQLException {
final String columnsDescription = (selectListDataTypes.isEmpty() //
? createColumnsDescriptionFromQuery(pushdownQuery)
: createColumnsDescriptionFromExpectedResult(selectListDataTypes));
return "IMPORT INTO (" + columnsDescription + ") FROM JDBC " + connectionDefinition + " STATEMENT '"
+ pushdownQuery.replace("'", "''") + "'";
}

private String createImportColumnsDescription(final String query) throws SQLException {
private String createColumnsDescriptionFromQuery(final String query) throws SQLException {
final ColumnMetadataReader columnMetadataReader = this.remoteMetadataReader.getColumnMetadataReader();
final ResultSetMetadataReader resultSetMetadataReader = new ResultSetMetadataReader(
this.connectionFactory.getConnection(), columnMetadataReader);
final String columnsDescription = resultSetMetadataReader.describeColumns(query);
LOGGER.finer(() -> "Import columns: " + columnsDescription);
return columnsDescription;
}

private String createColumnsDescriptionFromExpectedResult(final List<DataType> types) {
final StringBuilder builder = new StringBuilder();
int columnNumber = 1;
for (final DataType type : types) {
if (columnNumber > 1) {
builder.append(", ");
}
builder.append("c");
builder.append(columnNumber);
builder.append(" ");
builder.append(type.toString());
++columnNumber;
}
return builder.toString();
}
}
Loading

0 comments on commit 9b3f0f2

Please sign in to comment.