private static string FormatMessage(ObjectName tableName, string constraintName, string[] columnNames, ConstraintDeferrability deferrability) { return String.Format("{0} UNIQUE KEY violation for constraint '{1}({2})' on table '{3}'.", deferrability.AsDebugString(), constraintName, String.Join(", ", columnNames), tableName); }
private static string FormatMessage(ObjectName tableName, string constraintName, string[] columnNames, ObjectName refTableName, string[] refColumnNames, ConstraintDeferrability deferrability) { return String.Format("{0} FOREIGN KEY violation for constraint '{1}({2})' referencing '{3}({4})'", deferrability.AsDebugString(), constraintName, String.Join(", ", columnNames), refTableName, String.Join(", ", refColumnNames)); }
public static void CheckRemoveConstraintViolations(this ITransaction transaction, ITable table, int[] rowIndices, ConstraintDeferrability deferred) { // Quick exit case if (rowIndices == null || rowIndices.Length == 0) return; var tableInfo = table.TableInfo; var tableName = tableInfo.TableName; // Check any imported foreign key constraints. // This ensures that a referential reference can not be removed making // it invalid. var foreignConstraints = transaction.QueryTableImportedForeignKeys(tableName); foreach (var reference in foreignConstraints) { if (deferred == ConstraintDeferrability.InitiallyDeferred || reference.Deferred == ConstraintDeferrability.InitiallyImmediate) { // For each row removed from this column foreach (int rowIndex in rowIndices) { // Make sure the referenced record exists // Return the count of records where the given row of // ref_table_name(columns, ...) IN // table_name(ref_columns, ...) int rowCount = RowCountOfReferenceTable(transaction, rowIndex, reference.ForeignTable, reference.ForeignColumnNames, reference.TableName, reference.ColumnNames, true); // There must be 0 references otherwise the delete isn't allowed to // happen. if (rowCount > 0) { throw new ConstraintViolationException(SqlModelErrorCodes.ForeignKeyViolation, deferred.AsDebugString() + " foreign key constraint violation " + "on delete (" + reference.ConstraintName + ") Columns = " + reference.TableName + "( " + String.Join(", ", reference.ColumnNames) + " ) -> " + reference.ForeignTable + "( " + String.Join(", ", reference.ForeignColumnNames) + " )"); } } } } }
public static void CheckAddConstraintViolations(this ITransaction transaction, ITable table, int[] rowIndices, ConstraintDeferrability deferred) { string curSchema = table.TableInfo.TableName.Parent.Name; IQueryContext queryContext = new SystemQueryContext(transaction, curSchema); // Quick exit case if (rowIndices == null || rowIndices.Length == 0) return; var tableInfo = table.TableInfo; var tableName = tableInfo.TableName; // ---- Constraint checking ---- // Check any primary key constraint. var primaryKey = transaction.QueryTablePrimaryKey(tableName); if (primaryKey != null && (deferred == ConstraintDeferrability.InitiallyDeferred || primaryKey.Deferred == ConstraintDeferrability.InitiallyImmediate)) { // For each row added to this column foreach (int rowIndex in rowIndices) { if (!IsUniqueColumns(table, rowIndex, primaryKey.ColumnNames, false)) { throw new ConstraintViolationException( SqlModelErrorCodes.PrimaryKeyViolation, deferred.AsDebugString() + " primary Key constraint violation (" + primaryKey.ConstraintName + ") Columns = ( " + String.Join(", ", primaryKey.ColumnNames) + " ) Table = ( " + tableName + " )"); } } // For each row being added } // Check any unique constraints. var uniqueConstraints = transaction.QueryTableUniqueKeys(tableName); foreach (var unique in uniqueConstraints) { if (deferred == ConstraintDeferrability.InitiallyDeferred || unique.Deferred == ConstraintDeferrability.InitiallyImmediate) { // For each row added to this column foreach (int rowIndex in rowIndices) { if (!IsUniqueColumns(table, rowIndex, unique.ColumnNames, true)) { throw new ConstraintViolationException( SqlModelErrorCodes.UniqueViolation, deferred.AsDebugString() + " unique constraint violation (" + unique.ConstraintName + ") Columns = ( " + String.Join(", ", unique.ColumnNames) + " ) Table = ( " + tableName + " )"); } } // For each row being added } } // Check any foreign key constraints. // This ensures all foreign references in the table are referenced // to valid records. var foreignConstraints = transaction.QueryTableForeignKeys(tableName); foreach (var reference in foreignConstraints) { if (deferred == ConstraintDeferrability.InitiallyDeferred || reference.Deferred == ConstraintDeferrability.InitiallyImmediate) { // For each row added to this column foreach (int rowIndex in rowIndices) { // Make sure the referenced record exists // Return the count of records where the given row of // table_name(columns, ...) IN // ref_table_name(ref_columns, ...) int rowCount = RowCountOfReferenceTable(transaction, rowIndex, reference.TableName, reference.ColumnNames, reference.ForeignTable, reference.ForeignColumnNames, false); if (rowCount == -1) { // foreign key is NULL } if (rowCount == 0) { throw new ConstraintViolationException( SqlModelErrorCodes.ForeignKeyViolation, deferred.AsDebugString() + " foreign key constraint violation (" + reference.ConstraintName + ") Columns = " + reference.TableName + "( " + String.Join(", ", reference.ColumnNames) + " ) -> " + reference.ForeignTable + "( " + String.Join(", ", reference.ForeignColumnNames) + " )"); } } // For each row being added. } } // Any general checks of the inserted data var checkConstraints = transaction.QueryTableCheckExpressions(tableName); // For each check constraint, check that it evaluates to true. for (int i = 0; i < checkConstraints.Length; ++i) { var check = checkConstraints[i]; if (deferred == ConstraintDeferrability.InitiallyDeferred || check.Deferred == ConstraintDeferrability.InitiallyImmediate) { // TODO: var exp = tableInfo.ResolveColumns(transaction.IgnoreIdentifierCase(), check.CheckExpression); var exp = tableInfo.ResolveColumns(true, check.CheckExpression); // For each row being added to this column for (int rn = 0; rn < rowIndices.Length; ++rn) { var resolver = new TableRowVariableResolver(table, rowIndices[rn]); var evalExp = exp.Evaluate(queryContext, resolver, null); var ob = ((SqlConstantExpression) evalExp).Value; var b = ob.AsBoolean(); if (!b.IsNull) { if (b) { // Evaluated to false so don't allow this row to be added. throw new ConstraintViolationException( SqlModelErrorCodes.CheckViolation, deferred.AsDebugString() + " check constraint violation (" + check.ConstraintName + ") - '" + exp + "' evaluated to false for inserted/updated row."); } } else { // NOTE: This error will pass the row by default // TODO: emit a warning } } } } }
private static string FormatMessage(ObjectName tableName, string constraintName, string[] columnNames, ConstraintDeferrability deferrability) { return(String.Format("{0} UNIQUE KEY violation for constraint '{1}({2})' on table '{3}'.", deferrability.AsDebugString(), constraintName, String.Join(", ", columnNames), tableName)); }
private static string FormatMessage(ObjectName tableName, string constraintName, string[] columnNames, ObjectName refTableName, string[] refColumnNames, ConstraintDeferrability deferrability) { return(String.Format("{0} FOREIGN KEY violation for constraint '{1}({2})' referencing '{3}({4})'", deferrability.AsDebugString(), constraintName, String.Join(", ", columnNames), refTableName, String.Join(", ", refColumnNames))); }