├── .idea
├── .gitignore
├── compiler.xml
├── encodings.xml
├── jarRepositories.xml
├── misc.xml
└── vcs.xml
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── pw
│ │ └── dcp
│ │ ├── DatabaseChangePlatformApplication.java
│ │ ├── DatabaseType
│ │ └── Enum.java
│ │ ├── service
│ │ └── SchemaCompareService.java
│ │ └── utils
│ │ └── DatabaseSchemaComparator.java
└── resources
│ └── application.properties
└── test
└── java
└── com
└── pw
└── dcp
└── DatabaseChangePlatformApplicationTests.java
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SchemaDiff
2 |
3 | **SchemaDiff** is a powerful tool designed to compare and analyze the differences between database schemas, making it easier to manage and migrate databases in various environments. It supports different types of databases including Oracle, MySQL, PostgreSQL, and more.
4 |
5 | ## Features
6 |
7 | - **Cross-Platform Comparison**: Compare database schemas across different database types (e.g., Oracle to MySQL, PostgreSQL to MySQL, etc.).
8 | - **Comprehensive Diffing**: Supports table structures, indexes, stored procedures, sequences, triggers, and more.
9 | - **User-Friendly Interface**: Easy to use and integrates well with existing workflows.
10 | - **Efficient Reports**: Generate detailed reports on schema differences to simplify migration or database synchronization.
11 | - **Customizable**: Highly configurable to suit various project needs and database configurations.
12 |
13 | ## Supported Databases
14 |
15 | - Oracle
16 | - MySQL
17 | - PostgreSQL
18 | - SQL Server
19 | - DB2
20 | - Sybase
21 |
22 | ## Installation
23 |
24 | ### Requirements
25 |
26 | - Java 8 or later
27 | - Maven
28 |
29 | ### Steps to Install
30 |
31 | 1. Clone the repository:
32 | ```bash
33 | git clone https://github.com/your-username/SchemaDiff.git
34 |
35 | 2. Navigate to the project directory:
36 | ```bash
37 | cd SchemaDiff
38 |
39 | 3. Build the project using Maven:
40 | ```bash
41 | mvn clean install
42 |
43 | ### Usage
44 |
45 | To compare two database schemas, run the following command:
46 | ```bash
47 | java -jar SchemaDiff.jar
48 |
49 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | org.springframework.boot
7 | spring-boot-starter-parent
8 | 2.7.2
9 |
10 |
11 | com.pw
12 | dcp
13 | 0.0.1-SNAPSHOT
14 | Database-Change-Platform
15 | Demo project for Spring Boot
16 |
17 | 17
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter
23 |
24 |
25 |
26 | org.springframework.boot
27 | spring-boot-devtools
28 | runtime
29 | true
30 |
31 |
32 | org.projectlombok
33 | lombok
34 | true
35 |
36 |
37 |
38 |
39 | com.github.jsqlparser
40 | jsqlparser
41 | 3.1
42 |
43 |
44 |
45 |
46 | org.springframework.boot
47 | spring-boot-starter-test
48 | test
49 |
50 |
51 |
52 |
53 |
54 |
55 | org.springframework.boot
56 | spring-boot-maven-plugin
57 |
58 |
59 |
60 | org.projectlombok
61 | lombok
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/src/main/java/com/pw/dcp/DatabaseChangePlatformApplication.java:
--------------------------------------------------------------------------------
1 | package com.pw.dcp;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class DatabaseChangePlatformApplication {
8 |
9 | public static void main(String[] args) {
10 | SpringApplication.run(DatabaseChangePlatformApplication.class, args);
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/pw/dcp/DatabaseType/Enum.java:
--------------------------------------------------------------------------------
1 | package com.pw.dcp.DatabaseType;
2 |
3 | public class Enum {
4 | String Oracle = "Oracle";
5 | String MySQL = "MySQL";
6 | String SQLServer = "SQLServer";
7 | String PostgreSQL = "PostgreSQL";
8 | String DB2 = "DB2";
9 | String SQLite = "SQLite";
10 | String H2 = "H2";
11 | String Sybase = "Sybase";
12 | String MariaDB = "MariaDB";
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/pw/dcp/service/SchemaCompareService.java:
--------------------------------------------------------------------------------
1 | package com.pw.dcp.service;
2 |
3 | import org.springframework.stereotype.Service;
4 |
5 | @Service
6 | public class SchemaCompareService {
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/pw/dcp/utils/DatabaseSchemaComparator.java:
--------------------------------------------------------------------------------
1 | package com.pw.dcp.utils;
2 |
3 | import java.sql.*;
4 |
5 | public class DatabaseSchemaComparator {
6 |
7 |
8 | public static void compareSchemas(String usernameDB1, String usernameDB2) {
9 | try (Connection connectionDB1 = DriverManager.getConnection(JDBC_URL_DB1, USER_DB1, PASSWORD_DB1);
10 | Connection connectionDB2 = DriverManager.getConnection(JDBC_URL_DB2, USER_DB2, PASSWORD_DB2)) {
11 |
12 | compareTables(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
13 | compareTriggers(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
14 | compareSequences(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
15 | compareProcedures(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
16 | compareIndexes(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
17 | compareForeignKeys(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
18 | compareViews(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
19 | compareConstraints(connectionDB1, usernameDB1, connectionDB2, usernameDB2);
20 |
21 | } catch (SQLException e) {
22 | e.printStackTrace();
23 | }
24 | }
25 |
26 |
27 | private static void compareTables(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
28 | compareResults(
29 | executeQuery(connectionDB1, "SELECT table_name, column_name, data_type, data_length, nullable FROM all_tab_columns WHERE owner = '" + usernameDB1 + "' ORDER BY table_name, column_id"),
30 | executeQuery(connectionDB2, "SELECT table_name, column_name, data_type, data_length, nullable FROM all_tab_columns WHERE owner = '" + usernameDB2 + "' ORDER BY table_name, column_id")
31 | );
32 | }
33 |
34 |
35 | private static void compareTriggers(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
36 | compareResults(
37 | executeQuery(connectionDB1, "SELECT trigger_name, table_name, trigger_type, triggering_event FROM all_triggers WHERE table_owner = '" + usernameDB1 + "' ORDER BY trigger_name"),
38 | executeQuery(connectionDB2, "SELECT trigger_name, table_name, trigger_type, triggering_event FROM all_triggers WHERE table_owner = '" + usernameDB2 + "' ORDER BY trigger_name")
39 | );
40 | }
41 |
42 | private static void compareSequences(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
43 | compareResults(
44 | executeQuery(connectionDB1, "SELECT sequence_name, min_value, max_value, increment_by, last_number FROM all_sequences WHERE sequence_owner = '" + usernameDB1 + "' ORDER BY sequence_name"),
45 | executeQuery(connectionDB2, "SELECT sequence_name, min_value, max_value, increment_by, last_number FROM all_sequences WHERE sequence_owner = '" + usernameDB2 + "' ORDER BY sequence_name")
46 | );
47 | }
48 |
49 | private static void compareProcedures(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
50 | compareResults(
51 | executeQuery(connectionDB1, "SELECT object_name, procedure_name, object_type, arguments FROM all_procedures WHERE owner = '" + usernameDB1 + "' ORDER BY object_name, procedure_name"),
52 | executeQuery(connectionDB2, "SELECT object_name, procedure_name, object_type, arguments FROM all_procedures WHERE owner = '" + usernameDB2 + "' ORDER BY object_name, procedure_name")
53 | );
54 | }
55 |
56 | private static void compareIndexes(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
57 | compareResults(
58 | executeQuery(connectionDB1, "SELECT index_name, table_name, uniqueness, column_name FROM all_ind_columns WHERE table_owner = '" + usernameDB1 + "' ORDER BY index_name"),
59 | executeQuery(connectionDB2, "SELECT index_name, table_name, uniqueness, column_name FROM all_ind_columns WHERE table_owner = '" + usernameDB2 + "' ORDER BY index_name")
60 | );
61 | }
62 |
63 | private static void compareForeignKeys(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
64 | compareResults(
65 | executeQuery(connectionDB1, "SELECT constraint_name, table_name, r_constraint_name, delete_rule FROM all_constraints WHERE constraint_type = 'R' AND owner = '" + usernameDB1 + "' ORDER BY table_name, constraint_name"),
66 | executeQuery(connectionDB2, "SELECT constraint_name, table_name, r_constraint_name, delete_rule FROM all_constraints WHERE constraint_type = 'R' AND owner = '" + usernameDB2 + "' ORDER BY table_name, constraint_name")
67 | );
68 | }
69 |
70 | private static void compareViews(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
71 | compareResults(
72 | executeQuery(connectionDB1, "SELECT view_name, text FROM all_views WHERE owner = '" + usernameDB1 + "' ORDER BY view_name"),
73 | executeQuery(connectionDB2, "SELECT view_name, text FROM all_views WHERE owner = '" + usernameDB2 + "' ORDER BY view_name")
74 | );
75 | }
76 |
77 | private static void compareConstraints(Connection connectionDB1, String usernameDB1, Connection connectionDB2, String usernameDB2) throws SQLException {
78 | compareResults(
79 | executeQuery(connectionDB1, "SELECT constraint_name, table_name, constraint_type FROM all_constraints WHERE owner = '" + usernameDB1 + "' ORDER BY table_name, constraint_name"),
80 | executeQuery(connectionDB2, "SELECT constraint_name, table_name, constraint_type FROM all_constraints WHERE owner = '" + usernameDB2 + "' ORDER BY table_name, constraint_name")
81 | );
82 | }
83 |
84 |
85 | private static void compareResults(ResultSet resultSet1, ResultSet resultSet2) throws SQLException {
86 | ResultSetMetaData metaData1 = resultSet1.getMetaData();
87 | ResultSetMetaData metaData2 = resultSet2.getMetaData();
88 |
89 | int columnCount1 = metaData1.getColumnCount();
90 | int columnCount2 = metaData2.getColumnCount();
91 |
92 | // Check if the number of columns is the same in both result sets
93 | if (columnCount1 != columnCount2) {
94 | System.out.println("Number of columns in the result sets is not the same.");
95 | return;
96 | }
97 |
98 | // Compare column names
99 | for (int i = 1; i <= columnCount1; i++) {
100 | String columnName1 = metaData1.getColumnName(i);
101 | String columnName2 = metaData2.getColumnName(i);
102 |
103 | if (!columnName1.equals(columnName2)) {
104 | System.out.println("Column names do not match: " + columnName1 + " and " + columnName2);
105 | return;
106 | }
107 | }
108 |
109 | // Compare data in the result sets
110 | while (resultSet1.next() && resultSet2.next()) {
111 | for (int i = 1; i <= columnCount1; i++) {
112 | Object value1 = resultSet1.getObject(i);
113 | Object value2 = resultSet2.getObject(i);
114 |
115 | // Add your comparison logic here
116 | // For simplicity, I'm using toString() for comparison
117 | if (!value1.toString().equals(value2.toString())) {
118 | System.out.println("Data mismatch in column " + metaData1.getColumnName(i) +
119 | ": " + value1 + " (DB1) and " + value2 + " (DB2)");
120 | return;
121 | }
122 | }
123 | }
124 |
125 | // Check if one result set has more rows than the other
126 | if (resultSet1.next()) {
127 | System.out.println("More rows in the first result set.");
128 | } else if (resultSet2.next()) {
129 | System.out.println("More rows in the second result set.");
130 | } else {
131 | System.out.println("Result sets match.");
132 | }
133 | }
134 |
135 |
136 | private static ResultSet executeQuery(Connection connection, String sql) throws SQLException {
137 | try (Statement statement = connection.createStatement()) {
138 | return statement.executeQuery(sql);
139 | }
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/src/main/resources/application.properties:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/test/java/com/pw/dcp/DatabaseChangePlatformApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.pw.dcp;
2 |
3 | import org.junit.jupiter.api.Test;
4 | import org.springframework.boot.test.context.SpringBootTest;
5 |
6 | @SpringBootTest
7 | class DatabaseChangePlatformApplicationTests {
8 |
9 | @Test
10 | void contextLoads() {
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------