Skip to content
Snippets Groups Projects
Commit 73ec3b1e authored by Andy Kruth's avatar Andy Kruth
Browse files

[jdbc] solidified field ordering

Changes to account for the field ordering. Now correctly inserting and
updating field values so that they can be verified when using
dataintegrity=true.

Fixes #132
parent b7d22498
No related branches found
No related tags found
No related merge requests found
...@@ -83,6 +83,27 @@ public class JdbcDBClient extends DB { ...@@ -83,6 +83,27 @@ public class JdbcDBClient extends DB {
private static final String DEFAULT_PROP = ""; private static final String DEFAULT_PROP = "";
private ConcurrentMap<StatementType, PreparedStatement> cachedStatements; private ConcurrentMap<StatementType, PreparedStatement> cachedStatements;
/**
* Ordered field information for insert and update statements.
*/
private static class OrderedFieldInfo {
private String fieldKeys;
private List<String> fieldValues;
OrderedFieldInfo(String fieldKeys, List<String> fieldValues) {
this.fieldKeys = fieldKeys;
this.fieldValues = fieldValues;
}
String getFieldKeys() {
return fieldKeys;
}
List<String> getFieldValues() {
return fieldValues;
}
}
/** /**
* The statement type for the prepared statements. * The statement type for the prepared statements.
*/ */
...@@ -109,11 +130,13 @@ public class JdbcDBClient extends DB { ...@@ -109,11 +130,13 @@ public class JdbcDBClient extends DB {
private int shardIndex; private int shardIndex;
private int numFields; private int numFields;
private String tableName; private String tableName;
private String fieldString;
StatementType(Type type, String tableName, int numFields, int shardIndex) { StatementType(Type type, String tableName, int numFields, String fieldString, int shardIndex) {
this.type = type; this.type = type;
this.tableName = tableName; this.tableName = tableName;
this.numFields = numFields; this.numFields = numFields;
this.fieldString = fieldString;
this.shardIndex = shardIndex; this.shardIndex = shardIndex;
} }
...@@ -155,6 +178,9 @@ public class JdbcDBClient extends DB { ...@@ -155,6 +178,9 @@ public class JdbcDBClient extends DB {
if (type != other.type) { if (type != other.type) {
return false; return false;
} }
if (!fieldString.equals(other.fieldString)) {
return false;
}
return true; return true;
} }
} }
...@@ -261,6 +287,7 @@ public class JdbcDBClient extends DB { ...@@ -261,6 +287,7 @@ public class JdbcDBClient extends DB {
private PreparedStatement createAndCacheInsertStatement(StatementType insertType, String key) throws SQLException { private PreparedStatement createAndCacheInsertStatement(StatementType insertType, String key) throws SQLException {
StringBuilder insert = new StringBuilder("INSERT INTO "); StringBuilder insert = new StringBuilder("INSERT INTO ");
insert.append(insertType.tableName); insert.append(insertType.tableName);
insert.append(" (" + PRIMARY_KEY + "," + insertType.fieldString + ")");
insert.append(" VALUES(?"); insert.append(" VALUES(?");
for (int i = 0; i < insertType.numFields; i++) { for (int i = 0; i < insertType.numFields; i++) {
insert.append(",?"); insert.append(",?");
...@@ -304,14 +331,14 @@ public class JdbcDBClient extends DB { ...@@ -304,14 +331,14 @@ public class JdbcDBClient extends DB {
} }
private PreparedStatement createAndCacheUpdateStatement(StatementType updateType, String key) throws SQLException { private PreparedStatement createAndCacheUpdateStatement(StatementType updateType, String key) throws SQLException {
String[] fieldKeys = updateType.fieldString.split(",");
StringBuilder update = new StringBuilder("UPDATE "); StringBuilder update = new StringBuilder("UPDATE ");
update.append(updateType.tableName); update.append(updateType.tableName);
update.append(" SET "); update.append(" SET ");
for (int i = 0; i < updateType.numFields; i++) { for (int i = 0; i < fieldKeys.length; i++) {
update.append(COLUMN_PREFIX); update.append(fieldKeys[i]);
update.append(i);
update.append("=?"); update.append("=?");
if (i < updateType.numFields - 1) { if (i < fieldKeys.length - 1) {
update.append(", "); update.append(", ");
} }
} }
...@@ -349,7 +376,7 @@ public class JdbcDBClient extends DB { ...@@ -349,7 +376,7 @@ public class JdbcDBClient extends DB {
@Override @Override
public Status read(String tableName, String key, Set<String> fields, HashMap<String, ByteIterator> result) { public Status read(String tableName, String key, Set<String> fields, HashMap<String, ByteIterator> result) {
try { try {
StatementType type = new StatementType(StatementType.Type.READ, tableName, 1, getShardIndexByKey(key)); StatementType type = new StatementType(StatementType.Type.READ, tableName, 1, "", getShardIndexByKey(key));
PreparedStatement readStatement = cachedStatements.get(type); PreparedStatement readStatement = cachedStatements.get(type);
if (readStatement == null) { if (readStatement == null) {
readStatement = createAndCacheReadStatement(type, key); readStatement = createAndCacheReadStatement(type, key);
...@@ -378,7 +405,7 @@ public class JdbcDBClient extends DB { ...@@ -378,7 +405,7 @@ public class JdbcDBClient extends DB {
public Status scan(String tableName, String startKey, int recordcount, Set<String> fields, public Status scan(String tableName, String startKey, int recordcount, Set<String> fields,
Vector<HashMap<String, ByteIterator>> result) { Vector<HashMap<String, ByteIterator>> result) {
try { try {
StatementType type = new StatementType(StatementType.Type.SCAN, tableName, 1, getShardIndexByKey(startKey)); StatementType type = new StatementType(StatementType.Type.SCAN, tableName, 1, "", getShardIndexByKey(startKey));
PreparedStatement scanStatement = cachedStatements.get(type); PreparedStatement scanStatement = cachedStatements.get(type);
if (scanStatement == null) { if (scanStatement == null) {
scanStatement = createAndCacheScanStatement(type, startKey); scanStatement = createAndCacheScanStatement(type, startKey);
...@@ -408,14 +435,16 @@ public class JdbcDBClient extends DB { ...@@ -408,14 +435,16 @@ public class JdbcDBClient extends DB {
public Status update(String tableName, String key, HashMap<String, ByteIterator> values) { public Status update(String tableName, String key, HashMap<String, ByteIterator> values) {
try { try {
int numFields = values.size(); int numFields = values.size();
StatementType type = new StatementType(StatementType.Type.UPDATE, tableName, numFields, getShardIndexByKey(key)); OrderedFieldInfo fieldInfo = getFieldInfo(values);
StatementType type = new StatementType(StatementType.Type.UPDATE, tableName,
numFields, fieldInfo.getFieldKeys(), getShardIndexByKey(key));
PreparedStatement updateStatement = cachedStatements.get(type); PreparedStatement updateStatement = cachedStatements.get(type);
if (updateStatement == null) { if (updateStatement == null) {
updateStatement = createAndCacheUpdateStatement(type, key); updateStatement = createAndCacheUpdateStatement(type, key);
} }
int index = 1; int index = 1;
for (Map.Entry<String, ByteIterator> entry : values.entrySet()) { for (String value: fieldInfo.getFieldValues()) {
updateStatement.setString(index++, entry.getValue().toString()); updateStatement.setString(index++, value);
} }
updateStatement.setString(index, key); updateStatement.setString(index, key);
int result = updateStatement.executeUpdate(); int result = updateStatement.executeUpdate();
...@@ -433,16 +462,17 @@ public class JdbcDBClient extends DB { ...@@ -433,16 +462,17 @@ public class JdbcDBClient extends DB {
public Status insert(String tableName, String key, HashMap<String, ByteIterator> values) { public Status insert(String tableName, String key, HashMap<String, ByteIterator> values) {
try { try {
int numFields = values.size(); int numFields = values.size();
StatementType type = new StatementType(StatementType.Type.INSERT, tableName, numFields, getShardIndexByKey(key)); OrderedFieldInfo fieldInfo = getFieldInfo(values);
StatementType type = new StatementType(StatementType.Type.INSERT, tableName,
numFields, fieldInfo.getFieldKeys(), getShardIndexByKey(key));
PreparedStatement insertStatement = cachedStatements.get(type); PreparedStatement insertStatement = cachedStatements.get(type);
if (insertStatement == null) { if (insertStatement == null) {
insertStatement = createAndCacheInsertStatement(type, key); insertStatement = createAndCacheInsertStatement(type, key);
} }
insertStatement.setString(1, key); insertStatement.setString(1, key);
int index = 2; int index = 2;
for (Map.Entry<String, ByteIterator> entry : values.entrySet()) { for (String value: fieldInfo.getFieldValues()) {
String field = entry.getValue().toString(); insertStatement.setString(index++, value);
insertStatement.setString(index++, field);
} }
int result = insertStatement.executeUpdate(); int result = insertStatement.executeUpdate();
if (result == 1) { if (result == 1) {
...@@ -458,7 +488,7 @@ public class JdbcDBClient extends DB { ...@@ -458,7 +488,7 @@ public class JdbcDBClient extends DB {
@Override @Override
public Status delete(String tableName, String key) { public Status delete(String tableName, String key) {
try { try {
StatementType type = new StatementType(StatementType.Type.DELETE, tableName, 1, getShardIndexByKey(key)); StatementType type = new StatementType(StatementType.Type.DELETE, tableName, 1, "", getShardIndexByKey(key));
PreparedStatement deleteStatement = cachedStatements.get(type); PreparedStatement deleteStatement = cachedStatements.get(type);
if (deleteStatement == null) { if (deleteStatement == null) {
deleteStatement = createAndCacheDeleteStatement(type, key); deleteStatement = createAndCacheDeleteStatement(type, key);
...@@ -474,4 +504,20 @@ public class JdbcDBClient extends DB { ...@@ -474,4 +504,20 @@ public class JdbcDBClient extends DB {
return Status.ERROR; return Status.ERROR;
} }
} }
}
private OrderedFieldInfo getFieldInfo(HashMap<String, ByteIterator> values) {
String fieldKeys = "";
List<String> fieldValues = new ArrayList();
int count = 0;
for (Map.Entry<String, ByteIterator> entry : values.entrySet()) {
fieldKeys += entry.getKey();
if (count < values.size() - 1) {
fieldKeys += ",";
}
fieldValues.add(count, entry.getValue().toString());
count++;
}
return new OrderedFieldInfo(fieldKeys, fieldValues);
}
}
\ No newline at end of file
/** /**
* Copyright (c) 2015 Yahoo! Inc. All rights reserved. * Copyright (c) 2015 - 2016 Yahoo! Inc. All rights reserved.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you * Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You * may not use this file except in compliance with the License. You
...@@ -30,9 +30,6 @@ import java.util.HashSet; ...@@ -30,9 +30,6 @@ import java.util.HashSet;
import java.util.Properties; import java.util.Properties;
import java.util.Vector; import java.util.Vector;
/**
* Created by kruthar on 11/2/15.
*/
public class JdbcDBClientTest { public class JdbcDBClientTest {
private static final String TEST_DB_DRIVER = "org.hsqldb.jdbc.JDBCDriver"; private static final String TEST_DB_DRIVER = "org.hsqldb.jdbc.JDBCDriver";
private static final String TEST_DB_URL = "jdbc:hsqldb:mem:ycsb"; private static final String TEST_DB_URL = "jdbc:hsqldb:mem:ycsb";
...@@ -153,7 +150,7 @@ public class JdbcDBClientTest { ...@@ -153,7 +150,7 @@ public class JdbcDBClientTest {
public void insertTest() { public void insertTest() {
try { try {
String insertKey = "user0"; String insertKey = "user0";
insertRow(insertKey); HashMap<String, ByteIterator> insertMap = insertRow(insertKey);
ResultSet resultSet = jdbcConnection.prepareStatement( ResultSet resultSet = jdbcConnection.prepareStatement(
String.format("SELECT * FROM %s", TABLE_NAME) String.format("SELECT * FROM %s", TABLE_NAME)
...@@ -164,9 +161,7 @@ public class JdbcDBClientTest { ...@@ -164,9 +161,7 @@ public class JdbcDBClientTest {
// Check that all the columns have expected values // Check that all the columns have expected values
assertEquals(resultSet.getString(KEY_FIELD), insertKey); assertEquals(resultSet.getString(KEY_FIELD), insertKey);
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
// TODO: This will fail until the fix is made to insert and update fields in the correct order. assertEquals(resultSet.getString(FIELD_PREFIX + i), insertMap.get(FIELD_PREFIX + i).toString());
// TODO: Uncomment this assertEquals when the fix is made.
//assertEquals(resultSet.getString(FIELD_PREFIX + i), insertMap.get(FIELD_PREFIX + i));
} }
// Check that we do not have any more rows // Check that we do not have any more rows
assertFalse(resultSet.next()); assertFalse(resultSet.next());
...@@ -224,9 +219,7 @@ public class JdbcDBClientTest { ...@@ -224,9 +219,7 @@ public class JdbcDBClientTest {
resultSet.next(); resultSet.next();
assertEquals(resultSet.getString(KEY_FIELD), "user1"); assertEquals(resultSet.getString(KEY_FIELD), "user1");
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
// TODO: This will fail until the fix is made to insert and update fields in the correct order. assertEquals(resultSet.getString(FIELD_PREFIX + i), updateMap.get(FIELD_PREFIX + i).toString());
// TODO: Uncomment this assertEquals when the fix is made.
//assertEquals(resultSet.getString(FIELD_PREFIX + i), updateMap.get(FIELD_PREFIX + i));
} }
// Ensure that user2 record was not changed // Ensure that user2 record was not changed
...@@ -245,7 +238,7 @@ public class JdbcDBClientTest { ...@@ -245,7 +238,7 @@ public class JdbcDBClientTest {
@Test @Test
public void readTest() { public void readTest() {
String insertKey = "user0"; String insertKey = "user0";
insertRow(insertKey); HashMap<String, ByteIterator> insertMap = insertRow(insertKey);
HashSet<String> readFields = new HashSet<String>(); HashSet<String> readFields = new HashSet<String>();
HashMap<String, ByteIterator> readResultMap = new HashMap<String, ByteIterator>(); HashMap<String, ByteIterator> readResultMap = new HashMap<String, ByteIterator>();
...@@ -254,9 +247,7 @@ public class JdbcDBClientTest { ...@@ -254,9 +247,7 @@ public class JdbcDBClientTest {
jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap); jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap);
assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size()); assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size());
for (String field: readFields) { for (String field: readFields) {
// TODO: This will fail until the fix is made to insert and update fields in the correct order. assertEquals("Assert " + field + " was read correctly", insertMap.get(field).toString(), readResultMap.get(field).toString());
// TODO: Uncomment this assertEquals when the fix is made.
//assertEquals("Assert " + field + " was read correctly", insertMap.get(field), readResultMap.get(field));
} }
readResultMap = new HashMap<String, ByteIterator>(); readResultMap = new HashMap<String, ByteIterator>();
...@@ -267,9 +258,7 @@ public class JdbcDBClientTest { ...@@ -267,9 +258,7 @@ public class JdbcDBClientTest {
jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap); jdbcDBClient.read(TABLE_NAME, insertKey, readFields, readResultMap);
assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size()); assertEquals("Assert that result has correct number of fields", readFields.size(), readResultMap.size());
for (String field: readFields) { for (String field: readFields) {
// TODO: This will fail until the fix is made to insert and update fields in the correct order. assertEquals("Assert " + field + " was read correctly", insertMap.get(field).toString(), readResultMap.get(field).toString());
// TODO: Uncomment this assertEquals when the fix is made.
//assertEquals("Assert " + field + " was read correctly", insertMap.get(field), readResultMap.get(field));
} }
} }
...@@ -325,9 +314,7 @@ public class JdbcDBClientTest { ...@@ -325,9 +314,7 @@ public class JdbcDBClientTest {
for (HashMap<String, ByteIterator> result: resultVector) { for (HashMap<String, ByteIterator> result: resultVector) {
assertEquals("Assert that this row has the correct number of fields", fieldSet.size(), result.size()); assertEquals("Assert that this row has the correct number of fields", fieldSet.size(), result.size());
for (String field: fieldSet) { for (String field: fieldSet) {
// TODO: This will fail until the fix is made to insert and update fields in the correct order. assertEquals("Assert this field is correct in this row", keyMap.get(KEY_PREFIX + testIndex).get(field).toString(), result.get(field).toString());
// TODO: Uncomment this assertEquals when the fix is made.
//assertEquals("Assert this field is correct in this row", keyMap.get(KEY_PREFIX + testIndex).get(field), result.get(field));
} }
testIndex++; testIndex++;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment