This commit is contained in:
2017-10-30 13:37:21 +01:00
parent a08c71926f
commit 20d6827d0a
6 changed files with 224 additions and 227 deletions

View File

@@ -11,9 +11,9 @@ import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor @RequiredArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class SqlExecutionException extends Exception { public class SqlExecutionException extends Exception {
private static final long serialVersionUID = 3684929762067312606L; private static final long serialVersionUID = 3684929762067312606L;
private final String message; private final String message;
private final List<UserError> userErrors; private final List<UserError> userErrors;
private Throwable cause; private Throwable cause;
} }

View File

@@ -36,200 +36,197 @@ import lombok.extern.log4j.Log4j;
@Log4j @Log4j
public class SqlExecutor { public class SqlExecutor {
public static Result execute(Connection conn, String sql) throws SQLException, JsonProcessingException { public static Result execute(Connection conn, String sql) throws SQLException, JsonProcessingException {
log.trace("SQL: " + sql.trim()); log.trace("SQL: " + sql.trim());
@Cleanup @Cleanup
Statement stmt = conn.createStatement(); Statement stmt = conn.createStatement();
stmt.execute(sql.trim()); stmt.execute(sql.trim());
log.info("Executed"); log.info("Executed");
ResultBuilder resultBuilder = Result.builder(); ResultBuilder resultBuilder = Result.builder();
try { try {
handleUserErrors(conn, sql, stmt); handleUserErrors(conn, sql, stmt);
} catch (SqlExecutionException e) { } catch (SqlExecutionException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
resultBuilder.userErrors(e.getUserErrors()); resultBuilder.userErrors(e.getUserErrors());
} }
return resultBuilder.build(); return resultBuilder.build();
} }
public static QueryResult executeJsonQuery(Connection conn, String json) public static QueryResult executeJsonQuery(Connection conn, String json) throws SQLException, JsonParseException, JsonMappingException, IOException {
throws SQLException, JsonParseException, JsonMappingException, IOException { log.debug("Parsing JSON: " + json);
log.debug("Parsing JSON: " + json);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
QueryParameter queryParameter = mapper.readValue(json, QueryParameter.class); QueryParameter queryParameter = mapper.readValue(json, QueryParameter.class);
log.debug("Parsed QueryParamter: " + queryParameter.toString()); log.debug("Parsed QueryParamter: " + queryParameter.toString());
return executeQuery(conn, queryParameter); return executeQuery(conn, queryParameter);
} }
public static QueryResult executeQuery(Connection conn, QueryParameter parameters) throws SQLException { public static QueryResult executeQuery(Connection conn, QueryParameter parameters) throws SQLException {
if (parameters == null || parameters.getParameters() == null) { if (parameters == null || parameters.getParameters() == null) {
return executeQuery(conn, parameters.getSql()); return executeQuery(conn, parameters.getSql());
} else { } else {
return executeQuery(conn, parameters.getSql(), parameters.getParameters().toArray()); return executeQuery(conn, parameters.getSql(), parameters.getParameters().toArray());
} }
} }
public static QueryResult executeQuery(Connection conn, String sql, Object... parameters) throws SQLException { public static QueryResult executeQuery(Connection conn, String sql, Object... parameters) throws SQLException {
log.trace("SQL: " + sql.trim()); log.trace("SQL: " + sql.trim());
@Cleanup @Cleanup
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
if (parameters != null) { if (parameters != null) {
int parameterIndex = 1; int parameterIndex = 1;
for (Object object : parameters) { for (Object object : parameters) {
if (object != null) { if (object != null) {
if (object instanceof String) { if (object instanceof String) {
stmt.setString(parameterIndex, (String) object); stmt.setString(parameterIndex, (String) object);
} else if (object instanceof Integer) { } else if (object instanceof Integer) {
stmt.setInt(parameterIndex, (Integer) object); stmt.setInt(parameterIndex, (Integer) object);
} else if (object instanceof Long) { } else if (object instanceof Long) {
stmt.setLong(parameterIndex, (Long) object); stmt.setLong(parameterIndex, (Long) object);
} else { } else {
stmt.setString(parameterIndex, (String) object); stmt.setString(parameterIndex, (String) object);
String message = String.format("Unhandled paramter type <%s>. Defaulting to String", String message = String.format("Unhandled paramter type <%s>. Defaulting to String", object.getClass().getName());
object.getClass().getName()); log.warn(message);
log.warn(message); }
} } else {
} else { log.warn("parameter is null");
log.warn("parameter is null"); }
} parameterIndex++;
parameterIndex++; }
} }
}
@Cleanup @Cleanup
ResultSet rs = null; ResultSet rs = null;
QueryResultBuilder queryResultBuilder = QueryResult.builder(); QueryResultBuilder queryResultBuilder = QueryResult.builder();
try { try {
rs = stmt.executeQuery(); rs = stmt.executeQuery();
} catch (SQLException e) { } catch (SQLException e) {
return queryResultBuilder // return queryResultBuilder //
.exception(e.getClass().getName()) // .exception(e.getClass().getName()) //
.exceptionMessage(e.getMessage()) // .exceptionMessage(e.getMessage()) //
.build(); .build();
} }
try { try {
handleUserErrors(conn, sql, stmt); handleUserErrors(conn, sql, stmt);
} catch (SqlExecutionException e) { } catch (SqlExecutionException e) {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
return queryResultBuilder.userErrors(e.getUserErrors()).build(); return queryResultBuilder.userErrors(e.getUserErrors()).build();
} }
List<Row> rows = new Vector<Row>(); List<Row> rows = new Vector<Row>();
while (rs.next()) { while (rs.next()) {
ResultSetMetaData metaData = rs.getMetaData(); ResultSetMetaData metaData = rs.getMetaData();
if (rs.isFirst()) { if (rs.isFirst()) {
queryResultBuilder.columnDefinitions(getColumnDefinitions(metaData)); queryResultBuilder.columnDefinitions(getColumnDefinitions(metaData));
} }
RowBuilder rowBuilder = Row.builder(); RowBuilder rowBuilder = Row.builder();
List<Column> columns = new Vector<Column>(); List<Column> columns = new Vector<Column>();
int columnCount = metaData.getColumnCount(); int columnCount = metaData.getColumnCount();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) { for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
ColumnBuilder columnBuilder = Column.builder(); ColumnBuilder columnBuilder = Column.builder();
int columnType = metaData.getColumnType(columnIndex); int columnType = metaData.getColumnType(columnIndex);
if (columnType == Types.VARCHAR) { if (columnType == Types.VARCHAR) {
columnBuilder.value(rs.getString(columnIndex)); columnBuilder.value(rs.getString(columnIndex));
} else if (columnType == Types.NUMERIC) { } else if (columnType == Types.NUMERIC) {
columnBuilder.value(rs.getLong(columnIndex)); columnBuilder.value(rs.getLong(columnIndex));
} else { } else {
String message = String.format("Unhandled column type <%s>. Defaulting to String", rs.getMetaData().getColumnTypeName(columnIndex)); String message = String.format("Unhandled column type <%s>. Defaulting to String", rs.getMetaData().getColumnTypeName(columnIndex));
log.warn(message); log.warn(message);
} }
columns.add(columnBuilder.build()); columns.add(columnBuilder.build());
} }
rowBuilder.columns(columns); rowBuilder.columns(columns);
rows.add(rowBuilder.build()); rows.add(rowBuilder.build());
} }
return queryResultBuilder.rows(rows).build(); return queryResultBuilder.rows(rows).build();
} }
private static Vector<ColumnDefinition> getColumnDefinitions(ResultSetMetaData metaData) throws SQLException { private static Vector<ColumnDefinition> getColumnDefinitions(ResultSetMetaData metaData) throws SQLException {
Vector<ColumnDefinition> columnDefinitions = new Vector<ColumnDefinition>(); Vector<ColumnDefinition> columnDefinitions = new Vector<ColumnDefinition>();
int columnCount = metaData.getColumnCount(); int columnCount = metaData.getColumnCount();
for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) { for (int columnIndex = 1; columnIndex <= columnCount; columnIndex++) {
columnDefinitions.add(ColumnDefinition.builder() // columnDefinitions.add(ColumnDefinition.builder() //
.index(columnIndex) // .index(columnIndex) //
.name(metaData.getColumnLabel(columnIndex)) // .name(metaData.getColumnLabel(columnIndex)) //
.type(metaData.getColumnTypeName(columnIndex)) // .type(metaData.getColumnTypeName(columnIndex)) //
.build()); .build());
} }
return columnDefinitions; return columnDefinitions;
} }
private static void handleUserErrors(Connection conn, String sql, Statement stmt) private static void handleUserErrors(Connection conn, String sql, Statement stmt) throws SQLException, SqlExecutionException {
throws SQLException, SqlExecutionException { SQLWarning warnings = stmt.getWarnings();
SQLWarning warnings = stmt.getWarnings(); List<UserError> userErrors = new Vector<UserError>();
List<UserError> userErrors = new Vector<UserError>(); if (warnings != null) {
if (warnings != null) { userErrors = parseUserErrors(conn);
userErrors = parseUserErrors(conn); String message = String.format("Errors while executing SQL \"%s\"", sql);
String message = String.format("Errors while executing SQL \"%s\"", sql); throw new SqlExecutionException(message, userErrors);
throw new SqlExecutionException(message, userErrors); }
} }
}
private static List<UserError> parseUserErrors(Connection conn) throws SQLException { private static List<UserError> parseUserErrors(Connection conn) throws SQLException {
log.debug("Retrieving user errors"); log.debug("Retrieving user errors");
String userErrorsSql = "select name, type, sequence, line, position, text, attribute, message_number from user_errors where type <> 'JAVA CLASS' order by sequence"; String userErrorsSql = "select name, type, sequence, line, position, text, attribute, message_number from user_errors where type <> 'JAVA CLASS' order by sequence";
boolean first = true; boolean first = true;
Vector<UserError> userErrors = new Vector<UserError>(); Vector<UserError> userErrors = new Vector<UserError>();
Vector<MessageLine> lines = new Vector<UserError.MessageLine>(); Vector<MessageLine> lines = new Vector<UserError.MessageLine>();
UserErrorBuilder builder = UserError.builder(); UserErrorBuilder builder = UserError.builder();
@Cleanup @Cleanup
PreparedStatement userErrorsStmt = conn.prepareStatement(userErrorsSql); PreparedStatement userErrorsStmt = conn.prepareStatement(userErrorsSql);
@Cleanup @Cleanup
ResultSet userErrorsRs = userErrorsStmt.executeQuery(); ResultSet userErrorsRs = userErrorsStmt.executeQuery();
while (userErrorsRs.next()) { while (userErrorsRs.next()) {
long messageNumber = userErrorsRs.getLong("message_number"); long messageNumber = userErrorsRs.getLong("message_number");
if (messageNumber != 0) { if (messageNumber != 0) {
if (!first) { if (!first) {
builder.lines(lines); builder.lines(lines);
userErrors.add(builder.build()); userErrors.add(builder.build());
first = false; first = false;
builder = UserError.builder(); builder = UserError.builder();
lines = new Vector<UserError.MessageLine>(); lines = new Vector<UserError.MessageLine>();
} }
builder.name(userErrorsRs.getString("name")); builder.name(userErrorsRs.getString("name"));
builder.type(userErrorsRs.getString("type")); builder.type(userErrorsRs.getString("type"));
} }
lines.add(UserError.MessageLine.builder() // lines.add(UserError.MessageLine.builder() //
.sequence(userErrorsRs.getLong("sequence")) // .sequence(userErrorsRs.getLong("sequence")) //
.line(userErrorsRs.getLong("line")) // .line(userErrorsRs.getLong("line")) //
.position(userErrorsRs.getLong("position")) // .position(userErrorsRs.getLong("position")) //
.text(userErrorsRs.getString("text")) // .text(userErrorsRs.getString("text")) //
.attribute(userErrorsRs.getString("attribute")) // .attribute(userErrorsRs.getString("attribute")) //
.messageNumber(userErrorsRs.getLong("message_number")) // .messageNumber(userErrorsRs.getLong("message_number")) //
.build()); .build());
} }
builder.lines(lines); builder.lines(lines);
userErrors.add(builder.build()); userErrors.add(builder.build());
return userErrors; return userErrors;
} }
} }

