3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 14:54:15 +00:00

Add ability to optionally use a schema name in the Postgres block store.

Add a test to make sure things work when we set a schema name.
This commit is contained in:
Erik Tierney 2014-02-05 12:08:14 -05:00 committed by Mike Hearn
parent c95a864831
commit 59a18ab43f
2 changed files with 75 additions and 11 deletions

View File

@ -22,6 +22,7 @@ import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@ -49,6 +50,7 @@ public class PostgresFullPrunedBlockStore implements FullPrunedBlockStore {
private int fullStoreDepth;
private String username;
private String password;
private String schemaName;
private static final String driver = "org.postgresql.Driver";
private static final String CREATE_SETTINGS_TABLE = "CREATE TABLE settings (\n" +
@ -107,24 +109,59 @@ public class PostgresFullPrunedBlockStore implements FullPrunedBlockStore {
*/
public PostgresFullPrunedBlockStore(NetworkParameters params, int fullStoreDepth, String hostname, String dbName,
String username, String password) throws BlockStoreException {
this(params, fullStoreDepth, "jdbc:postgresql://" + hostname + "/" + dbName, username, password);
this(params, "jdbc:postgresql://" + hostname + "/" + dbName, fullStoreDepth, username, password, null);
}
/**
* Creates a new PostgresFullPrunedBlockStore.
* <p>Create a new PostgresFullPrunedBlockStore, storing the tables in the schema specified. You may want to
* specify a schema to avoid name collisions, or just to keep the database better organized. The schema is not
* required, and if one is not provided than the default schema for the username will be used. See
* <a href="http://www.postgres.org/docs/9.3/static/ddl-schemas.html">the postgres schema docs</a> for more on
* schemas.</p>
*
* @param params A copy of the NetworkParameters used
* @param fullStoreDepth The number of blocks of history stored in full (something like 1000 is pretty safe)
* @param connectionURL The jdbc url to connect to the database.
* @param username The database username
* @param password The password to the database
* @throws BlockStoreException if the database fails to open for any reason
* @param params A copy of the NetworkParameters used.
* @param fullStoreDepth The number of blocks of history stored in full (something like 1000 is pretty safe).
* @param hostname The hostname of the database to connect to.
* @param dbName The database to connect to.
* @param username The database username.
* @param password The password to the database.
* @param schemaName The name of the schema to put the tables in. May be null if no schema is being used.
* @throws BlockStoreException If the database fails to open for any reason.
*/
public PostgresFullPrunedBlockStore(NetworkParameters params, int fullStoreDepth, String connectionURL,
String username, String password) throws BlockStoreException {
public PostgresFullPrunedBlockStore(NetworkParameters params, int fullStoreDepth, String hostname, String dbName,
String username, String password, @Nullable String schemaName) throws BlockStoreException {
this(params, "jdbc:postgresql://" + hostname + "/" + dbName, fullStoreDepth, username, password, schemaName);
}
/**
* <p>Create a new PostgresFullPrunedBlockStore, using the full connection URL instead of a hostname and password,
* and optionally allowing a schema to be specified.</p>
*
* <p>The connection URL will be passed to the database driver, and should look like
* "jdbc:postrgresql://host[:port]/databasename". You can use this to change the port, or specify additional
* parameters. See <a href="http://jdbc.postgresql.org/documentation/head/connect.html#connection-parameters">
* the PostgreSQL JDBC documentation</a> for more on the connection URL.</p>
*
* <p>This constructor also accepts a schema name to use, which can be used to avoid name collisions, or to keep the
* database organized. If no schema is provided the default schema for the username will be used. See
* <a href="http://www.postgres.org/docs/9.3/static/ddl-schemas.html">the postgres schema docs</a> for more on
* schemas.</p>
*
*
* @param params A copy of the NetworkParameters used.
* @param connectionURL The jdbc url to connect to the database.
* @param fullStoreDepth The number of blocks of history stored in full (something like 1000 is pretty safe).
* @param username The database username.
* @param password The password to the database.
* @param schemaName The name of the schema to put the tables in. May be null if no schema is being used.
* @throws BlockStoreException If the database fails to open for any reason.
*/
public PostgresFullPrunedBlockStore(NetworkParameters params, String connectionURL, int fullStoreDepth,
String username, String password, @Nullable String schemaName) throws BlockStoreException {
this.params = params;
this.fullStoreDepth = fullStoreDepth;
this.connectionURL = connectionURL;
this.schemaName = schemaName;
this.username = username;
this.password = password;
@ -165,6 +202,12 @@ public class PostgresFullPrunedBlockStore implements FullPrunedBlockStore {
conn.set(DriverManager.getConnection(connectionURL, props));
Connection connection = conn.get();
// set the schema if one is needed
if(schemaName != null) {
Statement s = connection.createStatement();
s.execute("CREATE SCHEMA IF NOT EXISTS " + schemaName + ";");
s.execute("set search_path to '" + schemaName +"';");
}
allConnections.add(conn.get());
log.info("Made a new connection to database " + connectionURL);
} catch (SQLException ex) {

View File

@ -4,6 +4,7 @@ import com.google.bitcoin.store.BlockStoreException;
import com.google.bitcoin.store.FullPrunedBlockStore;
import com.google.bitcoin.store.PostgresFullPrunedBlockStore;
import org.junit.Ignore;
import org.junit.Test;
/**
* A Postgres implementation of the {@link AbstractFullPrunedBlockChainTest}
@ -16,15 +17,35 @@ public class PostgresFullPrunedBlockChainTest extends AbstractFullPrunedBlockCha
private static final String DB_NAME = "bitcoinj_test";
private static final String DB_USERNAME = "bitcoinj";
private static final String DB_PASSWORD = "password";
private static final String DB_SCHEMA = "blockstore_schema";
// whether to run the test with a schema name
private boolean useSchema = false;
@Override
public FullPrunedBlockStore createStore(NetworkParameters params, int blockCount)
throws BlockStoreException {
return new PostgresFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD);
if(useSchema) {
return new PostgresFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD, DB_SCHEMA);
}
else {
return new PostgresFullPrunedBlockStore(params, blockCount, DB_HOSTNAME, DB_NAME, DB_USERNAME, DB_PASSWORD);
}
}
@Override
public void resetStore(FullPrunedBlockStore store) throws BlockStoreException {
((PostgresFullPrunedBlockStore)store).resetStore();
}
@Test
public void testFirst100kBlocksWithCustomSchema() throws Exception {
boolean oldSchema = useSchema;
useSchema = true;
try {
super.testFirst100KBlocks();
} finally {
useSchema = oldSchema;
}
}
}