├── .gitignore ├── .travis.yml ├── README.md ├── pom.xml └── src ├── grants.sql ├── main ├── java │ └── com │ │ └── googlecode │ │ └── scheme2ddl │ │ ├── db2 │ │ ├── DDLFormatter.java │ │ ├── Db2LookInfoComparator.java │ │ ├── FileNameConstructor.java │ │ ├── IsAlterSequenceValuesPredicate.java │ │ ├── IsAlterTableAutoGeneratedPredicate.java │ │ ├── Main.java │ │ ├── RoutineAuthPrinter.java │ │ ├── TabAuthPrinter.java │ │ ├── UserObjectJobRunner.java │ │ ├── UserObjectProcessor.java │ │ ├── UserObjectReader.java │ │ ├── UserObjectWriter.java │ │ ├── aspect │ │ │ ├── Db2LookInfoStatAspect.java │ │ │ └── UserObjectStatAspect.java │ │ ├── dao │ │ │ ├── ConnectionDao.java │ │ │ ├── ConnectionDaoImpl.java │ │ │ ├── GrantsDao.java │ │ │ ├── GrantsDaoImpl.java │ │ │ ├── UserObjectDao.java │ │ │ └── UserObjectDaoDb2Impl.java │ │ ├── domain │ │ │ ├── DB2ObjectType.java │ │ │ ├── Db2LookInfo.java │ │ │ ├── GrantType.java │ │ │ ├── GranteeType.java │ │ │ ├── RoutineAuth.java │ │ │ ├── TabAuth.java │ │ │ └── UserObject.java │ │ └── listener │ │ │ └── AfterStepListener.java │ │ └── exception │ │ ├── CannotGetDDLException.java │ │ └── NonSkippableException.java └── resources │ ├── applicationContext.xml │ ├── db2-scheme2ddl.config.xml │ └── log4j.properties └── test └── java └── com └── googlecode └── scheme2ddl └── db2 ├── FileNameConstructorTest.java ├── MainTestDb2.java └── filter └── IsAlterTableAutoGeneratedPredicateTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Maven template 3 | target/ 4 | pom.xml.tag 5 | pom.xml.releaseBackup 6 | pom.xml.versionsBackup 7 | pom.xml.next 8 | release.properties 9 | dependency-reduced-pom.xml 10 | 11 | 12 | ### JetBrains template 13 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm 14 | 15 | *.iml 16 | 17 | ## Directory-based project format: 18 | .idea/ 19 | # if you remove the above rule, at least ignore the following: 20 | 21 | # User-specific stuff: 22 | # .idea/workspace.xml 23 | # .idea/tasks.xml 24 | # .idea/dictionaries 25 | 26 | # Sensitive or high-churn files: 27 | # .idea/dataSources.ids 28 | # .idea/dataSources.xml 29 | # .idea/sqlDataSources.xml 30 | # .idea/dynamic.xml 31 | # .idea/uiDesigner.xml 32 | 33 | # Gradle: 34 | # .idea/gradle.xml 35 | # .idea/libraries 36 | 37 | # Mongo Explorer plugin: 38 | # .idea/mongoSettings.xml 39 | 40 | ## File-based project format: 41 | *.ipr 42 | *.iws 43 | 44 | ## Plugin-specific files: 45 | 46 | # IntelliJ 47 | out/ 48 | 49 | # mpeltonen/sbt-idea plugin 50 | .idea_modules/ 51 | 52 | # JIRA plugin 53 | atlassian-ide-plugin.xml 54 | 55 | # Crashlytics plugin (for Android Studio and IntelliJ) 56 | com_crashlytics_export_strings.xml 57 | crashlytics.properties 58 | crashlytics-build.properties 59 | 60 | 61 | 62 | output -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | [ ![Download](https://api.bintray.com/packages/qwazer/maven/db2-scheme2ddl/images/download.svg) ](https://bintray.com/qwazer/maven/db2-scheme2ddl/_latestVersion)   [![Build Status](https://travis-ci.org/qwazer/db2-scheme2ddl.svg?branch=master)](https://travis-ci.org/qwazer/db2-scheme2ddl) 3 | 4 | ### Description ### 5 | 6 | **db2-scheme2ddl** - command line util for export IBM DB2 schema to set of ddl scripts. Provide a lot of configurations via basic command line options or advanced XML configuartion. 7 | 8 | :warning: Keep in mind, that db2-scheme2ddl build around undocumended `SYSPROC.DB2LK_GENERATE_DDL` procedure. So use it on your own risk. 9 | 10 | ### Benefits ### 11 | **db2-scheme2ddl** give ability to filter undesirable information, separate DDL in different files, pretty format output. 12 | 13 | ### How to start with minimal configuration ### 14 | Java must be installed on your computer. 15 | For exporting db2 scheme you must provide 16 | * DB connection string 17 | * output directory 18 | 19 | Usage example. Command 20 | ``` 21 | java -jar db2-scheme2ddl.jar -url scott/tiger@localhost:5000:SAMPLE -o C:/temp/db2-scheme/ 22 | ``` 23 | will produce directory tree 24 | ``` 25 | SCHEMA1/ 26 | views/ 27 | view1.sql 28 | view2.sql 29 | tables/ 30 | table1.sql 31 | functions 32 | /f1.sql 33 | ``` 34 | 35 | More command line options 36 | ``` 37 | java -jar db2-scheme2ddl.jar -help 38 | ... 39 | Options: 40 | -help, -h print this message 41 | -url, DB connection URL 42 | example: scott/tiger@localhost:5000:SAMPLE 43 | -o, --output, output dir 44 | -p, --parallel, number of parallel thread (default 4) 45 | -s, --schemas, a comma separated list of schemas for processing 46 | -c, --config, path to scheme2ddl config file (xml) 47 | --stop-on-warning, stop on getting DDL error (skip by default) 48 | -tc,--test-connection, test db connection available 49 | -version, print version info and exit 50 | ``` 51 | 52 | 53 | ### How it is work inside? ### 54 | 55 | 1. First, get list of all schemas from command line parameter, from congif or find all available schemas with query 56 | 57 | ``` 58 | SELECT table_schem from SYSIBM.SQLSCHEMAS 59 | ``` 60 | 2. Invoke undocumented DB2 function for every schema 61 | 62 | ``` 63 | CALL SYSPROC.DB2LK_GENERATE_DDL('-e -z SAMPLE', ?) 64 | ``` 65 | 3. store second INOUT parameter for later use 66 | 4. find primary object's DDL with query 67 | 68 | ``` 69 | select OP_SEQUENCE, SQL_STMT, OBJ_SCHEMA, OBJ_TYPE, OBJ_NAME, SQL_OPERATION 70 | FROM SYSTOOLS.DB2LOOK_INFO 71 | where OP_TOKEN=? and OBJ_SCHEMA=? 72 | and OBJ_TYPE=? and OBJ_NAME=? 73 | ``` 74 | 5. find depended object's DDL with additional filter parameter. For example, find indexes of table 75 | 76 | ``` 77 | SELECT * 78 | FROM SYSTOOLS.DB2LOOK_INFO t 79 | WHERE OBJ_TYPE = 'INDEX' 80 | AND OP_TOKEN = ? 81 | AND exists( 82 | SELECT 1 83 | FROM SYSCAT.INDEXES i 84 | WHERE TABSCHEMA = ? AND TABNAME = ? AND i.INDNAME = t.OBJ_NAME ) 85 | ``` 86 | 6. find grants from syscat.`*`auth tables, convert table rows to sql statements (Incomplete and potentially buggy code) 87 | 88 | 7. call SYSPROC.DB2LK_CLEAN_TABLE for every schema to clean temp data 89 | 90 | Unfortunately, SYSPROC.DB2LK\_GENERATE\_DDL doesn't accept -x parameter for DB version 9.7 91 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.googlecode 6 | db2-scheme2ddl 7 | 0.2.8-SNAPSHOT 8 | jar 9 | 10 | http://db2-scheme2ddl.googlecode.com 11 | 12 | 13 | scm:git:git@github.com:qwazer/db2-scheme2ddl.git 14 | scm:git:git@github.com:qwazer/db2-scheme2ddl.git 15 | scm:git:git@github.com:qwazer/db2-scheme2ddl.git 16 | HEAD 17 | 18 | 19 | 20 | 21 | otn-maven-repo 22 | Maven repo with artifacts from Oracle Technology Network for private usage 23 | https://subversion.assembla.com/svn/otn-maven-repo/m2/ 24 | 25 | 26 | 27 | 28 | 29 | bintray 30 | https://api.bintray.com/maven/${bintray.repo}/${bintray.package} 31 | 32 | 33 | 34 | 35 | UTF-8 36 | qwazer/maven 37 | db2-scheme2ddl 38 | 3.2.12.RELEASE 39 | 3.0.2.RELEASE 40 | 1.8.4 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.apache.maven.plugins 48 | maven-shade-plugin 49 | 2.1 50 | 51 | 52 | 53 | 54 | com.googlecode.scheme2ddl.db2.Main 55 | ${project.version} 56 | 57 | 58 | 59 | META-INF/spring.handlers 60 | 61 | 62 | META-INF/spring.schemas 63 | 64 | 65 | 66 | 67 | 68 | 69 | package 70 | 71 | shade 72 | 73 | 74 | 75 | 76 | 77 | org.codehaus.mojo 78 | build-helper-maven-plugin 79 | 1.9.1 80 | 81 | 82 | add-source 83 | generate-sources 84 | 85 | add-source 86 | 87 | 88 | 89 | src/${profile.name}/java 90 | 91 | 92 | 93 | 94 | 95 | 96 | org.apache.maven.plugins 97 | maven-compiler-plugin 98 | 3.1 99 | 100 | 1.5 101 | 1.5 102 | 103 | 104 | 105 | maven-source-plugin 106 | 107 | 108 | attach-sources 109 | deploy 110 | 111 | jar-no-fork 112 | 113 | 114 | 115 | 116 | 117 | org.apache.maven.plugins 118 | maven-release-plugin 119 | 2.5.1 120 | 121 | v@{project.version} 122 | false 123 | release 124 | true 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | org.springframework.batch 133 | spring-batch-core 134 | ${spring.batch.version} 135 | 136 | 137 | org.springframework 138 | spring-jdbc 139 | ${spring.framework.version} 140 | 141 | 142 | commons-io 143 | commons-io 144 | 2.4 145 | 146 | 147 | log4j 148 | log4j 149 | 1.2.17 150 | runtime 151 | 152 | 153 | 154 | commons-collections 155 | commons-collections 156 | 3.2.1 157 | 158 | 159 | 160 | 161 | org.springframework 162 | spring-aop 163 | ${spring.framework.version} 164 | 165 | 166 | 167 | org.aspectj 168 | aspectjweaver 169 | ${org.aspectj.version} 170 | 171 | 172 | 173 | 174 | junit 175 | junit 176 | 4.11 177 | test 178 | 179 | 180 | 186 | 187 | com.ibm.db2 188 | db2jcc4 189 | 4.19.26 190 | 191 | 192 | 193 | 194 | 195 | 196 | release 197 | 198 | 199 | 200 | maven-source-plugin 201 | 202 | 203 | attach-sources 204 | 205 | jar 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /src/grants.sql: -------------------------------------------------------------------------------- 1 | SELECT GRANTOR,GRANTORTYPE 2 | , 'TABLE' AS OBJ_TYPE 3 | , TABSCHEMA AS OBJ_SCHEMA, TABNAME AS OBJ_NAME 4 | , CONTROLAUTH, ALTERAUTH, DELETEAUTH, INDEXAUTH, INSERTAUTH, REFAUTH, SELECTAUTH, UPDATEAUTH 5 | , NULL AS USAGEAUTH, NULL AS ALTERINAUTH, NULL AS CREATEINAUTH, NULL AS DROPINAUTH, NULL AS BINDAUTH, NULL AS EXECUTEAUTH 6 | FROM SYSCAT.TABAUTH 7 | WHERE GRANTEETYPE = ? 8 | AND GRANTEE = ? 9 | UNION ALL 10 | SELECT GRANTOR,GRANTORTYPE 11 | , 'COLUMN' AS OBJ_TYPE 12 | , TABSCHEMA AS OBJ_SCHEMA, TABNAME AS OBJ_NAME 13 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 14 | , COLNAME, PRIVTYPE, GRANTABLE, NULL, NULL, NULL 15 | FROM SYSCAT.COLAUTH 16 | WHERE GRANTEETYPE = ? 17 | AND GRANTEE = ? 18 | UNION ALL 19 | SELECT GRANTOR,GRANTORTYPE 20 | , 'INDEX' AS OBJ_TYPE 21 | , INDSCHEMA AS OBJ_SCHEMA, INDNAME AS OBJ_NAME 22 | , CONTROLAUTH, NULL, NULL, NULL, NULL, NULL, NULL, NULL 23 | , NULL, NULL, NULL, NULL, NULL, NULL 24 | FROM SYSCAT.INDEXAUTH 25 | WHERE GRANTEETYPE = ? 26 | AND GRANTEE = ? 27 | UNION ALL 28 | SELECT GRANTOR,GRANTORTYPE 29 | , 'PACKAGE' AS OBJ_TYPE 30 | , PKGSCHEMA AS OBJ_SCHEMA, PKGNAME AS OBJ_NAME 31 | , CONTROLAUTH, NULL, NULL, NULL, NULL, NULL, NULL, NULL 32 | , NULL, NULL, NULL, NULL, BINDAUTH, EXECUTEAUTH 33 | FROM SYSCAT.PACKAGEAUTH 34 | WHERE GRANTEETYPE = ? 35 | AND GRANTEE = ? 36 | UNION ALL 37 | SELECT GRANTOR,GRANTORTYPE 38 | , 'PROCEDURE' AS OBJ_TYPE 39 | , SCHEMA AS OBJ_SCHEMA, SPECIFICNAME AS OBJ_NAME 40 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 41 | , ROUTINETYPE, NULL, NULL, NULL, NULL, EXECUTEAUTH 42 | FROM SYSCAT.ROUTINEAUTH 43 | WHERE GRANTEETYPE = ? 44 | AND GRANTEE = ? 45 | UNION ALL 46 | SELECT GRANTOR,GRANTORTYPE 47 | , 'SCHEMA' AS OBJ_TYPE 48 | , NULL AS OBJ_SCHEMA, SCHEMANAME AS OBJ_NAME 49 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 50 | , NULL, ALTERINAUTH, CREATEINAUTH, DROPINAUTH, NULL, NULL 51 | FROM SYSCAT.SCHEMAAUTH 52 | WHERE GRANTEETYPE = ? 53 | AND GRANTEE = ? 54 | UNION ALL 55 | SELECT GRANTOR,GRANTORTYPE 56 | , 'SEQUENCE' AS OBJ_TYPE 57 | , SEQSCHEMA AS OBJ_SCHEMA, SEQNAME AS OBJ_NAME 58 | , NULL, ALTERAUTH, NULL, NULL, NULL, NULL, NULL, NULL 59 | , USAGEAUTH, NULL, NULL, NULL, NULL, NULL 60 | FROM SYSCAT.SEQUENCEAUTH 61 | WHERE GRANTEETYPE = ? 62 | AND GRANTEE = ? 63 | UNION ALL 64 | SELECT GRANTOR,GRANTORTYPE 65 | , 'TABLESPACE' AS OBJ_TYPE 66 | , NULL AS OBJ_SCHEMA, TBSPACE AS OBJ_NAME 67 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 68 | , USEAUTH, NULL, NULL, NULL, NULL, NULL 69 | FROM SYSCAT.TBSPACEAUTH 70 | WHERE GRANTEETYPE = ? 71 | AND GRANTEE = ? 72 | UNION ALL 73 | SELECT GRANTOR,GRANTORTYPE 74 | , 'VARIABLE' AS OBJ_TYPE 75 | , VARSCHEMA AS OBJ_SCHEMA, VARNAME AS OBJ_NAME 76 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 77 | , READAUTH AS USAGEAUTH, WRITEAUTH AS ALTERINAUTH, NULL, NULL, NULL, NULL 78 | FROM SYSCAT.VARIABLEAUTH 79 | WHERE GRANTEETYPE = ? 80 | AND GRANTEE = ? 81 | UNION ALL 82 | SELECT GRANTOR,GRANTORTYPE 83 | , 'XML_SCHEMA' AS OBJ_TYPE 84 | , NULL AS OBJ_SCHEMA, CAST(OBJECTID AS VARCHAR(32)) AS OBJ_NAME 85 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 86 | , USAGEAUTH, NULL , NULL, NULL, NULL, NULL 87 | FROM SYSCAT.XSROBJECTAUTH 88 | WHERE GRANTEETYPE = ? 89 | AND GRANTEE = ? 90 | 91 | UNION ALL 92 | SELECT GRANTOR,GRANTORTYPE 93 | , 'MODULE' AS OBJ_TYPE 94 | , MODULESCHEMA AS OBJ_SCHEMA, MODULENAME AS OBJ_NAME 95 | , NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL 96 | , NULL, NULL, NULL, NULL, NULL, EXECUTEAUTH 97 | FROM SYSCAT.MODULEAUTH 98 | WHERE GRANTEETYPE = ? 99 | AND GRANTEE = ? 100 | 101 | ORDER BY OBJ_SCHEMA, OBJ_NAME, OBJ_TYPE 102 | WITH UR ; -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/DDLFormatter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | /** 4 | * @author A_Reshetnikov 5 | * @since Date: 18.10.2012 6 | */ 7 | public class DDLFormatter { 8 | 9 | private boolean noFormat; 10 | private boolean statementOnNewLine; 11 | private boolean isMorePrettyFormat = false; 12 | 13 | static String newline = "\r\n"; //may be use "\n" 14 | 15 | public String formatDDL(String ddl) { 16 | if (noFormat) 17 | return ddl; 18 | 19 | ddl = ddl.trim() + "\n"; 20 | 21 | if (!isMorePrettyFormat) 22 | return ddl; 23 | 24 | /* smart formatting */ 25 | ddl = ddl.replaceAll(newline + "GRANT ", newline + newline + " GRANT "); 26 | ddl = ddl.replaceAll(newline + "COMMENT ", newline + newline + " COMMENT "); 27 | ddl = ddl.replaceAll(newline + " CREATE ", newline + "CREATE "); 28 | ddl = ddl.replaceAll(newline + " ALTER ", newline + "ALTER "); 29 | return ddl; 30 | } 31 | 32 | public void setNoFormat(Boolean noFormat) { 33 | this.noFormat = noFormat; 34 | } 35 | 36 | @Deprecated 37 | public void setStatementOnNewLine(Boolean statementOnNewLine) { 38 | this.statementOnNewLine = statementOnNewLine; 39 | } 40 | 41 | public void setIsMorePrettyFormat(boolean isMorePrettyFormat) { 42 | this.isMorePrettyFormat = isMorePrettyFormat; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/Db2LookInfoComparator.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.Comparator; 6 | 7 | /** 8 | * @author ar 9 | * @since Date: 29.11.2014 10 | */ 11 | @Component 12 | public class Db2LookInfoComparator implements Comparator { 13 | public int compare(Db2LookInfo o1, Db2LookInfo o2) { 14 | return Long.compare(o1.getOpSequence(), o2.getOpSequence()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/FileNameConstructor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.beans.factory.InitializingBean; 7 | import org.springframework.util.Assert; 8 | 9 | import java.util.HashMap; 10 | import java.util.Map; 11 | 12 | /** 13 | * @author A_Reshetnikov 14 | * @since Date: 01.05.2013 15 | */ 16 | public class FileNameConstructor implements InitializingBean { 17 | 18 | private static final Log log = LogFactory.getLog(FileNameConstructor.class); 19 | public static String kw_schema_lower = "schema"; 20 | public static String kw_type_lower = "type"; 21 | public static String kw_types_plural_lower = "types_plural"; 22 | public static String kw_objectname_lower = "object_name"; 23 | public static String kw_extension_lower = "ext"; 24 | public static String kw_schema_UPPER = "SCHEMA"; 25 | public static String kw_type_UPPER = "TYPE"; 26 | public static String kw_types_plural_UPPER = "TYPES_PLURAL"; 27 | public static String kw_objectname_UPPER = "OBJECT_NAME"; 28 | public static String kw_extension_UPPER = "EXT"; 29 | public static String nonOracleChar = "%"; //char not used in Oracle names 30 | public static String templateDefault = "types_plural/object_name.ext"; 31 | private String template; 32 | private String preparedTemplate; 33 | private Map extensionMap; 34 | 35 | /** 36 | * prepare template 37 | * replace keywords with %keyword 38 | * 39 | * @param template 40 | * @return 41 | */ 42 | private static String prepareTemplate(String template) { 43 | String[] keywords = new String[]{ 44 | kw_schema_lower, kw_schema_UPPER, 45 | kw_types_plural_lower, kw_types_plural_UPPER, 46 | kw_objectname_lower, kw_objectname_UPPER, 47 | kw_extension_lower, kw_extension_UPPER}; 48 | for (int i = 0; i < keywords.length; i++) { 49 | template = template.replace(keywords[i], nonOracleChar + keywords[i]); 50 | } 51 | // keyword kw_type_lower is substring of kw_types_plural_lower so we need additional preparing 52 | String typesPluralTail = kw_types_plural_lower.replace(kw_type_lower, ""); 53 | template = template.replaceAll(kw_type_lower + "(?!" + typesPluralTail + ")", nonOracleChar + kw_type_lower); 54 | typesPluralTail = kw_types_plural_UPPER.replace(kw_type_UPPER, ""); 55 | template = template.replaceAll(kw_type_UPPER + "(?!S_PLURAL)", nonOracleChar + kw_type_UPPER); 56 | return template; 57 | } 58 | 59 | public static String abbreviate(String type) { 60 | type = type.replace("DATABASE", "DB"); 61 | type = type.replace("database", "db"); 62 | return type; 63 | } 64 | 65 | public static String pluralaze(String type) { 66 | type = type.toLowerCase(); 67 | if (type.endsWith("x") || type.endsWith("s")) { 68 | return type + "es"; 69 | } 70 | if (type.endsWith("y")) { 71 | return type.substring(0, type.length() - 1) + "ies"; 72 | } 73 | return type + "s"; 74 | } 75 | 76 | public String map2FileName(UserObject userObject) { 77 | String filename = preparedTemplate; 78 | 79 | filename = filename.replace(nonOracleChar + kw_schema_lower, userObject.getSchema().toLowerCase()); 80 | filename = filename.replace(nonOracleChar + kw_schema_UPPER, userObject.getSchema().toUpperCase()); 81 | 82 | String typeName = abbreviate(userObject.getType()).replace(" ", "_"); 83 | 84 | //process kw_types_plural before kw_type 85 | filename = filename.replace(nonOracleChar + kw_types_plural_lower, pluralaze(typeName).toLowerCase()); 86 | filename = filename.replace(nonOracleChar + kw_types_plural_UPPER, pluralaze(typeName).toUpperCase()); 87 | 88 | filename = filename.replace(nonOracleChar + kw_type_lower, typeName.toLowerCase()); 89 | filename = filename.replace(nonOracleChar + kw_type_UPPER, typeName.toUpperCase()); 90 | 91 | filename = filename.replace(nonOracleChar + kw_objectname_lower, userObject.getName().toLowerCase()); 92 | filename = filename.replace(nonOracleChar + kw_objectname_UPPER, userObject.getName().toUpperCase()); 93 | 94 | String extension = extensionMap.get(typeName.toUpperCase()); 95 | if (extension == null) { 96 | extension = extensionMap.get("DEFAULT"); 97 | Assert.state(extension != null, String.format("No file extension rule for type %s and no DEFAULT rule", typeName.toUpperCase())); 98 | } 99 | filename = filename.replace(nonOracleChar + kw_extension_lower, extension.toLowerCase()); 100 | filename = filename.replace(nonOracleChar + kw_extension_UPPER, extension.toUpperCase()); 101 | 102 | return filename; 103 | } 104 | 105 | public void setTemplate(String template) { 106 | this.template = template; 107 | } 108 | 109 | 110 | 111 | //for compability with old configs 112 | public void afterPropertiesSet() { 113 | String s; 114 | if (this.template == null) s = templateDefault; 115 | else s = template; 116 | preparedTemplate = prepareTemplate(s); 117 | 118 | if (extensionMap == null) { 119 | extensionMap = new HashMap(); 120 | extensionMap.put("DEFAULT", "sql"); 121 | } 122 | } 123 | 124 | public void setExtensionMap(Map extensionMap) { 125 | this.extensionMap = extensionMap; 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/IsAlterSequenceValuesPredicate.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 4 | import org.apache.commons.collections.Predicate; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Check that passed Db2LookInfo object is ALTER SEQUENCE statement ... 9 | * For example 10 | * ALTER SEQUENCE "MY "."S01" RESTART WITH 40 11 | * will rewturn true 12 | * 13 | * @author ar 14 | * @since Date: 05.04.2015 15 | */ 16 | @Component 17 | public class IsAlterSequenceValuesPredicate implements Predicate { 18 | 19 | /** 20 | * Unless otherwise specified, all names can include the following characters: 21 | 22 | The letters A through Z, and a through z, as defined in the basic (7-bit) ASCII character set. 23 | When used in identifiers for objects created with SQL statements, 24 | lowercase characters "a" through "z" are converted to uppercase unless they are delimited with quotes (") 25 | 0 through 9. 26 | ! % ( ) { } . - ^ ~ _ (underscore) @, #, $, and space. 27 | \ (backslash). 28 | 29 | */ 30 | private static String allowedCharsInIdentifier = "([a-zA-Z0-9_!%~@#$\\-\\.\\^\\s])+"; 31 | 32 | 33 | private static String pattern = "ALTER SEQUENCE \""+allowedCharsInIdentifier+"\"\\.\""+ allowedCharsInIdentifier + "\" RESTART WITH (\\d+)\\s*"; 34 | 35 | public boolean evaluate(Object object) { 36 | if (!(object instanceof Db2LookInfo)){ 37 | throw new IllegalArgumentException(); 38 | 39 | } 40 | 41 | boolean result = false; 42 | 43 | result = 44 | ((Db2LookInfo) object).getObjType().equals("SEQUENCE") 45 | && 46 | ((Db2LookInfo) object).getSqlOperation().equals("ALTER") 47 | && 48 | ((Db2LookInfo) object).getSqlStmt().matches(pattern ) 49 | ; 50 | return !result; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/IsAlterTableAutoGeneratedPredicate.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 4 | import org.apache.commons.collections.Predicate; 5 | import org.springframework.stereotype.Component; 6 | 7 | /** 8 | * Check that passed Db2LookInfo object is ALTER TABLE statement matches pattern 9 | * ALTER TABLE "([^a-zA-Z0-9\s])+"."([^a-zA-Z0-9\s])+" ALTER COLUMN "([^a-zA-Z0-9\s])+" RESTART WITH (\d+) 10 | *

