Skip to content

Commit

Permalink
* #79: Added error builder to the project.
Browse files Browse the repository at this point in the history
  • Loading branch information
AnastasiiaSergienko committed Dec 22, 2020
1 parent bd5434e commit 7fc086e
Show file tree
Hide file tree
Showing 20 changed files with 241 additions and 156 deletions.
7 changes: 6 additions & 1 deletion doc/changes/changes_9.0.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,9 @@ Code name:

* #64: Refactored the `AbstractRemoteMetadataReader` and `TableMetadataReader` interface
* #75: Restricted amount of mapped tables in the remote schema to 1000.
* #77: Refactored SQL generation for scalar functions.
* #77: Refactored SQL generation for scalar functions.
* #79: Added error builder to the project.

## Dependency Updates

* Updated `com.exasol:error-reporting-java:0.2.0` to `0.2.2`
4 changes: 4 additions & 0 deletions doc/error_codes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Latest Used Error Codes

E-VS-COM-JDBC-31
W-VS-COM-JDBC-7
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@
<dependency>
<groupId>com.exasol</groupId>
<artifactId>error-reporting-java</artifactId>
<version>0.2.0</version>
<version>0.2.2</version>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.json.*;

import com.exasol.adapter.AdapterException;
import com.exasol.errorreporting.ExaError;

/**
* Converts column adapter Notes into JSON format and back.
Expand Down Expand Up @@ -56,15 +57,19 @@ public String convertToJson(final ColumnAdapterNotes columnAdapterNotes) {
public ColumnAdapterNotes convertFromJsonToColumnAdapterNotes(final String adapterNotes, final String columnName)
throws AdapterException {
if ((adapterNotes == null) || adapterNotes.isEmpty()) {
throw new AdapterException("Adapter notes for column " + columnName + " are empty or NULL. " //
+ "Please refresh the virtual schema.");
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-3")
.message("Adapter notes for column \"{{columnName}}\" are empty or NULL.")
.unquotedParameter("columnName", columnName) //
.mitigation("Please refresh the virtual schema.").toString());
}
final JsonObject root;
try (final JsonReader jr = Json.createReader(new StringReader(adapterNotes))) {
root = jr.readObject();
} catch (final Exception exception) {
throw new AdapterException("Could not parse the column adapter notes of column \"" + columnName + "\"." //
+ "Please refresh the virtual schema.", exception);
} catch (final RuntimeException exception) {
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-4")
.message("Could not parse the column adapter notes of column \"{{columnName}}\".")
.unquotedParameter("columnName", columnName).mitigation("Please refresh the virtual schema.")
.toString(), exception);
}
return ColumnAdapterNotes.builder() //
.jdbcDataType(root.getInt(JDBC_DATA_TYPE)) //
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.json.*;

import com.exasol.adapter.AdapterException;
import com.exasol.errorreporting.ExaError;

/**
* Converts schema adapter Notes into JSON format and back.
Expand Down Expand Up @@ -48,7 +49,7 @@ private SchemaAdapterNotesJsonConverter() {
* @return string representation of a JSON Object
*/
public String convertToJson(final SchemaAdapterNotes schemaAdapterNotes) {
final JsonObjectBuilder builder = factory.createObjectBuilder()
final JsonObjectBuilder builder = this.factory.createObjectBuilder()
.add(CATALOG_SEPARATOR, schemaAdapterNotes.getCatalogSeparator())
.add(IDENTIFIER_QUOTE_STRING, schemaAdapterNotes.getIdentifierQuoteString())
.add(STORES_LOWER_CASE_IDENTIFIERS, schemaAdapterNotes.storesLowerCaseIdentifiers())
Expand Down Expand Up @@ -77,15 +78,19 @@ public String convertToJson(final SchemaAdapterNotes schemaAdapterNotes) {
public SchemaAdapterNotes convertFromJsonToSchemaAdapterNotes(final String adapterNotes, final String schemaName)
throws AdapterException {
if ((adapterNotes == null) || adapterNotes.isEmpty()) {
throw new AdapterException("Adapter notes for virtual schema " + schemaName + " are empty or NULL. " //
+ "Please refresh the virtual schema.");
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-5")
.message("Adapter notes for virtual schema \"{{schemaName}}\" are empty or NULL.")
.unquotedParameter("schemaName", schemaName) //
.mitigation("Please refresh the virtual schema.").toString());
}
final JsonObject root;
try (final JsonReader jr = Json.createReader(new StringReader(adapterNotes))) {
root = jr.readObject();
} catch (final Exception exception) {
throw new AdapterException("Could not parse the schema adapter notes of virtual schema \"" + schemaName
+ "\". Please refresh the virtual schema.", exception);
} catch (final RuntimeException exception) {
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-6")
.message("Could not parse the schema adapter notes of virtual schema \"{{schemaName}}\".")
.unquotedParameter("schemaName", schemaName) //
.mitigation("Please refresh the virtual schema.").toString(), exception);
}
checkKey(root, CATALOG_SEPARATOR, schemaName);
checkKey(root, IDENTIFIER_QUOTE_STRING, schemaName);
Expand Down Expand Up @@ -122,8 +127,11 @@ public SchemaAdapterNotes convertFromJsonToSchemaAdapterNotes(final String adapt
private static void checkKey(final JsonObject root, final String key, final String schemaName)
throws AdapterException {
if (!root.containsKey(key)) {
throw new AdapterException("Adapter notes of virtual schema " + schemaName + " don't have the key " + key
+ ". Please refresh the virtual schema");
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-7")
.message("Adapter notes of virtual schema \"{{schemaName}}\" don't have the key {{key}}.")
.unquotedParameter("schemaName", schemaName) //
.parameter("key", key) //
.mitigation("Please refresh the virtual schema").toString());
}
}
}
73 changes: 49 additions & 24 deletions src/main/java/com/exasol/adapter/dialects/AbstractSqlDialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import com.exasol.ExaMetadata;
import com.exasol.adapter.AdapterException;
Expand Down Expand Up @@ -178,14 +179,19 @@ protected void validateSupportedPropertiesList() throws PropertyValidationExcept
}

