Author: reschke
Date: Tue Nov 24 15:40:57 2015
New Revision: 1716178
URL: http://svn.apache.org/viewvc?rev=1716178&view=rev
Log:
OAK-3676: RDBDocumentStore on SQLServer: append logic creates many different
PreparedStatements
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java?rev=1716178&r1=1716177&r2=1716178&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreDB.java
Tue Nov 24 15:40:57 2015
@@ -40,6 +40,7 @@ import org.slf4j.LoggerFactory;
* Defines variation in the capabilities of different RDBs.
*/
public enum RDBDocumentStoreDB {
+
DEFAULT("default") {
},
@@ -237,9 +238,22 @@ public enum RDBDocumentStoreDB {
}
@Override
- public String getConcatQueryString(int dataOctetLimit, int dataLength)
{
- return "CONCAT(DATA, ?)";
+ public PreparedStatementComponent getConcatQuery(final String
appendData, final int dataOctetLimit) {
+ return new PreparedStatementComponent() {
+
+ @Override
+ public String getStatementComponent() {
+ return "CONCAT(DATA, ?)";
+ }
+
+ @Override
+ public int setParameters(PreparedStatement stmt, int
startIndex) throws SQLException {
+ stmt.setString(startIndex++, appendData);
+ return startIndex;
+ }
+ };
}
+
@Override
public String getAdditionalDiagnostics(RDBConnectionHandler ch, String
tableName) {
Connection con = null;
@@ -293,14 +307,23 @@ public enum RDBDocumentStoreDB {
}
@Override
- public String getConcatQueryString(int dataOctetLimit, int dataLength)
{
- /*
- * To avoid truncation when concatenating force an error when limit
- * is above the octet limit
- */
- return "CASE WHEN LEN(DATA) < " + (dataOctetLimit - dataLength) +
" THEN (DATA + CAST(? AS nvarchar(" + dataOctetLimit
- + "))) ELSE (DATA + CAST(DATA AS nvarchar(max))) END";
+ public PreparedStatementComponent getConcatQuery(final String
appendData, final int dataOctetLimit) {
+ return new PreparedStatementComponent() {
+
+ @Override
+ // this statement ensures that SQL server will generate an
exception on overflow
+ public String getStatementComponent() {
+ return "CASE WHEN LEN(DATA) < ? THEN (DATA + CAST(? AS
nvarchar(" + dataOctetLimit
+ + "))) ELSE (DATA + CAST(DATA AS nvarchar(max)))
END";
+ }
+ @Override
+ public int setParameters(PreparedStatement stmt, int
startIndex) throws SQLException {
+ stmt.setInt(startIndex++, dataOctetLimit -
appendData.length());
+ stmt.setString(startIndex++, appendData);
+ return startIndex;
+ }
+ };
}
@Override
@@ -346,6 +369,29 @@ public enum RDBDocumentStoreDB {
FETCHFIRST, LIMIT, TOP
};
+
+ /**
+ * Provides a component for a {@link PreparedStatement} and a method for
setting the
+ * parameters within this component
+ */
+ public interface PreparedStatementComponent {
+
+ /**
+ * @return a string suitable for inclusion into a {@link
PreparedStatement}
+ */
+ @Nonnull
+ public String getStatementComponent();
+
+ /**
+ * Set the parameters need by the statement component returned by
{@link #getStatementComponent()}
+ * @param stmt the statement
+ * @param index of first parameter to set
+ * @return index of next parameter to set
+ * @throws SQLException
+ */
+ public int setParameters(PreparedStatement stmt, int startIndex)
throws SQLException;
+ }
+
/**
* Check the database brand and version
*/
@@ -378,15 +424,26 @@ public enum RDBDocumentStoreDB {
* Returns the CONCAT function or its equivalent function or sub-query.
Note
* that the function MUST NOT cause a truncated value to be written!
*
+ * @param appendData
+ * string to be inserted
* @param dataOctetLimit
* expected capacity of data column
- * @param dataLength
- * length of string to be inserted
- *
- * @return the concat query string
*/
- public String getConcatQueryString(int dataOctetLimit, int dataLength) {
- return "DATA || CAST(? AS varchar(" + dataOctetLimit + "))";
+ public PreparedStatementComponent getConcatQuery(final String appendData,
final int dataOctetLimit) {
+
+ return new PreparedStatementComponent() {
+
+ @Override
+ public String getStatementComponent() {
+ return "DATA || CAST(? AS varchar(" + dataOctetLimit + "))";
+ }
+
+ @Override
+ public int setParameters(PreparedStatement stmt, int startIndex)
throws SQLException {
+ stmt.setString(startIndex++, appendData);
+ return startIndex;
+ }
+ };
}
/**
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java?rev=1716178&r1=1716177&r2=1716178&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
(original)
+++
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java
Tue Nov 24 15:40:57 2015
@@ -43,6 +43,7 @@ import org.apache.jackrabbit.oak.plugins
import org.apache.jackrabbit.oak.plugins.document.UpdateOp.Key;
import
org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStore.RDBTableMetaData;
import
org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStoreDB.FETCHFIRSTSYNTAX;
+import
org.apache.jackrabbit.oak.plugins.document.rdb.RDBDocumentStoreDB.PreparedStatementComponent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,11 +72,13 @@ public class RDBDocumentStoreJDBC {
public boolean appendingUpdate(Connection connection, RDBTableMetaData
tmd, String id, Long modified,
boolean setModifiedConditionally, Boolean hasBinary, Boolean
deletedOnce, Long modcount, Long cmodcount,
Long oldmodcount, String appendData) throws SQLException {
+ String appendDataWithComma = "," + appendData;
+ PreparedStatementComponent stringAppend =
this.dbInfo.getConcatQuery(appendDataWithComma, tmd.getDataLimitInOctets());
StringBuilder t = new StringBuilder();
t.append("update " + tmd.getName() + " set ");
t.append(setModifiedConditionally ? "MODIFIED = case when ? > MODIFIED
then ? else MODIFIED end, " : "MODIFIED = ?, ");
t.append("HASBINARY = ?, DELETEDONCE = ?, MODCOUNT = ?, CMODCOUNT = ?,
DSIZE = DSIZE + ?, ");
- t.append("DATA = " +
this.dbInfo.getConcatQueryString(tmd.getDataLimitInOctets(),
appendData.length()) + " ");
+ t.append("DATA = " + stringAppend.getStatementComponent() + " ");
t.append("where ID = ?");
if (oldmodcount != null) {
t.append(" and MODCOUNT = ?");
@@ -91,8 +94,8 @@ public class RDBDocumentStoreJDBC {
stmt.setObject(si++, deletedOnce ? 1 : 0, Types.SMALLINT);
stmt.setObject(si++, modcount, Types.BIGINT);
stmt.setObject(si++, cmodcount == null ? Long.valueOf(0) :
cmodcount, Types.BIGINT);
- stmt.setObject(si++, 1 + appendData.length(), Types.BIGINT);
- stmt.setString(si++, "," + appendData);
+ stmt.setObject(si++, appendDataWithComma.length(), Types.BIGINT);
+ si = stringAppend.setParameters(stmt, si);
setIdInStatement(tmd, stmt, si++, id);
if (oldmodcount != null) {
@@ -110,11 +113,13 @@ public class RDBDocumentStoreJDBC {
public boolean batchedAppendingUpdate(Connection connection,
RDBTableMetaData tmd, List<String> ids, Long modified,
boolean setModifiedConditionally, String appendData) throws
SQLException {
+ String appendDataWithComma = "," + appendData;
+ PreparedStatementComponent stringAppend =
this.dbInfo.getConcatQuery(appendDataWithComma, tmd.getDataLimitInOctets());
StringBuilder t = new StringBuilder();
t.append("update " + tmd.getName() + " set ");
t.append(setModifiedConditionally ? "MODIFIED = case when ? > MODIFIED
then ? else MODIFIED end, " : "MODIFIED = ?, ");
t.append("MODCOUNT = MODCOUNT + 1, DSIZE = DSIZE + ?, ");
- t.append("DATA = " +
this.dbInfo.getConcatQueryString(tmd.getDataLimitInOctets(),
appendData.length() + 1) + " ");
+ t.append("DATA = " + stringAppend.getStatementComponent() + " ");
t.append("where ID in (");
for (int i = 0; i < ids.size(); i++) {
if (i != 0) {
@@ -130,8 +135,8 @@ public class RDBDocumentStoreJDBC {
if (setModifiedConditionally) {
stmt.setObject(si++, modified, Types.BIGINT);
}
- stmt.setObject(si++, 1 + appendData.length(), Types.BIGINT);
- stmt.setString(si++, "," + appendData);
+ stmt.setObject(si++, appendDataWithComma.length(), Types.BIGINT);
+ si = stringAppend.setParameters(stmt, si);
for (String id : ids) {
setIdInStatement(tmd, stmt, si++, id);
}