Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changes/changes_18.0.2.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Code name: Improve code quality
* #311: Fixed metadata parsing and conversion diagnostics for missing JSON fields and nullable notes/comments, and made `SqlFunctionScalarCast` tolerate a null argument consistently with related SQL AST nodes.
* #310: Fixed `SqlStatementSelect.Builder.build()` so empty and partial builders no longer fail with a raw `NullPointerException`.
* #309: Fixed the `SqlNodeVisitor` API documentation and parameter names for `SqlPredicateIsNotNull` and `SqlPredicateIsNull`.
* #317: Applied small allocation cleanups in request parsing, logging timestamp formatting, and schema metadata JSON conversion.
* #308: Fixed `SqlLimit` so `limit` and `offset` stay non-negative for the full object lifetime by making the node immutable and aligning the validation message with the accepted zero values.
* #307: Fixed `PushdownSqlRenderer` so `HASHTYPE` data types include `bytesize` in rendered pushdown SQL JSON.
* #312: Fixed logging utility resource and handler lifecycle issues by closing version metadata streams, falling back when the thread context class loader is missing, defaulting absent version properties to `UNKNOWN`, closing replaced root log handlers, and resetting closed remote socket handlers before reuse.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ public final class SchemaMetadataJsonConverter {
private static final String COMMENT_KEY = "comment";
private static final String IDENTITY_KEY = "isIdentity";
private static final String DEFAULT_KEY = "default";
private static final String COLUMNS_KEY = "columns";
private final JsonBuilderFactory factory = Json.createBuilderFactory(Collections.emptyMap());

