Search in sources :

Example 11 with CloudSpannerSQLException

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());
}
Also used : CloudSpannerDriver(nl.topicus.jdbc.CloudSpannerDriver) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException)

Example 12 with CloudSpannerSQLException

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;
}
Also used : ArrayList(java.util.ArrayList) StringReader(java.io.StringReader) IOException(java.io.IOException) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException) StreamTokenizer(java.io.StreamTokenizer)

Example 13 with CloudSpannerSQLException

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();
}
Also used : TableKeyMetaData(nl.topicus.jdbc.MetaDataStore.TableKeyMetaData) TransactionCallable(com.google.cloud.spanner.TransactionRunner.TransactionCallable) ReadContext(com.google.cloud.spanner.ReadContext) SQLFeatureNotSupportedException(java.sql.SQLFeatureNotSupportedException) DatabaseClient(com.google.cloud.spanner.DatabaseClient) PlainSelect(net.sf.jsqlparser.statement.select.PlainSelect) TableKeyMetaData(nl.topicus.jdbc.MetaDataStore.TableKeyMetaData) SQLException(java.sql.SQLException) ResultSet(java.sql.ResultSet) Column(net.sf.jsqlparser.schema.Column) Update(net.sf.jsqlparser.statement.update.Update) SQLWarning(java.sql.SQLWarning) Code(com.google.rpc.Code) TransactionContext(com.google.cloud.spanner.TransactionContext) CloudSpannerConnection(nl.topicus.jdbc.CloudSpannerConnection) Table(net.sf.jsqlparser.schema.Table) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException) Collectors(java.util.stream.Collectors) AbstractCloudSpannerFetcher(nl.topicus.jdbc.AbstractCloudSpannerFetcher) SpannerException(com.google.cloud.spanner.SpannerException) List(java.util.List) Select(net.sf.jsqlparser.statement.select.Select) Statement(java.sql.Statement) CloudSpannerDriver(nl.topicus.jdbc.CloudSpannerDriver) SelectVisitorAdapter(net.sf.jsqlparser.statement.select.SelectVisitorAdapter) FromItemVisitorAdapter(net.sf.jsqlparser.statement.select.FromItemVisitorAdapter) Column(net.sf.jsqlparser.schema.Column) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException)

Example 14 with CloudSpannerSQLException

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);
        }
    }
}
Also used : CloudSpannerConnection(nl.topicus.jdbc.CloudSpannerConnection) Connection(java.sql.Connection) PreparedStatement(java.sql.PreparedStatement) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException) SpannerException(com.google.cloud.spanner.SpannerException) SQLException(java.sql.SQLException) ResultSetMetaData(java.sql.ResultSetMetaData) ResultSet(java.sql.ResultSet) SpannerException(com.google.cloud.spanner.SpannerException)

Example 15 with CloudSpannerSQLException

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();
}
Also used : Expression(net.sf.jsqlparser.expression.Expression) Column(net.sf.jsqlparser.schema.Column) WriteBuilder(com.google.cloud.spanner.Mutation.WriteBuilder) CloudSpannerSQLException(nl.topicus.jdbc.exception.CloudSpannerSQLException)

Aggregations

CloudSpannerSQLException (nl.topicus.jdbc.exception.CloudSpannerSQLException)18 Select (net.sf.jsqlparser.statement.select.Select)6 SQLException (java.sql.SQLException)5 JSQLParserException (net.sf.jsqlparser.JSQLParserException)5 Code (com.google.rpc.Code)4 Statement (net.sf.jsqlparser.statement.Statement)4 PlainSelect (net.sf.jsqlparser.statement.select.PlainSelect)4 SpannerException (com.google.cloud.spanner.SpannerException)3 TokenMgrError (net.sf.jsqlparser.parser.TokenMgrError)3 Column (net.sf.jsqlparser.schema.Column)3 SubSelect (net.sf.jsqlparser.statement.select.SubSelect)3 CloudSpannerConnection (nl.topicus.jdbc.CloudSpannerConnection)3 CloudSpannerDriver (nl.topicus.jdbc.CloudSpannerDriver)3 WriteBuilder (com.google.cloud.spanner.Mutation.WriteBuilder)2 ReadContext (com.google.cloud.spanner.ReadContext)2 Connection (java.sql.Connection)2 PreparedStatement (java.sql.PreparedStatement)2 ResultSet (java.sql.ResultSet)2 List (java.util.List)2 Collectors (java.util.stream.Collectors)2