protected String createUnsupportedElementMessage(final String unsupportedElement, final String property) {
return "The dialect " + this.properties.getSqlDialect() + " does not support " + unsupportedElement
+ " property. Please, do not set the \"" + property + "\" property.";
return ExaError.messageBuilder("E-VS-COM-JDBC-13")
.message("The dialect {{dialectName}} does not support {{unsupportedElement}} property.")
.parameter("dialectName", this.properties.getSqlDialect())
.parameter("unsupportedElement", unsupportedElement)
.mitigation(" Please, do not set the {{property}} property.") //
.parameter("property", property).toString();
}

private void validateConnectionNameProperty() throws PropertyValidationException {
if (!this.properties.hasConnectionName()) {
throw new PropertyValidationException(
"Please specify a connection using the property \"" + CONNECTION_NAME_PROPERTY + "\".");
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-14")
.message("Please specify a connection using the property {{connectionNameProperty}}.")
.parameter("connectionNameProperty", CONNECTION_NAME_PROPERTY).toString());
}
}

Expand All @@ -206,8 +212,11 @@ private void validateSchemaNameProperty() throws PropertyValidationException {
protected void validateBooleanProperty(final String property) throws PropertyValidationException {
if (this.properties.containsKey(property) //
&& !BOOLEAN_PROPERTY_VALUE_PATTERN.matcher(this.properties.get(property)).matches()) {
throw new PropertyValidationException("The value '" + this.properties.get(property) + "' for the property "
+ property + " is invalid. It has to be either 'true' or 'false' (case insensitive).");
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-15")
.message("The value {{value}} for the property {{property}} is invalid. "
+ "It has to be either 'true' or 'false' (case insensitive).")
.parameter("value", this.properties.get(property)) //
.parameter("property", property).toString());
}
}

