use of nl.topicus.jdbc.exception.CloudSpannerSQLException in project spanner-jdbc by olavloite.
the class CloudSpannerIT method createConnection.
private Connection createConnection() throws SQLException {
try {
Class.forName(CloudSpannerDriver.class.getName());
} catch (ClassNotFoundException e) {
throw new CloudSpannerSQLException("Could not load JDBC driver", Code.UNKNOWN, e);
}
StringBuilder url = new StringBuilder("jdbc:cloudspanner://localhost");
url.append(";Project=").append(projectId);
url.append(";Instance=").append(instanceId);
url.append(";Database=").append(DATABASE_ID);
url.append(";PvtKeyPath=").append(credentialsPath);
return DriverManager.getConnection(url.toString());
}
use of nl.topicus.jdbc.exception.CloudSpannerSQLException in project spanner-jdbc by olavloite.
the class DDLStatement method getTokens.
private static List<String> getTokens(String sql, int maxTokens) throws SQLException {
List<String> res = new ArrayList<>(maxTokens);
int tokenNumber = 0;
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(sql));
tokenizer.eolIsSignificant(false);
tokenizer.wordChars('_', '_');
tokenizer.wordChars('"', '"');
tokenizer.wordChars('\'', '\'');
tokenizer.quoteChar('`');
try {
while (tokenizer.nextToken() != StreamTokenizer.TT_EOF && (tokenizer.ttype == StreamTokenizer.TT_WORD || tokenizer.ttype == '`') && tokenNumber < maxTokens) {
res.add(tokenizer.sval);
tokenNumber++;
}
} catch (IOException e) {
throw new CloudSpannerSQLException("Could not parse DDL statement '" + sql + "'. Error: " + e.getMessage(), Code.INVALID_ARGUMENT, e);
}
return res;
}
use of nl.topicus.jdbc.exception.CloudSpannerSQLException in project spanner-jdbc by olavloite.
the class AbstractCloudSpannerStatement method createInsertSelectOnDuplicateKeyUpdateStatement.
/**
* Transform the given UPDATE-statement into an "INSERT INTO TAB1 (...)
* SELECT ... FROM TAB1 WHERE ... ON DUPLICATE KEY UPDATE"
*
* @param update
* The UPDATE-statement
* @return An SQL-statement equal to the UPDATE-statement but in INSERT form
* @throws SQLException
* if a database exception occurs while getting the table meta
* data or if the statement tries to update the primary key
* value
*/
protected String createInsertSelectOnDuplicateKeyUpdateStatement(Update update) throws SQLException {
String tableName = unquoteIdentifier(update.getTables().get(0).getName());
TableKeyMetaData table = getConnection().getTable(tableName);
List<String> keyColumns = table.getKeyColumns();
List<String> updateColumns = update.getColumns().stream().map(Column::getColumnName).map(String::toUpperCase).collect(Collectors.toList());
List<String> quotedKeyColumns = keyColumns.stream().map(this::quoteIdentifier).collect(Collectors.toList());
List<String> quotedAndQualifiedKeyColumns = keyColumns.stream().map(x -> quoteIdentifier(tableName) + "." + quoteIdentifier(x)).collect(Collectors.toList());
List<String> quotedUpdateColumns = updateColumns.stream().map(this::quoteIdentifier).collect(Collectors.toList());
List<String> expressions = update.getExpressions().stream().map(Object::toString).collect(Collectors.toList());
if (updateColumns.stream().anyMatch(keyColumns::contains)) {
String invalidCols = updateColumns.stream().filter(keyColumns::contains).collect(Collectors.joining());
throw new CloudSpannerSQLException("UPDATE of a primary key value is not allowed, cannot UPDATE the column(s) " + invalidCols, Code.INVALID_ARGUMENT);
}
StringBuilder res = new StringBuilder();
res.append("INSERT INTO ").append(quoteIdentifier(tableName)).append("\n(");
res.append(String.join(", ", quotedKeyColumns)).append(", ");
res.append(String.join(", ", quotedUpdateColumns)).append(")");
res.append("\nSELECT ").append(String.join(", ", quotedAndQualifiedKeyColumns)).append(", ");
res.append(String.join(", ", expressions));
res.append("\nFROM ").append(quoteIdentifier(tableName));
if (update.getWhere() != null)
res.append("\n").append("WHERE ").append(update.getWhere().toString());
res.append("\nON DUPLICATE KEY UPDATE");
return res.toString();
}
use of nl.topicus.jdbc.exception.CloudSpannerSQLException in project spanner-jdbc by olavloite.
the class AbstractTablePartWorker method genericRun.
protected void genericRun() throws SQLException {
String unquotedTableName = CloudSpannerDriver.unquoteIdentifier(getTable().getName());
List<String> columnNamesList = getColumnNames();
long batchSize = ConverterUtils.calculateActualBatchSize(columnNamesList.size(), connection, null, null, unquotedTableName);
boolean isExtendedMode = isExtendedMode(batchSize);
boolean wasAutocommit = connection.getAutoCommit();
if (!isExtendedMode && wasAutocommit) {
connection.setAutoCommit(false);
}
try (Connection destination = isExtendedMode ? connection.createCopyConnection() : null) {
if (destination != null) {
destination.setAutoCommit(false);
}
String sql = createSQL();
try (PreparedStatement statement = destination == null ? connection.prepareStatement(sql) : destination.prepareStatement(sql)) {
if (operation == DMLOperation.UPDATE) {
// Set force update
((CloudSpannerPreparedStatement) statement).setForceUpdate(true);
}
CloudSpannerPreparedStatement selectStatement = connection.prepareStatement(select.toString());
for (int i = 1; i <= parameters.getHighestIndex(); i++) {
selectStatement.setObject(i, parameters.getParameter(i));
}
try (ResultSet rs = selectStatement.executeQuery()) {
ResultSetMetaData metadata = rs.getMetaData();
while (rs.next()) {
for (int index = 1; index <= metadata.getColumnCount(); index++) {
Object object = rs.getObject(index);
statement.setObject(index, object);
}
statement.executeUpdate();
recordCount++;
if (destination != null && recordCount % batchSize == 0)
destination.commit();
}
}
}
if (destination != null) {
destination.commit();
}
if (wasAutocommit && !isExtendedMode) {
connection.commit();
connection.setAutoCommit(true);
}
} catch (SpannerException e) {
throw new CloudSpannerSQLException(e);
} catch (CloudSpannerSQLException e) {
throw e;
} catch (Exception e) {
throw new CloudSpannerSQLException(e.getMessage(), Code.UNKNOWN, e);
} finally {
if (wasAutocommit && !isExtendedMode) {
connection.rollback();
connection.setAutoCommit(true);
}
}
}
use of nl.topicus.jdbc.exception.CloudSpannerSQLException in project spanner-jdbc by olavloite.
the class CloudSpannerPreparedStatement method createUpdateMutation.
private Mutation createUpdateMutation(Update update, boolean generateParameterMetaData) throws SQLException {
if (update.getTables().isEmpty())
throw new CloudSpannerSQLException("No table found in update statement", Code.INVALID_ARGUMENT);
if (update.getTables().size() > 1)
throw new CloudSpannerSQLException("Update statements for multiple tables at once are not supported", Code.INVALID_ARGUMENT);
String table = unquoteIdentifier(update.getTables().get(0).getFullyQualifiedName());
getParameterStore().setTable(table);
List<Expression> expressions = update.getExpressions();
WriteBuilder builder = Mutation.newUpdateBuilder(table);
int index = 0;
for (Column col : update.getColumns()) {
String columnName = unquoteIdentifier(col.getFullyQualifiedName());
expressions.get(index).accept(new ValueBinderExpressionVisitorAdapter<>(getParameterStore(), builder.set(columnName), columnName));
index++;
}
visitUpdateWhereClause(update.getWhere(), builder, generateParameterMetaData);
return builder.build();
}
Aggregations