< Summary

Information
Class: ValidateLib.TabularData.Validation.ValidationRules.FKReferencedValuesMustMatchValidationRule
Assembly: validatelib.dll
File(s): C:\skola_karlovka\RP\code\csv-validator\CSV_Validator\ValidateLib\TabularData\Validation\ValidationRules\FKReferencedValuesMustMatchValidationRule.cs
Line coverage
100%
Covered lines: 45
Uncovered lines: 0
Coverable lines: 45
Total lines: 135
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

File(s)

C:\skola_karlovka\RP\code\csv-validator\CSV_Validator\ValidateLib\TabularData\Validation\ValidationRules\FKReferencedValuesMustMatchValidationRule.cs

#LineLine coverage
 1using System.Text;
 2using ValidateLib.ErrorsAndWarnings.Errors;
 3using ValidateLib.ErrorsAndWarnings.Errors.ValidationErrors;
 4using ValidateLib.Metadata.Descriptors;
 5using ValidateLib.Metadata.Validators;
 6using ValidateLib.TabularData.AnnotatedTabularDataModel;
 7
 8namespace ValidateLib.TabularData.Validation.ValidationRules
 9{
 10    public class FKReferencedValuesMustMatchValidationRule : IValidationRule
 11    {
 12        // validates that the values in the referencing columns match referenced values in the other table
 13        // also validates that the combination of referencing cells are referencing a unique row in referenced table
 14        public List<Error> ValidateReferencedValuesFK(List<Table> tables, TableGroupDescriptor tableGroupDescriptor)
 15        {
 116            List<Error> errors = new List<Error>();
 117            foreach (var table in tables)
 18            {
 119                if (table.foreignKeys is not null && table.foreignKeys.Count > 0)
 20                {
 121                    ResolveReferencedValuesForOneTable(table, tableGroupDescriptor, errors);
 22                }
 23            }
 124            return errors;
 25        }
 26
 27        private void ResolveReferencedValuesForOneTable(Table referencingTable, TableGroupDescriptor tableGroupDescripto
 28        {
 129            foreach (var FKDescriptor in referencingTable.foreignKeys!)
 30            {
 131                ResolveReferencedValuesForOneTableOneFK(referencingTable, tableGroupDescriptor, FKDescriptor, errors);
 32            }
 133        }
 34
 35        private void ResolveReferencedValuesForOneTableOneFK(Table referencingTable, TableGroupDescriptor tableGroupDesc
 36        {
 37            // these are the values that need to be unique inside the referenced table
 38            // they are imploded to one string to conserve less space
 139            Dictionary<string, bool> referencingValues = GetReferencingValues(referencingTable, FKDescriptor);
 140            TableDescriptor referencedTableDescriptor = ForeignKeyValidator.FindReferencedTable(tableGroupDescriptor, FK
 141            Table referencedTable = referencedTableDescriptor.table!;
 142            VerifyTheReferencingValuesExist(referencingTable, referencedTable, referencingValues, FKDescriptor, errors);
 43
 144        }
 45
 46        private Dictionary<string, bool> GetReferencingValues(Table referencingTable, ForeignKeyDescriptor FKDescriptor)
 47        {
 148            Dictionary<string, bool> referencingValues = new Dictionary<string, bool>();
 49
 150            int maxRows = 0;
 151            foreach (var column in referencingTable.columns)
 52            {
 153                maxRows = Math.Max(maxRows, column.cells.Count);
 54            }
 55
 156            for (int rowNumber = 0; rowNumber < maxRows; rowNumber++)
 57            {
 158                StringBuilder referencingValue = new StringBuilder();
 59
 160                foreach (var column in referencingTable.columns)
 61                {
 162                    if (column.name is null)
 63                        continue;
 64
 165                    if (FKDescriptor.columnReference!._value!.Contains(column.name))
 66                    {
 167                        referencingValue.Append(column.cells[rowNumber].stringValue);
 68                    }
 69                }
 170                referencingValues[referencingValue.ToString()] = true;
 71            }
 172            return referencingValues;
 73        }
 74
 75        private void VerifyTheReferencingValuesExist
 76            (
 77            Table referencingTable,
 78            Table referencedTable,
 79            Dictionary<string, bool> referencingValues,
 80            ForeignKeyDescriptor FKDescriptor,
 81            List<Error> errors
 82            )
 83        {
 184            int maxRows = 0;
 185            foreach (var column in referencedTable.columns)
 86            {
 187                maxRows = Math.Max(maxRows, column.cells.Count);
 88            }
 189            int numberOfKeys = referencingValues.Count;
 90
 191            for (int rowNumber = 0; rowNumber < maxRows; rowNumber++)
 92            {
 93
 194                string referencedValueStr = GetReferencedValue(referencedTable, FKDescriptor, rowNumber);
 195                if (referencingValues.ContainsKey(referencedValueStr))
 96                {
 197                    if (referencingValues[referencedValueStr] == true)
 98                    {
 199                        numberOfKeys--;
 1100                        referencingValues[referencedValueStr] = false;
 101                    }
 102                    else
 103                    {
 1104                        errors.Add(ErrorFactory.GetDuplicateInFKReferencedColumnsValidationError(referencedTable, GetRef
 105                    }
 106                }
 107
 108
 109            }
 110
 1111            if (numberOfKeys > 0)
 112            {
 1113                errors.Add(ErrorFactory.GetNotAllReferencedValuesExistValidationError(referencingTable, referencedTable,
 114            }
 1115        }
 116
 117        string GetReferencedValue(Table referencedTable, ForeignKeyDescriptor FKDescriptor, int rowNumber, string separa
 118        {
 1119            StringBuilder referencedValue = new StringBuilder();
 120
 1121            foreach (var column in referencedTable.columns)
 122            {
 1123                if (column.name is null)
 124                    continue;
 125
 1126                if (FKDescriptor!.reference!._value!.columnReference!._value!.Contains(column.name))
 127                {
 1128                    referencedValue.Append(separator + column.cells[rowNumber].stringValue);
 129                }
 130            }
 131
 1132            return referencedValue.ToString();
 133        }
 134    }
 135}