diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 9463411..97f6d7e 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -2000 \ No newline at end of file +2017 \ No newline at end of file diff --git a/Patcher/DB/ForeignKeyConstraint.cs b/Patcher/DB/ForeignKeyConstraint.cs index 04a2d0d..a261915 100644 --- a/Patcher/DB/ForeignKeyConstraint.cs +++ b/Patcher/DB/ForeignKeyConstraint.cs @@ -24,6 +24,7 @@ namespace Patcher.DB Cascade, SetNull, SetDefault, + Restrict, } public readonly string column; diff --git a/Patcher/DB/PostgresDBTraits.cs b/Patcher/DB/PostgresDBTraits.cs index 60a0e91..13a8a39 100644 --- a/Patcher/DB/PostgresDBTraits.cs +++ b/Patcher/DB/PostgresDBTraits.cs @@ -176,67 +176,161 @@ namespace Patcher.DB { private static string GetStringRepresentation(ForeignKeyConstraint.ReferentialAction action) { switch(action) { case ForeignKeyConstraint.ReferentialAction.NoAction: - return "NO ACTION"; + return "a"; case ForeignKeyConstraint.ReferentialAction.Cascade: - return "CASCADE"; + return "c"; case ForeignKeyConstraint.ReferentialAction.SetNull: - return "SET NULL"; + return "n"; case ForeignKeyConstraint.ReferentialAction.SetDefault: - return "SET DEFAULT"; + return "d"; + case ForeignKeyConstraint.ReferentialAction.Restrict: + return "r"; default: throw new ApplicationException("Unknown referential action"); } } private void CheckConstraint(Func commandCreator, ForeignKeyConstraint constraint) { + + Int64 referencedTableOid; + + Int16[] attnums; + Int16[] fattnums; + using(DbCommand command = commandCreator()) { - command.CommandText = string.Format("\\d {0}", _EscapeName(constraint.name)); + command.CommandText = "select c.* from pg_constraint c join pg_class r on c.conrelid = r.oid where r.relname = :ptable and c.conname = :pconstraint"; + AddParam(command, "ptable", DbType.String, constraint.table); + AddParam(command, "pconstraint", DbType.String, constraint.name); + using(var reader = ExecuteReader(command)) { - int row = 0; - while(reader.Read()) { - Logger.instance.Log("Row #" + row); - for(int j=0; j commandCreator, UniqueConstraint constraint) { + + Int16[] attnums = null; + using(DbCommand command = commandCreator()) { - command.CommandText = string.Format("\\d {0}", _EscapeName(constraint.name)); + command.CommandText = "select c.* from pg_constraint c join pg_class r on c.conrelid = r.oid where r.relname = :ptable and c.conname = :pconstraint"; + AddParam(command, "ptable", DbType.String, constraint.table); + AddParam(command, "pconstraint", DbType.String, constraint.name); + using(var reader = ExecuteReader(command)) { - int row = 0; + if(!reader.Read()) { + throw new FormattableException("Constraint {0}.{1} not found", constraint.table, constraint.name); + } + + if(reader.GetValue("contype").ToString() != "u") { + throw new FormattableException("Constraint {0}.{1} wrong type: expected {2}, got {3}", constraint.table, constraint.name, "C", reader.GetValue("contype")); + } + + attnums = (Int16[])reader.GetValue("conkey"); + } + } + + using(DbCommand command = commandCreator()) { + command.CommandText = string.Format("SELECT a.attnum, a.attname AS field, t.typname AS type, a.attlen AS length, a.atttypmod AS lengthvar, a.attnotnull AS notnull, d.adsrc AS defaultvalue FROM pg_attribute a JOIN pg_class c ON a.attrelid = c.oid JOIN pg_type t ON a.atttypid = t.oid LEFT JOIN pg_attrdef d ON c.oid = d.adrelid AND a.attnum = d.adnum WHERE c.relname = :ptable and a.attnum in ({0})", string.Join(", ", (from i in Enumerable.Range(0, attnums.Length) select ":pattnum" + i).ToArray())); + AddParam(command, "ptable", DbType.String, constraint.table); + for(int i=0; i dbColumns = new HashSet(); while(reader.Read()) { - Logger.instance.Log("Row #" + row); - for(int j=0; j commandCreator, CheckConstraint constraint) { using(DbCommand command = commandCreator()) { - command.CommandText = string.Format("\\d {0}", _EscapeName(constraint.name)); + command.CommandText = "select c.* from pg_constraint c join pg_class r on c.conrelid = r.oid where r.relname = :ptable and c.conname = :pconstraint"; + AddParam(command, "ptable", DbType.String, constraint.table); + AddParam(command, "pconstraint", DbType.String, constraint.name); using(var reader = ExecuteReader(command)) { - int row = 0; - while(reader.Read()) { - Logger.instance.Log("Row #" + row); - for(int j=0; j commandCreator, AbstractConstraint constraint) { diff --git a/Patcher/DB/SQLQueryManager.cs b/Patcher/DB/SQLQueryManager.cs index 91f9218..4256b1a 100644 --- a/Patcher/DB/SQLQueryManager.cs +++ b/Patcher/DB/SQLQueryManager.cs @@ -95,6 +95,7 @@ namespace Patcher.DB /// /// SQL-92, page 274 + /// SQL:1999 added a support for ON DELETE RESTRICT, and both Postgres and Oracle support it in their current versions /// private static string _ReferentialAction(ForeignKeyConstraint.ReferentialAction action) { @@ -108,6 +109,8 @@ namespace Patcher.DB return "SET NULL"; case ForeignKeyConstraint.ReferentialAction.SetDefault: return "SET DEFAULT"; + case ForeignKeyConstraint.ReferentialAction.Restrict: + return "RESTRICT"; default: throw new ApplicationException(string.Format("Unknown action {0}", action)); } diff --git a/Patcher/Data/Patch/AtomicPatch.cs b/Patcher/Data/Patch/AtomicPatch.cs index 1bd6a93..add6f31 100644 --- a/Patcher/Data/Patch/AtomicPatch.cs +++ b/Patcher/Data/Patch/AtomicPatch.cs @@ -51,6 +51,7 @@ namespace Patcher.Data.Patch } rollbackInfos.Add(new XElement("command", new XAttribute("num", i), commandRollbackInfoContent)); } + throw new ApplicationException("safety switch"); return new XDocument(new XElement("rollbackInfo", rollbackInfos.ToArray())); } diff --git a/Patcher/Data/XMLParser.cs b/Patcher/Data/XMLParser.cs index b99e77d..a5cf9b8 100644 --- a/Patcher/Data/XMLParser.cs +++ b/Patcher/Data/XMLParser.cs @@ -25,6 +25,8 @@ namespace Patcher.Data return ForeignKeyConstraint.ReferentialAction.SetNull; case "setDefault": return ForeignKeyConstraint.ReferentialAction.SetDefault; + case "restrict": + return ForeignKeyConstraint.ReferentialAction.Restrict; default: throw new FormattableException("Unknown referential action {0}", element.Value); } diff --git a/Patcher/Resources/IPatch.xsd b/Patcher/Resources/IPatch.xsd index a64c6cc..f20a9a7 100644 --- a/Patcher/Resources/IPatch.xsd +++ b/Patcher/Resources/IPatch.xsd @@ -15,7 +15,7 @@ - + @@ -38,6 +38,7 @@ +