FA-45271 / Data systems / Open access
Column binding ignores explicit relation qualifiers · case 01
Column binding ignores explicit relation qualifiers.
ROOT CAUSE
qualified-column-binding: Column binding ignores explicit relation qualifiers.
VERIFIED REPAIR
Preserve the stated physical representation and operation order: Resolve query references [qualifier-or-None,name] against schema entries [relation,name,field-id]. Unqualified names bind only when exactly one matching column exists. Qualified names use both relation and name; no candidates yields MISSING and several yield AMBIGUOUS. Return stable field IDs.
Unsuccessful approach: Prefix matching treats different relation aliases as interchangeable.
Case contract
Resolve query references [qualifier-or-None,name] against schema entries [relation,name,field-id]. Unqualified names bind only when exactly one matching column exists. Qualified names use both relation and name; no candidates yields MISSING and several yield AMBIGUOUS. Return stable field IDs.
Why this case matters
A bounded deterministic data engine model makes representation and changelog faults reproducible.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
schema,references=d
out=[]
for qualifier,name in references:
matches=[field for rel,col,field in schema if col==name and True]
if not matches: out.append('MISSING')
elif len(matches)>1: out.append('AMBIGUOUS')
else: out.append(matches[0])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('qualified same name', solve([[['a', 'x', 1], ['b', 'x', 2]], [['b', 'x'], ['a', 'x']]]), [2, 1])
check('ambiguous', solve([[['a', 'x', 1], ['b', 'x', 2]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 1]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 1]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 1]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 1]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 1]], [['a', 'x'], ['a', 'x']]]), [1, 1])
elif N == 2:
check('qualified same name', solve([[['a', 'x', 2], ['b', 'x', 3]], [['b', 'x'], ['a', 'x']]]), [3, 2])
check('ambiguous', solve([[['a', 'x', 2], ['b', 'x', 3]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 2]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 2]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 2]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 2]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 2]], [['a', 'x'], ['a', 'x']]]), [2, 2])
elif N == 3:
check('qualified same name', solve([[['a', 'x', 3], ['b', 'x', 4]], [['b', 'x'], ['a', 'x']]]), [4, 3])
check('ambiguous', solve([[['a', 'x', 3], ['b', 'x', 4]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 3]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 3]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 3]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 3]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 3]], [['a', 'x'], ['a', 'x']]]), [3, 3])
elif N == 4:
check('qualified same name', solve([[['a', 'x', 4], ['b', 'x', 5]], [['b', 'x'], ['a', 'x']]]), [5, 4])
check('ambiguous', solve([[['a', 'x', 4], ['b', 'x', 5]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 4]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 4]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 4]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 4]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 4]], [['a', 'x'], ['a', 'x']]]), [4, 4])
elif N == 5:
check('qualified same name', solve([[['a', 'x', 5], ['b', 'x', 6]], [['b', 'x'], ['a', 'x']]]), [6, 5])
check('ambiguous', solve([[['a', 'x', 5], ['b', 'x', 6]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 5]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 5]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 5]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 5]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 5]], [['a', 'x'], ['a', 'x']]]), [5, 5])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| qualified same name | ['AMBIGUOUS', 'AMBIGUOUS'] | [2, 1] | Failed |
| ambiguous | ['AMBIGUOUS'] | ['AMBIGUOUS'] | Passed |
| missing | ['MISSING'] | ['MISSING'] | Passed |
| case-sensitive | ['MISSING'] | ['MISSING'] | Passed |
| alias-prefix | [1] | ['MISSING'] | Failed |
| literal-space | ['MISSING'] | ['MISSING'] | Passed |
| repeat ref | [1, 1] | [1, 1] | Passed |
SHA-256 / a1cc0556dc4f351bc599035e3a6113463fef207ce9a90c28c327d16a03f08da4
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
schema,references=d
out=[]
for qualifier,name in references:
matches=[field for rel,col,field in schema if col==name and (qualifier is None or rel.startswith(qualifier))]
if not matches: out.append('MISSING')
elif len(matches)>1: out.append('AMBIGUOUS')
else: out.append(matches[0])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('qualified same name', solve([[['a', 'x', 1], ['b', 'x', 2]], [['b', 'x'], ['a', 'x']]]), [2, 1])
check('ambiguous', solve([[['a', 'x', 1], ['b', 'x', 2]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 1]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 1]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 1]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 1]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 1]], [['a', 'x'], ['a', 'x']]]), [1, 1])
elif N == 2:
check('qualified same name', solve([[['a', 'x', 2], ['b', 'x', 3]], [['b', 'x'], ['a', 'x']]]), [3, 2])
check('ambiguous', solve([[['a', 'x', 2], ['b', 'x', 3]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 2]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 2]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 2]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 2]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 2]], [['a', 'x'], ['a', 'x']]]), [2, 2])
elif N == 3:
check('qualified same name', solve([[['a', 'x', 3], ['b', 'x', 4]], [['b', 'x'], ['a', 'x']]]), [4, 3])
check('ambiguous', solve([[['a', 'x', 3], ['b', 'x', 4]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 3]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 3]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 3]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 3]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 3]], [['a', 'x'], ['a', 'x']]]), [3, 3])
elif N == 4:
check('qualified same name', solve([[['a', 'x', 4], ['b', 'x', 5]], [['b', 'x'], ['a', 'x']]]), [5, 4])
check('ambiguous', solve([[['a', 'x', 4], ['b', 'x', 5]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 4]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 4]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 4]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 4]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 4]], [['a', 'x'], ['a', 'x']]]), [4, 4])
elif N == 5:
check('qualified same name', solve([[['a', 'x', 5], ['b', 'x', 6]], [['b', 'x'], ['a', 'x']]]), [6, 5])
check('ambiguous', solve([[['a', 'x', 5], ['b', 'x', 6]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 5]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 5]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 5]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 5]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 5]], [['a', 'x'], ['a', 'x']]]), [5, 5])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| qualified same name | [2, 1] | [2, 1] | Passed |
| ambiguous | ['AMBIGUOUS'] | ['AMBIGUOUS'] | Passed |
| missing | ['MISSING'] | ['MISSING'] | Passed |
| case-sensitive | ['MISSING'] | ['MISSING'] | Passed |
| alias-prefix | [1] | ['MISSING'] | Failed |
| literal-space | ['MISSING'] | ['MISSING'] | Passed |
| repeat ref | [1, 1] | [1, 1] | Passed |
SHA-256 / 2bbb358cd7d69089542dee53c7a40351ae2d04f6cb5e8290e59ab6a1c2bd7dd9
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
N = 1
observations = []
def solve(d):
try:
schema,references=d
out=[]
for qualifier,name in references:
matches=[field for rel,col,field in schema if col==name and (qualifier is None or rel==qualifier)]
if not matches: out.append('MISSING')
elif len(matches)>1: out.append('AMBIGUOUS')
else: out.append(matches[0])
return out
except (IndexError, KeyError, ValueError, StopIteration) as exc:
return {"representation_error": type(exc).__name__}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
if N == 1:
check('qualified same name', solve([[['a', 'x', 1], ['b', 'x', 2]], [['b', 'x'], ['a', 'x']]]), [2, 1])
check('ambiguous', solve([[['a', 'x', 1], ['b', 'x', 2]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 1]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 1]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 1]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 1]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 1]], [['a', 'x'], ['a', 'x']]]), [1, 1])
elif N == 2:
check('qualified same name', solve([[['a', 'x', 2], ['b', 'x', 3]], [['b', 'x'], ['a', 'x']]]), [3, 2])
check('ambiguous', solve([[['a', 'x', 2], ['b', 'x', 3]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 2]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 2]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 2]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 2]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 2]], [['a', 'x'], ['a', 'x']]]), [2, 2])
elif N == 3:
check('qualified same name', solve([[['a', 'x', 3], ['b', 'x', 4]], [['b', 'x'], ['a', 'x']]]), [4, 3])
check('ambiguous', solve([[['a', 'x', 3], ['b', 'x', 4]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 3]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 3]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 3]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 3]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 3]], [['a', 'x'], ['a', 'x']]]), [3, 3])
elif N == 4:
check('qualified same name', solve([[['a', 'x', 4], ['b', 'x', 5]], [['b', 'x'], ['a', 'x']]]), [5, 4])
check('ambiguous', solve([[['a', 'x', 4], ['b', 'x', 5]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 4]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 4]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 4]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 4]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 4]], [['a', 'x'], ['a', 'x']]]), [4, 4])
elif N == 5:
check('qualified same name', solve([[['a', 'x', 5], ['b', 'x', 6]], [['b', 'x'], ['a', 'x']]]), [6, 5])
check('ambiguous', solve([[['a', 'x', 5], ['b', 'x', 6]], [[None, 'x']]]), ['AMBIGUOUS'])
check('missing', solve([[['a', 'x', 5]], [['a', 'z']]]), ['MISSING'])
check('case-sensitive', solve([[['a', 'X', 5]], [[None, 'x']]]), ['MISSING'])
check('alias-prefix', solve([[['ab', 'x', 5]], [['a', 'x']]]), ['MISSING'])
check('literal-space', solve([[['a', ' x ', 5]], [[None, 'x']]]), ['MISSING'])
check('repeat ref', solve([[['a', 'x', 5]], [['a', 'x'], ['a', 'x']]]), [5, 5])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| qualified same name | [2, 1] | [2, 1] | Passed |
| ambiguous | ['AMBIGUOUS'] | ['AMBIGUOUS'] | Passed |
| missing | ['MISSING'] | ['MISSING'] | Passed |
| case-sensitive | ['MISSING'] | ['MISSING'] | Passed |
| alias-prefix | ['MISSING'] | ['MISSING'] | Passed |
| literal-space | ['MISSING'] | ['MISSING'] | Passed |
| repeat ref | [1, 1] | [1, 1] | Passed |
SHA-256 / 172e34efddeffbd867c2dd0e7f09a95ed7a78df4da9d281b336dbf148c81c1b1
Verification & scope
Offline stipulated semantics over valid small inputs; no performance, concurrency, or production-engine conformance claim. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:44:20.484677+00:00.
Case digest / cbeb3e1a07cb40bec9b102a96670f197ff9c26c56b758ecfff6365962d5e4054