11 | * For example 12 | * ALTER TABLE "MY "."STUDENT" ALTER COLUMN "SID" RESTART WITH 100 13 | * will rewturn true 14 | * 15 | * @author ar 16 | * @since Date: 05.04.2015 17 | */ 18 | @Component 19 | public class IsAlterTableAutoGeneratedPredicate implements Predicate { 20 | 21 | /** 22 | * Unless otherwise specified, all names can include the following characters: 23 | 24 | The letters A through Z, and a through z, as defined in the basic (7-bit) ASCII character set. 25 | When used in identifiers for objects created with SQL statements, 26 | lowercase characters "a" through "z" are converted to uppercase unless they are delimited with quotes (") 27 | 0 through 9. 28 | ! % ( ) { } . - ^ ~ _ (underscore) @, #, $, and space. 29 | \ (backslash). 30 | 31 | */ 32 | private static String allowedCharsInIdentifier = "([a-zA-Z0-9_!%~@#$\\-\\.\\^\\s])+"; 33 | 34 | 35 | private static String pattern = "ALTER TABLE \""+allowedCharsInIdentifier+"\"\\.\""+ allowedCharsInIdentifier + "\" ALTER COLUMN \"" + allowedCharsInIdentifier +"\" RESTART WITH (\\d+)\\s*"; 36 | 37 | public boolean evaluate(Object object) { 38 | if (!(object instanceof Db2LookInfo)){ 39 | throw new IllegalArgumentException(); 40 | 41 | } 42 | 43 | boolean result = false; 44 | 45 | result = 46 | ((Db2LookInfo) object).getObjType().equals("TABLE") 47 | && 48 | ((Db2LookInfo) object).getSqlOperation().equals("ALTER") 49 | && 50 | ((Db2LookInfo) object).getSqlStmt().matches(pattern ) 51 | ; 52 | return !result; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/Main.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.dao.ConnectionDao; 4 | import com.ibm.db2.jcc.DB2DataSource; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.beans.factory.InitializingBean; 8 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 9 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 10 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; 11 | import org.springframework.context.ConfigurableApplicationContext; 12 | import org.springframework.context.support.ClassPathXmlApplicationContext; 13 | import org.springframework.context.support.FileSystemXmlApplicationContext; 14 | import org.springframework.core.task.SimpleAsyncTaskExecutor; 15 | 16 | import java.sql.SQLException; 17 | import java.util.ArrayList; 18 | import java.util.Arrays; 19 | import java.util.List; 20 | import java.util.Properties; 21 | 22 | /** 23 | * @author A_Reshetnikov 24 | * @since Date: 17.10.2012 25 | */ 26 | 27 | public class Main { 28 | 29 | private static final Log log = LogFactory.getLog(Main.class); 30 | public static String outputPath = null; 31 | public static int parallelCount = 4; 32 | private static boolean justPrintUsage = false; 33 | private static boolean justPrintVersion = false; 34 | private static boolean justTestConnection = false; 35 | private static boolean skipPublicDbLinks = false; 36 | private static boolean stopOnWarning = false; 37 | private static Boolean filterSequenceValues = null; 38 | private static String customConfigLocation = null; 39 | private static String defaultConfigLocation = "db2-scheme2ddl.config.xml"; 40 | private static String dbUrl = null; 41 | private static String schemas; 42 | private static List schemaList; 43 | 44 | 45 | 46 | 47 | public static void main(String[] args) throws Exception { 48 | collectArgs(args); 49 | if (justPrintUsage) { 50 | printUsage(); 51 | return; 52 | } 53 | if (justPrintVersion) { 54 | printVersion(); 55 | return; 56 | } 57 | 58 | ConfigurableApplicationContext context = loadApplicationContext(); 59 | 60 | modifyContext(context); 61 | 62 | validateContext(context); 63 | 64 | if (justTestConnection) { 65 | testDBConnection(context); 66 | } else { 67 | new UserObjectJobRunner().start(context); 68 | } 69 | } 70 | 71 | private static void testDBConnection(ConfigurableApplicationContext context) throws Exception { 72 | ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); 73 | DB2DataSource dataSource = (DB2DataSource) context.getBean("dataSource"); 74 | String url = dataSource.getUser() + "@" + dataSource.getServerName() + ":" + dataSource.getPortNumber() + ":" + dataSource.getDatabaseName(); 75 | if (connectionDao.isConnectionAvailable()) { 76 | System.out.println("OK success connection to " + url); 77 | } else { 78 | System.out.println("FAIL connect to " + url); 79 | throw new Exception("FAIL connect to " + url); 80 | } 81 | } 82 | 83 | private static void modifyContext(ConfigurableApplicationContext context) throws Exception { 84 | // DB2Driver todo 85 | 86 | if (dbUrl != null) { 87 | String url = "jdbc:db2://" + dbUrl; 88 | final String user = extractUserfromDbUrl(dbUrl); 89 | final String password = extractPasswordfromDbUrl(dbUrl); 90 | final String serverName = extractServerNamefromDbUrl(dbUrl); 91 | final int serverPort = extractPortFromDbUrl(dbUrl); 92 | final String databaseName = extractDbNameFromDbUrl(dbUrl); 93 | DB2DataSource dataSource = (DB2DataSource) context.getBean("dataSource"); 94 | dataSource.setServerName(serverName); 95 | dataSource.setPortNumber(serverPort); 96 | dataSource.setDatabaseName(databaseName); 97 | dataSource.setDriverType(4); 98 | dataSource.setUser(user); 99 | dataSource.setPassword(password); 100 | } 101 | if (outputPath != null) { 102 | UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); 103 | writer.setOutputPath(outputPath); 104 | } 105 | if (parallelCount > 0) { 106 | SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context.getBean("taskExecutor"); 107 | taskExecutor.setConcurrencyLimit(parallelCount); 108 | } 109 | 110 | processSchemas(context); 111 | 112 | FileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); //will create new one if not exist 113 | 114 | 115 | 116 | Properties properties = (Properties) context.getBean("mainProperties"); 117 | properties.setProperty("stopOnWarning", String.valueOf(stopOnWarning)); 118 | if (filterSequenceValues!=null) { 119 | properties.setProperty("filterSequenceValues", String.valueOf(filterSequenceValues)); 120 | } 121 | 122 | InitializingBean processor = (InitializingBean) context.getBean("processor"); 123 | processor.afterPropertiesSet(); 124 | 125 | 126 | 127 | } 128 | 129 | private static void processSchemas(ConfigurableApplicationContext context) { 130 | List listFromContext = retrieveSchemaListFromContext(context); 131 | if (schemas == null) { 132 | if (listFromContext.size() == 0) { 133 | schemaList = findSchemaListInDb(context); 134 | } else { 135 | 136 | } 137 | } else { 138 | String[] array = schemas.split(","); 139 | schemaList = new ArrayList(Arrays.asList(array)); 140 | } 141 | 142 | listFromContext.clear(); 143 | for (String s : schemaList) { 144 | listFromContext.add(s.toUpperCase().trim()); 145 | } 146 | 147 | //for compabality with old config 148 | if (listFromContext.size() == 1) { 149 | try { 150 | UserObjectReader userObjectReader = (UserObjectReader) context.getBean("reader"); 151 | userObjectReader.setSchemaName(listFromContext.get(0)); 152 | } catch (ClassCastException e) { 153 | // this mean that new config used, nothing to do 154 | } 155 | } 156 | } 157 | 158 | private static List findSchemaListInDb(ConfigurableApplicationContext context) { 159 | ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); 160 | List list = connectionDao.findAvailableSchemas(); 161 | List excludedSchemas = (List) context.getBean("excludedSchemas"); 162 | list.removeAll(excludedSchemas); 163 | list.remove(null); 164 | return list; 165 | 166 | } 167 | 168 | 169 | /** 170 | * @param context 171 | * @return existing bean 'schemaList', if this exists, or create and register new bean 172 | */ 173 | private static List retrieveSchemaListFromContext(ConfigurableApplicationContext context) { 174 | List list; 175 | try { 176 | list = (List) context.getBean("schemaList"); 177 | } catch (NoSuchBeanDefinitionException e) { 178 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); 179 | beanFactory.registerBeanDefinition("schemaList", BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class).getBeanDefinition()); 180 | list = (List) context.getBean("schemaList"); 181 | } 182 | return list; 183 | } 184 | 185 | /** 186 | * @param context 187 | * @return existing bean 'fileNameConstructor', if this exists, or create and register new bean 188 | */ 189 | private static FileNameConstructor retrieveFileNameConstructor(ConfigurableApplicationContext context) { 190 | FileNameConstructor fileNameConstructor; 191 | try { 192 | fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); 193 | } catch (NoSuchBeanDefinitionException e) { 194 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); 195 | beanFactory.registerBeanDefinition("fileNameConstructor", BeanDefinitionBuilder.rootBeanDefinition(FileNameConstructor.class).getBeanDefinition()); 196 | fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); 197 | fileNameConstructor.afterPropertiesSet(); 198 | //for compatability with old config without fileNameConstructor bean 199 | UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context.getBean("processor"); 200 | userObjectProcessor.setFileNameConstructor(fileNameConstructor); 201 | } 202 | return fileNameConstructor; 203 | } 204 | 205 | private static String extractUserfromDbUrl(String dbUrl) { 206 | return dbUrl.split("/")[0]; 207 | } 208 | 209 | private static String extractServerNamefromDbUrl(String dbUrl) { 210 | //user/pass@serverName:port:DbName 211 | return dbUrl.split("@")[1].split("/|:")[0]; 212 | } 213 | 214 | protected static int extractPortFromDbUrl(String dbUrl) { 215 | //user/pass@serverName:port:DbName 216 | return Integer.parseInt(dbUrl.split("@")[1].split("/|:")[1]); 217 | } 218 | 219 | private static String extractDbNameFromDbUrl(String dbUrl) { 220 | //user/pass@serverName:port:DbName 221 | return dbUrl.split("@")[1].split("/|:")[2]; 222 | } 223 | 224 | private static String extractPasswordfromDbUrl(String dbUrl) { 225 | //scott/tiger@localhost:1521:ORCL 226 | return dbUrl.split("/|@")[1]; 227 | } 228 | 229 | private static void validateContext(ConfigurableApplicationContext context) { 230 | // String userName = ((OracleDataSource) context.getBean("dataSource")).getUser().toUpperCase(); 231 | // List schemaList = (List) context.getBean("schemaList"); 232 | // Assert.state(isLaunchedByDBA || schemaList.size() == 1, "Cannot process multiply schemas if oracle user is not connected as sysdba"); 233 | // if (!isLaunchedByDBA) { 234 | // String schemaName = schemaList.get(0).toUpperCase(); 235 | // Assert.state(userName.startsWith(schemaName), 236 | // String.format("Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", schemaName, userName.toLowerCase())); 237 | // } 238 | } 239 | 240 | /** 241 | * Prints the usage information for this class to System.out. 242 | */ 243 | private static void printUsage() { 244 | String lSep = System.getProperty("line.separator"); 245 | StringBuffer msg = new StringBuffer(); 246 | msg.append("java -jar db2-scheme2ddl.jar [-url ] [-o] [-s]" + lSep); 247 | msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + lSep); 248 | msg.append("internally call to dbms_metadata.get_ddl " + lSep); 249 | msg.append("more config options in db2-scheme2ddl.config.xml " + lSep); 250 | msg.append("Options: " + lSep); 251 | msg.append(" -help, -h print this message" + lSep); 252 | // msg.append(" -verbose, -v be extra verbose" + lSep); 253 | msg.append(" -url, DB connection URL" + lSep); 254 | msg.append(" example: scott/tiger@localhost:5000:SAMPLE" + lSep); 255 | 256 | msg.append(" -o, --output, output dir" + lSep); 257 | msg.append(" -p, --parallel, number of parallel thread (default 4)" + lSep); 258 | msg.append(" -s, --schemas, a comma separated list of schemas for processing" + lSep); 259 | msg.append(" -c, --config, path to scheme2ddl config file (xml)" + lSep); 260 | msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + lSep); 261 | msg.append(" --filter-sequence-values, doesn't include alter statements with current sequence values" + lSep); 262 | msg.append(" -tc,--test-connection, test db connection available" + lSep); 263 | msg.append(" -version, print version info and exit" + lSep); 264 | System.out.println(msg.toString()); 265 | } 266 | 267 | private static void printVersion() { 268 | System.out.println("scheme2ddl version " + getVersion()); 269 | } 270 | 271 | private static String getVersion() { 272 | return Main.class.getPackage().getImplementationVersion(); 273 | } 274 | 275 | private static void collectArgs(String[] args) throws Exception { 276 | 277 | for (int i = 0; i < args.length; i++) { 278 | String arg = args[i]; 279 | if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { 280 | justPrintUsage = true; 281 | } else if (arg.equals("-url") || arg.equals("--url")) { 282 | dbUrl = args[i + 1]; 283 | 284 | i++; 285 | } else if (arg.equals("-o") || arg.equals("-output") || arg.equals("--output")) { 286 | outputPath = args[i + 1]; 287 | i++; 288 | } else if (arg.equals("-s") || arg.equals("-schemas") || arg.equals("--schemas")) { 289 | schemas = args[i + 1]; 290 | i++; 291 | } else if (arg.equals("-p") || arg.equals("--parallel") || arg.equals("-parallel")) { 292 | parallelCount = Integer.parseInt(args[i + 1]); 293 | i++; 294 | } else if (arg.equals("-tc") || arg.equals("--test-connection")) { 295 | justTestConnection = true; 296 | } else if (arg.equals("--stop-on-warning")) { 297 | stopOnWarning = true; 298 | } else if (arg.equals("--filter-sequence-values")) { 299 | filterSequenceValues = true; 300 | } else if (arg.equals("-c") || arg.equals("--config")) { 301 | customConfigLocation = args[i + 1]; 302 | i++; 303 | } else if (arg.equals("-version")) { 304 | justPrintVersion = true; 305 | } else if (arg.startsWith("-")) { 306 | // we don't have any more args to recognize! 307 | String msg = "Unknown argument: " + arg; 308 | System.err.println(msg); 309 | printUsage(); 310 | throw new Exception(""); 311 | } 312 | } 313 | } 314 | 315 | private static ConfigurableApplicationContext loadApplicationContext() { 316 | ConfigurableApplicationContext context = null; 317 | if (customConfigLocation != null) 318 | context = new FileSystemXmlApplicationContext(customConfigLocation); 319 | else 320 | context = new ClassPathXmlApplicationContext(defaultConfigLocation); 321 | return context; 322 | } 323 | } 324 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/RoutineAuthPrinter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.GrantType; 4 | import com.googlecode.scheme2ddl.db2.domain.RoutineAuth; 5 | import com.googlecode.scheme2ddl.db2.domain.TabAuth; 6 | import org.springframework.format.Printer; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.Locale; 10 | 11 | /** 12 | * @author ar 13 | * @since Date: 01.04.2015 14 | */ 15 | @Component 16 | public class RoutineAuthPrinter implements Printer { 17 | 18 | /* 19 | >>-GRANT EXECUTE ON--+-| function-designator |----------+-------> 20 | +-FUNCTION--+---------+--*---------+ 21 | | '-schema.-' | 22 | +-| method-designator |------------+ 23 | +-METHOD * FOR--+-type-name------+-+ 24 | | '-+---------+--*-' | 25 | | '-schema.-' | 26 | +-| procedure-designator |---------+ 27 | '-PROCEDURE--+---------+--*--------' 28 | '-schema.-' 29 | 30 | .-,---------------------------------. 31 | V | 32 | >--TO----+-+-------+--authorization-name-+-+--------------------> 33 | | +-USER--+ | 34 | | +-GROUP-+ | 35 | | '-ROLE--' | 36 | '-PUBLIC------------------------' 37 | 38 | >--+-------------------+--------------------------------------->< 39 | '-WITH GRANT OPTION-' 40 | 41 | function-designator 42 | 43 | |--+-FUNCTION--function-name--+-------------------------+-+-----| 44 | | '-(--+---------------+--)-' | 45 | | | .-,---------. | | 46 | | | V | | | 47 | | '---data-type-+-' | 48 | '-SPECIFIC FUNCTION--specific-name---------------------' 49 | 50 | method-designator 51 | 52 | |--+-METHOD--method-name--+-------------------------+--FOR--type-name-+--| 53 | | '-(--+---------------+--)-' | 54 | | | .-,---------. | | 55 | | | V | | | 56 | | '---data-type-+-' | 57 | '-SPECIFIC METHOD--specific-name-----------------------------------' 58 | 59 | procedure-designator 60 | 61 | |--+-PROCEDURE--procedure-name--+-------------------------+-+---| 62 | | '-(--+---------------+--)-' | 63 | | | .-,---------. | | 64 | | | V | | | 65 | | '---data-type-+-' | 66 | '-SPECIFIC PROCEDURE--specific-name----------------------' 67 | 68 | */ 69 | 70 | 71 | public static String template = "GRANT EXECUTE ON %s \"%s\".\"%s\" TO %s %s %s ;\n"; 72 | 73 | 74 | public String print(RoutineAuth routineAuth, Locale locale) { 75 | 76 | StringBuffer sb = new StringBuffer(); 77 | 78 | sb.append(String.format(template, routineAuth.getRoutineType().name(), routineAuth.getSchema(), 79 | routineAuth.getSpecificname(), routineAuth.getGranteeType().getSql(), 80 | routineAuth.getGrantee(), routineAuth.getExecuteAuth().getSql())); 81 | 82 | 83 | return sb.toString(); 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/TabAuthPrinter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.GrantType; 4 | import com.googlecode.scheme2ddl.db2.domain.TabAuth; 5 | import org.springframework.format.Printer; 6 | import org.springframework.stereotype.Component; 7 | 8 | import java.util.Locale; 9 | 10 | /** 11 | * @author ar 12 | * @since Date: 14.12.2014 13 | */ 14 | @Component 15 | public class TabAuthPrinter implements Printer { 16 | 17 | /* 18 | .-PRIVILEGES-. 19 | >>-GRANT--+-ALL--+------------+---------------------------+-----> 20 | | .-,-----------------------------------------. | 21 | | V | | 22 | '---+-ALTER---------------------------------+-+-' 23 | +-CONTROL-------------------------------+ 24 | +-DELETE--------------------------------+ 25 | +-INDEX---------------------------------+ 26 | +-INSERT--------------------------------+ 27 | +-REFERENCES--+-----------------------+-+ 28 | | | .-,-----------. | | 29 | | | V | | | 30 | | '-(----column-name-+--)-' | 31 | +-SELECT--------------------------------+ 32 | '-UPDATE--+-----------------------+-----' 33 | | .-,-----------. | 34 | | V | | 35 | '-(----column-name-+--)-' 36 | 37 | .-TABLE-. 38 | >--ON--+-------+--+-table-name----+-----------------------------> 39 | | (1) | 40 | +-view-name-----+ 41 | '-nickname------' 42 | 43 | .-,---------------------------------. 44 | V | 45 | >--TO----+-+-------+--authorization-name-+-+--------------------> 46 | | +-USER--+ | 47 | | +-GROUP-+ | 48 | | '-ROLE--' | 49 | '-PUBLIC------------------------' 50 | 51 | >--+-------------------+--------------------------------------->< 52 | '-WITH GRANT OPTION-' 53 | 54 | */ 55 | 56 | 57 | public static String template = "GRANT %s ON TABLE \"%s\".\"%s\" TO %s %s %s ;\n"; 58 | 59 | 60 | public String print(TabAuth tabAuth, Locale locale) { 61 | 62 | //todo fix PUBLIC 63 | StringBuffer sb = new StringBuffer(); 64 | 65 | if (!tabAuth.getAlterAuth().equals(GrantType.N)) { 66 | sb.append(String.format(template, "ALTER", tabAuth.getTabSchema(), 67 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 68 | tabAuth.getGrantee(), tabAuth.getAlterAuth().getSql())); 69 | } 70 | if (!tabAuth.getControlAuth().equals(GrantType.N)) { 71 | sb.append(String.format(template, "CONTROL", tabAuth.getTabSchema(), 72 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 73 | tabAuth.getGrantee(), tabAuth.getControlAuth().getSql())); 74 | } 75 | 76 | if (!tabAuth.getDeleteAuth().equals(GrantType.N)) { 77 | sb.append(String.format(template, "DELETE", tabAuth.getTabSchema(), 78 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 79 | tabAuth.getGrantee(), tabAuth.getDeleteAuth().getSql())); 80 | } 81 | if (!tabAuth.getIndexAuth().equals(GrantType.N)) { 82 | sb.append(String.format(template, "INDEX", tabAuth.getTabSchema(), 83 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 84 | tabAuth.getGrantee(), tabAuth.getIndexAuth().getSql())); 85 | } 86 | if (!tabAuth.getInsertAuth().equals(GrantType.N)) { 87 | sb.append(String.format(template, "INSERT", tabAuth.getTabSchema(), 88 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 89 | tabAuth.getGrantee(), tabAuth.getInsertAuth().getSql())); 90 | } 91 | if (!tabAuth.getRefAuth().equals(GrantType.N)) { 92 | sb.append(String.format(template, "REFERENCES", tabAuth.getTabSchema(), 93 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 94 | tabAuth.getGrantee(), tabAuth.getRefAuth().getSql())); 95 | } 96 | if (!tabAuth.getSelectAuth().equals(GrantType.N)) { 97 | sb.append(String.format(template, "SELECT", tabAuth.getTabSchema(), 98 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 99 | tabAuth.getGrantee(), tabAuth.getSelectAuth().getSql())); 100 | } 101 | if (!tabAuth.getUpdateAuth().equals(GrantType.N)) { 102 | sb.append(String.format(template, "UPDATE", tabAuth.getTabSchema(), 103 | tabAuth.getTabName(), tabAuth.getGranteeType().getSql(), 104 | tabAuth.getGrantee(), tabAuth.getUpdateAuth().getSql())); 105 | } 106 | 107 | 108 | return sb.toString(); 109 | } 110 | 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/UserObjectJobRunner.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import org.apache.commons.logging.Log; 4 | import org.apache.commons.logging.LogFactory; 5 | import org.springframework.batch.core.*; 6 | import org.springframework.batch.core.launch.JobLauncher; 7 | import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 8 | import org.springframework.context.ConfigurableApplicationContext; 9 | import org.springframework.util.Assert; 10 | 11 | import java.util.List; 12 | 13 | /** 14 | * @author A_Reshetnikov 15 | * @since Date: 22.10.2012 16 | */ 17 | public class UserObjectJobRunner { 18 | protected static final Log logger = LogFactory.getLog(UserObjectJobRunner.class); 19 | private JobLauncher launcher; 20 | 21 | int start(ConfigurableApplicationContext context ) throws Exception { 22 | try { 23 | context.getAutowireCapableBeanFactory().autowireBeanProperties(this, 24 | AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); 25 | 26 | Assert.state(launcher != null, "A JobLauncher must be provided. Please add one to the configuration."); 27 | Job job = (Job) context.getBean("job1"); 28 | 29 | List schemaList = (List) context.getBean("schemaList"); 30 | Assert.state(schemaList != null && schemaList.size()!=0, "schemaList must be provided. Please add one to the configuration. "); 31 | 32 | logger.info(String.format("Will try to process schema %s %s ", schemaList.size() > 1 ? "list" : "", schemaList)); 33 | 34 | for (String schemaName : schemaList){ 35 | JobParametersBuilder parametersBuilder = new JobParametersBuilder(); 36 | parametersBuilder.addString("schemaName", schemaName); 37 | JobParameters jobParameters = parametersBuilder.toJobParameters(); 38 | logger.trace(String.format("Start spring batch job with parameters %s", jobParameters)); 39 | JobExecution jobExecution = launcher.run(job, jobParameters); 40 | //write some log 41 | writeJobExecutionStatus(jobExecution, jobParameters); 42 | if (jobExecution.getStatus().isUnsuccessful()){ 43 | throw new Exception(String.format("Job %s unsuccessful", jobParameters)); 44 | } 45 | } 46 | 47 | logger.info(String.format("Processing schema %s %s completed ", schemaList.size() > 1 ? "list" : "", schemaList)); 48 | 49 | return 1; 50 | 51 | } catch (Exception e) { 52 | String message = "Job Terminated in error: " + e.getMessage(); 53 | logger.error(message, e); 54 | throw e; 55 | } finally { 56 | if (context != null) { 57 | context.close(); 58 | } 59 | } 60 | } 61 | 62 | private JobParameters getJobParameters(String schemaName, boolean launchedByDBA) { 63 | JobParametersBuilder parametersBuilder = new JobParametersBuilder(); 64 | parametersBuilder.addString("schemaName", schemaName.toUpperCase()); 65 | return parametersBuilder.toJobParameters(); 66 | } 67 | 68 | private void writeJobExecutionStatus(JobExecution jobExecution, JobParameters jobParameters) { 69 | StepExecution step = jobExecution.getStepExecutions().toArray(new StepExecution[]{})[0]; 70 | String schemaName = jobParameters.getString("schemaName"); 71 | logger.info(String.format("Written %d ddls with user objects from total %d in schema %s", 72 | step.getWriteCount(), step.getReadCount(), schemaName)); 73 | logger.info(String.format("Skip processing %d user objects from total %d in schema %s", 74 | step.getFilterCount(), step.getReadCount(), schemaName)); 75 | long seconds = ((step.getEndTime().getTime()-step.getStartTime().getTime())/1000); 76 | logger.info(String.format("scheme2ddl of schema %s %s in %d seconds", schemaName, jobExecution.getStatus().toString().toLowerCase(), seconds)); 77 | } 78 | 79 | public void setLauncher(JobLauncher launcher) { 80 | this.launcher = launcher; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/UserObjectProcessor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.dao.GrantsDao; 4 | import com.googlecode.scheme2ddl.db2.dao.UserObjectDao; 5 | import com.googlecode.scheme2ddl.db2.domain.*; 6 | import com.googlecode.scheme2ddl.exception.CannotGetDDLException; 7 | import com.googlecode.scheme2ddl.exception.NonSkippableException; 8 | import org.apache.commons.collections.CollectionUtils; 9 | import org.apache.commons.collections.Predicate; 10 | import org.apache.commons.logging.Log; 11 | import org.apache.commons.logging.LogFactory; 12 | import org.springframework.batch.item.ItemProcessor; 13 | import org.springframework.beans.factory.InitializingBean; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | import org.springframework.beans.factory.annotation.Value; 16 | import org.springframework.stereotype.Component; 17 | 18 | import javax.annotation.Resource; 19 | import java.util.*; 20 | 21 | 22 | /** 23 | * @author A_Reshetnikov 24 | * @since Date: 17.10.2012 25 | */ 26 | @Component(value = "processor") 27 | public class UserObjectProcessor implements ItemProcessor, InitializingBean { 28 | 29 | private static final Log log = LogFactory.getLog(UserObjectProcessor.class); 30 | @Autowired 31 | private UserObjectDao userObjectDao; 32 | @Autowired 33 | private GrantsDao grantsDao; 34 | @Autowired 35 | private TabAuthPrinter tabAuthPrinter; 36 | @Autowired 37 | private RoutineAuthPrinter routineAuthPrinter; 38 | @Autowired 39 | private DDLFormatter ddlFormatter; 40 | @Autowired 41 | private FileNameConstructor fileNameConstructor; 42 | @Resource 43 | private Map> excludes; 44 | @Resource 45 | private Map> dependencies; 46 | @Value( value = "#{mainProperties[stopOnWarning]}") 47 | private boolean stopOnWarning; 48 | @Value( value = "#{mainProperties[filterSequenceValues]}") 49 | private boolean filterSequenceValues; 50 | @Autowired 51 | private Predicate isAlterTableAutoGeneratedPredicate; 52 | @Autowired 53 | private Predicate isAlterSequenceValuesPredicate; 54 | 55 | @Autowired 56 | private Comparator db2LookInfoComparator; 57 | 58 | @Autowired 59 | private Properties mainProperties; //keep it for overwriting from cli invokation 60 | 61 | public UserObject process(UserObject userObject) throws Exception { 62 | 63 | if (needToExclude(userObject)) { 64 | log.debug(String.format("Skipping processing of user object %s ", userObject)); 65 | return null; 66 | } 67 | userObject.setDdl(map2Ddl(userObject)); 68 | userObject.setFileName(fileNameConstructor.map2FileName(userObject)); 69 | return userObject; 70 | } 71 | 72 | private boolean needToExclude(UserObject userObject) { 73 | if (excludes == null || excludes.size() == 0) return false; 74 | if (excludes.get("*") != null) { 75 | for (String pattern : excludes.get("*")) { 76 | if (matchesByPattern(userObject.getName(), pattern)) 77 | return true; 78 | } 79 | } 80 | for (String typeName : excludes.keySet()) { 81 | if (typeName.equalsIgnoreCase(userObject.getType())) { 82 | if (excludes.get(typeName) == null) return true; 83 | for (String pattern : excludes.get(typeName)) { 84 | if (matchesByPattern(userObject.getName(), pattern)) 85 | return true; 86 | } 87 | } 88 | } 89 | return false; 90 | } 91 | 92 | private boolean matchesByPattern(String s, String pattern) { 93 | pattern = pattern.replace("*", "(.*)").toLowerCase(); 94 | return s.toLowerCase().matches(pattern); 95 | } 96 | 97 | private String map2Ddl(UserObject userObject) throws CannotGetDDLException, NonSkippableException { 98 | try { 99 | 100 | List list = userObjectDao.findDDLs(userObject); 101 | 102 | if (userObject.getType().equals("TABLE")) 103 | 104 | { 105 | if (dependencies.get(DB2ObjectType.TABLE) != null 106 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.COLUMN)) { 107 | list.addAll(userObjectDao.findTableColumns(userObject)); 108 | } 109 | if (dependencies.get(DB2ObjectType.TABLE) != null 110 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.INDEX)) { 111 | list.addAll(userObjectDao.findTableIndexes(userObject)); 112 | } 113 | if (dependencies.get(DB2ObjectType.TABLE) != null 114 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.CHECK)) { 115 | list.addAll(userObjectDao.findTableChecks(userObject)); 116 | } 117 | if (dependencies.get(DB2ObjectType.TABLE) != null 118 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.FOREIGN_KEY)) { 119 | list.addAll(userObjectDao.findTableFkeys(userObject)); 120 | } 121 | if (dependencies.get(DB2ObjectType.TABLE) != null 122 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.PRIMARY_KEY)) { 123 | list.addAll(userObjectDao.findTablePkeys(userObject)); 124 | } 125 | if (dependencies.get(DB2ObjectType.TABLE) != null 126 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.UNIQUE)) { 127 | list.addAll(userObjectDao.findTableUniques(userObject)); 128 | } 129 | } 130 | 131 | String result = ""; 132 | if (filterSequenceValues) { 133 | CollectionUtils.filter(list, isAlterTableAutoGeneratedPredicate); 134 | CollectionUtils.filter(list, isAlterSequenceValuesPredicate); 135 | } 136 | Collections.sort(list, db2LookInfoComparator); 137 | for (Db2LookInfo db2LookInfo : list) { 138 | result = result + db2LookInfo.getSqlStmt() + ";\n"; //todo config format options 139 | } 140 | 141 | if (userObject.getType().equals("TABLE")) { 142 | if (dependencies.get(DB2ObjectType.TABLE) != null 143 | && dependencies.get(DB2ObjectType.TABLE).contains(DB2ObjectType.OBJECT_GRANTS)) { 144 | List tabAuths = grantsDao.findTableGrants(userObject); 145 | 146 | if (!tabAuths.isEmpty()) { 147 | result += "\n" + 148 | "--------------------------------------------\n" + 149 | "-- Authorization Statements on Tables/Views \n" + 150 | "--------------------------------------------\n" + 151 | "\n"; 152 | } 153 | 154 | for (TabAuth tabAuth : tabAuths) { 155 | result += tabAuthPrinter.print(tabAuth, null) + "\n"; 156 | } 157 | 158 | } 159 | } 160 | 161 | if (userObject.getType().equals("VIEW")) { 162 | if (dependencies.get(DB2ObjectType.VIEW) != null 163 | && dependencies.get(DB2ObjectType.VIEW).contains(DB2ObjectType.OBJECT_GRANTS)) { 164 | List tabAuths = grantsDao.findTableGrants(userObject); 165 | 166 | if (!tabAuths.isEmpty()) { 167 | result += "\n" + 168 | "--------------------------------------------\n" + 169 | "-- Authorization Statements on Tables/Views \n" + 170 | "--------------------------------------------\n" + 171 | "\n"; 172 | } 173 | for (TabAuth tabAuth : tabAuths) { 174 | result += tabAuthPrinter.print(tabAuth, null) + "\n"; 175 | } 176 | 177 | } 178 | } 179 | 180 | if (userObject.getType().equals("FUNCTION")) { 181 | if (dependencies.get(DB2ObjectType.FUNCTION) != null 182 | && dependencies.get(DB2ObjectType.FUNCTION).contains(DB2ObjectType.OBJECT_GRANTS)) { 183 | List routineAuths = grantsDao.findRoutineGrants(userObject); 184 | 185 | if (!routineAuths.isEmpty()) { 186 | result += "\n" + 187 | "-----------------------------------------------------\n" + 188 | "-- Authorization Statements on User Defined Functions \n" + 189 | "-----------------------------------------------------\n" + 190 | "\n"; 191 | } 192 | for (RoutineAuth routineAuth : routineAuths) { 193 | result += routineAuthPrinter.print(routineAuth, null) + "\n"; 194 | } 195 | 196 | } 197 | } 198 | 199 | if (userObject.getType().equals("PROCEDURE")) { 200 | if (dependencies.get(DB2ObjectType.PROCEDURE) != null 201 | && dependencies.get(DB2ObjectType.PROCEDURE).contains(DB2ObjectType.OBJECT_GRANTS)) { 202 | List routineAuths = grantsDao.findRoutineGrants(userObject); 203 | 204 | if (!routineAuths.isEmpty()) { 205 | result += "\n" + 206 | "-----------------------------------------------------\n" + 207 | "-- Authorization Statements on Stored Procedures \n" + 208 | "-----------------------------------------------------" + 209 | "\n"; 210 | } 211 | for (RoutineAuth routineAuth : routineAuths) { 212 | result += routineAuthPrinter.print(routineAuth, null) + "\n"; 213 | } 214 | 215 | } 216 | } 217 | 218 | 219 | return ddlFormatter.formatDDL(result); 220 | } catch (Exception e) { 221 | log.warn(String.format("Cannot get DDL for object %s with error message %s", userObject, e.getMessage())); 222 | if (stopOnWarning) { 223 | throw new NonSkippableException(e); 224 | } else 225 | throw new CannotGetDDLException(e); 226 | } 227 | 228 | } 229 | 230 | public void setExcludes(Map excludes) { 231 | this.excludes = excludes; 232 | } 233 | 234 | public void setDependencies(Map dependencies) { 235 | this.dependencies = dependencies; 236 | } 237 | 238 | public void setUserObjectDao(UserObjectDao userObjectDao) { 239 | this.userObjectDao = userObjectDao; 240 | } 241 | 242 | public void setDdlFormatter(DDLFormatter ddlFormatter) { 243 | this.ddlFormatter = ddlFormatter; 244 | } 245 | 246 | public void setFileNameConstructor(FileNameConstructor fileNameConstructor) { 247 | this.fileNameConstructor = fileNameConstructor; 248 | } 249 | 250 | public void setStopOnWarning(boolean stopOnWarning) { 251 | this.stopOnWarning = stopOnWarning; 252 | } 253 | 254 | public void setFilterSequenceValues(boolean filterSequenceValues) { 255 | this.filterSequenceValues = filterSequenceValues; 256 | } 257 | 258 | public void afterPropertiesSet() throws Exception { 259 | stopOnWarning = Boolean.valueOf(mainProperties.getProperty("stopOnWarning")); 260 | filterSequenceValues = Boolean.valueOf(mainProperties.getProperty("filterSequenceValues")); 261 | } 262 | } 263 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/UserObjectReader.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.dao.UserObjectDao; 4 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.batch.item.ItemReader; 8 | import org.springframework.batch.item.NonTransientResourceException; 9 | import org.springframework.batch.item.ParseException; 10 | import org.springframework.batch.item.UnexpectedInputException; 11 | import org.springframework.beans.factory.annotation.Autowired; 12 | import org.springframework.beans.factory.annotation.Value; 13 | import org.springframework.context.annotation.Scope; 14 | import org.springframework.stereotype.Component; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * @author A_Reshetnikov 20 | * @since Date: 17.10.2012 21 | */ 22 | @Component (value = "reader") 23 | @Scope(value = "step") 24 | public class UserObjectReader implements ItemReader { 25 | 26 | private static final Log log = LogFactory.getLog(UserObjectReader.class); 27 | private List list; 28 | 29 | @Autowired 30 | private UserObjectDao userObjectDao; 31 | 32 | 33 | @Value("#{jobParameters['schemaName']}") 34 | private String schemaName; 35 | 36 | 37 | public synchronized UserObject read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { 38 | if (list == null) { 39 | fillList(); 40 | log.info(String.format("Found %s items for processing in schema %s", list.size(), schemaName)); 41 | } 42 | if (list.size() == 0) { 43 | return null; 44 | } else 45 | return list.remove(0); 46 | } 47 | 48 | private synchronized void fillList() { 49 | log.info(String.format("Start getting of user object list in schema %s for processing", schemaName)); 50 | list = userObjectDao.findListForProccessing(); 51 | 52 | } 53 | 54 | public void setUserObjectDao(UserObjectDao userObjectDao) { 55 | this.userObjectDao = userObjectDao; 56 | } 57 | 58 | public void setSchemaName(String schemaName) { 59 | this.schemaName = schemaName; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/UserObjectWriter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | 4 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 5 | import org.apache.commons.io.FileUtils; 6 | import org.apache.commons.io.FilenameUtils; 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.springframework.batch.core.StepExecution; 10 | import org.springframework.batch.core.annotation.BeforeStep; 11 | import org.springframework.batch.item.ExecutionContext; 12 | import org.springframework.batch.item.ItemWriter; 13 | 14 | import java.io.File; 15 | import java.util.List; 16 | 17 | /** 18 | * @author A_Reshetnikov 19 | * @since Date: 16.10.2012 20 | */ 21 | public class UserObjectWriter implements ItemWriter { 22 | 23 | private static final Log log = LogFactory.getLog(UserObjectWriter.class); 24 | private String outputPath; 25 | 26 | private StepExecution stepExecution; 27 | 28 | 29 | public void write(List data) throws Exception { 30 | if (data.size() > 0) { 31 | writeUserObject(data.get(0)); 32 | } 33 | } 34 | 35 | public void writeUserObject(UserObject userObject) throws Exception { 36 | String absoluteFileName = outputPath + "/" + userObject.getFileName(); 37 | absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); 38 | File file = new File(absoluteFileName); 39 | FileUtils.writeStringToFile(file, userObject.getDdl()); 40 | log.info(String.format("Saved %s %s.%s to file %s", 41 | userObject.getType().toLowerCase(), 42 | userObject.getSchema().toLowerCase(), 43 | userObject.getName().toLowerCase(), 44 | file.getAbsolutePath())); 45 | ExecutionContext stepContext = this.stepExecution.getExecutionContext(); 46 | stepContext.put("opToken", userObject.getOpToken()); 47 | } 48 | 49 | @BeforeStep 50 | public void saveStepExecution(StepExecution stepExecution) { 51 | this.stepExecution = stepExecution; 52 | } 53 | 54 | 55 | 56 | public void setOutputPath(String outputPath) { 57 | this.outputPath = outputPath; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/aspect/Db2LookInfoStatAspect.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.aspect; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 4 | import org.aspectj.lang.annotation.After; 5 | import org.aspectj.lang.annotation.AfterReturning; 6 | import org.aspectj.lang.annotation.Aspect; 7 | import org.aspectj.lang.annotation.Before; 8 | import org.springframework.batch.core.Job; 9 | import org.springframework.batch.core.JobParameters; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.ArrayList; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | /** 17 | * @author ar 18 | * @since Date: 05.04.2015 19 | */ 20 | @Aspect 21 | @Component 22 | public class Db2LookInfoStatAspect { 23 | private List listExludedByFilter; 24 | private List listExludedByAlterSequenceFilter; 25 | 26 | public Db2LookInfoStatAspect() { 27 | this.listExludedByFilter = Collections.synchronizedList(new ArrayList()); 28 | this.listExludedByAlterSequenceFilter = Collections.synchronizedList(new ArrayList()); 29 | } 30 | 31 | @AfterReturning(pointcut = "execution(boolean com.googlecode.scheme2ddl.db2.IsAlterTableAutoGeneratedPredicate.evaluate(..)) &&" 32 | + "args(object)", 33 | returning = "retVal") 34 | public void exludedByFilter(Object object, boolean retVal) { 35 | if (retVal == false ) { 36 | listExludedByFilter.add((Db2LookInfo) object); 37 | } 38 | } 39 | @AfterReturning(pointcut = "execution(boolean com.googlecode.scheme2ddl.db2.IsAlterSequenceValuesPredicate.evaluate(..)) &&" 40 | + "args(object)", 41 | returning = "retVal") 42 | public void exludedByFilterIsAlterSequenceV(Object object, boolean retVal) { 43 | if (retVal == false ) { 44 | listExludedByAlterSequenceFilter.add((Db2LookInfo) object); 45 | } 46 | } 47 | 48 | @Before("execution(* org.springframework.batch.core.launch.JobLauncher.run(..))") 49 | public void clearStatistic() { 50 | this.listExludedByFilter = Collections.synchronizedList(new ArrayList()); 51 | this.listExludedByAlterSequenceFilter = Collections.synchronizedList(new ArrayList()); 52 | } 53 | 54 | @After("execution(* org.springframework.batch.core.launch.JobLauncher.run(..)) &&" + 55 | " args(job, jobParameters)") 56 | public void printStatistic(Job job, JobParameters jobParameters) { 57 | String schemaName = jobParameters.getString("schemaName"); 58 | if (!listExludedByFilter.isEmpty() || !listExludedByAlterSequenceFilter.isEmpty()) { 59 | prettyPrint(schemaName); 60 | } 61 | } 62 | 63 | /** 64 | * 65 | * @param schemaName 66 | * @param listExludedByConfig 67 | * @param listSkippedBySQLError 68 | */ 69 | public void prettyPrint(String schemaName) { 70 | String lSep = System.getProperty("line.separator"); 71 | StringBuilder sb = new StringBuilder(); 72 | sb.append(lSep); 73 | sb.append("-------------------------------------------------------"); 74 | sb.append(lSep); 75 | sb.append(" R E P O R T F I L T E R E D S T A T E M E N T S "); 76 | sb.append(lSep); 77 | sb.append("-------------------------------------------------------"); 78 | sb.append(lSep); 79 | if (!listExludedByFilter.isEmpty()){ 80 | sb.append(String.format("%d alter table statements with auto generated sequence values was filtered", listExludedByFilter.size())); 81 | sb.append(lSep); 82 | } 83 | if (!listExludedByAlterSequenceFilter.isEmpty()) { 84 | sb.append(String.format("%d alter sequence statements with actual sequence values was filtered", listExludedByAlterSequenceFilter.size())); 85 | sb.append(lSep); 86 | } 87 | sb.append(lSep); 88 | 89 | System.out.println(sb.toString()); 90 | 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/aspect/UserObjectStatAspect.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.aspect; 2 | 3 | 4 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 5 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 6 | import com.googlecode.scheme2ddl.exception.CannotGetDDLException; 7 | import org.aspectj.lang.annotation.*; 8 | import org.springframework.batch.core.Job; 9 | import org.springframework.batch.core.JobParameters; 10 | import org.springframework.stereotype.Component; 11 | 12 | import java.util.*; 13 | 14 | /** 15 | * Collect statistics about skipped objects and 16 | * print detailed report after end of schema processing 17 | * 18 | * @author A_Reshetnikov 19 | * @since Date: 03.07.2013 20 | */ 21 | @Aspect 22 | @Component 23 | public class UserObjectStatAspect { 24 | 25 | private List listExludedByConfig; 26 | private List listSkippedBySQLError; 27 | 28 | public UserObjectStatAspect() { 29 | this.listExludedByConfig = Collections.synchronizedList(new ArrayList()); 30 | this.listSkippedBySQLError = Collections.synchronizedList(new ArrayList()); 31 | } 32 | 33 | @AfterReturning(pointcut = "execution(* com.googlecode.scheme2ddl.db2.UserObjectProcessor.process(..)) &&" 34 | + "args(userObject)", 35 | returning = "retVal") 36 | public void exludedByConfig(UserObject userObject, Object retVal) { 37 | if (retVal == null) { 38 | listExludedByConfig.add(userObject); 39 | } 40 | } 41 | 42 | @AfterThrowing(pointcut = "execution(* com.googlecode.scheme2ddl.db2.UserObjectProcessor.process(..)) &&" 43 | + "args(userObject)", 44 | throwing = "ex") 45 | public void skippedBySQLError(UserObject userObject, CannotGetDDLException ex) { 46 | listSkippedBySQLError.add(userObject); 47 | } 48 | 49 | @Before("execution(* org.springframework.batch.core.launch.JobLauncher.run(..))") 50 | public void clearStatistic() { 51 | this.listExludedByConfig = Collections.synchronizedList(new ArrayList()); 52 | this.listSkippedBySQLError = Collections.synchronizedList(new ArrayList()); 53 | } 54 | 55 | @After("execution(* org.springframework.batch.core.launch.JobLauncher.run(..)) &&" + 56 | " args(job, jobParameters)") 57 | public void printStatistic(Job job, JobParameters jobParameters) { 58 | String schemaName = jobParameters.getString("schemaName"); 59 | prettyPrint(schemaName); 60 | 61 | } 62 | 63 | /** 64 | * report something like this: 65 | *

 66 |      *    -------------------------------------------------------
 67 |      *       R E P O R T     S K I P P E D     O B J E C T S
 68 |      *    -------------------------------------------------------
 69 |      *    | skip rule |        object type        |    count    |
 70 |      *    -------------------------------------------------------
 71 |      *    |  config   |  INDEX                    |      2      |
 72 |      *    | sql error |  PUBLIC DATABASE LINK     |      4      |
 73 |      * 
74 | * 75 | * @param schemaName 76 | * @param listExludedByConfig 77 | * @param listSkippedBySQLError 78 | */ 79 | public void prettyPrint(String schemaName) { 80 | String lSep = System.getProperty("line.separator"); 81 | StringBuilder sb = new StringBuilder(); 82 | sb.append(lSep); 83 | sb.append("-------------------------------------------------------"); 84 | sb.append(lSep); 85 | sb.append(" R E P O R T S K I P P E D O B J E C T S "); 86 | sb.append(lSep); 87 | sb.append("-------------------------------------------------------"); 88 | 89 | if (listExludedByConfig.size() + listSkippedBySQLError.size() == 0) { 90 | sb.append(" No skipped objects "); 91 | sb.append(lSep); 92 | return; 93 | } 94 | 95 | sb.append(lSep); 96 | sb.append("| skip rule | object type | count |"); 97 | sb.append(lSep); 98 | sb.append("-------------------------------------------------------"); 99 | sb.append(lSep); 100 | 101 | prettyPrintList(sb, " config ", listExludedByConfig); 102 | prettyPrintList(sb, "sql error", listSkippedBySQLError); 103 | 104 | System.out.println(sb.toString()); 105 | 106 | } 107 | 108 | private void prettyPrintList(StringBuilder sb, String ruleName, List listExludedByConfig) { 109 | String lSep = System.getProperty("line.separator"); 110 | Map groupByType = groupByType(listExludedByConfig); 111 | for (String type : groupByType.keySet()) { 112 | Formatter formatter = new Formatter(); 113 | sb.append(formatter.format("| %s | %-24s | %-6s |", ruleName, type, groupByType.get(type)).toString()); 114 | sb.append(lSep); 115 | } 116 | } 117 | 118 | private Map groupByType(List list) { 119 | Map map = new HashMap(); 120 | for (UserObject userObject : list) { 121 | 122 | if (map.containsKey(userObject.getType())) { 123 | map.put(userObject.getType(), map.get(userObject.getType()) + 1); 124 | } else { 125 | map.put(userObject.getType(), 1); 126 | } 127 | } 128 | return map; 129 | } 130 | 131 | } 132 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/ConnectionDao.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import org.springframework.stereotype.Component; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Check some properties of connection 9 | * 10 | * @author A_Reshetnikov 11 | * @since Date: 23.07.2013 12 | */ 13 | public interface ConnectionDao { 14 | 15 | boolean isConnectionAvailable(); 16 | 17 | List findAvailableSchemas(); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/ConnectionDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.dao.DataAccessException; 5 | import org.springframework.jdbc.core.support.JdbcDaoSupport; 6 | import org.springframework.stereotype.Component; 7 | 8 | import javax.sql.DataSource; 9 | import java.util.List; 10 | 11 | /** 12 | * @author A_Reshetnikov 13 | * @since Date: 23.07.2013 14 | */ 15 | @Component(value = "connectionDao") 16 | public class ConnectionDaoImpl extends JdbcDaoSupport implements ConnectionDao { 17 | 18 | @Autowired 19 | public ConnectionDaoImpl(DataSource dataSource) { 20 | this.setDataSource(dataSource); 21 | } 22 | 23 | public boolean isConnectionAvailable() { 24 | try { 25 | getJdbcTemplate().queryForInt("select 1 from SYSIBM.dual"); 26 | } catch (DataAccessException e) { 27 | return false; 28 | } 29 | return true; 30 | } 31 | 32 | public List findAvailableSchemas() { 33 | return getJdbcTemplate().queryForList("SELECT table_schem from SYSIBM.SQLSCHEMAS ", String.class ); 34 | } 35 | 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/GrantsDao.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.RoutineAuth; 4 | import com.googlecode.scheme2ddl.db2.domain.TabAuth; 5 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * @author ar 11 | * @since Date: 14.12.2014 12 | */ 13 | public interface GrantsDao { 14 | 15 | List findTableGrants(UserObject userObject); 16 | 17 | List findRoutineGrants(UserObject userObject); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/GrantsDaoImpl.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.*; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.context.annotation.Scope; 6 | import org.springframework.jdbc.core.RowMapper; 7 | import org.springframework.jdbc.core.support.JdbcDaoSupport; 8 | import org.springframework.stereotype.Component; 9 | 10 | import javax.sql.DataSource; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.util.List; 14 | 15 | /** 16 | * @author ar 17 | * @since Date: 14.12.2014 18 | */ 19 | @Component(value = "grantsDao") 20 | @Scope(value = "step") 21 | public class GrantsDaoImpl extends JdbcDaoSupport implements GrantsDao { 22 | 23 | 24 | @Autowired 25 | public GrantsDaoImpl(DataSource dataSource) { 26 | setDataSource(dataSource); 27 | } 28 | 29 | public List findTableGrants(UserObject userObject) { 30 | 31 | 32 | return getJdbcTemplate().query("select * from SYSCAT.TABAUTH where TABSCHEMA = ? and GRANTOR != 'SYSIBM' and TABNAME = ?", 33 | new Object[]{userObject.getSchema(), userObject.getName()}, 34 | new RowMapper() { 35 | public TabAuth mapRow(ResultSet rs, int rowNum) throws SQLException { 36 | TabAuth tabAuth = new TabAuth(); 37 | tabAuth.setGrantee(rs.getString("GRANTEE")); 38 | tabAuth.setGranteeType(GranteeType.mapByCode(rs.getString("GRANTEETYPE"))); 39 | tabAuth.setTabSchema(rs.getString("TABSCHEMA")); 40 | tabAuth.setTabName(rs.getString("TABNAME")); 41 | tabAuth.setAlterAuth(GrantType.valueOf(rs.getString("ALTERAUTH"))); 42 | tabAuth.setControlAuth(GrantType.valueOf(rs.getString("CONTROLAUTH"))); 43 | tabAuth.setDeleteAuth(GrantType.valueOf(rs.getString("DELETEAUTH"))); 44 | tabAuth.setIndexAuth(GrantType.valueOf(rs.getString("INDEXAUTH"))); 45 | tabAuth.setInsertAuth(GrantType.valueOf(rs.getString("INSERTAUTH"))); 46 | tabAuth.setRefAuth(GrantType.valueOf(rs.getString("REFAUTH"))); 47 | tabAuth.setSelectAuth(GrantType.valueOf(rs.getString("SELECTAUTH"))); 48 | tabAuth.setUpdateAuth(GrantType.valueOf(rs.getString("UPDATEAUTH"))); 49 | 50 | if ("PUBLIC ".equals(tabAuth.getGrantee())) { 51 | tabAuth.setGranteeType(GranteeType.PUBLIC); 52 | } 53 | return tabAuth; 54 | } 55 | }); 56 | } 57 | 58 | public List findRoutineGrants(UserObject userObject) { 59 | return getJdbcTemplate().query("select * from SYSCAT.ROUTINEAUTH where SCHEMA = ? and GRANTOR != 'SYSIBM' and SPECIFICNAME = ?", 60 | new Object[]{userObject.getSchema(), userObject.getName()}, 61 | new RowMapper() { 62 | public RoutineAuth mapRow(ResultSet rs, int rowNum) throws SQLException { 63 | RoutineAuth routineAuth = new RoutineAuth(); 64 | routineAuth.setGrantee(rs.getString("GRANTEE")); 65 | routineAuth.setGranteeType(GranteeType.mapByCode(rs.getString("GRANTEETYPE"))); 66 | routineAuth.setSchema(rs.getString("SCHEMA")); 67 | routineAuth.setSpecificname(rs.getString("SPECIFICNAME")); 68 | routineAuth.setRoutineType(RoutineAuth.RoutineType.mapByCode(rs.getString("ROUTINETYPE"))); 69 | routineAuth.setExecuteAuth(GrantType.valueOf(rs.getString("EXECUTEAUTH"))); 70 | 71 | if (GranteeType.GROUP.equals(routineAuth.getGranteeType()) 72 | && "PUBLIC ".equals(routineAuth.getGrantee())){ 73 | routineAuth.setGranteeType(GranteeType.PUBLIC); 74 | } 75 | 76 | return routineAuth; 77 | } 78 | }); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/UserObjectDao.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 4 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * @author A_Reshetnikov 10 | * @since Date: 17.10.2012 11 | */ 12 | public interface UserObjectDao { 13 | 14 | List findListForProccessing(); 15 | 16 | List findDDLs(UserObject userObject); 17 | 18 | List findTableColumns(UserObject userObject); 19 | 20 | List findTableIndexes(UserObject userObject); 21 | 22 | List findTableChecks(UserObject userObject); 23 | 24 | List findTableFkeys(UserObject userObject); 25 | 26 | List findTablePkeys(UserObject userObject); 27 | 28 | List findTableUniques(UserObject userObject); 29 | 30 | void callCleanTable(Long opToken); 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/dao/UserObjectDaoDb2Impl.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.dao; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.DB2ObjectType; 4 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 5 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 6 | import org.apache.commons.logging.Log; 7 | import org.apache.commons.logging.LogFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.beans.factory.annotation.Value; 10 | import org.springframework.context.annotation.Scope; 11 | import org.springframework.jdbc.core.RowMapper; 12 | import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; 13 | import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; 14 | import org.springframework.jdbc.core.support.JdbcDaoSupport; 15 | import org.springframework.stereotype.Component; 16 | 17 | import javax.annotation.PostConstruct; 18 | import javax.annotation.Resource; 19 | import javax.sql.DataSource; 20 | import java.sql.*; 21 | import java.util.HashSet; 22 | import java.util.List; 23 | import java.util.Map; 24 | import java.util.Set; 25 | 26 | /** 27 | * @author A_Reshetnikov 28 | * @since Date: 17.10.2012 29 | */ 30 | @Component(value = "userObjectDao") 31 | @Scope(value = "step") 32 | public class UserObjectDaoDb2Impl extends JdbcDaoSupport implements UserObjectDao { 33 | 34 | private static final Log log = LogFactory.getLog(UserObjectDaoDb2Impl.class); 35 | @Value("#{jobParameters['schemaName']}") 36 | private String schemaName; 37 | 38 | private Set nonPrimaryTypes; 39 | 40 | @Resource(name = "dependencies") 41 | private Map> dependencies; 42 | 43 | 44 | @Autowired 45 | public UserObjectDaoDb2Impl(DataSource dataSource) { 46 | setDataSource(dataSource); 47 | 48 | } 49 | 50 | @PostConstruct 51 | public void setNonPrimaryTypesFromDependencies() { 52 | nonPrimaryTypes = new HashSet(); 53 | for (DB2ObjectType key : dependencies.keySet()) { 54 | for (DB2ObjectType depended : dependencies.get(key)) { 55 | nonPrimaryTypes.add(depended.getInternalName()); 56 | } 57 | } 58 | } 59 | 60 | public List findListForProccessing() { 61 | 62 | 63 | long opToken = call_DB2LK_GENERATE_DDL("-e -z " + schemaName); 64 | 65 | log.debug("findListForProccessing opToken is " + opToken); 66 | 67 | MapSqlParameterSource parameters = new MapSqlParameterSource(); 68 | parameters.addValue("opToken", opToken); 69 | parameters.addValue("schemaName", schemaName); 70 | 71 | 72 | NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(getJdbcTemplate()); 73 | 74 | String sql = "SELECT DISTINCT OBJ_TYPE, OBJ_NAME, OP_TOKEN " + 75 | "FROM SYSTOOLS.DB2LOOK_INFO WHERE OP_TOKEN=:opToken AND OBJ_SCHEMA=:schemaName " ; 76 | if (nonPrimaryTypes != null && !nonPrimaryTypes.isEmpty()) { 77 | parameters.addValue("nonPrimaryTypes", nonPrimaryTypes); 78 | sql += " and OBJ_TYPE not in (:nonPrimaryTypes) "; 79 | } 80 | 81 | return namedParameterJdbcTemplate.query(sql, parameters, new UserObjectRowMapper()); 82 | } 83 | 84 | 85 | private long call_DB2LK_GENERATE_DDL(String db2lookinfoParams) { //todo rename 86 | long opToken = 0; 87 | Connection con = null; 88 | //todo rewrite with spring 89 | 90 | try { 91 | con = getDataSource().getConnection(); 92 | CallableStatement cstmt; 93 | ResultSet rs; 94 | cstmt = con.prepareCall("CALL SYSPROC.DB2LK_GENERATE_DDL(?, ?)"); 95 | cstmt.setString(1, db2lookinfoParams); 96 | cstmt.registerOutParameter(2, Types.BIGINT); 97 | cstmt.executeUpdate(); 98 | opToken = cstmt.getLong(2); 99 | } catch (SQLException e) { 100 | e.printStackTrace(); 101 | } finally { 102 | if (con != null) { 103 | try { 104 | con.close(); 105 | } catch (SQLException e) { 106 | e.printStackTrace(); 107 | } 108 | } 109 | } 110 | return opToken; 111 | 112 | } 113 | 114 | public List findDDLs(UserObject userObject) { 115 | return getJdbcTemplate().query("select OP_SEQUENCE, SQL_STMT, OBJ_SCHEMA, OBJ_TYPE, OBJ_NAME, SQL_OPERATION " + 116 | "FROM SYSTOOLS.DB2LOOK_INFO where OP_TOKEN=? and OBJ_SCHEMA=? and OBJ_TYPE=? and OBJ_NAME=?", 117 | new Object[]{userObject.getOpToken(), schemaName, userObject.getType(), userObject.getName()}, 118 | new Db2LookInfoRowMapper()); 119 | 120 | } 121 | 122 | public List findTableColumns(UserObject userObject) { 123 | if (!"TABLE".equals(userObject.getType())) { 124 | throw new IllegalArgumentException(); 125 | } 126 | 127 | List list = getJdbcTemplate().query( 128 | "SELECT * " + 129 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 130 | " WHERE OBJ_TYPE = 'COLUMN' " + 131 | " AND OP_TOKEN = ? " + 132 | " and OBJ_SCHEMA=? " + 133 | " and OBJ_NAME like ? " + 134 | " ", 135 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName() + "\".\"%"}, 136 | new Db2LookInfoRowMapper()); 137 | 138 | return list; 139 | } 140 | 141 | public List findTableIndexes(UserObject userObject) { 142 | 143 | if (!"TABLE".equals(userObject.getType())) { 144 | throw new IllegalArgumentException(); 145 | } 146 | 147 | List list = getJdbcTemplate().query( 148 | "SELECT * " + 149 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 150 | " WHERE OBJ_TYPE = 'INDEX' " + 151 | " AND OP_TOKEN = ? " + 152 | " AND exists( " + 153 | " SELECT 1 " + 154 | " FROM SYSCAT.INDEXES i " + 155 | " WHERE TABSCHEMA = ? AND TABNAME = ? AND i.INDNAME = t.OBJ_NAME ) ", 156 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName()}, 157 | 158 | new Db2LookInfoRowMapper()); 159 | 160 | 161 | return list; 162 | } 163 | 164 | public List findTableFkeys(UserObject userObject) { 165 | List list = getJdbcTemplate().query( 166 | "SELECT * " + 167 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 168 | " WHERE OBJ_TYPE = 'FKEY' " + 169 | " AND OP_TOKEN = ? " + 170 | " and OBJ_SCHEMA=? " + 171 | " and OBJ_NAME=? " + 172 | " ", 173 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName()}, 174 | 175 | new Db2LookInfoRowMapper()); 176 | 177 | 178 | return list; 179 | } 180 | 181 | public List findTableChecks(UserObject userObject) { 182 | List list = getJdbcTemplate().query( 183 | "SELECT * " + 184 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 185 | " WHERE OBJ_TYPE = 'CHECK' " + 186 | " AND OP_TOKEN = ? " + 187 | " and OBJ_SCHEMA=? " + 188 | " and OBJ_NAME=? " + 189 | " ", 190 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName()}, 191 | 192 | new Db2LookInfoRowMapper()); 193 | 194 | 195 | return list; 196 | } 197 | 198 | public List findTablePkeys(UserObject userObject) { 199 | List list = getJdbcTemplate().query( 200 | "SELECT * " + 201 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 202 | " WHERE OBJ_TYPE = 'PKEY' AND OP_TOKEN = ? AND t.OBJ_SCHEMA = ? AND OBJ_NAME = ?" , 203 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName()}, 204 | 205 | new Db2LookInfoRowMapper()); 206 | 207 | 208 | return list; 209 | } 210 | 211 | public List findTableUniques(UserObject userObject) { 212 | List list = getJdbcTemplate().query( 213 | "SELECT * " + 214 | " FROM SYSTOOLS.DB2LOOK_INFO t " + 215 | " WHERE OBJ_TYPE = 'UNIQUE' AND OP_TOKEN = ? AND t.OBJ_SCHEMA = ? AND OBJ_NAME = ?", 216 | new Object[]{userObject.getOpToken(), schemaName, userObject.getName()}, 217 | new Db2LookInfoRowMapper()); 218 | return list; 219 | } 220 | 221 | public void callCleanTable(Long opToken) { 222 | 223 | getJdbcTemplate().execute(String.format("call SYSPROC.DB2LK_CLEAN_TABLE(%d)", opToken)); 224 | //todo rewrite with ps 225 | } 226 | 227 | public void setSchemaName(String schemaName) { 228 | this.schemaName = schemaName; 229 | } 230 | 231 | 232 | private class UserObjectRowMapper implements RowMapper { 233 | public UserObject mapRow(ResultSet rs, int rowNum) throws SQLException { 234 | UserObject userObject = new UserObject(); 235 | userObject.setName(rs.getString("OBJ_NAME")); 236 | userObject.setType(rs.getString("OBJ_TYPE")); 237 | userObject.setOpToken(rs.getLong("OP_TOKEN")); 238 | userObject.setSchema(schemaName == null ? "" : schemaName); 239 | return userObject; 240 | } 241 | } 242 | 243 | private class Db2LookInfoRowMapper implements RowMapper { 244 | public Db2LookInfo mapRow(ResultSet rs, int rowNum) throws SQLException { 245 | Db2LookInfo db2LookInfo = new Db2LookInfo(); 246 | db2LookInfo.setObjName(rs.getString("OBJ_NAME")); 247 | db2LookInfo.setObjType(rs.getString("OBJ_TYPE")); 248 | db2LookInfo.setObjSchema(rs.getString("OBJ_SCHEMA").trim()); 249 | db2LookInfo.setOpSequence(rs.getLong("OP_SEQUENCE")); 250 | db2LookInfo.setSqlOperation(rs.getString("SQL_OPERATION")); 251 | db2LookInfo.setSqlStmtClob(rs.getClob("SQL_STMT")); 252 | 253 | if (db2LookInfo.getSqlStmtClob() != null) { 254 | 255 | if ((int) db2LookInfo.getSqlStmtClob().length() > 0) { 256 | String s = db2LookInfo.getSqlStmtClob().getSubString(1, (int) db2LookInfo.getSqlStmtClob().length()); 257 | db2LookInfo.setSqlStmt(s); 258 | } 259 | } 260 | 261 | return db2LookInfo; 262 | } 263 | } 264 | 265 | } 266 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/DB2ObjectType.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | /** 4 | * @author ar 5 | * @since Date: 14.12.2014 6 | */ 7 | public enum DB2ObjectType { 8 | ALIAS(null), 9 | CHECK(null), 10 | COLUMN(null), 11 | FOREIGN_KEY("FKEY"), 12 | FUNCTION(null), 13 | MODULE(null), 14 | MQT(null), 15 | INDEX(null), 16 | NICKNAME(null), 17 | PACKAGE(null), 18 | PRIMARY_KEY("PKEY"), 19 | PROCEDURE(null), 20 | REFERENCE(null), 21 | ROUTINE(null), //todo remove 22 | SCHEMA(null), 23 | SEQUENCE(null), 24 | TABLE(null), 25 | TABLESPACE(null), 26 | TRIGGER(null), 27 | UDF(null), 28 | UDT(null), 29 | UNIQUE(null), 30 | VIEW(null), 31 | VARIABLE(null), 32 | XML_SCHEMA(null), 33 | 34 | OBJECT_GRANTS(null); 35 | 36 | private String internalName; 37 | 38 | DB2ObjectType(String internalName) { 39 | this.internalName = internalName; 40 | } 41 | 42 | public String getInternalName() { 43 | return internalName == null ? name() : internalName; 44 | } 45 | } -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/Db2LookInfo.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | import java.sql.Clob; 4 | 5 | /** 6 | * Object to represent some fields of SYSTOOLS.DB2LOOK_INFO table in DB2 7 | * @author ar 8 | * @since Date: 29.11.2014 9 | */ 10 | public class Db2LookInfo { 11 | 12 | /* 13 | CREATE TABLE DB2LOOK_INFO 14 | ( 15 | OP_TOKEN INT NOT NULL, 16 | OP_SEQUENCE INT NOT NULL, 17 | SQL_OPERATION VARCHAR(129) NOT NULL, 18 | OBJ_ID INT, 19 | OBJ_TYPE VARCHAR(129) NOT NULL, 20 | OBJ_SUBTYPE CHAR(1), 21 | OBJ_SCHEMA VARCHAR(129), 22 | OBJ_NAME VARCHAR(129) NOT NULL, 23 | OBJ_DEFINER VARCHAR(129), 24 | OBJ_QUALIFIER VARCHAR(129), 25 | OBJ_ATTRIBUTE VARCHAR(129), 26 | RELATED_OBJ_INFO VARCHAR(254), 27 | CREATION_TIME TIMESTAMP, 28 | SQL_STMT CLOB(2097152) NOT NULL 29 | ); 30 | CREATE UNIQUE INDEX DB2LK_SEQUENCE_IND ON DB2LOOK_INFO (OP_TOKEN, OP_SEQUENCE, CREATION_TIME); 31 | CREATE UNIQUE INDEX DB2LOOK_IND ON DB2LOOK_INFO (OP_TOKEN, SQL_OPERATION, OBJ_TYPE, OBJ_SCHEMA, OBJ_NAME); 32 | 33 | */ 34 | 35 | private long opToken; 36 | private long opSequence; 37 | private String objSchema; 38 | private String objName; 39 | private String objType; 40 | private String sqlOperation; 41 | private String sqlStmt; 42 | private Clob sqlStmtClob; 43 | 44 | public long getOpToken() { 45 | return opToken; 46 | } 47 | 48 | public void setOpToken(long opToken) { 49 | this.opToken = opToken; 50 | } 51 | 52 | public long getOpSequence() { 53 | return opSequence; 54 | } 55 | 56 | public void setOpSequence(long opSequence) { 57 | this.opSequence = opSequence; 58 | } 59 | 60 | public String getObjSchema() { 61 | return objSchema; 62 | } 63 | 64 | public void setObjSchema(String objSchema) { 65 | this.objSchema = objSchema; 66 | } 67 | 68 | public String getObjName() { 69 | return objName; 70 | } 71 | 72 | public void setObjName(String objName) { 73 | this.objName = objName; 74 | } 75 | 76 | public String getObjType() { 77 | return objType; 78 | } 79 | 80 | public void setObjType(String objType) { 81 | this.objType = objType; 82 | } 83 | 84 | public String getSqlOperation() { 85 | return sqlOperation; 86 | } 87 | 88 | public void setSqlOperation(String sqlOperation) { 89 | this.sqlOperation = sqlOperation; 90 | } 91 | 92 | public String getSqlStmt() { 93 | return sqlStmt; 94 | } 95 | 96 | public void setSqlStmt(String sqlStmt) { 97 | this.sqlStmt = sqlStmt; 98 | } 99 | 100 | public Clob getSqlStmtClob() { 101 | return sqlStmtClob; 102 | } 103 | 104 | public void setSqlStmtClob(Clob sqlStmtClob) { 105 | this.sqlStmtClob = sqlStmtClob; 106 | } 107 | 108 | @Override 109 | public String toString() { 110 | return "Db2LookInfo{" + 111 | "opToken=" + opToken + 112 | ", opSequence=" + opSequence + 113 | ", objSchema=" + objSchema + 114 | ", objName=" + objName + 115 | ", objType=" + objType + 116 | ", sqlOperation='" + sqlOperation + '\'' + 117 | ", sqlStmt='" + sqlStmt + '\'' + 118 | '}'; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/GrantType.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | /** 4 | * @author ar 5 | * @since Date: 01.04.2015 6 | */ 7 | public enum GrantType { 8 | G("WITH GRANT OPTION"), 9 | N(""), 10 | Y(""); 11 | 12 | private String sql; 13 | 14 | GrantType(String sql) { 15 | this.sql = sql; 16 | } 17 | 18 | public String getSql() { 19 | return sql; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/GranteeType.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * @author ar 8 | * @since Date: 01.04.2015 9 | */ 10 | public enum GranteeType { 11 | USER("U", "USER"), 12 | GROUP("G", "GROUP"), 13 | ROlE("R", "ROLE"), 14 | PUBLIC("", ""); 15 | 16 | private String code; 17 | private String sql; 18 | 19 | private static Map map; 20 | 21 | static { 22 | map = new HashMap(); 23 | 24 | for (GranteeType granteeType : GranteeType.values()) { 25 | map.put(granteeType.getCode(), granteeType); 26 | } 27 | } 28 | 29 | 30 | GranteeType(String code, String sql) { 31 | this.code = code; 32 | this.sql = sql; 33 | } 34 | 35 | public String getCode() { 36 | return code; 37 | } 38 | 39 | public String getSql() { 40 | return sql; 41 | } 42 | 43 | public static GranteeType mapByCode(String code) { 44 | return map.get(code); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/RoutineAuth.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * 8 | * * Content of FROM SYSCAT.TABAUTH 9 | * Authorization Statements on routines 10 | * 11 | * @author ar 12 | * @since Date: 01.04.2015 13 | */ 14 | public class RoutineAuth { 15 | /* 16 | CREATE TABLE "ROUTINEAUTH" 17 | ( 18 | "GRANTEE" VARCHAR(128) NOT NULL, 19 | "GRANTEETYPE" CHAR(1) NOT NULL, 20 | "SCHEMA" VARCHAR(128) NOT NULL, 21 | "SPECIFICNAME" VARCHAR(128), 22 | "ROUTINETYPE" CHAR(1) NOT NULL, 23 | "EXECUTEAUTH" CHAR(1) NOT NULL, 24 | ); 25 | 26 | */ 27 | 28 | private String grantee; 29 | private GranteeType granteeType; 30 | private String schema; 31 | private String specificname; 32 | private RoutineType routineType; 33 | private GrantType executeAuth; 34 | 35 | 36 | /** 37 | * @author ar 38 | * @since Date: 01.04.2015 39 | */ 40 | public enum RoutineType { 41 | FUNCTION("F"), 42 | METHOD("M"), 43 | PROCEDURE("P"); 44 | 45 | private String code; 46 | 47 | private static Map map; 48 | 49 | static { 50 | map = new HashMap(); 51 | 52 | for (RoutineType routineType : RoutineType.values()) { 53 | map.put(routineType.getCode(), routineType); 54 | } 55 | } 56 | 57 | RoutineType(String code) { 58 | this.code = code; 59 | } 60 | 61 | public String getCode() { 62 | return code; 63 | } 64 | 65 | public static RoutineType mapByCode(String code) { 66 | return map.get(code); 67 | } 68 | } 69 | 70 | public String getGrantee() { 71 | return grantee; 72 | } 73 | 74 | public void setGrantee(String grantee) { 75 | this.grantee = grantee; 76 | } 77 | 78 | public GranteeType getGranteeType() { 79 | return granteeType; 80 | } 81 | 82 | public void setGranteeType(GranteeType granteeType) { 83 | this.granteeType = granteeType; 84 | } 85 | 86 | public String getSchema() { 87 | return schema; 88 | } 89 | 90 | public void setSchema(String schema) { 91 | this.schema = schema; 92 | } 93 | 94 | public String getSpecificname() { 95 | return specificname; 96 | } 97 | 98 | public void setSpecificname(String specificname) { 99 | this.specificname = specificname; 100 | } 101 | 102 | public RoutineType getRoutineType() { 103 | return routineType; 104 | } 105 | 106 | public void setRoutineType(RoutineType routineType) { 107 | this.routineType = routineType; 108 | } 109 | 110 | public GrantType getExecuteAuth() { 111 | return executeAuth; 112 | } 113 | 114 | public void setExecuteAuth(GrantType executeAuth) { 115 | this.executeAuth = executeAuth; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/TabAuth.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | /** 4 | * Content of FROM SYSCAT.TABAUTH 5 | * Authorization Statements on Tables/Views 6 | * 7 | * @author ar 8 | * @since Date: 14.12.2014 9 | */ 10 | public class TabAuth { 11 | 12 | /* 13 | CREATE TABLE TABAUTH 14 | ( 15 | GRANTOR VARCHAR(128) NOT NULL, 16 | GRANTORTYPE CHAR(1) NOT NULL, 17 | GRANTEE VARCHAR(128) NOT NULL, 18 | GRANTEETYPE CHAR(1) NOT NULL, 19 | TABSCHEMA VARCHAR(128) NOT NULL, 20 | TABNAME VARCHAR(128) NOT NULL, 21 | CONTROLAUTH CHAR(1) NOT NULL, 22 | ALTERAUTH CHAR(1) NOT NULL, 23 | DELETEAUTH CHAR(1) NOT NULL, 24 | INDEXAUTH CHAR(1) NOT NULL, 25 | INSERTAUTH CHAR(1) NOT NULL, 26 | REFAUTH CHAR(1) NOT NULL, 27 | SELECTAUTH CHAR(1) NOT NULL, 28 | UPDATEAUTH CHAR(1) NOT NULL 29 | ); 30 | 31 | */ 32 | 33 | private String grantee; 34 | private GranteeType granteeType; 35 | private String tabSchema; 36 | private String tabName; 37 | private GrantType controlAuth; 38 | private GrantType alterAuth; 39 | private GrantType deleteAuth; 40 | private GrantType indexAuth; 41 | private GrantType insertAuth; 42 | private GrantType refAuth; 43 | private GrantType selectAuth; 44 | private GrantType updateAuth; 45 | 46 | 47 | public String getGrantee() { 48 | return grantee; 49 | } 50 | 51 | public void setGrantee(String grantee) { 52 | this.grantee = grantee; 53 | } 54 | 55 | public GranteeType getGranteeType() { 56 | return granteeType; 57 | } 58 | 59 | public void setGranteeType(GranteeType granteeType) { 60 | this.granteeType = granteeType; 61 | } 62 | 63 | public String getTabSchema() { 64 | return tabSchema; 65 | } 66 | 67 | public void setTabSchema(String tabSchema) { 68 | this.tabSchema = tabSchema; 69 | } 70 | 71 | public String getTabName() { 72 | return tabName; 73 | } 74 | 75 | public void setTabName(String tabName) { 76 | this.tabName = tabName; 77 | } 78 | 79 | public GrantType getControlAuth() { 80 | return controlAuth; 81 | } 82 | 83 | public void setControlAuth(GrantType controlAuth) { 84 | this.controlAuth = controlAuth; 85 | } 86 | 87 | public GrantType getAlterAuth() { 88 | return alterAuth; 89 | } 90 | 91 | public void setAlterAuth(GrantType alterAuth) { 92 | this.alterAuth = alterAuth; 93 | } 94 | 95 | public GrantType getDeleteAuth() { 96 | return deleteAuth; 97 | } 98 | 99 | public void setDeleteAuth(GrantType deleteAuth) { 100 | this.deleteAuth = deleteAuth; 101 | } 102 | 103 | public GrantType getIndexAuth() { 104 | return indexAuth; 105 | } 106 | 107 | public void setIndexAuth(GrantType indexAuth) { 108 | this.indexAuth = indexAuth; 109 | } 110 | 111 | public GrantType getInsertAuth() { 112 | return insertAuth; 113 | } 114 | 115 | public void setInsertAuth(GrantType insertAuth) { 116 | this.insertAuth = insertAuth; 117 | } 118 | 119 | public GrantType getRefAuth() { 120 | return refAuth; 121 | } 122 | 123 | public void setRefAuth(GrantType refAuth) { 124 | this.refAuth = refAuth; 125 | } 126 | 127 | public GrantType getSelectAuth() { 128 | return selectAuth; 129 | } 130 | 131 | public void setSelectAuth(GrantType selectAuth) { 132 | this.selectAuth = selectAuth; 133 | } 134 | 135 | public GrantType getUpdateAuth() { 136 | return updateAuth; 137 | } 138 | 139 | public void setUpdateAuth(GrantType updateAuth) { 140 | this.updateAuth = updateAuth; 141 | } 142 | 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/domain/UserObject.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.domain; 2 | 3 | /** 4 | * @author A_Reshetnikov 5 | * @since Date: 17.10.2012 6 | */ 7 | public class UserObject { 8 | 9 | private String name; 10 | private String type; 11 | private String schema; 12 | private String ddl; 13 | private String fileName; 14 | private long opToken; 15 | 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public String getType() { 26 | return type; 27 | } 28 | 29 | public String getSchema() { 30 | return schema; 31 | } 32 | 33 | public void setType(String type) { 34 | this.type = type; 35 | } 36 | 37 | public void setSchema(String schema) { 38 | this.schema = schema; 39 | } 40 | 41 | public String getDdl() { 42 | return ddl; 43 | } 44 | 45 | public void setDdl(String ddl) { 46 | this.ddl = ddl; 47 | } 48 | 49 | public String getFileName() { 50 | return fileName; 51 | } 52 | 53 | public void setFileName(String fileName) { 54 | this.fileName = fileName; 55 | } 56 | 57 | public long getOpToken() { 58 | return opToken; 59 | } 60 | 61 | public void setOpToken(long opToken) { 62 | this.opToken = opToken; 63 | } 64 | 65 | @Override 66 | public String toString() { 67 | return "UserObject{" + 68 | "name='" + name + '\'' + 69 | ", type='" + type + '\'' + 70 | ", schema='" + schema + '\'' + 71 | ", ddl='" + ddl + '\'' + 72 | '}'; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/db2/listener/AfterStepListener.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.listener; 2 | 3 | import com.googlecode.scheme2ddl.db2.dao.UserObjectDao; 4 | import org.springframework.batch.core.ExitStatus; 5 | import org.springframework.batch.core.StepExecution; 6 | import org.springframework.batch.core.StepExecutionListener; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Component; 9 | 10 | /** 11 | * @author ar 12 | * @since Date: 30.05.2015 13 | */ 14 | @Component 15 | public class AfterStepListener implements StepExecutionListener { 16 | 17 | @Autowired 18 | private UserObjectDao userObjectDao; 19 | 20 | 21 | public void beforeStep(StepExecution stepExecution) { 22 | //todo implement beforeStep in AfterStepListener 23 | } 24 | 25 | public ExitStatus afterStep(StepExecution stepExecution) { 26 | Long opToken = stepExecution.getExecutionContext().getLong("opToken"); 27 | if (opToken != null) { 28 | userObjectDao.callCleanTable(opToken); 29 | } 30 | return stepExecution.getExitStatus(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/exception/CannotGetDDLException.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.exception; 2 | 3 | /** 4 | * @author A_Reshetnikov 5 | * @since Date: 16.05.2013 6 | */ 7 | public class CannotGetDDLException extends Exception { 8 | 9 | public CannotGetDDLException() { 10 | super(); 11 | } 12 | 13 | public CannotGetDDLException(Throwable cause) { 14 | super(cause); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/exception/NonSkippableException.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.exception; 2 | 3 | /** 4 | * @author A_Reshetnikov 5 | * @since Date: 03.07.2013 6 | */ 7 | public class NonSkippableException extends Exception { 8 | public NonSkippableException() { 9 | } 10 | 11 | public NonSkippableException(Throwable cause) { 12 | super(cause); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/applicationContext.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/resources/db2-scheme2ddl.config.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 62 | 63 | 64 | 65 | 67 | 68 | 69 | 70 | 71 | 72 | sql 73 | 74 | 75 | 76 | 77 | 79 | 80 | 81 | 82 | COLUMN 83 | PRIMARY_KEY 84 | FOREIGN_KEY 85 | CHECK 86 | UNIQUE 87 | INDEX 88 | OBJECT_GRANTS 89 | 90 | 91 | 92 | 93 | 94 | OBJECT_GRANTS 95 | 96 | 97 | 98 | 99 | OBJECT_GRANTS 100 | 101 | 102 | 103 | 104 | OBJECT_GRANTS 105 | 106 | 107 | 108 | 109 | 110 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | SQLJ 124 | SYSCAT 125 | SYSFUN 126 | SYSIBM 127 | SYSIBMADM 128 | SYSIBMINTERNAL 129 | SYSIBMTS 130 | SYSPROC 131 | SYSPUBLIC 132 | SYSSTAT 133 | SQLTRACE 134 | SYSTOOLS 135 | 136 | 137 | 138 | 139 | true 140 | false 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootCategory=INFO, stdout 2 | 3 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 4 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 5 | log4j.appender.stdout.layout.ConversionPattern=%m%n 6 | 7 | log4j.category.org.springframework=WARN 8 | #log4j.category.org.springframework.jdbc=TRACE 9 | #log4j.category.org.springframework.batch=TRACE 10 | #log4j.category.com.googlecode.scheme2ddl=TRACE -------------------------------------------------------------------------------- /src/test/java/com/googlecode/scheme2ddl/db2/FileNameConstructorTest.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import com.googlecode.scheme2ddl.db2.domain.UserObject; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import java.util.ArrayList; 8 | import java.util.HashMap; 9 | import java.util.List; 10 | import java.util.Map; 11 | 12 | import static org.junit.Assert.assertEquals; 13 | 14 | /** 15 | * @author A_Reshetnikov 16 | * @since Date: 03.05.2013 17 | */ 18 | 19 | public class FileNameConstructorTest { 20 | private FileNameConstructor fileNameConstructor; 21 | private List list; 22 | 23 | @Before 24 | public void setUp() throws Exception { 25 | this.fileNameConstructor = new FileNameConstructor(); 26 | fileNameConstructor.afterPropertiesSet(); 27 | this.list = new ArrayList(); 28 | UserObject userObject = new UserObject(); 29 | userObject.setName("SimpleName"); 30 | userObject.setType("Table"); 31 | userObject.setSchema("SCHEMA_Name"); 32 | list.add(userObject); 33 | 34 | userObject = new UserObject(); 35 | userObject.setName("SYS$_#NAME"); 36 | userObject.setType("REFRESH GROUP"); 37 | userObject.setSchema(""); 38 | list.add(userObject); 39 | 40 | userObject = new UserObject(); 41 | userObject.setName("StraNge_NAME$"); 42 | userObject.setType("Index"); 43 | userObject.setSchema("dummy"); 44 | list.add(userObject); 45 | 46 | userObject = new UserObject(); 47 | userObject.setName("lib01"); 48 | userObject.setType("library"); 49 | userObject.setSchema("dummy"); 50 | list.add(userObject); 51 | 52 | userObject = new UserObject(); 53 | userObject.setName("TYPE_01"); 54 | userObject.setType("TYPE"); 55 | userObject.setSchema("TYPES"); 56 | list.add(userObject); 57 | 58 | userObject = new UserObject(); 59 | userObject.setName("oracle/i18n/data/lx10039.glb"); 60 | userObject.setType("JAVA RESOURCE"); 61 | userObject.setSchema("SYS"); 62 | list.add(userObject); 63 | 64 | 65 | } 66 | 67 | // @org.junit.Test 68 | // public void testMap2FileName() throws Exception { 69 | // 70 | // } 71 | 72 | @Test 73 | public void testDefaultTemplate() throws Exception { 74 | for (UserObject userObject : list) { 75 | String fileName = FileNameConstructor.pluralaze(FileNameConstructor.abbreviate(userObject.getType())).replace(" ", "_") + "/" + userObject.getName() + ".sql"; 76 | fileName = fileName.toLowerCase(); 77 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 78 | } 79 | } 80 | 81 | @Test 82 | public void testKeywordSchema() throws Exception { 83 | String template = FileNameConstructor.kw_schema_lower + "/" + FileNameConstructor.kw_schema_UPPER; 84 | fileNameConstructor.setTemplate(template); 85 | fileNameConstructor.afterPropertiesSet(); 86 | for (UserObject userObject : list) { 87 | String fileName = userObject.getSchema().toLowerCase() + "/" + userObject.getSchema().toUpperCase(); 88 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 89 | } 90 | } 91 | 92 | @Test 93 | public void testKeywordObjectName() throws Exception { 94 | String template = FileNameConstructor.kw_objectname_lower + "/" + FileNameConstructor.kw_objectname_UPPER; 95 | fileNameConstructor.setTemplate(template); 96 | fileNameConstructor.afterPropertiesSet(); 97 | for (UserObject userObject : list) { 98 | String fileName = userObject.getName().toLowerCase() + "/" + userObject.getName().toUpperCase(); 99 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 100 | } 101 | } 102 | 103 | @Test 104 | public void testKeywordExtension() throws Exception { 105 | String template = FileNameConstructor.kw_extension_lower + "/" + FileNameConstructor.kw_extension_UPPER; 106 | fileNameConstructor.setTemplate(template); 107 | fileNameConstructor.afterPropertiesSet(); 108 | for (UserObject userObject : list) { 109 | String fileName = "sql" + "/" + "sql".toUpperCase(); 110 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 111 | } 112 | } 113 | 114 | @Test 115 | public void testTemplateWithTypeMix() throws Exception { 116 | String template = FileNameConstructor.kw_type_lower + "/" + FileNameConstructor.kw_type_lower + 117 | FileNameConstructor.kw_type_UPPER + "/" + FileNameConstructor.kw_types_plural_lower + "//" + 118 | FileNameConstructor.kw_types_plural_UPPER + "/" + FileNameConstructor.kw_types_plural_UPPER + ".TyPEs_PLURAL"; 119 | fileNameConstructor.setTemplate(template); 120 | fileNameConstructor.afterPropertiesSet(); 121 | for (UserObject userObject : list) { 122 | String type = FileNameConstructor.abbreviate(userObject.getType().toLowerCase()).replace(" ", "_"); 123 | String typePlural = FileNameConstructor.pluralaze(FileNameConstructor.abbreviate(userObject.getType())).replace(" ", "_"); 124 | String fileName = type.toLowerCase() + "/" + type.toLowerCase() + 125 | type.toUpperCase() + "/" + typePlural.toLowerCase() + "//" + 126 | typePlural.toUpperCase() + "/" + typePlural.toUpperCase() + ".TyPEs_PLURAL"; 127 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 128 | } 129 | } 130 | 131 | @Test 132 | public void testApplyExtensionRules() { 133 | Map extensionMap = new HashMap(); 134 | extensionMap.put("DEFAULT", "sql"); 135 | extensionMap.put("VIEW", "vw"); 136 | fileNameConstructor.setExtensionMap(extensionMap); 137 | UserObject userObject = new UserObject(); 138 | userObject.setName("view01"); 139 | userObject.setType("view"); 140 | userObject.setSchema(""); 141 | String fileName = FileNameConstructor.pluralaze(FileNameConstructor.abbreviate(userObject.getType())).replace(" ", "_") + "/" + userObject.getName() + ".vw"; 142 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject)); 143 | } 144 | 145 | @Test(expected=IllegalStateException.class) 146 | public void testExtensionRulesWrongConfig() { 147 | Map extensionMap = new HashMap(); 148 | extensionMap.put("VIEW", "vw"); 149 | fileNameConstructor.setExtensionMap(extensionMap); 150 | UserObject userObject = new UserObject(); 151 | userObject.setName(""); 152 | userObject.setType("strange type"); 153 | userObject.setSchema(""); 154 | fileNameConstructor.map2FileName(userObject); 155 | } 156 | 157 | 158 | } 159 | -------------------------------------------------------------------------------- /src/test/java/com/googlecode/scheme2ddl/db2/MainTestDb2.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class MainTestDb2 { 8 | 9 | @Test 10 | public void testExtractPortFromDbUrl (){ 11 | String url = "user/pass@serverName:123:DbName"; 12 | int port = Main.extractPortFromDbUrl(url); 13 | assertEquals(123, port); 14 | } 15 | 16 | 17 | 18 | 19 | } -------------------------------------------------------------------------------- /src/test/java/com/googlecode/scheme2ddl/db2/filter/IsAlterTableAutoGeneratedPredicateTest.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.db2.filter; 2 | 3 | import com.googlecode.scheme2ddl.db2.IsAlterTableAutoGeneratedPredicate; 4 | import com.googlecode.scheme2ddl.db2.domain.Db2LookInfo; 5 | import org.junit.Test; 6 | 7 | import static org.junit.Assert.assertFalse; 8 | import static org.junit.Assert.assertTrue; 9 | 10 | /** 11 | * @author ar 12 | * @since Date: 05.04.2015 13 | */ 14 | public class IsAlterTableAutoGeneratedPredicateTest { 15 | 16 | 17 | IsAlterTableAutoGeneratedPredicate predicate = new IsAlterTableAutoGeneratedPredicate(); 18 | 19 | @Test 20 | public void testAlterTableAutoIncrement() throws Exception { 21 | Db2LookInfo db2LookInfo = new Db2LookInfo(); 22 | db2LookInfo.setObjName("A"); 23 | db2LookInfo.setObjType("TABLE"); 24 | db2LookInfo.setSqlOperation("ALTER"); 25 | db2LookInfo.setSqlStmt("ALTER TABLE \"MY \".\"STUDENT\" ALTER COLUMN \"SID_ID\" RESTART WITH 100 "); 26 | assertFalse(predicate.evaluate(db2LookInfo)); 27 | 28 | } 29 | 30 | @Test 31 | public void testAlterTableNotAutoincrement() throws Exception { 32 | Db2LookInfo db2LookInfo = new Db2LookInfo(); 33 | db2LookInfo.setObjName("A"); 34 | db2LookInfo.setObjType("TABLE"); 35 | db2LookInfo.setSqlOperation("ALTER"); 36 | db2LookInfo.setSqlStmt("ALTER TABLE \"MY \".\"ORG_TEMP\" \n" + 37 | "\tADD CONSTRAINT \"DEPTNAME\" CHECK \n" + 38 | "\t\t(LENGTH(RTRIM(DEPTNAME)) >0)\n" + 39 | "\tENFORCED\n" + 40 | "\tENABLE QUERY OPTIMIZATION ;"); 41 | assertTrue(predicate.evaluate(db2LookInfo)); 42 | 43 | } 44 | } --------------------------------------------------------------------------------