/**
Expand Down Expand Up @@ -94,7 +95,7 @@ private JsonObjectBuilder convertTableMetadata(final TableMetadata table) {
final JsonObjectBuilder tableBuilder = this.factory.createObjectBuilder();
tableBuilder.add(TYPE_KEY, "table");
tableBuilder.add(TABLE_NAME_KEY, table.getName());
final JsonArrayBuilder columnsBuilder = Json.createArrayBuilder();
final JsonArrayBuilder columnsBuilder = this.factory.createArrayBuilder();
for (final ColumnMetadata column : table.getColumns()) {
columnsBuilder.add(convertColumnMetadata(column));
}
Expand All @@ -104,7 +105,7 @@ private JsonObjectBuilder convertTableMetadata(final TableMetadata table) {
if (table.hasComment()) {
tableBuilder.add(COMMENT_KEY, table.getComment());
}
tableBuilder.add("columns", columnsBuilder);
tableBuilder.add(COLUMNS_KEY, columnsBuilder);
return tableBuilder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

import static com.exasol.adapter.request.parser.RequestParserConstants.PROPERTIES_KEY;

import java.io.ByteArrayInputStream;
import java.nio.charset.StandardCharsets;
import java.io.StringReader;
import java.util.*;
import java.util.Map.Entry;

Expand All @@ -27,9 +26,7 @@ class AbstractRequestParser {
* @return JSON reader
*/
protected JsonReader createJsonReader(final String rawRequest) {
final ByteArrayInputStream rawRequestStream = new ByteArrayInputStream(
rawRequest.getBytes(StandardCharsets.UTF_8));
return Json.createReader(rawRequestStream);
return Json.createReader(new StringReader(rawRequest));
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.exasol.adapter.response.converter;

import static java.util.Collections.emptyMap;

import com.exasol.adapter.capabilities.*;
import com.exasol.adapter.metadata.converter.SchemaMetadataJsonConverter;
import com.exasol.adapter.response.*;
Expand All @@ -16,6 +18,7 @@ public final class ResponseJsonConverter {
private static final String LITERAL_PREFIX = "LITERAL_";
private static final String SCHEMA_METADATA = "schemaMetadata";
private static final ResponseJsonConverter responseJsonConverter = new ResponseJsonConverter();
private final JsonBuilderFactory factory = Json.createBuilderFactory(emptyMap());

private ResponseJsonConverter() {
}
Expand All @@ -37,7 +40,7 @@ public static ResponseJsonConverter getInstance() {
*/
@SuppressWarnings("squid:S1172")
public String convertDropVirtualSchemaResponse(final DropVirtualSchemaResponse dropResponse) {
return Json.createObjectBuilder() //
return this.factory.createObjectBuilder() //
.add("type", "dropVirtualSchema") //
.build() //
.toString();
Expand All @@ -50,7 +53,7 @@ public String convertDropVirtualSchemaResponse(final DropVirtualSchemaResponse d
* @return string representation of a JSON Object
*/
public String convertCreateVirtualSchemaResponse(final CreateVirtualSchemaResponse createResponse) {
return Json.createObjectBuilder() //
return this.factory.createObjectBuilder() //
.add("type", "createVirtualSchema") //
.add(SCHEMA_METADATA,
SchemaMetadataJsonConverter.getInstance().convert(createResponse.getSchemaMetadata())) //
Expand All @@ -65,7 +68,7 @@ public String convertCreateVirtualSchemaResponse(final CreateVirtualSchemaRespon
* @return string representation of a JSON Object
*/
public String convertPushDownResponse(final PushDownResponse pushDownResponse) {
return Json.createObjectBuilder() //
return this.factory.createObjectBuilder() //
.add("type", "pushdown") //
.add("sql", pushDownResponse.getPushDownSql()) //
.build() //
Expand All @@ -79,8 +82,8 @@ public String convertPushDownResponse(final PushDownResponse pushDownResponse) {
* @return string representation of a JSON Object
*/
public String convertGetCapabilitiesResponse(final GetCapabilitiesResponse getCapabilitiesResponse) {
final JsonObjectBuilder builder = Json.createObjectBuilder().add("type", "getCapabilities");
final JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
final JsonObjectBuilder builder = this.factory.createObjectBuilder().add("type", "getCapabilities");
final JsonArrayBuilder arrayBuilder = this.factory.createArrayBuilder();
final Capabilities capabilities = getCapabilitiesResponse.getCapabilities();
addMainCapabilitiesToBuilder(capabilities, arrayBuilder);
addScalarFunctionCapabilitiesToBuilder(capabilities, arrayBuilder);
Expand Down Expand Up @@ -136,7 +139,7 @@ private void addMainCapabilitiesToBuilder(final Capabilities capabilities, final
* @return string representation of a JSON Object
*/
public String convertRefreshResponse(final RefreshResponse refreshResponse) {
return Json.createObjectBuilder() //
return this.factory.createObjectBuilder() //
.add("type", "refresh") //
.add(SCHEMA_METADATA,
SchemaMetadataJsonConverter.getInstance().convert(refreshResponse.getSchemaMetadata())) //
Expand All @@ -151,7 +154,7 @@ public String convertRefreshResponse(final RefreshResponse refreshResponse) {
* @return string representation of a JSON Object
*/
public String convertSetPropertiesResponse(final SetPropertiesResponse setPropertiesResponse) {
final JsonObjectBuilder builder = Json.createObjectBuilder();
final JsonObjectBuilder builder = this.factory.createObjectBuilder();
builder.add("type", "setProperties");
if (setPropertiesResponse.getSchemaMetadata() != null) {
builder.add(SCHEMA_METADATA,
Expand Down
25 changes: 13 additions & 12 deletions src/main/java/com/exasol/logging/CompactFormatter.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.io.PrintWriter;
import java.io.StringWriter;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.logging.Formatter;
import java.util.logging.LogRecord;
Expand All @@ -13,7 +13,8 @@
*/
public class CompactFormatter extends Formatter {
private static final String LOG_LEVEL_FORMAT = "%-8s";
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
private final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS")
.withZone(ZoneOffset.UTC);

/**
* Formats a log record according in a compact manner.
Expand All @@ -24,14 +25,14 @@ public class CompactFormatter extends Formatter {
* <code>yyyy-MM-dd HH:mm:ss.SSS LEVEL [c.e.ClassName] The message.</code>
*/
@Override
public String format(final LogRecord record) {
public String format(final LogRecord logRecord) {
final StringBuilder builder = new StringBuilder();
builder.append(formatTimestamp(record.getMillis()));
builder.append(formatTimestamp(logRecord.getMillis()));
builder.append(" ");
builder.append(String.format(LOG_LEVEL_FORMAT, record.getLevel()));
appendClassName(record.getSourceClassName(), builder);
builder.append(formatMessage(record));
formatException(record, builder);
builder.append(String.format(LOG_LEVEL_FORMAT, logRecord.getLevel()));
appendClassName(logRecord.getSourceClassName(), builder);
builder.append(formatMessage(logRecord));
formatException(logRecord, builder);
builder.append(System.lineSeparator());
return builder.toString();
}
Expand Down Expand Up @@ -61,16 +62,16 @@ private void appendNonEmptyClassName(final String className, final StringBuilder

private String formatTimestamp(final long millis) {
final Instant instant = Instant.ofEpochMilli(millis);
return this.dateTimeFormatter.format(instant.atZone(ZoneId.of("Z")));
return this.dateTimeFormatter.format(instant);
}

private void formatException(final LogRecord record, final StringBuilder builder) {
final Throwable thrown = record.getThrown();
private void formatException(final LogRecord logRecord, final StringBuilder builder) {
final Throwable thrown = logRecord.getThrown();
if (thrown != null) {
builder.append("\n\t");
final StringWriter errors = new StringWriter();
thrown.printStackTrace(new PrintWriter(errors));
builder.append(errors);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ void setPropertiesRequest() {
() -> assertThat(properties, hasEntry(equalTo("NULL_value"), equalTo(null))));
}

@Test
void setPropertiesRequestPreservesUtf8Characters() {
final String rawRequest = JsonEntry.object(
entry("type", "setProperties"),
entry("properties", object(entry("CITY", "München"))),
SCHEMA_METADATA_INFO).render();
final AdapterRequest request = this.parser.parse(rawRequest);
final Map<String, String> properties = ((SetPropertiesRequest) request).getProperties();
assertThat(properties, hasEntry(equalTo("CITY"), equalTo("München")));
}

@Test
void unsupportedPropertyType() {
final String rawRequest = JsonEntry.object(//
Expand Down Expand Up @@ -157,4 +168,4 @@ private JsonParent createPushDownRequest(final JsonEntry selectListDataTypes) {
)))))))), //
SCHEMA_METADATA_INFO);
}
}
}
Loading