diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandler.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandler.java index 6d2711ea..0793b536 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandler.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandler.java @@ -32,4 +32,20 @@ public abstract class DatabaseHandler public abstract boolean isRenameConstraint(); public abstract boolean isUpdateIdentity(); + + public final boolean isExpressionDifferent(String pExpression1, String pExpression2) + { + if( pExpression1==null && pExpression2==null ) { + return false; + } + if( pExpression1==null || pExpression2==null ) { + return true; + } + return isExpressionDifferentNotNull(pExpression1,pExpression2); + } + + protected boolean isExpressionDifferentNotNull(String pExpression1, String pExpression2) + { + return !pExpression1.equals(pExpression2); + } } diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerH2.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerH2.java index c1ede37f..a1f33d96 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerH2.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerH2.java @@ -61,7 +61,7 @@ public String getDefaultTablespace( CallableStatementProvider pCallableStatement @Override public DdlBuilder createDdlBuilder( Parameters pParameters ) { - return new DdlBuilderHsqlDb( pParameters ); + return new DdlBuilderHsqlDb( pParameters, this ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerHsqlDb.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerHsqlDb.java index f54c86cc..cb010335 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerHsqlDb.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerHsqlDb.java @@ -61,7 +61,7 @@ public String getDefaultTablespace( CallableStatementProvider pCallableStatement @Override public DdlBuilder createDdlBuilder( Parameters pParameters ) { - return new DdlBuilderHsqlDb( pParameters ); + return new DdlBuilderHsqlDb( pParameters, this ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerMySql.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerMySql.java index ad189cfa..177ab150 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerMySql.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerMySql.java @@ -61,7 +61,7 @@ public String getDefaultTablespace( CallableStatementProvider pCallableStatement @Override public DdlBuilder createDdlBuilder( Parameters pParameters ) { - return new DdlBuilderMySql( pParameters ); + return new DdlBuilderMySql( pParameters, this ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerOracle.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerOracle.java index 0764103b..790acaaa 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerOracle.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerOracle.java @@ -78,7 +78,7 @@ public String getDefaultTablespace( CallableStatementProvider pCallableStatement @Override public DdlBuilder createDdlBuilder( Parameters pParameters ) { - return new DdlBuilderOracle( pParameters ); + return new DdlBuilderOracle( pParameters, this ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerPostgres.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerPostgres.java new file mode 100644 index 00000000..4075197b --- /dev/null +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DatabaseHandlerPostgres.java @@ -0,0 +1,168 @@ +package de.opitzconsulting.orcas.diff; + +import java.util.ArrayList; +import java.util.List; + +import de.opitzconsulting.orcas.sql.CallableStatementProvider; +import de.opitzconsulting.orcas.sql.WrapperExecuteStatement; +import de.opitzconsulting.origOrcasDsl.CharType; + +public class DatabaseHandlerPostgres extends DatabaseHandler { + @Override + public void createOrcasUpdatesTable(String pOrcasUpdatesTableName, CallableStatementProvider pOrcasCallableStatementProvider) { + String + lSql = + "create table " + + pOrcasUpdatesTableName + + " ( scup_id serial, scup_script_name varchar(4000) not null, scup_logname varchar(100) not null, scup_date date not null, scup_schema varchar(30) not null, primary key (scup_id))"; + new WrapperExecuteStatement(lSql, pOrcasCallableStatementProvider).execute(); + } + + @Override + public void insertIntoOrcasUpdatesTable( + String pOrcasUpdatesTableName, + CallableStatementProvider pOrcasCallableStatementProvider, + String pFilePart, + String pLogname) { + String lSql = "" + // + " insert into " + pOrcasUpdatesTableName + "(" + // + " scup_script_name," + // + " scup_date," + // + " scup_schema," + // + " scup_logname" + // + " )" + // + " values (" + // + " ?," + // + " current_timestamp," + // + " user," + // + " ?" + // + " )" + // + ""; + List lInsertParameters = new ArrayList(); + lInsertParameters.add(pFilePart); + lInsertParameters.add(pLogname); + new WrapperExecuteStatement(lSql, pOrcasCallableStatementProvider, lInsertParameters).execute(); + new WrapperExecuteStatement("commit", pOrcasCallableStatementProvider).execute(); + } + + @Override + public LoadIst createLoadIst(CallableStatementProvider pCallableStatementProvider, Parameters pParameters) { + return new LoadIstPostgres(pCallableStatementProvider, pParameters); + } + + @Override + public CharType getDefaultCharType(CallableStatementProvider pCallableStatementProvider) { + return CharType.CHAR; + } + + @Override + public String getDefaultTablespace(CallableStatementProvider pCallableStatementProvider) { + return null; + } + + @Override + public DdlBuilder createDdlBuilder(Parameters pParameters) { + return new DdlBuilderPostgres(pParameters, this); + } + + @Override + public void executeDiffResultStatement(String pStatementToExecute, CallableStatementProvider pCallableStatementProvider) { + new WrapperExecuteStatement(pStatementToExecute, pCallableStatementProvider).execute(); + } + + @Override + public boolean isRenamePrimaryKey() { + return true; + } + + @Override + public boolean isRenameIndex() { + return true; + } + + @Override + public boolean isRenameMView() { + return true; + } + + @Override + public boolean isRenameForeignKey() { + return true; + } + + @Override + public boolean isRenameUniqueKey() { + return true; + } + + @Override + public boolean isRenameConstraint() { + return true; + } + + @Override + public boolean isUpdateIdentity() { + return false; + } + + private String cleanupSubExpression(String pExpression) { + String lReturn = pExpression; + + lReturn = lReturn.trim(); + + if (lReturn.startsWith("(") && lReturn.endsWith(")")) { + lReturn = lReturn.substring(1, lReturn.length() - 1); + } + + lReturn = lReturn.toLowerCase(); + + lReturn = lReturn.replace("current_timestamp", "now"); + + + + lReturn = lReturn.replace("(", ""); + lReturn = lReturn.replace(")", ""); + lReturn = lReturn.replace("[", ""); + lReturn = lReturn.replace("]", ""); + lReturn = lReturn.replace(" ", ""); + + lReturn = lReturn.replace("=anyarray", "in"); + lReturn = lReturn.replace("::charactervarying", ""); + lReturn = lReturn.replace("::text", ""); + + return lReturn; + } + + private String cleanupExpression(String pExpression) { + String lReturn = ""; + + String[] lSplit = pExpression.split("'"); + boolean lIsIn = false; + for (int i = 0; i < lSplit.length; i++) { + if (lIsIn) { + lReturn += lSplit[i]; + } else { + lReturn += cleanupSubExpression(lSplit[i]); + } + lIsIn = !lIsIn; + if (i != lSplit.length - 1) { + lReturn += "'"; + } + } + + return lReturn; + } + + @Override + protected boolean isExpressionDifferentNotNull(String pExpression1, String pExpression2) { + return super.isExpressionDifferentNotNull(cleanupExpression(pExpression1), cleanupExpression(pExpression2)); + } + + public static void main(String[] args) { + System.out.println(new DatabaseHandlerPostgres().cleanupExpression( + "((status)::text = ANY ((ARRAY['GENEHMIGT'::characteR varying, 'WARTEN_AUF_GENEHMIGUNG'::character varying])::text[]))")); + System.out.println(new DatabaseHandlerPostgres().cleanupExpression( + "STATUS in ('GENEHMIGT','WARTEN_AUF_GENEHMIGUNG')")); + + } +} diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilder.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilder.java index cb1adc63..4ec0c27b 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilder.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilder.java @@ -59,10 +59,16 @@ public abstract class DdlBuilder { private Parameters parameters; + private DatabaseHandler databaseHandler; - public DdlBuilder( Parameters pParameters ) + protected DatabaseHandler getDatabaseHandler() { + return databaseHandler; + } + + public DdlBuilder( Parameters pParameters, DatabaseHandler pDatabaseHandler ) { parameters = pParameters; + databaseHandler = pDatabaseHandler; } public boolean isAllColumnsNew( List pColumns, TableDiff pTableDiff ) diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderHsqlDb.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderHsqlDb.java index 7fb57655..db84306d 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderHsqlDb.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderHsqlDb.java @@ -18,9 +18,9 @@ public class DdlBuilderHsqlDb extends DdlBuilder { - public DdlBuilderHsqlDb( Parameters pParameters ) + public DdlBuilderHsqlDb( Parameters pParameters, DatabaseHandler pDatabaseHandler ) { - super( pParameters ); + super( pParameters, pDatabaseHandler ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderMySql.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderMySql.java index e23f6c1d..d8a5f928 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderMySql.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderMySql.java @@ -18,9 +18,9 @@ public class DdlBuilderMySql extends DdlBuilder { - public DdlBuilderMySql( Parameters pParameters ) + public DdlBuilderMySql( Parameters pParameters, DatabaseHandler pDatabaseHandler ) { - super( pParameters ); + super( pParameters, pDatabaseHandler ); } @Override diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderOracle.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderOracle.java index a34891a7..f4a1add2 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderOracle.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderOracle.java @@ -2,8 +2,8 @@ public class DdlBuilderOracle extends DdlBuilder { - public DdlBuilderOracle( Parameters pParameters ) + public DdlBuilderOracle( Parameters pParameters, DatabaseHandler pDatabaseHandler ) { - super( pParameters ); + super( pParameters, pDatabaseHandler ); } } diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderPostgres.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderPostgres.java new file mode 100644 index 00000000..3ed7e922 --- /dev/null +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/DdlBuilderPostgres.java @@ -0,0 +1,242 @@ +package de.opitzconsulting.orcas.diff; + +import static de.opitzconsulting.origOrcasDsl.OrigOrcasDslPackage.Literals.*; + +import java.util.List; +import java.util.stream.Collectors; + +import de.opitzconsulting.orcas.orig.diff.ColumnDiff; +import de.opitzconsulting.orcas.orig.diff.IndexDiff; +import de.opitzconsulting.orcas.orig.diff.TableDiff; +import de.opitzconsulting.origOrcasDsl.CompressType; +import de.opitzconsulting.origOrcasDsl.DataType; +import de.opitzconsulting.origOrcasDsl.ParallelType; + +public class DdlBuilderPostgres extends DdlBuilder { + public DdlBuilderPostgres(Parameters pParameters, DatabaseHandler pDatabaseHandler) { + super(pParameters, pDatabaseHandler); + } + + @Override + protected String getDatatypeName(DataType pData_typeNew) { + if (pData_typeNew == DataType.VARCHAR2) { + return "VARCHAR"; + } + if (pData_typeNew == DataType.NUMBER) { + return "NUMERIC"; + } + + return super.getDatatypeName(pData_typeNew); + } + + @Override + protected String getColumnDatatype(ColumnDiff pColumnDiff) { + if (pColumnDiff.identityDiff.isNew) { + if (pColumnDiff.data_typeNew == DataType.SMALLINT) { + return "smallserial"; + } + if (pColumnDiff.data_typeNew == DataType.INT) { + return "serial"; + } + if (pColumnDiff.data_typeNew == DataType.BIGINT) { + return "bigserial"; + } + + throw new IllegalStateException("identity column cannot be used with datataype: " + pColumnDiff.data_typeNew); + } + return super.getColumnDatatype(pColumnDiff); + } + + @Override + protected String createColumnCreatePart(ColumnDiff pColumnDiff, boolean pWithoutNotNull) { + String lReturn = pColumnDiff.nameNew + " " + getColumnDatatype(pColumnDiff); + + if (pColumnDiff.default_valueNew != null) { + lReturn = lReturn + " default " + pColumnDiff.default_valueNew; + } + + if (pColumnDiff.notnullNew) { + if (!pWithoutNotNull) { + lReturn = lReturn + " not null"; + } + } + + return lReturn; + } + + @Override + public void recreateColumn(StatementBuilder p, TableDiff pTableDiff, ColumnDiff pColumnDiff) { + p.failIfAdditionsOnly("can't recreate columns"); + + String lTmpOldColumnameNew = "DTO_" + pColumnDiff.nameNew; + String lTmpNewColumnameNew = "DTN_" + pColumnDiff.nameNew; + + p.stmtStartAlterTableNoCombine(pTableDiff); + p.stmtAppend("add " + lTmpNewColumnameNew + " " + getColumnDatatype(pColumnDiff)); + if ("virtual".equals(pColumnDiff.virtualNew)) { + p.stmtAppend("as (" + pColumnDiff.default_valueNew + ") virtual"); + } + p.stmtDone(); + + if (!"virtual".equals(pColumnDiff.virtualNew)) { + p.addStmt("update " + pTableDiff.nameNew + " set " + lTmpNewColumnameNew + " = " + pColumnDiff.nameOld); + p.addStmt("commit"); + } + + p.addStmt("alter table " + pTableDiff.nameNew + " rename column " + pColumnDiff.nameOld + " to " + lTmpOldColumnameNew); + p.addStmt("alter table " + pTableDiff.nameNew + " rename column " + lTmpNewColumnameNew + " to " + pColumnDiff.nameNew); + p.addStmt("alter table " + pTableDiff.nameNew + " drop column " + lTmpOldColumnameNew); + + if (pColumnDiff.default_valueNew != null && !"virtual".equals(pColumnDiff.virtualNew)) { + p.stmtStart("alter table " + pTableDiff.nameNew + " modify ( " + pColumnDiff.nameNew + " default"); + p.stmtAppend(pColumnDiff.default_valueNew); + p.stmtAppend(")"); + p.stmtDone(); + } + + if (pColumnDiff.notnullNew) { + p.stmtStart("alter table " + pTableDiff.nameNew + " alter column " + pColumnDiff.nameNew); + p.stmtAppend("set not null"); + p.stmtDone(); + } + } + + @Override + public void createIndex( + StatementBuilder p, TableDiff pTableDiff, IndexDiff pIndexDiff, boolean pIsIndexParallelCreate) { + p.stmtStart("create"); + if (pIndexDiff.uniqueNew != null) { + p.stmtAppend(pIndexDiff.uniqueNew); + } + if (pIndexDiff.bitmapNew != null) { + p.stmtAppend("bitmap"); + } + p.stmtAppend("index"); + p.stmtAppend(pIndexDiff.consNameNew); + p.stmtAppend("on"); + p.stmtAppend(pTableDiff.nameNew); + p.stmtAppend("("); + if (pIndexDiff.function_based_expressionNew != null) { + p.stmtAppend(pIndexDiff.function_based_expressionNew); + } else { + p.stmtAppend(getColumnList(pIndexDiff.index_columnsDiff)); + } + p.stmtAppend(")"); + if (pIndexDiff.domain_index_expressionNew != null) { + p.stmtAppend(pIndexDiff.domain_index_expressionNew); + } else { + if (pIndexDiff.loggingNew != null) { + p.stmtAppend(pIndexDiff.loggingNew.getLiteral()); + } + } + if (pIndexDiff.tablespaceNew != null) { + p.stmtAppend("tablespace"); + p.stmtAppend(pIndexDiff.tablespaceNew); + } + if (pIndexDiff.globalNew != null) { + p.stmtAppend(pIndexDiff.globalNew.getLiteral()); + } + if (pIndexDiff.bitmapNew == null && pIndexDiff.compressionNew == CompressType.COMPRESS) { + p.stmtAppend("compress"); + } + if (pIndexDiff.compressionNew == CompressType.NOCOMPRESS) { + p.stmtAppend("nocompress"); + } + + if (pIndexDiff.parallelNew == ParallelType.PARALLEL) { + p.stmtAppend("parallel"); + if (pIndexDiff.parallel_degreeNew != null && pIndexDiff.parallel_degreeNew > 1) { + p.stmtAppend(" " + pIndexDiff.parallel_degreeNew); + } + } + } + + @Override + public Runnable getColumnDropHandler( + StatementBuilder p, TableDiff pTableDiff, List pColumnDiffList) { + Runnable lAdditionsOnlyAlternativeHandler = () -> + { + pColumnDiffList.stream()// + .filter(pColumnDiff -> pColumnDiff.notnullOld && pColumnDiff.default_valueOld == null)// + .forEach(pColumnDiff -> + { + p.stmtStartAlterTable(pTableDiff); + p.stmtAppend("alter column"); + p.stmtAppend(pColumnDiff.nameOld); + p.stmtAppend("drop not null"); + p.stmtDone(StatementBuilder.ADDITIONSONLY_ALTERNATIVE_COMMENT); + }); + }; + + return () -> + { + p.stmtStartAlterTableNoCombine(pTableDiff); + + p.stmtAppend("drop column"); + + p.stmtAppend(pColumnDiffList.stream().map(pColumnDiff -> pColumnDiff.nameOld).collect(Collectors.joining(","))); + p.stmtDone(lAdditionsOnlyAlternativeHandler); + }; + } + + @Override + public void alterColumnIfNeeded(StatementBuilderAlter p1, TableDiff pTableDiff, ColumnDiff pColumnDiff) { + p1.handleAlterBuilder()// + .ifDifferent(COLUMN__BYTEORCHAR)// + .ifDifferent(COLUMN__PRECISION)// + .ifDifferent(COLUMN__SCALE)// + .handle(p -> + { + p.stmtStartAlterTable(pTableDiff.nameNew); + p.stmtAppend("alter column"); + p.stmtAppend(pColumnDiff.nameNew + " type " + getColumnDatatype(pColumnDiff)); + p.stmtDone(); + }); + + p1.handleAlterBuilder()// + .ifDifferent(COLUMN__VIRTUAL) + .failIfAdditionsOnly("virtual".equals(pColumnDiff.virtualNew), "can't make existing column virtual") + .failIfAdditionsOnly(!"virtual".equals(pColumnDiff.virtualNew), "can't materialize virtual column") + .handle(p -> + { + + }); + + p1.handleAlterBuilder()// + .ifDifferent( + COLUMN__DEFAULT_VALUE, + getDatabaseHandler().isExpressionDifferent(pColumnDiff.default_valueNew, pColumnDiff.default_valueOld))// + .ignoreIfAdditionsOnly(pColumnDiff.default_valueNew == null)// + .failIfAdditionsOnly(pColumnDiff.default_valueOld != null, "can't change default")// + .handle(p -> + { + p.stmtStartAlterTable(pTableDiff); + p.stmtAppend(" alter " + pColumnDiff.nameNew); + + if (pColumnDiff.default_valueNew == null) { + p.stmtAppend("drop default"); + } else { + p.stmtAppend("set default"); + p.stmtAppend(pColumnDiff.default_valueNew); + } + + p.stmtDone(); + }); + + p1.handleAlterBuilder()// + .ifDifferent(COLUMN__NOTNULL)// + .ignoreIfAdditionsOnly(pColumnDiff.notnullNew)// + .handle(p -> + { + p.stmtStartAlterTable(pTableDiff); + p.stmtAppend("alter column"); + p.stmtAppend(pColumnDiff.nameNew); + if (pColumnDiff.notnullNew == false) { + p.stmtAppend("drop not null"); + } else { + p.stmtAppend("set not null"); + } + p.stmtDone(); + }); + } +} diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/LoadIstPostgres.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/LoadIstPostgres.java new file mode 100644 index 00000000..c5fb3064 --- /dev/null +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/LoadIstPostgres.java @@ -0,0 +1,896 @@ +package de.opitzconsulting.orcas.diff; + +import java.math.BigDecimal; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.emf.common.util.EList; + +import de.opitzconsulting.orcas.orig.diff.DiffRepository; +import de.opitzconsulting.orcas.sql.CallableStatementProvider; +import de.opitzconsulting.orcas.sql.WrapperIteratorResultSet; +import de.opitzconsulting.origOrcasDsl.Column; +import de.opitzconsulting.origOrcasDsl.ColumnIdentity; +import de.opitzconsulting.origOrcasDsl.ColumnRef; +import de.opitzconsulting.origOrcasDsl.CommentObjectType; +import de.opitzconsulting.origOrcasDsl.Constraint; +import de.opitzconsulting.origOrcasDsl.DataType; +import de.opitzconsulting.origOrcasDsl.FkDeleteRuleType; +import de.opitzconsulting.origOrcasDsl.ForeignKey; +import de.opitzconsulting.origOrcasDsl.Index; +import de.opitzconsulting.origOrcasDsl.IndexOrUniqueKey; +import de.opitzconsulting.origOrcasDsl.InlineComment; +import de.opitzconsulting.origOrcasDsl.LobStorage; +import de.opitzconsulting.origOrcasDsl.Model; +import de.opitzconsulting.origOrcasDsl.ModelElement; +import de.opitzconsulting.origOrcasDsl.ParallelType; +import de.opitzconsulting.origOrcasDsl.PrimaryKey; +import de.opitzconsulting.origOrcasDsl.Sequence; +import de.opitzconsulting.origOrcasDsl.Table; +import de.opitzconsulting.origOrcasDsl.UniqueKey; +import de.opitzconsulting.origOrcasDsl.impl.ColumnIdentityImpl; +import de.opitzconsulting.origOrcasDsl.impl.ColumnImpl; +import de.opitzconsulting.origOrcasDsl.impl.ColumnRefImpl; +import de.opitzconsulting.origOrcasDsl.impl.ConstraintImpl; +import de.opitzconsulting.origOrcasDsl.impl.ForeignKeyImpl; +import de.opitzconsulting.origOrcasDsl.impl.IndexImpl; +import de.opitzconsulting.origOrcasDsl.impl.InlineCommentImpl; +import de.opitzconsulting.origOrcasDsl.impl.LobStorageImpl; +import de.opitzconsulting.origOrcasDsl.impl.ModelImpl; +import de.opitzconsulting.origOrcasDsl.impl.PrimaryKeyImpl; +import de.opitzconsulting.origOrcasDsl.impl.SequenceImpl; +import de.opitzconsulting.origOrcasDsl.impl.TableImpl; +import de.opitzconsulting.origOrcasDsl.impl.UniqueKeyImpl; + +public class LoadIstPostgres extends LoadIst { + private Map> includeMap = new HashMap>(); + + private Map constraintMapForFK = new HashMap(); + private Map constraintTableMapForFK = new HashMap(); + + private Parameters _parameters; + + private CallableStatementProvider _callableStatementProvider; + + public LoadIstPostgres(CallableStatementProvider pCallableStatementProvider, Parameters pParameters) { + _callableStatementProvider = pCallableStatementProvider; + _parameters = pParameters; + } + + private void registerConstarintForFK(String pUkConstraintname, Table pTable, String pTableOwner, Object pConstarint) { + constraintMapForFK.put(getNameWithOwner(pUkConstraintname, pTableOwner), pConstarint); + constraintTableMapForFK.put(getNameWithOwner(pUkConstraintname, pTableOwner), pTable); + } + + @Override + public Model loadModel(boolean pWithSequeneceMayValueSelect) { + isIgnoredTable("TEST", "TEST"); + + Model pModel = new ModelImpl(); + + loadSequencesIntoModel(pModel, true); + + loadTablesIntoModel(pModel); + loadTableColumnsIntoModel(pModel); + + /* + * loadLobstorageIntoModel( pModel ); + */ + loadIndexesIntoModel(pModel); + loadIndexColumnsIntoModel(pModel); + /* + * loadIndexExpressionsIntoModel( pModel ); + */ + loadTableConstraintsIntoModel(pModel); + loadTableConstraintColumnsIntoModel(pModel); + loadTableForeignKeyConstraintColumnsIntoModel(pModel); + /* + * loadTableCommentsIntoModel( pModel ); loadTableColumnCommentsIntoModel( + * pModel ); + * + * updateForeignkeyDestdata( pModel ); + */ + + return pModel; + } + + // private String getExcludeWhere( String pExcludeWhere ) + // { + // if( pExcludeWhere.charAt( 0 ) == '@' ) + // { + // return "object_name like '%$%'"; + // } + // else + // { + // return pExcludeWhere; + // } + // } + + private void loadIgnoreCache(String pExcludeWhere, final String pType) { + if (!includeMap.containsKey(pType)) { + includeMap.put(pType, new ArrayList()); + + String lSql = "select tablename, tableowner, 0 is_exclude from " + getDataDictionaryView("tables"); + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (pResultSet.getInt("is_exclude") == 0) { + includeMap.get(pType).add(getNameWithOwner(pResultSet.getString("tablename"), pResultSet.getString("tableowner"))); + } + } + }.execute(); + + // String lSql = "select object_name, owner, case when ( " + + // getExcludeWhere( pExcludeWhere ) + " ) then 1 else 0 end is_exclude + // from " + getDataDictionaryView( "objects" ) + " where object_type=?"; + // + // new WrapperIteratorResultSet( lSql, getCallableStatementProvider(), + // Collections.singletonList( pType ) ) + // { + // @Override + // protected void useResultSetRow( ResultSet pResultSet ) throws + // SQLException + // { + // if( pResultSet.getInt( "is_exclude" ) == 0 ) + // { + // includeMap.get( pType ).add( getNameWithOwner( pResultSet.getString( + // "object_name" ), pResultSet.getString( "owner" ) ) ); + // } + // } + // }.execute(); + } + } + + private boolean isIgnored(String pName, String pOwner, String pExcludeWhere, String pType) { + loadIgnoreCache(pExcludeWhere, pType); + + return !includeMap.get(pType).contains(getNameWithOwner(pName, pOwner)); + } + + private boolean isIgnoredTable(String pString, String pOwner) { + if (pString.equalsIgnoreCase(OrcasScriptRunner.ORCAS_UPDATES_TABLE)) { + return true; + } + + return isIgnored(pString, pOwner, _parameters.getExcludewheretable(), "TABLE"); + } + + private boolean isIgnoredSequence(String pString, String pOwner) { + return isIgnored(pString, pOwner, _parameters.getExcludewheretable(), "SEQUENCE"); + } + + private int toInt(BigDecimal pBigDecimal) { + if (pBigDecimal == null) { + return DiffRepository.getNullIntValue(); + } + return pBigDecimal.intValue(); + } + + private interface DegreeHandler { + void setDegree(ParallelType pParallelType, int ParallelDegree); + } + + private void handleDegree(String pDegree, DegreeHandler pDegreeHandler) { + if (pDegree != null) { + ParallelType lParallelType; + int lParallelDegree = DiffRepository.getNullIntValue(); + + if (pDegree.equals("1")) { + lParallelType = ParallelType.NOPARALLEL; + } else { + lParallelType = ParallelType.PARALLEL; + if (!pDegree.equals("DEFAULT")) { + lParallelDegree = toInt(new BigDecimal(pDegree)); + } + } + + pDegreeHandler.setDegree(lParallelType, lParallelDegree); + } + } + + private String getNameWithOwner(String pObjectName, String pOwner) { + if (_parameters.getMultiSchema()) { + return pOwner + "." + pObjectName; + } else { + return pObjectName; + } + } + + private Table findTable(Model pModel, String pTablename, String pOwner) { + for (ModelElement lModelElement : pModel.getModel_elements()) { + if (lModelElement instanceof Table) { + if (((Table) lModelElement).getName().equals(getNameWithOwner(pTablename, pOwner))) { + return (Table) lModelElement; + } + } + } + + throw new IllegalStateException("Table not found: " + pTablename); + } + + private Index findIndex(Model pModel, String pTablename, String pTableOwner, String pIndexname, String pIndexOwner) { + for (IndexOrUniqueKey lIndexOrUniqueKey : findTable(pModel, pTablename, pTableOwner).getInd_uks()) { + if (lIndexOrUniqueKey instanceof Index) { + if (((Index) lIndexOrUniqueKey).getConsName().equals(getNameWithOwner(pIndexname, pIndexOwner))) { + return (Index) lIndexOrUniqueKey; + } + } + } + + throw new IllegalStateException("Index not found: " + pTablename + " " + pIndexname); + } + + private UniqueKey findUniqueKey(Model pModel, String pTablename, String pOwner, String pUniquekeyname) { + for (IndexOrUniqueKey lIndexOrUniqueKey : findTable(pModel, pTablename, pOwner).getInd_uks()) { + if (lIndexOrUniqueKey instanceof UniqueKey) { + if (((UniqueKey) lIndexOrUniqueKey).getConsName().equals(pUniquekeyname)) { + return (UniqueKey) lIndexOrUniqueKey; + } + } + } + + throw new IllegalStateException("UK not found: " + pTablename + " " + pUniquekeyname); + } + + private ForeignKey findForeignKey(Model pModel, String pTablename, String pOwner, String pForeignkeyname) { + for (ForeignKey lForeignKey : findTable(pModel, pTablename, pOwner).getForeign_keys()) { + if (lForeignKey.getConsName().equals(pForeignkeyname)) { + return lForeignKey; + } + } + + throw new IllegalStateException("FK not found: " + pTablename + " " + pForeignkeyname); + } + + private void loadTableColumnsIntoModel(final Model pModel) { + String lSql; + + lSql = "select a.attnum as ordinal_position,\n" + + " a.attname as column_name,\n" + + " t.typname as data_type,\n" + + " a.attlen as attlen,\n" + + " a.attnotnull = false as is_nullable,\n" + + " c.relname as table_name,\n" + + " case\n" + + " when atttypmod = -1\n" + + " then null\n" + + " else ((atttypmod - 4) >> 16) & 65535\n" + + " end as precision,\n" + + " case\n" + + " when atttypmod = -1 then null\n" + + " else (atttypmod - 4) & 65535\n" + + " end as scale,\n" + + " pg_get_serial_sequence(a.attrelid::regclass::text, a.attname) is not null as is_generated,\n" + + " (select adsrc\n" + + " from pg_attrdef ad\n" + + " where ad.adrelid = c.oid\n" + + " and ad.adnum = a.attnum\n" + + " ) as column_default" + + " from pg_class c,\n" + + " pg_attribute a,\n" + + " pg_type t,\n" + + " pg_namespace n\n" + + " where c.relkind = 'r'\n" + + " and a.attnum > 0\n" + + " and a.attrelid = c.oid\n" + + " and a.atttypid = t.oid\n" + + " and c.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n"; + + if (_parameters.isOrderColumnsByName()) { + lSql += " order by c.relname, a.attname, a.attnum"; + } else { + lSql += " order by c.relname, a.attnum, a.attname"; + } + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + Column lColumn = new ColumnImpl(); + + lColumn.setName(pResultSet.getString("column_name")); + + lColumn.setNotnull(!pResultSet.getBoolean("is_nullable")); + + if (pResultSet.getString("data_type").startsWith("numeric")) { + lColumn.setData_type(DataType.NUMBER); + lColumn.setPrecision(pResultSet.getInt("precision")); + lColumn.setScale(pResultSet.getInt("scale")); + } + if (pResultSet.getString("data_type").startsWith("int2")) { + lColumn.setData_type(DataType.SMALLINT); + } + if (pResultSet.getString("data_type").startsWith("int4")) { + lColumn.setData_type(DataType.INT); + } + if (pResultSet.getString("data_type").startsWith("int8")) { + lColumn.setData_type(DataType.BIGINT); + } + if (pResultSet.getString("data_type").startsWith("bit")) { + lColumn.setData_type(DataType.BIT); + } + if (pResultSet.getString("data_type").startsWith("blob")) { + lColumn.setData_type(DataType.BLOB); + } + if (pResultSet.getString("data_type").startsWith("clob")) { + lColumn.setData_type(DataType.CLOB); + } + if (pResultSet.getString("data_type").startsWith("varchar")) { + lColumn.setData_type(DataType.VARCHAR2); + lColumn.setPrecision(pResultSet.getInt("scale")); + } + if (pResultSet.getString("data_type").startsWith("char")) { + lColumn.setData_type(DataType.CHAR); + lColumn.setPrecision(pResultSet.getInt("scale")); + } + if (pResultSet.getString("data_type").startsWith("datetime")) { + lColumn.setData_type(DataType.DATE); + } + if (pResultSet.getString("data_type").startsWith("timestamp")) { + lColumn.setData_type(DataType.TIMESTAMP); + } + + if (pResultSet.getBoolean("is_generated")) { + ColumnIdentity lColumnIdentity = new ColumnIdentityImpl(); + + lColumnIdentity.setBy_default("default"); + lColumnIdentity.setOn_null("null"); + + lColumn.setIdentity(lColumnIdentity); + } else { + if (null != pResultSet.getString("column_default")) { + lColumn.setDefault_value(pResultSet.getString("column_default")); + } + } + + findTable(pModel, pResultSet.getString("table_name"), null).getColumns().add(lColumn); + } + } + }.execute(); + + } + + private String getDataDictionaryView(String pName) { + String lViewName = "pg_" + pName; + + return "(select pg_" + pName + ".*, user as owner from " + lViewName + " where schemaname = 'public' and tableowner = user ) " + pName; + } + + private String getDataDictionaryViewNoTableowner(String pName) { + String lViewName = "pg_" + pName; + + return "(select pg_" + pName + ".*, user as owner from " + lViewName + " where schemaname = 'public' ) " + pName; + } + + private String getDataDictionaryViewInformationSchema(String pName) { + String lViewName = "information_schema." + pName; + + return "(select " + pName + ".*, user as owner from " + lViewName + " where table_schema = 'public' and table_catalog = user ) " + pName; + } + + private void loadIndexesIntoModel(final Model pModel) { + String lSql = "select ct.relname as table_name,\n" + + " ci.relname as index_name\n" + + " from pg_class ct,\n" + + " pg_class ci,\n" + + " pg_namespace n,\n" + + " pg_index i\n" + + " where i.indrelid = ct.oid\n" + + " and i.indexrelid = ci.oid\n" + + " and ct.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n" + + " and indisunique = false\n" + + " order by ci.relname"; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + final Index lIndex = new IndexImpl(); + + lIndex.setConsName(getNameWithOwner(pResultSet.getString("index_name"), null)); + + findTable(pModel, pResultSet.getString("table_name"), null).getInd_uks().add(lIndex); + } + } + }.execute(); + } + + private void loadIndexColumnsIntoModel(final Model pModel) { + String lSql = "select a.attname as column_name,\n" + + " ct.relname as table_name,\n" + + " ci.relname as index_name\n" + + " from pg_class ct,\n" + + " pg_class ci,\n" + + " pg_attribute a,\n" + + " pg_type t,\n" + + " pg_namespace n,\n" + + " pg_index i\n" + + " where i.indrelid = ct.oid\n" + + " and i.indexrelid = ci.oid\n" + + " and a.attnum > 0\n" + + " and a.attrelid = ci.oid\n" + + " and a.atttypid = t.oid\n" + + " and ct.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n" + + " and indisunique = false\n" + + " order by ci.relname, a.attnum"; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + ColumnRef lColumnRef = new ColumnRefImpl(); + + lColumnRef.setColumn_name(pResultSet.getString("column_name")); + + findIndex( + pModel, + pResultSet.getString("table_name"), + null, + pResultSet.getString("index_name"), + null).getIndex_columns().add(lColumnRef); + } + } + }.execute(); + } + + private void setIndexColumnExpression( + Model pModel, + String pTablename, + String pTableOwner, + String pIndexName, + String pIndexOwner, + int pColumnPosition, + String pExpression, + int pMaxColumnPositionForInd) { + Index lIndex = findIndex(pModel, pTablename, pTableOwner, pIndexName, pIndexOwner); + + // TODO ltrim(p_expression,',') + lIndex.getIndex_columns().get(pColumnPosition - 1).setColumn_name(pExpression.replace("\"", "").replace(" ", "")); + + if (pColumnPosition == pMaxColumnPositionForInd) { + String lString = null; + + for (ColumnRef lColumnRef : lIndex.getIndex_columns()) { + if (lString == null) { + lString = ""; + } else { + lString += ","; + } + + lString += lColumnRef.getColumn_name(); + } + + lIndex.setFunction_based_expression(lString); + lIndex.getIndex_columns().clear(); + } + + } + + private void loadIndexExpressionsIntoModel(final Model pModel) { + String lSql = "" + // + " select ind_expressions.table_name," + // + " indexes.table_owner," + // + " ind_expressions.index_name," + // + " ind_expressions.owner," + // + " column_position," + // + " column_expression," + // + " max (column_position)" + // + " over" + // + " (" + // + " partition by" + // + " ind_expressions.table_name," + // + " ind_expressions.index_name" + // + " ) as max_column_position_for_index" + // + " from " + getDataDictionaryView("ind_expressions") + "," + // + " " + getDataDictionaryView("indexes") + // + " where generated = 'N'" + // + " and ind_expressions.index_name = indexes.index_name" + // + " and ind_expressions.owner = indexes.owner" + // + " and (indexes.index_name,indexes.table_name,indexes.owner) not in" + // + " (" + // + " select constraint_name," + // + " table_name," + // + " owner" + // + " from " + getDataDictionaryView("constraints") + // + " where constraint_type in ( 'U', 'P' )" + // + " and constraint_name = constraints.index_name" + // + " )" + // + " order by table_name," + // + " index_name," + // + " column_position" + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), pResultSet.getString("owner"))) { + setIndexColumnExpression( + pModel, + pResultSet.getString("table_name"), + pResultSet.getString("table_owner"), + pResultSet.getString("index_name"), + pResultSet.getString("owner"), + pResultSet.getInt("column_position"), + pResultSet.getString("column_expression"), + pResultSet.getInt("max_column_position_for_index")); + } + } + }.execute(); + } + + private void loadSequencesIntoModel(final Model pModel, final boolean pWithSequeneceMayValueSelect) { + String lSql = "" + // + " select relname" + // + " from pg_class" + // + " where relkind = 'S'" + // + " order by relname " + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredSequence(pResultSet.getString("relname"), null)) { + Sequence lSequence = new SequenceImpl(); + + lSequence.setSequence_name(getNameWithOwner(pResultSet.getString("relname"), null)); + + /* + * lSequence.setIncrement_by( toInt( pResultSet.getBigDecimal( + * "increment_by" ) ) ); if( pWithSequeneceMayValueSelect ) { + * lSequence.setMax_value_select( pResultSet.getString( "last_number" + * ) ); } lSequence.setCache( toInt( pResultSet.getBigDecimal( + * "cache_size" ) ) ); lSequence.setMinvalue( toInt( + * pResultSet.getBigDecimal( "min_value" ) ) ); lSequence.setMaxvalue( + * toInt( pResultSet.getBigDecimal( "max_value" ) ) ); + * + * if( "Y".equals( pResultSet.getString( "cycle_flag" ) ) ) { + * lSequence.setCycle( CycleType.CYCLE ); } else { lSequence.setCycle( + * CycleType.NOCYCLE ); } + * + * if( "Y".equals( pResultSet.getString( "order_flag" ) ) ) { + * lSequence.setOrder( OrderType.ORDER ); } else { lSequence.setOrder( + * OrderType.NOORDER ); } + */ + + pModel.getModel_elements().add(lSequence); + } + } + }.execute(); + } + + private void loadTableConstraintsIntoModel(final Model pModel) { + String lSql = "select conname as constraint_name,\n" + + " c.relname as table_name,\n" + + " contype as constraint_type,\n" + + " confdeltype as delete_rule,\n" + + " consrc\n" + + " from pg_constraint co,\n" + + " pg_class c,\n" + + " pg_namespace n\n" + + " where co.conrelid = c.oid\n" + + " and c.relkind = 'r'\n" + + " and c.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n" + + " order by c.relname, conname"; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + Table lTable = findTable(pModel, pResultSet.getString("table_name"), null); + + if ("p".equals(pResultSet.getString("constraint_type"))) { + PrimaryKey lPrimaryKey = new PrimaryKeyImpl(); + + lPrimaryKey.setConsName(pResultSet.getString("constraint_name")); + + registerConstarintForFK(pResultSet.getString("constraint_name"), lTable, null, lPrimaryKey); + + lTable.setPrimary_key(lPrimaryKey); + } + + if ("u".equals(pResultSet.getString("constraint_type"))) { + UniqueKey lUniqueKey = new UniqueKeyImpl(); + + lUniqueKey.setConsName(pResultSet.getString("constraint_name")); + + registerConstarintForFK(pResultSet.getString("constraint_name"), lTable, null, lUniqueKey); + + lTable.getInd_uks().add(lUniqueKey); + } + + if ("f".equals(pResultSet.getString("constraint_type"))) { + ForeignKey lForeignKey = new ForeignKeyImpl(); + + lForeignKey.setConsName(pResultSet.getString("constraint_name")); + + if ("r".equals(pResultSet.getString("delete_rule"))) { + lForeignKey.setDelete_rule(FkDeleteRuleType.NO_ACTION); + } + if ("a".equals(pResultSet.getString("delete_rule"))) { + lForeignKey.setDelete_rule(FkDeleteRuleType.NO_ACTION); + } + if ("n".equals(pResultSet.getString("delete_rule"))) { + lForeignKey.setDelete_rule(FkDeleteRuleType.SET_NULL); + } + if ("c".equals(pResultSet.getString("delete_rule"))) { + lForeignKey.setDelete_rule(FkDeleteRuleType.CASCADE); + } + + lTable.getForeign_keys().add(lForeignKey); + } + + if ("c".equals(pResultSet.getString("constraint_type"))) { + Constraint lConstraint = new ConstraintImpl(); + + lConstraint.setConsName(pResultSet.getString("constraint_name")); + + String lConsrc = pResultSet.getString("consrc"); + lConstraint.setRule(lConsrc.substring(1, lConsrc.length() - 1).toUpperCase()); + + lTable.getConstraints().add(lConstraint); + } + } + } + }.execute(); + } + + private void loadTableConstraintColumnsIntoModel(final Model pModel) { + String lSql = "select a.attname as column_name,\n" + + " ct.relname as table_name,\n" + + " c.conname as constraint_name,\n" + + " contype as constraint_type\n" + + " from pg_class ct,\n" + + " pg_attribute a,\n" + + " pg_namespace n,\n" + + " pg_constraint c\n" + + " where c.conrelid = ct.oid\n" + + " and a.attnum > 0\n" + + " and a.attnum=ANY(c.conkey)\n" + + " and a.attrelid = ct.oid\n" + + " and ct.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n" + + " and contype != 'c'\n" + + " and contype != 'f'\n" + + " order by ct.relname, a.attnum"; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + ColumnRef lColumnRef = new ColumnRefImpl(); + + lColumnRef.setColumn_name(pResultSet.getString("column_name")); + + if ("p".equals(pResultSet.getString("constraint_type"))) { + findTable(pModel, pResultSet.getString("table_name"), null) + .getPrimary_key() + .getPk_columns() + .add(lColumnRef); + } + + if ("u".equals(pResultSet.getString("constraint_type"))) { + findUniqueKey( + pModel, + pResultSet.getString("table_name"), + null, + pResultSet.getString("constraint_name")).getUk_columns().add(lColumnRef); + } + } + } + }.execute(); + } + + private void loadTableForeignKeyConstraintColumnsIntoModel(final Model pModel) { + String lSql = "select a.attname as column_name,\n" + + " ar.attname as referenced_column_name,\n" + + " ct.relname as table_name,\n" + + " ctr.relname as referenced_table_name,\n" + + " c.conname as constraint_name\n" + + " from pg_class ct,\n" + + " pg_class ctr,\n" + + " pg_attribute a,\n" + + " pg_attribute ar,\n" + + " pg_namespace n,\n" + + " pg_constraint c\n" + + " where c.conrelid = ct.oid\n" + + " and c.confrelid = ctr.oid\n" + + " and a.attnum > 0\n" + + " and a.attrelid = ct.oid\n" + + " and a.attnum=ANY(c.conkey)\n" + + " and ar.attnum > 0\n" + + " and ar.attrelid = ctr.oid\n" + + " and ar.attnum=ANY(c.confkey)\n" + + " and ct.relnamespace = n.oid\n" + + " and n.nspname = 'public'\n" + + " and contype = 'f'\n" + + " and array_position(c.conkey,a.attnum) = array_position(c.confkey,ar.attnum)\n" + + " order by ct.relname, array_position(c.conkey,a.attnum)"; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), null)) { + ColumnRef lColumnRef = new ColumnRefImpl(); + + lColumnRef.setColumn_name(pResultSet.getString("column_name")); + + ForeignKey + lForeignKey = + findForeignKey( + pModel, + pResultSet.getString("table_name"), + null, + pResultSet.getString("constraint_name")); + lForeignKey.getSrcColumns().add(lColumnRef); + lForeignKey.setDestTable(pResultSet.getString("referenced_table_name")); + + ColumnRef lDestColumnRef = new ColumnRefImpl(); + lDestColumnRef.setColumn_name(pResultSet.getString("referenced_column_name")); + lForeignKey.getDestColumns().add(lDestColumnRef); + } + } + }.execute(); + } + + private void loadTableCommentsIntoModel(final Model pModel) { + String lSql = "" + // + " select table_name," + // + " owner," + // + " comments" + // + " from " + getDataDictionaryView("tab_comments") + // + " where comments is not null" + // + " order by table_name" + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), pResultSet.getString("owner"))) { + InlineComment lInlineComment = new InlineCommentImpl(); + + lInlineComment.setComment(pResultSet.getString("comments")); + + lInlineComment.setComment_object(CommentObjectType.TABLE); + + findTable(pModel, pResultSet.getString("table_name"), pResultSet.getString("owner")).getComments().add(lInlineComment); + } + } + }.execute(); + } + + private void loadTableColumnCommentsIntoModel(final Model pModel) { + String lSql = "" + // + " select table_name," + // + " column_name," + // + " owner," + // + " comments" + // + " from " + getDataDictionaryView("col_comments") + // + " where comments is not null" + // + " order by table_name," + // + " column_name" + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), pResultSet.getString("owner"))) { + InlineComment lInlineComment = new InlineCommentImpl(); + + lInlineComment.setComment(pResultSet.getString("comments")); + + lInlineComment.setColumn_name(pResultSet.getString("column_name")); + + lInlineComment.setComment_object(CommentObjectType.COLUMN); + + findTable(pModel, pResultSet.getString("table_name"), pResultSet.getString("owner")).getComments().add(lInlineComment); + } + } + }.execute(); + } + + private void loadLobstorageIntoModel(final Model pModel) { + String lSql = "" + // + " select table_name," + // + " owner," + // + " column_name," + // + " tablespace_name" + // + " from " + getDataDictionaryView("lobs") + // + " order by table_name," + // + " column_name" + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("table_name"), pResultSet.getString("owner"))) { + LobStorage lLobStorage = new LobStorageImpl(); + + lLobStorage.setColumn_name(pResultSet.getString("column_name")); + + Table lTable = findTable(pModel, pResultSet.getString("table_name"), pResultSet.getString("owner")); + + if (findColumn(lTable, lLobStorage.getColumn_name()) != null) { + lTable.getLobStorages().add(lLobStorage); + } + } + } + + private Column findColumn(Table pTable, String pColumnName) { + for (Column lColumn : pTable.getColumns()) { + if (lColumn.getName().equals(pColumnName)) { + return lColumn; + } + } + + return null; + } + }.execute(); + } + + private void updateForeignkeyDestdata(Model pModel) { + for (ModelElement lModelElement : pModel.getModel_elements()) { + if (lModelElement instanceof Table) { + for (ForeignKey lForeignKey : ((Table) lModelElement).getForeign_keys()) { + String lRefConstraintName = lForeignKey.getDestTable(); + + lForeignKey.setDestTable(constraintTableMapForFK.get(lRefConstraintName).getName()); + + Object lConstraint = constraintMapForFK.get(lRefConstraintName); + + EList lColumns = null; + + if (lConstraint instanceof PrimaryKey) { + lColumns = ((PrimaryKey) lConstraint).getPk_columns(); + } + + if (lConstraint instanceof UniqueKey) { + lColumns = ((UniqueKey) lConstraint).getUk_columns(); + } + + for (ColumnRef lColumnRef : lColumns) { + ColumnRef lNewColumnRef = new ColumnRefImpl(); + + lNewColumnRef.setColumn_name(lColumnRef.getColumn_name()); + + lForeignKey.getDestColumns().add(lNewColumnRef); + } + } + } + } + } + + private void loadTablesIntoModel(final Model pModel) { + String lSql = "" + // + " select tables.tablename," + // + " tables.tableowner" + // + " from " + getDataDictionaryView("tables") + // + " order by tablename" + // + ""; + + new WrapperIteratorResultSet(lSql, getCallableStatementProvider()) { + @Override + protected void useResultSetRow(ResultSet pResultSet) throws SQLException { + if (!isIgnoredTable(pResultSet.getString("tablename"), pResultSet.getString("tableowner"))) { + final Table lTable = new TableImpl(); + + lTable.setName(getNameWithOwner(pResultSet.getString("tablename"), pResultSet.getString("tableowner"))); + + pModel.getModel_elements().add(lTable); + } + } + }.execute(); + } + + private CallableStatementProvider getCallableStatementProvider() { + return _callableStatementProvider; + } +} diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/Orcas.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/Orcas.java index f8bd5858..0a984d25 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/Orcas.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/Orcas.java @@ -111,6 +111,11 @@ protected DatabaseHandler getDatabaseHandler() return new DatabaseHandlerH2(); } + if( getParameters().getJdbcConnectParameters().getJdbcUrl().startsWith( "jdbc:postgresql" ) ) + { + return new DatabaseHandlerPostgres(); + } + return new DatabaseHandlerOracle(); } diff --git a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/OrcasDiff.java b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/OrcasDiff.java index fd2eede8..607dde42 100644 --- a/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/OrcasDiff.java +++ b/orcas_core/build_source/orcas_diff/src/main/java/de/opitzconsulting/orcas/diff/OrcasDiff.java @@ -315,7 +315,7 @@ private void updateIsRecreateNeeded( ModelDiff pModelDiff ) { setRecreateNeededFor( lConstraintDiff )// .ifDifferentName( CONSTRAINT__CONS_NAME, oldContraintNames, lConstraintDiff.consNameNew, lConstraintDiff.consNameOld, databaseHandler.isRenameConstraint() )// - .ifDifferent( CONSTRAINT__RULE )// + .ifDifferent( CONSTRAINT__RULE, databaseHandler.isExpressionDifferent(lConstraintDiff.ruleNew,lConstraintDiff.ruleOld) )// .ifDifferent( CONSTRAINT__DEFERRTYPE )// .calculate(); }