View File

@@ -14,8 +14,8 @@ import lombok.ToString;
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class QueryParameter { public class QueryParameter {
@JsonProperty("sql") @JsonProperty("sql")
private String sql; private String sql;
@JsonProperty("parameters") @JsonProperty("parameters")
private List<Object> parameters; private List<Object> parameters;
} }

View File

@@ -14,44 +14,44 @@ import lombok.ToString;
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class QueryResult { public class QueryResult {
@Getter @Getter
@Builder @Builder
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public static class ColumnDefinition { public static class ColumnDefinition {
@JsonProperty("index") @JsonProperty("index")
private int index; private int index;
@JsonProperty("name") @JsonProperty("name")
private String name; private String name;
@JsonProperty("type") @JsonProperty("type")
private String type; private String type;
} }
@Getter @Getter
@Builder @Builder
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public static class Row { public static class Row {
@Getter @Getter
@Builder @Builder
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public static class Column { public static class Column {
@JsonProperty("value") @JsonProperty("value")
private Object value; private Object value;
} }
@JsonProperty("columns") @JsonProperty("columns")
private List<Column> columns; private List<Column> columns;
} }
private List<ColumnDefinition> columnDefinitions; private List<ColumnDefinition> columnDefinitions;
@JsonProperty("rows") @JsonProperty("rows")
private List<Row> rows; private List<Row> rows;
@JsonProperty("userErrors") @JsonProperty("userErrors")
private List<UserError> userErrors; private List<UserError> userErrors;
@JsonProperty("exception") @JsonProperty("exception")
private String exception; private String exception;
@JsonProperty("exceptionMessage") @JsonProperty("exceptionMessage")
private String exceptionMessage; private String exceptionMessage;
} }

View File

@@ -10,5 +10,5 @@ import lombok.ToString;
@Getter @Getter
@ToString @ToString
public class Result { public class Result {
private List<UserError> userErrors; private List<UserError> userErrors;
} }

View File

@@ -14,28 +14,28 @@ import lombok.ToString;
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class UserError { public class UserError {
@Getter @Getter
@Builder @Builder
@ToString @ToString
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public static class MessageLine { public static class MessageLine {
private Long sequence; private Long sequence;
@JsonProperty("line") @JsonProperty("line")
private Long line; private Long line;
@JsonProperty("position") @JsonProperty("position")
private Long position; private Long position;
@JsonProperty("text") @JsonProperty("text")
private String text; private String text;
@JsonProperty("attribute") @JsonProperty("attribute")
private String attribute; private String attribute;
private Long messageNumber; private Long messageNumber;
} }
@JsonProperty("name") @JsonProperty("name")
private String name; private String name;
@JsonProperty("type") @JsonProperty("type")
private String type; private String type;
@JsonProperty("lines") @JsonProperty("lines")
private List<MessageLine> lines; private List<MessageLine> lines;
} }