REPO-4180: Service Pack: MNT-20305 Oracle schema validation check failure with ojdbc7.jar version 12.1.0.2

- fixed regression in SchemaBootstrap that cause the schema validation to not be done
   - added support for custom sequences retrieval (active if only schema reference sequences file exists)
   - added dialect and script utility classes
   - refactored ExportDb, ScriptExecutorImpl and SchemaBootstrap to use the utility classes to reduce code duplication
This commit is contained in:
Cristian Turlica
2019-02-28 11:40:16 +02:00
committed by GitHub
parent 328e729405
commit 0507f2ad4d
5 changed files with 3854 additions and 3649 deletions

View File

@@ -52,7 +52,6 @@ import java.sql.SQLXML;
import java.sql.Savepoint; import java.sql.Savepoint;
import java.sql.Statement; import java.sql.Statement;
import java.sql.Struct; import java.sql.Struct;
import java.sql.Types;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
@@ -82,6 +81,7 @@ import org.alfresco.repo.domain.patch.AppliedPatchDAO;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.descriptor.DescriptorService; import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.util.DatabaseMetaDataHelper; import org.alfresco.util.DatabaseMetaDataHelper;
import org.alfresco.util.DialectUtil;
import org.alfresco.util.LogUtil; import org.alfresco.util.LogUtil;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
@@ -111,9 +111,6 @@ import org.springframework.extensions.surf.util.I18NUtil;
*/ */
public class SchemaBootstrap extends AbstractLifecycleBean public class SchemaBootstrap extends AbstractLifecycleBean
{ {
/** The placeholder for the configured <code>Dialect</code> class name: <b>${db.script.dialect}</b> */
private static final String PLACEHOLDER_DIALECT = "\\$\\{db\\.script\\.dialect\\}";
/** The global property containing the default batch size used by --FOREACH */ /** The global property containing the default batch size used by --FOREACH */
private static final String PROPERTY_DEFAULT_BATCH_SIZE = "system.upgrade.default.batchsize"; private static final String PROPERTY_DEFAULT_BATCH_SIZE = "system.upgrade.default.batchsize";
@@ -323,7 +320,6 @@ public class SchemaBootstrap extends AbstractLifecycleBean
* type (e.g. PostgreSQL) * type (e.g. PostgreSQL)
* *
* @param schemaReferenceUrls the schemaReferenceUrls to set * @param schemaReferenceUrls the schemaReferenceUrls to set
* @see #PLACEHOLDER_DIALECT
*/ */
public void setSchemaReferenceUrls(List<String> schemaReferenceUrls) public void setSchemaReferenceUrls(List<String> schemaReferenceUrls)
{ {
@@ -1155,64 +1151,11 @@ public class SchemaBootstrap extends AbstractLifecycleBean
try { scriptInputStream.close(); } catch (Throwable e) {} // usually a duplicate close try { scriptInputStream.close(); } catch (Throwable e) {} // usually a duplicate close
} }
// now execute it // now execute it
String dialectScriptUrl = scriptUrl.replaceAll(PLACEHOLDER_DIALECT, dialect.getClass().getName()); String dialectScriptUrl = scriptUrl.replaceAll(DialectUtil.PLACEHOLDER_DIALECT, dialect.getClass().getName());
// Replace the script placeholders // Replace the script placeholders
executeScriptFile(connection, tempFile, dialectScriptUrl); executeScriptFile(connection, tempFile, dialectScriptUrl);
} }
/**
* Replaces the dialect placeholder in the resource URL and attempts to find a file for
* it. If not found, the dialect hierarchy will be walked until a compatible resource is
* found. This makes it possible to have resources that are generic to all dialects.
*
* @return The Resource, otherwise null
*/
private Resource getDialectResource(Class<?> dialectClass, String resourceUrl)
{
// replace the dialect placeholder
String dialectResourceUrl = resolveDialectUrl(dialectClass, resourceUrl);
// get a handle on the resource
Resource resource = rpr.getResource(dialectResourceUrl);
if (!resource.exists())
{
// it wasn't found. Get the superclass of the dialect and try again
Class<?> superClass = dialectClass.getSuperclass();
if (Dialect.class.isAssignableFrom(superClass))
{
// we still have a Dialect - try again
return getDialectResource(superClass, resourceUrl);
}
else
{
// we have exhausted all options
return null;
}
}
else
{
// we have a handle to it
return resource;
}
}
/**
* Takes resource URL containing the {@link SchemaBootstrap#PLACEHOLDER_DIALECT dialect placeholder text}
* and substitutes the placeholder with the name of the given dialect's class.
* <p/>
* For example:
* <pre>
* resolveDialectUrl(MySQLInnoDBDialect.class, "classpath:alfresco/db/${db.script.dialect}/myfile.xml")
* </pre>
* would give the following String:
* <pre>
* classpath:alfresco/db/org.hibernate.dialect.MySQLInnoDBDialect/myfile.xml
* </pre>
*/
private String resolveDialectUrl(Class<?> dialectClass, String resourceUrl)
{
return resourceUrl.replaceAll(PLACEHOLDER_DIALECT, dialectClass.getName());
}
/** /**
* Replaces the dialect placeholder in the script URL and attempts to find a file for * Replaces the dialect placeholder in the script URL and attempts to find a file for
* it. If not found, the dialect hierarchy will be walked until a compatible script is * it. If not found, the dialect hierarchy will be walked until a compatible script is
@@ -1222,7 +1165,7 @@ public class SchemaBootstrap extends AbstractLifecycleBean
*/ */
private InputStream getScriptInputStream(Class<?> dialectClazz, String scriptUrl) throws Exception private InputStream getScriptInputStream(Class<?> dialectClazz, String scriptUrl) throws Exception
{ {
Resource resource = getDialectResource(dialectClazz, scriptUrl); Resource resource = DialectUtil.getDialectResource(rpr, dialectClazz, scriptUrl);
if (resource == null) if (resource == null)
{ {
throw new AlfrescoRuntimeException("Script [ " + scriptUrl + " ] can't be found for " + dialectClazz); throw new AlfrescoRuntimeException("Script [ " + scriptUrl + " ] can't be found for " + dialectClazz);
@@ -1749,8 +1692,12 @@ public class SchemaBootstrap extends AbstractLifecycleBean
{ {
// Remove the flag indicating a running bootstrap // Remove the flag indicating a running bootstrap
setBootstrapCompleted(connection); setBootstrapCompleted(connection);
// Validate the schema, post-upgrade
validateSchema("Alfresco-{0}-Validation-Post-Upgrade-{1}-", null);
// 4.0+ schema dump
dumpSchema("post-upgrade");
} }
reportNormalizedDumps();
} }
else else
{ {
@@ -1804,17 +1751,6 @@ public class SchemaBootstrap extends AbstractLifecycleBean
} }
} }
private void reportNormalizedDumps()
{
if (executedStatementsThreadLocal.get() != null)
{
// Validate the schema, post-upgrade
validateSchema("Alfresco-{0}-Validation-Post-Upgrade-{1}-", null);
// 4.0+ schema dump
dumpSchema("post-upgrade");
}
}
private void writeLogsWithDBStatementExecuted() private void writeLogsWithDBStatementExecuted()
{ {
// Copy the executed statements to the output file // Copy the executed statements to the output file
@@ -1861,11 +1797,11 @@ public class SchemaBootstrap extends AbstractLifecycleBean
// and process each in turn. // and process each in turn.
for (String schemaReferenceUrl : schemaReferenceUrls) for (String schemaReferenceUrl : schemaReferenceUrls)
{ {
Resource referenceResource = getDialectResource(dialect.getClass(), schemaReferenceUrl); Resource referenceResource = DialectUtil.getDialectResource(rpr, dialect.getClass(), schemaReferenceUrl);
if (referenceResource == null || !referenceResource.exists()) if (referenceResource == null || !referenceResource.exists())
{ {
String resourceUrl = resolveDialectUrl(dialect.getClass(), schemaReferenceUrl); String resourceUrl = DialectUtil.resolveDialectUrl(dialect.getClass(), schemaReferenceUrl);
LogUtil.debug(logger, DEBUG_SCHEMA_COMP_NO_REF_FILE, resourceUrl); LogUtil.debug(logger, DEBUG_SCHEMA_COMP_NO_REF_FILE, resourceUrl);
} }
else else

View File

@@ -47,6 +47,7 @@ import org.alfresco.repo.domain.dialect.Dialect;
import org.alfresco.repo.domain.dialect.MySQLInnoDBDialect; import org.alfresco.repo.domain.dialect.MySQLInnoDBDialect;
import org.alfresco.repo.domain.dialect.PostgreSQLDialect; import org.alfresco.repo.domain.dialect.PostgreSQLDialect;
import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.util.DialectUtil;
import org.alfresco.util.LogUtil; import org.alfresco.util.LogUtil;
import org.alfresco.util.TempFileProvider; import org.alfresco.util.TempFileProvider;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@@ -58,8 +59,6 @@ import org.springframework.core.io.support.ResourcePatternResolver;
public class ScriptExecutorImpl implements ScriptExecutor public class ScriptExecutorImpl implements ScriptExecutor
{ {
/** The placeholder for the configured <code>Dialect</code> class name: <b>${db.script.dialect}</b> */
private static final String PLACEHOLDER_DIALECT = "\\$\\{db\\.script\\.dialect\\}";
/** The global property containing the default batch size used by --FOREACH */ /** The global property containing the default batch size used by --FOREACH */
private static final String PROPERTY_DEFAULT_BATCH_SIZE = "system.upgrade.default.batchsize"; private static final String PROPERTY_DEFAULT_BATCH_SIZE = "system.upgrade.default.batchsize";
private static final String MSG_EXECUTING_GENERATED_SCRIPT = "schema.update.msg.executing_generated_script"; private static final String MSG_EXECUTING_GENERATED_SCRIPT = "schema.update.msg.executing_generated_script";
@@ -186,68 +185,11 @@ public class ScriptExecutorImpl implements ScriptExecutor
try { scriptInputStream.close(); } catch (Throwable e) {} // usually a duplicate close try { scriptInputStream.close(); } catch (Throwable e) {} // usually a duplicate close
} }
// now execute it // now execute it
String dialectScriptUrl = scriptUrl.replaceAll(PLACEHOLDER_DIALECT, dialect.getClass().getName()); String dialectScriptUrl = scriptUrl.replaceAll(DialectUtil.PLACEHOLDER_DIALECT, dialect.getClass().getName());
// Replace the script placeholders // Replace the script placeholders
executeScriptFile(connection, tempFile, dialectScriptUrl); executeScriptFile(connection, tempFile, dialectScriptUrl);
} }
/**
* Replaces the dialect placeholder in the resource URL and attempts to find a file for
* it. If not found, the dialect hierarchy will be walked until a compatible resource is
* found. This makes it possible to have resources that are generic to all dialects.
*
* @return The Resource, otherwise null
*/
private Resource getDialectResource(Class dialectClass, String resourceUrl)
{
// replace the dialect placeholder
String dialectResourceUrl = resolveDialectUrl(dialectClass, resourceUrl);
// get a handle on the resource
Resource resource = rpr.getResource(dialectResourceUrl);
if (!resource.exists())
{
// it wasn't found. Get the superclass of the dialect and try again
Class superClass = dialectClass.getSuperclass();
if (Dialect.class.isAssignableFrom(superClass))
{
// we still have a Dialect - try again
return getDialectResource(superClass, resourceUrl);
}
else
{
// we have exhausted all options
return null;
}
}
else
{
// we have a handle to it
return resource;
}
}
/**
* Takes resource URL containing the {@link ScriptExecutorImpl#PLACEHOLDER_DIALECT dialect placeholder text}
* and substitutes the placeholder with the name of the given dialect's class.
* <p/>
* For example:
* <pre>
* resolveDialectUrl(MySQLInnoDBDialect.class, "classpath:alfresco/db/${db.script.dialect}/myfile.xml")
* </pre>
* would give the following String:
* <pre>
* classpath:alfresco/db/org.hibernate.dialect.MySQLInnoDBDialect/myfile.xml
* </pre>
*
* @param dialectClass Class
* @param resourceUrl String
* @return String
*/
private String resolveDialectUrl(Class dialectClass, String resourceUrl)
{
return resourceUrl.replaceAll(PLACEHOLDER_DIALECT, dialectClass.getName());
}
/** /**
* Replaces the dialect placeholder in the script URL and attempts to find a file for * Replaces the dialect placeholder in the script URL and attempts to find a file for
* it. If not found, the dialect hierarchy will be walked until a compatible script is * it. If not found, the dialect hierarchy will be walked until a compatible script is
@@ -257,7 +199,7 @@ public class ScriptExecutorImpl implements ScriptExecutor
*/ */
private InputStream getScriptInputStream(Class dialectClazz, String scriptUrl) throws Exception private InputStream getScriptInputStream(Class dialectClazz, String scriptUrl) throws Exception
{ {
Resource resource = getDialectResource(dialectClazz, scriptUrl); Resource resource = DialectUtil.getDialectResource(rpr, dialectClazz, scriptUrl);
if (resource == null) if (resource == null)
{ {
return null; return null;

View File

@@ -0,0 +1,107 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.util;
import java.io.IOException;
import java.io.LineNumberReader;
import org.springframework.core.io.support.EncodedResource;
public abstract class DBScriptUtil
{
private static final String DEFAULT_SCRIPT_COMMENT_PREFIX = "--";
/**
* Read a script from the provided EncodedResource and build a String containing
* the lines.
*
* @param resource
* the resource (potentially associated with a specific encoding) to
* load the SQL script from
* @return a String containing the script lines
*/
public static String readScript(EncodedResource resource) throws IOException
{
return readScript(resource, DEFAULT_SCRIPT_COMMENT_PREFIX);
}
/**
* Read a script from the provided EncodedResource, using the supplied line
* comment prefix, and build a String containing the lines.
*
* @param resource
* the resource (potentially associated with a specific encoding) to
* load the SQL script from
* @param lineCommentPrefix
* the prefix that identifies comments in the SQL script (typically
* "--")
* @return a String containing the script lines
*/
private static String readScript(EncodedResource resource, String lineCommentPrefix) throws IOException
{
LineNumberReader lineNumberReader = new LineNumberReader(resource.getReader());
try
{
return readScript(lineNumberReader, lineCommentPrefix);
}
finally
{
lineNumberReader.close();
}
}
/**
* Read a script from the provided LineNumberReader, using the supplied line
* comment prefix, and build a String containing the lines.
*
* @param lineNumberReader
* the LineNumberReader containing the script to be processed
* @param lineCommentPrefix
* the prefix that identifies comments in the SQL script (typically
* "--")
* @return a String containing the script lines
*/
private static String readScript(LineNumberReader lineNumberReader, String lineCommentPrefix) throws IOException
{
String statement = lineNumberReader.readLine();
StringBuilder scriptBuilder = new StringBuilder();
while (statement != null)
{
if (lineCommentPrefix != null && !statement.startsWith(lineCommentPrefix))
{
if (scriptBuilder.length() > 0)
{
scriptBuilder.append('\n');
}
scriptBuilder.append(statement);
}
statement = lineNumberReader.readLine();
}
return scriptBuilder.toString();
}
}

View File

@@ -0,0 +1,94 @@
/*
* #%L
* Alfresco Repository
* %%
* Copyright (C) 2005 - 2019 Alfresco Software Limited
* %%
* This file is part of the Alfresco software.
* If the software was purchased under a paid Alfresco license, the terms of
* the paid license agreement will prevail. Otherwise, the software is
* provided under the following open source license terms:
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
package org.alfresco.util;
import org.alfresco.repo.domain.dialect.Dialect;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
public abstract class DialectUtil
{
/** The placeholder for the configured <code>Dialect</code> class name: <b>${db.script.dialect}</b> */
public static final String PLACEHOLDER_DIALECT = "\\$\\{db\\.script\\.dialect\\}";
/**
* Replaces the dialect placeholder in the resource URL and attempts to find a
* file for it. If not found, the dialect hierarchy will be walked until a
* compatible resource is found. This makes it possible to have resources that
* are generic to all dialects.
*
* @return The Resource, otherwise null
*/
public static Resource getDialectResource(ResourcePatternResolver resourcePatternResolver, Class<?> dialectClass, String resourceUrl)
{
// replace the dialect placeholder
String dialectResourceUrl = resolveDialectUrl(dialectClass, resourceUrl);
// get a handle on the resource
Resource resource = resourcePatternResolver.getResource(dialectResourceUrl);
if (!resource.exists())
{
// it wasn't found. Get the superclass of the dialect and try again
Class<?> superClass = dialectClass.getSuperclass();
if (Dialect.class.isAssignableFrom(superClass))
{
// we still have a Dialect - try again
return getDialectResource(resourcePatternResolver, superClass, resourceUrl);
}
else
{
// we have exhausted all options
return null;
}
}
else
{
// we have a handle to it
return resource;
}
}
/**
* Takes resource URL containing the {@link DialectUtil#PLACEHOLDER_DIALECT
* dialect placeholder text} and substitutes the placeholder with the name of
* the given dialect's class.
* <p/>
* For example:
*
* <pre>
* resolveDialectUrl(MySQLInnoDBDialect.class, "classpath:alfresco/db/${db.script.dialect}/myfile.xml")
* </pre>
*
* would give the following String:
*
* <pre>
* classpath:alfresco/db/org.hibernate.dialect.MySQLInnoDBDialect/myfile.xml
* </pre>
*/
public static String resolveDialectUrl(Class<?> dialectClass, String resourceUrl)
{
return resourceUrl.replaceAll(PLACEHOLDER_DIALECT, dialectClass.getName());
}
}

View File

@@ -25,9 +25,11 @@
*/ */
package org.alfresco.util.schemacomp; package org.alfresco.util.schemacomp;
import java.io.IOException;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.sql.Connection; import java.sql.Connection;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.Map; import java.util.Map;
@@ -40,7 +42,9 @@ import org.alfresco.repo.domain.dialect.TypeNames;
import org.alfresco.service.descriptor.Descriptor; import org.alfresco.service.descriptor.Descriptor;
import org.alfresco.service.descriptor.DescriptorService; import org.alfresco.service.descriptor.DescriptorService;
import org.alfresco.util.DatabaseMetaDataHelper; import org.alfresco.util.DatabaseMetaDataHelper;
import org.alfresco.util.DialectUtil;
import org.alfresco.util.PropertyCheck; import org.alfresco.util.PropertyCheck;
import org.alfresco.util.DBScriptUtil;
import org.alfresco.util.schemacomp.model.Column; import org.alfresco.util.schemacomp.model.Column;
import org.alfresco.util.schemacomp.model.ForeignKey; import org.alfresco.util.schemacomp.model.ForeignKey;
import org.alfresco.util.schemacomp.model.Index; import org.alfresco.util.schemacomp.model.Index;
@@ -51,7 +55,10 @@ import org.alfresco.util.schemacomp.model.Table;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.EncodedResource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
/** /**
* Exports a database schema to an in-memory {@link Schema} object. * Exports a database schema to an in-memory {@link Schema} object.
@@ -60,6 +67,8 @@ import org.springframework.context.ApplicationContext;
*/ */
public class ExportDb public class ExportDb
{ {
private static final String SCHEMA_REFERENCE_SEQUENCES_SQL_FILE = "classpath:alfresco/dbscripts/create/${db.script.dialect}/Schema-Reference-Sequences.sql";
/** Reverse map from database types to JDBC types (loaded from a Hibernate dialect). */ /** Reverse map from database types to JDBC types (loaded from a Hibernate dialect). */
private final Map<String, Integer> reverseTypeMap = new TreeMap<String, Integer>(); private final Map<String, Integer> reverseTypeMap = new TreeMap<String, Integer>();
@@ -86,6 +95,7 @@ public class ExportDb
private final static Log log = LogFactory.getLog(ExportDb.class); private final static Log log = LogFactory.getLog(ExportDb.class);
private ResourcePatternResolver rpr = new PathMatchingResourcePatternResolver(this.getClass().getClassLoader());
public ExportDb(ApplicationContext context) public ExportDb(ApplicationContext context)
{ {
@@ -227,19 +237,38 @@ public class ExportDb
private void extractSchema(DatabaseMetaData dbmd, String schemaName, String prefixFilter) private void extractSchema(DatabaseMetaData dbmd, String schemaName, String prefixFilter)
throws SQLException, IllegalArgumentException, IllegalAccessException throws SQLException, IllegalArgumentException, IllegalAccessException, IOException
{ {
if (log.isDebugEnabled()) if (log.isDebugEnabled())
{ {
log.debug("Retrieving tables: schemaName=[" + schemaName + "], prefixFilter=[" + prefixFilter + "]"); log.debug("Retrieving tables: schemaName=[" + schemaName + "], prefixFilter=[" + prefixFilter + "]");
} }
final String[] tableTypes;
final ResultSet tables = dbmd.getTables(null, schemaName, prefixFilter, new String[] Resource sequencesRefResource = getSequencesReferenceResource();
if (sequencesRefResource != null && sequencesRefResource.exists())
{ {
"TABLE", "VIEW", "SEQUENCE" tableTypes = new String[] {"TABLE", "VIEW"};
});
retrieveAndProcessSequences(dbmd, sequencesRefResource, schemaName, prefixFilter);
}
else
{
tableTypes = new String[] { "TABLE", "VIEW", "SEQUENCE" };
}
final ResultSet tables = dbmd.getTables(null, schemaName, prefixFilter, tableTypes);
processTables(dbmd, tables);
}
private void processTables(DatabaseMetaData dbmd, ResultSet tables)
throws SQLException, IllegalArgumentException, IllegalAccessException
{
if (tables == null)
{
return;
}
while (tables.next()) while (tables.next())
{ {
@@ -512,4 +541,101 @@ public class ExportDb
{ {
this.dbSchemaName = dbSchemaName; this.dbSchemaName = dbSchemaName;
} }
/**
* Attempts to find the schema reference sequences sql file. If not found, the
* dialect hierarchy will be walked until a compatible resource is found. This
* makes it possible to have resources that are generic to all dialects.
*
* @return The Resource, otherwise null
*/
private Resource getSequencesReferenceResource()
{
return DialectUtil.getDialectResource(rpr, dialect.getClass(), SCHEMA_REFERENCE_SEQUENCES_SQL_FILE);
}
/**
* Retrieves and process DB sequences for the schema validation check.
*
* @param dbmd
* the database meta data
* @param resource
* the resource to load the SQL script from
* @param schemaName
* the DB schema name
* @param prefixFilter
* the DB tables prefix filter
*/
private void retrieveAndProcessSequences(DatabaseMetaData dbmd, Resource resource, String schemaName, String prefixFilter)
throws SQLException, IllegalArgumentException, IllegalAccessException, IOException
{
final String script = DBScriptUtil.readScript(new EncodedResource(resource, "UTF-8"));
if (!script.isEmpty())
{
retrieveAndProcessSequences(dbmd, script, schemaName, prefixFilter);
}
}
/**
* Retrieves and process DB sequences for the schema validation check.
*
* @param dbmd
* the database meta data
* @param script
* the SQL script
* @param schemaName
* the DB schema name
* @param prefixFilter
* the DB tables prefix filter
*/
private void retrieveAndProcessSequences(DatabaseMetaData dbmd, String script, String schemaName, String prefixFilter)
throws SQLException, IllegalArgumentException, IllegalAccessException
{
if (log.isDebugEnabled())
{
log.debug("Retrieving DB sequences...");
}
PreparedStatement stmt = null;
try
{
stmt = dbmd.getConnection().prepareStatement(script);
stmt.setString(1, schemaName);
stmt.setString(2, prefixFilter);
boolean haveResults = stmt.execute();
if (haveResults)
{
ResultSet sequences = stmt.getResultSet();
if (log.isDebugEnabled())
{
log.debug("Sequences processing started...");
}
processTables(dbmd, sequences);
if (log.isDebugEnabled())
{
log.debug("Sequences processing completed.");
}
}
}
finally
{
if (stmt != null)
{
try
{
stmt.close();
}
catch (Throwable e)
{
// Little can be done at this stage.
}
}
}
}
} }