├── .gitignore ├── .settings └── org.eclipse.jdt.core.prefs ├── .travis.yml ├── README.md ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── googlecode │ │ └── scheme2ddl │ │ ├── AlternateFileNameConstructor.java │ │ ├── DDLFormatter.java │ │ ├── FileNameConstructor.java │ │ ├── IFileNameConstructor.java │ │ ├── Main.java │ │ ├── TypeNamesUtil.java │ │ ├── UserObjectJobRunner.java │ │ ├── UserObjectProcessor.java │ │ ├── UserObjectReader.java │ │ ├── UserObjectWriter.java │ │ ├── aspect │ │ └── StatAspect.java │ │ ├── dao │ │ ├── ConnectionDao.java │ │ ├── ConnectionDaoImpl.java │ │ ├── UserObjectDao.java │ │ └── UserObjectDaoImpl.java │ │ ├── domain │ │ └── UserObject.java │ │ └── exception │ │ ├── CannotGetDDLException.java │ │ └── NonSkippableException.java └── resources │ ├── applicationContext.xml │ ├── logback.xml │ └── scheme2ddl.config.xml └── test ├── java └── com │ └── googlecode │ └── scheme2ddl │ ├── BaseIT.java │ ├── ConfigurationIT.java │ ├── DDLFormatterTest.java │ ├── FileNameConstructorTest.java │ ├── MainCLITest.java │ ├── MainIT.java │ ├── PublicDbLinkIT.java │ ├── UserObjectWriterTest.java │ └── dao │ └── UserObjectDaoImplIT.java └── resources ├── test-default.properties ├── test.config.xml └── test_schema_list.config.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .classpath 3 | .project 4 | .settings/ 5 | target/ 6 | pom.xml.tag 7 | pom.xml.releaseBackup 8 | pom.xml.versionsBackup 9 | pom.xml.next 10 | release.properties 11 | dependency-reduced-pom.xml 12 | buildNumber.properties 13 | output 14 | scheme2ddl.iml 15 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.methodParameters=generate 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=11 4 | org.eclipse.jdt.core.compiler.compliance=11 5 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 6 | org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning 7 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore 8 | org.eclipse.jdt.core.compiler.release=disabled 9 | org.eclipse.jdt.core.compiler.source=11 10 | org.eclipse.jdt.core.formatter.align_type_members_on_columns=false 11 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 12 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 13 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 14 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 15 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 16 | org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 17 | org.eclipse.jdt.core.formatter.alignment_for_assignment=0 18 | org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 19 | org.eclipse.jdt.core.formatter.alignment_for_compact_if=48 20 | org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=16 21 | org.eclipse.jdt.core.formatter.alignment_for_enum_constants=49 22 | org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=32 23 | org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 24 | org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 25 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 26 | org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 27 | org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 28 | org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=4 29 | org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 30 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 31 | org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 32 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 33 | org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 34 | org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 35 | org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 36 | org.eclipse.jdt.core.formatter.blank_lines_after_package=1 37 | org.eclipse.jdt.core.formatter.blank_lines_before_field=0 38 | org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 39 | org.eclipse.jdt.core.formatter.blank_lines_before_imports=0 40 | org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0 41 | org.eclipse.jdt.core.formatter.blank_lines_before_method=1 42 | org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 43 | org.eclipse.jdt.core.formatter.blank_lines_before_package=0 44 | org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 45 | org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 46 | org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line 47 | org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line 48 | org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line 49 | org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line 50 | org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line 51 | org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line 52 | org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line 53 | org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line 54 | org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line 55 | org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line 56 | org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line 57 | org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line 58 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false 59 | org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false 60 | org.eclipse.jdt.core.formatter.comment.format_block_comments=true 61 | org.eclipse.jdt.core.formatter.comment.format_header=true 62 | org.eclipse.jdt.core.formatter.comment.format_html=true 63 | org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true 64 | org.eclipse.jdt.core.formatter.comment.format_line_comments=true 65 | org.eclipse.jdt.core.formatter.comment.format_source_code=false 66 | org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true 67 | org.eclipse.jdt.core.formatter.comment.indent_root_tags=true 68 | org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert 69 | org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=do not insert 70 | org.eclipse.jdt.core.formatter.comment.line_length=120 71 | org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true 72 | org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true 73 | org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false 74 | org.eclipse.jdt.core.formatter.compact_else_if=true 75 | org.eclipse.jdt.core.formatter.continuation_indentation=2 76 | org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 77 | org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off 78 | org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on 79 | org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false 80 | org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true 81 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true 82 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true 83 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true 84 | org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true 85 | org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true 86 | org.eclipse.jdt.core.formatter.indent_empty_lines=false 87 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true 88 | org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true 89 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true 90 | org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true 91 | org.eclipse.jdt.core.formatter.indentation.size=2 92 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert 93 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert 94 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert 95 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert 96 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert 97 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert 98 | org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert 99 | org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert 100 | org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert 101 | org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert 102 | org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert 103 | org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert 104 | org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert 105 | org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert 106 | org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert 107 | org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert 108 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert 109 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert 110 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert 111 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert 112 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert 113 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert 114 | org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert 115 | org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert 116 | org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert 117 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert 118 | org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert 119 | org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert 120 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert 121 | org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert 122 | org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert 123 | org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert 124 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert 125 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert 126 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert 127 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert 128 | org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert 129 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert 130 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert 131 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert 132 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert 133 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert 134 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert 135 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert 136 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert 137 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert 138 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert 139 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert 140 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert 141 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert 142 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert 143 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert 144 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert 145 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert 146 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert 147 | org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert 148 | org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert 149 | org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert 150 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert 151 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert 152 | org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert 153 | org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=do not insert 154 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert 155 | org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert 156 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert 157 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert 158 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert 159 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert 160 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert 161 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert 162 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert 163 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert 164 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert 165 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert 166 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert 167 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert 168 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert 169 | org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert 170 | org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert 171 | org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert 172 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert 173 | org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert 174 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert 175 | org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert 176 | org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert 177 | org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert 178 | org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert 179 | org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert 180 | org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert 181 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert 182 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert 183 | org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert 184 | org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=do not insert 185 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert 186 | org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert 187 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert 188 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert 189 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert 190 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert 191 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert 192 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert 193 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert 194 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert 195 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert 196 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert 197 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert 198 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert 199 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert 200 | org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert 201 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert 202 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert 203 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert 204 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert 205 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert 206 | org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=insert 207 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert 208 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert 209 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert 210 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert 211 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert 212 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert 213 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert 214 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert 215 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert 216 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert 217 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert 218 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert 219 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert 220 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert 221 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert 222 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert 223 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert 224 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert 225 | org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert 226 | org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert 227 | org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert 228 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert 229 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert 230 | org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert 231 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert 232 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert 233 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert 234 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert 235 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert 236 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert 237 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert 238 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert 239 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert 240 | org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert 241 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert 242 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert 243 | org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert 244 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert 245 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert 246 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert 247 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert 248 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert 249 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert 250 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert 251 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert 252 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert 253 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert 254 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert 255 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert 256 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert 257 | org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert 258 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert 259 | org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert 260 | org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert 261 | org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert 262 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert 263 | org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert 264 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert 265 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert 266 | org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert 267 | org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert 268 | org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert 269 | org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert 270 | org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert 271 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert 272 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert 273 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert 274 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert 275 | org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert 276 | org.eclipse.jdt.core.formatter.join_lines_in_comments=true 277 | org.eclipse.jdt.core.formatter.join_wrapped_lines=true 278 | org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false 279 | org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false 280 | org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false 281 | org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false 282 | org.eclipse.jdt.core.formatter.lineSplit=120 283 | org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false 284 | org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false 285 | org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 286 | org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 287 | org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false 288 | org.eclipse.jdt.core.formatter.tabulation.char=space 289 | org.eclipse.jdt.core.formatter.tabulation.size=4 290 | org.eclipse.jdt.core.formatter.use_on_off_tags=false 291 | org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false 292 | org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true 293 | org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true 294 | org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true 295 | org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter 296 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | #sudo: required 3 | 4 | services: 5 | - docker 6 | 7 | jdk: 8 | - oraclejdk11 9 | 10 | before_install: 11 | - docker pull wnameless/oracle-xe-11g-r2 12 | - docker run --name oracle -d -p 127.0.0.1:49161:1521 -e ORACLE_ALLOW_REMOTE=true wnameless/oracle-xe-11g-r2 13 | # - docker inspect oracle 14 | # - docker ps -a 15 | - echo "Wait to allow Oracle to be initialized" 16 | - sleep 10 17 | - docker top oracle 18 | - sleep 10 19 | - docker top oracle 20 | - sleep 10 21 | - docker top oracle 22 | - sleep 10 23 | - docker top oracle 24 | - sleep 10 25 | - docker top oracle 26 | - sleep 10 27 | - docker top oracle 28 | 29 | script: 30 | - mvn test verify 31 | 32 | after_success: 33 | - mvn coveralls:report -Dcoveralls.repoToken=$COVERALLS_REPO_TOKEN 34 | 35 | cache: 36 | directories: 37 | - $HOME/.m2 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Latest version of 'scheme2ddl' @ Cloudsmith](https://api-prd.cloudsmith.io/v1/badges/version/qwazer/repo/maven/scheme2ddl/latest/a=noarch;xg=com.googlecode/?render=true&show_latest=true)](https://cloudsmith.io/~qwazer/repos/repo/packages/detail/maven/scheme2ddl/latest/a=noarch;xg=com.googlecode/)   [![Build Status](https://travis-ci.com/qwazer/scheme2ddl.svg?branch=master)](https://travis-ci.com/qwazer/scheme2ddl)   [![Coverage Status](https://coveralls.io/repos/github/qwazer/scheme2ddl/badge.svg?branch=master)](https://coveralls.io/github/qwazer/scheme2ddl?branch=master) 2 | 3 | **scheme2ddl** is command line util for export oracle schema to set of ddl scripts. Provide a lot of configurations via basic command line options or advanced XML configuartion. 4 | 5 | **scheme2ddl** is part of 6 | [oracle-ddl2svn](https://github.com/qwazer/oracle-ddl2svn) project. 7 | 8 | 9 | 10 | ### Benefits 11 | **scheme2ddl** give ability to filter undesirable information, separate DDL in different files, pretty format output. 12 | 13 | ### Download 14 | 15 | Use link above or 16 | 17 | ```yaml 18 | wget https://dl.cloudsmith.io/public/qwazer/repo/maven/com/googlecode/scheme2ddl/2.4.4/scheme2ddl-2.4.4.jar 19 | ``` 20 | 21 | ### How to start with minimal configuration 22 | Java must be installed on your computer. 23 | 24 | For exporting oracle scheme you must provide 25 | 26 | - DB connection string 27 | - output directory 28 | 29 | Usage example. Command 30 | 31 | java -jar scheme2ddl.jar -url scott/tiger@localhost:1521:ORCL -o C:/temp/oracle-ddl2svn/ 32 | 33 | 34 | will produce directory tree 35 | 36 | views/ 37 | view1.sql 38 | view2.sql 39 | tables/ 40 | table1.sql 41 | functions 42 | /f1.sql 43 | 44 | 45 | More command line options 46 | 47 | java -jar scheme2ddl.jar -help 48 | ... 49 | Options: 50 | -help, -h print this message 51 | -url, DB connection URL 52 | example: scott/tiger@localhost:1521:ORCL 53 | -o, --output, output dir 54 | -p, --parallel, number of parallel thread (default 4) 55 | -s, --schemas, a comma separated list of schemas for processing 56 | (works only if connected to oracle as sysdba) 57 | -c, --config, path to scheme2ddl config file (xml) 58 | -f, --filter, filter for specific DDL objects 59 | every LIKE wildcard can be used 60 | -tf, --type-filter, filter for specific DDL object types 61 | -tfm, --type-filtermode, mode for type filter: include(default) or exclude 62 | --stop-on-warning, stop on getting DDL error (skip by default) 63 | -rsv, replace actual sequence values with 1 64 | --replace-sequence-values, 65 | -tc,--test-connection, test db connection available 66 | -version, print version info and exit 67 | 68 | On Unix platform you can run `scheme2ddl.jar` as executable file: 69 | 70 | chmod +x scheme2ddl.jar 71 | ./scheme2ddl.jar 72 | 73 | 74 | ### How it is work inside? 75 | 76 | 1. First, get list of all user_object to export 77 | 78 | ```sql 79 | select * from user_objects 80 | ``` 81 | 82 | 2. then applying [dbms_metadata.set_transform_param](http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_metada.htm#i1000135) 83 | 3. for every user object invoke [dbms_metadata.get_ddl](http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_metada.htm#i1019414) and [dbms_metadata.get_dependent_ddl](http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14258/d_metada.htm#i1019414) 84 | 4. print every ddl to separate file grouped in folders like tables, views, procedures etc 85 | 86 | *scheme2ddl* build on top of [spring-batch](http://static.springsource.org/spring-batch/) framework. 87 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | 5 | com.googlecode 6 | scheme2ddl 7 | 2.4.5-SNAPSHOT 8 | jar 9 | 10 | 11 | org.springframework.boot 12 | spring-boot-starter-parent 13 | 1.4.2.RELEASE 14 | 15 | 16 | https://github.com/qwazer/scheme2ddl 17 | 18 | 19 | scm:git:git@github.com:qwazer/scheme2ddl.git 20 | scm:git:git@github.com:qwazer/scheme2ddl.git 21 | scm:git:git@github.com:qwazer/scheme2ddl.git 22 | v2.4.4 23 | 24 | 25 | 26 | 27 | 28 | cloudsmith 29 | https://maven.cloudsmith.io/qwazer/repo 30 | 31 | 32 | 33 | 34 | UTF-8 35 | qwazer/maven 36 | scheme2ddl 37 | yourcoverallsprojectrepositorytoken 38 | 39 | 40 | 41 | 42 | 43 | 44 | org.springframework.boot 45 | spring-boot-maven-plugin 46 | 47 | true 48 | 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-release-plugin 53 | 2.5.3 54 | 55 | v@{project.version} 56 | false 57 | release 58 | true 59 | 60 | 61 | 62 | org.apache.maven.plugins 63 | maven-compiler-plugin 64 | 3.8.0 65 | 66 | 11 67 | 11 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-failsafe-plugin 73 | 74 | 75 | org.jacoco 76 | jacoco-maven-plugin 77 | 0.8.4 78 | 79 | 80 | default-prepare-agent 81 | 82 | prepare-agent 83 | 84 | 85 | 86 | default-report 87 | verify 88 | 89 | report 90 | 91 | 92 | 93 | default-check 94 | 95 | check 96 | 97 | 98 | 99 | 100 | 101 | BUNDLE 102 | 103 | 104 | 105 | COMPLEXITY 106 | COVEREDRATIO 107 | 0.50 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | org.eluder.coveralls 118 | coveralls-maven-plugin 119 | 4.3.0 120 | 121 | ${coveralls.repoToken} 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | org.springframework.boot 130 | spring-boot-starter-batch 131 | 132 | 133 | org.apache.tomcat 134 | tomcat-jdbc 135 | 136 | 137 | 138 | 139 | org.springframework.boot 140 | spring-boot-starter-aop 141 | 142 | 143 | org.springframework.boot 144 | spring-boot-starter-logging 145 | 146 | 147 | org.springframework.boot 148 | spring-boot-starter-test 149 | test 150 | 151 | 152 | commons-io 153 | commons-io 154 | 2.14.0 155 | 156 | 157 | javax.annotation 158 | javax.annotation-api 159 | 1.3.1 160 | 161 | 162 | 163 | com.oracle.database.jdbc 164 | ojdbc10 165 | 19.11.0.0 166 | 167 | 168 | 169 | com.oracle.database.nls 170 | orai18n 171 | 21.1.0.0 172 | 173 | 174 | 175 | 176 | org.testng 177 | testng 178 | 6.8 179 | test 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | release 189 | 190 | 191 | 192 | maven-source-plugin 193 | 194 | 195 | attach-sources 196 | 197 | jar 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/AlternateFileNameConstructor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.annotation.Resource; 7 | 8 | import org.springframework.beans.factory.InitializingBean; 9 | import org.springframework.util.Assert; 10 | 11 | import com.googlecode.scheme2ddl.domain.UserObject; 12 | 13 | public class AlternateFileNameConstructor implements IFileNameConstructor, InitializingBean { 14 | public static final String KW_SCHEMA_LOWER = "%s"; 15 | public static final String KW_SCHEMA_UPPER = "%S"; 16 | public static final String KW_TYPE_LOWER = "%a"; 17 | public static final String KW_TYPE_UPPER = "%A"; 18 | public static final String KW_TYPES_PLURAL_LOWER = "%t"; 19 | public static final String KW_TYPES_PLURAL_UPPER = "%T"; 20 | public static final String KW_OBJECTNAME_LOWER = "%o"; 21 | public static final String KW_OBJECTNAME_UPPER = "%O"; 22 | public static final String KW_EXTENSION_LOWER = "%e"; 23 | public static final String KW_EXTENSION_UPPER = "%E"; 24 | 25 | public static final String TEMPLATEDEFAULT = "%t/%o.%e"; 26 | 27 | private String template; 28 | private String templateForSysDBA = "%S/%t/%o.%e"; 29 | private Map extensionMap; 30 | private boolean combinePackage; 31 | private boolean needToReplaceWindowsReservedFileNames = false; 32 | 33 | private boolean sysDbaTmpl = false; 34 | 35 | @Resource 36 | private Map windowsReservedNamesReplacements; 37 | 38 | @Override 39 | public void useSysDBATemplate() { 40 | this.sysDbaTmpl = true; 41 | } 42 | 43 | @Override 44 | public String map2FileName(UserObject userObject) { 45 | String filename = sysDbaTmpl ? templateForSysDBA : template; 46 | 47 | filename = filename.replace(KW_SCHEMA_LOWER, userObject.getSchema().toLowerCase()); 48 | filename = filename.replace(KW_SCHEMA_UPPER, userObject.getSchema().toUpperCase()); 49 | 50 | String typeName = abbreviate(userObject.getType()).replace(" ", "_"); 51 | String typeNameBackup = typeName; 52 | if (combinePackage && typeName.equals("PACKAGE_BODY")) { 53 | typeName = "PACKAGE"; 54 | } 55 | 56 | filename = filename.replace(KW_TYPES_PLURAL_LOWER, pluralize(typeName).toLowerCase()); 57 | filename = filename.replace(KW_TYPES_PLURAL_UPPER, pluralize(typeName).toUpperCase()); 58 | filename = filename.replace(KW_TYPE_LOWER, typeName.toLowerCase()); 59 | filename = filename.replace(KW_TYPE_UPPER, typeName.toUpperCase()); 60 | 61 | if (combinePackage) { 62 | typeName = typeNameBackup; 63 | } 64 | 65 | String userObjectName = userObject.getName(); 66 | if (needToReplaceWindowsReservedFileNames && (windowsReservedNamesReplacements.get(userObjectName) != null)) { 67 | userObjectName = windowsReservedNamesReplacements.get(userObjectName); 68 | } 69 | 70 | filename = filename.replace(KW_OBJECTNAME_LOWER, userObjectName.toLowerCase()); 71 | filename = filename.replace(KW_OBJECTNAME_UPPER, userObjectName.toUpperCase()); 72 | 73 | String extension = extensionMap.get(typeName.toUpperCase()); 74 | if (extension == null) { 75 | extension = extensionMap.get("DEFAULT"); 76 | Assert.state(extension != null, 77 | String.format("No file extension rule for type %s and no DEFAULT rule", typeName.toUpperCase())); 78 | } 79 | filename = filename.replace(KW_EXTENSION_LOWER, extension.toLowerCase()); 80 | filename = filename.replace(KW_EXTENSION_UPPER, extension.toUpperCase()); 81 | 82 | return filename; 83 | } 84 | 85 | @Override 86 | public void afterPropertiesSet() { 87 | if ((this.template == null) || this.template.isBlank()) { 88 | this.template = TEMPLATEDEFAULT; 89 | } 90 | if (extensionMap == null) { 91 | extensionMap = new HashMap<>(); 92 | extensionMap.put("DEFAULT", "sql"); 93 | } 94 | if (windowsReservedNamesReplacements == null) { 95 | needToReplaceWindowsReservedFileNames = false; 96 | } 97 | } 98 | 99 | public void setTemplate(String template) { 100 | this.template = template; 101 | } 102 | 103 | public void setTemplateForSysDBA(String templateForSysDBA) { 104 | this.templateForSysDBA = templateForSysDBA; 105 | } 106 | 107 | public void setExtensionMap(Map extensionMap) { 108 | this.extensionMap = extensionMap; 109 | } 110 | 111 | public void setCombinePackage(boolean combinePackage) { 112 | this.combinePackage = combinePackage; 113 | } 114 | 115 | public void setNeedToReplaceWindowsReservedFileNames(boolean needToReplaceWindowsReservedFileNames) { 116 | this.needToReplaceWindowsReservedFileNames = needToReplaceWindowsReservedFileNames; 117 | } 118 | 119 | private String abbreviate(String type) { 120 | type = type.replace("DATABASE", "DB"); 121 | type = type.replace("database", "db"); 122 | return type; 123 | } 124 | 125 | private String pluralize(String type) { 126 | type = type.toLowerCase(); 127 | if (type.endsWith("x") || type.endsWith("s")) { 128 | return type + "es"; 129 | } else if (type.endsWith("y")) { 130 | return type.substring(0, type.length() - 1) + "ies"; 131 | } else { 132 | return type + "s"; 133 | } 134 | } 135 | 136 | } 137 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/DDLFormatter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.regex.Matcher; 7 | import java.util.regex.Pattern; 8 | 9 | /** 10 | * @author A_Reshetnikov 11 | * @since Date: 18.10.2012 12 | */ 13 | public class DDLFormatter { 14 | 15 | private boolean noFormat; 16 | private boolean sortCreateIndexStatements = true; 17 | private boolean statementOnNewLine; 18 | private boolean isMorePrettyFormat = false; 19 | 20 | static String newline = "\r\n"; //may be use "\n" 21 | 22 | public String formatDDL(String ddl) { 23 | if (noFormat) 24 | return ddl; 25 | 26 | ddl = ddl.trim() + "\n"; 27 | 28 | // replace unix line endings with windows 29 | ddl = ddl.replaceAll("\r\n", "\n"); 30 | ddl = ddl.replaceAll("\n", "\r\n"); 31 | 32 | if (!isMorePrettyFormat) 33 | return ddl; 34 | 35 | /* smart formatting */ 36 | ddl = ddl.replaceAll(newline + "GRANT ", newline + newline + " GRANT "); 37 | ddl = ddl.replaceAll(newline + "COMMENT ", newline + newline + " COMMENT "); 38 | ddl = ddl.replaceAll(newline + " CREATE ", newline + "CREATE "); 39 | ddl = ddl.replaceAll(newline + " ALTER ", newline + "ALTER "); 40 | return ddl; 41 | } 42 | 43 | public void setNoFormat(Boolean noFormat) { 44 | this.noFormat = noFormat; 45 | } 46 | 47 | @Deprecated 48 | public void setStatementOnNewLine(Boolean statementOnNewLine) { 49 | this.statementOnNewLine = statementOnNewLine; 50 | } 51 | 52 | public void setIsMorePrettyFormat(boolean isMorePrettyFormat) { 53 | this.isMorePrettyFormat = isMorePrettyFormat; 54 | } 55 | 56 | public void setSortCreateIndexStatements(boolean sortCreateIndexStatements) { 57 | this.sortCreateIndexStatements = sortCreateIndexStatements; 58 | } 59 | 60 | public String replaceActualSequenceValueWithOne(String res) { 61 | 62 | String output; 63 | Pattern p = Pattern.compile("CREATE SEQUENCE (.*) START WITH (\\d+) (.*)"); 64 | Matcher m = p.matcher(res); 65 | if (m.find()) { 66 | output = m.replaceFirst("CREATE SEQUENCE " + m.group(1) + " START WITH 1 " + m.group(3) ); 67 | if (!"1".equals(m.group(2))) 68 | output = output + newline + "/* -- actual sequence value was replaced by scheme2ddl to 1 */"; 69 | } 70 | else { 71 | output = res; 72 | } 73 | return output; 74 | } 75 | 76 | /** 77 | * Read input string with list of 'create index' statements and, tokenize and sort alphabetically. 78 | * @param dependentDLL -string with list of 'create index' statements 79 | * @return string with sorted alphabetically 'create index' statements 80 | */ 81 | public String sortIndexesInDDL(String dependentDLL) { 82 | if (noFormat || !sortCreateIndexStatements){ 83 | return dependentDLL; 84 | } 85 | String[] parts = dependentDLL.split("(?=CREATE INDEX)|(?=CREATE UNIQUE INDEX)|(?=CREATE BITMAP INDEX)"); 86 | List list = new ArrayList(); 87 | for (String part : parts) { 88 | if (part != null && !part.trim().isEmpty()) { 89 | list.add(part.trim()); 90 | } 91 | } 92 | Collections.sort(list); 93 | StringBuilder s = new StringBuilder(); 94 | String prefix = "\n "; //to preserve formatting of dbms_metadata.get_depended_ddl output 95 | for (String statement:list){ 96 | s.append(prefix); 97 | prefix = "\n"; 98 | s.append(statement); 99 | } 100 | return s.toString(); 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/FileNameConstructor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | import javax.annotation.Resource; 7 | 8 | import org.springframework.beans.factory.InitializingBean; 9 | import org.springframework.util.Assert; 10 | 11 | import com.googlecode.scheme2ddl.domain.UserObject; 12 | 13 | /** 14 | * @author A_Reshetnikov 15 | * @since Date: 01.05.2013 16 | */ 17 | public class FileNameConstructor implements IFileNameConstructor, InitializingBean { 18 | public static final String KW_SCHEMA_LOWER = "schema"; 19 | public static final String KW_TYPE_LOWER = "type"; 20 | public static final String KW_TYPES_PLURAL_LOWER = "types_plural"; 21 | public static final String KW_OBJECTNAME_LOWER = "object_name"; 22 | public static final String KW_EXTENSION_LOWER = "ext"; 23 | public static final String KW_SCHEMA_UPPER = "SCHEMA"; 24 | public static final String KW_TYPE_UPPER = "TYPE"; 25 | public static final String KW_TYPES_PLURAL_UPPER = "TYPES_PLURAL"; 26 | public static final String KW_OBJECTNAME_UPPER = "OBJECT_NAME"; 27 | public static final String KW_EXTENSION_UPPER = "EXT"; 28 | public static final String NONORACLECHAR = "%"; //char not used in Oracle names 29 | public static final String TEMPLATEDEFAULT = "types_plural/object_name.ext"; 30 | 31 | private String template; 32 | private String templateForSysDBA = "SCHEMA/types_plural/object_name.ext"; 33 | private String preparedTemplate; 34 | private Map extensionMap; 35 | private boolean combinePackage; 36 | 37 | private boolean needToReplaceWindowsReservedFileNames = false; 38 | 39 | @Resource 40 | private Map windowsReservedNamesReplacements; 41 | 42 | /** 43 | * prepare template 44 | * replace keywords with %keyword 45 | * 46 | * @param template 47 | * @return 48 | */ 49 | private static String prepareTemplate(String template) { 50 | var keywords = new String[]{ 51 | KW_SCHEMA_LOWER, KW_SCHEMA_UPPER, 52 | KW_TYPES_PLURAL_LOWER, KW_TYPES_PLURAL_UPPER, 53 | KW_OBJECTNAME_LOWER, KW_OBJECTNAME_UPPER, 54 | KW_EXTENSION_LOWER, KW_EXTENSION_UPPER}; 55 | for (int i = 0; i < keywords.length; i++) { 56 | template = template.replace(keywords[i], NONORACLECHAR + keywords[i]); 57 | } 58 | // keyword kw_type_lower is substring of kw_types_plural_lower so we need additional preparing 59 | String typesPluralTail = KW_TYPES_PLURAL_LOWER.replace(KW_TYPE_LOWER, ""); 60 | template = template.replaceAll(KW_TYPE_LOWER + "(?!" + typesPluralTail + ")", NONORACLECHAR + KW_TYPE_LOWER); 61 | typesPluralTail = KW_TYPES_PLURAL_UPPER.replace(KW_TYPE_UPPER, ""); 62 | template = template.replaceAll(KW_TYPE_UPPER + "(?!S_PLURAL)", NONORACLECHAR + KW_TYPE_UPPER); 63 | return template; 64 | } 65 | 66 | @Override 67 | public void useSysDBATemplate() { 68 | template = templateForSysDBA; 69 | afterPropertiesSet(); 70 | } 71 | 72 | public static String abbreviate(String type) { 73 | type = type.replace("DATABASE", "DB"); 74 | type = type.replace("database", "db"); 75 | return type; 76 | } 77 | 78 | public static String pluralaze(String type) { 79 | type = type.toLowerCase(); 80 | if (type.endsWith("x") || type.endsWith("s")) { 81 | return type + "es"; 82 | } 83 | if (type.endsWith("y")) { 84 | return type.substring(0, type.length() - 1) + "ies"; 85 | } 86 | return type + "s"; 87 | } 88 | 89 | public String map2FileName(UserObject userObject) { 90 | String filename = preparedTemplate; 91 | 92 | filename = filename.replace(NONORACLECHAR + KW_SCHEMA_LOWER, userObject.getSchema().toLowerCase()); 93 | filename = filename.replace(NONORACLECHAR + KW_SCHEMA_UPPER, userObject.getSchema().toUpperCase()); 94 | 95 | String typeName = abbreviate(userObject.getType()).replace(" ", "_"); 96 | 97 | String typeName_backup = typeName; 98 | if (combinePackage && typeName.equals("PACKAGE_BODY")) { 99 | typeName = "PACKAGE"; 100 | } 101 | 102 | //process kw_types_plural before kw_type 103 | filename = filename.replace(NONORACLECHAR + KW_TYPES_PLURAL_LOWER, pluralaze(typeName).toLowerCase()); 104 | filename = filename.replace(NONORACLECHAR + KW_TYPES_PLURAL_UPPER, pluralaze(typeName).toUpperCase()); 105 | 106 | filename = filename.replace(NONORACLECHAR + KW_TYPE_LOWER, typeName.toLowerCase()); 107 | filename = filename.replace(NONORACLECHAR + KW_TYPE_UPPER, typeName.toUpperCase()); 108 | 109 | if (combinePackage) { 110 | typeName = typeName_backup; 111 | } 112 | 113 | String userObjectName = userObject.getName(); 114 | 115 | if (needToReplaceWindowsReservedFileNames){ 116 | if (windowsReservedNamesReplacements.get(userObjectName) != null){ 117 | userObjectName = windowsReservedNamesReplacements.get(userObjectName); 118 | } 119 | } 120 | 121 | filename = filename.replace(NONORACLECHAR + KW_OBJECTNAME_LOWER, userObjectName.toLowerCase()); 122 | filename = filename.replace(NONORACLECHAR + KW_OBJECTNAME_UPPER, userObjectName.toUpperCase()); 123 | 124 | String extension = extensionMap.get(typeName.toUpperCase()); 125 | if (extension == null) { 126 | extension = extensionMap.get("DEFAULT"); 127 | Assert.state(extension != null, String.format("No file extension rule for type %s and no DEFAULT rule", typeName.toUpperCase())); 128 | } 129 | filename = filename.replace(NONORACLECHAR + KW_EXTENSION_LOWER, extension.toLowerCase()); 130 | filename = filename.replace(NONORACLECHAR + KW_EXTENSION_UPPER, extension.toUpperCase()); 131 | 132 | return filename; 133 | } 134 | 135 | public void setTemplate(String template) { 136 | this.template = template; 137 | } 138 | 139 | public String getTemplateForSysDBA() { 140 | return templateForSysDBA; 141 | } 142 | 143 | public void setTemplateForSysDBA(String templateForSysDBA) { 144 | this.templateForSysDBA = templateForSysDBA; 145 | } 146 | 147 | //for compability with old configs 148 | public void afterPropertiesSet() { 149 | preparedTemplate = prepareTemplate(this.template == null ? TEMPLATEDEFAULT : template); 150 | 151 | if (extensionMap == null) { 152 | extensionMap = new HashMap<>(); 153 | extensionMap.put("DEFAULT", "sql"); 154 | } 155 | 156 | 157 | if (windowsReservedNamesReplacements == null){ 158 | needToReplaceWindowsReservedFileNames=false; 159 | 160 | } 161 | } 162 | 163 | public void setExtensionMap(Map extensionMap) { 164 | this.extensionMap = extensionMap; 165 | } 166 | 167 | public void setCombinePackage(boolean combinePackage) { 168 | this.combinePackage = combinePackage; 169 | } 170 | 171 | public void setNeedToReplaceWindowsReservedFileNames(boolean needToReplaceWindowsReservedFileNames) { 172 | this.needToReplaceWindowsReservedFileNames = needToReplaceWindowsReservedFileNames; 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/IFileNameConstructor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import com.googlecode.scheme2ddl.domain.UserObject; 4 | 5 | public interface IFileNameConstructor { 6 | /** Switch to SYSDBA naming scheme */ 7 | void useSysDBATemplate(); 8 | /** Returns filename based on UserObject */ 9 | String map2FileName(UserObject userObject); 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/Main.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import com.googlecode.scheme2ddl.dao.ConnectionDao; 4 | import oracle.jdbc.pool.OracleDataSource; 5 | import org.apache.commons.logging.Log; 6 | import org.apache.commons.logging.LogFactory; 7 | import org.springframework.beans.factory.NoSuchBeanDefinitionException; 8 | import org.springframework.beans.factory.support.BeanDefinitionBuilder; 9 | import org.springframework.beans.factory.support.BeanDefinitionRegistry; 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 | import org.springframework.util.Assert; 16 | 17 | import java.sql.SQLException; 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | /** 23 | * @author A_Reshetnikov 24 | * @since Date: 17.10.2012 25 | */ 26 | public class Main { 27 | 28 | private static final Log log = LogFactory.getLog(Main.class); 29 | public static String outputPath = null; 30 | public static int parallelCount = 4; 31 | private static boolean justPrintUsage = false; 32 | private static boolean justPrintVersion = false; 33 | private static boolean justTestConnection = false; 34 | private static boolean skipPublicDbLinks = false; 35 | private static boolean stopOnWarning = false; 36 | private static boolean replaceSequenceValues = false; 37 | private static String customConfigLocation = null; 38 | private static final String defaultConfigLocation = "scheme2ddl.config.xml"; 39 | private static String dbUrl = null; 40 | private static String schemas; 41 | private static boolean isLaunchedByDBA; 42 | private static List schemaList; 43 | private static String objectFilter = "%"; 44 | private static String typeFilter = ""; 45 | private static String typeFilterMode = "include"; 46 | 47 | public static void main(String[] args) throws Exception { 48 | typeFilterMode = "include"; //default is to include any type filter 49 | 50 | collectArgs(args); 51 | if (justPrintUsage) { 52 | printUsage(); 53 | return; 54 | } 55 | if (justPrintVersion) { 56 | printVersion(); 57 | return; 58 | } 59 | 60 | ConfigurableApplicationContext context = loadApplicationContext(); 61 | 62 | modifyContext(context); 63 | 64 | validateContext(context); 65 | 66 | if (justTestConnection) { 67 | testDBConnection(context); 68 | } else { 69 | // todo remove this System.out.println and move this params to bean params, not job params 70 | // System.out.println("DDL object filter: " + objectFilter); 71 | // System.out.println("DDL type filter: " + typeFilter); 72 | // System.out.println("DDL type filter mode: " + typeFilterMode); 73 | new UserObjectJobRunner().start(context, isLaunchedByDBA, objectFilter.toLowerCase(), typeFilter.toUpperCase(), typeFilterMode.toLowerCase()); 74 | } 75 | } 76 | 77 | private static void testDBConnection(ConfigurableApplicationContext context) throws SQLException { 78 | ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); 79 | OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); 80 | if (connectionDao.isConnectionAvailable()) { 81 | System.out.println("OK success connection to " + dataSource.getURL()); 82 | } else { 83 | System.out.println("FAIL connect to " + dataSource.getURL()); //todo unreacheble statement 84 | } 85 | } 86 | 87 | private static void modifyContext(ConfigurableApplicationContext context) { 88 | if (dbUrl != null) { 89 | String url = "jdbc:oracle:thin:" + dbUrl; 90 | String user = extractUserfromDbUrl(dbUrl); 91 | String password = extractPasswordfromDbUrl(dbUrl); 92 | OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); 93 | dataSource.setURL(url); 94 | // for OracleDataSource in connectionCachingEnabled mode need explicitly set user and password 95 | dataSource.setUser(user); 96 | dataSource.setPassword(password); 97 | } 98 | if (outputPath != null) { 99 | UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); 100 | writer.setOutputPath(outputPath); 101 | } 102 | if (parallelCount > 0) { 103 | SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context.getBean("taskExecutor"); 104 | taskExecutor.setConcurrencyLimit(parallelCount); 105 | } 106 | String userName = ((OracleDataSource) context.getBean("dataSource")).getUser(); 107 | isLaunchedByDBA = userName.toLowerCase().matches(".+as +sysdba *"); 108 | if (!isLaunchedByDBA){ 109 | ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); 110 | isLaunchedByDBA = connectionDao.hasSelectCatalogRole(); //todo rename isLaunchedByDBA -> processForeignSchema 111 | } 112 | //process schemas 113 | processSchemas(context); 114 | 115 | IFileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); //will create new one if not exist 116 | if (isLaunchedByDBA) { 117 | fileNameConstructor.useSysDBATemplate(); 118 | } 119 | 120 | if (stopOnWarning){ 121 | UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); 122 | processor.setStopOnWarning(stopOnWarning); 123 | } 124 | if (replaceSequenceValues){ 125 | UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); 126 | processor.setReplaceSequenceValues(replaceSequenceValues); 127 | } 128 | 129 | } 130 | 131 | private static void processSchemas(ConfigurableApplicationContext context) { 132 | List listFromContext = retrieveSchemaListFromContext(context); 133 | if (schemas == null) { 134 | if (listFromContext.size() == 0) { 135 | //get default schema from username 136 | schemaList = extactSchemaListFromUserName(context); 137 | } else { 138 | if (isLaunchedByDBA) 139 | schemaList = new ArrayList(listFromContext); 140 | else { 141 | log.warn("Ignore 'schemaList' from advanced config, because oracle user is not connected as sys dba"); 142 | schemaList = extactSchemaListFromUserName(context); 143 | } 144 | } 145 | } else { 146 | String[] array = schemas.split(","); 147 | schemaList = new ArrayList(Arrays.asList(array)); 148 | } 149 | 150 | listFromContext.clear(); 151 | for (String s : schemaList) { 152 | listFromContext.add(s.toUpperCase().trim()); 153 | } 154 | 155 | //for compabality with old config 156 | if (listFromContext.size() == 1) { 157 | try { 158 | UserObjectReader userObjectReader = (UserObjectReader) context.getBean("reader"); 159 | userObjectReader.setSchemaName(listFromContext.get(0)); 160 | } catch (ClassCastException e) { 161 | // this mean that new config used, nothing to do 162 | } 163 | } 164 | } 165 | 166 | private static List extactSchemaListFromUserName(ConfigurableApplicationContext context) { 167 | OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); 168 | String schemaName = dataSource.getUser().split(" ")[0]; 169 | List list = new ArrayList(); 170 | list.add(schemaName); 171 | return list; 172 | } 173 | 174 | /** 175 | * @param context 176 | * @return existing bean 'schemaList', if this exists, or create and register new bean 177 | */ 178 | private static List retrieveSchemaListFromContext(ConfigurableApplicationContext context) { 179 | List list; 180 | try { 181 | list = (List) context.getBean("schemaList"); 182 | } catch (NoSuchBeanDefinitionException e) { 183 | DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); 184 | beanFactory.registerBeanDefinition("schemaList", BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class).getBeanDefinition()); 185 | list = (List) context.getBean("schemaList"); 186 | } 187 | return list; 188 | } 189 | 190 | /** 191 | * @param context 192 | * @return existing bean 'fileNameConstructor', if this exists, or create and register new bean 193 | */ 194 | private static IFileNameConstructor retrieveFileNameConstructor(ConfigurableApplicationContext context) { 195 | IFileNameConstructor fileNameConstructor; 196 | try { 197 | fileNameConstructor = (IFileNameConstructor) context.getBean("fileNameConstructor"); 198 | } catch (NoSuchBeanDefinitionException e) { 199 | BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) context.getBeanFactory(); 200 | beanFactory.registerBeanDefinition("fileNameConstructor", BeanDefinitionBuilder.rootBeanDefinition(FileNameConstructor.class).getBeanDefinition()); 201 | fileNameConstructor = (IFileNameConstructor) context.getBean("fileNameConstructor"); 202 | UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context.getBean("processor"); 203 | userObjectProcessor.setFileNameConstructor(fileNameConstructor); 204 | } 205 | return fileNameConstructor; 206 | } 207 | 208 | private static String extractUserfromDbUrl(String dbUrl) { 209 | return dbUrl.split("/")[0]; 210 | } 211 | 212 | private static String extractPasswordfromDbUrl(String dbUrl) { 213 | //scott/tiger@localhost:1521:ORCL 214 | return dbUrl.split("/|@")[1]; 215 | } 216 | 217 | private static void validateContext(ConfigurableApplicationContext context) { 218 | String userName = ((OracleDataSource) context.getBean("dataSource")).getUser().toUpperCase(); 219 | List schemaList = (List) context.getBean("schemaList"); 220 | Assert.state(isLaunchedByDBA || schemaList.size() == 1, "Cannot process multiply schemas if oracle user is not connected as sysdba"); 221 | if (!isLaunchedByDBA) { 222 | String schemaName = schemaList.get(0).toUpperCase(); 223 | Assert.state(userName.startsWith(schemaName), 224 | String.format("Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", schemaName, userName.toLowerCase())); 225 | } 226 | } 227 | 228 | /** 229 | * Prints the usage information for this class to System.out. 230 | */ 231 | private static void printUsage() { 232 | String lSep = System.getProperty("line.separator"); 233 | StringBuffer msg = new StringBuffer(); 234 | msg.append("java -jar scheme2ddl.jar [-url ] [-o] [-s]" + lSep); 235 | msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + lSep); 236 | msg.append("internally call to dbms_metadata.get_ddl " + lSep); 237 | msg.append("more config options in scheme2ddl.config.xml " + lSep); 238 | msg.append("Options: " + lSep); 239 | msg.append(" -help, -h print this message" + lSep); 240 | // msg.append(" -verbose, -v be extra verbose" + lSep); 241 | msg.append(" -url, DB connection URL" + lSep); 242 | msg.append(" example: scott/tiger@localhost:1521:ORCL" + lSep); 243 | 244 | msg.append(" -o, --output, output dir" + lSep); 245 | msg.append(" -p, --parallel, number of parallel thread (default 4)" + lSep); 246 | msg.append(" -s, --schemas, a comma separated list of schemas for processing" + lSep); 247 | msg.append(" (works only if connected to oracle as sysdba)" + lSep); 248 | msg.append(" -c, --config, path to scheme2ddl config file (xml)" + lSep); 249 | msg.append(" -f, --filter, filter for specific DDL objects" + lSep); 250 | msg.append(" every LIKE wildcard can be used" + lSep); 251 | msg.append(" -tf, --type-filter, filter for specific DDL object types" + lSep); 252 | msg.append(" -tfm, --type-filtermode, mode for type filter: include(default) or exclude" + lSep); 253 | msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + lSep); 254 | msg.append(" -rsv, replace actual sequence values with 1 " + lSep); 255 | msg.append(" --replace-sequence-values, " + lSep); 256 | msg.append(" -tc,--test-connection, test db connection available" + lSep); 257 | msg.append(" -version, print version info and exit" + lSep); 258 | System.out.println(msg.toString()); 259 | } 260 | 261 | private static void printVersion() { 262 | System.out.println("scheme2ddl version " + getVersion()); 263 | } 264 | 265 | private static String getVersion() { 266 | return Main.class.getPackage().getImplementationVersion(); 267 | } 268 | 269 | private static void collectArgs(String[] args) throws Exception { 270 | 271 | for (int i = 0; i < args.length; i++) { 272 | String arg = args[i]; 273 | if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { 274 | justPrintUsage = true; 275 | } else if (arg.equals("-url") || arg.equals("--url")) { 276 | dbUrl = args[i + 1]; 277 | //check for as sysdba connection 278 | if (args.length >= i + 3) { 279 | if ((args[i + 2].toLowerCase().equals("as")) && 280 | (args[i + 3].toLowerCase().startsWith("sysdba"))) { 281 | //isLaunchedByDBA = true; 282 | dbUrl = args[i + 1] + " " + args[i + 2] + " " + args[i + 3]; 283 | i = i + 2; 284 | } 285 | } 286 | i++; 287 | } else if (arg.equals("-o") || arg.equals("-output") || arg.equals("--output")) { 288 | outputPath = args[i + 1]; 289 | i++; 290 | } else if (arg.equals("-s") || arg.equals("-schemas") || arg.equals("--schemas")) { 291 | schemas = args[i + 1]; 292 | i++; 293 | } else if (arg.equals("-p") || arg.equals("--parallel") || arg.equals("-parallel")) { 294 | parallelCount = Integer.parseInt(args[i + 1]); 295 | i++; 296 | } else if (arg.equals("-tc") || arg.equals("--test-connection")) { 297 | justTestConnection = true; 298 | } else if (arg.equals("--stop-on-warning")) { 299 | stopOnWarning = true; 300 | } else if ((arg.equals("-rsv") || arg.equals("--replace-sequence-values"))) { 301 | replaceSequenceValues = true; 302 | } else if (arg.equals("-c") || arg.equals("--config")) { 303 | customConfigLocation = args[i + 1]; 304 | i++; 305 | } else if (arg.equals("-f") || arg.equals("--filter")) { 306 | objectFilter = args[i + 1]; 307 | //remove single quotes if given 308 | if (objectFilter.length() > 0 && 309 | objectFilter.charAt(objectFilter.length()-1)=='\'' && 310 | objectFilter.charAt(0)=='\'') { 311 | objectFilter = objectFilter.substring(1, objectFilter.length()-1); 312 | } 313 | i++; 314 | } else if (arg.equals("-tf") || arg.equals("--type-filter")) { 315 | typeFilter = args[i + 1]; 316 | i++; 317 | } else if (arg.equals("-tfm") || arg.equals("--type-filtermode")) { 318 | typeFilterMode = args[i + 1]; 319 | i++; 320 | //default to include if anything except include or exclude is given as argument 321 | if (!typeFilterMode.equals("include") && !typeFilterMode.equals("exclude")) { 322 | typeFilterMode = "include"; 323 | } 324 | } else if (arg.equals("-version")) { 325 | justPrintVersion = true; 326 | } else if (arg.startsWith("-")) { 327 | // we don't have any more args to recognize! 328 | String msg = "Unknown argument: " + arg; 329 | System.err.println(msg); 330 | printUsage(); 331 | throw new Exception(msg); 332 | } 333 | } 334 | } 335 | 336 | private static ConfigurableApplicationContext loadApplicationContext() { 337 | ConfigurableApplicationContext context = null; 338 | if (customConfigLocation != null) 339 | context = new FileSystemXmlApplicationContext(customConfigLocation); 340 | else 341 | context = new ClassPathXmlApplicationContext(defaultConfigLocation); 342 | return context; 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/TypeNamesUtil.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | /** 4 | * Util for converting type names between 'package DBMS_METADATA' and 'table USER_OBJECTS' formats 5 | * @author A_Reshetnikov 6 | * @since Date: 30.04.2013 7 | */ 8 | public class TypeNamesUtil { 9 | 10 | /** 11 | * Oracle types in user_table without underscore, for example PACKAGE BODY 12 | * but in DBMS_METADATA with underscore PACKAGE_BODY 13 | * @param type - type name from user_table and advanced config 14 | * 15 | * @return type name for using in DBMS_METADATA package 16 | */ 17 | public static String map2TypeForDBMS(String type) { 18 | if (type.contains("DATABASE LINK")) 19 | return "DB_LINK"; 20 | if (type.equals("JOB")) 21 | return "PROCOBJ"; 22 | if (type.equals("SCHEDULE")) 23 | return "PROCOBJ"; 24 | if (type.equals("PROGRAM")) 25 | return "PROCOBJ"; 26 | if (type.equals("PACKAGE")) 27 | return "PACKAGE_SPEC"; 28 | return type.replace(" ", "_"); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/UserObjectJobRunner.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import oracle.jdbc.pool.OracleDataSource; 4 | import org.apache.commons.logging.Log; 5 | import org.apache.commons.logging.LogFactory; 6 | import org.springframework.batch.core.*; 7 | import org.springframework.batch.core.launch.JobLauncher; 8 | import org.springframework.beans.factory.config.AutowireCapableBeanFactory; 9 | import org.springframework.context.ConfigurableApplicationContext; 10 | import org.springframework.util.Assert; 11 | 12 | import java.util.List; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author A_Reshetnikov 17 | * @since Date: 22.10.2012 18 | */ 19 | public class UserObjectJobRunner { 20 | protected static final Log logger = LogFactory.getLog(UserObjectJobRunner.class); 21 | private JobLauncher launcher; 22 | 23 | int start(ConfigurableApplicationContext context, boolean launchedByDBA, String objectFilter, String typeFilter, String typeFilterMode) throws Exception { 24 | try { 25 | context.getAutowireCapableBeanFactory().autowireBeanProperties(this, 26 | AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, false); 27 | 28 | Assert.state(launcher != null, "A JobLauncher must be provided. Please add one to the configuration."); 29 | Job job = (Job) context.getBean("job1"); 30 | 31 | List schemaList = (List) context.getBean("schemaList"); 32 | Assert.state(schemaList != null && schemaList.size()!=0, "schemaList must be provided. Please add one to the configuration. "); 33 | 34 | logger.info(String.format("Will try to process schema %s %s ", schemaList.size() > 1 ? "list" : "", schemaList)); 35 | 36 | for (String schemaName : schemaList){ 37 | JobParametersBuilder parametersBuilder = new JobParametersBuilder(); 38 | parametersBuilder.addString("schemaName", schemaName); 39 | parametersBuilder.addString("launchedByDBA", Boolean.toString(launchedByDBA)); 40 | parametersBuilder.addString("objectFilter", objectFilter); 41 | parametersBuilder.addString("typeFilter", typeFilter); 42 | parametersBuilder.addString("typeFilterMode", typeFilterMode); 43 | JobParameters jobParameters = parametersBuilder.toJobParameters(); 44 | logger.trace(String.format("Start spring batch job with parameters %s", jobParameters)); 45 | JobExecution jobExecution = launcher.run(job, jobParameters); 46 | //write some log 47 | writeJobExecutionStatus(jobExecution, jobParameters); 48 | if (jobExecution.getStatus().isUnsuccessful()){ 49 | throw new Exception(String.format("Job %s unsuccessful", jobParameters)); 50 | } 51 | } 52 | 53 | logger.info(String.format("Processing schema %s %s completed ", schemaList.size() > 1 ? "list" : "", schemaList)); 54 | 55 | return 1; 56 | 57 | } catch (Exception e) { 58 | String message = "Job Terminated in error: " + e.getMessage(); 59 | logger.error(message, e); 60 | throw e; 61 | } finally { 62 | if (context != null) { 63 | context.close(); 64 | } 65 | } 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/UserObjectProcessor.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import com.googlecode.scheme2ddl.dao.UserObjectDao; 4 | import com.googlecode.scheme2ddl.domain.UserObject; 5 | import com.googlecode.scheme2ddl.exception.CannotGetDDLException; 6 | import com.googlecode.scheme2ddl.exception.NonSkippableException; 7 | import org.apache.commons.logging.Log; 8 | import org.apache.commons.logging.LogFactory; 9 | import org.springframework.batch.item.ItemProcessor; 10 | 11 | import java.util.Map; 12 | import java.util.Set; 13 | 14 | import static com.googlecode.scheme2ddl.TypeNamesUtil.map2TypeForDBMS; 15 | 16 | /** 17 | * @author A_Reshetnikov 18 | * @since Date: 17.10.2012 19 | */ 20 | public class UserObjectProcessor implements ItemProcessor { 21 | 22 | private static final Log log = LogFactory.getLog(UserObjectProcessor.class); 23 | private UserObjectDao userObjectDao; 24 | private DDLFormatter ddlFormatter; 25 | private IFileNameConstructor fileNameConstructor; 26 | private Map> excludes; 27 | private Map> dependencies; 28 | private boolean stopOnWarning; 29 | private boolean replaceSequenceValues; 30 | 31 | public UserObject process(UserObject userObject) throws Exception { 32 | 33 | if (needToExclude(userObject)) { 34 | log.debug(String.format("Skipping processing of user object %s ", userObject)); 35 | return null; 36 | } 37 | userObject.setDdl(map2Ddl(userObject)); 38 | userObject.setFileName(fileNameConstructor.map2FileName(userObject)); 39 | return userObject; 40 | } 41 | 42 | private boolean needToExclude(UserObject userObject) { 43 | if (excludes == null || excludes.size() == 0) return false; 44 | if (excludes.get("*") != null) { 45 | for (String pattern : excludes.get("*")) { 46 | if (matchesByPattern(userObject.getName(), pattern)) 47 | return true; 48 | } 49 | } 50 | for (String typeName : excludes.keySet()) { 51 | if (typeName.equalsIgnoreCase(userObject.getType())) { 52 | if (excludes.get(typeName) == null) return true; 53 | for (String pattern : excludes.get(typeName)) { 54 | if (matchesByPattern(userObject.getName(), pattern)) 55 | return true; 56 | } 57 | } 58 | } 59 | return false; 60 | } 61 | 62 | private boolean matchesByPattern(String s, String pattern) { 63 | pattern = pattern.replace("*", "(.*)").toLowerCase(); 64 | return s.toLowerCase().matches(pattern); 65 | } 66 | 67 | private String map2Ddl(UserObject userObject) throws CannotGetDDLException, NonSkippableException { 68 | try { 69 | if (userObject.getType().equals("DBMS JOB")) { 70 | return ddlFormatter.formatDDL(userObjectDao.findDbmsJobDDL(userObject.getName())); 71 | } 72 | if (userObject.getType().equals("PUBLIC DATABASE LINK")) { 73 | return ddlFormatter.formatDDL(userObjectDao.findDDLInPublicScheme(map2TypeForDBMS(userObject.getType()), userObject.getName())); 74 | } 75 | if (userObject.getType().equals("REFRESH_GROUP")) { 76 | return ddlFormatter.formatDDL(userObjectDao.findRefGroupDDL(userObject.getType(), userObject.getName())); 77 | } 78 | StringBuilder res = new StringBuilder(userObjectDao.findPrimaryDDL(map2TypeForDBMS(userObject.getType()), userObject.getName())); 79 | if (userObject.getType().equals("SEQUENCE") && replaceSequenceValues) { 80 | res = new StringBuilder(ddlFormatter.replaceActualSequenceValueWithOne(res.toString())); 81 | } 82 | Set dependedTypes = dependencies.get(userObject.getType()); 83 | if (dependedTypes != null) { 84 | for (String dependedType : dependedTypes) { 85 | String dependentDLL = userObjectDao.findDependentDLLByTypeName(dependedType, userObject.getName()); 86 | if (dependedType.equals("INDEX")){ 87 | dependentDLL = ddlFormatter.sortIndexesInDDL(dependentDLL); 88 | } 89 | res.append(dependentDLL); 90 | } 91 | } 92 | return ddlFormatter.formatDDL(res.toString()); 93 | } catch (Exception e) { 94 | log.warn(String.format("Cannot get DDL for object %s with error message %s", userObject, e.getMessage())); 95 | if (stopOnWarning) { 96 | throw new NonSkippableException(e); 97 | } else 98 | throw new CannotGetDDLException(e); 99 | } 100 | 101 | } 102 | 103 | public void setExcludes(Map excludes) { 104 | this.excludes = excludes; 105 | } 106 | 107 | public void setDependencies(Map dependencies) { 108 | this.dependencies = dependencies; 109 | } 110 | 111 | public void setUserObjectDao(UserObjectDao userObjectDao) { 112 | this.userObjectDao = userObjectDao; 113 | } 114 | 115 | public void setDdlFormatter(DDLFormatter ddlFormatter) { 116 | this.ddlFormatter = ddlFormatter; 117 | } 118 | 119 | public void setFileNameConstructor(IFileNameConstructor fileNameConstructor) { 120 | this.fileNameConstructor = fileNameConstructor; 121 | } 122 | 123 | public void setReplaceSequenceValues(boolean replaceSequenceValues) { 124 | this.replaceSequenceValues = replaceSequenceValues; 125 | } 126 | 127 | public void setStopOnWarning(boolean stopOnWarning) { 128 | this.stopOnWarning = stopOnWarning; 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/UserObjectReader.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | import com.googlecode.scheme2ddl.dao.UserObjectDao; 4 | import com.googlecode.scheme2ddl.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.Bean; 14 | import org.springframework.context.annotation.Scope; 15 | import org.springframework.stereotype.Component; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * @author A_Reshetnikov 21 | * @since Date: 17.10.2012 22 | */ 23 | public class UserObjectReader implements ItemReader { 24 | 25 | private static final Log log = LogFactory.getLog(UserObjectReader.class); 26 | private List list; 27 | 28 | @Autowired 29 | private UserObjectDao userObjectDao; 30 | private boolean processPublicDbLinks = false; 31 | private boolean processDmbsJobs = false; 32 | private boolean processConstraint = false; 33 | 34 | @Value("#{jobParameters['schemaName']}") 35 | private String schemaName; 36 | 37 | 38 | public synchronized UserObject read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException { 39 | if (list == null) { 40 | fillList(); 41 | log.info(String.format("Found %s items for processing in schema %s", list.size(), schemaName)); 42 | } 43 | if (list.size() == 0) { 44 | return null; 45 | } else 46 | return list.remove(0); 47 | } 48 | 49 | private synchronized void fillList() { 50 | log.info(String.format("Start getting of user object list in schema %s for processing", schemaName)); 51 | list = userObjectDao.findListForProccessing(); 52 | if (processPublicDbLinks) { 53 | list.addAll(userObjectDao.findPublicDbLinks()); 54 | } 55 | if (processDmbsJobs) { 56 | list.addAll(userObjectDao.findDmbsJobs()); 57 | } 58 | if (processConstraint){ 59 | list.addAll(userObjectDao.findConstaints()); 60 | } 61 | 62 | } 63 | 64 | public void setUserObjectDao(UserObjectDao userObjectDao) { 65 | this.userObjectDao = userObjectDao; 66 | } 67 | 68 | public void setProcessPublicDbLinks(boolean processPublicDbLinks) { 69 | this.processPublicDbLinks = processPublicDbLinks; 70 | } 71 | 72 | public void setProcessDmbsJobs(boolean processDmbsSchedulerJobs) { 73 | this.processDmbsJobs = processDmbsSchedulerJobs; 74 | } 75 | 76 | public void setProcessConstraint(boolean processConstraint) { 77 | this.processConstraint = processConstraint; 78 | } 79 | 80 | public void setSchemaName(String schemaName) { 81 | this.schemaName = schemaName; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl; 2 | 3 | 4 | import com.googlecode.scheme2ddl.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.item.ItemWriter; 10 | 11 | import java.io.File; 12 | import java.nio.charset.Charset; 13 | import java.util.List; 14 | 15 | /** 16 | * @author A_Reshetnikov 17 | * @since Date: 16.10.2012 18 | */ 19 | public class UserObjectWriter implements ItemWriter { 20 | 21 | private static final Log log = LogFactory.getLog(UserObjectWriter.class); 22 | private String outputPath; 23 | private String encoding = "utf-8"; 24 | 25 | public void write(List data) throws Exception { 26 | if (data.size() > 0) { 27 | writeUserObject(data.get(0)); 28 | } 29 | } 30 | 31 | public void writeUserObject(UserObject userObject) throws Exception { 32 | String absoluteFileName = outputPath + "/" + userObject.getFileName(); 33 | absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); 34 | File file = new File(absoluteFileName); 35 | FileUtils.writeStringToFile(file, userObject.getDdl(), Charset.forName(encoding)); 36 | log.info(String.format("Saved %s %s.%s to file %s", 37 | userObject.getType().toLowerCase(), 38 | userObject.getSchema().toLowerCase(), 39 | userObject.getName().toLowerCase(), 40 | file.getAbsolutePath())); 41 | } 42 | 43 | public void setEncoding(String encoding) { 44 | this.encoding = encoding; 45 | } 46 | 47 | public void setOutputPath(String outputPath) { 48 | this.outputPath = outputPath; 49 | } 50 | 51 | @Deprecated 52 | public void setFileNameCase(String fileNameCase) { 53 | //for compatability with 2.1.x config 54 | } 55 | @Deprecated 56 | public void setIncludeSchemaName(boolean includeSchemaName) { 57 | //for compatability with 2.1.x config 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/googlecode/scheme2ddl/aspect/StatAspect.java: -------------------------------------------------------------------------------- 1 | package com.googlecode.scheme2ddl.aspect; 2 | 3 | 4 | import com.googlecode.scheme2ddl.domain.UserObject; 5 | import com.googlecode.scheme2ddl.exception.CannotGetDDLException; 6 | import org.aspectj.lang.annotation.*; 7 | import org.springframework.batch.core.Job; 8 | import org.springframework.batch.core.JobParameters; 9 | 10 | import java.util.*; 11 | 12 | /** 13 | * Collect statistics about skipped objects and 14 | * print detailed report after end of schema processing 15 | * 16 | * @author A_Reshetnikov 17 | * @since Date: 03.07.2013 18 | */ 19 | @Aspect 20 | public class StatAspect { 21 | 22 | private List listExludedByConfig; 23 | private List listSkippedBySQLError; 24 | 25 | public StatAspect() { 26 | this.listExludedByConfig = Collections.synchronizedList(new ArrayList()); 27 | this.listSkippedBySQLError = Collections.synchronizedList(new ArrayList()); 28 | } 29 | 30 | @AfterReturning(pointcut = "execution(* com.googlecode.scheme2ddl.UserObjectProcessor.process(..)) &&" 31 | + "args(userObject)", 32 | returning = "retVal") 33 | public void exludedByConfig(UserObject userObject, Object retVal) { 34 | if (retVal == null) { 35 | listExludedByConfig.add(userObject); 36 | } 37 | } 38 | 39 | @AfterThrowing(pointcut = "execution(* com.googlecode.scheme2ddl.UserObjectProcessor.process(..)) &&" 40 | + "args(userObject)", 41 | throwing = "ex") 42 | public void skippedBySQLError(UserObject userObject, CannotGetDDLException ex) { 43 | listSkippedBySQLError.add(userObject); 44 | } 45 | 46 | @Before("execution(* org.springframework.batch.core.launch.JobLauncher.run(..))") 47 | public void clearStatistic() { 48 | this.listExludedByConfig = Collections.synchronizedList(new ArrayList()); 49 | this.listSkippedBySQLError = Collections.synchronizedList(new ArrayList()); 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 | --------------------------------------------------------------------------------