Expand All @@ -230,14 +239,19 @@ private void validateDebugPortNumber(final String debugAddress) {
try {
final int port = Integer.parseInt(portAsString);
if ((port < 1) || (port > 65535)) {
LOGGER.warning(() -> "Debug output port " + port + " is out of range. Port specified in property "
+ DEBUG_ADDRESS_PROPERTY
+ "must have following format: <host>[:<port>], and be between 1 and 65535.");
LOGGER.warning(() -> ExaError.messageBuilder("W-VS-COM-JDBC-1")
.message("Debug output port {{port}} is out of range.") //
.unquotedParameter("port", port)
.mitigation("Port specified in property {{debugAddressProperty}} must have "
+ "the following format: <host>[:<port>], and be between 1 and 65535.")
.parameter("debugAddressProperty", DEBUG_ADDRESS_PROPERTY).toString());
}
} catch (final NumberFormatException ex) {
LOGGER.warning(() -> "Illegal debug output port \"" + portAsString + "\". Property "
+ DEBUG_ADDRESS_PROPERTY
+ "must have following format: <host>[:<port>], where port is a number between 1 and 65535.");
LOGGER.warning(() -> ExaError.messageBuilder("W-VS-COM-JDBC-2").message(
"Illegal debug output port {{portAsString}}. Property {{debugAddressProperty}} must have "
+ "the following format: <host>[:<port>], where port is a number between 1 and 65535.")
.parameter("debugAddressProperty", DEBUG_ADDRESS_PROPERTY)
.parameter("portAsString", portAsString).toString());
}
}
}
Expand All @@ -248,10 +262,14 @@ private void validateExceptionHandling() throws PropertyValidationException {
if (!((exceptionHandling == null) || exceptionHandling.isEmpty())) {
for (final SqlDialect.ExceptionHandlingMode mode : SqlDialect.ExceptionHandlingMode.values()) {
if (!mode.name().equals(exceptionHandling)) {
throw new PropertyValidationException(
"Invalid value '" + exceptionHandling + "' for property " + EXCEPTION_HANDLING_PROPERTY
+ ". Choose one of: " + ExceptionHandlingMode.IGNORE_INVALID_VIEWS.name() + ", "
+ ExceptionHandlingMode.NONE.name());
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-16").message(
"Invalid value {{exceptionHandlingValue}} for property {{exceptionHandlingProperty}}.")
.parameter("exceptionHandlingValue", exceptionHandling)
.parameter("exceptionHandlingProperty", EXCEPTION_HANDLING_PROPERTY)
.mitigation("Choose one of: {{availableValues}}.")
.unquotedParameter("availableValues", Arrays.stream(ExceptionHandlingMode.values())
.map(Enum::toString).collect(Collectors.toList()).toString())
.toString());
}
}
}
Expand All @@ -265,13 +283,19 @@ protected void checkImportPropertyConsistency(final String importFromProperty, f
final boolean connectionIsEmpty = ((value == null) || value.isEmpty());
if (isDirectImport) {
if (connectionIsEmpty) {
throw new PropertyValidationException("You defined the property " + importFromProperty
+ ", please also define " + connectionProperty);
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-17")
.message("You defined the property {{importFromProperty}}.")
.parameter("importFromProperty", importFromProperty)
.mitigation("Please also define {{connectionProperty}}.")
.parameter("connectionProperty", connectionProperty).toString());
}
} else {
if (!connectionIsEmpty) {
throw new PropertyValidationException("You defined the property " + connectionProperty
+ " without setting " + importFromProperty + " to 'TRUE'. This is not allowed");
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-18")
.message("You defined the property {{connectionProperty}} without setting "
+ "{{importFromProperty}} to 'TRUE'. This is not allowed")
.parameter("connectionProperty", connectionProperty)
.parameter("importFromProperty", importFromProperty).toString());
}
}
}
Expand All @@ -283,10 +307,11 @@ protected void validateCastNumberToDecimalProperty(final String castNumberToDeci
final String precisionAndScale = this.properties.get(castNumberToDecimalProperty);
final Matcher matcher = pattern.matcher(precisionAndScale);
if (!matcher.matches()) {
throw new PropertyValidationException(ExaError.messageBuilder("E-VSJ-1").message(
"Unable to parse adapter property {{propertyName}} value {{value}} into a number's precision and scale. The required format is '<precision>,<scale>', where both are integer numbers.")
.parameter("propertyName", castNumberToDecimalProperty).parameter("value", precisionAndScale)
.toString());
throw new PropertyValidationException(ExaError.messageBuilder("E-VS-COM-JDBC-19").message(
"Unable to parse adapter property {{propertyName}} value {{value}} into a number's precision "
+ "and scale. The required format is '<precision>,<scale>' where both are integer numbers.")
.parameter("propertyName", castNumberToDecimalProperty) //
.parameter("value", precisionAndScale).toString());
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import com.exasol.adapter.AdapterProperties;
import com.exasol.adapter.jdbc.ConnectionFactory;
import com.exasol.errorreporting.ExaError;

/**
* This class implements a registry for supported SQL dialects.
Expand All @@ -20,9 +21,9 @@ public final class SqlDialectRegistry {
*
* @return singleton instance
*/
public static final synchronized SqlDialectRegistry getInstance() {
public static synchronized SqlDialectRegistry getInstance() {
if (instance == null) {
LOGGER.finer(() -> "Instanciating SQL dialect registry and loading adapter factories.");
LOGGER.finer(() -> "Instantiating SQL dialect registry and loading adapter factories.");
instance = new SqlDialectRegistry();
instance.loadSqlDialectFactories();
}
Expand All @@ -31,9 +32,7 @@ public static final synchronized SqlDialectRegistry getInstance() {

private void loadSqlDialectFactories() {
final ServiceLoader<SqlDialectFactory> serviceLoader = ServiceLoader.load(SqlDialectFactory.class);
final Iterator<SqlDialectFactory> factories = serviceLoader.iterator();
while (factories.hasNext()) {
final SqlDialectFactory factory = factories.next();
for (final SqlDialectFactory factory : serviceLoader) {
registerSqlDialectFactory(factory);
}
LOGGER.fine(() -> "Registered SQL dialects: " + listRegisteredSqlDialectNames());
Expand Down Expand Up @@ -85,7 +84,9 @@ public SqlDialect getDialectForName(final String name, final ConnectionFactory c
+ factory.getSqlDialectVersion());
return factory.createSqlDialect(connectionFactory, properties);
} else {
throw new IllegalArgumentException("Unknown SQL dialect \"" + name + "\" requested. " + describe());
throw new IllegalArgumentException(ExaError.messageBuilder("E-VS-COM-JDBC-20") //
.message("Unknown SQL dialect {{name}} requested.") //
.parameter("name", name).toString() + describe());
}
}

Expand Down Expand Up @@ -127,4 +128,4 @@ public String listRegisteredSqlDialectNames() {
.collect(Collectors.joining(", "));
return dialectNamesAsString.isEmpty() ? "none" : dialectNamesAsString;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import com.exasol.adapter.dialects.*;
import com.exasol.adapter.jdbc.*;
import com.exasol.adapter.sql.SqlStatement;
import com.exasol.errorreporting.ExaError;

/**
* Abstract implementation of {@link QueryRewriter}.
Expand Down Expand Up @@ -67,20 +68,18 @@ private String createPushdownQuery(final SqlStatement statement, final AdapterPr

protected ExaConnectionInformation getConnectionInformation(final ExaMetadata exaMetadata,
final AdapterProperties properties) throws AdapterException {
final ExaConnectionInformation exaConnectionInformation;
if (properties.hasConnectionName()) {
final String connectionName = properties.getConnectionName();
try {
exaConnectionInformation = exaMetadata.getConnection(connectionName);
return exaMetadata.getConnection(connectionName);
} catch (final ExaConnectionAccessException exception) {
throw new AdapterException("Unable to access information about the Exasol connection named \""
+ connectionName + "\" trying to create a connection definition for rewritten query.",
exception);
throw new AdapterException(ExaError.messageBuilder("E-VS-COM-JDBC-8").message(
"Unable to access information about the Exasol connection named {{connectionName}} trying to"
+ " create a connection definition for rewritten query.")
.parameter("connectionName", connectionName).toString(), exception);
}
} else {
exaConnectionInformation = null;
}
return exaConnectionInformation;
return null;
}

/**
Expand All @@ -94,5 +93,4 @@ protected ExaConnectionInformation getConnectionInformation(final ExaMetadata ex
*/
protected abstract String generateImportStatement(final String connectionDefinition, final String pushdownQuery)
throws SQLException;

}
Loading

0 comments on commit 7fc086e

Please sign in to comment.