Implement and test DBStore swap_table functionality

This commit is contained in:
Winston Li 2016-08-23 22:32:50 +01:00 committed by Michael Mazour
parent d2b628d904
commit 9d19cdd261
14 changed files with 252 additions and 47 deletions

View file

@ -8,7 +8,11 @@ import java.sql.SQLException;
*/
public interface SQLUpdate {
public String getSQL();
public void addParametersToStatement(PreparedStatement statement) throws SQLException;
String getSQL();
default void addParametersToStatement(
PreparedStatement statement
) throws SQLException {
}
}

View file

@ -3,14 +3,14 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import uk.ac.ic.wlgitbridge.bridge.db.DBInitException;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetLatestVersionForProjectSQLQuery;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetOldestProjectName;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetPathForURLInProjectSQLQuery;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetProjectNamesSQLQuery;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateIndexURLIndexStore;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateProjectsTableSQLUpdate;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateURLIndexStoreSQLUpdate;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.*;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete.DeleteFilesForProjectSQLUpdate;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.AddURLIndexSQLUpdate;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.SetProjectSQLUpdate;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.SetProjectLastAccessedTime;
import java.io.File;
import java.sql.*;
@ -80,15 +80,15 @@ public class SqliteDBStore implements DBStore {
@Override
public String getOldestUnswappedProject() {
throw new UnsupportedOperationException();
return query(new GetOldestProjectName());
}
@Override
public void setLastAccessedTime(
String projectName,
Timestamp time
Timestamp lastAccessed
) {
throw new UnsupportedOperationException();
update(new SetProjectLastAccessedTime(projectName, lastAccessed));
}
private Connection openConnectionTo(File dbFile) {
@ -117,7 +117,9 @@ public class SqliteDBStore implements DBStore {
Stream.of(
new CreateProjectsTableSQLUpdate(),
new CreateURLIndexStoreSQLUpdate(),
new CreateIndexURLIndexStore()
new CreateIndexURLIndexStore(),
new CreateSwapTable(),
new CreateSwapTableIndex()
).forEach(this::update);
}

View file

@ -0,0 +1,30 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.query;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created by winston on 23/08/2016.
*/
public class GetOldestProjectName implements SQLQuery<String> {
private static final String GET_OLDEST_PROJECT_NAME =
"SELECT `project_name`, MIN(`last_accessed`)\n" +
" FROM `swap_table`";
@Override
public String getSQL() {
return GET_OLDEST_PROJECT_NAME;
}
@Override
public String processResultSet(ResultSet resultSet) throws SQLException {
while (resultSet.next()) {
return resultSet.getString("project_name");
}
return null;
}
}

View file

@ -2,7 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.query;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedList;
@ -30,9 +29,4 @@ public class GetProjectNamesSQLQuery implements SQLQuery<List<String>> {
return GET_URL_INDEXES_FOR_PROJECT_NAME;
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
}
}

View file

@ -2,25 +2,18 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Created by Winston on 21/02/15.
*/
public class CreateIndexURLIndexStore implements SQLUpdate {
public static final String CREATE_INDEX_URL_INDEX_STORE =
"CREATE UNIQUE INDEX IF NOT EXISTS `project_path_index` ON `url_index_store`(`project_name`, `path`);\n";
"CREATE UNIQUE INDEX IF NOT EXISTS `project_path_index` " +
"ON `url_index_store`(`project_name`, `path`);\n";
@Override
public String getSQL() {
return CREATE_INDEX_URL_INDEX_STORE;
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
}
}

View file

@ -2,9 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Created by Winston on 20/11/14.
*/
@ -21,9 +18,4 @@ public class CreateProjectsTableSQLUpdate implements SQLUpdate {
return CREATE_PROJECTS_TABLE;
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
}
}

View file

@ -0,0 +1,27 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
/**
* Created by winston on 23/08/2016.
*/
public class CreateSwapTable implements SQLUpdate {
private static final String CREATE_SWAP_TABLE =
"CREATE TABLE IF NOT EXISTS `swap_table` (\n" +
" `project_name` VARCHAR NOT NULL DEFAULT '',\n" +
" `last_accessed` DATETIME NULL DEFAULT 0,\n" +
" PRIMARY KEY (`project_name`),\n" +
" CONSTRAINT `swap_table_fk_1`\n" +
" FOREIGN KEY (`project_name`)\n" +
" REFERENCES `projects`(`name`)\n" +
" ON DELETE CASCADE\n" +
" ON UPDATE CASCADE\n" +
")";
@Override
public String getSQL() {
return CREATE_SWAP_TABLE;
}
}

View file

@ -0,0 +1,19 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
/**
* Created by winston on 23/08/2016.
*/
public class CreateSwapTableIndex implements SQLUpdate {
private static final String CREATE_SWAP_TABLE_INDEX =
"CREATE INDEX IF NOT EXISTS `swap_table_index`\n" +
" ON `swap_table`(`last_accessed`)";
@Override
public String getSQL() {
return CREATE_SWAP_TABLE_INDEX;
}
}

View file

