Skip to content

Commit

Permalink
Fix Invalid Lookups of namespaced fields (#3759)
Browse files Browse the repository at this point in the history
These modifications address the error reported in Issue #3752.

The issue stemmed from the fact that during loading, when namespaces
were injected into the mapping, only the key of the lookups dictionary
would be altered, not the lookup class itself. For instance,
`mapping.lookups` would appear as follows:

```
{
    <namespace>__<field>__c: MappingLookup(..., name="<field>__c", ...)
}
```

In the `_infer_and_validate_lookups` function within
`mapping_parser.py`, we validate whether the sObjects mentioned in the
mapping file under the lookup field are indeed part of the `referenceTo`
of that field. However, the problem arose from the utilization of the
`name` attribute under `MappingLookup` instead of the key value.

**Change:** We've modified it to reference the `name` with the key value
of `mapping.lookups` instead of accessing it within `MappingLookup`
class. This way the `name` would be the field with the injected
namespace

Fixes #3752
  • Loading branch information
aditya-balachander authored Mar 4, 2024
1 parent f911075 commit 2b3bdf5
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 5 deletions.
1 change: 1 addition & 0 deletions cumulusci/core/tests/test_datasets_e2e.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def count(sobject):
objs["Account"].remove("Description")
objs["Account"].remove("History__c")
objs["Account"].remove("ns__Description__c")
objs["Account"].remove("ns__LinkedAccount__c")
objs["Account"].remove("Primary_Contact__c")
dataset.update_schema_subset(objs)
timer.checkpoint("Updated Subset")
Expand Down
8 changes: 4 additions & 4 deletions cumulusci/tasks/bulkdata/mapping_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,13 +612,13 @@ def _infer_and_validate_lookups(mapping: Dict, sf: Salesforce):
{f["name"]: f for f in getattr(sf, m.sf_object).describe()["fields"]}
)

for lookup in m.lookups.values():
for lookup_name, lookup in m.lookups.items():
if lookup.after:
# If configured by the user, skip.
# TODO: do we need more validation here?
continue

field_describe = describe.get(lookup.name, {})
field_describe = describe.get(lookup_name, {})
reference_to_objects = field_describe.get("referenceTo", [])
target_objects = []

Expand All @@ -634,7 +634,7 @@ def _infer_and_validate_lookups(mapping: Dict, sf: Salesforce):
target_objects.append(sf_object)
else:
logger.error(
f"The lookup {sf_object} is not a valid lookup for {lookup.name} in sf_object: {m.sf_object}"
f"The lookup {sf_object} is not a valid lookup for {lookup_name} in sf_object: {m.sf_object}"
)
fail = True
except KeyError:
Expand All @@ -660,7 +660,7 @@ def _infer_and_validate_lookups(mapping: Dict, sf: Salesforce):
]
if not all([target_index < idx for target_index in target_indices]):
logger.error(
f"All included target objects ({','.join(target_objects)}) for the field {m.sf_object}.{lookup.name} "
f"All included target objects ({','.join(target_objects)}) for the field {m.sf_object}.{lookup_name} "
f"must precede {m.sf_object} in the mapping."
)
fail = True
Expand Down
33 changes: 33 additions & 0 deletions cumulusci/tasks/bulkdata/tests/test_mapping_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -1071,6 +1071,39 @@ def test_validate_and_inject_mapping_injects_namespaces(self):

assert list(ms.fields.keys()) == ["ns__Description__c"]

@responses.activate
def test_validate_and_inject_mapping_injects_namespaces__validates_lookup(self):
"""Test to verify that with namespace inject, we validate lookups correctly"""
mock_describe_calls()
# Note: ns__Description__c is a mock field added to our stored, mock describes (in JSON)
mapping = parse_from_yaml(
StringIO(
"""Insert Accounts:
sf_object: Account
table: Account
fields:
- Description__c
lookups:
LinkedAccount__c:
table: Account"""
)
)
ms = mapping["Insert Accounts"]
org_config = DummyOrgConfig(
{"instance_url": "https://example.com", "access_token": "abc123"}, "test"
)

assert ms.validate_and_inject_namespace(
org_config.salesforce_client,
"ns",
DataOperationType.INSERT,
inject_namespaces=True,
)
# Here we verify that the field ns__LinkedAccount__c does lookup
# to sobject Account inside of describe
_infer_and_validate_lookups(mapping, org_config.salesforce_client)
assert list(ms.lookups.keys()) == ["ns__LinkedAccount__c"]

@responses.activate
def test_validate_and_inject_mapping_removes_namespaces(self):
mock_describe_calls()
Expand Down

Large diffs are not rendered by default.

0 comments on commit 2b3bdf5

Please sign in to comment.