From 9fe47f77d4af5b409866b33c6b8e4dd9966bb200 Mon Sep 17 00:00:00 2001 From: Francesco Nigro Date: Mon, 16 Apr 2018 16:52:08 +0200 Subject: [PATCH] ARTEMIS-1813 DB2 should avoid Blob to append data (cherry picked from commit 998be38348b523dda744bba10826cc35a7e4b9d7) --- .../store/drivers/AbstractJDBCDriver.java | 2 +- .../store/file/Db2SequentialFileDriver.java | 79 +++++++++++++++++++ .../jdbc/store/file/JDBCFileUtils.java | 13 ++- .../jdbc/store/sql/PropertySQLProvider.java | 2 +- .../src/main/resources/journal-sql.properties | 4 +- 5 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/Db2SequentialFileDriver.java diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java index e421a3bba9..262cf2e1a0 100644 --- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java +++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/drivers/AbstractJDBCDriver.java @@ -292,7 +292,7 @@ public abstract class AbstractJDBCDriver { } public final void setConnection(Connection connection) { - if (connection == null) { + if (this.connection == null) { this.connection = connection; } } diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/Db2SequentialFileDriver.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/Db2SequentialFileDriver.java new file mode 100644 index 0000000000..1043002f9f --- /dev/null +++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/Db2SequentialFileDriver.java @@ -0,0 +1,79 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.activemq.artemis.jdbc.store.file; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.SQLException; + +import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider; + +@SuppressWarnings("SynchronizeOnNonFinalField") +public final class Db2SequentialFileDriver extends JDBCSequentialFileFactoryDriver { + + public Db2SequentialFileDriver() { + super(); + } + + public Db2SequentialFileDriver(DataSource dataSource, SQLProvider provider) { + super(dataSource, provider); + } + + public Db2SequentialFileDriver(Connection connection, SQLProvider provider) { + super(connection, provider); + } + + @Override + protected void prepareStatements() throws SQLException { + this.deleteFile = connection.prepareStatement(sqlProvider.getDeleteFileSQL()); + this.createFile = connection.prepareStatement(sqlProvider.getInsertFileSQL(), new String[]{"ID"}); + this.selectFileByFileName = connection.prepareStatement(sqlProvider.getSelectFileByFileName()); + this.copyFileRecord = connection.prepareStatement(sqlProvider.getCopyFileRecordByIdSQL()); + this.renameFile = connection.prepareStatement(sqlProvider.getUpdateFileNameByIdSQL()); + this.readLargeObject = connection.prepareStatement(sqlProvider.getReadLargeObjectSQL()); + this.appendToLargeObject = connection.prepareStatement(sqlProvider.getAppendToLargeObjectSQL()); + this.selectFileNamesByExtension = connection.prepareStatement(sqlProvider.getSelectFileNamesByExtensionSQL()); + } + + @Override + public int writeToFile(JDBCSequentialFile file, byte[] data) throws SQLException { + if (data == null || data.length == 0) { + return 0; + } + synchronized (connection) { + try { + connection.setAutoCommit(false); + int bytesWritten; + appendToLargeObject.setBytes(1, data); + appendToLargeObject.setLong(2, file.getId()); + final int updatesFiles = appendToLargeObject.executeUpdate(); + assert updatesFiles <= 1; + connection.commit(); + if (updatesFiles == 0) { + bytesWritten = 0; + } else { + bytesWritten = data.length; + } + return bytesWritten; + } catch (SQLException e) { + connection.rollback(); + throw e; + } + } + } +} diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java index 803584b55c..478b5030eb 100644 --- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java +++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/file/JDBCFileUtils.java @@ -24,6 +24,7 @@ import java.sql.SQLException; import org.apache.activemq.artemis.jdbc.store.sql.PropertySQLProvider; import org.apache.activemq.artemis.jdbc.store.sql.SQLProvider; +import static org.apache.activemq.artemis.jdbc.store.sql.PropertySQLProvider.Factory.SQLDialect.DB2; import static org.apache.activemq.artemis.jdbc.store.sql.PropertySQLProvider.Factory.SQLDialect.POSTGRESQL; class JDBCFileUtils { @@ -32,8 +33,11 @@ class JDBCFileUtils { String jdbcConnectionUrl, SQLProvider provider) throws SQLException { final JDBCSequentialFileFactoryDriver dbDriver; - if (POSTGRESQL.equals(PropertySQLProvider.Factory.identifyDialect(driverClass))) { + final PropertySQLProvider.Factory.SQLDialect sqlDialect = PropertySQLProvider.Factory.identifyDialect(driverClass); + if (POSTGRESQL.equals(sqlDialect)) { dbDriver = new PostgresSequentialSequentialFileDriver(); + } else if (DB2.equals(sqlDialect)) { + dbDriver = new Db2SequentialFileDriver(); } else { dbDriver = new JDBCSequentialFileFactoryDriver(); } @@ -51,6 +55,8 @@ class JDBCFileUtils { } if (POSTGRESQL.equals(sqlDialect)) { dbDriver = new PostgresSequentialSequentialFileDriver(dataSource, provider); + } else if (DB2.equals(sqlDialect)) { + dbDriver = new Db2SequentialFileDriver(dataSource, provider); } else { dbDriver = new JDBCSequentialFileFactoryDriver(dataSource, provider); } @@ -59,9 +65,12 @@ class JDBCFileUtils { static JDBCSequentialFileFactoryDriver getDBFileDriver(Connection connection, SQLProvider provider) throws SQLException { JDBCSequentialFileFactoryDriver dbDriver; - if (POSTGRESQL.equals(PropertySQLProvider.Factory.investigateDialect(connection))) { + final PropertySQLProvider.Factory.SQLDialect sqlDialect = PropertySQLProvider.Factory.investigateDialect(connection); + if (POSTGRESQL.equals(sqlDialect)) { dbDriver = new PostgresSequentialSequentialFileDriver(connection, provider); dbDriver.setConnection(connection); + } else if (DB2.equals(sqlDialect)) { + dbDriver = new Db2SequentialFileDriver(connection, provider); } else { dbDriver = new JDBCSequentialFileFactoryDriver(connection, provider); } diff --git a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/sql/PropertySQLProvider.java b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/sql/PropertySQLProvider.java index 47530a8ca2..2f29cf92ae 100644 --- a/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/sql/PropertySQLProvider.java +++ b/artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/sql/PropertySQLProvider.java @@ -374,7 +374,7 @@ public class PropertySQLProvider implements SQLProvider { if (dialect == null) { logger.warnf("Unable to detect database dialect from connection metadata or JDBC driver name."); } else { - logger.debugf("Detect database dialect as '%s'."); + logger.debugf("Detect database dialect as '%s'.", dialect); } } catch (Exception e) { logger.debug("Unable to read JDBC metadata.", e); diff --git a/artemis-jdbc-store/src/main/resources/journal-sql.properties b/artemis-jdbc-store/src/main/resources/journal-sql.properties index 2ed56be2b4..b526b975b7 100644 --- a/artemis-jdbc-store/src/main/resources/journal-sql.properties +++ b/artemis-jdbc-store/src/main/resources/journal-sql.properties @@ -86,4 +86,6 @@ max-blob-size.oracle=4294967296 table-names-case.oracle=upper # DB2 SQL statements -create-file-table.db2=CREATE TABLE %s (ID BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), FILENAME VARCHAR(255), EXTENSION VARCHAR(10), DATA BLOB, PRIMARY KEY(ID)) \ No newline at end of file +max-blob-size.db2=2147483647 +create-file-table.db2=CREATE TABLE %s (ID BIGINT GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1), FILENAME VARCHAR(255), EXTENSION VARCHAR(10), DATA BLOB(2G), PRIMARY KEY(ID)) +append-to-file.db2=UPDATE %s SET DATA = (DATA || ?) WHERE ID=? \ No newline at end of file