Repository: frictionlessdata/frictionless-py

Issue:
Add ForeignKey fields in ForeignKey Error note
# Overview

When a ForeignKey Error is reported there is no way to know which ForiegnKey didn't validate.
Yet one resource can have multiple ForeignKeys attached to it.
It would help to add the Foreign Key Fields in the Error note.

I made a small edit in my local version of fircitonless-py to add those fields in the error note like this : 
```
{
...
"note": "currency;year;reporting not found in the lookup table as currency;year;reporting",
...
"note": "partner not found in the lookup table as original_name",
...
}
```

Fields are ; separated if multiple and both target and source fields are displayed.

But maybe those should be added as variables in the error objects rather than in the note string?

I can submit a PR if you validate the concept and needs.
It was mandatory in my case to understand what was the issue.



Discussion:
paulgirard: Mmm something went wrong with the CI apparently...
Let me know If I can help.
roll: Hi, @aivuk can you please take a look?
Eugenio2192: I have a slight modification of this feature but I can't update this pull request becasue it is in a foreign repo, is it ok if I make a different pull request?

@paulgirard  are you still working on this?
aivuk: > I have a slight modification of this feature but I can't update this pull request becasue it is in a foreign repo, is it ok if I make a different pull request?
> 
> @paulgirard are you still working on this?

No problem in creating a new pull, but then I will close this one after you created the new one
Eugenio2192: > > I have a slight modification of this feature but I can't update this pull request becasue it is in a foreign repo, is it ok if I make a different pull request?
> > @paulgirard are you still working on this?
> 
> No problem in creating a new pull, but then I will close this one after you created the new one

I did a pull request with my work account, I did not take over the tests however.

Patch:
diff --git a/frictionless/resource.py b/frictionless/resource.py
index df607b68..f4fddd25 100644
--- a/frictionless/resource.py
+++ b/frictionless/resource.py
@@ -981,7 +981,12 @@ class Resource(Metadata):
                                 continue
                             match = cells in group_lookup.get(group["sourceKey"], set())
                             if not match:
-                                note = "not found in the lookup table"
+                                note = 'for "%s": values "%s" not found in the lookup table "%s" as "%s"' % (
+                                    ", ".join(group["targetKey"]),
+                                    ", ".join(str(d) for d in cells),
+                                    group["sourceName"],
+                                    ", ".join(group["sourceKey"]),
+                                )
                                 error = errors.ForeignKeyError.from_row(row, note=note)
                                 row.errors.append(error)
 


Test patch:
diff --git a/tests/validate/test_package.py b/tests/validate/test_package.py
index ba747427..0d63df69 100644
--- a/tests/validate/test_package.py
+++ b/tests/validate/test_package.py
@@ -186,6 +186,24 @@ DESCRIPTOR_FK = {
     ],
 }
 
+MULTI_FK_RESSOURCE = {
+    "name": "travel_time",
+    "data": [["from", "to", "hours"], [1, 2, 1.5], [2, 3, 8], [3, 4, 18]],
+    "schema": {
+        "fields": [
+            {"name": "from", "type": "integer"},
+            {"name": "to", "type": "integer"},
+            {"name": "hours", "type": "number"},
+        ],
+        "foreignKeys": [
+            {
+                "fields": ["from", "to"],
+                "reference": {"resource": "cities", "fields": ["id", "next_id"]},
+            }
+        ],
+    },
+}
+
 
 def test_validate_package_schema_foreign_key_error():
     descriptor = deepcopy(DESCRIPTOR_FK)
@@ -230,6 +248,30 @@ def test_validate_package_schema_foreign_key_internal_resource_violation_non_exi
     ]
 
 
+def test_validate_package_schema_multiple_foreign_key():
+    descriptor = deepcopy(DESCRIPTOR_FK)
+    descriptor["resources"].append(MULTI_FK_RESSOURCE)
+    report = validate(descriptor)
+    assert report.valid
+
+
+def test_validate_package_schema_multiple_foreign_key_resource_violation_non_existent():
+    descriptor = deepcopy(DESCRIPTOR_FK)
+    # remove London
+    del descriptor["resources"][0]["data"][1]
+    descriptor["resources"].append(MULTI_FK_RESSOURCE)
+    report = validate(descriptor)
+    assert report.flatten(["rowPosition", "fieldPosition", "code", "cells", "note"]) == [
+        [
+            2,
+            None,
+            "foreign-key-error",
+            ["1", "2", "1.5"],
+            'for "from, to": values "1, 2" not found in the lookup table "cities" as "id, next_id"',
+        ],
+    ]
+
+
 # Stats
 
 DESCRIPTOR_SH = {