Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

MODE-1861 Database binary store is more adaptable to different DBMSes

Changed how the DatabaseBinaryStore configures and uses the database,
so that the various SQL statements (both DDL and DML) are read from
property files rather than be dynamically created. This means that it
is far easier to see and understand exactly the kinds of statements
that are issued for a given DBMS. It also allows the database table
and statements to be altered slightly for specific DBMSes.

Several DBMS-specific property files (containing the SQL statements)
were added to accommodate the variations in the previously-generated
statements. There is a fair amount of duplication, but each file
is self-contained, is very readable, and can be customized as needed
(including by the user, since additional property files can be created
to override those ModeShape provides out-of-the-box).
IMO, these benefits outweigh the negative aspects of the duplication.

Since several DBMSes (including MySQL, PostgreSQL, Sybase
and SQLServer) consider 'usage' to be a reserved keyword, the 'usage'
column was renamed to 'usage_flag' in the create-table and other
statements for all of the DBMSes. (This shouldn't be a problem,
since the use of reserved words should have prevented creation
of the table in the first place). The statements for the other DBMSes
still use 'usage', but these DBMSes don't consider 'usage' to be a
reserved keyword.

This change also reduced the amount of "general-purpose" JDBC-oriented
code, such as eliminating the SQLBuilder code.

Finally, the Database class now creates PreparedStatement objects
during initialization, and these are reused throughout the lifetime
of the DatabaseBinaryStore. This will increase performance compared
with creating a PreparedStatement every time one is needed.
  • Loading branch information...
commit 4ede63a1d7966eb5707a1a4b072b6e3393244c35 1 parent e5abba0
@rhauch rhauch authored hchiorean committed
Showing with 664 additions and 628 deletions.
  1. +2 −0  modeshape-jcr/src/main/java/org/modeshape/jcr/JcrI18n.java
  2. +289 −488 modeshape-jcr/src/main/java/org/modeshape/jcr/value/binary/Database.java
  3. +47 −9 modeshape-jcr/src/main/java/org/modeshape/jcr/value/binary/DatabaseBinaryStore.java
  4. +2 −0  modeshape-jcr/src/main/resources/org/modeshape/jcr/JcrI18n.properties
  5. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_default_database.properties
  6. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_hsql_database.properties
  7. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_mysql_database.properties
  8. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_oracle_database.properties
  9. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_postgres_database.properties
  10. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_sqlserver_database.properties
  11. +46 −0 modeshape-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_sybase_database.properties
  12. +0 −131 modeshape-jcr/src/test/java/org/modeshape/jcr/value/binary/DatabaseTest.java
  13. +2 −0  modeshape-jcr/src/test/resources/log4j.properties
