missing_mandatory_column

This rule checks if the rows of each table contains its mandatory columns. For example, the addID column is mandatory for the addresses table. The following address table row,

                                                  Invalid Dataset                                                  
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ addL2                                                                                                           ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 123 Doe Street                                                                                                  │
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘

would fail validation. The following address table row would pass validation,

                                                   Valid Dataset                                                   
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ addID                              addL2                                                                       ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 1                                 │ 123 Doe Street                                                              │
└───────────────────────────────────┴─────────────────────────────────────────────────────────────────────────────┘

Error report

The error report will have the following fields

  • errorType: missing_mandatory_column

  • tableName: The name of the table containing the missing column

  • columnName The name of the missing column

  • rowNumber: The index of the table row with the error

  • row The dictionary containing the row

  • validationRuleFields: The ODM data dictionary rule fields violated by this row

  • message: Missing mandatory column <columnName> in table <tableName> in row number <rowIndex>

Example

{
'errors': [
│   │   {
│   │   │   'errorType': 'missing_mandatory_column',
│   │   │   'tableName': 'addresses',
│   │   │   'columnName': 'addID',
│   │   │   'rowNumber': 1,
│   │   │   'row': {
│   │   │   │   'addL2': '123 Doe Street'
│   │   │   },
│   │   │   'validationRuleFields': [
│   │   │   │   {
│   │   │   │   │   'addresses': 'pK',
│   │   │   │   │   'partID': 'addID',
│   │   │   │   │   'addressesRequired': 'mandatory'
│   │   │   │   }
│   │   │   ],
│   │   │   'message': 'missing_mandatory_column rule violated in table addresses, column addID: Missing mandatory column addID'
│   │   }
],
'warnings': []
}

Rule metadata

All the metadata for this rule is contained in the parts sheet in the data dictionary. The relevant columns are:

  • partID: Contains the name of a part

  • <table_name>: Used to indicate whether the part is associated with a table

    Can have one of the following values:

    • pK: The part is a primary key for the table

    • fK: The part is a foreign key for the table

    • header: The part is the name of a column in the table

    • input

    • NA: The part is not applicable to the table

  • <table_name>Required: Used to indicate whether a column is mandatory for a table

    Can have one of the following values:

    • mandatory: The column is mandatory

    • optional: The column is not mandatory

    • NA: The column is not applicable

Example

                                                     Parts v2                                                      
┏━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┓
┃ partID     partType    addresses  addressesR…  contacts  contactsRe…  status  firstReleas…  lastUpdated ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━┩
│ addresses │ tables     │ NA        │ NA          │ NA       │ NA          │ active │ 1.0.0        │ 2.0.0       │
│ addID     │ attributes │ pK        │ mandatory   │ NA       │ NA          │ active │ 1.0.0        │ 2.0.0       │
│ addL2     │ attributes │ header    │ optional    │ NA       │ NA          │ active │ 1.0.0        │ 2.0.0       │
│ contacts  │ tables     │ NA        │ NA          │ NA       │ NA          │ active │ 1.0.0        │ 2.0.0       │
│ contID    │ attributes │ NA        │ NA          │ pK       │ mandatory   │ active │ 1.0.0        │ 2.0.0       │
└───────────┴────────────┴───────────┴─────────────┴──────────┴─────────────┴────────┴──────────────┴─────────────┘

Cerberus Schema

The generated cerberus object for the example above is shown below,

{
'schemaVersion': '2.0.0',
'schema': {
│   │   'addresses': {
│   │   │   'type': 'list',
│   │   │   'schema': {
│   │   │   │   'type': 'dict',
│   │   │   │   'schema': {
│   │   │   │   │   'addID': {
│   │   │   │   │   │   'required': True,
│   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   'ruleID': 'missing_mandatory_column',
│   │   │   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   │   │   'partID': 'addID',
│   │   │   │   │   │   │   │   │   │   'addresses': 'pK',
│   │   │   │   │   │   │   │   │   │   'addressesRequired': 'mandatory'
│   │   │   │   │   │   │   │   │   }
│   │   │   │   │   │   │   │   ]
│   │   │   │   │   │   │   }
│   │   │   │   │   │   ]
│   │   │   │   │   }
│   │   │   │   },
│   │   │   │   'meta': [
│   │   │   │   │   {
│   │   │   │   │   │   'partID': 'addresses',
│   │   │   │   │   │   'partType': 'tables'
│   │   │   │   │   }
│   │   │   │   ]
│   │   │   }
│   │   },
│   │   'contacts': {
│   │   │   'type': 'list',
│   │   │   'schema': {
│   │   │   │   'type': 'dict',
│   │   │   │   'schema': {
│   │   │   │   │   'contID': {
│   │   │   │   │   │   'required': True,
│   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   'ruleID': 'missing_mandatory_column',
│   │   │   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   │   │   'partID': 'contID',
│   │   │   │   │   │   │   │   │   │   'contacts': 'pK',
│   │   │   │   │   │   │   │   │   │   'contactsRequired': 'mandatory'
│   │   │   │   │   │   │   │   │   }
│   │   │   │   │   │   │   │   ]
│   │   │   │   │   │   │   }
│   │   │   │   │   │   ]
│   │   │   │   │   }
│   │   │   │   },
│   │   │   │   'meta': [
│   │   │   │   │   {
│   │   │   │   │   │   'partID': 'contacts',
│   │   │   │   │   │   'partType': 'tables'
│   │   │   │   │   }
│   │   │   │   ]
│   │   │   }
│   │   }
}
}