@ -2,9 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* Created by Winston on 20/11/14.
*/
@ -16,7 +13,11 @@ public class CreateURLIndexStoreSQLUpdate implements SQLUpdate {
" `url` text NOT NULL,\n"+
" `path` text NOT NULL,\n"+
" PRIMARY KEY (`project_name`,`url`),\n"+
" CONSTRAINT `url_index_store_ibfk_1` FOREIGN KEY (`project_name`) REFERENCES `projects` (`name`) ON DELETE CASCADE ON UPDATE CASCADE\n"+
" CONSTRAINT `url_index_store_ibfk_1` " +
"FOREIGN KEY (`project_name`) " +
"REFERENCES `projects` (`name`) " +
"ON DELETE CASCADE " +
"ON UPDATE CASCADE\n"+
");\n";
@Override
@ -24,9 +25,4 @@ public class CreateURLIndexStoreSQLUpdate implements SQLUpdate {
return CREATE_URL_INDEX_STORE;
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
}
}

View file

@ -11,7 +11,8 @@ import java.sql.SQLException;
public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
private static final String DELETE_URL_INDEXES_FOR_PROJECT_NAME =
"DELETE FROM `url_index_store` WHERE `project_name` = ? AND path IN (";
"DELETE FROM `url_index_store` " +
"WHERE `project_name` = ? AND path IN (";
private final String projectName;
private final String[] paths;
@ -23,7 +24,9 @@ public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
@Override
public String getSQL() {
StringBuilder sb = new StringBuilder(DELETE_URL_INDEXES_FOR_PROJECT_NAME);
StringBuilder sb = new StringBuilder(
DELETE_URL_INDEXES_FOR_PROJECT_NAME
);
for (int i = 0; i < paths.length; i++) {
sb.append("?");
if (i < paths.length - 1) {
@ -35,7 +38,9 @@ public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
public void addParametersToStatement(
PreparedStatement statement
) throws SQLException {
statement.setString(1, projectName);
for (int i = 0; i < paths.length; i++) {
statement.setString(i + 2, paths[i]);

View file

@ -11,7 +11,12 @@ import java.sql.SQLException;
public class AddURLIndexSQLUpdate implements SQLUpdate {
private static final String ADD_URL_INDEX =
"INSERT OR REPLACE INTO `url_index_store` (`project_name`, `url`, `path`) VALUES (?, ?, ?);\n";
"INSERT OR REPLACE INTO `url_index_store`(" +
"`project_name`, " +
"`url`, " +
"`path`" +
") VALUES " +
"(?, ?, ?)\n";
private final String projectName;
private final String url;
@ -29,7 +34,9 @@ public class AddURLIndexSQLUpdate implements SQLUpdate {
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
public void addParametersToStatement(
PreparedStatement statement
) throws SQLException {
statement.setString(1, projectName);
statement.setString(2, url);
statement.setString(3, path);

View file

@ -0,0 +1,47 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
/**
* Created by winston on 23/08/2016.
*/
public class SetProjectLastAccessedTime implements SQLUpdate {
private static final String SET_PROJECT_LAST_ACCESSED_TIME =
"INSERT OR REPLACE INTO `swap_table`(\n" +
" `project_name`,\n" +
" `last_accessed`\n" +
") VALUES (\n" +
" ?,\n" +
" ?\n" +
")";
private final String projectName;
private final Timestamp lastAccessed;
public SetProjectLastAccessedTime(
String projectName,
Timestamp lastAccessed
) {
this.projectName = projectName;
this.lastAccessed = lastAccessed;
}
@Override
public String getSQL() {
return SET_PROJECT_LAST_ACCESSED_TIME;
}
@Override
public void addParametersToStatement(
PreparedStatement statement
) throws SQLException {
statement.setString(1, projectName);
statement.setTimestamp(2, lastAccessed);
}
}

View file

@ -11,7 +11,8 @@ import java.sql.SQLException;
public class SetProjectSQLUpdate implements SQLUpdate {
private static final String SET_PROJECT =
"INSERT OR REPLACE INTO `projects`(`name`, `version_id`) VALUES (?, ?);\n";
"INSERT OR REPLACE INTO `projects`(`name`, `version_id`) " +
"VALUES (?, ?);\n";
private final String projectName;
private final int versionID;

View file

@ -0,0 +1,88 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import org.junit.Before;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
/**
* Created by winston on 23/08/2016.
*/
public class SqliteDBStoreTest {
private SqliteDBStore dbStore;
@Before
public void setup() throws IOException {
TemporaryFolder tmpFolder = new TemporaryFolder();
tmpFolder.create();
dbStore = new SqliteDBStore(tmpFolder.newFile("dbStore.db"));
}
@Test
public void swapTableStartsOutEmpty() {
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void testGetOldestUnswappedProject() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
)
);
dbStore.setLatestVersionForProject("asdf", 1);
dbStore.setLastAccessedTime(
"asdf",
Timestamp.valueOf(
LocalDateTime.now().minus(1, ChronoUnit.SECONDS)
)
);
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now()
)
);
assertEquals("asdf", dbStore.getOldestUnswappedProject());
}
@Test
public void noOldestProjectIfAllEvicated() {
dbStore.setLatestVersionForProject("older", 3);
dbStore.setLastAccessedTime("older", null);
assertNull(dbStore.getOldestUnswappedProject());
}
@Test
public void nullLastAccessedTimesDoNotCount() {
dbStore.setLatestVersionForProject("older", 2);
dbStore.setLastAccessedTime(
"older",
Timestamp.valueOf(
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
)
);
dbStore.setLatestVersionForProject("newer", 3);
dbStore.setLastAccessedTime(
"newer",
Timestamp.valueOf(
LocalDateTime.now()
)
);
assertEquals("older", dbStore.getOldestUnswappedProject());
dbStore.setLastAccessedTime("older", null);
assertEquals("newer", dbStore.getOldestUnswappedProject());
}
}