View
2  modeshape-jcr/src/main/java/org/modeshape/jcr/JcrI18n.java
@@ -473,6 +473,8 @@
public static I18n noReindex;
public static I18n reindexAll;
+ public static I18n errorCreatingDatabaseTable;
+
static {
try {
I18n.initialize(JcrI18n.class);
View
777 modeshape-jcr/src/main/java/org/modeshape/jcr/value/binary/Database.java
@@ -23,6 +23,7 @@
*/
package org.modeshape.jcr.value.binary;
+import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -30,28 +31,67 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Properties;
import java.util.Set;
+import org.modeshape.common.logging.Logger;
import org.modeshape.common.util.StringUtil;
+import org.modeshape.jcr.JcrI18n;
import org.modeshape.jcr.value.BinaryKey;
/**
* Helper class for manipulation with database.
+ * <p>
+ * This class looks for database SQL statements in properties files named "<code>binary_store_{type}_database.properties</code>"
+ * located within the "org/modeshape/jcr/database" area of the classpath, where "<code>{type}</code>" is {@link #determineType()
+ * determined} from the connection, and matches one of the following:
+ * <ul>
+ * <li><code>mysql</code></li>
+ * <li><code>postgres</code></li>
+ * <li><code>derby</code></li>
+ * <li><code>hsql</code></li>
+ * <li><code>h2</code></li>
+ * <li><code>sqlite</code></li>
+ * <li><code>db2</code></li>
+ * <li><code>db2_390</code></li>
+ * <li><code>informix</code></li>
+ * <li><code>interbase</code></li>
+ * <li><code>firebird</code></li>
+ * <li><code>sqlserver</code></li>
+ * <li><code>access</code></li>
+ * <li><code>oracle</code></li>
+ * <li><code>sybase</code></li>
+ * </ul>
+ * If the corresponding file is not found on the classpath, then the "<code>binary_store_default_database.properties</code>" file
+ * is used.
+ * </p>
+ * <p>
+ * Each property file should contain the set of DDL and DML statements that are used by the binary store, and the
+ * database-specific file allows database-specific schemas and queries to be used. If the properties file that corresponds to the
+ * connection's database type is not found on the classpath, then the "<code>binary_store_default_database.properties</code>" file
+ * is used.
+ * </p>
+ * <p>
+ * ModeShape does not provide out-of-the-box properties files for each of the database types listed above. If you run into any
+ * problems, you can override the statements by providing a property file that matches the naming pattern described above, and by
+ * putting that file on the classpath. (If you want to override one of ModeShape's out-of-the-box properties files, then be sure
+ * to put your custom file first on the classpath.)
+ * </p>
*
* @author kulikov
*/
public class Database {
- // connection to a database
- protected final Connection connection;
- // table name prefix
- private String prefix;
- protected Type databaseType;
+ private static final Logger LOGGER = Logger.getLogger(Database.class);
- // SQLBuilder
- private SQLBuilder sqlBuilder = new SQLBuilder();
- private SQLType sqlType = new SQLType();
+ public static final String TABLE_NAME = "CONTENT_STORE";
- public enum Type {
+ public static final String STATEMENTS_FILE_PATH = "org/modeshape/jcr/database/";
+ protected static final String STATEMENTS_FILE_PREFIX = "binary_store_";
+ protected static final String STATEMENTS_FILENAME_SUFFIX = "_database.properties";
+ protected static final String DEFAULT_STATEMENTS_FILE_PATH = STATEMENTS_FILE_PATH + STATEMENTS_FILE_PREFIX + "default"
+ + STATEMENTS_FILENAME_SUFFIX;
+
+ public static enum Type {
MYSQL,
POSTGRES,
DERBY,
@@ -63,13 +103,30 @@
INFORMIX,
INTERBASE,
FIREBIRD,
- SQL_SERVER,
+ SQLSERVER,
ACCESS,
ORACLE,
SYBASE,
UNKNOWN;
}
+ private final Connection connection;
+ private final Type databaseType;
+ private final String prefix;
+ private final String tableName;
+ private final Properties statements;
+ private PreparedStatement addContentSql;
+ private PreparedStatement getUsedContentSql;
+ private PreparedStatement getUnusedContentSql;
+ private PreparedStatement markUnusedSql;
+ private PreparedStatement markUsedSql;
+ private PreparedStatement removedExpiredSql;
+ private PreparedStatement getMimeType;
+ private PreparedStatement setMimeType;
+ private PreparedStatement getExtractedTextSql;
+ private PreparedStatement setExtractedTextSql;
+ private PreparedStatement getBinaryKeysSql;
+
/**
* Creates new instance of the database.
*
@@ -77,44 +134,216 @@
* @throws BinaryStoreException if the database type cannot be determined
*/
public Database( Connection connection ) throws BinaryStoreException {
- this.connection = connection;
- databaseType = determineType();
+ this(connection, null, null);
}
/**
- * Shows type of this database.
+ * Creates new instance of the database.
*
- * @return database type identifier.
+ * @param connection connection to a database
+ * @param type the type of database; may be null if the type is to be determined
+ * @param prefix the prefix for the table name; may be null or blank
+ * @throws BinaryStoreException if the database type cannot be determined
*/
- public Type getDatabaseType() {
- return databaseType;
+ public Database( Connection connection,
+ Type type,
+ String prefix ) throws BinaryStoreException {
+ assert connection != null;
+ this.connection = connection;
+ this.databaseType = type != null ? type : determineType();
+ this.prefix = prefix == null ? null : prefix.trim();
+ this.tableName = this.prefix != null && this.prefix.length() != 0 ? this.prefix + TABLE_NAME : TABLE_NAME;
+ LOGGER.debug("Discovered DBMS type for binary store as '{0}' on {1}", databaseType, connection);
+
+ try {
+ // Load the default statements ...
+ String statementsFilename = DEFAULT_STATEMENTS_FILE_PATH;
+ InputStream statementStream = getClass().getClassLoader().getResourceAsStream(statementsFilename);
+ Properties defaultStatements = new Properties();
+ try {
+ LOGGER.trace("Loading default statement from '{0}'", statementsFilename);
+ defaultStatements.load(statementStream);
+ } finally {
+ statementStream.close();
+ }
+
+ // Look for type-specific statements ...
+ statementsFilename = STATEMENTS_FILE_PATH + STATEMENTS_FILE_PREFIX + databaseType.name().toLowerCase()
+ + STATEMENTS_FILENAME_SUFFIX;
+ statementStream = getClass().getClassLoader().getResourceAsStream(statementsFilename);
+ if (statementStream != null) {
+ // Try to read the type-specific statements ...
+ try {
+ LOGGER.trace("Loading DBMS-specific statement from '{0}'", statementsFilename);
+ statements = new Properties(defaultStatements);
+ statements.load(statementStream);
+ } finally {
+ statementStream.close();
+ }
+ } else {
+ // No type-specific statements, so just use the default statements ...
+ statements = defaultStatements;
+ LOGGER.trace("No DBMS-specific statement found in '{0}'", statementsFilename);
+ }
+
+ } catch (IOException e) {
+ throw new BinaryStoreException(e);
+ }
}
/**
- * Modifies database type.
+ * Prepare this instance and the underlying database for usage.
*
- * @param databaseType new database type identifier.
+ * @throws BinaryStoreException if there is a problem
+ */
+ public void initialize() throws BinaryStoreException {
+ try {
+ // First, prepare a statement to see if the table exists ...
+ boolean createTable = true;
+ try {
+ PreparedStatement exists = prepareStatement("table_exists_query");
+ LOGGER.trace("Running statement: {0}", exists);
+ exists.execute();
+ exists.close();
+ createTable = false;
+ } catch (SQLException e) {
+ // proceed to create the table ...
+ }
+
+ if (createTable) {
+ LOGGER.debug("Unable to find existing table. Attempting to create '{0}' table in {1}", tableName, connection);
+ try {
+ PreparedStatement create = prepareStatement("create_table");
+ LOGGER.trace("Running statement: {0}", create);
+ create.execute();
+ create.close();
+ } catch (SQLException e) {
+ String msg = JcrI18n.errorCreatingDatabaseTable.text(tableName, databaseType, connection, e.getMessage());
+ throw new BinaryStoreException(msg);
+ }
+ }
+
+ // Now prepare all of the SQL statements ...
+ addContentSql = prepareStatement("add_content");
+ getUsedContentSql = prepareStatement("get_used_content");
+ getUnusedContentSql = prepareStatement("get_unused_content");
+ markUnusedSql = prepareStatement("mark_unused");
+ markUsedSql = prepareStatement("mark_used");
+ removedExpiredSql = prepareStatement("remove_expired");
+ getMimeType = prepareStatement("get_mimetype");
+ setMimeType = prepareStatement("set_mimetype");
+ getExtractedTextSql = prepareStatement("get_extracted_text");
+ setExtractedTextSql = prepareStatement("set_extracted_text");
+ getBinaryKeysSql = prepareStatement("get_binary_keys");
+ } catch (SQLException e) {
+ throw new BinaryStoreException(e);
+ }
+ }
+
+ protected PreparedStatement prepareStatement( String statementKey ) throws SQLException {
+ String statementString = statements.getProperty(statementKey);
+ statementString = StringUtil.createString(statementString, tableName);
+ LOGGER.trace("Preparing statement: {0}", statementString);
+ return connection.prepareStatement(statementString);
+ }
+
+ protected Type determineType() throws BinaryStoreException {
+ try {
+ String name = connection.getMetaData().getDatabaseProductName().toLowerCase();
+ if (name.toLowerCase().contains("mysql")) {
+ return Type.MYSQL;
+ } else if (name.contains("postgres")) {
+ return Type.POSTGRES;
+ } else if (name.contains("derby")) {
+ return Type.DERBY;
+ } else if (name.contains("hsql") || name.toLowerCase().contains("hypersonic")) {
+ return Type.HSQL;
+ } else if (name.contains("h2")) {
+ return Type.H2;
+ } else if (name.contains("sqlite")) {
+ return Type.SQLITE;
+ } else if (name.contains("db2")) {
+ return Type.DB2;
+ } else if (name.contains("informix")) {
+ return Type.INFORMIX;
+ } else if (name.contains("interbase")) {
+ return Type.INTERBASE;
+ } else if (name.contains("firebird")) {
+ return Type.FIREBIRD;
+ } else if (name.contains("sqlserver") || name.toLowerCase().contains("microsoft")) {
+ return Type.SQLSERVER;
+ } else if (name.contains("access")) {
+ return Type.ACCESS;
+ } else if (name.contains("oracle")) {
+ return Type.ORACLE;
+ } else if (name.contains("adaptive")) {
+ return Type.SYBASE;
+ }
+ return Type.UNKNOWN;
+ } catch (SQLException e) {
+ throw new BinaryStoreException(e);
+ }
+ }
+
+ /**
+ * Closes connection with database.
*/
- protected void setDatabaseType( Type databaseType ) {
- this.databaseType = databaseType;
+ public void disconnect() {
+ if (connection != null) {
+ boolean failed = false;
+ try {
+ if (addContentSql != null) addContentSql.close();
+ if (getUsedContentSql != null) getUsedContentSql.close();
+ if (getUnusedContentSql != null) getUnusedContentSql.close();
+ if (markUnusedSql != null) markUnusedSql.close();
+ if (markUsedSql != null) markUsedSql.close();
+ if (removedExpiredSql != null) removedExpiredSql.close();
+ if (getMimeType != null) getMimeType.close();
+ if (setMimeType != null) setMimeType.close();
+ if (getExtractedTextSql != null) getExtractedTextSql.close();
+ if (setExtractedTextSql != null) setExtractedTextSql.close();
+ if (getBinaryKeysSql != null) getBinaryKeysSql.close();
+ } catch (SQLException e) {
+ failed = true;
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ if (!failed) throw new RuntimeException(e);
+ } finally {
+ addContentSql = null;
+ getUsedContentSql = null;
+ getUnusedContentSql = null;
+ markUnusedSql = null;
+ markUsedSql = null;
+ removedExpiredSql = null;
+ getMimeType = null;
+ setMimeType = null;
+ getExtractedTextSql = null;
+ setExtractedTextSql = null;
+ getBinaryKeysSql = null;
+ }
+ }
+ }
}
/**
- * Configures table name prefix.
+ * The connection that this object is using.
*
- * @param prefix table name prefix.
+ * @return the connection; never null
*/
- public void setPrefix( String prefix ) {
- this.prefix = prefix;
+ public Connection getConnection() {
+ return connection;
}
/**
- * Convergence table name including prefix if configured.
+ * Shows type of this database.
*
- * @return table name.
+ * @return database type identifier.
*/
- private String tableName() {
- return StringUtil.isBlank(prefix) ? "CONTENT_STORE" : prefix + "_CONTENT_STORE";
+ public Type getDatabaseType() {
+ return databaseType;
}
/**
@@ -137,15 +366,10 @@ private long now() {
public PreparedStatement insertContentSQL( BinaryKey key,
InputStream stream ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.insert()
- .into(tableName())
- .columns("cid", "usage_time", "payload", "usage")
- .values("?", "?", "?", "1")
- .build();
- sql.setString(1, key.toString());
- sql.setTimestamp(2, new java.sql.Timestamp(now()));
- sql.setBinaryStream(3, stream);
- return sql;
+ addContentSql.setString(1, key.toString());
+ addContentSql.setTimestamp(2, new java.sql.Timestamp(now()));
+ addContentSql.setBinaryStream(3, stream);
+ return addContentSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -155,26 +379,16 @@ public PreparedStatement insertContentSQL( BinaryKey key,
* Generates SQL statement for content retrieve.
*
* @param key content id
- * @param inUse true if the binary given by the key is expected to be still be in use, or false if the binary can be no longer used
+ * @param inUse true if the binary given by the key is expected to be still be in use, or false if the binary can be no longer
+ * used
* @return executable SQL statement
* @throws BinaryStoreException
*/
- public PreparedStatement retrieveContentSQL( BinaryKey key, boolean inUse ) throws BinaryStoreException {
+ public PreparedStatement retrieveContentSQL( BinaryKey key,
+ boolean inUse ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.select()
- .columns("payload")
- .from(tableName())
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .and()
- .condition("usage", sqlType.integer(), "=", "?")
- .build();
+ PreparedStatement sql = inUse ? getUsedContentSql : getUnusedContentSql;
sql.setString(1, key.toString());
- if (inUse) {
- sql.setInt(2, 1);
- } else {
- sql.setInt(2, 0);
- }
return sql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
@@ -190,16 +404,9 @@ public PreparedStatement retrieveContentSQL( BinaryKey key, boolean inUse ) thro
*/
public PreparedStatement markUnusedSQL( BinaryKey key ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.update(tableName())
- .set("usage", "?")
- .set("usage_time", "?")
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setInt(1, 0);
- sql.setTimestamp(2, new java.sql.Timestamp(now()));
- sql.setString(3, key.toString());
- return sql;
+ markUnusedSql.setTimestamp(1, new java.sql.Timestamp(now()));
+ markUnusedSql.setString(2, key.toString());
+ return markUnusedSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -207,21 +414,15 @@ public PreparedStatement markUnusedSQL( BinaryKey key ) throws BinaryStoreExcept
/**
* Generates SQL statement which marks content as used.
- *
+ *
* @param key the content id.
* @return SQL statement.
* @throws BinaryStoreException
*/
public PreparedStatement restoreContentSQL( BinaryKey key ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.update(tableName())
- .set("usage", "?")
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setInt(1, 1);
- sql.setString(2, key.toString());
- return sql;
+ markUsedSql.setString(1, key.toString());
+ return markUsedSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -236,13 +437,8 @@ public PreparedStatement restoreContentSQL( BinaryKey key ) throws BinaryStoreEx
*/
public PreparedStatement removeExpiredContentSQL( long deadline ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.delete()
- .from(tableName())
- .where()
- .condition("usage_time", sqlType.timestamp(), "<", "?")
- .build();
- sql.setTimestamp(1, new java.sql.Timestamp(deadline));
- return sql;
+ removedExpiredSql.setTimestamp(1, new java.sql.Timestamp(deadline));
+ return removedExpiredSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -257,14 +453,8 @@ public PreparedStatement removeExpiredContentSQL( long deadline ) throws BinaryS
*/
public PreparedStatement retrieveMimeTypeSQL( BinaryKey key ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.select()
- .columns("mime_type")
- .from(tableName())
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setString(1, key.toString());
- return sql;
+ getMimeType.setString(1, key.toString());
+ return getMimeType;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -281,14 +471,9 @@ public PreparedStatement retrieveMimeTypeSQL( BinaryKey key ) throws BinaryStore
public PreparedStatement updateMimeTypeSQL( BinaryKey key,
String mimeType ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.update(tableName())
- .set("mime_type", "?")
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setString(1, mimeType);
- sql.setString(2, key.toString());
- return sql;
+ setMimeType.setString(1, mimeType);
+ setMimeType.setString(2, key.toString());
+ return setMimeType;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -303,14 +488,8 @@ public PreparedStatement updateMimeTypeSQL( BinaryKey key,
*/
public PreparedStatement retrieveExtTextSQL( BinaryKey key ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.select()
- .columns("ext_text")
- .from(tableName())
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setString(1, key.toString());
- return sql;
+ getExtractedTextSql.setString(1, key.toString());
+ return getExtractedTextSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -327,14 +506,9 @@ public PreparedStatement retrieveExtTextSQL( BinaryKey key ) throws BinaryStoreE
public PreparedStatement updateExtTextSQL( BinaryKey key,
String text ) throws BinaryStoreException {
try {
- PreparedStatement sql = sqlBuilder.update(tableName())
- .set("ext_text", "?")
- .where()
- .condition("cid", sqlType.integer(), "=", "?")
- .build();
- sql.setString(1, text);
- sql.setString(2, key.toString());
- return sql;
+ setExtractedTextSql.setString(1, text);
+ setExtractedTextSql.setString(2, key.toString());
+ return setExtractedTextSql;
} catch (SQLException e) {
throw new BinaryStoreException(e);
}
@@ -348,17 +522,7 @@ public PreparedStatement updateExtTextSQL( BinaryKey key,
* @throws BinaryStoreException
*/
public PreparedStatement retrieveBinaryKeys( Set<BinaryKey> keys ) throws BinaryStoreException {
- try {
- PreparedStatement sql = sqlBuilder.select()
- .columns("cid")
- .from(tableName())
- .where()
- .condition("usage", sqlType.integer(), "=", "1")
- .build();
- return sql;
- } catch (SQLException e) {
- throw new BinaryStoreException(e);
- }
+ return getBinaryKeysSql;
}
/**
@@ -369,6 +533,7 @@ public PreparedStatement retrieveBinaryKeys( Set<BinaryKey> keys ) throws Binary
*/
public static void execute( PreparedStatement sql ) throws BinaryStoreException {
try {
+ LOGGER.trace("Running statement: {0}", sql);
sql.execute();
} catch (SQLException e) {
throw new BinaryStoreException(e);
@@ -384,6 +549,7 @@ public static void execute( PreparedStatement sql ) throws BinaryStoreException
*/
public static ResultSet executeQuery( PreparedStatement sql ) throws BinaryStoreException {
try {
+ LOGGER.trace("Running statement: {0}", sql);
return sql.executeQuery();
} catch (SQLException e) {
throw new BinaryStoreException(e);
@@ -398,6 +564,7 @@ public static ResultSet executeQuery( PreparedStatement sql ) throws BinaryStore
*/
public static void executeUpdate( PreparedStatement sql ) throws BinaryStoreException {
try {
+ LOGGER.trace("Running statement: {0}", sql);
sql.executeUpdate();
} catch (SQLException e) {
throw new BinaryStoreException(e);
@@ -444,7 +611,7 @@ public static String asString( ResultSet rs ) throws BinaryStoreException {
/**
* Provides access to query data
- *
+ *
* @param rs retrieved query result
* @return result as string.
* @throws BinaryStoreException
@@ -461,370 +628,4 @@ public static String asString( ResultSet rs ) throws BinaryStoreException {
return result;
}
- /**
- * Checks database for CONTENT_STORE table
- *
- * @return true if table exists
- * @throws BinaryStoreException
- */
- public boolean tableExists() throws BinaryStoreException {
- try {
- PreparedStatement sql = connection.prepareStatement("select count(*) from " + tableName());
- Database.execute(sql);
- return true;
- } catch (SQLException e) {
- return false;
- }
- }
-
- /**
- * Creates table for storage.
- *
- * @throws BinaryStoreException
- */
- public void createTable() throws BinaryStoreException {
- try {
- PreparedStatement sql = connection.prepareStatement("create table " + tableName() + " (" + "cid "
- + sqlType.varchar(255) + " not null," + "mime_type "
- + sqlType.varchar(255) + ", " + "ext_text "
- + sqlType.varchar(1000) + "," + "usage " + sqlType.integer()
- + "," + "usage_time " + sqlType.timestamp() + "," + "payload "
- + sqlType.blob() + "," + "primary key(cid))");
- Database.execute(sql);
- } catch (Exception e) {
- throw new BinaryStoreException(e);
- }
- }
-
- private Type determineType() throws BinaryStoreException {
- if (connection == null) {
- return Type.UNKNOWN;
- }
- try {
- String name = connection.getMetaData().getDatabaseProductName().toLowerCase();
- if (name.toLowerCase().contains("mysql")) {
- return Type.MYSQL;
- } else if (name.contains("postgres")) {
- return Type.POSTGRES;
- } else if (name.contains("derby")) {
- return Type.DERBY;
- } else if (name.contains("hsql") || name.toLowerCase().contains("hypersonic")) {
- return Type.HSQL;
- } else if (name.contains("h2")) {
- return Type.H2;
- } else if (name.contains("sqlite")) {
- return Type.SQLITE;
- } else if (name.contains("db2")) {
- return Type.DB2;
- } else if (name.contains("informix")) {
- return Type.INFORMIX;
- } else if (name.contains("interbase")) {
- return Type.INTERBASE;
- } else if (name.contains("firebird")) {
- return Type.FIREBIRD;
- } else if (name.contains("sqlserver") || name.toLowerCase().contains("microsoft")) {
- return Type.SQL_SERVER;
- } else if (name.contains("access")) {
- return Type.ACCESS;
- } else if (name.contains("oracle")) {
- return Type.ORACLE;
- } else if (name.contains("adaptive")) {
- return Type.SYBASE;
- }
- return Type.UNKNOWN;
- } catch (SQLException e) {
- throw new BinaryStoreException(e);
- }
- }
-
- /**
- * Closes connection with database.
- */
- public void disconnect() {
- if (connection != null) {
- try {
- connection.close();
- } catch (SQLException e) {
- }
- }
- }
-
- /**
- * Database specific SQL types
- */
- private class SQLType {
-
- protected SQLType() {
- }
-
- /**
- * Integer type.
- *
- * @return integer type descriptor.
- */
- public String integer() {
- return "INTEGER";
- }
-
- /**
- * Timestamp type.
- *
- * @return timestamp type descriptor.
- */
- public String timestamp() {
- return "TIMESTAMP";
- }
-
- /**
- * BLOB type.
- *
- * @return BLOB type descriptor.
- */
- protected String blob() {
- switch (databaseType) {
- case SQL_SERVER:
- case SYBASE:
- return "IMAGE";
- case HSQL:
- return "OBJECT";
- default:
- return "BLOB";
- }
- }
-
- /**
- * VARCHAR type.
- *
- * @param size size in characters.
- * @return VACRCHAR type descriptor.
- */
- protected String varchar( int size ) {
- switch (databaseType) {
- case ORACLE:
- return "VARCHAR2(" + size + ")";
- default:
- return "VARCHAR(" + size + ")";
- }
- }
- }
-
- /**
- * Database specific SQL query builder.
- */
- public class SQLBuilder {
- private boolean set = false;
-
- // inner buffer for building sql string
- private StringBuilder sql;
-
- /**
- * Generates prepared statement.
- *
- * @return prepared statement
- * @throws SQLException
- */
- public PreparedStatement build() throws SQLException {
- return connection.prepareStatement(sql.toString());
- }
-
- /**
- * Shows built statement as text.
- *
- * @return build statement as text.
- */
- public String getSQL() {
- return sql.toString();
- }
-
- /**
- * Appends 'insert' keyword to the statement.
- *
- * @return this builder instance.
- */
- public SQLBuilder insert() {
- set = false;
- sql = new StringBuilder();
- sql.append("INSERT ");
- return this;
- }
-
- /**
- * Appends 'select' keyword to the statement.
- *
- * @return this builder instance.
- */
- public SQLBuilder select() {
- set = false;
- sql = new StringBuilder();
- sql.append("SELECT ");
- return this;
- }
-
- /**
- * Appends 'delete' keyword to the statement.
- *
- * @return this builder instance.
- */
- public SQLBuilder delete() {
- set = false;
- sql = new StringBuilder();
- sql.append("DELETE ");
- return this;
- }
-
- /**
- * Appends 'update' keyword with table name to the statement.
- *
- * @param tableName the name of the table to update
- * @return this builder instance.
- */
- public SQLBuilder update( String tableName ) {
- set = false;
- sql = new StringBuilder();
- sql.append("UPDATE ");
- sql.append(tableName);
- return this;
- }
-
- /**
- * Appends 'set' part.
- *
- * @param col column name to update
- * @param val new value
- * @return this builder instance
- */
- public SQLBuilder set( String col,
- String val ) {
- if (!set) {
- sql.append(" SET ");
- set = true;
- } else {
- sql.append(", ");
- }
- sql.append(col);
- sql.append("=");
- sql.append(val);
- return this;
- }
-
- /**
- * Appends 'into 'keyword and open bracket to the statement.
- *
- * @param tableName the name of the table; may not be null
- * @return this builder instance.
- */
- public SQLBuilder into( String tableName ) {
- sql.append("INTO ");
- sql.append(tableName);
- sql.append(" (");
- return this;
- }
-
- /**
- * Appends comma separated list of specified column names.
- *
- * @param columns list of column names
- * @return this builder instance.
- */
- public SQLBuilder columns( String... columns ) {
- sql.append(columns[0]);
-
- for (int i = 1; i < columns.length; i++) {
- sql.append(", ");
- sql.append(columns[i]);
- }
-
- return this;
- }
-
- /**
- * Appends closed bracket and 'value(...)' of sql statement.
- *
- * @param columns list of values
- * @return this builder instance.
- */
-
- public SQLBuilder values( String... columns ) {
- sql.append(") VALUES (");
- sql.append(columns[0]);
-
- for (int i = 1; i < columns.length; i++) {
- sql.append(", ");
- sql.append(columns[i]);
- }
-
- sql.append(")");
- return this;
- }
-
- /**
- * Appends 'from' keyword.
- *
- * @param tableName the name of the table; may not be null
- * @return this builder instance.
- */
- public SQLBuilder from( String tableName ) {
- sql.append(" FROM ");
- sql.append(tableName);
- return this;
- }
-
- /**
- * Appends 'where' keyword.
- *
- * @return this builder instance.
- */
- public SQLBuilder where() {
- sql.append(" WHERE ");
- return this;
- }
-
- /**
- * Appends 'and' keyword.
- *
- * @return this builder instance.
- */
- public SQLBuilder and() {
- sql.append(" AND ");
- return this;
- }
-
- /**
- * Builds database specific condition statement.
- *
- * @param column column name used in left hand side of condition
- * @param colType type of the column
- * @param sign sign between lhs and rhs
- * @param value right hand side of the condition
- * @return this builder instance.
- */
- public SQLBuilder condition( String column,
- String colType,
- String sign,
- String value ) {
- sql.append(column);
- sql.append(sign);
- switch (databaseType) {
- case SYBASE:
- sql.append("convert(");
- sql.append(colType);
- sql.append(",");
- sql.append(value);
- sql.append(")");
- break;
- case POSTGRES:
- sql.append("cast(");
- sql.append(value);
- sql.append(" as ");
- sql.append(colType);
- sql.append(")");
- break;
- default:
- sql.append(value);
- }
- return this;
- }
-
- }
-
}
View
56 modeshape-jcr/src/main/java/org/modeshape/jcr/value/binary/DatabaseBinaryStore.java
@@ -44,6 +44,47 @@
/**
* A {@link BinaryStore} implementation that uses a database for persisting binary values.
+ * <p>
+ * This binary store implementation establishes a connection to the specified database and then attempts to determine which type
+ * of database is being used. ModeShape is aware of the following database types:
+ * <ul>
+ * <li><code>mysql</code></li>
+ * <li><code>postgres</code></li>
+ * <li><code>derby</code></li>
+ * <li><code>hsql</code></li>
+ * <li><code>h2</code></li>
+ * <li><code>sqlite</code></li>
+ * <li><code>db2</code></li>
+ * <li><code>db2_390</code></li>
+ * <li><code>informix</code></li>
+ * <li><code>interbase</code></li>
+ * <li><code>firebird</code></li>
+ * <li><code>sqlserver</code></li>
+ * <li><code>access</code></li>
+ * <li><code>oracle</code></li>
+ * <li><code>sybase</code></li>
+ * </ul>
+ * This binary store implementation then uses DDL and DML statements to create the table(s) if not already existing and to perform
+ * the various operations required of a binary store. ModeShape can use database-specific statements, although a default set of
+ * SQL-99 statements are used as a fallback.
+ * </p>
+ * <p>
+ * These statements are read from a property file named "<code>binary_store_{type}_database.properties</code>", where where "
+ * <code>{type}</code>" is one of the above-mentioned database type strings. These properties files are expected to be found on
+ * the classpath directly under "org/modeshape/jcr/database". If the corresponding file is not found on the classpath, then the "
+ * <code>binary_store_default_database.properties</code>" file provided by ModeShape is used.
+ * </p>
+ * <p>
+ * ModeShape provides out-of-the-box database-specific files for several of the DBMSes that are popular within the open source
+ * community. The properties files for the other database types are not provided (though the ModeShape community will gladly
+ * incorporate them if you wish to make them available to us); in such cases, simply copy one of the provided properties files
+ * (e.g., "<code>binary_store_default_database.properties</code>" is often a good start) and customize it for your particular
+ * DBMS, naming it according to the pattern described above and including it on the classpath.
+ * </p>
+ * <p>
+ * Note that this mechanism can also be used to override the statements that ModeShape does provide out-of-the-box. In such cases,
+ * be sure to place the file on the classpath before the ModeShape JARs so that your file will be discovered first.
+ * </p>
*/
@ThreadSafe
public class DatabaseBinaryStore extends AbstractBinaryStore {
@@ -137,7 +178,7 @@ public InputStream getInputStream( BinaryKey key ) throws BinaryStoreException {
InputStream inputStream = Database.asStream(rs);
if (inputStream == null) {
try {
- throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(key, database.connection.getCatalog()));
+ throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(key, database.getConnection().getCatalog()));
} catch (SQLException e) {
logger.debug(e, "Unable to retrieve db information");
}
@@ -172,8 +213,8 @@ protected String getStoredMimeType( BinaryValue source ) throws BinaryStoreExcep
private void checkContentExists( BinaryValue source ) throws BinaryStoreException {
if (!contentExists(source.getKey(), true)) {
try {
- throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(source.getKey(),
- database.connection.getCatalog()));
+ throw new BinaryStoreException(JcrI18n.unableToFindBinaryValue.text(source.getKey(), database.getConnection()
+ .getCatalog()));
} catch (SQLException e) {
logger.debug("Cannot get catalog information", e);
}
@@ -210,14 +251,11 @@ public void start() {
username,
password);
- // TODO: here we are making decision which kind of database we will talk to.
- // Right now, we just have one kind of utility, and no specializations for specific databases
- // DatabaseMetaData metaData = connection.getMetaData();
+ // Create the database helper that behaves differently based upon the type of database
database = new Database(connection);
- if (!database.tableExists()) {
- database.createTable();
- }
+ // Initialize the helper and database, creating the database table if it is missing ...
+ database.initialize();
} catch (Exception e) {
throw new RuntimeException(e);
}
View
2  modeshape-jcr/src/main/resources/org/modeshape/jcr/JcrI18n.properties
@@ -455,3 +455,5 @@ errorRemovingProjection = Removing the projection in workspace '{0}' at '{1}' (w
reindexMissingNoIndexesExist = Re-indexing only missing indexes for repository {0}. Since no indexes exist, all content will be re-indexed.
noReindex = Index rebuild mode for repository {0} is 'never' and there aren't any indexes. Any content which already exists will not be available to queries.
reindexAll = All content will be re-indexed for repository {0}.
+
+errorCreatingDatabaseTable = Error attemting to create the database table '{0}' in '{1}' database at {2}: {3}
View
46 ...cr/src/main/resources/org/modeshape/jcr/database/binary_store_default_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage INTEGER, \
+ usage_time TIMESTAMP, \
+ payload BLOB, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = ? AND usage=1
+get_unused_content = SELECT payload FROM {0} WHERE cid = ? AND usage=0
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage=0, usage_time = ? WHERE cid = ?
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage=1 WHERE cid = ?
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < ?
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = ?
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = ?
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = ?
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = ?
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage = 1
View
46 ...e-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_hsql_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage INTEGER, \
+ usage_time TIMESTAMP, \
+ payload OBJECT, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = ? AND usage=1
+get_unused_content = SELECT payload FROM {0} WHERE cid = ? AND usage=0
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage=0, usage_time = ? WHERE cid = ?
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage=1 WHERE cid = ?
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < ?
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = ?
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = ?
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = ?
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = ?
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage = 1
View
46 ...-jcr/src/main/resources/org/modeshape/jcr/database/binary_store_mysql_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage_flag INTEGER, \
+ usage_time TIMESTAMP, \
+ payload LARGEBLOB, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage_flag) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = ? AND usage_flag=1
+get_unused_content = SELECT payload FROM {0} WHERE cid = ? AND usage_flag=0
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage_flag=0, usage_time = ? WHERE cid = ?
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage_flag=1 WHERE cid = ?
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < ?
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = ?
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = ?
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = ?
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = ?
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage_flag = 1
View
46 ...jcr/src/main/resources/org/modeshape/jcr/database/binary_store_oracle_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR2(255) NOT NULL, \
+ mime_type VARCHAR2(255), \
+ ext_text VARCHAR2(1000), \
+ usage INTEGER, \
+ usage_time TIMESTAMP, \
+ payload BLOB, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = ? AND usage=1
+get_unused_content = SELECT payload FROM {0} WHERE cid = ? AND usage=0
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage=0, usage_time = ? WHERE cid = ?
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage=1 WHERE cid = ?
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < ?
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = ?
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = ?
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = ?
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = ?
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage = 1
View
46 ...r/src/main/resources/org/modeshape/jcr/database/binary_store_postgres_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage_flag INTEGER, \
+ usage_time TIMESTAMP, \
+ payload BLOB, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage_flag) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = CAST(? AS INTEGER) AND usage_flag = CAST(1 AS INTEGER)
+get_unused_content = SELECT payload FROM {0} WHERE cid = CAST(? AS INTEGER) AND usage_flag = CAST(0 AS INTEGER)
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage_flag=0, usage_time = ? WHERE cid = CAST(? AS INTEGER)
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage_flag=1 WHERE cid = CAST(? AS INTEGER)
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < CAST(? AS TIMESTAMP)
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = CAST(? AS INTEGER)
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = CAST(? AS INTEGER)
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = CAST(? AS INTEGER)
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = CAST(? AS INTEGER)
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage_flag = CAST(1 AS INTEGER)
View
46 .../src/main/resources/org/modeshape/jcr/database/binary_store_sqlserver_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage_flag INTEGER, \
+ usage_time TIMESTAMP, \
+ payload IMAGE, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage_flag) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = ? AND usage_flag=1
+get_unused_content = SELECT payload FROM {0} WHERE cid = ? AND usage_flag=0
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage_flag=0, usage_time = ? WHERE cid = ?
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage_flag=1 WHERE cid = ?
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < ?
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = ?
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = ?
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = ?
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = ?
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage_flag = 1
View
46 ...jcr/src/main/resources/org/modeshape/jcr/database/binary_store_sybase_database.properties
@@ -0,0 +1,46 @@
+# In all of the following statements, the '{0}' variable represents the table name
+
+# The statement that creates the table.
+create_table = CREATE TABLE {0} ( \
+ cid VARCHAR(255) NOT NULL, \
+ mime_type VARCHAR(255), \
+ ext_text VARCHAR(1000), \
+ usage_flag INTEGER, \
+ usage_time TIMESTAMP, \
+ payload IMAGE, \
+ primary key(cid) \
+ )
+
+# The query that is used to determine if the table already exists by returning any result set.
+table_exists_query = SELECT COUNT(*) FROM {0}
+
+# Insert a new binary value into the table
+add_content = INSERT INTO {0} (cid, usage_time, payload, usage_flag) VALUES ( ?,?,?,1 )
+
+# Get the content for the binary with the supplied key
+get_used_content = SELECT payload FROM {0} WHERE cid = CONVERT(INTEGER,?) AND usage_flag = CONVERT(INTEGER,1)
+get_unused_content = SELECT payload FROM {0} WHERE cid = CONVERT(INTEGER,?) AND usage_flag = CONVERT(INTEGER,0)
+
+# Mark the binary with the specified key as being unused
+mark_unused = UPDATE {0} SET usage_flag=0, usage_time = ? WHERE cid = CONVERT(INTEGER,?)
+
+# Mark the binary with the specified key as being used
+mark_used = UPDATE {0} SET usage_flag=1 WHERE cid = CONVERT(INTEGER,?)
+
+# Remove all rows that have been unused for less than the supplied time
+remove_expired = DELETE FROM {0} WHERE usage_time < CONVERT(TIMESTAMP,1)
+
+# Get the MIME type for the binary with the specified key
+get_mimetype = SELECT mime_type FROM {0} WHERE cid = CONVERT(INTEGER,?)
+
+# Set the MIME type for the binary with the specified key
+set_mimetype = UPDATE {0} SET mime_type = ? WHERE cid = CONVERT(INTEGER,?)
+
+# Get the text that was extracted from the binary with the specified key
+get_extracted_text = SELECT ext_text FROM {0} WHERE cid = CONVERT(INTEGER,?)
+
+# Set the text that was extracted from the binary with the specified key
+set_extracted_text = UPDATE {0} SET ext_text = ? WHERE cid = CONVERT(INTEGER,?)
+
+# Get all of the binary keys
+get_binary_keys = SELECT cid FROM {0} WHERE usage_flag = CONVERT(INTEGER,1)
View
131 modeshape-jcr/src/test/java/org/modeshape/jcr/value/binary/DatabaseTest.java
@@ -1,131 +0,0 @@
-/*
- * To change this template, choose Tools | Templates
- * and open the template in the editor.
- */
-package org.modeshape.jcr.value.binary;
-
-import static org.junit.Assert.assertEquals;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/**
- * @author kulikov
- */
-public class DatabaseTest {
-
- private Database database;
- private Database.SQLBuilder sqlBuilder;
-
- public DatabaseTest() {
- }
-
- @BeforeClass
- public static void setUpClass() throws Exception {
- }
-
- @AfterClass
- public static void tearDownClass() throws Exception {
- }
-
- @Before
- public void setUp() throws BinaryStoreException {
- database = new Database(null);
- sqlBuilder = database.new SQLBuilder();
- }
-
- @After
- public void tearDown() {
- }
-
- @Test
- public void testDefaultInsertStatementBuilding() {
- String sql = sqlBuilder.insert().into("xxx").columns("c1", "c2", "c3").values("?", "?", "?").getSQL().toLowerCase();
- assertEquals("insert into xxx (c1, c2, c3) values (?, ?, ?)", sql);
- }
-
- @Test
- public void testDefaultSelectStatement() {
- String sql = sqlBuilder.select()
- .columns("c1", "c2", "c3")
- .from("xxx")
- .where()
- .condition("c1", "integer", "<", "?")
- .and()
- .condition("c2", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- assertEquals("select c1, c2, c3 from xxx where c1<? and c2=?", sql);
- }
-
- @Test
- public void testDefaultDeleteStatement() {
- String sql = sqlBuilder.delete()
- .from("xxx")
- .where()
- .condition("c1", "integer", "<", "?")
- .and()
- .condition("c2", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- assertEquals("delete from xxx where c1<? and c2=?", sql);
- }
-
- @Test
- public void testDefaultUpdateStatement() {
- String sql = sqlBuilder.update("xxx")
- .set("c1", "?")
- .where()
- .condition("c1", "integer", "<", "?")
- .and()
- .condition("c2", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- assertEquals("update xxx set c1=? where c1<? and c2=?", sql);
- }
-
- @Test
- public void testDefaultUpdateStatement2() {
- String sql = sqlBuilder.update("content_store")
- .set("usage", "?")
- .set("timestamp", "?")
- .where()
- .condition("id", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- System.out.println(sql);
- }
-
- @Test
- public void testSybaseSelectStatement() {
- database.setDatabaseType(Database.Type.SYBASE);
- String sql = sqlBuilder.select()
- .columns("c1", "c2", "c3")
- .from("xxx")
- .where()
- .condition("c1", "integer", "<", "?")
- .and()
- .condition("c2", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- assertEquals("select c1, c2, c3 from xxx where c1<convert(integer,?) and c2=convert(integer,?)", sql);
- }
-
- @Test
- public void testPostgresSelectStatement() {
- database.setDatabaseType(Database.Type.POSTGRES);
- String sql = sqlBuilder.select()
- .columns("c1", "c2", "c3")
- .from("xxx")
- .where()
- .condition("c1", "integer", "<", "?")
- .and()
- .condition("c2", "integer", "=", "?")
- .getSQL()
- .toLowerCase();
- assertEquals("select c1, c2, c3 from xxx where c1<cast(? as integer) and c2=cast(? as integer)", sql);
- }
-
-}
View
2  modeshape-jcr/src/test/resources/log4j.properties
@@ -19,10 +19,12 @@ log4j.logger.com.mchange.v2.c3p0=WARN
log4j.logger.org.apache.jackrabbit.test=WARN
log4j.logger.org.modeshape.jcr.tck=WARN
log4j.logger.org.modeshape.jcr.ModeShapeTckTest=WARN
+
#log4j.logger.org.modeshape.jcr.query=TRACE
#log4j.logger.org.modeshape.jcr.cache=TRACE
#log4j.logger.org.modeshape.jcr.txn=TRACE
#log4j.logger.org.modeshape.jcr.sequencing=DEBUG
+#log4j.logger.org.modeshape.jcr.value.binary.Database=TRACE
# This line turns on detailed log messages
#log4j.logger.org.modeshape=DEBUG
Please sign in to comment.
Something went wrong with that request. Please try again.