From 69bd8720a79c7d040daa4556f512d9786d0d88ce Mon Sep 17 00:00:00 2001 From: spyman1802 <1525822@qq.com> Date: Fri, 26 Mar 2021 11:23:30 +0800 Subject: [PATCH] add new functions --- pom.xml | 31 +- .../googlecode/scheme2ddl/DDLFormatter.java | 205 ++++-- .../java/com/googlecode/scheme2ddl/Main.java | 559 +++++++-------- .../googlecode/scheme2ddl/TypeNamesUtil.java | 48 +- .../scheme2ddl/UserObjectJobRunner.java | 104 ++- .../scheme2ddl/UserObjectProcessor.java | 203 +++--- .../scheme2ddl/UserObjectReader.java | 94 ++- .../scheme2ddl/UserObjectWriter.java | 66 +- .../scheme2ddl/dao/UserObjectDaoImpl.java | 667 +++++++++--------- src/main/resources/applicationContext.xml | 2 +- src/main/resources/scheme2ddl.config.xml | 27 +- .../scheme2ddl/DDLFormatterTest.java | 140 ++-- 12 files changed, 1110 insertions(+), 1036 deletions(-) diff --git a/pom.xml b/pom.xml index 2da67cd..0dc5aa8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ com.googlecode scheme2ddl - 2.4.3-SNAPSHOT + 2.4.2 jar @@ -19,7 +19,7 @@ scm:git:git@github.com:qwazer/scheme2ddl.git scm:git:git@github.com:qwazer/scheme2ddl.git scm:git:git@github.com:qwazer/scheme2ddl.git - HEAD + v2.4.2 @@ -76,10 +76,7 @@ 1.6 - - org.apache.maven.plugins - maven-failsafe-plugin - + org.jacoco jacoco-maven-plugin @@ -169,11 +166,16 @@ mvn install:install-file -Dfile=ojdbc5.jar -DgroupId=com.oracle -DartifactId=ojdbc5 -Dversion=11.2.0.3.0 -Dpackaging=jar -DgeneratePom=true --> - com.oracle - ojdbc5 - 11.2.0.3.0 + com.oracle.ojdbc + ojdbc8 + 19.3.0.0 + + com.oracle.ojdbc + orai18n + 19.3.0.0 + org.testng @@ -190,17 +192,6 @@ release - - maven-source-plugin - - - attach-sources - - jar - - - - diff --git a/src/main/java/com/googlecode/scheme2ddl/DDLFormatter.java b/src/main/java/com/googlecode/scheme2ddl/DDLFormatter.java index 88c497a..7dfb79a 100644 --- a/src/main/java/com/googlecode/scheme2ddl/DDLFormatter.java +++ b/src/main/java/com/googlecode/scheme2ddl/DDLFormatter.java @@ -12,91 +12,144 @@ */ public class DDLFormatter { - private boolean noFormat; - private boolean sortCreateIndexStatements = true; - private boolean statementOnNewLine; - private boolean isMorePrettyFormat = false; - - static String newline = "\r\n"; //may be use "\n" - - public String formatDDL(String ddl) { - if (noFormat) - return ddl; - - ddl = ddl.trim() + "\n"; - - // replace unix line endings with windows - ddl = ddl.replaceAll("\r\n", "\n"); - ddl = ddl.replaceAll("\n", "\r\n"); - - if (!isMorePrettyFormat) - return ddl; - - /* smart formatting */ - ddl = ddl.replaceAll(newline + "GRANT ", newline + newline + " GRANT "); - ddl = ddl.replaceAll(newline + "COMMENT ", newline + newline + " COMMENT "); - ddl = ddl.replaceAll(newline + " CREATE ", newline + "CREATE "); - ddl = ddl.replaceAll(newline + " ALTER ", newline + "ALTER "); - return ddl; - } + static String newline = "\r\n"; //may be use "\n" + private boolean noFormat; + private boolean sortCreateIndexStatements = true; + private boolean statementOnNewLine; + private boolean isMorePrettyFormat = true; - public void setNoFormat(Boolean noFormat) { - this.noFormat = noFormat; + public String formatDDL(String ddl) { + if (noFormat) { + return ddl; } - @Deprecated - public void setStatementOnNewLine(Boolean statementOnNewLine) { - this.statementOnNewLine = statementOnNewLine; - } + ddl = ddl.trim() + "\n"; + + // replace unix line endings with windows + ddl = ddl.replaceAll("\r\n", "\n"); + ddl = ddl.replaceAll("\n", "\r\n"); - public void setIsMorePrettyFormat(boolean isMorePrettyFormat) { - this.isMorePrettyFormat = isMorePrettyFormat; + if (!isMorePrettyFormat) { + return ddl; } - public void setSortCreateIndexStatements(boolean sortCreateIndexStatements) { - this.sortCreateIndexStatements = sortCreateIndexStatements; + // replace " + ddl = ddl.replaceAll("\"", ""); + + // replace owner + ddl = ddl.replaceAll(Main.schemaList.get(0).toUpperCase() + "\\.", ""); + + /* smart formatting */ +// ddl = ddl.replaceAll(newline + "GRANT ", newline + newline + "GRANT "); +// ddl = ddl.replaceAll(newline + "COMMENT ", newline + newline + "COMMENT "); + ddl = ddl.replaceAll(newline + " CREATE ", newline + "CREATE "); + ddl = ddl.replaceAll(newline + " ALTER ", newline + "ALTER "); + + // replace tab + ddl = ddl.replaceAll("\\t", " "); + + return ddl; + } + + public String formatTableDDL(String ddl) { + // for table + ddl = ddl.replaceAll(newline + "\\s*\\(", newline + "("); + ddl = ddl.replaceAll(newline + "\\s*\\)", newline + ")"); + ddl = ddl.replaceAll(" ENABLE,", ","); + ddl = ddl.replaceAll(",0\\)", ")"); + ddl = ddl.replaceAll(newline + "\\s*COMMENT ", newline + "COMMENT "); +// ddl = ddl.replaceAll(newline + "" + newline + "\\s*;", newline + "COMMENT "); + + String output; + + // find "alter table CONSTRAINT" + Pattern p = Pattern.compile(newline + "ALTER TABLE (.*)"); + Matcher m = p.matcher(ddl); + if (m.find()) { + output = m.replaceFirst(""); + output = output.replaceAll(newline + "\\s*USING .*", ""); + output = output + newline + "alter table " + m.group(1) + " using index;"; + ddl = output; } - public String replaceActualSequenceValueWithOne(String res) { - - String output; - Pattern p = Pattern.compile("CREATE SEQUENCE (.*) START WITH (\\d+) (.*)"); - Matcher m = p.matcher(res); - if (m.find()) { - output = m.replaceFirst("CREATE SEQUENCE " + m.group(1) + " START WITH 1 " + m.group(3) ); - if (!"1".equals(m.group(2))) - output = output + newline + "/* -- actual sequence value was replaced by scheme2ddl to 1 */"; - } - else { - output = res; - } - return output; + // find "alter table CONSTRAINT" + do { + p = Pattern.compile(newline + "CREATE (.*)INDEX (.*)" + newline + "\\s*;"); + m = p.matcher(ddl); + + if (m.find()) { + output = m.replaceFirst(newline + "CREATE " + m.group(1) + "INDEX " + m.group(2).trim() + ";"); + ddl = output; + } else { + break; + } + } while (true); + + // remove SUPPLEMENTAL LOG + ddl = ddl.replaceAll(newline + ".*SUPPLEMENTAL LOG.*", ""); + + return ddl; + } + + public void setNoFormat(Boolean noFormat) { + this.noFormat = noFormat; + } + + @Deprecated + public void setStatementOnNewLine(Boolean statementOnNewLine) { + this.statementOnNewLine = statementOnNewLine; + } + + public void setIsMorePrettyFormat(boolean isMorePrettyFormat) { + this.isMorePrettyFormat = isMorePrettyFormat; + } + + public void setSortCreateIndexStatements(boolean sortCreateIndexStatements) { + this.sortCreateIndexStatements = sortCreateIndexStatements; + } + + public String replaceActualSequenceValueWithOne(String res) { + + String output; + Pattern p = Pattern.compile("CREATE SEQUENCE (.*) MINVALUE 1 .*"); +// Pattern p = Pattern.compile("CREATE SEQUENCE (.*) MINVALUE 1 START WITH (\\d+) (.*)"); + Matcher m = p.matcher(res); + if (m.find()) { + output = m.replaceFirst("CREATE SEQUENCE " + m.group(1) + ";"); +// output = m.replaceFirst("CREATE SEQUENCE " + m.group(1) + " START WITH 1 " + m.group(3)); +// if (!"1".equals(m.group(2))) +// output = output + newline + "/* -- actual sequence value was replaced by scheme2ddl to 1 */"; + } else { + output = res; } + return output; + } - /** - * Read input string with list of 'create index' statements and, tokenize and sort alphabetically. - * @param dependentDLL -string with list of 'create index' statements - * @return string with sorted alphabetically 'create index' statements - */ - public String sortIndexesInDDL(String dependentDLL) { - if (noFormat || !sortCreateIndexStatements){ - return dependentDLL; - } - String[] parts = dependentDLL.split("(?=CREATE INDEX)|(?=CREATE UNIQUE INDEX)|(?=CREATE BITMAP INDEX)"); - List list = new ArrayList(); - for (String part : parts) { - if (part != null && !part.trim().isEmpty()) { - list.add(part.trim()); - } - } - Collections.sort(list); - StringBuilder s = new StringBuilder(); - String prefix = "\n "; //to preserve formatting of dbms_metadata.get_depended_ddl output - for (String statement:list){ - s.append(prefix); - prefix = "\n"; - s.append(statement); - } - return s.toString(); + /** + * Read input string with list of 'create index' statements and, tokenize and sort alphabetically. + * + * @param dependentDLL -string with list of 'create index' statements + * @return string with sorted alphabetically 'create index' statements + */ + public String sortIndexesInDDL(String dependentDLL) { + if (noFormat || !sortCreateIndexStatements) { + return dependentDLL; + } + String[] parts = dependentDLL.split("(?=CREATE INDEX)|(?=CREATE UNIQUE INDEX)|(?=CREATE BITMAP INDEX)"); + List list = new ArrayList(); + for (String part : parts) { + if (part != null && !part.trim().isEmpty()) { + list.add(part.trim()); + } + } + Collections.sort(list); + StringBuilder s = new StringBuilder(); + String prefix = "\n "; //to preserve formatting of dbms_metadata.get_depended_ddl output + for (String statement : list) { + s.append(prefix); + prefix = "\n"; + s.append(statement); } + return s.toString(); + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/Main.java b/src/main/java/com/googlecode/scheme2ddl/Main.java index 1cf89e6..05a9939 100644 --- a/src/main/java/com/googlecode/scheme2ddl/Main.java +++ b/src/main/java/com/googlecode/scheme2ddl/Main.java @@ -24,323 +24,324 @@ */ public class Main { - private static final Log log = LogFactory.getLog(Main.class); - public static String outputPath = null; - public static int parallelCount = 4; - private static boolean justPrintUsage = false; - private static boolean justPrintVersion = false; - private static boolean justTestConnection = false; - private static boolean skipPublicDbLinks = false; - private static boolean stopOnWarning = false; - private static boolean replaceSequenceValues = false; - private static String customConfigLocation = null; - private static final String defaultConfigLocation = "scheme2ddl.config.xml"; - private static String dbUrl = null; - private static String schemas; - private static boolean isLaunchedByDBA; - private static List schemaList; - private static String objectFilter = "%"; - private static String typeFilter = ""; - private static String typeFilterMode = "include"; + private static final Log log = LogFactory.getLog(Main.class); + private static final String defaultConfigLocation = "scheme2ddl.config.xml"; + public static String outputPath = null; + public static int parallelCount = 4; + private static boolean justPrintUsage = false; + private static boolean justPrintVersion = false; + private static boolean justTestConnection = false; + private static boolean skipPublicDbLinks = false; + private static boolean stopOnWarning = false; + private static boolean replaceSequenceValues = false; + private static String customConfigLocation = null; + private static String dbUrl = null; + private static String schemas; + private static boolean isLaunchedByDBA; + public static List schemaList; + private static String objectFilter = "%"; + private static String typeFilter = ""; + private static String typeFilterMode = "include"; - public static void main(String[] args) throws Exception { - typeFilterMode = "include"; //default is to include any type filter - - collectArgs(args); - if (justPrintUsage) { - printUsage(); - return; - } - if (justPrintVersion) { - printVersion(); - return; - } + public static void main(String[] args) throws Exception { + typeFilterMode = "include"; //default is to include any type filter + + collectArgs(args); + if (justPrintUsage) { + printUsage(); + return; + } + if (justPrintVersion) { + printVersion(); + return; + } - ConfigurableApplicationContext context = loadApplicationContext(); + ConfigurableApplicationContext context = loadApplicationContext(); - modifyContext(context); + modifyContext(context); - validateContext(context); + validateContext(context); - if (justTestConnection) { - testDBConnection(context); - } else { - // todo remove this System.out.println and move this params to bean params, not job params + if (justTestConnection) { + testDBConnection(context); + } else { + // todo remove this System.out.println and move this params to bean params, not job params // System.out.println("DDL object filter: " + objectFilter); // System.out.println("DDL type filter: " + typeFilter); // System.out.println("DDL type filter mode: " + typeFilterMode); - new UserObjectJobRunner().start(context, isLaunchedByDBA, objectFilter.toLowerCase(), typeFilter.toUpperCase(), typeFilterMode.toLowerCase()); - } + new UserObjectJobRunner().start(context, isLaunchedByDBA, objectFilter.toLowerCase(), typeFilter.toUpperCase(), typeFilterMode.toLowerCase()); } + } - private static void testDBConnection(ConfigurableApplicationContext context) throws SQLException { - ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - if (connectionDao.isConnectionAvailable()) { - System.out.println("OK success connection to " + dataSource.getURL()); - } else { - System.out.println("FAIL connect to " + dataSource.getURL()); //todo unreacheble statement - } + private static void testDBConnection(ConfigurableApplicationContext context) throws SQLException { + ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); + OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); + if (connectionDao.isConnectionAvailable()) { + System.out.println("OK success connection to " + dataSource.getURL()); + } else { + System.out.println("FAIL connect to " + dataSource.getURL()); //todo unreacheble statement } + } - private static void modifyContext(ConfigurableApplicationContext context) { - if (dbUrl != null) { - String url = "jdbc:oracle:thin:" + dbUrl; - String user = extractUserfromDbUrl(dbUrl); - String password = extractPasswordfromDbUrl(dbUrl); - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - dataSource.setURL(url); - // for OracleDataSource in connectionCachingEnabled mode need explicitly set user and password - dataSource.setUser(user); - dataSource.setPassword(password); - } - if (outputPath != null) { - UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); - writer.setOutputPath(outputPath); - } - if (parallelCount > 0) { - SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context.getBean("taskExecutor"); - taskExecutor.setConcurrencyLimit(parallelCount); - } - String userName = ((OracleDataSource) context.getBean("dataSource")).getUser(); - isLaunchedByDBA = userName.toLowerCase().matches(".+as +sysdba *"); - if (!isLaunchedByDBA){ - ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); - isLaunchedByDBA = connectionDao.hasSelectCatalogRole(); //todo rename isLaunchedByDBA -> processForeignSchema - } - //process schemas - processSchemas(context); - - FileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); //will create new one if not exist - if (isLaunchedByDBA) { - fileNameConstructor.setTemplate(fileNameConstructor.getTemplateForSysDBA()); - fileNameConstructor.afterPropertiesSet(); - } - - if (stopOnWarning){ - UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); - processor.setStopOnWarning(stopOnWarning); - } - if (replaceSequenceValues){ - UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); - processor.setReplaceSequenceValues(replaceSequenceValues); - } + private static void modifyContext(ConfigurableApplicationContext context) { + if (dbUrl != null) { + String url = "jdbc:oracle:thin:" + dbUrl; + String user = extractUserfromDbUrl(dbUrl); + String password = extractPasswordfromDbUrl(dbUrl); + OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); + dataSource.setURL(url); + // for OracleDataSource in connectionCachingEnabled mode need explicitly set user and password + dataSource.setUser(user); + dataSource.setPassword(password); + } + if (outputPath != null) { + UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); + writer.setOutputPath(outputPath); + } + if (parallelCount > 0) { + SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context.getBean("taskExecutor"); + taskExecutor.setConcurrencyLimit(parallelCount); + } + String userName = ((OracleDataSource) context.getBean("dataSource")).getUser(); + isLaunchedByDBA = userName.toLowerCase().matches(".+as +sysdba *"); + if (!isLaunchedByDBA) { + ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); + isLaunchedByDBA = connectionDao.hasSelectCatalogRole(); //todo rename isLaunchedByDBA -> processForeignSchema + } + //process schemas + processSchemas(context); + FileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); //will create new one if not exist + if (isLaunchedByDBA) { + fileNameConstructor.setTemplate(fileNameConstructor.getTemplateForSysDBA()); + fileNameConstructor.afterPropertiesSet(); } - private static void processSchemas(ConfigurableApplicationContext context) { - List listFromContext = retrieveSchemaListFromContext(context); - if (schemas == null) { - if (listFromContext.size() == 0) { - //get default schema from username - schemaList = extactSchemaListFromUserName(context); - } else { - if (isLaunchedByDBA) - schemaList = new ArrayList(listFromContext); - else { - log.warn("Ignore 'schemaList' from advanced config, because oracle user is not connected as sys dba"); - schemaList = extactSchemaListFromUserName(context); - } - } - } else { - String[] array = schemas.split(","); - schemaList = new ArrayList(Arrays.asList(array)); - } + if (stopOnWarning) { + UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); + processor.setStopOnWarning(stopOnWarning); + } + if (replaceSequenceValues) { + UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); + processor.setReplaceSequenceValues(replaceSequenceValues); + } - listFromContext.clear(); - for (String s : schemaList) { - listFromContext.add(s.toUpperCase().trim()); - } + } - //for compabality with old config - if (listFromContext.size() == 1) { - try { - UserObjectReader userObjectReader = (UserObjectReader) context.getBean("reader"); - userObjectReader.setSchemaName(listFromContext.get(0)); - } catch (ClassCastException e) { - // this mean that new config used, nothing to do - } + private static void processSchemas(ConfigurableApplicationContext context) { + List listFromContext = retrieveSchemaListFromContext(context); + if (schemas == null) { + if (listFromContext.size() == 0) { + //get default schema from username + schemaList = extactSchemaListFromUserName(context); + } else { + if (isLaunchedByDBA) { + schemaList = new ArrayList(listFromContext); + } else { + log.warn("Ignore 'schemaList' from advanced config, because oracle user is not connected as sys dba"); + schemaList = extactSchemaListFromUserName(context); } + } + } else { + String[] array = schemas.split(","); + schemaList = new ArrayList(Arrays.asList(array)); } - private static List extactSchemaListFromUserName(ConfigurableApplicationContext context) { - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - String schemaName = dataSource.getUser().split(" ")[0]; - List list = new ArrayList(); - list.add(schemaName); - return list; + listFromContext.clear(); + for (String s : schemaList) { + listFromContext.add(s.toUpperCase().trim()); } - /** - * @param context - * @return existing bean 'schemaList', if this exists, or create and register new bean - */ - private static List retrieveSchemaListFromContext(ConfigurableApplicationContext context) { - List list; - try { - list = (List) context.getBean("schemaList"); - } catch (NoSuchBeanDefinitionException e) { - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); - beanFactory.registerBeanDefinition("schemaList", BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class).getBeanDefinition()); - list = (List) context.getBean("schemaList"); - } - return list; + //for compabality with old config + if (listFromContext.size() == 1) { + try { + UserObjectReader userObjectReader = (UserObjectReader) context.getBean("reader"); + userObjectReader.setSchemaName(listFromContext.get(0)); + } catch (ClassCastException e) { + // this mean that new config used, nothing to do + } } + } - /** - * @param context - * @return existing bean 'fileNameConstructor', if this exists, or create and register new bean - */ - private static FileNameConstructor retrieveFileNameConstructor(ConfigurableApplicationContext context) { - FileNameConstructor fileNameConstructor; - try { - fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); - } catch (NoSuchBeanDefinitionException e) { - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); - beanFactory.registerBeanDefinition("fileNameConstructor", BeanDefinitionBuilder.rootBeanDefinition(FileNameConstructor.class).getBeanDefinition()); - fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); - fileNameConstructor.afterPropertiesSet(); - //for compatability with old config without fileNameConstructor bean - UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context.getBean("processor"); - userObjectProcessor.setFileNameConstructor(fileNameConstructor); - } - return fileNameConstructor; - } + private static List extactSchemaListFromUserName(ConfigurableApplicationContext context) { + OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); + String schemaName = dataSource.getUser().split(" ")[0]; + List list = new ArrayList(); + list.add(schemaName); + return list; + } - private static String extractUserfromDbUrl(String dbUrl) { - return dbUrl.split("/")[0]; + /** + * @param context + * @return existing bean 'schemaList', if this exists, or create and register new bean + */ + private static List retrieveSchemaListFromContext(ConfigurableApplicationContext context) { + List list; + try { + list = (List) context.getBean("schemaList"); + } catch (NoSuchBeanDefinitionException e) { + DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); + beanFactory.registerBeanDefinition("schemaList", BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class).getBeanDefinition()); + list = (List) context.getBean("schemaList"); } + return list; + } - private static String extractPasswordfromDbUrl(String dbUrl) { - //scott/tiger@localhost:1521:ORCL - return dbUrl.split("/|@")[1]; + /** + * @param context + * @return existing bean 'fileNameConstructor', if this exists, or create and register new bean + */ + private static FileNameConstructor retrieveFileNameConstructor(ConfigurableApplicationContext context) { + FileNameConstructor fileNameConstructor; + try { + fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); + } catch (NoSuchBeanDefinitionException e) { + DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); + beanFactory.registerBeanDefinition("fileNameConstructor", BeanDefinitionBuilder.rootBeanDefinition(FileNameConstructor.class).getBeanDefinition()); + fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); + fileNameConstructor.afterPropertiesSet(); + //for compatability with old config without fileNameConstructor bean + UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context.getBean("processor"); + userObjectProcessor.setFileNameConstructor(fileNameConstructor); } + return fileNameConstructor; + } - private static void validateContext(ConfigurableApplicationContext context) { - String userName = ((OracleDataSource) context.getBean("dataSource")).getUser().toUpperCase(); - List schemaList = (List) context.getBean("schemaList"); - Assert.state(isLaunchedByDBA || schemaList.size() == 1, "Cannot process multiply schemas if oracle user is not connected as sysdba"); - if (!isLaunchedByDBA) { - String schemaName = schemaList.get(0).toUpperCase(); - Assert.state(userName.startsWith(schemaName), - String.format("Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", schemaName, userName.toLowerCase())); - } - } + private static String extractUserfromDbUrl(String dbUrl) { + return dbUrl.split("/")[0]; + } - /** - * Prints the usage information for this class to System.out. - */ - private static void printUsage() { - String lSep = System.getProperty("line.separator"); - StringBuffer msg = new StringBuffer(); - msg.append("java -jar scheme2ddl.jar [-url ] [-o] [-s]" + lSep); - msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + lSep); - msg.append("internally call to dbms_metadata.get_ddl " + lSep); - msg.append("more config options in scheme2ddl.config.xml " + lSep); - msg.append("Options: " + lSep); - msg.append(" -help, -h print this message" + lSep); - // msg.append(" -verbose, -v be extra verbose" + lSep); - msg.append(" -url, DB connection URL" + lSep); - msg.append(" example: scott/tiger@localhost:1521:ORCL" + lSep); + private static String extractPasswordfromDbUrl(String dbUrl) { + //scott/tiger@localhost:1521:ORCL + return dbUrl.split("/|@")[1]; + } - msg.append(" -o, --output, output dir" + lSep); - msg.append(" -p, --parallel, number of parallel thread (default 4)" + lSep); - msg.append(" -s, --schemas, a comma separated list of schemas for processing" + lSep); - msg.append(" (works only if connected to oracle as sysdba)" + lSep); - msg.append(" -c, --config, path to scheme2ddl config file (xml)" + lSep); - msg.append(" -f, --filter, filter for specific DDL objects" + lSep); - msg.append(" every LIKE wildcard can be used" + lSep); - msg.append(" -tf, --type-filter, filter for specific DDL object types" + lSep); - msg.append(" -tfm, --type-filtermode, mode for type filter: include(default) or exclude" + lSep); - msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + lSep); - msg.append(" -rsv, replace actual sequence values with 1 " + lSep); - msg.append(" --replace-sequence-values, " + lSep); - msg.append(" -tc,--test-connection, test db connection available" + lSep); - msg.append(" -version, print version info and exit" + lSep); - System.out.println(msg.toString()); + private static void validateContext(ConfigurableApplicationContext context) { + String userName = ((OracleDataSource) context.getBean("dataSource")).getUser().toUpperCase(); + List schemaList = (List) context.getBean("schemaList"); + Assert.state(isLaunchedByDBA || schemaList.size() == 1, "Cannot process multiply schemas if oracle user is not connected as sysdba"); + if (!isLaunchedByDBA) { + String schemaName = schemaList.get(0).toUpperCase(); + Assert.state(userName.startsWith(schemaName), + String.format("Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", schemaName, userName.toLowerCase())); } + } - private static void printVersion() { - System.out.println("scheme2ddl version " + getVersion()); - } + /** + * Prints the usage information for this class to System.out. + */ + private static void printUsage() { + String lSep = System.getProperty("line.separator"); + StringBuffer msg = new StringBuffer(); + msg.append("java -jar scheme2ddl.jar [-url ] [-o] [-s]" + lSep); + msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + lSep); + msg.append("internally call to dbms_metadata.get_ddl " + lSep); + msg.append("more config options in scheme2ddl.config.xml " + lSep); + msg.append("Options: " + lSep); + msg.append(" -help, -h print this message" + lSep); + // msg.append(" -verbose, -v be extra verbose" + lSep); + msg.append(" -url, DB connection URL" + lSep); + msg.append(" example: scott/tiger@localhost:1521:ORCL" + lSep); - private static String getVersion() { - return Main.class.getPackage().getImplementationVersion(); - } + msg.append(" -o, --output, output dir" + lSep); + msg.append(" -p, --parallel, number of parallel thread (default 4)" + lSep); + msg.append(" -s, --schemas, a comma separated list of schemas for processing" + lSep); + msg.append(" (works only if connected to oracle as sysdba)" + lSep); + msg.append(" -c, --config, path to scheme2ddl config file (xml)" + lSep); + msg.append(" -f, --filter, filter for specific DDL objects" + lSep); + msg.append(" every LIKE wildcard can be used" + lSep); + msg.append(" -tf, --type-filter, filter for specific DDL object types" + lSep); + msg.append(" -tfm, --type-filtermode, mode for type filter: include(default) or exclude" + lSep); + msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + lSep); + msg.append(" -rsv, replace actual sequence values with 1 " + lSep); + msg.append(" --replace-sequence-values, " + lSep); + msg.append(" -tc,--test-connection, test db connection available" + lSep); + msg.append(" -version, print version info and exit" + lSep); + System.out.println(msg.toString()); + } + + private static void printVersion() { + System.out.println("scheme2ddl version " + getVersion()); + } + + private static String getVersion() { + return Main.class.getPackage().getImplementationVersion(); + } - private static void collectArgs(String[] args) throws Exception { + private static void collectArgs(String[] args) throws Exception { - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { - justPrintUsage = true; - } else if (arg.equals("-url") || arg.equals("--url")) { - dbUrl = args[i + 1]; - //check for as sysdba connection - if (args.length >= i + 3) { - if ((args[i + 2].toLowerCase().equals("as")) && - (args[i + 3].toLowerCase().startsWith("sysdba"))) { - //isLaunchedByDBA = true; - dbUrl = args[i + 1] + " " + args[i + 2] + " " + args[i + 3]; - i = i + 2; - } - } - i++; - } else if (arg.equals("-o") || arg.equals("-output") || arg.equals("--output")) { - outputPath = args[i + 1]; - i++; - } else if (arg.equals("-s") || arg.equals("-schemas") || arg.equals("--schemas")) { - schemas = args[i + 1]; - i++; - } else if (arg.equals("-p") || arg.equals("--parallel") || arg.equals("-parallel")) { - parallelCount = Integer.parseInt(args[i + 1]); - i++; - } else if (arg.equals("-tc") || arg.equals("--test-connection")) { - justTestConnection = true; - } else if (arg.equals("--stop-on-warning")) { - stopOnWarning = true; - } else if ((arg.equals("-rsv") || arg.equals("--replace-sequence-values"))) { - replaceSequenceValues = true; - } else if (arg.equals("-c") || arg.equals("--config")) { - customConfigLocation = args[i + 1]; - i++; - } else if (arg.equals("-f") || arg.equals("--filter")) { - objectFilter = args[i + 1]; - //remove single quotes if given - if (objectFilter.length() > 0 && - objectFilter.charAt(objectFilter.length()-1)=='\'' && - objectFilter.charAt(0)=='\'') { - objectFilter = objectFilter.substring(1, objectFilter.length()-1); - } - i++; - } else if (arg.equals("-tf") || arg.equals("--type-filter")) { - typeFilter = args[i + 1]; - i++; - } else if (arg.equals("-tfm") || arg.equals("--type-filtermode")) { - typeFilterMode = args[i + 1]; - i++; - //default to include if anything except include or exclude is given as argument - if (!typeFilterMode.equals("include") && !typeFilterMode.equals("exclude")) { - typeFilterMode = "include"; - } - } else if (arg.equals("-version")) { - justPrintVersion = true; - } else if (arg.startsWith("-")) { - // we don't have any more args to recognize! - String msg = "Unknown argument: " + arg; - System.err.println(msg); - printUsage(); - throw new Exception(msg); - } + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { + justPrintUsage = true; + } else if (arg.equals("-url") || arg.equals("--url")) { + dbUrl = args[i + 1]; + //check for as sysdba connection + if (args.length >= i + 3) { + if ((args[i + 2].toLowerCase().equals("as")) && + (args[i + 3].toLowerCase().startsWith("sysdba"))) { + //isLaunchedByDBA = true; + dbUrl = args[i + 1] + " " + args[i + 2] + " " + args[i + 3]; + i = i + 2; + } + } + i++; + } else if (arg.equals("-o") || arg.equals("-output") || arg.equals("--output")) { + outputPath = args[i + 1]; + i++; + } else if (arg.equals("-s") || arg.equals("-schemas") || arg.equals("--schemas")) { + schemas = args[i + 1]; + i++; + } else if (arg.equals("-p") || arg.equals("--parallel") || arg.equals("-parallel")) { + parallelCount = Integer.parseInt(args[i + 1]); + i++; + } else if (arg.equals("-tc") || arg.equals("--test-connection")) { + justTestConnection = true; + } else if (arg.equals("--stop-on-warning")) { + stopOnWarning = true; + } else if ((arg.equals("-rsv") || arg.equals("--replace-sequence-values"))) { + replaceSequenceValues = true; + } else if (arg.equals("-c") || arg.equals("--config")) { + customConfigLocation = args[i + 1]; + i++; + } else if (arg.equals("-f") || arg.equals("--filter")) { + objectFilter = args[i + 1]; + //remove single quotes if given + if (objectFilter.length() > 0 && + objectFilter.charAt(objectFilter.length() - 1) == '\'' && + objectFilter.charAt(0) == '\'') { + objectFilter = objectFilter.substring(1, objectFilter.length() - 1); + } + i++; + } else if (arg.equals("-tf") || arg.equals("--type-filter")) { + typeFilter = args[i + 1]; + i++; + } else if (arg.equals("-tfm") || arg.equals("--type-filtermode")) { + typeFilterMode = args[i + 1]; + i++; + //default to include if anything except include or exclude is given as argument + if (!typeFilterMode.equals("include") && !typeFilterMode.equals("exclude")) { + typeFilterMode = "include"; } + } else if (arg.equals("-version")) { + justPrintVersion = true; + } else if (arg.startsWith("-")) { + // we don't have any more args to recognize! + String msg = "Unknown argument: " + arg; + System.err.println(msg); + printUsage(); + throw new Exception(msg); + } } + } - private static ConfigurableApplicationContext loadApplicationContext() { - ConfigurableApplicationContext context = null; - if (customConfigLocation != null) - context = new FileSystemXmlApplicationContext(customConfigLocation); - else - context = new ClassPathXmlApplicationContext(defaultConfigLocation); - return context; + private static ConfigurableApplicationContext loadApplicationContext() { + ConfigurableApplicationContext context = null; + if (customConfigLocation != null) { + context = new FileSystemXmlApplicationContext(customConfigLocation); + } else { + context = new ClassPathXmlApplicationContext(defaultConfigLocation); } + return context; + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/TypeNamesUtil.java b/src/main/java/com/googlecode/scheme2ddl/TypeNamesUtil.java index cbfb0ad..37c199f 100644 --- a/src/main/java/com/googlecode/scheme2ddl/TypeNamesUtil.java +++ b/src/main/java/com/googlecode/scheme2ddl/TypeNamesUtil.java @@ -2,31 +2,41 @@ /** * Util for converting type names between 'package DBMS_METADATA' and 'table USER_OBJECTS' formats + * * @author A_Reshetnikov * @since Date: 30.04.2013 */ public class TypeNamesUtil { - /** - * Oracle types in user_table without underscore, for example PACKAGE BODY - * but in DBMS_METADATA with underscore PACKAGE_BODY - * @param type - type name from user_table and advanced config - * - * @return type name for using in DBMS_METADATA package - */ - public static String map2TypeForDBMS(String type) { - if (type.contains("DATABASE LINK")) - return "DB_LINK"; - if (type.equals("JOB")) - return "PROCOBJ"; - if (type.equals("SCHEDULE")) - return "PROCOBJ"; - if (type.equals("PROGRAM")) - return "PROCOBJ"; - if (type.equals("PACKAGE")) - return "PACKAGE_SPEC"; - return type.replace(" ", "_"); + /** + * Oracle types in user_table without underscore, for example PACKAGE BODY + * but in DBMS_METADATA with underscore PACKAGE_BODY + * + * @param type - type name from user_table and advanced config + * @return type name for using in DBMS_METADATA package + */ + public static String map2TypeForDBMS(String type) { + if (type.contains("DATABASE LINK")) + return "DB_LINK"; + if (type.equals("JOB")) + return "PROCOBJ"; + if (type.equals("SCHEDULE")) + return "PROCOBJ"; + if (type.equals("PROGRAM")) + return "PROCOBJ"; + if (type.equals("PACKAGE")) + return "PACKAGE_SPEC"; + + if (type.toUpperCase().contains("SUBPARTITION")) { + return type.replaceAll("SUBPARTITION", "").trim(); + } + + if (type.toUpperCase().contains("PARTITION")) { + return type.replaceAll("PARTITION", "").trim(); } + return type.replace(" ", "_"); + } + } diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectJobRunner.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectJobRunner.java index e4b4076..8e18dde 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectJobRunner.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectJobRunner.java @@ -1,6 +1,5 @@ package com.googlecode.scheme2ddl; -import oracle.jdbc.pool.OracleDataSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.core.*; @@ -10,73 +9,72 @@ import org.springframework.util.Assert; import java.util.List; -import java.util.Map; /** * @author A_Reshetnikov * @since Date: 22.10.2012 */ public class UserObjectJobRunner { - protected static final Log logger = LogFactory.getLog(UserObjectJobRunner.class); - private JobLauncher launcher; + protected static final Log logger = LogFactory.getLog(UserObjectJobRunner.class); + private JobLauncher launcher; - int start(ConfigurableApplicationContext context, boolean launchedByDBA, String objectFilter, String typeFilter, String typeFilterMode) throws Exception { - try { - context.getAutowireCapableBeanFactory().autowireBeanProperties(this, - AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); + int start(ConfigurableApplicationContext context, boolean launchedByDBA, String objectFilter, String typeFilter, String typeFilterMode) throws Exception { + try { + context.getAutowireCapableBeanFactory().autowireBeanProperties(this, + AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); - Assert.state(launcher != null, "A JobLauncher must be provided. Please add one to the configuration."); - Job job = (Job) context.getBean("job1"); + Assert.state(launcher != null, "A JobLauncher must be provided. Please add one to the configuration."); + Job job = (Job) context.getBean("job1"); - List schemaList = (List) context.getBean("schemaList"); - Assert.state(schemaList != null && schemaList.size()!=0, "schemaList must be provided. Please add one to the configuration. "); + List schemaList = (List) context.getBean("schemaList"); + Assert.state(schemaList != null && schemaList.size() != 0, "schemaList must be provided. Please add one to the configuration. "); - logger.info(String.format("Will try to process schema %s %s ", schemaList.size() > 1 ? "list" : "", schemaList)); + logger.info(String.format("Will try to process schema %s %s ", schemaList.size() > 1 ? "list" : "", schemaList)); - for (String schemaName : schemaList){ - JobParametersBuilder parametersBuilder = new JobParametersBuilder(); - parametersBuilder.addString("schemaName", schemaName); - parametersBuilder.addString("launchedByDBA", Boolean.toString(launchedByDBA)); - parametersBuilder.addString("objectFilter", objectFilter); - parametersBuilder.addString("typeFilter", typeFilter); - parametersBuilder.addString("typeFilterMode", typeFilterMode); - JobParameters jobParameters = parametersBuilder.toJobParameters(); - logger.trace(String.format("Start spring batch job with parameters %s", jobParameters)); - JobExecution jobExecution = launcher.run(job, jobParameters); - //write some log - writeJobExecutionStatus(jobExecution, jobParameters); - if (jobExecution.getStatus().isUnsuccessful()){ - throw new Exception(String.format("Job %s unsuccessful", jobParameters)); - } - } + for (String schemaName : schemaList) { + JobParametersBuilder parametersBuilder = new JobParametersBuilder(); + parametersBuilder.addString("schemaName", schemaName); + parametersBuilder.addString("launchedByDBA", Boolean.toString(launchedByDBA)); + parametersBuilder.addString("objectFilter", objectFilter); + parametersBuilder.addString("typeFilter", typeFilter); + parametersBuilder.addString("typeFilterMode", typeFilterMode); + JobParameters jobParameters = parametersBuilder.toJobParameters(); + logger.trace(String.format("Start spring batch job with parameters %s", jobParameters)); + JobExecution jobExecution = launcher.run(job, jobParameters); + //write some log + writeJobExecutionStatus(jobExecution, jobParameters); + if (jobExecution.getStatus().isUnsuccessful()) { + throw new Exception(String.format("Job %s unsuccessful", jobParameters)); + } + } - logger.info(String.format("Processing schema %s %s completed ", schemaList.size() > 1 ? "list" : "", schemaList)); + logger.info(String.format("Processing schema %s %s completed ", schemaList.size() > 1 ? "list" : "", schemaList)); - return 1; + return 1; - } catch (Exception e) { - String message = "Job Terminated in error: " + e.getMessage(); - logger.error(message, e); - throw e; - } finally { - if (context != null) { - context.close(); - } - } + } catch (Exception e) { + String message = "Job Terminated in error: " + e.getMessage(); + logger.error(message, e); + throw e; + } finally { + if (context != null) { + context.close(); + } } + } - private void writeJobExecutionStatus(JobExecution jobExecution, JobParameters jobParameters) { - StepExecution step = jobExecution.getStepExecutions().toArray(new StepExecution[]{})[0]; - String schemaName = jobParameters.getString("schemaName"); - logger.info(String.format("Written %d ddls with user objects from total %d in schema %s", - step.getWriteCount(), step.getReadCount(), schemaName)); - logger.info(String.format("Skip processing %d user objects from total %d in schema %s", - step.getFilterCount(), step.getReadCount(), schemaName)); - long seconds = ((step.getEndTime().getTime()-step.getStartTime().getTime())/1000); - logger.info(String.format("scheme2ddl of schema %s %s in %d seconds", schemaName, jobExecution.getStatus().toString().toLowerCase(), seconds)); - } + private void writeJobExecutionStatus(JobExecution jobExecution, JobParameters jobParameters) { + StepExecution step = jobExecution.getStepExecutions().toArray(new StepExecution[]{})[0]; + String schemaName = jobParameters.getString("schemaName"); + logger.info(String.format("Written %d ddls with user objects from total %d in schema %s", + step.getWriteCount(), step.getReadCount(), schemaName)); + logger.info(String.format("Skip processing %d user objects from total %d in schema %s", + step.getFilterCount(), step.getReadCount(), schemaName)); + long seconds = ((step.getEndTime().getTime() - step.getStartTime().getTime()) / 1000); + logger.info(String.format("scheme2ddl of schema %s %s in %d seconds", schemaName, jobExecution.getStatus().toString().toLowerCase(), seconds)); + } - public void setLauncher(JobLauncher launcher) { - this.launcher = launcher; - } + public void setLauncher(JobLauncher launcher) { + this.launcher = launcher; + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java index 09d7c68..0a11269 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java @@ -19,112 +19,123 @@ */ public class UserObjectProcessor implements ItemProcessor { - private static final Log log = LogFactory.getLog(UserObjectProcessor.class); - private UserObjectDao userObjectDao; - private DDLFormatter ddlFormatter; - private FileNameConstructor fileNameConstructor; - private Map> excludes; - private Map> dependencies; - private boolean stopOnWarning; - private boolean replaceSequenceValues; - - public UserObject process(UserObject userObject) throws Exception { - - if (needToExclude(userObject)) { - log.debug(String.format("Skipping processing of user object %s ", userObject)); - return null; - } - userObject.setDdl(map2Ddl(userObject)); - userObject.setFileName(fileNameConstructor.map2FileName(userObject)); - return userObject; + private static final Log log = LogFactory.getLog(UserObjectProcessor.class); + private UserObjectDao userObjectDao; + private DDLFormatter ddlFormatter; + private FileNameConstructor fileNameConstructor; + private Map> excludes; + private Map> dependencies; + private boolean stopOnWarning; + private boolean replaceSequenceValues; + + public UserObject process(UserObject userObject) throws Exception { + + if (needToExclude(userObject)) { + log.debug(String.format("Skipping processing of user object %s ", userObject)); + return null; } - - private boolean needToExclude(UserObject userObject) { - if (excludes == null || excludes.size() == 0) return false; - if (excludes.get("*") != null) { - for (String pattern : excludes.get("*")) { - if (matchesByPattern(userObject.getName(), pattern)) - return true; - } - } - for (String typeName : excludes.keySet()) { - if (typeName.equalsIgnoreCase(userObject.getType())) { - if (excludes.get(typeName) == null) return true; - for (String pattern : excludes.get(typeName)) { - if (matchesByPattern(userObject.getName(), pattern)) - return true; - } - } - } - return false; + userObject.setDdl(map2Ddl(userObject)); + userObject.setFileName(fileNameConstructor.map2FileName(userObject)); + return userObject; + } + + private boolean needToExclude(UserObject userObject) { + if (excludes == null || excludes.size() == 0) return false; + if (excludes.get("*") != null) { + for (String pattern : excludes.get("*")) { + if (matchesByPattern(userObject.getName(), pattern)) + return true; + } } - - private boolean matchesByPattern(String s, String pattern) { - pattern = pattern.replace("*", "(.*)").toLowerCase(); - return s.toLowerCase().matches(pattern); + for (String typeName : excludes.keySet()) { + if (typeName.equalsIgnoreCase(userObject.getType())) { + if (excludes.get(typeName) == null) return true; + for (String pattern : excludes.get(typeName)) { + if (matchesByPattern(userObject.getName(), pattern)) + return true; + } + } } - - private String map2Ddl(UserObject userObject) throws CannotGetDDLException, NonSkippableException { - try { - if (userObject.getType().equals("DBMS JOB")) { - return ddlFormatter.formatDDL(userObjectDao.findDbmsJobDDL(userObject.getName())); - } - if (userObject.getType().equals("PUBLIC DATABASE LINK")) { - return ddlFormatter.formatDDL(userObjectDao.findDDLInPublicScheme(map2TypeForDBMS(userObject.getType()), userObject.getName())); - } - if (userObject.getType().equals("REFRESH_GROUP")) { - return ddlFormatter.formatDDL(userObjectDao.findRefGroupDDL(userObject.getType(), userObject.getName())); - } - StringBuilder res = new StringBuilder(userObjectDao.findPrimaryDDL(map2TypeForDBMS(userObject.getType()), userObject.getName())); - if (userObject.getType().equals("SEQUENCE") && replaceSequenceValues) { - res = new StringBuilder(ddlFormatter.replaceActualSequenceValueWithOne(res.toString())); - } - Set dependedTypes = dependencies.get(userObject.getType()); - if (dependedTypes != null) { - for (String dependedType : dependedTypes) { - String dependentDLL = userObjectDao.findDependentDLLByTypeName(dependedType, userObject.getName()); - if (dependedType.equals("INDEX")){ - dependentDLL = ddlFormatter.sortIndexesInDDL(dependentDLL); - } - res.append(dependentDLL); - } - } - return ddlFormatter.formatDDL(res.toString()); - } catch (Exception e) { - log.warn(String.format("Cannot get DDL for object %s with error message %s", userObject, e.getMessage())); - if (stopOnWarning) { - throw new NonSkippableException(e); - } else - throw new CannotGetDDLException(e); + return false; + } + + private boolean matchesByPattern(String s, String pattern) { + pattern = pattern.replace("*", "(.*)").toLowerCase(); + return s.toLowerCase().matches(pattern); + } + + private String map2Ddl(UserObject userObject) throws CannotGetDDLException, NonSkippableException { + try { + if (userObject.getType().equals("DBMS JOB")) { + return ddlFormatter.formatDDL(userObjectDao.findDbmsJobDDL(userObject.getName())); + } + + if (userObject.getType().equals("PUBLIC DATABASE LINK")) { + return ddlFormatter.formatDDL(userObjectDao.findDDLInPublicScheme(map2TypeForDBMS(userObject.getType()), userObject.getName())); + } + + if (userObject.getType().equals("REFRESH_GROUP")) { + return ddlFormatter.formatDDL(userObjectDao.findRefGroupDDL(userObject.getType(), userObject.getName())); + } + + StringBuilder res = new StringBuilder(userObjectDao.findPrimaryDDL(map2TypeForDBMS(userObject.getType()), userObject.getName())); + + if (userObject.getType().equals("SEQUENCE") && replaceSequenceValues) { + res = new StringBuilder(ddlFormatter.replaceActualSequenceValueWithOne(res.toString())); + } + + Set dependedTypes = dependencies.get(userObject.getType()); + if (dependedTypes != null) { + for (String dependedType : dependedTypes) { + String dependentDLL = userObjectDao.findDependentDLLByTypeName(dependedType, userObject.getName()); + if (dependedType.equals("INDEX")) { + dependentDLL = ddlFormatter.sortIndexesInDDL(dependentDLL); + } + res.append(dependentDLL); } - + } + + // if type is table + if (userObject.getType().equals("TABLE")) { + return ddlFormatter.formatTableDDL(ddlFormatter.formatDDL(res.toString())); + } + + return ddlFormatter.formatDDL(res.toString()); + } catch (Exception e) { + log.warn(String.format("Cannot get DDL for object %s with error message %s", userObject, e.getMessage())); + if (stopOnWarning) { + throw new NonSkippableException(e); + } else + throw new CannotGetDDLException(e); } - public void setExcludes(Map excludes) { - this.excludes = excludes; - } + } - public void setDependencies(Map dependencies) { - this.dependencies = dependencies; - } + public void setExcludes(Map excludes) { + this.excludes = excludes; + } - public void setUserObjectDao(UserObjectDao userObjectDao) { - this.userObjectDao = userObjectDao; - } + public void setDependencies(Map dependencies) { + this.dependencies = dependencies; + } - public void setDdlFormatter(DDLFormatter ddlFormatter) { - this.ddlFormatter = ddlFormatter; - } + public void setUserObjectDao(UserObjectDao userObjectDao) { + this.userObjectDao = userObjectDao; + } - public void setFileNameConstructor(FileNameConstructor fileNameConstructor) { - this.fileNameConstructor = fileNameConstructor; - } + public void setDdlFormatter(DDLFormatter ddlFormatter) { + this.ddlFormatter = ddlFormatter; + } - public void setReplaceSequenceValues(boolean replaceSequenceValues) { - this.replaceSequenceValues = replaceSequenceValues; - } + public void setFileNameConstructor(FileNameConstructor fileNameConstructor) { + this.fileNameConstructor = fileNameConstructor; + } - public void setStopOnWarning(boolean stopOnWarning) { - this.stopOnWarning = stopOnWarning; - } + public void setReplaceSequenceValues(boolean replaceSequenceValues) { + this.replaceSequenceValues = replaceSequenceValues; + } + + public void setStopOnWarning(boolean stopOnWarning) { + this.stopOnWarning = stopOnWarning; + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectReader.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectReader.java index 4839e04..50db4de 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectReader.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectReader.java @@ -10,9 +10,6 @@ import org.springframework.batch.item.UnexpectedInputException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Scope; -import org.springframework.stereotype.Component; import java.util.List; @@ -22,62 +19,63 @@ */ public class UserObjectReader implements ItemReader { - private static final Log log = LogFactory.getLog(UserObjectReader.class); - private List list; + private static final Log log = LogFactory.getLog(UserObjectReader.class); + public List list; - @Autowired - private UserObjectDao userObjectDao; - private boolean processPublicDbLinks = false; - private boolean processDmbsJobs = false; - private boolean processConstraint = false; + @Autowired + private UserObjectDao userObjectDao; + private boolean processPublicDbLinks = false; + private boolean processDmbsJobs = false; + private boolean processConstraint = false; - @Value("#{jobParameters['schemaName']}") - private String schemaName; + @Value("#{jobParameters['schemaName']}") + private String schemaName; - public synchronized UserObject read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { - if (list == null) { - fillList(); - log.info(String.format("Found %s items for processing in schema %s", list.size(), schemaName)); - } - if (list.size() == 0) { - return null; - } else - return list.remove(0); + public synchronized UserObject read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { + if (list == null) { + fillList(); + log.info(String.format("Found %s items for processing in schema %s", list.size(), schemaName)); } + if (list.size() == 0) { + return null; + } else + return list.remove(0); + } - private synchronized void fillList() { - log.info(String.format("Start getting of user object list in schema %s for processing", schemaName)); - list = userObjectDao.findListForProccessing(); - if (processPublicDbLinks) { - list.addAll(userObjectDao.findPublicDbLinks()); - } - if (processDmbsJobs) { - list.addAll(userObjectDao.findDmbsJobs()); - } - if (processConstraint){ - list.addAll(userObjectDao.findConstaints()); - } + private synchronized void fillList() { + log.info(String.format("Start getting of user object list in schema %s for processing", schemaName)); + list = userObjectDao.findListForProccessing(); + if (processPublicDbLinks) { + list.addAll(userObjectDao.findPublicDbLinks()); } - - public void setUserObjectDao(UserObjectDao userObjectDao) { - this.userObjectDao = userObjectDao; + if (processDmbsJobs) { + list.addAll(userObjectDao.findDmbsJobs()); } - - public void setProcessPublicDbLinks(boolean processPublicDbLinks) { - this.processPublicDbLinks = processPublicDbLinks; + if (processConstraint) { + list.addAll(userObjectDao.findConstaints()); } - public void setProcessDmbsJobs(boolean processDmbsSchedulerJobs) { - this.processDmbsJobs = processDmbsSchedulerJobs; - } + } - public void setProcessConstraint(boolean processConstraint) { - this.processConstraint = processConstraint; - } + public void setUserObjectDao(UserObjectDao userObjectDao) { + this.userObjectDao = userObjectDao; + } - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; - } + public void setProcessPublicDbLinks(boolean processPublicDbLinks) { + this.processPublicDbLinks = processPublicDbLinks; + } + + public void setProcessDmbsJobs(boolean processDmbsSchedulerJobs) { + this.processDmbsJobs = processDmbsSchedulerJobs; + } + + public void setProcessConstraint(boolean processConstraint) { + this.processConstraint = processConstraint; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java index 919d2f6..bbab291 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java @@ -17,40 +17,40 @@ */ public class UserObjectWriter implements ItemWriter { - private static final Log log = LogFactory.getLog(UserObjectWriter.class); - private String outputPath; + private static final Log log = LogFactory.getLog(UserObjectWriter.class); + private String outputPath; - public void write(List data) throws Exception { - if (data.size() > 0) { - writeUserObject(data.get(0)); - } - } - - public void writeUserObject(UserObject userObject) throws Exception { - String absoluteFileName = outputPath + "/" + userObject.getFileName(); - absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); - File file = new File(absoluteFileName); - FileUtils.writeStringToFile(file, userObject.getDdl()); - log.info(String.format("Saved %s %s.%s to file %s", - userObject.getType().toLowerCase(), - userObject.getSchema().toLowerCase(), - userObject.getName().toLowerCase(), - file.getAbsolutePath())); - } - - - - public void setOutputPath(String outputPath) { - this.outputPath = outputPath; - } - - @Deprecated - public void setFileNameCase(String fileNameCase) { - //for compatability with 2.1.x config - } - @Deprecated - public void setIncludeSchemaName(boolean includeSchemaName) { - //for compatability with 2.1.x config + public void write(List data) throws Exception { + if (data.size() > 0) { + writeUserObject(data.get(0)); } + } + + public void writeUserObject(UserObject userObject) throws Exception { + String absoluteFileName = outputPath + "/" + userObject.getFileName(); + absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); + File file = new File(absoluteFileName); + FileUtils.writeStringToFile(file, userObject.getDdl()); + log.info(String.format("Saved %s %s.%s to file %s", + userObject.getType().toLowerCase(), + userObject.getSchema().toLowerCase(), + userObject.getName().toLowerCase(), + file.getAbsolutePath())); + } + + + public void setOutputPath(String outputPath) { + this.outputPath = outputPath; + } + + @Deprecated + public void setFileNameCase(String fileNameCase) { + //for compatability with 2.1.x config + } + + @Deprecated + public void setIncludeSchemaName(boolean includeSchemaName) { + //for compatability with 2.1.x config + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImpl.java b/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImpl.java index ed5ece7..d3083c0 100644 --- a/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImpl.java +++ b/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImpl.java @@ -24,173 +24,184 @@ */ public class UserObjectDaoImpl extends JdbcDaoSupport implements UserObjectDao { - private static final Log log = LogFactory.getLog(UserObjectDaoImpl.class); - private Map transformParams; - @Value("#{jobParameters['schemaName']}") - private String schemaName; - @Value("#{jobParameters['launchedByDBA']}") - private boolean isLaunchedByDBA = false; - @Value("#{jobParameters['objectFilter']}") - private String objectFilter; - @Value("#{jobParameters['typeFilter']}") - private String typeFilter; - @Value("#{jobParameters['typeFilterMode']}") - private String typeFilterMode = "include"; - - public List findListForProccessing() { - String sql; - if (isLaunchedByDBA) { - sql = "select t.object_name, object_type " + - " from dba_objects t " + - " where t.generated = 'N' " + - " and lower(t.object_name) like '" + objectFilter + "' " + - " and t.owner = '" + schemaName + "' " + - " and not exists (select 1 " + - " from user_nested_tables unt" + - " where t.object_name = unt.table_name)"; - if (!typeFilter.isEmpty()) { //type filter is filled - sql += " and upper(t.object_type) "; - - if (typeFilterMode.equals("exclude")) //exclude types - sql += " NOT "; - - sql += " IN (" + typeFilter + ") "; - } - if (isTypeAllowed("'REFRESH GROUP'")) { - sql += " UNION ALL " + - " select rname as object_name, 'REFRESH_GROUP' as object_type " + - " from dba_refresh a " + - " where a.rowner = '" + schemaName + "' " + - " and lower(a.rname) like '" + objectFilter + "' "; - } - } else { - sql = "select t.object_name, object_type " + - " from user_objects t " + - " where t.generated = 'N' " + - " and lower(t.object_name) like '" + objectFilter + "' " + - " and not exists (select 1 " + - " from user_nested_tables unt" + - " where t.object_name = unt.table_name)"; - if (!typeFilter.isEmpty()) { - sql += " and upper(t.object_type) "; - - if (typeFilterMode.equals("exclude")) //exclude types - sql += " NOT "; - - sql += " IN (" + typeFilter + ") "; - } - if (isTypeAllowed("'REFRESH GROUP'")) { - sql += " UNION ALL " + - " select rname as object_name, 'REFRESH_GROUP' as object_type " + - " from user_refresh " + - " where lower(rname) like '" + objectFilter + "' "; - } - } - return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + private static final Log log = LogFactory.getLog(UserObjectDaoImpl.class); + + private Map transformParams; + @Value("#{jobParameters['schemaName']}") + private String schemaName; + @Value("#{jobParameters['launchedByDBA']}") + private boolean isLaunchedByDBA = false; + @Value("#{jobParameters['objectFilter']}") + private String objectFilter; + @Value("#{jobParameters['typeFilter']}") + private String typeFilter; + @Value("#{jobParameters['typeFilterMode']}") + private String typeFilterMode = "include"; + + public List findListForProccessing() { + String sql; + if (isLaunchedByDBA) { + sql = "with" + + " oo as (" + + " select /*+ materialize */ * from dba_objects)" + + " select distinct t.object_name, object_type " + + " from oo t " + + " where t.generated = 'N' " + +// " and t.object_name like 'IDX_T_%' " + + " and t.object_type not like '%PARTITION%'" + + " and t.object_name like '" + objectFilter.toLowerCase() + "' " + + " and t.owner = '" + schemaName + "' " + + " and not exists (select 1 " + + " from user_nested_tables unt" + + " where t.object_name = unt.table_name)"; + if (!typeFilter.isEmpty()) { //type filter is filled + sql += " and upper(t.object_type) "; + + if (typeFilterMode.equals("exclude")) //exclude types + sql += " NOT "; + + sql += " IN (" + typeFilter + ") "; + } + if (isTypeAllowed("'REFRESH GROUP'")) { + sql += " UNION ALL " + + " select rname as object_name, 'REFRESH_GROUP' as object_type " + + " from dba_refresh a " + + " where a.rowner = '" + schemaName + "' " + + " and lower(a.rname) like '" + objectFilter + "' "; + } + } else { + sql = "select t.object_name, object_type " + + " from user_objects t " + + " where t.generated = 'N' " + + " and lower(t.object_name) like '" + objectFilter + "' " + + " and not exists (select 1 " + + " from user_nested_tables unt" + + " where t.object_name = unt.table_name)"; + if (!typeFilter.isEmpty()) { + sql += " and upper(t.object_type) "; + + if (typeFilterMode.equals("exclude")) //exclude types + sql += " NOT "; + + sql += " IN (" + typeFilter + ") "; + } + if (isTypeAllowed("'REFRESH GROUP'")) { + sql += " UNION ALL " + + " select rname as object_name, 'REFRESH_GROUP' as object_type " + + " from user_refresh " + + " where lower(rname) like '" + objectFilter + "' "; + } } - public List findPublicDbLinks() { - List list = new ArrayList(); + log.info("SQL: " + sql); + + return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + } + + public List findPublicDbLinks() { + List list = new ArrayList(); + try { + list = getJdbcTemplate().query( + "select db_link as object_name, 'PUBLIC DATABASE LINK' as object_type " + + "from DBA_DB_LINKS " + + "where owner='PUBLIC'" + + " and lower(db_link) like '" + objectFilter + "' ", + new UserObjectRowMapper()); + } catch (BadSqlGrammarException sqlGrammarException) { + if (sqlGrammarException.getSQLException().getErrorCode() == 942) { + String userName = null; try { - list = getJdbcTemplate().query( - "select db_link as object_name, 'PUBLIC DATABASE LINK' as object_type " + - "from DBA_DB_LINKS " + - "where owner='PUBLIC'" + - " and lower(db_link) like '" + objectFilter + "' ", - new UserObjectRowMapper()); - } catch (BadSqlGrammarException sqlGrammarException) { - if (sqlGrammarException.getSQLException().getErrorCode() == 942) { - String userName = null; - try { - userName = getDataSource().getConnection().getMetaData().getUserName(); - } catch (SQLException e) { - } - log.warn("WARNING: processing of 'PUBLIC DATABASE LINK' will be skipped because " + userName + " no access to view it" + - "\n Possible decisions:\n\n" + - " 1) Exclude processPublicDbLinks option in advanced config to disable this warning\n " + - " \n" + - " \n" + - " ...\n" + - " \n" + - "\n" + - " 2) Or try give access to user " + userName + " with sql command\n " + - " GRANT SELECT_CATALOG_ROLE TO " + userName + "; \n\n"); - } - return list; + userName = getDataSource().getConnection().getMetaData().getUserName(); + } catch (SQLException e) { } + log.warn("WARNING: processing of 'PUBLIC DATABASE LINK' will be skipped because " + userName + " no access to view it" + + "\n Possible decisions:\n\n" + + " 1) Exclude processPublicDbLinks option in advanced config to disable this warning\n " + + " \n" + + " \n" + + " ...\n" + + " \n" + + "\n" + + " 2) Or try give access to user " + userName + " with sql command\n " + + " GRANT SELECT_CATALOG_ROLE TO " + userName + "; \n\n"); + } + return list; + } - for (UserObject userObject : list) { - userObject.setSchema("PUBLIC"); - } - return list; + for (UserObject userObject : list) { + userObject.setSchema("PUBLIC"); } + return list; + } - public List findDmbsJobs() { - String tableName = isLaunchedByDBA ? "dba_jobs" : "user_jobs"; - String whereClause = isLaunchedByDBA ? "schema_user = '" + schemaName + "'" : "schema_user != 'SYSMAN'"; - String sql = "select job || '' as object_name, 'DBMS JOB' as object_type " + - "from " + tableName + " where " + whereClause + " and to_char(job) like '" + objectFilter + "' "; - // a little bit ugly, but this prevents an output from jobs if dbms job is not in typeFilter - if (!isTypeAllowed("'DBMS JOB'")) { - sql += " and 1 = 2 "; - } - return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + public List findDmbsJobs() { + String tableName = isLaunchedByDBA ? "dba_jobs" : "user_jobs"; + String whereClause = isLaunchedByDBA ? "schema_user = '" + schemaName + "'" : "schema_user != 'SYSMAN'"; + String sql = "select job || '' as object_name, 'DBMS JOB' as object_type " + + "from " + tableName + " where " + whereClause + " and to_char(job) like '" + objectFilter + "' "; + // a little bit ugly, but this prevents an output from jobs if dbms job is not in typeFilter + if (!isTypeAllowed("'DBMS JOB'")) { + sql += " and 1 = 2 "; } + return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + } - public List findConstaints() { - String sql; - String prevent_constraint = new String(""); - String prevent_refconstraint = new String(""); - - if (!isTypeAllowed("'CONSTRAINT'")) { - prevent_constraint = " and 1 = 2 "; - } - if (!isTypeAllowed("'REF_CONSTRAINT'")) { - prevent_refconstraint = " and 1 = 2 "; - } - if (isLaunchedByDBA) - sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" + - " from all_constraints " + - " where constraint_type != 'R' and owner = '" + schemaName + "'" + - " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint + - " UNION ALL " + - " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" + - " from all_constraints " + - " where constraint_type = 'R' and owner = '" + schemaName + "'" + - " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint; - else - sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" + - " from user_constraints where constraint_type != 'R'" + - " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint + - " UNION ALL " + - " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" + - " from user_constraints where constraint_type = 'R'" + - " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint; - - return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + public List findConstaints() { + String sql; + String prevent_constraint = new String(""); + String prevent_refconstraint = new String(""); + + if (!isTypeAllowed("'CONSTRAINT'")) { + prevent_constraint = " and 1 = 2 "; + } + if (!isTypeAllowed("'REF_CONSTRAINT'")) { + prevent_refconstraint = " and 1 = 2 "; } + if (isLaunchedByDBA) + sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" + + " from all_constraints " + + " where constraint_type != 'R' and owner = '" + schemaName + "'" + + " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint + + " UNION ALL " + + " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" + + " from all_constraints " + + " where constraint_type = 'R' and owner = '" + schemaName + "'" + + " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint; + else + sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" + + " from user_constraints where constraint_type != 'R'" + + " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint + + " UNION ALL " + + " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" + + " from user_constraints where constraint_type = 'R'" + + " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint; + + return getJdbcTemplate().query(sql, new UserObjectRowMapper()); + } - public String findPrimaryDDL(final String type, final String name) { - if (isLaunchedByDBA) - return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, schemaName); - else - return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?) from dual", type, name, null); + public String findPrimaryDDL(final String type, final String name) { + + if (isLaunchedByDBA) { + return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, schemaName); + } else { + return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?) from dual", type, name, null); } + } - private String executeDbmsMetadataGetDdl(final String query, final String type, final String name, final String schema) { - return (String) getJdbcTemplate().execute(new ConnectionCallback() { - public String doInConnection(Connection connection) throws SQLException, DataAccessException { - applyTransformParameters(connection); - PreparedStatement ps = connection.prepareStatement(query); - ps.setString(1, type); - ps.setString(2, name); - if (schema != null) { - ps.setString(3, schema); - } - ResultSet rs = null; - try { - rs = ps.executeQuery(); - } catch (SQLException e) { + private String executeDbmsMetadataGetDdl(final String query, final String type, final String name, final String schema) { + return (String) getJdbcTemplate().execute(new ConnectionCallback() { + public String doInConnection(Connection connection) throws SQLException, DataAccessException { + applyTransformParameters(connection); + PreparedStatement ps = connection.prepareStatement(query); + ps.setString(1, type); + ps.setString(2, name); + if (schema != null) { + ps.setString(3, schema); + } + ResultSet rs = null; + try { + rs = ps.executeQuery(); + } catch (SQLException e) { // log.trace(String.format("Error during select dbms_metadata.get_ddl('%s', '%s') from dual\n" + // "Try to exclude type '%s' in advanced config excludes section\n", type, name, map2TypeForConfig(type))); // log.trace(String.format("Sample:\n\n" + @@ -203,190 +214,190 @@ public String doInConnection(Connection connection) throws SQLException, DataAcc // " \n" + // "...\n" + // "", map2TypeForConfig(type), name)); - throw e; - } - try { - if (rs.next()) { - return rs.getString(1); - } - } finally { - rs.close(); - } - return null; - } - }); - } + throw e; + } + try { + if (rs.next()) { + return rs.getString(1); + } + } finally { + rs.close(); + } + return null; + } + }); + } - public String findDependentDLLByTypeName(final String type, final String name) { - - return (String) getJdbcTemplate().execute(new ConnectionCallback() { - final String query = "select dbms_metadata.get_dependent_ddl(?, ?, ?) from dual"; - - public Object doInConnection(Connection connection) throws SQLException, DataAccessException { - applyTransformParameters(connection); - PreparedStatement ps = connection.prepareStatement(query); - ps.setString(1, type); - ps.setString(2, name); - ps.setString(3, isLaunchedByDBA ? schemaName : null); - ResultSet rs; - try { - rs = ps.executeQuery(); - } catch (SQLException e) { - log.trace(String.format("Error during select dbms_metadata.get_dependent_ddl(%s, %s) from dual", type, name)); - return ""; - } - try { - if (rs.next()) { - return rs.getString(1); - } - } finally { - rs.close(); - } - return null; - } - }); - } + public String findDependentDLLByTypeName(final String type, final String name) { - public String findDDLInPublicScheme(String type, String name) { - return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, "PUBLIC"); - } + return (String) getJdbcTemplate().execute(new ConnectionCallback() { + final String query = "select dbms_metadata.get_dependent_ddl(?, ?, ?) from dual"; - public String findDbmsJobDDL(String name) { - String sql; - if (isLaunchedByDBA) - // The 'dbms_job.user_export' function does not work with sys/dba users (can't find users jobs). :( - sql = "DECLARE\n" + - " callstr VARCHAR2(4096);\n" + - "BEGIN\n" + - " sys.dbms_ijob.full_export(" + name + ", callstr);\n" + - ":done := callstr; END;"; - else - sql = "DECLARE\n" + - " callstr VARCHAR2(4096);\n" + - "BEGIN\n" + - " dbms_job.user_export(" + name + ", callstr);\n" + - ":done := callstr; " + - "END;"; - - return (String) getJdbcTemplate().execute(sql, new CallableStatementCallbackImpl()); - } - - public String findRefGroupDDL(String type, final String name) { - if (isLaunchedByDBA) - return findPrimaryDDL(map2TypeForDBMS(type), name); - else - return (String) getJdbcTemplate().execute(new ConnectionCallback() { - final String query = - "SELECT 'begin'" - + "|| CHR (13) || CHR (10)" - + "|| '-- dbms_refresh.destroy(name => '''" - + "|| rname" - + "|| ''');'" - + "|| CHR (13) || CHR (10)" - + "|| ' dbms_refresh.make (name => '''" - + "|| rname" - + "|| ''', '" - + "|| CHR (13) || CHR (10)" - + "|| ' list => '''" - + "|| listagg(name, ',') within group (order by name)" - + "|| ''','" - + "|| CHR (13) || CHR (10)" - + "|| ' next_date => '" - + "|| CASE WHEN MAX(next_date) IS NULL THEN 'NULL' ELSE 'to_date(''' || TO_CHAR (MAX (next_date), 'DD.MM.YYYY HH24:MI:SS') || ''', ''DD.MM.YYYY HH24:MI:SS'')' END" - + "|| ', '" - + "|| CHR (13) || CHR (10)" - + "|| ' interval => '" - + "|| CASE WHEN MAX(interval) IS NULL THEN 'NULL' ELSE '''' || MAX (REPLACE(interval, '''', '''''')) || '''' END " - + "|| ');'" - + "|| CHR (13) || CHR (10)" - + "|| ' commit;'" - + "|| CHR (13) || CHR (10)" - + "|| 'end;'" - + "|| CHR (13) || CHR (10)" - + "|| '/'" - + "|| CHR (13) || CHR (10)" - + " FROM user_refresh_children " - + " WHERE rname = UPPER ('"+name+"')" - + " GROUP BY rname"; - - public Object doInConnection(Connection connection) throws SQLException, DataAccessException { - //todo sl4j logger.debug( "query: \n {} ", query); - applyTransformParameters(connection); - PreparedStatement ps = connection.prepareStatement(query); - - ResultSet rs; - - try { - rs = ps.executeQuery(); - } catch (SQLException e) { - log.trace(String.format("Error during select ddl for refresh group (%s)", name)); - return ""; - } - try { - if (rs.next()) { - return rs.getString(1); - } - } finally { - rs.close(); - } - return null; - } - }); - } - - public void applyTransformParameters(Connection connection) throws SQLException { - for (String parameterName : transformParams.keySet()) { - connection.setAutoCommit(false); - // setBoolean doesn't convert java boolean to pl/sql boolean, so used such query building - String sql = String.format( - "BEGIN " + - " dbms_metadata.set_transform_param(DBMS_METADATA.SESSION_TRANSFORM,'%s',%s);" + - " END;", parameterName, transformParams.get(parameterName)); - PreparedStatement ps = connection.prepareCall(sql); - // ps.setString(1, parameterName); - // ps.setBoolean(2, transformParams.get(parameterName) ); //In general this doesn't work - ps.execute(); + public Object doInConnection(Connection connection) throws SQLException, DataAccessException { + applyTransformParameters(connection); + PreparedStatement ps = connection.prepareStatement(query); + ps.setString(1, type); + ps.setString(2, name); + ps.setString(3, isLaunchedByDBA ? schemaName : null); + ResultSet rs; + try { + rs = ps.executeQuery(); + } catch (SQLException e) { + log.trace(String.format("Error during select dbms_metadata.get_dependent_ddl(%s, %s) from dual", type, name)); + return ""; } - } + try { + if (rs.next()) { + return rs.getString(1); + } + } finally { + rs.close(); + } + return null; + } + }); + } - public void setTransformParams(Map transformParams) { - this.transformParams = transformParams; - } + public String findDDLInPublicScheme(String type, String name) { + return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, "PUBLIC"); + } - public void setSchemaName(String schemaName) { - this.schemaName = schemaName; - } + public String findDbmsJobDDL(String name) { + String sql; + if (isLaunchedByDBA) + // The 'dbms_job.user_export' function does not work with sys/dba users (can't find users jobs). :( + sql = "DECLARE\n" + + " callstr VARCHAR2(4096);\n" + + "BEGIN\n" + + " sys.dbms_ijob.full_export(" + name + ", callstr);\n" + + ":done := callstr; END;"; + else + sql = "DECLARE\n" + + " callstr VARCHAR2(4096);\n" + + "BEGIN\n" + + " dbms_job.user_export(" + name + ", callstr);\n" + + ":done := callstr; " + + "END;"; - public void setLaunchedByDBA(boolean launchedByDBA) { - this.isLaunchedByDBA = launchedByDBA; - } + return (String) getJdbcTemplate().execute(sql, new CallableStatementCallbackImpl()); + } + + public String findRefGroupDDL(String type, final String name) { + if (isLaunchedByDBA) + return findPrimaryDDL(map2TypeForDBMS(type), name); + else + return (String) getJdbcTemplate().execute(new ConnectionCallback() { + final String query = + "SELECT 'begin'" + + "|| CHR (13) || CHR (10)" + + "|| '-- dbms_refresh.destroy(name => '''" + + "|| rname" + + "|| ''');'" + + "|| CHR (13) || CHR (10)" + + "|| ' dbms_refresh.make (name => '''" + + "|| rname" + + "|| ''', '" + + "|| CHR (13) || CHR (10)" + + "|| ' list => '''" + + "|| listagg(name, ',') within group (order by name)" + + "|| ''','" + + "|| CHR (13) || CHR (10)" + + "|| ' next_date => '" + + "|| CASE WHEN MAX(next_date) IS NULL THEN 'NULL' ELSE 'to_date(''' || TO_CHAR (MAX (next_date), 'DD.MM.YYYY HH24:MI:SS') || ''', ''DD.MM.YYYY HH24:MI:SS'')' END" + + "|| ', '" + + "|| CHR (13) || CHR (10)" + + "|| ' interval => '" + + "|| CASE WHEN MAX(interval) IS NULL THEN 'NULL' ELSE '''' || MAX (REPLACE(interval, '''', '''''')) || '''' END " + + "|| ');'" + + "|| CHR (13) || CHR (10)" + + "|| ' commit;'" + + "|| CHR (13) || CHR (10)" + + "|| 'end;'" + + "|| CHR (13) || CHR (10)" + + "|| '/'" + + "|| CHR (13) || CHR (10)" + + " FROM user_refresh_children " + + " WHERE rname = UPPER ('" + name + "')" + + " GROUP BY rname"; + + public Object doInConnection(Connection connection) throws SQLException, DataAccessException { + //todo sl4j logger.debug( "query: \n {} ", query); + applyTransformParameters(connection); + PreparedStatement ps = connection.prepareStatement(query); - private class CallableStatementCallbackImpl implements CallableStatementCallback { - public Object doInCallableStatement(CallableStatement callableStatement) throws SQLException, DataAccessException { - callableStatement.registerOutParameter(1, java.sql.Types.VARCHAR); - callableStatement.executeUpdate(); - return callableStatement.getString(1); + ResultSet rs; + + try { + rs = ps.executeQuery(); + } catch (SQLException e) { + log.trace(String.format("Error during select ddl for refresh group (%s)", name)); + return ""; + } + try { + if (rs.next()) { + return rs.getString(1); + } + } finally { + rs.close(); + } + return null; } + }); + } + + public void applyTransformParameters(Connection connection) throws SQLException { + for (String parameterName : transformParams.keySet()) { + connection.setAutoCommit(false); + // setBoolean doesn't convert java boolean to pl/sql boolean, so used such query building + String sql = String.format( + "BEGIN " + + " dbms_metadata.set_transform_param(DBMS_METADATA.SESSION_TRANSFORM,'%s',%s);" + + " END;", parameterName, transformParams.get(parameterName)); + PreparedStatement ps = connection.prepareCall(sql); + // ps.setString(1, parameterName); + // ps.setBoolean(2, transformParams.get(parameterName) ); //In general this doesn't work + ps.execute(); } + } - private class UserObjectRowMapper implements RowMapper { - public UserObject mapRow(ResultSet rs, int rowNum) throws SQLException { - UserObject userObject = new UserObject(); - userObject.setName(rs.getString("object_name")); - userObject.setType(rs.getString("object_type")); - userObject.setSchema(schemaName == null ? "" : schemaName); - return userObject; - } + public void setTransformParams(Map transformParams) { + this.transformParams = transformParams; + } + + public void setSchemaName(String schemaName) { + this.schemaName = schemaName; + } + + public void setLaunchedByDBA(boolean launchedByDBA) { + this.isLaunchedByDBA = launchedByDBA; + } + + private boolean isTypeAllowed(String typeName) { + if (typeFilter.isEmpty()) // empty type filter means all types are allowed + return true; + if (typeFilterMode.equals("include") && typeFilter.contains(typeName)) // given typeName is in the typeFilter + return true; + if (typeFilterMode.equals("exclude") && !typeFilter.contains(typeName)) // given typeName is not in the typeFilter + return true; + + return false; + } + + private class CallableStatementCallbackImpl implements CallableStatementCallback { + public Object doInCallableStatement(CallableStatement callableStatement) throws SQLException, DataAccessException { + callableStatement.registerOutParameter(1, java.sql.Types.VARCHAR); + callableStatement.executeUpdate(); + return callableStatement.getString(1); + } + } + + private class UserObjectRowMapper implements RowMapper { + public UserObject mapRow(ResultSet rs, int rowNum) throws SQLException { + UserObject userObject = new UserObject(); + userObject.setName(rs.getString("object_name")); + userObject.setType(rs.getString("object_type")); + userObject.setSchema(schemaName == null ? "" : schemaName); + return userObject; } - - private boolean isTypeAllowed (String typeName) { - if (typeFilter.isEmpty()) // empty type filter means all types are allowed - return true; - if (typeFilterMode.equals("include") && typeFilter.contains(typeName)) // given typeName is in the typeFilter - return true; - if (typeFilterMode.equals("exclude") && !typeFilter.contains(typeName)) // given typeName is not in the typeFilter - return true; - - return false; - } + } } diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml index ccd5775..756a85e 100644 --- a/src/main/resources/applicationContext.xml +++ b/src/main/resources/applicationContext.xml @@ -51,7 +51,7 @@ - + diff --git a/src/main/resources/scheme2ddl.config.xml b/src/main/resources/scheme2ddl.config.xml index ba261b6..f52861c 100644 --- a/src/main/resources/scheme2ddl.config.xml +++ b/src/main/resources/scheme2ddl.config.xml @@ -9,11 +9,10 @@ - + - - - + + @@ -51,7 +50,7 @@ - + @@ -163,14 +162,14 @@ COMMENT INDEX - OBJECT_GRANT - TRIGGER + + COMMENT - OBJECT_GRANT + @@ -178,32 +177,32 @@ COMMENT INDEX MATERIALIZED_VIEW_LOG - OBJECT_GRANT + - OBJECT_GRANT + - OBJECT_GRANT + - OBJECT_GRANT + - OBJECT_GRANT + - OBJECT_GRANT + diff --git a/src/test/java/com/googlecode/scheme2ddl/DDLFormatterTest.java b/src/test/java/com/googlecode/scheme2ddl/DDLFormatterTest.java index 7f1607b..2cbe223 100644 --- a/src/test/java/com/googlecode/scheme2ddl/DDLFormatterTest.java +++ b/src/test/java/com/googlecode/scheme2ddl/DDLFormatterTest.java @@ -13,73 +13,75 @@ */ public class DDLFormatterTest { - private DDLFormatter ddlFormatter = new DDLFormatter(); - - @Test - public void testReplaceActualSequenceValueWithOne() throws Exception { - - String s = "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n"; - String res = ddlFormatter.replaceActualSequenceValueWithOne(s); - assertEquals( - "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n" + - "\r\n" + - "/* -- actual sequence value was replaced by scheme2ddl to 1 */" - , res); - - } - - @Test - public void testReplaceActualSequenceValueWithOneOnWrongDDL() throws Exception { - - String s = "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n"; - String res = ddlFormatter.replaceActualSequenceValueWithOne(s); - assertNotEquals( - "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n" - , res); - - } - - - @Test - public void testSortPreserveOriginalDDLIfNoSort() { - String s = "\n CREATE UNIQUE INDEX \"HR\".\"REG_ID_PK\" ON \"HR\".\"REGIONS\" (\"REGION_ID\") \n" + - " ;"; - String res = ddlFormatter.sortIndexesInDDL(s); - assertEquals(s, res); - } - - @Test - public void testSortIndexes() { - String s = " CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" + - " ;\n" + - " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" + - " ;"; - String res = ddlFormatter.sortIndexesInDDL(s); - assertEquals( - "\n CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" + - " ;\n" + - "CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" + - " ;" - , res); - } - - @Test - public void testSortIndexesUniq() { - String s = - " \n" + - "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" + - " ;\n" + - " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" + - " ; " + - "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" + - " ;\n"; - String res = ddlFormatter.sortIndexesInDDL(s); - assertEquals("\n " + - "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" + - " ;\n" + - "CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" + - " ;\n" + - "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" + - " ;", res); - } + private DDLFormatter ddlFormatter = new DDLFormatter(); + + @Test + public void testReplaceActualSequenceValueWithOne() throws Exception { + + String s = "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n"; + String res = ddlFormatter.replaceActualSequenceValueWithOne(s); + assertEquals("CREATE SEQUENCE \"TEST01\".\"SEQ_01\" ;\n", res); + +// assertEquals( +// "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n" + +// "\r\n" + +// "/* -- actual sequence value was replaced by scheme2ddl to 1 */" +// , res); + + } + + @Test + public void testReplaceActualSequenceValueWithOneOnWrongDDL() throws Exception { + + String s = "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n"; + String res = ddlFormatter.replaceActualSequenceValueWithOne(s); + assertNotEquals( + "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n" + , res); + + } + + + @Test + public void testSortPreserveOriginalDDLIfNoSort() { + String s = "\n CREATE UNIQUE INDEX \"HR\".\"REG_ID_PK\" ON \"HR\".\"REGIONS\" (\"REGION_ID\") \n" + + " ;"; + String res = ddlFormatter.sortIndexesInDDL(s); + assertEquals(s, res); + } + + @Test + public void testSortIndexes() { + String s = " CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" + + " ;\n" + + " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" + + " ;"; + String res = ddlFormatter.sortIndexesInDDL(s); + assertEquals( + "\n CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" + + " ;\n" + + "CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" + + " ;" + , res); + } + + @Test + public void testSortIndexesUniq() { + String s = + " \n" + + "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" + + " ;\n" + + " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" + + " ; " + + "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" + + " ;\n"; + String res = ddlFormatter.sortIndexesInDDL(s); + assertEquals("\n " + + "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" + + " ;\n" + + "CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" + + " ;\n" + + "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" + + " ;", res); + } } \ No newline at end of file