From 60d5a2fefee6937586d0333bcdce6a4176d7c5cb Mon Sep 17 00:00:00 2001 From: rocket Date: Wed, 26 May 2021 14:12:22 +0300 Subject: [PATCH 01/16] Rm color codes from output --- .rultor.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index 5f067f3..0aaee5c 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -5,12 +5,12 @@ assets: gitSecret.txt: rocket-3/dbgit-test#gitSecret.txt merge: script: |- - java -version - mvn -version - mvn clean install package appassembler:assemble -D skipTests + java -version --batch-mode + mvn -version --batch-mode + mvn clean install package appassembler:assemble -D skipTests --batch-mode deploy: script: |- java -version mvn -version - mvn clean install package appassembler:assemble -D skipTests - mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* + mvn clean install package appassembler:assemble -D skipTests --batch-mode + mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode From 3c9d91fda866b6a19f3cac181ea345cf5000bcfd Mon Sep 17 00:00:00 2001 From: rocket Date: Wed, 26 May 2021 14:15:14 +0300 Subject: [PATCH 02/16] Test before merge --- .rultor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.rultor.yml b/.rultor.yml index 0aaee5c..0045b46 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -8,6 +8,7 @@ merge: java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode + mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode deploy: script: |- java -version From 6c8de42f9a60bd826a3e436d92d361af2b51a432 Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Wed, 26 May 2021 20:08:16 +0300 Subject: [PATCH 03/16] Update .rultor.yml to fix built application permission denied --- .rultor.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index 0045b46..f5cffd0 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -8,10 +8,12 @@ merge: java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode + chmod u+r+x /target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode deploy: script: |- - java -version - mvn -version + java -version --batch-mode + mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode + chmod u+r+x /target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode From 5f5a97030b80ef6df0a63544490ccd7fbd9a3941 Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Wed, 26 May 2021 20:14:57 +0300 Subject: [PATCH 04/16] Update .rultor.yml --- .rultor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index f5cffd0..e0464c1 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -8,12 +8,12 @@ merge: java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode - chmod u+r+x /target/dbgit/bin/dbgit + chmod u+r+x target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode deploy: script: |- java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode - chmod u+r+x /target/dbgit/bin/dbgit + chmod u+r+x target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode From 44c3aca4516ca809b0a74d3978cc34d270e1553f Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Sun, 30 May 2021 16:50:35 +0300 Subject: [PATCH 05/16] Update .rultor.yml Suppress mvn install package command output --- .rultor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index e0464c1..e0cc173 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -7,13 +7,13 @@ merge: script: |- java -version --batch-mode mvn -version --batch-mode - mvn clean install package appassembler:assemble -D skipTests --batch-mode + mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet chmod u+r+x target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode deploy: script: |- java -version --batch-mode mvn -version --batch-mode - mvn clean install package appassembler:assemble -D skipTests --batch-mode + mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet chmod u+r+x target/dbgit/bin/dbgit mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode From 425c4512534016090b066f1d38039776217fad4c Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Mon, 31 May 2021 19:11:07 +0300 Subject: [PATCH 06/16] Update rultor.yml for brevity, also try using custom args for tests running --- .rultor.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index e0cc173..8cb47c9 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -3,17 +3,15 @@ env: assets: pgSecret.txt: rocket-3/dbgit-test#pgSecret.txt gitSecret.txt: rocket-3/dbgit-test#gitSecret.txt -merge: +install: script: |- java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet chmod u+r+x target/dbgit/bin/dbgit +merge: + script: |- mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode deploy: script: |- - java -version --batch-mode - mvn -version --batch-mode - mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet - chmod u+r+x target/dbgit/bin/dbgit - mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode + mvn test -Dtest=$tests --batch-mode From 73acda59eec4341af81abeaddfc8e71d5a146f85 Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Mon, 31 May 2021 19:19:44 +0300 Subject: [PATCH 07/16] Update .rultor.yml --- .rultor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index 8cb47c9..262a005 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -3,8 +3,7 @@ env: assets: pgSecret.txt: rocket-3/dbgit-test#pgSecret.txt gitSecret.txt: rocket-3/dbgit-test#gitSecret.txt -install: - script: |- +install: |- java -version --batch-mode mvn -version --batch-mode mvn clean install package appassembler:assemble -D skipTests --batch-mode --quiet From 3e6669b1629b39d730f6aaf32361943e2b643683 Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Thu, 3 Jun 2021 22:46:57 +0300 Subject: [PATCH 08/16] Update rultor.yml with `tests` parameter being optional --- .rultor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index 262a005..5cfaf6e 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -10,7 +10,7 @@ install: |- chmod u+r+x target/dbgit/bin/dbgit merge: script: |- - mvn test -Dtest=*selfTest,*DbGitIntegrationTestBasic* --batch-mode + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'}$ --batch-mode deploy: script: |- - mvn test -Dtest=$tests --batch-mode + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'}$ --batch-mode From 1911a448ffa3425b33a6a9de9d457dfe0bd63cb7 Mon Sep 17 00:00:00 2001 From: rocket-3 <47713503+rocket-3@users.noreply.github.com> Date: Fri, 4 Jun 2021 00:34:10 +0300 Subject: [PATCH 09/16] Update .rultor.yml to fix my mistake with extra symbol in cmdline --- .rultor.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.rultor.yml b/.rultor.yml index 5cfaf6e..54df89d 100644 --- a/.rultor.yml +++ b/.rultor.yml @@ -10,7 +10,7 @@ install: |- chmod u+r+x target/dbgit/bin/dbgit merge: script: |- - mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'}$ --batch-mode + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'} --batch-mode deploy: script: |- - mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'}$ --batch-mode + mvn test -Dtest=${tests:-'*selfTest,*DbGitIntegrationTestBasic*'} --batch-mode From f1e2c90f2b9c2984fbb6de0ccab044e931627719 Mon Sep 17 00:00:00 2001 From: rocket Date: Wed, 2 Jun 2021 19:34:27 +0300 Subject: [PATCH 10/16] Fix restore table data on postgres when DBGit can't handle changed column order between schema generations on delete Fix restore table data on postgres when DBGit can't handle text id columns on delete Fix DbGitIntegrationTestBasic#gitToDbRestoreWorks when it can't checkout to other commit because of changed .dblink file conflict --- .../fusionsoft/dbgit/data_table/RowData.java | 384 +++++++++--------- .../fusionsoft/dbgit/meta/MetaTableData.java | 6 +- .../postgres/DBRestoreTableDataPostgres.java | 39 +- .../DbGitIntegrationTestBasic.java | 5 +- .../specific/PathPatchDbGitCheckoutHard.java | 22 + 5 files changed, 253 insertions(+), 203 deletions(-) create mode 100644 src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java diff --git a/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java b/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java index abf313e..a3e58f7 100644 --- a/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java +++ b/src/main/java/ru/fusionsoft/dbgit/data_table/RowData.java @@ -1,190 +1,194 @@ -package ru.fusionsoft.dbgit.data_table; - -import java.io.IOException; -import java.sql.ResultSet; -import java.util.*; - -import de.siegmar.fastcsv.reader.CsvRow; -import org.apache.commons.csv.CSVPrinter; -import org.apache.commons.csv.CSVRecord; - -import ru.fusionsoft.dbgit.core.DBGitLang; -import ru.fusionsoft.dbgit.core.ExceptionDBGit; -import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; -import ru.fusionsoft.dbgit.dbobjects.DBTable; -import ru.fusionsoft.dbgit.meta.MetaTable; -import ru.fusionsoft.dbgit.utils.CalcHash; -import ru.fusionsoft.dbgit.utils.ConsoleWriter; - -public class RowData { - //protected Map data = new LinkedHashMap<>(); - private List rowList = new ArrayList<>(); - private String hashRow; - //protected String key; - //protected MetaTable metaTable; - - public RowData(ResultSet rs, MetaTable metaTable) throws Exception { - //this.metaTable = metaTable; - loadDataFromRS(rs, metaTable); - } - - public RowData(CsvRow record, MetaTable metaTable, CsvRow titleColumns) throws Exception { - //this.metaTable = metaTable; - loadDataFromCSVRecord(record, titleColumns, metaTable); - } - - public RowData(CSVRecord record, MetaTable metaTable, CSVRecord titleColumns) throws Exception { - //this.metaTable = metaTable; - loadDataFromCSVRecord(record, titleColumns, metaTable); - } - - public void loadDataFromRS(ResultSet rs, MetaTable metaTable) throws Exception { - for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { - String columnName = rs.getMetaData().getColumnName(i+1); - - if (columnName.equalsIgnoreCase("DBGIT_ROW_NUM")) - continue; - - ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); - - if (cd.loadFromDB(rs, rs.getMetaData().getColumnName(i+1))) - rowList.add(cd); - //data.put(columnName, cd); - } - - hashRow = calcRowHash().substring(0, 24); - - //key = calcRowKey(metaTable.getIdColumns()); - } - - private void loadDataFromCSVRecord(CsvRow record, CsvRow titleColumns, MetaTable metaTable) throws Exception { - if (record.getFieldCount() != titleColumns.getFieldCount()) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); - } - - for (int i = 0; i < record.getFieldCount(); i++) { - String columnName = titleColumns.getField(i); - if (metaTable.getFieldsMap().get(columnName) == null) { - throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); - } - - ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); - cd.deserialize(record.getField(i).equals("") ? null : record.getField(i)); - - rowList.add(cd); - //data.put(columnName, cd); - } - hashRow = calcRowHash().substring(0, 24); - - //key = calcRowKey(metaTable.getIdColumns()); - - } - - private void loadDataFromCSVRecord(CSVRecord record, CSVRecord titleColumns, MetaTable metaTable) throws Exception { - - if (record.size() != titleColumns.size()) { - throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); - } - - for (int i = 0; i < record.size(); i++) { - String columnName = titleColumns.get(i); - if (metaTable.getFieldsMap().get(columnName) == null) { - throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); - } - - ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); - cd.deserialize(record.get(i)); - - rowList.add(cd); - //data.put(columnName, cd); - } - hashRow = calcRowHash().substring(0, 24); - - //key = calcRowKey(metaTable.getIdColumns()); - } - - public void saveDataToCsv(CSVPrinter csvPrinter, DBTable tbl) throws Exception { - //for (ICellData cd : getData().values()) - for (ICellData cd : rowList) - csvPrinter.print(cd.serialize(tbl)); - - csvPrinter.println(); - } - /* - public String calcRowKey(List idColumns) throws Exception { - if (idColumns.size() > 0) { - StringBuilder keyBuilder = new StringBuilder(); - for (String nmId : idColumns) { - keyBuilder.append(data.get(nmId).convertToString()+"_"); - } - return keyBuilder.toString(); - } else { - return hashRow; - } - } - */ - public String calcRowKey(List idColumns) throws Exception { - return hashRow; - /* - if (idColumns.size() > 0) { - StringBuilder keyBuilder = new StringBuilder(); - for (Integer nmId : idColumns) { - keyBuilder.append(rowList.get(nmId).convertToString()+"_"); - } - return keyBuilder.toString(); - } else { - return hashRow; - }*/ - } - - - public String calcRowHash() throws Exception { - CalcHash ch = new CalcHash(); - //for (ICellData cd : data.values()) { - for (ICellData cd : rowList) { - String str = cd.convertToString(); - if ( str != null) - ch.addData(str); - } - return ch.calcHashStr(); - } - - public Map getData(List fields) { - Map res = new LinkedHashMap<>(); - - int i = 0; - for (ICellData cd : rowList) { - res.put(fields.get(i), cd); - i++; - } - - return res; - } - - public Map getData() { - Map res = new HashMap<>(); - - int i = 0; - for (ICellData cd : rowList) { - res.put(String.valueOf(i), cd); - i++; - } - - return res; - } - - public List getListData() { - return rowList; - } - - public String getHashRow() { - return hashRow; - } - - public String getKey() { - //return key; - return hashRow; - } - - -} +package ru.fusionsoft.dbgit.data_table; + +import java.sql.ResultSet; +import java.text.MessageFormat; +import java.util.*; + +import de.siegmar.fastcsv.reader.CsvRow; +import java.util.stream.Collectors; + +import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; + +import ru.fusionsoft.dbgit.core.DBGitLang; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRunTime; +import ru.fusionsoft.dbgit.dbobjects.DBTable; +import ru.fusionsoft.dbgit.meta.MetaTable; +import ru.fusionsoft.dbgit.utils.CalcHash; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; + +public class RowData { + //protected Map data = new LinkedHashMap<>(); + private List rowList = new ArrayList<>(); + private String hashRow; + //protected String key; + //protected MetaTable metaTable; + + public RowData(ResultSet rs, MetaTable metaTable) throws Exception { + //this.metaTable = metaTable; + loadDataFromRS(rs, metaTable); + } + + public RowData(CsvRow record, MetaTable metaTable, CsvRow titleColumns) throws Exception { + //this.metaTable = metaTable; + loadDataFromCSVRecord(record, titleColumns, metaTable); + } + + @Deprecated + public RowData(CSVRecord record, MetaTable metaTable, CSVRecord titleColumns) throws Exception { + //this.metaTable = metaTable; + loadDataFromCSVRecord(record, titleColumns, metaTable); + } + + private void loadDataFromRS(ResultSet rs, MetaTable metaTable) throws Exception { + for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) { + String columnName = rs.getMetaData().getColumnName(i+1); + + if (columnName.equalsIgnoreCase("DBGIT_ROW_NUM")) + continue; + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + + if (cd.loadFromDB(rs, rs.getMetaData().getColumnName(i+1))) + rowList.add(cd); + //data.put(columnName, cd); + } + + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + } + + private void loadDataFromCSVRecord(CsvRow record, CsvRow titleColumns, MetaTable metaTable) throws Exception { + if (record.getFieldCount() != titleColumns.getFieldCount()) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); + } + + for (int i = 0; i < record.getFieldCount(); i++) { + String columnName = titleColumns.getField(i); + if (metaTable.getFieldsMap().get(columnName) == null) { + throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); + } + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + cd.deserialize(record.getField(i).equals("") ? null : record.getField(i)); + + rowList.add(cd); + //data.put(columnName, cd); + } + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + + } + + @Deprecated + private void loadDataFromCSVRecord(CSVRecord record, CSVRecord titleColumns, MetaTable metaTable) throws Exception { + + if (record.size() != titleColumns.size()) { + throw new ExceptionDBGit(DBGitLang.getInstance().getValue("errors", "dataTable", "differentCount")); + } + + for (int i = 0; i < record.size(); i++) { + String columnName = titleColumns.get(i); + if (metaTable.getFieldsMap().get(columnName) == null) { + throw new ExceptionDBGitRunTime(DBGitLang.getInstance().getValue("errors", "dataTable", "fieldNotFound").withParams(columnName)); + } + + ICellData cd = FactoryCellData.createCellData(metaTable.getFieldsMap().get(columnName).getTypeUniversal()); + cd.deserialize(record.get(i)); + + rowList.add(cd); + //data.put(columnName, cd); + } + hashRow = calcRowHash().substring(0, 24); + + //key = calcRowKey(metaTable.getIdColumns()); + } + + public void saveDataToCsv(CSVPrinter csvPrinter, DBTable tbl) throws Exception { + //for (ICellData cd : getData().values()) + for (ICellData cd : rowList) + csvPrinter.print(cd.serialize(tbl)); + + csvPrinter.println(); + } + /* + public String calcRowKey(List idColumns) throws Exception { + if (idColumns.size() > 0) { + StringBuilder keyBuilder = new StringBuilder(); + for (String nmId : idColumns) { + keyBuilder.append(data.get(nmId).convertToString()+"_"); + } + return keyBuilder.toString(); + } else { + return hashRow; + } + } + */ + public String calcRowKey(List idColumns) throws Exception { + return hashRow; + /* + if (idColumns.size() > 0) { + StringBuilder keyBuilder = new StringBuilder(); + for (Integer nmId : idColumns) { + keyBuilder.append(rowList.get(nmId).convertToString()+"_"); + } + return keyBuilder.toString(); + } else { + return hashRow; + }*/ + } + + + public String calcRowHash() throws Exception { + CalcHash ch = new CalcHash(); + //for (ICellData cd : data.values()) { + for (ICellData cd : rowList) { + String str = cd.convertToString(); + if ( str != null) + ch.addData(str); + } + return ch.calcHashStr(); + } + + public Map getData(List fields) { + Map res = new LinkedHashMap<>(); + + int i = 0; + for (ICellData cd : rowList) { + res.put(fields.get(i), cd); + i++; + } + + return res; + } + + public Map getData() { + Map res = new HashMap<>(); + + int i = 0; + for (ICellData cd : rowList) { + res.put(String.valueOf(i), cd); + i++; + } + + return res; + } + + public List getListData() { + return rowList; + } + + public String getHashRow() { + return hashRow; + } + + public String getKey() { + //return key; + return hashRow; + } + + +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java index f547312..fa3042d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaTableData.java @@ -88,8 +88,10 @@ public void setTable(DBTable table) throws ExceptionDBGit { this.table = table; setName(table.getSchema()+"/"+table.getName()+"."+getType().getValue()); } - - + + public void setFields(List fields) { + this.fields = fields; + } @Override public void setName(String name) throws ExceptionDBGit { diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java index a303494..c5320e3 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java @@ -77,6 +77,13 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { if (getAdapter().getTable(schema, currentTableData.getTable().getName()) != null) { //actually load data from database currentTableData.setDataTable(getAdapter().getTableData(schema, currentTableData.getTable().getName())); + currentTableData.setFields( + getAdapter().getTableFields(schema, currentTableData.getTable().getName()) + .entrySet().stream() + .sorted(Comparator.comparing(x->x.getValue().getOrder())) + .map( x->x.getKey() ) + .collect(Collectors.toList()) + ); ResultSet rs = currentTableData.getDataTable().resultSet(); @@ -127,9 +134,7 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableData currentTableData) throws Exception{ - List fieldsList = restoreTableData.getFields(); -// System.err.println("fieldsList = " + String.join(",", fieldsList)); - if(fieldsList.size() == 0 ) { + if(restoreTableData.getFields().size() == 0 || currentTableData.getFields().size() == 0 ) { ConsoleWriter.printlnRed(DBGitLang.getInstance() .getValue("errors", "restore", "emptyFieldsList") , 1 @@ -163,6 +168,18 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa //DELETE if (!diffTableData.entriesOnlyOnRight().isEmpty()) { + diffTableData.entriesOnlyOnRight().values().forEach( x->{ + System.err.print( + MessageFormat.format( + "\n{0}", + x.getData(currentTableData.getFields()) + .entrySet() + .stream() + .map(y -> y.getKey() + " = " + y.getValue().getSQLData().substring(0, Integer.min(y.getValue().getSQLData().length(), 8))) + .collect(Collectors.joining("\t")) + ) + ); + }); ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); StringBuilder deleteQuery = new StringBuilder(); @@ -170,10 +187,15 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa StringJoiner fieldJoiner = new StringJoiner(","); StringJoiner valuejoiner = new StringJoiner(","); - for( Map.Entry entry : rowData.getData(fieldsList).entrySet()) { + for( Map.Entry entry : rowData.getData(currentTableData.getFields()).entrySet()) { if (keyNames.contains(entry.getKey())) { fieldJoiner.add("\"" + entry.getKey() + "\""); - valuejoiner.add(entry.getValue().convertToString()); + final String value = entry.getValue().convertToString(); + if( value.matches("-?\\d+(\\.0)?") ) { + valuejoiner.add( String.valueOf( (long) Double.parseDouble(value) ) ); + } else { + valuejoiner.add("'" + value + "'"); + } } } @@ -200,7 +222,6 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa } //UPDATE - ConsoleWriter.detailsPrintln("Entries differing count: " + diffTableData.entriesDiffering().keySet().size(), messageLevel); if (!diffTableData.entriesDiffering().isEmpty()) { ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "updating"), messageLevel); String updateQuery = ""; @@ -209,7 +230,7 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa for (ValueDifference diffRowData : diffTableData.entriesDiffering().values()) { if (!diffRowData.leftValue().getHashRow().equals(diffRowData.rightValue().getHashRow())) { - Map tempCols = diffRowData.leftValue().getData(fieldsList); + Map tempCols = diffRowData.leftValue().getData(restoreTableData.getFields()); for (String key : tempCols.keySet()) { if (tempCols.get(key) == null || tempCols.get(key).convertToString() == null) continue; if (keyNames.contains(key)) { @@ -236,7 +257,7 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa updateQuery = "UPDATE " + tblNameEscaped + " SET (" + updFieldJoiner.toString() + ") = " - + valuesToString(tempCols.values(), colTypes, fieldsList) + " " + + valuesToString(tempCols.values(), colTypes, restoreTableData.getFields()) + " " + "WHERE (" + keyFieldsJoiner.toString() + ") = (" + keyValuesJoiner.toString() + ");\n"; @@ -262,7 +283,7 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa String insertQuery = MessageFormat.format("INSERT INTO {0}{1}{2};" , tblNameEscaped, fields - , valuesToString(rowData.getData(fieldsList).values(), colTypes, fieldsList) + , valuesToString(rowData.getData(restoreTableData.getFields()).values(), colTypes, restoreTableData.getFields()) ); ConsoleWriter.detailsPrintln(insertQuery, messageLevel+1); diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java index 9928fb6..568ef29 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -20,6 +20,7 @@ import ru.fusionsoft.dbgit.integration.primitives.chars.CommitsFromRepo; import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfUnsafeScalar; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckout; +import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckoutHard; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitClonesRepo; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitRestore; import ru.fusionsoft.dbgit.integration.primitives.chars.CharsOfConsoleWhenRunning; @@ -252,10 +253,10 @@ public final void gitToDbRestoreWorks() throws Exception { new PathPatchDbGitCheckout(commitNames.get(0), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), new PathPatchDbGitRestore("-r", "-v"), - new PathPatchDbGitCheckout(commitNames.get(1), "-nodb", "-v"), + new PathPatchDbGitCheckoutHard(commitNames.get(1), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), new PathPatchDbGitRestore("-r", "-v"), - new PathPatchDbGitCheckout(commitNames.get(2), "-nodb", "-v"), + new PathPatchDbGitCheckoutHard(commitNames.get(2), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), new PathPatchDbGitRestore("-r", "-v") ), diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java new file mode 100644 index 0000000..502985a --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/patch/specific/PathPatchDbGitCheckoutHard.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.patch.specific; + +import java.io.PrintStream; +import java.nio.file.Path; +import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; +import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitCheckout; + +public class PathPatchDbGitCheckoutHard extends PatchSequential { + public PathPatchDbGitCheckoutHard(ArgsDbGitCheckout argsDbGitCheckout, PrintStream printStream) { + super( + new PathPatchDbGitReset("-hard"), + new PathPatchDbGitCheckout(argsDbGitCheckout, printStream) + ); + } + + public PathPatchDbGitCheckoutHard(CharSequence... checkoutArgs) { + super( + new PathPatchDbGitReset("-hard"), + new PathPatchDbGitCheckout(new ArgsDbGitCheckout(checkoutArgs)) + ); + } +} From 907392074a04a48357a3882a229a5a7f4957c664 Mon Sep 17 00:00:00 2001 From: rocket Date: Thu, 3 Jun 2021 21:02:42 +0300 Subject: [PATCH 11/16] Fix of DbGit can not restore table data for Postgres when new vesion of table contains no rows Some new exception throwing points added to catch possible issues in future Change DBGitIntegrationTestBasic case when DBGit can't handle data with 10k+ rows table - now passes when file is empty, cause it's 'not a bug but a feature' now --- .../fusionsoft/dbgit/command/CmdRestore.java | 5 +-- .../ru/fusionsoft/dbgit/core/DBGitIndex.java | 3 +- .../postgres/DBRestoreTableDataPostgres.java | 31 ++++--------------- src/main/resources/lang/eng.yaml | 2 +- .../DbGitIntegrationTestBasic.java | 4 +-- 5 files changed, 13 insertions(+), 32 deletions(-) diff --git a/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java b/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java index 513578e..07eb480 100644 --- a/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java +++ b/src/main/java/ru/fusionsoft/dbgit/command/CmdRestore.java @@ -210,8 +210,9 @@ private boolean checkNeedsRestore(IMetaObject obj){ final boolean exists = GitMetaDataManager.getInstance().loadFromDB(dbObj); isRestore = !exists || !dbObj.getHash().equals(obj.getHash()); } catch (ExceptionDBGit e) { - isRestore = true; - e.printStackTrace(); + throw new ExceptionDBGitRunTime(e); +// isRestore = true; +// e.printStackTrace(); } return isRestore; } diff --git a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java index cbabb81..735eff8 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/DBGitIndex.java @@ -77,8 +77,7 @@ public boolean removeItem(String name) { saveDBIndex(); return true; } catch (Exception ex){ - ex.printStackTrace(); - return false; + throw new ExceptionDBGitRunTime("Remove item from index error", ex); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java index c5320e3..4b5da5c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTableDataPostgres.java @@ -134,21 +134,14 @@ public boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { } public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableData currentTableData) throws Exception{ - if(restoreTableData.getFields().size() == 0 || currentTableData.getFields().size() == 0 ) { - ConsoleWriter.printlnRed(DBGitLang.getInstance() - .getValue("errors", "restore", "emptyFieldsList") - , 1 - ); - ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); - return; + //if empty restore table data -> delete all currentTableData + if (currentTableData.getFields().size() == 0 ) { + final CharSequence msg = DBGitLang.getInstance().getValue("errors", "restore", "currentFieldsListIsEmpty").toString(); + throw new ExceptionDBGit(msg); } if (restoreTableData.getmapRows() == null) { - ConsoleWriter.printlnRed(DBGitLang.getInstance() - .getValue("errors", "restore", "emptyRowsList") - , 1 - ); - ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); - return; + final CharSequence msg = DBGitLang.getInstance().getValue("errors", "restore", "emptyRowsList").toString(); + throw new ExceptionDBGit(msg); } IDBAdapter adapter = getAdapter(); @@ -168,18 +161,6 @@ public void restoreTableDataPostgres(MetaTableData restoreTableData, MetaTableDa //DELETE if (!diffTableData.entriesOnlyOnRight().isEmpty()) { - diffTableData.entriesOnlyOnRight().values().forEach( x->{ - System.err.print( - MessageFormat.format( - "\n{0}", - x.getData(currentTableData.getFields()) - .entrySet() - .stream() - .map(y -> y.getKey() + " = " + y.getValue().getSQLData().substring(0, Integer.min(y.getValue().getSQLData().length(), 8))) - .collect(Collectors.joining("\t")) - ) - ); - }); ConsoleWriter.detailsPrintln(lang.getValue("general", "restore", "deleting"), messageLevel); StringBuilder deleteQuery = new StringBuilder(); diff --git a/src/main/resources/lang/eng.yaml b/src/main/resources/lang/eng.yaml index d7e0f72..941d303 100644 --- a/src/main/resources/lang/eng.yaml +++ b/src/main/resources/lang/eng.yaml @@ -203,7 +203,7 @@ errors: cantConnect: Can't connect to db! errorLoadDelete: Error load and delete object fileAlreadyExists: Error write script, file {0} already exists - emptyFieldsList: Empty fieldList, maybe empty csv... + currentFieldsListIsEmpty: Empty fieldList in current table which means the table is not reconstructed properly... emptyRowsList: MapRows is null, maybe empty csv... add: badCommand: Bad command. Not found object to add! diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java index 568ef29..780b12d 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -187,9 +187,9 @@ public final void dbToFilesDumpWorks() { } ), new SimpleTest<>( - "rental table data (10K+ rows) is not empty", + "rental table data (10K+ rows) exists and is empty", (path) -> { - return ! Files.readAllLines(path.resolve(".dbgit/public/rental.csv")).isEmpty(); + return Files.readAllLines(path.resolve(".dbgit/public/rental.csv")).isEmpty(); } ) ); From 585bff9f8771ac00a59cd5e44cb7e44c6c158799 Mon Sep 17 00:00:00 2001 From: rocket Date: Fri, 4 Jun 2021 18:39:20 +0300 Subject: [PATCH 12/16] Fix SelfTest.java running "throwable must not be null" error. Now works as expected. --- .../java/ru/fusionsoft/dbgit/integration/SelfTest.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java b/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java index da85706..73eacc6 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/SelfTest.java @@ -67,11 +67,8 @@ public final void failsToFalseOnException() { new Patch() { @Override public void apply(Path root) throws Exception { - System.out.println("access " - + root.toString()); - throw new Error( - "dummy error" - ); + System.out.println("access " + root.toString()); + throw new RuntimeException("dummy error"); } } ), From 0775fc7b641564d501d4f69b34d623c248bc66d8 Mon Sep 17 00:00:00 2001 From: rocket Date: Fri, 4 Jun 2021 18:49:07 +0300 Subject: [PATCH 13/16] Add backups enabled DbGitIntegrationTestBasic#gitToDbRestoreWorks This scenario uses sequential restore and can cause some errors in backup adapters when running --- .../DbGitIntegrationTestBasic.java | 4 ++++ .../dbgit/CharsDbGitConfigBackupEnabled.java | 22 +++++++++++++++++++ .../dbgit/CharsDbGitConfigDefault.java | 22 +++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java create mode 100644 src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java index 780b12d..ac1b293 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -19,6 +19,7 @@ import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemoteTestRepo; import ru.fusionsoft.dbgit.integration.primitives.chars.CommitsFromRepo; import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfUnsafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbGitConfigBackupEnabled; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckout; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckoutHard; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitClonesRepo; @@ -252,12 +253,15 @@ public final void gitToDbRestoreWorks() throws Exception { new PathPatchDbGitCheckout(nameOfSourceBranch, "-b", "-nodb"), new PathPatchDbGitCheckout(commitNames.get(0), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), new PathPatchDbGitRestore("-r", "-v"), new PathPatchDbGitCheckoutHard(commitNames.get(1), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), new PathPatchDbGitRestore("-r", "-v"), new PathPatchDbGitCheckoutHard(commitNames.get(2), "-nodb", "-v"), new PathPatchDbGitLink(linkArgs), + new PathPatchCreatingFile(".dbgit/dbgitconfig", new CharsDbGitConfigBackupEnabled()), new PathPatchDbGitRestore("-r", "-v") ), new ProjectTestResourcesCleanDirectoryPath("04") diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java new file mode 100644 index 0000000..c1f79ed --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigBackupEnabled.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbGitConfigBackupEnabled extends CharSequenceEnvelope { + public CharsDbGitConfigBackupEnabled() { + super(() -> { + return "[core]\n" + + "MAX_ROW_COUNT_FETCH = 10000\n" + + "LIMIT_FETCH = true\n" + + "LOG_ROTATE = 31\n" + + "LANG = ENG\n" + + "SCRIPT_ROTATE = 31\n" + + "TO_MAKE_BACKUP = true\n" + + "BACKUP_TO_SCHEME = true\n" + + "BACKUP_TABLEDATA = true\n" + + "PORTION_SIZE = 50000\n" + + "TRY_COUNT = 1000\n" + + "TRY_DELAY = 10\n"; + }); + } +} diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java new file mode 100644 index 0000000..09e219e --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbGitConfigDefault.java @@ -0,0 +1,22 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbGitConfigDefault extends CharSequenceEnvelope { + public CharsDbGitConfigDefault() { + super(()->{ + return "[core]\n" + + "MAX_ROW_COUNT_FETCH = 10000\n" + + "LIMIT_FETCH = true\n" + + "LOG_ROTATE = 31\n" + + "LANG = ENG\n" + + "SCRIPT_ROTATE = 31\n" + + "TO_MAKE_BACKUP = false\n" + + "BACKUP_TO_SCHEME = true\n" + + "BACKUP_TABLEDATA = true\n" + + "PORTION_SIZE = 50000\n" + + "TRY_COUNT = 1000\n" + + "TRY_DELAY = 10\n"; + }); + } +} From ce0026f929fefb032a67f85527e284fcafb40b8b Mon Sep 17 00:00:00 2001 From: rocket Date: Mon, 7 Jun 2021 20:25:33 +0300 Subject: [PATCH 14/16] Add template code for UDTs, Enums and Domains Meta/DB objects support DBEnum/DBUserDefinedType/DBDomain are instances of MetaSql, that's why no modification in Backup adapters needed --- .../fusionsoft/dbgit/adapters/DBAdapter.java | 3 ++ .../fusionsoft/dbgit/adapters/IDBAdapter.java | 11 ++++- .../dbgit/core/GitMetaDataManager.java | 8 +++- .../fusionsoft/dbgit/dbobjects/DBDomain.java | 13 ++++++ .../ru/fusionsoft/dbgit/dbobjects/DBEnum.java | 13 ++++++ .../dbgit/dbobjects/DBUserDefinedType.java | 13 ++++++ .../fusionsoft/dbgit/meta/DBGitMetaType.java | 33 ++++++++++++++- .../ru/fusionsoft/dbgit/meta/MetaDomain.java | 40 +++++++++++++++++++ .../ru/fusionsoft/dbgit/meta/MetaEnum.java | 32 +++++++++++++++ .../ru/fusionsoft/dbgit/meta/MetaUDT.java | 40 +++++++++++++++++++ .../dbgit/mssql/DBAdapterMssql.java | 33 +++++++++++++++ .../dbgit/mysql/DBAdapterMySql.java | 36 +++++++++++++++++ .../dbgit/oracle/DBAdapterOracle.java | 37 ++++++++++++++++- .../dbgit/postgres/DBAdapterPostgres.java | 33 +++++++++++++++ .../postgres/DBRestoreDomainPostgres.java | 17 ++++++++ .../dbgit/postgres/DBRestoreEnumPostgres.java | 17 ++++++++ .../dbgit/postgres/DBRestoreUDTPostgres.java | 17 ++++++++ .../FactoryDBAdapterRestorePostgres.java | 3 ++ 18 files changed, 394 insertions(+), 5 deletions(-) create mode 100644 src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java create mode 100644 src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java index e128dee..b9dff97 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java @@ -169,6 +169,9 @@ private void printRestoreMessage(IMetaObject obj) { if(obj instanceof MetaView){ leafName = "restoreView"; } if(obj instanceof MetaTrigger){ leafName = "restoreTrigger"; } if(obj instanceof MetaSchema){ leafName = "restoreSchema"; } + if(obj instanceof MetaSchema){ leafName = "restoreUDT"; } + if(obj instanceof MetaEnum){ leafName = "restoreEnum"; } + if(obj instanceof MetaDomain){ leafName = "restoreDomain"; } if(obj instanceof MetaRole){ leafName = "restoreRole"; } if(obj instanceof MetaProcedure){ leafName = "restorePrc"; } if(obj instanceof MetaPackage){ leafName = "restorePkg"; } diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java index ecad994..0d366f6 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/IDBAdapter.java @@ -7,6 +7,8 @@ import ru.fusionsoft.dbgit.core.ExceptionDBGit; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -21,6 +23,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; @@ -143,7 +146,13 @@ public interface IDBAdapter { public Map getUsers(); public Map getRoles(); - + Map getUDTs(String schema); + Map getDomains(String schema); + Map getEnums(String schema); + DBUserDefinedType getUDT(String schema, String name); + DBDomain getDomain(String schema, String name); + DBEnum getEnum(String schema, String name); + public boolean userHasRightsToGetDdlOfOtherUsers(); public IFactoryDBBackupAdapter getBackupAdapterFactory(); diff --git a/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java b/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java index a95d943..bf50d04 100644 --- a/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java +++ b/src/main/java/ru/fusionsoft/dbgit/core/GitMetaDataManager.java @@ -94,7 +94,7 @@ private void addToMapSqlObject( objs.put(obj); } - } + } public boolean loadFromDB(IMetaObject obj) throws ExceptionDBGit { try { @@ -241,6 +241,12 @@ public IMapMetaObject loadDBMetaData(boolean includeBackupSchemas) throws Except addToMapSqlObject(dbObjs, adapter.getProcedures(schema.getName()), DBGitMetaType.DbGitProcedure); if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DbGitView.getValue())) addToMapSqlObject(dbObjs, adapter.getViews(schema.getName()), DBGitMetaType.DbGitView); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitEnum.getValue())) + addToMapSqlObject(dbObjs, adapter.getEnums(schema.getName()), DBGitMetaType.DBGitEnum); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitUserDefinedType.getValue())) + addToMapSqlObject(dbObjs, adapter.getUDTs(schema.getName()), DBGitMetaType.DBGitUserDefinedType); + if (!ignore.matchOne(schema.getName() + "/*." + DBGitMetaType.DBGitDomain.getValue())) + addToMapSqlObject(dbObjs, adapter.getDomains(schema.getName()), DBGitMetaType.DBGitDomain); } //data tables diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java new file mode 100644 index 0000000..92c437d --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBDomain.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBDomain extends DBSQLObject { + public DBDomain() { + } + + public DBDomain(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java new file mode 100644 index 0000000..dae9f76 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBEnum.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBEnum extends DBSQLObject { + public DBEnum() { + } + + public DBEnum(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java new file mode 100644 index 0000000..cf064a9 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/dbobjects/DBUserDefinedType.java @@ -0,0 +1,13 @@ +package ru.fusionsoft.dbgit.dbobjects; + +import java.util.Set; +import ru.fusionsoft.dbgit.utils.StringProperties; + +public class DBUserDefinedType extends DBSQLObject { + public DBUserDefinedType() { + } + + public DBUserDefinedType(String name, StringProperties options, String schema, String owner, Set dependencies, String sql) { + super(name, options, schema, owner, dependencies, sql); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java index 73b678c..3f48dc7 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java @@ -46,6 +46,36 @@ public Integer getPriority() { } }, + DBGitUserDefinedType("udt"){ + public Class getMetaClass() { + return MetaUDT.class; + } + + public Integer getPriority() { + return 11; + } + }, + + DBGitEnum("enum"){ + public Class getMetaClass() { + return MetaUDT.class; + } + + public Integer getPriority() { + return 12; + } + }, + + DBGitDomain("domain"){ + public Class getMetaClass() { + return MetaUDT.class; + } + + public Integer getPriority() { + return 13; + } + }, + DBGitSequence("seq"){ public Class getMetaClass() { return MetaSequence.class; @@ -134,8 +164,7 @@ public Class getMetaClass() { public Integer getPriority() { return 210; } - } - ; + }; private static Map listAllTypes; static { diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java new file mode 100644 index 0000000..a7aa969 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaDomain.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; + +public class MetaDomain extends MetaSql { + public MetaDomain() { + } + + public MetaDomain(DBSQLObject sqlObject) throws ExceptionDBGit { + super(sqlObject); + } + + /** + * @return Type meta object + */ + @Override + public final IDBGitMetaType getType() { + return DBGitMetaType.DBGitDomain; + } + + /** + * load current object from DB + */ + @Override + public final boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBDomain dbObject = adapter.getDomain(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java new file mode 100644 index 0000000..fd41f51 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaEnum.java @@ -0,0 +1,32 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; + +public class MetaEnum extends MetaSql { + /** + * @return Type meta object + */ + @Override + public IDBGitMetaType getType() { + return DBGitMetaType.DBGitEnum; + } + + /** + * load current object from DB + */ + @Override + public boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBEnum dbObject = adapter.getEnum(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java b/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java new file mode 100644 index 0000000..014fd0d --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/meta/MetaUDT.java @@ -0,0 +1,40 @@ +package ru.fusionsoft.dbgit.meta; + +import ru.fusionsoft.dbgit.adapters.AdapterFactory; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; + +public class MetaUDT extends MetaSql { + public MetaUDT() { + } + + public MetaUDT(DBSQLObject sqlObject) throws ExceptionDBGit { + super(sqlObject); + } + + /** + * @return Type meta object + */ + @Override + public final IDBGitMetaType getType() { + return DBGitMetaType.DBGitUserDefinedType; + } + + /** + * load current object from DB + */ + @Override + public final boolean loadFromDB() throws ExceptionDBGit { + final IDBAdapter adapter = AdapterFactory.createAdapter(); + final NameMeta nm = MetaObjectFactory.parseMetaName(name); + final DBUserDefinedType dbObject = adapter.getUDT(nm.getSchema(), nm.getName()); + + if (dbObject != null) { + setSqlObject(dbObject); + return true; + } else + return false; + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java b/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java index 5a32860..f33d99d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mssql/DBAdapterMssql.java @@ -1163,6 +1163,39 @@ public Map getRoles() { return listRole; } + @Override + public Map getUDTs(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getDomains(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getEnums(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + @Override public boolean userHasRightsToGetDdlOfOtherUsers() { try{ diff --git a/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java b/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java index 774fe87..563da91 100644 --- a/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java +++ b/src/main/java/ru/fusionsoft/dbgit/mysql/DBAdapterMySql.java @@ -24,6 +24,8 @@ import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.core.db.FieldType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -37,6 +39,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; import ru.fusionsoft.dbgit.meta.TreeMapMetaObject; @@ -821,6 +824,39 @@ public Map getUsers() { @Override public Map getRoles() { return Collections.emptyMap(); } + @Override + public Map getUDTs(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getDomains(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getEnums(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + protected String getFieldType(ResultSet rs) { try { final StringBuilder type = new StringBuilder(); diff --git a/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java b/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java index c813cf5..032af9a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java +++ b/src/main/java/ru/fusionsoft/dbgit/oracle/DBAdapterOracle.java @@ -27,6 +27,8 @@ import ru.fusionsoft.dbgit.data_table.StringData; import ru.fusionsoft.dbgit.data_table.TextFileData; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -41,6 +43,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; import ru.fusionsoft.dbgit.meta.IMetaObject; @@ -958,7 +961,39 @@ public Map getRoles() { return listRole; } - + @Override + public Map getUDTs(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getDomains(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getEnums(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + static { reservedWords.add("ACCESS"); reservedWords.add("ADD"); diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java index 21d5e12..79acb45 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java @@ -1010,6 +1010,39 @@ public Map getRoles() { return listRole; } + @Override + public Map getUDTs(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getDomains(String schema) { + return Collections.emptyMap(); + } + + @Override + public Map getEnums(String schema) { + return Collections.emptyMap(); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBDomain getDomain(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + + @Override + public DBEnum getEnum(String schema, String name) { + final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); + throw new ExceptionDBGitObjectNotFound(msg); + } + @Override public boolean userHasRightsToGetDdlOfOtherUsers() { return true; } @Override diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java new file mode 100644 index 0000000..dc9e529 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.postgres; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.meta.IMetaObject; + +public class DBRestoreDomainPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public final void removeMetaObject(IMetaObject obj) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java new file mode 100644 index 0000000..cccbd38 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.postgres; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.meta.IMetaObject; + +public class DBRestoreEnumPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public final void removeMetaObject(IMetaObject obj) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java new file mode 100644 index 0000000..9190a16 --- /dev/null +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java @@ -0,0 +1,17 @@ +package ru.fusionsoft.dbgit.postgres; + +import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; +import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.meta.IMetaObject; + +public class DBRestoreUDTPostgres extends DBRestoreAdapter { + @Override + public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } + + @Override + public final void removeMetaObject(IMetaObject obj) throws Exception { + throw new NotImplementedExceptionDBGitRuntime(); + } +} diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java index a9e8f3f..c7c7e1a 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/FactoryDBAdapterRestorePostgres.java @@ -22,6 +22,9 @@ public class FactoryDBAdapterRestorePostgres implements IFactoryDBAdapterRestote static { Map aMap = new HashMap(); aMap.put(DBGitMetaType.DBGitSchema.getValue(), new DBRestoreSchemaPostgres()); + aMap.put(DBGitMetaType.DBGitUserDefinedType.getValue(), new DBRestoreUDTPostgres()); + aMap.put(DBGitMetaType.DBGitDomain.getValue(), new DBRestoreDomainPostgres()); + aMap.put(DBGitMetaType.DBGitEnum.getValue(), new DBRestoreEnumPostgres()); aMap.put(DBGitMetaType.DBGitTableSpace.getValue(), new DBRestoreTableSpacePostgres()); aMap.put(DBGitMetaType.DBGitRole.getValue(), new DBRestoreRolePostgres()); aMap.put(DBGitMetaType.DBGitSequence.getValue(), new DBRestoreSequencePostgres()); From 730ded92be5a4b86606e7ea252f4b6ef9f19f4d1 Mon Sep 17 00:00:00 2001 From: rocket Date: Tue, 8 Jun 2021 22:04:41 +0300 Subject: [PATCH 15/16] Add implementation of DBAdapterPostgres.getEnums, DBAdapterPostgres.getDomains Add IT case just testing fetch and existence of such objects Disabled DbGitIntegrationTestNotebook for automatic test execution not to accidentally burn test repos --- .../dbgit/adapters/DBAdapterProxy.java | 35 +++++- .../fusionsoft/dbgit/meta/DBGitMetaType.java | 4 +- .../dbgit/postgres/DBAdapterPostgres.java | 118 +++++++++++++++++- .../DbGitIntegrationTestBasic.java | 17 ++- .../DbGitIntegrationTestNotebook.java | 2 + .../dbgit/CharsDbIgnoreWithDataAndTypes.java | 25 ++++ 6 files changed, 194 insertions(+), 7 deletions(-) create mode 100644 src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java index 6e0ecc6..8f7797d 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapterProxy.java @@ -8,6 +8,8 @@ import ru.fusionsoft.dbgit.core.SchemaSynonym; import ru.fusionsoft.dbgit.core.db.DbType; import ru.fusionsoft.dbgit.dbobjects.DBConstraint; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; import ru.fusionsoft.dbgit.dbobjects.DBFunction; import ru.fusionsoft.dbgit.dbobjects.DBIndex; import ru.fusionsoft.dbgit.dbobjects.DBPackage; @@ -22,6 +24,7 @@ import ru.fusionsoft.dbgit.dbobjects.DBTableSpace; import ru.fusionsoft.dbgit.dbobjects.DBTrigger; import ru.fusionsoft.dbgit.dbobjects.DBUser; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.dbobjects.DBView; import ru.fusionsoft.dbgit.meta.IMapMetaObject; @@ -186,7 +189,37 @@ public Map getUsers() { public Map getRoles() { return adapter.getRoles(); } - + + @Override + public Map getUDTs(String schema) { + return adapter.getUDTs(schema); + } + + @Override + public Map getDomains(String schema) { + return adapter.getDomains(schema); + } + + @Override + public Map getEnums(String schema) { + return adapter.getEnums(schema); + } + + @Override + public DBUserDefinedType getUDT(String schema, String name) { + return adapter.getUDT(schema, name); + } + + @Override + public DBDomain getDomain(String schema, String name) { + return adapter.getDomain(schema, name); + } + + @Override + public DBEnum getEnum(String schema, String name) { + return adapter.getEnum(schema, name); + } + public T schemaSynonymMap(T object) { if (object == null) return null; diff --git a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java index 3f48dc7..78452b6 100644 --- a/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java +++ b/src/main/java/ru/fusionsoft/dbgit/meta/DBGitMetaType.java @@ -58,7 +58,7 @@ public Integer getPriority() { DBGitEnum("enum"){ public Class getMetaClass() { - return MetaUDT.class; + return MetaEnum.class; } public Integer getPriority() { @@ -68,7 +68,7 @@ public Integer getPriority() { DBGitDomain("domain"){ public Class getMetaClass() { - return MetaUDT.class; + return MetaDomain.class; } public Integer getPriority() { diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java index 79acb45..0f9fc6f 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java @@ -9,6 +9,7 @@ import com.diogonunes.jcdp.color.api.Ansi; import com.google.common.collect.ImmutableMap; +import java.util.stream.Collectors; import org.apache.commons.lang3.exception.ExceptionUtils; import ru.fusionsoft.dbgit.adapters.*; import ru.fusionsoft.dbgit.core.*; @@ -1012,17 +1013,130 @@ public Map getRoles() { @Override public Map getUDTs(String schema) { + System.out.println("getting UDT's"); return Collections.emptyMap(); } @Override public Map getDomains(String schema) { - return Collections.emptyMap(); + System.out.println("getting domains"); + final Map objects = new HashMap<>(); + final String query = + "SELECT \n" + + " n.nspname,\n" + + " t.typname, \n" + + " dom.data_type, \n" + + " dom.domain_default,\n" + + " r.rolname,\n" + + " pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "RIGHT JOIN information_schema.domains dom ON dom.domain_name = t.typname AND dom.domain_schema = n.nspname\n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n" + + "AND dom.domain_schema = '"+schema+"'"; + + System.out.println("query = " + query); + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while (rs.next()) { + final String name = rs.getString("typname"); + final String owner = rs.getString("rolname"); + final String type = rs.getString("data_type"); + final String defaultValue = rs.getString("domain_default"); + + final List constraintSqls = new ArrayList<>(); + final String constraintsQuery = + "SELECT con.conname, con.convalidated, con.consrc\n" + + "FROM information_schema.domains dom\n" + + "INNER JOIN information_schema.domain_constraints dcon ON dcon.domain_schema = dom.domain_schema AND dcon.domain_name = dom.domain_name\n" + + "INNER JOIN pg_catalog.pg_constraint con ON dcon.constraint_name = con.conname\n" + + "WHERE dom.domain_schema = '"+schema+"' AND dom.domain_name = '"+name+"'"; + try (Statement stmt2 = getConnection().createStatement(); ResultSet conRs = stmt2.executeQuery(constraintsQuery)) { + while (conRs.next()) { + final String conName = conRs.getString("conname"); + final String conSrc = conRs.getString("consrc"); + final Boolean conIsValidated = conRs.getBoolean("convalidated"); + final String conSql = MessageFormat.format( + "ALTER DOMAIN {0}.{1} ADD CONSTRAINT {2} CHECK {3} {4};", + escapeNameIfNeeded(schema), + escapeNameIfNeeded(name), + escapeNameIfNeeded(conName), + conSrc, + conIsValidated ? "" : "NOT VALID" + ); + constraintSqls.add(conSql); + System.out.println("conSql = " + conSql); + } + } + + final StringProperties options = new StringProperties(rs); + final String sql = MessageFormat.format( + "CREATE DOMAIN {0}.{1} AS {2} {3}; ALTER DOMAIN {0}.{1} OWNER TO {4};\n{5}", + escapeNameIfNeeded(schema), escapeNameIfNeeded(name), type, defaultValue != null ? "DEFAULT " + defaultValue : "", owner, + String.join("\n", constraintSqls) + ); + System.out.println("sql = " + sql); + + DBDomain object = new DBDomain(name, options, schema, owner, Collections.emptySet(), sql); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; } @Override public Map getEnums(String schema) { - return Collections.emptyMap(); + System.out.println("getting enums"); + final Map objects = new HashMap<>(); + final String query = + "SELECT t.typname, r.rolname, pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description," + + "ARRAY( \n" + + " SELECT e.enumlabel\n" + + " FROM pg_catalog.pg_enum e\n" + + " WHERE e.enumtypid = t.oid\n" + + " ORDER BY e.oid \n" + + ") AS elements\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n" + + "AND n.nspname = '"+schema+"'" + + "AND t.typtype = 'e'"; + + System.out.println("query = " + query); + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + + while (rs.next()) { + final String name = rs.getString("typname"); + final String owner = rs.getString("rolname"); + final StringProperties options = new StringProperties(rs); + final List elements = Arrays.stream((String[]) rs.getArray("elements").getArray()) + .map( x->"'"+x+"'") + .collect(Collectors.toList()); + final String sql = MessageFormat.format( + "CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} ONWER TO {3}", + schema, name, String.join(",", elements), owner + ); + System.out.println("sql = " + sql); + + DBEnum object = new DBEnum(name, options, schema, owner, Collections.emptySet(), sql); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; } @Override diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java index 780b12d..680c5c7 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -19,6 +19,7 @@ import ru.fusionsoft.dbgit.integration.primitives.args.specific.ArgsDbGitAddRemoteTestRepo; import ru.fusionsoft.dbgit.integration.primitives.chars.CommitsFromRepo; import ru.fusionsoft.dbgit.integration.primitives.chars.LinesOfUnsafeScalar; +import ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit.CharsDbIgnoreWithDataAndTypes; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckout; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitCheckoutHard; import ru.fusionsoft.dbgit.integration.primitives.patch.specific.PathPatchDbGitClonesRepo; @@ -154,10 +155,10 @@ public final void dbToFilesDumpWorks() { new ArgsExplicit("add", "\"*\""), new PathWithFiles( - new PathPatchCreatingFile(".dbgit/.dbignore", new CharsDbIgnoreWithTableData()), + new PathPatchCreatingFile(".dbgit/.dbignore", new CharsDbIgnoreWithDataAndTypes()), new PathAfterDbGitRun( - new ArgsDbGitLinkPgAuto("pagilla"), + new ArgsDbGitLinkPgAuto("dvdrental"), new PathAfterDbGitRun( new ArgsExplicit("init"), @@ -191,6 +192,18 @@ public final void dbToFilesDumpWorks() { (path) -> { return Files.readAllLines(path.resolve(".dbgit/public/rental.csv")).isEmpty(); } + ), + new SimpleTest<>( + "mpaa_rating.enum exists", + (path) -> { + return path.resolve(".dbgit/public/mpaa_rating.enum").toFile().exists(); + } + ), + new SimpleTest<>( + "year.domain exists", + (path) -> { + return path.resolve(".dbgit/public/year.domain").toFile().exists(); + } ) ); diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java index b60b53c..218bebc 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestNotebook.java @@ -3,6 +3,7 @@ import java.nio.file.Path; import java.text.MessageFormat; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import ru.fusionsoft.dbgit.integration.primitives.PatchSequential; @@ -29,6 +30,7 @@ import ru.fusionsoft.dbgit.integration.primitives.path.specific.dbgit.scenarios.PathAfterDbGitDumpsDbSchemaToGit; @Tag("notebook") +@Disabled public class DbGitIntegrationTestNotebook { @Test public final void appendsDbSchemaToBranchOfTestRepo() { diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java new file mode 100644 index 0000000..c3725d4 --- /dev/null +++ b/src/test/java/ru/fusionsoft/dbgit/integration/primitives/chars/specific/dbgit/CharsDbIgnoreWithDataAndTypes.java @@ -0,0 +1,25 @@ +package ru.fusionsoft.dbgit.integration.primitives.chars.specific.dbgit; + +import ru.fusionsoft.dbgit.integration.primitives.chars.CharSequenceEnvelope; + +public class CharsDbIgnoreWithDataAndTypes extends CharSequenceEnvelope { + public CharsDbIgnoreWithDataAndTypes() { + super(()->{ + return "*\n" + + "!public/*.ts\n" + + "!public/*.sch\n" + + "!public/*.seq\n" + + "!public/*.tbl\n" + + "!public/*.pkg\n" + + "!public/*.trg\n" + + "!public/*.prc\n" + + "!public/*.fnc\n" + + "!public/*.vw\n" + + "!public/*.blob\n" + + "!public/*.udt\n" + + "!public/*.enum\n" + + "!public/*.domain\n" + + "!public/*.csv\n"; + }); + } +} From ddf015c8da0e1eaf8d3dffcc5e5851ce4983d6e4 Mon Sep 17 00:00:00 2001 From: rocket Date: Fri, 11 Jun 2021 03:38:44 +0300 Subject: [PATCH 16/16] Impl. of DBRestore(Domain|Enum|UDT)Postgres Fix of some new implementations errors Improve test case with custom types --- .../fusionsoft/dbgit/adapters/DBAdapter.java | 2 +- .../dbgit/postgres/DBAdapterPostgres.java | 122 ++++++++++++++---- .../postgres/DBRestoreDomainPostgres.java | 113 +++++++++++++++- .../dbgit/postgres/DBRestoreEnumPostgres.java | 103 ++++++++++++++- .../postgres/DBRestoreTablePostgres.java | 2 + .../dbgit/postgres/DBRestoreUDTPostgres.java | 108 +++++++++++++++- src/main/resources/lang/eng.yaml | 3 + .../DbGitIntegrationTestBasic.java | 10 +- 8 files changed, 421 insertions(+), 42 deletions(-) diff --git a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java index b9dff97..ff75722 100644 --- a/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java +++ b/src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java @@ -169,7 +169,7 @@ private void printRestoreMessage(IMetaObject obj) { if(obj instanceof MetaView){ leafName = "restoreView"; } if(obj instanceof MetaTrigger){ leafName = "restoreTrigger"; } if(obj instanceof MetaSchema){ leafName = "restoreSchema"; } - if(obj instanceof MetaSchema){ leafName = "restoreUDT"; } + if(obj instanceof MetaUDT){ leafName = "restoreUDT"; } if(obj instanceof MetaEnum){ leafName = "restoreEnum"; } if(obj instanceof MetaDomain){ leafName = "restoreDomain"; } if(obj instanceof MetaRole){ leafName = "restoreRole"; } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java index 0f9fc6f..14b7f95 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java @@ -1013,8 +1013,68 @@ public Map getRoles() { @Override public Map getUDTs(String schema) { - System.out.println("getting UDT's"); - return Collections.emptyMap(); + final Map objects = new HashMap<>(); + final String query = + "SELECT \n" + + " n.nspname AS schema,\n" + + " t.typname AS name, \n" + + " r.rolname AS owner,\n" + + " pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description\n" + + "FROM pg_type t \n" + + "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n" + + "LEFT JOIN pg_roles r ON r.oid = t.typowner\n" + + "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n" + + "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n" + + "AND t.typtype = 'c'\n" + + "AND n.nspname = '"+schema+"'"; + + try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { + while (rs.next()) { + final String name = rs.getString("name"); + final String owner = rs.getString("owner"); + final List attributesSqls = new ArrayList<>(); + final String attributesQuery = + "SELECT \n" + + " attribute_name AS \"name\", \n" + + " data_type AS \"type\", \n" + + " ordinal_position AS \"order\"\n" + + "FROM information_schema.attributes a\n" + + "WHERE udt_schema = '"+schema+"' AND udt_name = '"+name+"'\n" + + "ORDER BY ordinal_position"; + try (Statement stmt2 = getConnection().createStatement(); ResultSet attributeRs = stmt2.executeQuery( + attributesQuery)) { + while (attributeRs.next()) { + final String attrName = attributeRs.getString("name"); + final String attrType = attributeRs.getString("type"); + final String udtAttrDefinition = MessageFormat.format( + "{0} {1}", + escapeNameIfNeeded(attrName), + attrType + ); + attributesSqls.add(udtAttrDefinition); + } + } + final StringProperties options = new StringProperties(); + final String sql = MessageFormat.format( + "CREATE TYPE {0}.{1} AS (\n{2}\n);\n" + + "ALTER TYPE {0}.{1} OWNER TO {3};", + escapeNameIfNeeded(schema), + escapeNameIfNeeded(name), + String.join(",\n ", attributesSqls), + owner + ); + + DBUserDefinedType object = new DBUserDefinedType(name, options, schema, owner, Collections.emptySet(), sql); + options.addChild("attributes", String.join(",", attributesSqls)); + options.addChild("description", rs.getString("description")); + objects.put(name, object); + } + + } catch (Exception e) { + throw new ExceptionDBGitRunTime(e); + } + + return objects; } @Override @@ -1024,7 +1084,7 @@ public Map getDomains(String schema) { final String query = "SELECT \n" + " n.nspname,\n" - + " t.typname, \n" + + " t.typname, \n" + " dom.data_type, \n" + " dom.domain_default,\n" + " r.rolname,\n" @@ -1038,7 +1098,6 @@ public Map getDomains(String schema) { + "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n" + "AND dom.domain_schema = '"+schema+"'"; - System.out.println("query = " + query); try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { while (rs.next()) { @@ -1059,16 +1118,14 @@ public Map getDomains(String schema) { final String conName = conRs.getString("conname"); final String conSrc = conRs.getString("consrc"); final Boolean conIsValidated = conRs.getBoolean("convalidated"); - final String conSql = MessageFormat.format( + constraintSqls.add(MessageFormat.format( "ALTER DOMAIN {0}.{1} ADD CONSTRAINT {2} CHECK {3} {4};", - escapeNameIfNeeded(schema), - escapeNameIfNeeded(name), - escapeNameIfNeeded(conName), - conSrc, + escapeNameIfNeeded(schema), + escapeNameIfNeeded(name), + escapeNameIfNeeded(conName), + conSrc, conIsValidated ? "" : "NOT VALID" - ); - constraintSqls.add(conSql); - System.out.println("conSql = " + conSql); + )); } } @@ -1078,7 +1135,6 @@ public Map getDomains(String schema) { escapeNameIfNeeded(schema), escapeNameIfNeeded(name), type, defaultValue != null ? "DEFAULT " + defaultValue : "", owner, String.join("\n", constraintSqls) ); - System.out.println("sql = " + sql); DBDomain object = new DBDomain(name, options, schema, owner, Collections.emptySet(), sql); objects.put(name, object); @@ -1112,23 +1168,23 @@ public Map getEnums(String schema) { + "AND n.nspname = '"+schema+"'" + "AND t.typtype = 'e'"; - System.out.println("query = " + query); try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) { while (rs.next()) { final String name = rs.getString("typname"); final String owner = rs.getString("rolname"); - final StringProperties options = new StringProperties(rs); - final List elements = Arrays.stream((String[]) rs.getArray("elements").getArray()) - .map( x->"'"+x+"'") - .collect(Collectors.toList()); + final String elements = String.join( + ",", + Arrays.stream((String[]) rs.getArray("elements").getArray()).map( x->"'"+x+"'").collect(Collectors.toList()) + ); + final StringProperties options = new StringProperties(); final String sql = MessageFormat.format( - "CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} ONWER TO {3}", - schema, name, String.join(",", elements), owner + "CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} OWNER TO {3}", + schema, name, elements, owner ); - System.out.println("sql = " + sql); DBEnum object = new DBEnum(name, options, schema, owner, Collections.emptySet(), sql); + options.addChild("elements", elements); objects.put(name, object); } @@ -1141,20 +1197,32 @@ public Map getEnums(String schema) { @Override public DBUserDefinedType getUDT(String schema, String name) { - final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); - throw new ExceptionDBGitObjectNotFound(msg); + final Map udTs = getUDTs(schema); + if (udTs.containsKey(name)) { + return udTs.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } } @Override public DBDomain getDomain(String schema, String name) { - final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); - throw new ExceptionDBGitObjectNotFound(msg); + final Map domains = getDomains(schema); + if (domains.containsKey(name)) { + return domains.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } } @Override public DBEnum getEnum(String schema, String name) { - final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString(); - throw new ExceptionDBGitObjectNotFound(msg); + final Map enums = getEnums(schema); + if (enums.containsKey(name)) { + return enums.get(name); + } else { + throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString()); + } } @Override diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java index dc9e529..56039a1 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreDomainPostgres.java @@ -1,17 +1,122 @@ package ru.fusionsoft.dbgit.postgres; +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBDomain; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaDomain; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; public class DBRestoreDomainPostgres extends DBRestoreAdapter { @Override public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (final StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + if (! ( obj instanceof MetaDomain )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError").withParams( + obj.getName(), + "domain", + obj.getType().getValue() + ) + ); + } + final DBSQLObject restoreDomain = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map domains = adapter.getDomains(restoreDomain.getSchema()); + + if (domains.containsKey(restoreDomain.getName())) { + final DBDomain currentDomain = domains.get(restoreDomain.getName()); + if ( + ! restoreDomain.getOptions().get("attributes").equals( + currentDomain.getOptions().get("attributes") + ) + ) { + st.execute(MessageFormat.format( + "DROP DOMAIN IF EXISTS {0}._deprecated_{1} RESTRICT;\n" + + "ALTER DOMAIN {0}.{1} RENAME TO _deprecated_{1};\n" + + "{2}", + currentDomain.getSchema(), currentDomain.getName(), getDdlEscaped(restoreDomain) + )); + } else { + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentDomain, restoreDomain.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreDomain)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; } @Override - public final void removeMetaObject(IMetaObject obj) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + public void removeMetaObject(IMetaObject obj) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP DOMAIN IF EXISTS {0}.{1} RESTRICT", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE DOMAIN " + schema + "." + name, + "CREATE DOMAIN " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java index cccbd38..f781be4 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreEnumPostgres.java @@ -1,17 +1,112 @@ package ru.fusionsoft.dbgit.postgres; +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Arrays; +import java.util.List; +import java.util.Map; import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGit; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBEnum; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaEnum; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; public class DBRestoreEnumPostgres extends DBRestoreAdapter { @Override public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql())) { + if (! ( obj instanceof MetaEnum )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError") + .withParams(obj.getName(), "enum", obj.getType().getValue()) + ); + } + final DBSQLObject restoreEnum = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map enums = adapter.getEnums(restoreEnum.getSchema()); + + if(enums.containsKey(restoreEnum.getName())) { + DBEnum currentEnum = enums.get(restoreEnum.getName()); + if( + ! restoreEnum.getOptions().get("elements").equals( + currentEnum.getOptions().get("elements") + ) + ) { + st.execute(MessageFormat.format( + "ALTER TYPE {0}.{1} RENAME TO _deprecated_{1};\n{2}", + currentEnum.getSchema(), currentEnum.getName(), getDdlEscaped(restoreEnum) + )); + } else{ + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentEnum, restoreEnum.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreEnum)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; } @Override - public final void removeMetaObject(IMetaObject obj) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + public void removeMetaObject(IMetaObject obj) throws Exception { + IDBAdapter adapter = getAdapter(); + Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging(connect, adapter.getStreamOutputSqlCommand(), adapter.isExecSql())){ + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP TYPE {0}.{1}", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE TYPE " + schema + "." + name, + "CREATE TYPE " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); } } diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java index 3627acc..a7ff235 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreTablePostgres.java @@ -324,6 +324,8 @@ private void restoreTableFields(MetaTable restoreTable, MetaTable existingTable, &&(restoreField.getTypeUniversal() != FieldType.BOOLEAN) &&(existingField.getTypeUniversal() != FieldType.STRING_NATIVE) &&(restoreField.getTypeUniversal() != FieldType.STRING_NATIVE) + &&(existingField.getTypeUniversal() != FieldType.NATIVE) + &&(restoreField.getTypeUniversal() != FieldType.NATIVE) && hasNotTypeSql(tblField, "json") && hasNotTypeSql(tblField, "text[]") && hasNotTypeSql(tblField, "text") diff --git a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java index 9190a16..14e206c 100644 --- a/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java +++ b/src/main/java/ru/fusionsoft/dbgit/postgres/DBRestoreUDTPostgres.java @@ -1,17 +1,117 @@ package ru.fusionsoft.dbgit.postgres; +import java.sql.Connection; +import java.text.MessageFormat; +import java.util.Map; import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter; -import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime; +import ru.fusionsoft.dbgit.adapters.IDBAdapter; +import ru.fusionsoft.dbgit.core.DBGitConfig; +import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore; +import ru.fusionsoft.dbgit.dbobjects.DBSQLObject; +import ru.fusionsoft.dbgit.dbobjects.DBUserDefinedType; import ru.fusionsoft.dbgit.meta.IMetaObject; +import ru.fusionsoft.dbgit.meta.MetaUDT; +import ru.fusionsoft.dbgit.statement.StatementLogging; +import ru.fusionsoft.dbgit.utils.ConsoleWriter; public class DBRestoreUDTPostgres extends DBRestoreAdapter { @Override public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + try (final StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + if (! ( obj instanceof MetaUDT )) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "metaTypeError").withParams(obj.getName(), "udt", obj.getType().getValue()) + ); + } + final DBSQLObject restoreUDT = (DBSQLObject) obj.getUnderlyingDbObject(); + final Map udts = adapter.getUDTs(restoreUDT.getSchema()); + + if (udts.containsKey(restoreUDT.getName())) { + final DBUserDefinedType currentUDT = udts.get(restoreUDT.getName()); + if ( + ! restoreUDT.getOptions().get("attributes").equals( + currentUDT.getOptions().get("attributes") + ) + ) { + st.execute(MessageFormat.format( + "ALTER TYPE {0}.{1} RENAME TO _deprecated_{1};\n" + + "{2}", + currentUDT.getSchema(), currentUDT.getName(), getDdlEscaped(restoreUDT) + )); + } else { + if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) { + st.execute(getChangeOwnerDdl(currentUDT, restoreUDT.getOwner())); + } + } + } else { + st.execute(getDdlEscaped(restoreUDT)); + } + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()), + e + ); + } finally { + ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok")); + } + return true; } @Override - public final void removeMetaObject(IMetaObject obj) throws Exception { - throw new NotImplementedExceptionDBGitRuntime(); + public void removeMetaObject(IMetaObject obj) throws Exception { + final IDBAdapter adapter = getAdapter(); + final Connection connect = adapter.getConnection(); + + try (StatementLogging st = new StatementLogging( + connect, + adapter.getStreamOutputSqlCommand(), + adapter.isExecSql() + )) { + + final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject(); + st.execute(MessageFormat.format( + "DROP TYPE {0}.{1}", + adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())), + adapter.escapeNameIfNeeded(currentObject.getName()) + )); + + } catch (Exception e) { + throw new ExceptionDBGitRestore( + lang.getValue("errors", "restore", "objectRemoveError") + .withParams(obj.getName()), e); + } + } + + private String getDdlEscaped(DBSQLObject dbsqlObject) { + String query = dbsqlObject.getSql(); + final String name = dbsqlObject.getName(); + final String schema = dbsqlObject.getSchema(); + final String nameEscaped = adapter.escapeNameIfNeeded(name); + final String schemaEscaped = adapter.escapeNameIfNeeded(schema); + + if (! name.equalsIgnoreCase(nameEscaped)) { + query = query.replace( + "CREATE TYPE " + schema + "." + name, + "CREATE TYPE " + schemaEscaped + "." + nameEscaped + ); + } + if (! query.endsWith(";")) query = query + ";\n"; + query = query + "\n"; + return query; + } + + private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) { + return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n" + , adapter.escapeNameIfNeeded(dbsqlObject.getSchema()) + , adapter.escapeNameIfNeeded(dbsqlObject.getName()) + , owner + ); } } diff --git a/src/main/resources/lang/eng.yaml b/src/main/resources/lang/eng.yaml index 941d303..1a3e5db 100644 --- a/src/main/resources/lang/eng.yaml +++ b/src/main/resources/lang/eng.yaml @@ -73,6 +73,9 @@ general: restoreTrigger: Restoring trigger {0} ... restoreSeq: Restoring sequence {0} ... restoreSchema: Restoring schema {0} ... + restoreUDT: Restoring user defined type {0} ... + restoreEnum: Restoring enum {0} ... + restoreDomain: Restoring domain {0} ... restoreRole: Restoring role {0} ... restorePrc: Restoring procedure {0} ... restorePkg: Restoring package {0} ... diff --git a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java index a23293c..fdffffe 100644 --- a/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java +++ b/src/test/java/ru/fusionsoft/dbgit/integration/DbGitIntegrationTestBasic.java @@ -205,6 +205,12 @@ public final void dbToFilesDumpWorks() { (path) -> { return path.resolve(".dbgit/public/year.domain").toFile().exists(); } + ), + new SimpleTest<>( + "film_summary.udt exists", + (path) -> { + return path.resolve(".dbgit/public/film_summary.udt").toFile().exists(); + } ) ); @@ -308,7 +314,7 @@ public final void dbToDbRestoreWorksWithCustomTypes() { //pagilla to local repo new PathAfterDbGitLinkAndAdd( new ArgsDbGitLinkPgAuto("pagilla"), - new CharsDbIgnoreWithTableData(), + new CharsDbIgnoreWithDataAndTypes(), //dvdrental to test#databasegit new PathAfterDbGitRun( @@ -320,7 +326,7 @@ public final void dbToDbRestoreWorksWithCustomTypes() { //dvdrental to local repo new PathAfterDbGitLinkAndAdd( new ArgsDbGitLinkPgAuto("dvdrental"), - new CharsDbIgnoreWithTableData(), + new CharsDbIgnoreWithDataAndTypes(), new PathAfterDbGitRun( new ArgsExplicit("init"),