Author: reschke Date: Fri Nov 10 15:39:38 2017 New Revision: 1814876 URL: http://svn.apache.org/viewvc?rev=1814876&view=rev Log: OAK-6927: RDBDocumentStore: allow schema evolution part 4: read VERSION column and let RDBRow handle it
Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBExport.java jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBRow.java jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializerTest.java Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java?rev=1814876&r1=1814875&r2=1814876&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStoreJDBC.java Fri Nov 10 15:39:38 2017 @@ -407,26 +407,34 @@ public class RDBDocumentStoreJDBC { List<RDBRow> result = new ArrayList<RDBRow>(); long dataTotal = 0, bdataTotal = 0; PreparedStatement stmt = null; + String fields; + if (tmd.hasVersion()) { + fields = "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, VERSION, DATA, BDATA"; + } else { + fields = "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA"; + } ResultSet rs = null; try { - stmt = prepareQuery(connection, tmd, "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA", minId, + stmt = prepareQuery(connection, tmd, fields, minId, maxId, excludeKeyPatterns, conditions, limit, "ID"); rs = stmt.executeQuery(); while (rs.next() && result.size() < limit) { - String id = getIdFromRS(tmd, rs, 1); + int field = 1; + String id = getIdFromRS(tmd, rs, field++); if ((minId != null && id.compareTo(minId) < 0) || (maxId != null && id.compareTo(maxId) > 0)) { throw new DocumentStoreException( "unexpected query result: '" + minId + "' < '" + id + "' < '" + maxId + "' - broken DB collation?"); } - long modified = readLongFromResultSet(rs, 2); - long modcount = readLongFromResultSet(rs, 3); - long cmodcount = readLongFromResultSet(rs, 4); - Long hasBinary = readLongOrNullFromResultSet(rs, 5); - Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, 6); - String data = rs.getString(7); - byte[] bdata = rs.getBytes(8); - result.add(new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, data, bdata)); + long modified = readLongFromResultSet(rs, field++); + long modcount = readLongFromResultSet(rs, field++); + long cmodcount = readLongFromResultSet(rs, field++); + Long hasBinary = readLongOrNullFromResultSet(rs, field++); + Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, field++); + long schemaVersion = tmd.hasVersion() ? readLongFromResultSet(rs, field++) : 0; + String data = rs.getString(field++); + byte[] bdata = rs.getBytes(field++); + result.add(new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, schemaVersion, data, bdata)); dataTotal += data.length(); bdataTotal += bdata == null ? 0 : bdata.length; } @@ -523,8 +531,13 @@ public class RDBDocumentStoreJDBC { this.ch = ch; this.connection = ch.getROConnection(); this.tmd = tmd; - this.stmt = prepareQuery(connection, tmd, "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA", - minId, maxId, excludeKeyPatterns, conditions, limit, sortBy); + String fields; + if (tmd.hasVersion()) { + fields = "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, VERSION, DATA, BDATA"; + } else { + fields = "ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA"; + } + this.stmt = prepareQuery(connection, tmd, fields, minId, maxId, excludeKeyPatterns, conditions, limit, sortBy); this.rs = stmt.executeQuery(); this.next = internalNext(); this.message = String.format("Query on %s with params minid '%s' maxid '%s' excludeKeyPatterns %s conditions %s.", @@ -563,15 +576,17 @@ public class RDBDocumentStoreJDBC { long start = System.currentTimeMillis(); try { if (this.rs.next()) { - String id = getIdFromRS(this.tmd, this.rs, 1); - long modified = readLongFromResultSet(this.rs, 2); - long modcount = readLongFromResultSet(this.rs, 3); - long cmodcount = readLongFromResultSet(this.rs, 4); - Long hasBinary = readLongOrNullFromResultSet(this.rs, 5); - Boolean deletedOnce = readBooleanOrNullFromResultSet(this.rs, 6); - String data = this.rs.getString(7); - byte[] bdata = this.rs.getBytes(8); - return new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, data, bdata); + int field = 1; + String id = getIdFromRS(this.tmd, this.rs, field++); + long modified = readLongFromResultSet(this.rs, field++); + long modcount = readLongFromResultSet(this.rs, field++); + long cmodcount = readLongFromResultSet(this.rs, field++); + Long hasBinary = readLongOrNullFromResultSet(this.rs, field++); + Boolean deletedOnce = readBooleanOrNullFromResultSet(this.rs, field++); + long schemaVersion = tmd.hasVersion() ? readLongFromResultSet(rs, field++) : 0; + String data = this.rs.getString(field++); + byte[] bdata = this.rs.getBytes(field++); + return new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, schemaVersion, data, bdata); } else { this.rs = closeResultSet(this.rs); this.stmt = closeStatement(this.stmt); @@ -684,7 +699,11 @@ public class RDBDocumentStoreJDBC { for (List<String> keys : Iterables.partition(allKeys, RDBJDBCTools.MAX_IN_CLAUSE)) { PreparedStatementComponent inClause = RDBJDBCTools.createInStatement("ID", keys, tmd.isIdBinary()); StringBuilder query = new StringBuilder(); - query.append("select ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA from "); + if (tmd.hasVersion()) { + query.append("select ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, VERSION, DATA, BDATA from "); + } else { + query.append("select ID, MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, DATA, BDATA from "); + } query.append(tmd.getName()); query.append(" where ").append(inClause.getStatementComponent()); @@ -696,16 +715,17 @@ public class RDBDocumentStoreJDBC { rs = stmt.executeQuery(); while (rs.next()) { - int col = 1; - String id = getIdFromRS(tmd, rs, col++); - long modified = readLongFromResultSet(rs, col++); - long modcount = readLongFromResultSet(rs, col++); - long cmodcount = readLongFromResultSet(rs, col++); - Long hasBinary = readLongOrNullFromResultSet(rs, col++); - Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, col++); - String data = rs.getString(col++); - byte[] bdata = rs.getBytes(col++); - RDBRow row = new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, data, bdata); + int field = 1; + String id = getIdFromRS(tmd, rs, field++); + long modified = readLongFromResultSet(rs, field++); + long modcount = readLongFromResultSet(rs, field++); + long cmodcount = readLongFromResultSet(rs, field++); + Long hasBinary = readLongOrNullFromResultSet(rs, field++); + Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, field++); + long schemaVersion = tmd.hasVersion() ? readLongFromResultSet(rs, field++) : 0; + String data = rs.getString(field++); + byte[] bdata = rs.getBytes(field++); + RDBRow row = new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, schemaVersion, data, bdata); rows.add(row); } } catch (SQLException ex) { @@ -735,7 +755,14 @@ public class RDBDocumentStoreJDBC { boolean useCaseStatement = lastmodcount != -1 && lastmodified >= 1; StringBuffer sql = new StringBuffer(); - sql.append("select MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, "); + String fields; + if (tmd.hasVersion()) { + fields = "MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, VERSION, "; + } else { + fields = "MODIFIED, MODCOUNT, CMODCOUNT, HASBINARY, DELETEDONCE, "; + } + + sql.append("select ").append(fields); if (useCaseStatement) { // the case statement causes the actual row data not to be // sent in case we already have it @@ -762,14 +789,16 @@ public class RDBDocumentStoreJDBC { rs = stmt.executeQuery(); if (rs.next()) { - long modified = readLongFromResultSet(rs, 1); - long modcount = readLongFromResultSet(rs, 2); - long cmodcount = readLongFromResultSet(rs, 3); - Long hasBinary = readLongOrNullFromResultSet(rs, 4); - Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, 5); - String data = rs.getString(6); - byte[] bdata = rs.getBytes(7); - return new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, data, bdata); + int field = 1; + long modified = readLongFromResultSet(rs, field++); + long modcount = readLongFromResultSet(rs, field++); + long cmodcount = readLongFromResultSet(rs, field++); + Long hasBinary = readLongOrNullFromResultSet(rs, field++); + Boolean deletedOnce = readBooleanOrNullFromResultSet(rs, field++); + long schemaVersion = tmd.hasVersion() ? readLongFromResultSet(rs, field++) : 0; + String data = rs.getString(field++); + byte[] bdata = rs.getBytes(field++); + return new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, schemaVersion, data, bdata); } else { return null; } Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBExport.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBExport.java?rev=1814876&r1=1814875&r2=1814876&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBExport.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBExport.java Fri Nov 10 15:39:38 2017 @@ -219,7 +219,7 @@ public class RDBExport { try { RDBRow row = new RDBRow(id, "1".equals(shasbinary) ? 1L : 0L, "1".equals(sdeletedonce), smodified.length() == 0 ? 0 : Long.parseLong(smodified), Long.parseLong(smodcount), - Long.parseLong(scmodcount), sdata, bytes); + Long.parseLong(scmodcount), -1L, sdata, bytes); StringBuilder fulljson = dumpRow(ser, id, row); if (format == Format.CSV) { out.println(asCSV(fieldNames, fulljson)); @@ -321,7 +321,7 @@ public class RDBExport { String data = rs.getString("DATA"); byte[] bdata = rs.getBytes("BDATA"); - RDBRow row = new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, data, bdata); + RDBRow row = new RDBRow(id, hasBinary, deletedOnce, modified, modcount, cmodcount, -1L, data, bdata); StringBuilder fulljson = dumpRow(ser, id, row); if (format == Format.CSV) { out.println(asCSV(fieldNames, fulljson)); Modified: jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBRow.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBRow.java?rev=1814876&r1=1814875&r2=1814876&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBRow.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBRow.java Fri Nov 10 15:39:38 2017 @@ -22,9 +22,8 @@ import javax.annotation.Nonnull; /** * Container for the information in a RDB database column. * <p> - * Note that the String "data" and the byte[] "bdata" may be null - * when the SQL SELECT request was conditional on "modcount" being - * unchanged. + * Note that the String "data" and the byte[] "bdata" may be {@code null} when + * the SQL SELECT request was conditional on "modcount" being unchanged. */ public class RDBRow { @@ -34,16 +33,19 @@ public class RDBRow { private final Long hasBinaryProperties; private final Boolean deletedOnce; private final long modified, modcount, cmodcount; + private final long schemaVersion; private final String data; private final byte[] bdata; - public RDBRow(String id, Long hasBinaryProperties, Boolean deletedOnce, Long modified, Long modcount, Long cmodcount, String data, byte[] bdata) { + public RDBRow(String id, Long hasBinaryProperties, Boolean deletedOnce, Long modified, Long modcount, Long cmodcount, + Long schemaVersion, String data, byte[] bdata) { this.id = id; this.hasBinaryProperties = hasBinaryProperties; this.deletedOnce = deletedOnce; this.modified = modified != null ? modified.longValue() : LONG_UNSET; this.modcount = modcount != null ? modcount.longValue() : LONG_UNSET; this.cmodcount = cmodcount != null ? cmodcount.longValue() : LONG_UNSET; + this.schemaVersion = schemaVersion != null ? schemaVersion.longValue() : LONG_UNSET; this.data = data; this.bdata = bdata; } @@ -89,6 +91,13 @@ public class RDBRow { return cmodcount; } + /** + * @return {@link #LONG_UNSET} when not set in the database + */ + public long getSchemaVersion() { + return schemaVersion; + } + @CheckForNull public byte[] getBdata() { return bdata; Modified: jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializerTest.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializerTest.java?rev=1814876&r1=1814875&r2=1814876&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializerTest.java (original) +++ jackrabbit/oak/trunk/oak-store-document/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentSerializerTest.java Fri Nov 10 15:39:38 2017 @@ -56,7 +56,7 @@ public class RDBDocumentSerializerTest { @Test public void testSimpleString() { - RDBRow row = new RDBRow("_foo", 1L, true, 1l, 2l, 3l, "{}", null); + RDBRow row = new RDBRow("_foo", 1L, true, 1l, 2l, 3l, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(true, doc.hasBinary()); @@ -66,7 +66,7 @@ public class RDBDocumentSerializerTest { @Test public void testNoSysprops() { - RDBRow row = new RDBRow("_foo", null, null, 1l, 2l, 3l, "{}", null); + RDBRow row = new RDBRow("_foo", null, null, 1l, 2l, 3l, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); @@ -78,7 +78,7 @@ public class RDBDocumentSerializerTest { @Test public void testSimpleBlob() throws UnsupportedEncodingException { - RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, "\"blob\"", "{}".getBytes("UTF-8")); + RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, "\"blob\"", "{}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals(false, doc.hasBinary()); @@ -87,7 +87,7 @@ public class RDBDocumentSerializerTest { @Test public void testSimpleBlob2() throws UnsupportedEncodingException { - RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, "\"blob\"", + RDBRow row = new RDBRow("_foo", 0L, false, 1l, 2l, 3l, 0L, "\"blob\"", "{\"s\":\"string\", \"b\":true, \"i\":1}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); @@ -101,7 +101,7 @@ public class RDBDocumentSerializerTest { @Test public void testSimpleBoth() throws UnsupportedEncodingException { try { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, "{}", "{}".getBytes("UTF-8")); + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "{}", "{}".getBytes("UTF-8")); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { @@ -110,7 +110,7 @@ public class RDBDocumentSerializerTest { @Test public void testBlobAndDiff() throws UnsupportedEncodingException { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "\"blob\", [[\"=\", \"foo\", \"bar\"],[\"M\", \"m1\", 1],[\"M\", \"m2\", 3]]", "{\"m1\":2, \"m2\":2}".getBytes("UTF-8")); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); @@ -122,7 +122,7 @@ public class RDBDocumentSerializerTest { @Test public void testBlobAndDiffBorked() throws UnsupportedEncodingException { try { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, "[[\"\", \"\", \"\"]]", "{}".getBytes("UTF-8")); + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "[[\"\", \"\", \"\"]]", "{}".getBytes("UTF-8")); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { @@ -131,7 +131,7 @@ public class RDBDocumentSerializerTest { @Test public void testNullModified() throws UnsupportedEncodingException { - RDBRow row = new RDBRow("_foo", 1L, true, null, 2l, 3l, "{}", null); + RDBRow row = new RDBRow("_foo", 1L, true, null, 2l, 3l, 0L, "{}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertNull(doc.getModified()); } @@ -139,7 +139,7 @@ public class RDBDocumentSerializerTest { @Test public void testBrokenJSONTrailingComma() throws UnsupportedEncodingException { try { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, "{ \"x\" : 1, }", null); + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "{ \"x\" : 1, }", null); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { @@ -149,7 +149,7 @@ public class RDBDocumentSerializerTest { @Test public void testBrokenJSONUnquotedIdentifier() throws UnsupportedEncodingException { try { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, "{ x : 1, }", null); + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "{ x : 1, }", null); this.ser.fromRow(Collection.NODES, row); fail("should fail"); } catch (DocumentStoreException expected) { @@ -158,7 +158,7 @@ public class RDBDocumentSerializerTest { @Test public void testSimpleStringNonAscii() { - RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, "{\"x\":\"\u20ac\uD834\uDD1E\"}", null); + RDBRow row = new RDBRow("_foo", 1L, false, 1l, 2l, 3l, 0L, "{\"x\":\"\u20ac\uD834\uDD1E\"}", null); NodeDocument doc = this.ser.fromRow(Collection.NODES, row); assertEquals("_foo", doc.getId()); assertEquals("\u20ac\uD834\uDD1E", doc.get("x"));