The data dictionary columns that should be included in the meta field are: * partID * <table_name> * <table_name>Required

Version 1

We need three pieces of information to make the cerberus schema for version 1:

  1. The columns that are part of the version 1 table

  2. The version 2 equivalent for each column

  3. The version 2 equivalent for the table

Details for the above points can be found here

We then check if the version 2 equivalent column is mandatory in the version 2 equivalent table, if it is, then it should be mandatory in version 1. For example,

                                                     Parts v1                                                      
┏━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┓
┃ partID   partT…  addres…  addre…  contac…  conta…  versio…  versi…  versio…  status  first…  lastUp… ┃
┡━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━━┩
│ addres… │ tables │ NA      │ NA     │ NA      │ NA     │ tables  │ Addre… │ NA      │ active │ 1.0.0  │ 2.0.0   │
│ addID   │ attri… │ pK      │ manda… │ NA      │ NA     │ variab… │ Addre… │ Addres… │ active │ 1.0.0  │ 2.0.0   │
│ addL2   │ attri… │ header  │ optio… │ NA      │ NA     │ variab… │ Addre… │ addres… │ active │ 1.0.0  │ 2.0.0   │
│ contac… │ tables │ NA      │ NA     │ NA      │ NA     │ tables  │ Conta… │ NA      │ active │ 1.0.0  │ 2.0.0   │
│ contID  │ attri… │ NA      │ NA     │ pK      │ manda… │ variab… │ Conta… │ Contac… │ active │ 1.0.0  │ 2.0.0   │
└─────────┴────────┴─────────┴────────┴─────────┴────────┴─────────┴────────┴─────────┴────────┴────────┴─────────┘

The corresponding version 1 cerberus schema is shown below,

{
'schemaVersion': '1.0.0',
'schema': {
│   │   'Address': {
│   │   │   'type': 'list',
│   │   │   'schema': {
│   │   │   │   'type': 'dict',
│   │   │   │   'schema': {
│   │   │   │   │   'AddressId': {
│   │   │   │   │   │   'required': True,
│   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   'ruleID': 'missing_mandatory_column',
│   │   │   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   │   │   'partID': 'addID',
│   │   │   │   │   │   │   │   │   │   'addresses': 'pK',
│   │   │   │   │   │   │   │   │   │   'addressesRequired': 'mandatory',
│   │   │   │   │   │   │   │   │   │   'version1Location': 'variables',
│   │   │   │   │   │   │   │   │   │   'version1Table': 'Address',
│   │   │   │   │   │   │   │   │   │   'version1Variable': 'AddressId'
│   │   │   │   │   │   │   │   │   }
│   │   │   │   │   │   │   │   ]
│   │   │   │   │   │   │   }
│   │   │   │   │   │   ]
│   │   │   │   │   }
│   │   │   │   },
│   │   │   │   'meta': [
│   │   │   │   │   {
│   │   │   │   │   │   'partID': 'addresses',
│   │   │   │   │   │   'partType': 'tables',
│   │   │   │   │   │   'version1Location': 'tables',
│   │   │   │   │   │   'version1Table': 'Address'
│   │   │   │   │   }
│   │   │   │   ]
│   │   │   }
│   │   },
│   │   'Contact': {
│   │   │   'type': 'list',
│   │   │   'schema': {
│   │   │   │   'type': 'dict',
│   │   │   │   'schema': {
│   │   │   │   │   'ContactId': {
│   │   │   │   │   │   'required': True,
│   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   'ruleID': 'missing_mandatory_column',
│   │   │   │   │   │   │   │   'meta': [
│   │   │   │   │   │   │   │   │   {
│   │   │   │   │   │   │   │   │   │   'partID': 'contID',
│   │   │   │   │   │   │   │   │   │   'contacts': 'pK',
│   │   │   │   │   │   │   │   │   │   'contactsRequired': 'mandatory',
│   │   │   │   │   │   │   │   │   │   'version1Location': 'variables',
│   │   │   │   │   │   │   │   │   │   'version1Table': 'Contact',
│   │   │   │   │   │   │   │   │   │   'version1Variable': 'ContactId'
│   │   │   │   │   │   │   │   │   }
│   │   │   │   │   │   │   │   ]
│   │   │   │   │   │   │   }
│   │   │   │   │   │   ]
│   │   │   │   │   }
│   │   │   │   },
│   │   │   │   'meta': [
│   │   │   │   │   {
│   │   │   │   │   │   'partID': 'contacts',
│   │   │   │   │   │   'partType': 'tables',
│   │   │   │   │   │   'version1Location': 'tables',
│   │   │   │   │   │   'version1Table': 'Contact'
│   │   │   │   │   }
│   │   │   │   ]
│   │   │   }
│   │   }
}
}

The meta field for version 1 validation schemas for this rule should include the rows for version 2 along with the version1Location, version1Table, and version1Variable column.