());
50 | }
51 |
52 | @After("execution(* org.springframework.batch.core.launch.JobLauncher.run(..)) &&" +
53 | " args(job, jobParameters)")
54 | public void printStatistic(Job job, JobParameters jobParameters) {
55 | String schemaName = jobParameters.getString("schemaName");
56 | prettyPrint(schemaName);
57 | // System.out.println("schemaName = " + schemaName);
58 | // System.out.println("listExludedByConfig = " + listExludedByConfig); //todo pretty print
59 | // System.out.println("listSkippedBySQLError = " + listSkippedBySQLError); //todo pretty print
60 | }
61 |
62 | /**
63 | * report something like this:
64 | *
65 | * -------------------------------------------------------
66 | * R E P O R T S K I P P E D O B J E C T S
67 | * -------------------------------------------------------
68 | * | skip rule | object type | count |
69 | * -------------------------------------------------------
70 | * | config | INDEX | 2 |
71 | * | sql error | PUBLIC DATABASE LINK | 4 |
72 | *
73 | *
74 | * @param schemaName
75 | * @param listExludedByConfig
76 | * @param listSkippedBySQLError
77 | */
78 | public void prettyPrint(String schemaName) {
79 | String lSep = System.getProperty("line.separator");
80 | StringBuilder sb = new StringBuilder();
81 | sb.append(lSep);
82 | sb.append("-------------------------------------------------------");
83 | sb.append(lSep);
84 | sb.append(" R E P O R T S K I P P E D O B J E C T S ");
85 | sb.append(lSep);
86 | sb.append("-------------------------------------------------------");
87 |
88 | if (listExludedByConfig.size() + listSkippedBySQLError.size() == 0) {
89 | sb.append(" No skipped objects ");
90 | sb.append(lSep);
91 | return;
92 | }
93 |
94 | sb.append(lSep);
95 | sb.append("| skip rule | object type | count |");
96 | sb.append(lSep);
97 | sb.append("-------------------------------------------------------");
98 | sb.append(lSep);
99 |
100 | prettyPrintList(sb, " config ", listExludedByConfig);
101 | prettyPrintList(sb, "sql error", listSkippedBySQLError);
102 |
103 | System.out.println(sb.toString());
104 |
105 | }
106 |
107 | private void prettyPrintList(StringBuilder sb, String ruleName, List listExludedByConfig) {
108 | String lSep = System.getProperty("line.separator");
109 | Map groupByType = groupByType(listExludedByConfig);
110 | for (String type : groupByType.keySet()) {
111 | Formatter formatter = new Formatter();
112 | sb.append(formatter.format("| %s | %-24s | %-6s |", ruleName, type, groupByType.get(type)).toString());
113 | sb.append(lSep);
114 | }
115 | }
116 |
117 | private Map groupByType(List list) {
118 | Map map = new HashMap();
119 | for (UserObject userObject : list) {
120 |
121 | if (map.containsKey(userObject.getType())) {
122 | map.put(userObject.getType(), map.get(userObject.getType()) + 1);
123 | } else {
124 | map.put(userObject.getType(), 1);
125 | }
126 | }
127 | return map;
128 | }
129 |
130 | }
131 |
--------------------------------------------------------------------------------
/src/main/java/com/googlecode/scheme2ddl/dao/ConnectionDao.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.dao;
2 |
3 | /**
4 | * Check some properties of connection
5 | *
6 | * @author A_Reshetnikov
7 | * @since Date: 23.07.2013
8 | */
9 | public interface ConnectionDao {
10 |
11 | boolean isConnectionAvailable();
12 |
13 | boolean hasSelectCatalogRole();
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/googlecode/scheme2ddl/dao/ConnectionDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.dao;
2 |
3 | import org.springframework.dao.DataAccessException;
4 | import org.springframework.jdbc.core.support.JdbcDaoSupport;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @author A_Reshetnikov
10 | * @since Date: 23.07.2013
11 | */
12 | public class ConnectionDaoImpl extends JdbcDaoSupport implements ConnectionDao {
13 |
14 | public boolean isConnectionAvailable() {
15 | try {
16 | getJdbcTemplate().queryForObject("select 1 from dual", Integer.class) ;
17 | } catch (DataAccessException e) {
18 | return false;
19 | }
20 | return true;
21 | }
22 |
23 | public boolean hasSelectCatalogRole() {
24 | List list = getJdbcTemplate().queryForList("select 1 from session_roles where role = 'SELECT_CATALOG_ROLE'");
25 | return (list.size() == 1);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDao.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.dao;
2 |
3 | import com.googlecode.scheme2ddl.domain.UserObject;
4 |
5 | import java.util.Collection;
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 findPublicDbLinks();
17 |
18 | List findDmbsJobs();
19 |
20 | List findConstaints();
21 |
22 | String findPrimaryDDL(String type, String name);
23 |
24 | String findDependentDLLByTypeName(String type, String name);
25 |
26 | String findDDLInPublicScheme(String type, String name);
27 |
28 | String findDbmsJobDDL(String name);
29 |
30 | String findRefGroupDDL(String type, String name);
31 |
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImpl.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.dao;
2 |
3 | import com.googlecode.scheme2ddl.domain.UserObject;
4 | import org.apache.commons.logging.Log;
5 | import org.apache.commons.logging.LogFactory;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.dao.DataAccessException;
8 | import org.springframework.jdbc.BadSqlGrammarException;
9 | import org.springframework.jdbc.core.CallableStatementCallback;
10 | import org.springframework.jdbc.core.ConnectionCallback;
11 | import org.springframework.jdbc.core.RowMapper;
12 | import org.springframework.jdbc.core.support.JdbcDaoSupport;
13 |
14 | import java.sql.*;
15 | import java.util.ArrayList;
16 | import java.util.List;
17 | import java.util.Map;
18 |
19 | import static com.googlecode.scheme2ddl.TypeNamesUtil.map2TypeForDBMS;
20 |
21 | /**
22 | * @author A_Reshetnikov
23 | * @since Date: 17.10.2012
24 | */
25 | public class UserObjectDaoImpl extends JdbcDaoSupport implements UserObjectDao {
26 |
27 | private static final Log log = LogFactory.getLog(UserObjectDaoImpl.class);
28 | private Map transformParams;
29 | @Value("#{jobParameters['schemaName']}")
30 | private String schemaName;
31 | @Value("#{jobParameters['launchedByDBA']}")
32 | private boolean isLaunchedByDBA = false;
33 | @Value("#{jobParameters['objectFilter']}")
34 | private String objectFilter;
35 | @Value("#{jobParameters['typeFilter']}")
36 | private String typeFilter;
37 | @Value("#{jobParameters['typeFilterMode']}")
38 | private String typeFilterMode = "include";
39 |
40 | public List findListForProccessing() {
41 | String sql;
42 | if (isLaunchedByDBA) {
43 | sql = "select t.object_name, object_type " +
44 | " from dba_objects t " +
45 | " where t.generated = 'N' " +
46 | " and lower(t.object_name) like '" + objectFilter + "' " +
47 | " and t.owner = '" + schemaName + "' " +
48 | " and not exists (select 1 " +
49 | " from user_nested_tables unt" +
50 | " where t.object_name = unt.table_name)";
51 | if (!typeFilter.isEmpty()) { //type filter is filled
52 | sql += " and upper(t.object_type) ";
53 |
54 | if (typeFilterMode.equals("exclude")) //exclude types
55 | sql += " NOT ";
56 |
57 | sql += " IN (" + typeFilter + ") ";
58 | }
59 | if (isTypeAllowed("'REFRESH GROUP'")) {
60 | sql += " UNION ALL " +
61 | " select rname as object_name, 'REFRESH_GROUP' as object_type " +
62 | " from dba_refresh a " +
63 | " where a.rowner = '" + schemaName + "' " +
64 | " and lower(a.rname) like '" + objectFilter + "' ";
65 | }
66 | } else {
67 | sql = "select t.object_name, object_type " +
68 | " from user_objects t " +
69 | " where t.generated = 'N' " +
70 | " and lower(t.object_name) like '" + objectFilter + "' " +
71 | " and not exists (select 1 " +
72 | " from user_nested_tables unt" +
73 | " where t.object_name = unt.table_name)";
74 | if (!typeFilter.isEmpty()) {
75 | sql += " and upper(t.object_type) ";
76 |
77 | if (typeFilterMode.equals("exclude")) //exclude types
78 | sql += " NOT ";
79 |
80 | sql += " IN (" + typeFilter + ") ";
81 | }
82 | if (isTypeAllowed("'REFRESH GROUP'")) {
83 | sql += " UNION ALL " +
84 | " select rname as object_name, 'REFRESH_GROUP' as object_type " +
85 | " from user_refresh " +
86 | " where lower(rname) like '" + objectFilter + "' ";
87 | }
88 | }
89 | return getJdbcTemplate().query(sql, new UserObjectRowMapper());
90 | }
91 |
92 | public List findPublicDbLinks() {
93 | List list = new ArrayList();
94 | try {
95 | list = getJdbcTemplate().query(
96 | "select db_link as object_name, 'PUBLIC DATABASE LINK' as object_type " +
97 | "from DBA_DB_LINKS " +
98 | "where owner='PUBLIC'" +
99 | " and lower(db_link) like '" + objectFilter + "' ",
100 | new UserObjectRowMapper());
101 | } catch (BadSqlGrammarException sqlGrammarException) {
102 | if (sqlGrammarException.getSQLException().getErrorCode() == 942) {
103 | String userName = null;
104 | try {
105 | userName = getDataSource().getConnection().getMetaData().getUserName();
106 | } catch (SQLException e) {
107 | }
108 | log.warn("WARNING: processing of 'PUBLIC DATABASE LINK' will be skipped because " + userName + " no access to view it" +
109 | "\n Possible decisions:\n\n" +
110 | " 1) Exclude processPublicDbLinks option in advanced config to disable this warning\n " +
111 | " \n" +
112 | " \n" +
113 | " ...\n" +
114 | " \n" +
115 | "\n" +
116 | " 2) Or try give access to user " + userName + " with sql command\n " +
117 | " GRANT SELECT_CATALOG_ROLE TO " + userName + "; \n\n");
118 | }
119 | return list;
120 | }
121 |
122 | for (UserObject userObject : list) {
123 | userObject.setSchema("PUBLIC");
124 | }
125 | return list;
126 | }
127 |
128 | public List findDmbsJobs() {
129 | String tableName = isLaunchedByDBA ? "dba_jobs" : "user_jobs";
130 | String whereClause = isLaunchedByDBA ? "schema_user = '" + schemaName + "'" : "schema_user != 'SYSMAN'";
131 | String sql = "select job || '' as object_name, 'DBMS JOB' as object_type " +
132 | "from " + tableName + " where " + whereClause + " and to_char(job) like '" + objectFilter + "' ";
133 | // a little bit ugly, but this prevents an output from jobs if dbms job is not in typeFilter
134 | if (!isTypeAllowed("'DBMS JOB'")) {
135 | sql += " and 1 = 2 ";
136 | }
137 | return getJdbcTemplate().query(sql, new UserObjectRowMapper());
138 | }
139 |
140 | public List findConstaints() {
141 | String sql;
142 | String prevent_constraint = new String("");
143 | String prevent_refconstraint = new String("");
144 |
145 | if (!isTypeAllowed("'CONSTRAINT'")) {
146 | prevent_constraint = " and 1 = 2 ";
147 | }
148 | if (!isTypeAllowed("'REF_CONSTRAINT'")) {
149 | prevent_refconstraint = " and 1 = 2 ";
150 | }
151 | if (isLaunchedByDBA)
152 | sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" +
153 | " from all_constraints " +
154 | " where constraint_type != 'R' and owner = '" + schemaName + "'" +
155 | " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint +
156 | " UNION ALL " +
157 | " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" +
158 | " from all_constraints " +
159 | " where constraint_type = 'R' and owner = '" + schemaName + "'" +
160 | " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint;
161 | else
162 | sql = " select constraint_name as object_name, 'CONSTRAINT' as object_type" +
163 | " from user_constraints where constraint_type != 'R'" +
164 | " and lower(constraint_name) like '" + objectFilter + "' " + prevent_constraint +
165 | " UNION ALL " +
166 | " select constraint_name as object_name, 'REF_CONSTRAINT' as object_type" +
167 | " from user_constraints where constraint_type = 'R'" +
168 | " and lower(constraint_name) like '" + objectFilter + "' " + prevent_refconstraint;
169 |
170 | return getJdbcTemplate().query(sql, new UserObjectRowMapper());
171 | }
172 |
173 | public String findPrimaryDDL(final String type, final String name) {
174 | if (isLaunchedByDBA)
175 | return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, schemaName);
176 | else
177 | return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?) from dual", type, name, null);
178 | }
179 |
180 | private String executeDbmsMetadataGetDdl(final String query, final String type, final String name, final String schema) {
181 | return (String) getJdbcTemplate().execute(new ConnectionCallback() {
182 | public String doInConnection(Connection connection) throws SQLException, DataAccessException {
183 | applyTransformParameters(connection);
184 | PreparedStatement ps = connection.prepareStatement(query);
185 | ps.setString(1, type);
186 | ps.setString(2, name);
187 | if (schema != null) {
188 | ps.setString(3, schema);
189 | }
190 | ResultSet rs = null;
191 | try {
192 | rs = ps.executeQuery();
193 | } catch (SQLException e) {
194 | // log.trace(String.format("Error during select dbms_metadata.get_ddl('%s', '%s') from dual\n" +
195 | // "Try to exclude type '%s' in advanced config excludes section\n", type, name, map2TypeForConfig(type)));
196 | // log.trace(String.format("Sample:\n\n" +
197 | // " \n" +
198 | // "...\n" +
199 | // " \n" +
200 | // " \n" +
201 | // " %s\n" +
202 | // " \n" +
203 | // " \n" +
204 | // "...\n" +
205 | // "", map2TypeForConfig(type), name));
206 | throw e;
207 | }
208 | try {
209 | if (rs.next()) {
210 | return rs.getString(1);
211 | }
212 | } finally {
213 | rs.close();
214 | }
215 | return null;
216 | }
217 | });
218 | }
219 |
220 | public String findDependentDLLByTypeName(final String type, final String name) {
221 |
222 | return (String) getJdbcTemplate().execute(new ConnectionCallback() {
223 | final String query = "select dbms_metadata.get_dependent_ddl(?, ?, ?) from dual";
224 |
225 | public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
226 | applyTransformParameters(connection);
227 | PreparedStatement ps = connection.prepareStatement(query);
228 | ps.setString(1, type);
229 | ps.setString(2, name);
230 | ps.setString(3, isLaunchedByDBA ? schemaName : null);
231 | ResultSet rs;
232 | try {
233 | rs = ps.executeQuery();
234 | } catch (SQLException e) {
235 | log.trace(String.format("Error during select dbms_metadata.get_dependent_ddl(%s, %s) from dual", type, name));
236 | return "";
237 | }
238 | try {
239 | if (rs.next()) {
240 | return rs.getString(1);
241 | }
242 | } finally {
243 | rs.close();
244 | }
245 | return null;
246 | }
247 | });
248 | }
249 |
250 | public String findDDLInPublicScheme(String type, String name) {
251 | return executeDbmsMetadataGetDdl("select dbms_metadata.get_ddl(?, ?, ?) from dual", type, name, "PUBLIC");
252 | }
253 |
254 | public String findDbmsJobDDL(String name) {
255 | String sql;
256 | if (isLaunchedByDBA)
257 | // The 'dbms_job.user_export' function does not work with sys/dba users (can't find users jobs). :(
258 | sql = "DECLARE\n" +
259 | " callstr VARCHAR2(4096);\n" +
260 | "BEGIN\n" +
261 | " sys.dbms_ijob.full_export(" + name + ", callstr);\n" +
262 | ":done := callstr; END;";
263 | else
264 | sql = "DECLARE\n" +
265 | " callstr VARCHAR2(4096);\n" +
266 | "BEGIN\n" +
267 | " dbms_job.user_export(" + name + ", callstr);\n" +
268 | ":done := callstr; " +
269 | "END;";
270 |
271 | return (String) getJdbcTemplate().execute(sql, new CallableStatementCallbackImpl());
272 | }
273 |
274 | public String findRefGroupDDL(String type, final String name) {
275 | if (isLaunchedByDBA)
276 | return findPrimaryDDL(map2TypeForDBMS(type), name);
277 | else
278 | return (String) getJdbcTemplate().execute(new ConnectionCallback() {
279 | final String query =
280 | "SELECT 'begin'"
281 | + "|| CHR (13) || CHR (10)"
282 | + "|| '-- dbms_refresh.destroy(name => '''"
283 | + "|| rname"
284 | + "|| ''');'"
285 | + "|| CHR (13) || CHR (10)"
286 | + "|| ' dbms_refresh.make (name => '''"
287 | + "|| rname"
288 | + "|| ''', '"
289 | + "|| CHR (13) || CHR (10)"
290 | + "|| ' list => '''"
291 | + "|| listagg(name, ',') within group (order by name)"
292 | + "|| ''','"
293 | + "|| CHR (13) || CHR (10)"
294 | + "|| ' next_date => '"
295 | + "|| CASE WHEN MAX(next_date) IS NULL THEN 'NULL' ELSE 'to_date(''' || TO_CHAR (MAX (next_date), 'DD.MM.YYYY HH24:MI:SS') || ''', ''DD.MM.YYYY HH24:MI:SS'')' END"
296 | + "|| ', '"
297 | + "|| CHR (13) || CHR (10)"
298 | + "|| ' interval => '"
299 | + "|| CASE WHEN MAX(interval) IS NULL THEN 'NULL' ELSE '''' || MAX (REPLACE(interval, '''', '''''')) || '''' END "
300 | + "|| ');'"
301 | + "|| CHR (13) || CHR (10)"
302 | + "|| ' commit;'"
303 | + "|| CHR (13) || CHR (10)"
304 | + "|| 'end;'"
305 | + "|| CHR (13) || CHR (10)"
306 | + "|| '/'"
307 | + "|| CHR (13) || CHR (10)"
308 | + " FROM user_refresh_children "
309 | + " WHERE rname = UPPER ('"+name+"')"
310 | + " GROUP BY rname";
311 |
312 | public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
313 | //todo sl4j logger.debug( "query: \n {} ", query);
314 | applyTransformParameters(connection);
315 | PreparedStatement ps = connection.prepareStatement(query);
316 |
317 | ResultSet rs;
318 |
319 | try {
320 | rs = ps.executeQuery();
321 | } catch (SQLException e) {
322 | log.trace(String.format("Error during select ddl for refresh group (%s)", name));
323 | return "";
324 | }
325 | try {
326 | if (rs.next()) {
327 | return rs.getString(1);
328 | }
329 | } finally {
330 | rs.close();
331 | }
332 | return null;
333 | }
334 | });
335 | }
336 |
337 | public void applyTransformParameters(Connection connection) throws SQLException {
338 | for (String parameterName : transformParams.keySet()) {
339 | connection.setAutoCommit(false);
340 | // setBoolean doesn't convert java boolean to pl/sql boolean, so used such query building
341 | String sql = String.format(
342 | "BEGIN " +
343 | " dbms_metadata.set_transform_param(DBMS_METADATA.SESSION_TRANSFORM,'%s',%s);" +
344 | " END;", parameterName, transformParams.get(parameterName));
345 | PreparedStatement ps = connection.prepareCall(sql);
346 | // ps.setString(1, parameterName);
347 | // ps.setBoolean(2, transformParams.get(parameterName) ); //In general this doesn't work
348 | ps.execute();
349 | }
350 | }
351 |
352 | public void setTransformParams(Map transformParams) {
353 | this.transformParams = transformParams;
354 | }
355 |
356 | public void setSchemaName(String schemaName) {
357 | this.schemaName = schemaName;
358 | }
359 |
360 | public void setLaunchedByDBA(boolean launchedByDBA) {
361 | this.isLaunchedByDBA = launchedByDBA;
362 | }
363 |
364 | private class CallableStatementCallbackImpl implements CallableStatementCallback {
365 | public Object doInCallableStatement(CallableStatement callableStatement) throws SQLException, DataAccessException {
366 | callableStatement.registerOutParameter(1, java.sql.Types.VARCHAR);
367 | callableStatement.executeUpdate();
368 | return callableStatement.getString(1);
369 | }
370 | }
371 |
372 | private class UserObjectRowMapper implements RowMapper {
373 | public UserObject mapRow(ResultSet rs, int rowNum) throws SQLException {
374 | UserObject userObject = new UserObject();
375 | userObject.setName(rs.getString("object_name"));
376 | userObject.setType(rs.getString("object_type"));
377 | userObject.setSchema(schemaName == null ? "" : schemaName);
378 | return userObject;
379 | }
380 | }
381 |
382 | private boolean isTypeAllowed (String typeName) {
383 | if (typeFilter.isEmpty()) // empty type filter means all types are allowed
384 | return true;
385 | if (typeFilterMode.equals("include") && typeFilter.contains(typeName)) // given typeName is in the typeFilter
386 | return true;
387 | if (typeFilterMode.equals("exclude") && !typeFilter.contains(typeName)) // given typeName is not in the typeFilter
388 | return true;
389 |
390 | return false;
391 | }
392 | }
393 |
--------------------------------------------------------------------------------
/src/main/java/com/googlecode/scheme2ddl/domain/UserObject.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.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 |
15 |
16 | public String getName() {
17 | return name;
18 | }
19 |
20 | public void setName(String name) {
21 | this.name = name;
22 | }
23 |
24 | public String getType() {
25 | return type;
26 | }
27 |
28 | public String getSchema() {
29 | return schema;
30 | }
31 |
32 | public void setType(String type) {
33 | this.type = type;
34 | }
35 |
36 | public void setSchema(String schema) {
37 | this.schema = schema;
38 | }
39 |
40 | public String getDdl() {
41 | return ddl;
42 | }
43 |
44 | public void setDdl(String ddl) {
45 | this.ddl = ddl;
46 | }
47 |
48 | public String getFileName() {
49 | return fileName;
50 | }
51 |
52 | public void setFileName(String fileName) {
53 | this.fileName = fileName;
54 | }
55 |
56 |
57 | @Override
58 | public String toString() {
59 | return "UserObject{" +
60 | "name='" + name + '\'' +
61 | ", type='" + type + '\'' +
62 | ", schema='" + schema + '\'' +
63 | ", ddl='" + ddl + '\'' +
64 | '}';
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/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(Throwable cause) {
10 | super(cause);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/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 |
9 | public NonSkippableException(Throwable cause) {
10 | super(cause);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/resources/applicationContext.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 |
37 |
38 |
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 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | %msg%n
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/resources/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 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
90 |
92 |
94 |
101 |
102 |
103 |
104 | sql
105 |
106 |
107 |
108 |
109 |
110 |
111 | .sql
112 |
113 |
114 | .prc
115 |
116 |
117 | .fnc
118 |
119 |
120 | .trg
121 |
122 |
123 | .vw
124 |
125 |
126 | .pks
127 |
128 |
129 | -body.pkb
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 | sql
139 |
140 |
141 | prc
142 |
143 |
144 | fnc
145 |
146 |
147 | trg
148 |
149 |
150 | vw
151 |
152 |
153 | pks
154 |
155 |
156 | pkb
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 | sql
165 |
166 |
167 |
168 |
169 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 | COMMENT
205 | INDEX
206 | OBJECT_GRANT
207 | TRIGGER
208 |
209 |
210 |
211 |
212 | COMMENT
213 | OBJECT_GRANT
214 |
215 |
216 |
217 |
218 | COMMENT
219 | INDEX
220 | MATERIALIZED_VIEW_LOG
221 | OBJECT_GRANT
222 |
223 |
224 |
225 |
226 | OBJECT_GRANT
227 |
228 |
229 |
230 |
231 | OBJECT_GRANT
232 |
233 |
234 |
235 |
236 | OBJECT_GRANT
237 |
238 |
239 |
240 |
241 | OBJECT_GRANT
242 |
243 |
244 |
245 |
246 | OBJECT_GRANT
247 |
248 |
249 |
250 |
251 |
254 |
255 |
256 |
257 | *_*_temp_*
258 |
259 |
260 |
268 |
269 | *
270 | *
271 | *
272 |
273 |
274 |
275 | *
276 | *
277 |
278 |
279 |
280 | SYSTP*
281 | *==
282 |
283 | SYS_PLSQL_*
284 |
285 |
286 |
287 |
288 |
289 |
290 |
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/BaseIT.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import org.apache.commons.io.FileUtils;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.jdbc.CannotGetJdbcConnectionException;
8 | import org.springframework.jdbc.core.JdbcTemplate;
9 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
10 | import org.springframework.test.util.ReflectionTestUtils;
11 | import org.testng.SkipException;
12 | import org.testng.annotations.AfterMethod;
13 | import org.testng.annotations.BeforeClass;
14 | import org.testng.annotations.BeforeMethod;
15 |
16 | import java.io.ByteArrayOutputStream;
17 | import java.io.File;
18 | import java.io.IOException;
19 | import java.io.PrintStream;
20 | import java.util.UUID;
21 |
22 | import static org.testng.Assert.assertEquals;
23 | import static org.testng.Assert.assertTrue;
24 |
25 | /**
26 | * Created by Anton Reshetnikov on 12 Dec 2016.
27 | */
28 | @SpringBootTest(classes = ConfigurationIT.class, properties = "test-default.properties")
29 | public abstract class BaseIT extends AbstractTestNGSpringContextTests {
30 |
31 | @Value("${hrUrl}")
32 | protected String url;
33 |
34 | @Value("${dbaUrl}")
35 | protected String dbaUrl;
36 |
37 | @Value("${dbaAsSysdbaUrl}")
38 | protected String dbaAsSysdbaUrl;
39 |
40 |
41 | @Autowired
42 | protected JdbcTemplate dbaJdbcTemplate;
43 |
44 | protected final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
45 | protected final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
46 |
47 | protected final PrintStream outOriginal = System.out;
48 | protected final PrintStream errorOriginal = System.err;
49 |
50 |
51 | protected File tempOutput;
52 |
53 |
54 | @BeforeClass
55 | public void setUp() {
56 | try {
57 | dbaJdbcTemplate.execute("ALTER USER HR ACCOUNT UNLOCK IDENTIFIED BY pass");
58 | }
59 | catch (CannotGetJdbcConnectionException e){
60 | logger.warn("Ignore all test due", e);
61 | throw new SkipException("Ignore all test due " + e.getMessage());
62 | }
63 |
64 | }
65 |
66 | @BeforeMethod
67 | public void resetDefaultsForStaticFields() throws Exception {
68 | ReflectionTestUtils.setField(Main.class, "justPrintUsage", false);
69 | ReflectionTestUtils.setField(Main.class, "justPrintVersion", false);
70 | ReflectionTestUtils.setField(Main.class, "justTestConnection", false);
71 | ReflectionTestUtils.setField(Main.class, "dbUrl", null);
72 | ReflectionTestUtils.setField(Main.class, "objectFilter", "%");
73 | ReflectionTestUtils.setField(Main.class, "typeFilter", "");
74 | ReflectionTestUtils.setField(Main.class, "typeFilterMode", "include");
75 | ReflectionTestUtils.setField(Main.class, "isLaunchedByDBA", false);
76 | ReflectionTestUtils.setField(Main.class, "schemas", null);
77 | ReflectionTestUtils.setField(Main.class, "schemaList", null);
78 | ReflectionTestUtils.setField(Main.class, "replaceSequenceValues", false);
79 | ReflectionTestUtils.setField(Main.class, "customConfigLocation", null);
80 | ReflectionTestUtils.setField(Main.class, "parallelCount", 4);
81 | ReflectionTestUtils.setField(Main.class, "outputPath", null);
82 | }
83 |
84 | @BeforeMethod
85 | public void setUpStreams() {
86 | System.setOut(new PrintStream(outContent));
87 | System.setErr(new PrintStream(errContent));
88 | }
89 |
90 | @AfterMethod
91 | public void cleanUpStreams() throws IOException {
92 | System.setOut(outOriginal);
93 | System.setErr(errorOriginal);
94 | outContent.reset();
95 | errContent.reset();
96 | }
97 |
98 | @BeforeMethod
99 | public void setUpTempOutputDir(){
100 | tempOutput = FileUtils.getFile(FileUtils.getTempDirectoryPath(),
101 | "scheme2ddl-test-tmp-output",
102 | UUID.randomUUID().toString().substring(0,8));
103 | }
104 |
105 | @AfterMethod
106 | public void cleanUpTempOutput() throws IOException {
107 | FileUtils.deleteDirectory(tempOutput);
108 | }
109 |
110 | protected static void assertEqualsFileContent(String path, String content) throws IOException {
111 | File file = new File(path);
112 | assertTrue(file.exists(), "file doesn't exists " + file );
113 | String fileContent = FileUtils.readFileToString(file, "UTF-8");
114 | assertEquals(fileContent.trim().replace("\r", ""), content.replace("\r", ""));
115 |
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/ConfigurationIT.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import oracle.jdbc.driver.OracleDriver;
4 | import oracle.jdbc.pool.OracleDataSource;
5 | import oracle.jdbc.pool.OracleDataSourceFactory;
6 | import org.springframework.beans.factory.annotation.Value;
7 | import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
8 | import org.springframework.boot.context.properties.ConfigurationProperties;
9 | import org.springframework.context.annotation.*;
10 | import org.springframework.jdbc.core.JdbcTemplate;
11 | import org.springframework.test.context.TestPropertySource;
12 |
13 | import javax.sql.DataSource;
14 | import java.sql.SQLException;
15 |
16 | /**
17 | * @author A_Reshetnikov
18 | * @since Date: 18.09.2016
19 | */
20 | @Configuration
21 | @PropertySource("classpath:test-${spring.profiles.active:default}.properties")
22 | public class ConfigurationIT {
23 |
24 |
25 | @Value("${dba.datasource.url}")
26 | private String url;
27 | @Value("${dba.datasource.username}")
28 | private String username;
29 | @Value("${dba.datasource.password}")
30 | private String password;
31 |
32 |
33 | @Bean
34 | public DataSource dbaDataSource() throws SQLException {
35 | OracleDataSource dataSource = new OracleDataSource();
36 | dataSource.setURL(url);
37 | dataSource.setUser(username);
38 | dataSource.setPassword(password);
39 | return dataSource;
40 | }
41 |
42 | @Bean
43 | public JdbcTemplate dbaJdbcTemplate(DataSource dataSource){
44 | return new JdbcTemplate(dataSource);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/DDLFormatterTest.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 |
4 | import org.testng.annotations.Test;
5 |
6 | import static org.testng.Assert.assertNotEquals;
7 | import static org.testng.AssertJUnit.assertEquals;
8 |
9 |
10 | /**
11 | * @author ar
12 | * @since Date: 18.04.2015
13 | */
14 | public class DDLFormatterTest {
15 |
16 | private DDLFormatter ddlFormatter = new DDLFormatter();
17 |
18 | @Test
19 | public void testReplaceActualSequenceValueWithOne() throws Exception {
20 |
21 | String s = "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n";
22 | String res = ddlFormatter.replaceActualSequenceValueWithOne(s);
23 | assertEquals(
24 | "CREATE SEQUENCE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n" +
25 | "\r\n" +
26 | "/* -- actual sequence value was replaced by scheme2ddl to 1 */"
27 | , res);
28 |
29 | }
30 |
31 | @Test
32 | public void testReplaceActualSequenceValueWithOneOnWrongDDL() throws Exception {
33 |
34 | String s = "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 2122 CACHE 20 NOORDER NOCYCLE ;\n";
35 | String res = ddlFormatter.replaceActualSequenceValueWithOne(s);
36 | assertNotEquals(
37 | "CREATE TABLE \"TEST01\".\"SEQ_01\" MINVALUE 1 MAXVALUE 9999999999999999999999999999 INCREMENT BY 1 START WITH 1 CACHE 20 NOORDER NOCYCLE ;\n"
38 | , res);
39 |
40 | }
41 |
42 |
43 | @Test
44 | public void testSortPreserveOriginalDDLIfNoSort() {
45 | String s = "\n CREATE UNIQUE INDEX \"HR\".\"REG_ID_PK\" ON \"HR\".\"REGIONS\" (\"REGION_ID\") \n" +
46 | " ;";
47 | String res = ddlFormatter.sortIndexesInDDL(s);
48 | assertEquals(s, res);
49 | }
50 |
51 | @Test
52 | public void testSortIndexes() {
53 | String s = " CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" +
54 | " ;\n" +
55 | " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" +
56 | " ;";
57 | String res = ddlFormatter.sortIndexesInDDL(s);
58 | assertEquals(
59 | "\n CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C3\") \n" +
60 | " ;\n" +
61 | "CREATE INDEX \"HR\".\"A_IDX2\" ON \"HR\".\"A\" (\"C2\") \n" +
62 | " ;"
63 | , res);
64 | }
65 |
66 | @Test
67 | public void testSortIndexesUniq() {
68 | String s =
69 | " \n" +
70 | "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" +
71 | " ;\n" +
72 | " CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" +
73 | " ; " +
74 | "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" +
75 | " ;\n";
76 | String res = ddlFormatter.sortIndexesInDDL(s);
77 | assertEquals("\n " +
78 | "CREATE BITMAP INDEX \"HR\".\"A_BITMAP_IDX\" ON \"HR\".\"A\" (\"C1\", \"C5\") \n" +
79 | " ;\n" +
80 | "CREATE INDEX \"HR\".\"A_IDX1\" ON \"HR\".\"A\" (\"C1\") \n" +
81 | " ;\n" +
82 | "CREATE UNIQUE INDEX \"HR\".\"A_UNIQ2\" ON \"HR\".\"A\" (\"C1\", \"B2\") \n" +
83 | " ;", res);
84 | }
85 | }
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/FileNameConstructorTest.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import com.googlecode.scheme2ddl.domain.UserObject;
4 | import org.springframework.context.ConfigurableApplicationContext;
5 | import org.springframework.context.support.FileSystemXmlApplicationContext;
6 | import org.testng.annotations.BeforeClass;
7 | import org.testng.annotations.BeforeMethod;
8 | import org.testng.annotations.Test;
9 |
10 | import java.util.ArrayList;
11 | import java.util.HashMap;
12 | import java.util.List;
13 | import java.util.Map;
14 |
15 | import static com.googlecode.scheme2ddl.FileNameConstructor.abbreviate;
16 | import static com.googlecode.scheme2ddl.FileNameConstructor.pluralaze;
17 | import static org.testng.AssertJUnit.assertEquals;
18 |
19 |
20 | /**
21 | * @author A_Reshetnikov
22 | * @since Date: 03.05.2013
23 | */
24 |
25 | public class FileNameConstructorTest {
26 | private FileNameConstructor fileNameConstructor;
27 | private List list;
28 |
29 | @BeforeMethod
30 | public void setUp() throws Exception {
31 | this.fileNameConstructor = new FileNameConstructor();
32 | fileNameConstructor.afterPropertiesSet();
33 | this.list = new ArrayList();
34 | UserObject userObject = new UserObject();
35 | userObject.setName("SimpleName");
36 | userObject.setType("Table");
37 | userObject.setSchema("SCHEMA_Name");
38 | list.add(userObject);
39 |
40 | userObject = new UserObject();
41 | userObject.setName("SYS$_#NAME");
42 | userObject.setType("REFRESH GROUP");
43 | userObject.setSchema("");
44 | list.add(userObject);
45 |
46 | userObject = new UserObject();
47 | userObject.setName("StraNge_NAME$");
48 | userObject.setType("Index");
49 | userObject.setSchema("dummy");
50 | list.add(userObject);
51 |
52 | userObject = new UserObject();
53 | userObject.setName("lib01");
54 | userObject.setType("library");
55 | userObject.setSchema("dummy");
56 | list.add(userObject);
57 |
58 | userObject = new UserObject();
59 | userObject.setName("TYPE_01");
60 | userObject.setType("TYPE");
61 | userObject.setSchema("TYPES");
62 | list.add(userObject);
63 |
64 | userObject = new UserObject();
65 | userObject.setName("oracle/i18n/data/lx10039.glb");
66 | userObject.setType("JAVA RESOURCE");
67 | userObject.setSchema("SYS");
68 | list.add(userObject);
69 |
70 |
71 | }
72 |
73 | // @org.junit.Test
74 | // public void testMap2FileName() throws Exception {
75 | //
76 | // }
77 |
78 | @Test
79 | public void testDefaultTemplate() throws Exception {
80 | for (UserObject userObject : list) {
81 | String fileName = pluralaze(abbreviate(userObject.getType())).replace(" ", "_") + "/" + userObject.getName() + ".sql";
82 | fileName = fileName.toLowerCase();
83 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
84 | }
85 | }
86 |
87 | @Test
88 | public void testKeywordSchema() throws Exception {
89 | String template = FileNameConstructor.KW_SCHEMA_LOWER + "/" + FileNameConstructor.KW_SCHEMA_UPPER;
90 | fileNameConstructor.setTemplate(template);
91 | fileNameConstructor.afterPropertiesSet();
92 | for (UserObject userObject : list) {
93 | String fileName = userObject.getSchema().toLowerCase() + "/" + userObject.getSchema().toUpperCase();
94 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
95 | }
96 | }
97 |
98 | @Test
99 | public void testKeywordObjectName() throws Exception {
100 | String template = FileNameConstructor.KW_OBJECTNAME_LOWER + "/" + FileNameConstructor.KW_OBJECTNAME_UPPER;
101 | fileNameConstructor.setTemplate(template);
102 | fileNameConstructor.afterPropertiesSet();
103 | for (UserObject userObject : list) {
104 | String fileName = userObject.getName().toLowerCase() + "/" + userObject.getName().toUpperCase();
105 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
106 | }
107 | }
108 |
109 | @Test
110 | public void testKeywordExtension() throws Exception {
111 | String template = FileNameConstructor.KW_EXTENSION_LOWER + "/" + FileNameConstructor.KW_EXTENSION_UPPER;
112 | fileNameConstructor.setTemplate(template);
113 | fileNameConstructor.afterPropertiesSet();
114 | for (UserObject userObject : list) {
115 | String fileName = "sql" + "/" + "sql".toUpperCase();
116 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
117 | }
118 | }
119 |
120 | @Test
121 | public void testTemplateWithTypeMix() throws Exception {
122 | String template = FileNameConstructor.KW_TYPE_LOWER + "/" + FileNameConstructor.KW_TYPE_LOWER +
123 | FileNameConstructor.KW_TYPE_UPPER + "/" + FileNameConstructor.KW_TYPES_PLURAL_LOWER + "//" +
124 | FileNameConstructor.KW_TYPES_PLURAL_UPPER + "/" + FileNameConstructor.KW_TYPES_PLURAL_UPPER + ".TyPEs_PLURAL";
125 | fileNameConstructor.setTemplate(template);
126 | fileNameConstructor.afterPropertiesSet();
127 | for (UserObject userObject : list) {
128 | String type = abbreviate(userObject.getType().toLowerCase()).replace(" ", "_");
129 | String typePlural = pluralaze(abbreviate(userObject.getType())).replace(" ", "_");
130 | String fileName = type.toLowerCase() + "/" + type.toLowerCase() +
131 | type.toUpperCase() + "/" + typePlural.toLowerCase() + "//" +
132 | typePlural.toUpperCase() + "/" + typePlural.toUpperCase() + ".TyPEs_PLURAL";
133 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
134 | }
135 | }
136 |
137 | @Test
138 | public void testApplyExtensionRules() {
139 | Map extensionMap = new HashMap();
140 | extensionMap.put("DEFAULT", "sql");
141 | extensionMap.put("VIEW", "vw");
142 | fileNameConstructor.setExtensionMap(extensionMap);
143 | UserObject userObject = new UserObject();
144 | userObject.setName("view01");
145 | userObject.setType("view");
146 | userObject.setSchema("");
147 | String fileName = pluralaze(abbreviate(userObject.getType())).replace(" ", "_") + "/" + userObject.getName() + ".vw";
148 | assertEquals(fileName, fileNameConstructor.map2FileName(userObject));
149 | }
150 |
151 | @Test(expectedExceptions=IllegalStateException.class)
152 | public void testExtensionRulesWrongConfig() {
153 | Map extensionMap = new HashMap();
154 | extensionMap.put("VIEW", "vw");
155 | fileNameConstructor.setExtensionMap(extensionMap);
156 | UserObject userObject = new UserObject();
157 | userObject.setName("");
158 | userObject.setType("strange type");
159 | userObject.setSchema("");
160 | fileNameConstructor.map2FileName(userObject);
161 | }
162 |
163 |
164 | }
165 |
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/MainCLITest.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import org.springframework.test.util.ReflectionTestUtils;
4 | import org.testng.annotations.AfterMethod;
5 | import org.testng.annotations.BeforeMethod;
6 | import org.testng.annotations.DataProvider;
7 | import org.testng.annotations.Test;
8 |
9 | import java.io.ByteArrayOutputStream;
10 | import java.io.PrintStream;
11 |
12 | import static org.hamcrest.MatcherAssert.assertThat;
13 | import static org.hamcrest.core.StringContains.containsString;
14 | import static org.testng.Assert.*;
15 |
16 | /**
17 | * Created by Anton Reshetnikov on 06 Dec 2016.
18 | */
19 |
20 | public class MainCLITest {
21 |
22 | private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();
23 | private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();
24 |
25 | private final PrintStream outOriginal = System.out;
26 | private final PrintStream errorOriginal = System.err;
27 |
28 | @BeforeMethod
29 | public void setUp() throws Exception {
30 | ReflectionTestUtils.setField(Main.class, "justPrintUsage", false);
31 | ReflectionTestUtils.setField(Main.class, "justPrintVersion", false);
32 | ReflectionTestUtils.setField(Main.class, "justTestConnection", false);
33 | ReflectionTestUtils.setField(Main.class, "dbUrl", null);
34 | }
35 |
36 | @BeforeMethod
37 | public void setUpStreams() {
38 | System.setOut(new PrintStream(outContent));
39 | System.setErr(new PrintStream(errContent));
40 | }
41 |
42 | @AfterMethod
43 | public void cleanUpStreams() {
44 | System.setOut(outOriginal);
45 | System.setErr(errorOriginal);
46 | outContent.reset();
47 | errContent.reset();
48 | }
49 |
50 |
51 | @DataProvider
52 | public static Object[][] testPrintUsageOptionsParams() {
53 | return new Object[][]{
54 | new String[][]{{"-h"}},
55 | new String[][]{{"--help"}},
56 | new String[][]{{"-help"}},
57 | new String[][]{{"-h"}},
58 | new String[][]{{"-url", "1", "-tc", "-h"}},
59 | new String[][]{{"-tc", "--help"}},
60 | };
61 | }
62 |
63 |
64 | @Test(dataProvider = "testPrintUsageOptionsParams")
65 | public void testPrintUsageOptions(String[] args) throws Exception {
66 | Main.main(args);
67 | assertThat(outContent.toString(), containsString("java -jar scheme2ddl.jar"));
68 | assertThat(outContent.toString(), containsString("example: scott/tiger@localhost:1521:ORCL"));
69 | }
70 |
71 | @Test
72 | public void testPrintVersionOption() throws Exception {
73 | String[] args = {"-version"};
74 | Main.main(args);
75 | assertThat(outContent.toString(), containsString("scheme2ddl version "));
76 | }
77 |
78 | @Test(expectedExceptions = Exception.class, expectedExceptionsMessageRegExp = "Unknown argument: .*")
79 | public void testUnknownArgument() throws Exception {
80 | String[] args = {"-xYx"};
81 | Main.main(args);
82 | }
83 |
84 |
85 | }
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/MainIT.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import static org.hamcrest.MatcherAssert.assertThat;
4 | import static org.hamcrest.Matchers.not;
5 | import static org.hamcrest.core.StringContains.containsString;
6 | import static org.testng.Assert.assertTrue;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 |
11 | import org.apache.commons.io.FileUtils;
12 | import org.springframework.jdbc.CannotGetJdbcConnectionException;
13 | import org.testng.Assert;
14 | import org.testng.SkipException;
15 | import org.testng.annotations.BeforeClass;
16 | import org.testng.annotations.DataProvider;
17 | import org.testng.annotations.Test;
18 |
19 | /**
20 | * @author A_Reshetnikov
21 | * @since Date: 17.09.2016
22 | */
23 |
24 | //@SpringBootTest(classes = ConfigurationIT.class, properties = "test-default.properties")
25 | public class MainIT extends BaseIT {
26 |
27 |
28 |
29 | @BeforeClass
30 | public void setUp() {
31 | try {
32 | dbaJdbcTemplate.execute("ALTER USER HR ACCOUNT UNLOCK IDENTIFIED BY pass");
33 | }
34 | catch (CannotGetJdbcConnectionException e){
35 | logger.warn("Ignore all test due", e);
36 | throw new SkipException("Ignore all test due " + e.getMessage());
37 | }
38 |
39 | }
40 |
41 |
42 |
43 |
44 | @DataProvider
45 | public static Object[][] justTestConnectionParamNames() {
46 | return new Object[][]{
47 | {"-url", "-tc"},
48 | {"-url", "--test-connection"},
49 | };
50 | }
51 |
52 |
53 | @Test(dataProvider = "justTestConnectionParamNames")
54 | public void testJustTestConnectionPositive(String urlParamName, String testConnParamName) throws Exception {
55 | String[] args = {urlParamName, url, testConnParamName};
56 | Main.main(args);
57 | Assert.assertEquals(
58 | outContent.toString(),
59 | String.format("OK success connection to jdbc:oracle:thin:%1$s%n", url)
60 | );
61 | }
62 |
63 | @Test(expectedExceptions = CannotGetJdbcConnectionException.class)
64 | public void testJustTestConnectionNegative() throws Exception {
65 | String[] args = {"-url", "1/1@127.0.0.1:789789", "-tc"};
66 | Main.main(args);
67 | }
68 |
69 |
70 |
71 | @Test
72 | public void testExportHRSchemaDefault() throws Exception {
73 | String[] args = {"-url", url};
74 | Main.main(args);
75 | assertHRSchemaDefault(
76 | FileUtils.getFile(new File("output")).getAbsolutePath(),
77 | outContent.toString());
78 | }
79 |
80 | private static void assertHRSchemaDefault(String dirPath, String out) throws IOException {
81 | assertThat(out, containsString("Will try to process schema [HR]"));
82 | assertThat(out, containsString("Start getting of user object list in schema HR for processing"));
83 | assertThat(out, containsString("WARNING: processing of 'PUBLIC DATABASE LINK' will be skipped because HR no access to view it"));
84 | assertThat(out, containsString("Found 34 items for processing in schema HR"));
85 | assertThat(out, containsString(String.format("Saved sequence hr.locations_seq to file %1$s%2$1ssequences%2$1slocations_seq.sql", dirPath, File.separator)));
86 | assertThat(out, containsString(String.format("Saved sequence hr.employees_seq to file %1$s%2$1ssequences%2$1semployees_seq.sql", dirPath, File.separator)));
87 | assertThat(out, containsString(String.format("Saved trigger hr.update_job_history to file %1$s%2$1striggers%2$1supdate_job_history.sql", dirPath, File.separator)));
88 | assertThat(out, containsString(String.format("Saved procedure hr.add_job_history to file %1$s%2$1sprocedures%2$1sadd_job_history.sql", dirPath, File.separator)));
89 | assertThat(out, containsString(String.format("Saved table hr.locations to file %1$s%2$1stables%2$1slocations.sql", dirPath, File.separator)));
90 | assertThat(out, containsString(String.format("Saved procedure hr.secure_dml to file %1$s%2$1sprocedures%2$1ssecure_dml.sql", dirPath, File.separator)));
91 | assertThat(out, containsString(String.format("Saved view hr.emp_details_view to file %1$s%2$1sviews%2$1semp_details_view.sql", dirPath, File.separator)));
92 |
93 | assertThat(out, containsString(String.format(
94 | "-------------------------------------------------------%n" +
95 | " R E P O R T S K I P P E D O B J E C T S %n" +
96 | "-------------------------------------------------------%n" +
97 | "| skip rule | object type | count |%n" +
98 | "-------------------------------------------------------%n" +
99 | "| config | INDEX | 19 |")));
100 |
101 |
102 | assertThat(out, containsString("Written 15 ddls with user objects from total 34 in schema HR"));
103 | assertThat(out, containsString("Skip processing 19 user objects from total 34 in schema HR"));
104 | assertThat(out, containsString("scheme2ddl of schema HR completed"));
105 |
106 |
107 | assertEqualsFileContent(dirPath + "/sequences/locations_seq.sql", "CREATE SEQUENCE \"HR\".\"LOCATIONS_SEQ\"" +
108 | " MINVALUE 1 MAXVALUE 9900 INCREMENT BY 100 START WITH 3300 NOCACHE NOORDER NOCYCLE ;");
109 |
110 |
111 | assertEqualsFileContent(dirPath + "/tables/regions.sql", "CREATE TABLE \"HR\".\"REGIONS\" \n" +
112 | " (\t\"REGION_ID\" NUMBER CONSTRAINT \"REGION_ID_NN\" NOT NULL ENABLE, \n" +
113 | "\t\"REGION_NAME\" VARCHAR2(25)\n" +
114 | " ) ;\n" +
115 | " ALTER TABLE \"HR\".\"REGIONS\" ADD CONSTRAINT \"REG_ID_PK\" PRIMARY KEY (\"REGION_ID\") ENABLE;\n" +
116 | " CREATE UNIQUE INDEX \"HR\".\"REG_ID_PK\" ON \"HR\".\"REGIONS\" (\"REGION_ID\") \n" +
117 | " ;");
118 |
119 | assertEqualsFileContent(dirPath + "/triggers/secure_employees.sql",
120 | "CREATE OR REPLACE TRIGGER \"HR\".\"SECURE_EMPLOYEES\" \n" +
121 | " BEFORE INSERT OR UPDATE OR DELETE ON employees\n" +
122 | "BEGIN\n" +
123 | " secure_dml;\n" +
124 | "END secure_employees;\n" +
125 | "/\n" +
126 | "ALTER TRIGGER \"HR\".\"SECURE_EMPLOYEES\" DISABLE;");
127 | }
128 |
129 |
130 | @Test(expectedExceptions = RuntimeException.class,
131 | expectedExceptionsMessageRegExp = "Cannot process schema \'PUBLIC\' with oracle user \'hr\', " +
132 | "if it\'s not connected as sysdba")
133 | public void testProcessForeignSchemaNegative() throws Exception {
134 | String[] args = {"-url", url, "-s", "PUBLIC"};
135 | Main.main(args);
136 | }
137 |
138 | @Test
139 | public void testProcessForeignSchema() throws Exception {
140 | String outputPath = tempOutput.getAbsolutePath();
141 |
142 | String[] args = {"-url", dbaUrl, "-s", "HR,OUTLN", "-o", outputPath};
143 |
144 | Main.main(args);
145 | String out = outContent.toString();
146 |
147 | assertThat(out, containsString("Will try to process schema list [HR, OUTLN]"));
148 | assertThat(out, containsString("Found 34 items for processing in schema HR"));
149 | assertThat(out, containsString("Found 8 items for processing in schema OUTLN"));
150 |
151 | assertEqualsFileContent(outputPath + "/OUTLN/procedures/ora$grant_sys_select.sql",
152 | "CREATE OR REPLACE PROCEDURE \"OUTLN\".\"ORA$GRANT_SYS_SELECT\" as\n" +
153 | "begin\n" +
154 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$ TO SELECT_CATALOG_ROLE';\n" +
155 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$HINTS TO SELECT_CATALOG_ROLE';\n" +
156 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$NODES TO SELECT_CATALOG_ROLE';\n" +
157 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$ TO SYS WITH GRANT OPTION';\n" +
158 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$HINTS TO SYS WITH GRANT OPTION';\n" +
159 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$NODES TO SYS WITH GRANT OPTION';\n" +
160 | "end;\n" +
161 | "/");
162 |
163 |
164 | assertEqualsFileContent(outputPath +"/HR/tables/regions.sql",
165 | "CREATE TABLE \"HR\".\"REGIONS\" \n" +
166 | " (\t\"REGION_ID\" NUMBER CONSTRAINT \"REGION_ID_NN\" NOT NULL ENABLE, \n" +
167 | "\t\"REGION_NAME\" VARCHAR2(25)\n" +
168 | " ) ;\n" +
169 | " ALTER TABLE \"HR\".\"REGIONS\" ADD CONSTRAINT \"REG_ID_PK\" PRIMARY KEY (\"REGION_ID\") ENABLE;\n" +
170 | " CREATE UNIQUE INDEX \"HR\".\"REG_ID_PK\" ON \"HR\".\"REGIONS\" (\"REGION_ID\") \n" +
171 | " ;");
172 |
173 | }
174 |
175 | @Test
176 | public void testProcessForeignSchemaParallel() throws Exception {
177 | String outputPath = tempOutput.getAbsolutePath();
178 |
179 | String[] args = {"-url", dbaUrl, "--schemas", "OUTLN", "--output", outputPath, "--parallel", "2"};
180 |
181 | Main.main(args);
182 | String out = outContent.toString();
183 |
184 | assertThat(out, containsString("Will try to process schema [OUTLN]"));
185 | assertThat(out, containsString("Found 8 items for processing in schema OUTLN"));
186 |
187 | assertEqualsFileContent(outputPath + "/OUTLN/procedures/ora$grant_sys_select.sql",
188 | "CREATE OR REPLACE PROCEDURE \"OUTLN\".\"ORA$GRANT_SYS_SELECT\" as\n" +
189 | "begin\n" +
190 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$ TO SELECT_CATALOG_ROLE';\n" +
191 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$HINTS TO SELECT_CATALOG_ROLE';\n" +
192 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$NODES TO SELECT_CATALOG_ROLE';\n" +
193 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$ TO SYS WITH GRANT OPTION';\n" +
194 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$HINTS TO SYS WITH GRANT OPTION';\n" +
195 | " EXECUTE IMMEDIATE 'GRANT SELECT ON OUTLN.OL$NODES TO SYS WITH GRANT OPTION';\n" +
196 | "end;\n" +
197 | "/");
198 | }
199 |
200 | @Test
201 | public void testFilterAndReplaceSeqValue() throws Exception {
202 | String outputPath = tempOutput.getAbsolutePath();
203 |
204 | String[] args = {"-url", url, "-f", "LOCATIONS_SEQ", "-o", outputPath};
205 | Main.main(args);
206 |
207 | String out = outContent.toString();
208 | assertThat(out, containsString("Found 1 items for processing in schema HR"));
209 |
210 | assertEqualsFileContent(outputPath + "/sequences/locations_seq.sql", "CREATE SEQUENCE \"HR\".\"LOCATIONS_SEQ\"" +
211 | " MINVALUE 1 MAXVALUE 9900 INCREMENT BY 100 START WITH 3300 NOCACHE NOORDER NOCYCLE ;");
212 |
213 |
214 | String[] args2 = {"-url", url, "--filter", "LOCATIONS_SEQ", "--output", outputPath, "--replace-sequence-values"};
215 | Main.main(args2);
216 | out = outContent.toString();
217 | assertThat(out, containsString("Found 1 items for processing in schema HR"));
218 |
219 | assertEqualsFileContent(outputPath + "/sequences/locations_seq.sql", "CREATE SEQUENCE \"HR\".\"LOCATIONS_SEQ\" MINVALUE 1 MAXVALUE 9900 INCREMENT BY 100 START WITH 1 NOCACHE NOORDER NOCYCLE ;\n" +
220 | "/* -- actual sequence value was replaced by scheme2ddl to 1 */");
221 |
222 | }
223 |
224 | @Test
225 | public void testRunWithConfigPath() throws Exception {
226 | String outputPath = tempOutput.getAbsolutePath();
227 | String[] args = {"-url", url, "-c", "src/main/resources/scheme2ddl.config.xml", "-o", outputPath};
228 | Main.main(args);
229 | assertHRSchemaDefault(
230 | outputPath,
231 | outContent.toString());
232 | }
233 |
234 |
235 | @Test(enabled = false) //todo enable
236 | public void testRunAsSysDbaTestConnection() throws Exception {
237 | String outputPath = tempOutput.getAbsolutePath();
238 | String dba[] = dbaAsSysdbaUrl.split(" ");
239 | assertTrue(dba.length==3);
240 | String[] args = {"-url", dba[0], dba[1], dba[2], "-tc"};
241 | Main.main(args);
242 | Assert.assertEquals(
243 | outContent.toString(),
244 | "OK success connection to jdbc:oracle:thin:" + dbaAsSysdbaUrl + "\n");
245 |
246 | }
247 |
248 |
249 | @Test(enabled = false) //todo enable
250 | public void testRunAsSysDbaWithTypeFilter() throws Exception {
251 | String outputPath = tempOutput.getAbsolutePath();
252 | String dba[] = dbaAsSysdbaUrl.split(" ");
253 | assertTrue(dba.length==3);
254 | String[] args = {"-url", dba[0], dba[1], dba[2], "--type-filter", "'SCHEDULE', 'JOB'"};
255 | Main.main(args);
256 | String out = outContent.toString();
257 | assertThat(out, containsString("Will try to process schema [SYS]"));
258 | assertThat(out, containsString("Found 13 items for processing in schema SYS"));
259 | assertThat(out, containsString("Cannot get DDL for object UserObject"));
260 |
261 | }
262 |
263 | @Test
264 | public void testRunWithTestCustomConfig() throws Exception {
265 | String outputPath = tempOutput.getAbsolutePath();
266 | String[] args = {"-url", url, "-c", "src/test/resources/test.config.xml", "-o", outputPath};
267 | Main.main(args);
268 | String out = outContent.toString();
269 | assertThat(out, containsString("Found 68 items for processing in schema HR"));
270 | assertThat(out, containsString(
271 | "Cannot get DDL for object UserObject{name='SYS_C004102', type='CONSTRAINT', schema='HR', ddl='null'} " +
272 | "with error message ConnectionCallback; uncategorized SQLException for SQL [];" +
273 | " SQL state [99999]; error code [31603];" +
274 | " ORA-31603: object \"SYS_C004102\" of type CONSTRAINT not found in schema \"HR\"\n"));
275 |
276 |
277 | assertThat(out, containsString(String.format(
278 | "-------------------------------------------------------%n" +
279 | " R E P O R T S K I P P E D O B J E C T S %n" +
280 | "-------------------------------------------------------%n" +
281 | "| skip rule | object type | count |%n" +
282 | "-------------------------------------------------------%n" +
283 | "| config | INDEX | 19 |%n" +
284 | "| sql error | CONSTRAINT | 1 |"
285 | )));
286 | }
287 |
288 |
289 | @Test(enabled = false) //todo enable
290 | public void testCustomConfigWithSchemaList() throws Exception {
291 | String outputPath = tempOutput.getAbsolutePath();
292 | String[] args = {"-url", url, "-c", "src/test/resources/test_schema_list.config.xml", "-o", outputPath};
293 | Main.main(args);
294 | String out = outContent.toString();
295 | assertThat(out, containsString("Ignore 'schemaList' from advanced config, because oracle user is not connected as sys dba"));
296 | assertThat(out, containsString("Found 68 items for processing in schema HR"));
297 | assertThat(out, containsString(
298 | "Cannot get DDL for object UserObject{name='SYS_C004102', type='CONSTRAINT', schema='HR', ddl='null'} " +
299 | "with error message ConnectionCallback; uncategorized SQLException for SQL [];" +
300 | " SQL state [99999]; error code [31603];" +
301 | " ORA-31603: object \"SYS_C004102\" of type CONSTRAINT not found in schema \"HR\"\n"));
302 |
303 |
304 | assertThat(out, containsString(
305 | "-------------------------------------------------------\n" +
306 | " R E P O R T S K I P P E D O B J E C T S \n" +
307 | "-------------------------------------------------------\n" +
308 | "| skip rule | object type | count |\n" +
309 | "-------------------------------------------------------\n" +
310 | "| config | INDEX | 19 |\n" +
311 | "| sql error | CONSTRAINT | 1 |"
312 | ));
313 | }
314 |
315 | @Test(enabled = false) //todo enable
316 | public void testCustomConfigWithSchemaListAsDba() throws Exception {
317 | String outputPath = tempOutput.getAbsolutePath();
318 | String dba[] = dbaAsSysdbaUrl.split(" ");
319 | assertTrue(dba.length==3);
320 | String[] args = {"-url", dba[0], dba[1], dba[2], "-c", "src/test/resources/test_schema_list.config.xml", "-o", outputPath};
321 | Main.main(args);
322 | String out = outContent.toString();
323 | assertThat(out, not(containsString("Ignore 'schemaList' from advanced config, because oracle user is not connected as sys dba")));
324 | assertThat(out, containsString("Will try to process schema list [SCOTT, HR]"));
325 | assertThat(out, containsString("Found 0 items for processing in schema SCOTT"));
326 | assertThat(out, containsString("Found 68 items for processing in schema HR"));
327 | assertThat(out, containsString(
328 | "Cannot get DDL for object UserObject{name='SYS_C004102', type='CONSTRAINT', schema='HR', ddl='null'} " +
329 | "with error message ConnectionCallback; uncategorized SQLException for SQL [];" +
330 | " SQL state [99999]; error code [31603];" +
331 | " ORA-31603: object \"SYS_C004102\" of type CONSTRAINT not found in schema \"HR\"\n"));
332 |
333 |
334 | assertThat(out, containsString(
335 | "-------------------------------------------------------\n" +
336 | " R E P O R T S K I P P E D O B J E C T S \n" +
337 | "-------------------------------------------------------\n" +
338 | "| skip rule | object type | count |\n" +
339 | "-------------------------------------------------------\n" +
340 | "| config | INDEX | 19 |\n" +
341 | "| sql error | CONSTRAINT | 1 |"
342 | ));
343 | }
344 |
345 | @Test
346 | public void testStopOnWarning() throws Exception {
347 | String outputPath = tempOutput.getAbsolutePath();
348 | String[] args = {"-url", url, "-c", "src/test/resources/test.config.xml", "-o", outputPath, "--stop-on-warning"};
349 | try {
350 | Main.main(args);
351 | }
352 | catch (Exception e){
353 |
354 | }
355 | String out = outContent.toString();
356 | assertThat(out, containsString("Found 68 items for processing in schema HR"));
357 | assertThat(out, containsString("scheme2ddl of schema HR failed"));
358 | assertThat(out, containsString("com.googlecode.scheme2ddl.exception.NonSkippableException"));
359 |
360 | }
361 |
362 |
363 |
364 | }
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/PublicDbLinkIT.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import org.apache.commons.io.FileUtils;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.beans.factory.annotation.Value;
6 | import org.springframework.boot.test.context.SpringBootTest;
7 | import org.springframework.dao.InvalidDataAccessResourceUsageException;
8 | import org.springframework.jdbc.BadSqlGrammarException;
9 | import org.springframework.jdbc.CannotGetJdbcConnectionException;
10 | import org.springframework.jdbc.core.JdbcTemplate;
11 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
12 | import org.springframework.test.util.ReflectionTestUtils;
13 | import org.testng.Assert;
14 | import org.testng.SkipException;
15 | import org.testng.annotations.*;
16 |
17 | import java.io.ByteArrayOutputStream;
18 | import java.io.File;
19 | import java.io.IOException;
20 | import java.io.PrintStream;
21 | import java.sql.SQLException;
22 | import java.util.UUID;
23 |
24 | import static org.hamcrest.MatcherAssert.assertThat;
25 | import static org.hamcrest.core.StringContains.containsString;
26 | import static org.testng.Assert.assertEquals;
27 | import static org.testng.Assert.assertTrue;
28 |
29 | /**
30 | * @author A_Reshetnikov
31 | * @since Date: 17.09.2016
32 | */
33 |
34 |
35 | public class PublicDbLinkIT extends BaseIT {
36 |
37 | @Value("${testUserUrl}")
38 | protected String testUserUrl;
39 |
40 |
41 | @BeforeClass
42 | public void createSchema() {
43 | try{
44 | dropUser();
45 | }catch (InvalidDataAccessResourceUsageException e) {
46 | logger.warn("", e);
47 | }
48 | try {
49 | createUser();
50 | } catch (CannotGetJdbcConnectionException e) {
51 | logger.warn("Ignore all test due", e);
52 | throw new SkipException("Ignore all test due " + e.getMessage());
53 | }
54 |
55 | }
56 |
57 | private void createUser() {
58 | dbaJdbcTemplate.execute("CREATE USER scheme2ddl_test02 IDENTIFIED BY pass");
59 | dbaJdbcTemplate.execute("GRANT CONNECT, SELECT_CATALOG_ROLE to scheme2ddl_test02");
60 | dbaJdbcTemplate.execute("ALTER USER scheme2ddl_test02 ACCOUNT UNLOCK IDENTIFIED BY pass");
61 | }
62 |
63 |
64 | // @AfterClass(alwaysRun = true)
65 | public void dropUser(){
66 | dbaJdbcTemplate.execute("drop USER scheme2ddl_test02");
67 | }
68 |
69 | @BeforeClass
70 | public void createDBLink(){
71 | dbaJdbcTemplate.execute("CREATE PUBLIC DATABASE LINK remote USING 'remote'");
72 | }
73 |
74 | @AfterClass
75 | public void dropDBLink(){
76 | dbaJdbcTemplate.execute("DROP PUBLIC DATABASE LINK remote");
77 | }
78 |
79 |
80 | @Test
81 | public void testPublicDbLinksWithSelectCatalogRole() throws Exception {
82 | String outputPath = tempOutput.getAbsolutePath();
83 | String[] args = {"-url", testUserUrl, "-o", outputPath};
84 | Main.main(args);
85 | String out = outContent.toString();
86 |
87 | assertThat(out, containsString("Written 1 ddls with user objects from total 1 in schema"));
88 |
89 | assertEqualsFileContent(outputPath + "/PUBLIC/public_db_links/remote.sql",
90 | "CREATE PUBLIC DATABASE LINK \"REMOTE\"\n" +
91 | " USING 'remote';");
92 |
93 | }
94 |
95 |
96 | }
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/UserObjectWriterTest.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl;
2 |
3 | import com.googlecode.scheme2ddl.domain.UserObject;
4 | import org.assertj.core.api.Assertions;
5 | import org.testng.annotations.Test;
6 |
7 | import java.io.File;
8 | import java.nio.charset.StandardCharsets;
9 |
10 | public class UserObjectWriterTest {
11 |
12 | private UserObjectWriter userObjectWriter = new UserObjectWriter();
13 |
14 | @Test
15 | public void testWriteUserObjectWithUtf8() throws Exception {
16 |
17 | String content = "--你好 Немного текста в UTF-8";
18 | String outputPath = "output";
19 | userObjectWriter.setOutputPath(outputPath);
20 | UserObject userObject = new UserObject();
21 | userObject.setType("tmp_test");
22 | userObject.setSchema("tmp_test");
23 | userObject.setName("content_utf8");
24 | userObject.setFileName("tmp_test.sql");
25 | userObject.setDdl(content);
26 | userObjectWriter.writeUserObject(userObject);
27 |
28 | String fileName = outputPath + "/" + userObject.getFileName();
29 | File f = new File(fileName);
30 | f.deleteOnExit(); //to delete temp file after test over
31 | Assertions.assertThat(f).usingCharset(StandardCharsets.UTF_8).hasContent(content);
32 |
33 | }
34 | }
--------------------------------------------------------------------------------
/src/test/java/com/googlecode/scheme2ddl/dao/UserObjectDaoImplIT.java:
--------------------------------------------------------------------------------
1 | package com.googlecode.scheme2ddl.dao;
2 |
3 | import com.googlecode.scheme2ddl.ConfigurationIT;
4 | import org.springframework.beans.factory.annotation.Autowired;
5 | import org.springframework.boot.test.context.SpringBootTest;
6 | import org.springframework.jdbc.CannotGetJdbcConnectionException;
7 | import org.springframework.jdbc.UncategorizedSQLException;
8 | import org.springframework.jdbc.core.JdbcTemplate;
9 | import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
10 | import org.testng.SkipException;
11 | import org.testng.annotations.BeforeClass;
12 | import org.testng.annotations.BeforeMethod;
13 | import org.testng.annotations.Test;
14 |
15 | import java.util.HashMap;
16 |
17 | import static org.testng.Assert.*;
18 |
19 | /**
20 | * Created by Anton Reshetnikov on 12 Dec 2016.
21 | */
22 | @SpringBootTest(classes = ConfigurationIT.class, properties = "test-default.properties")
23 | public class UserObjectDaoImplIT extends AbstractTestNGSpringContextTests {
24 |
25 |
26 |
27 | private UserObjectDaoImpl userObjectDao;
28 |
29 | @Autowired
30 | protected JdbcTemplate dbaJdbcTemplate;
31 |
32 | @BeforeClass
33 | public void setUp() {
34 | try {
35 | dbaJdbcTemplate.execute("select 1 from dual");
36 | }
37 | catch (CannotGetJdbcConnectionException e){
38 | logger.warn("Ignore all test due", e);
39 | throw new SkipException("Ignore all test due " + e.getMessage());
40 | }
41 |
42 | }
43 |
44 |
45 | @BeforeClass
46 | public void initDao() throws Exception {
47 | userObjectDao = new UserObjectDaoImpl();
48 |
49 | userObjectDao.setLaunchedByDBA(false);
50 | userObjectDao.setJdbcTemplate(dbaJdbcTemplate);
51 | userObjectDao.setSchemaName("NONE");
52 | userObjectDao.setTransformParams(new HashMap());
53 |
54 | }
55 |
56 | @Test
57 | public void findRefGroupDDLNotDba(){
58 | userObjectDao.setLaunchedByDBA(false);
59 | String ddl = userObjectDao.findRefGroupDDL("REFRESH_GROUP", "testName");
60 | assertNull(ddl);
61 |
62 | }
63 |
64 | @Test(expectedExceptions = UncategorizedSQLException.class)
65 | public void findRefGroupDDLDba(){
66 | userObjectDao.setLaunchedByDBA(true);
67 | String ddl = userObjectDao.findRefGroupDDL("REFRESH_GROUP", "testName");
68 |
69 | }
70 |
71 | }
--------------------------------------------------------------------------------
/src/test/resources/test-default.properties:
--------------------------------------------------------------------------------
1 | #- docker pull wnameless/oracle-xe-11g
2 | #- docker run -d -p 49161:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g
3 |
4 |
5 | dbaUrl=system/oracle@127.0.0.1:49161/XE
6 | dbaAsSysdbaUrl=sys as sysdba/oracle@127.0.0.1:49161/XE
7 | hrUrl=hr/pass@127.0.0.1:49161/XE
8 |
9 | testUserUrl=scheme2ddl_test02/pass@127.0.0.1:49161/XE
10 |
11 |
12 | dba.datasource.url=jdbc:oracle:thin:@127.0.0.1:49161:XE
13 | dba.datasource.username=system
14 | dba.datasource.password=oracle
--------------------------------------------------------------------------------
/src/test/resources/test.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 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
75 |
76 |
77 |
78 |
79 |
81 |
82 |
84 |
85 |
86 |
87 |
88 |
89 | sql
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | sql
98 |
99 |
100 | prc
101 |
102 |
103 | fnc
104 |
105 |
106 | trg
107 |
108 |
109 | vw
110 |
111 |
112 | pks
113 |
114 |
115 | pkb
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | sql
124 |
125 |
126 |
127 |
128 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | COMMENT
164 | INDEX
165 | OBJECT_GRANT
166 | TRIGGER
167 |
168 |
169 |
170 |
171 | COMMENT
172 | OBJECT_GRANT
173 |
174 |
175 |
176 |
177 | COMMENT
178 | INDEX
179 | MATERIALIZED_VIEW_LOG
180 | OBJECT_GRANT
181 |
182 |
183 |
184 |
185 | OBJECT_GRANT
186 |
187 |
188 |
189 |
190 | OBJECT_GRANT
191 |
192 |
193 |
194 |
195 | OBJECT_GRANT
196 |
197 |
198 |
199 |
200 | OBJECT_GRANT
201 |
202 |
203 |
204 |
205 | OBJECT_GRANT
206 |
207 |
208 |
209 |
210 |
213 |
214 |
215 |
216 | *_*_temp_*
217 |
218 |
219 |
227 |
228 | *
229 | *
230 | *
231 |
232 |
233 |
234 | *
235 | *
236 |
237 |
238 |
239 | SYSTP*
240 | *==
241 |
242 | SYS_PLSQL_*
243 |
244 |
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------
/src/test/resources/test_schema_list.config.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | SCOTT
22 | HR
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
75 |
76 |
77 |
78 |
79 |
81 |
82 |
84 |
85 |
86 |
87 |
88 |
89 | sql
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | sql
98 |
99 |
100 | prc
101 |
102 |
103 | fnc
104 |
105 |
106 | trg
107 |
108 |
109 | vw
110 |
111 |
112 | pks
113 |
114 |
115 | pkb
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 | sql
124 |
125 |
126 |
127 |
128 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 | COMMENT
164 | INDEX
165 | OBJECT_GRANT
166 | TRIGGER
167 |
168 |
169 |
170 |
171 | COMMENT
172 | OBJECT_GRANT
173 |
174 |
175 |
176 |
177 | COMMENT
178 | INDEX
179 | MATERIALIZED_VIEW_LOG
180 | OBJECT_GRANT
181 |
182 |
183 |
184 |
185 | OBJECT_GRANT
186 |
187 |
188 |
189 |
190 | OBJECT_GRANT
191 |
192 |
193 |
194 |
195 | OBJECT_GRANT
196 |
197 |
198 |
199 |
200 | OBJECT_GRANT
201 |
202 |
203 |
204 |
205 | OBJECT_GRANT
206 |
207 |
208 |
209 |
210 |
213 |
214 |
215 |
216 | *_*_temp_*
217 |
218 |
219 |
227 |
228 | *
229 | *
230 | *
231 |
232 |
233 |
234 | *
235 | *
236 |
237 |
238 |
239 | SYSTP*
240 | *==
241 |
242 | SYS_PLSQL_*
243 |
244 |
245 |
246 |
247 |
248 |
249 |
--------------------------------------------------------------------------------