diff --git a/compiler/semantic/scope.go b/compiler/semantic/scope.go index 63c4a4a57..4f4556f5d 100644 --- a/compiler/semantic/scope.go +++ b/compiler/semantic/scope.go @@ -187,6 +187,23 @@ func (s *Scope) resolve(t *translator, n ast.Node, path field.Path, inType super } out, dyn, err := scope.resolveUnqualified(path[0]) if err != nil { + // A multi-element path that fails unqualified resolution may still + // be a valid qualified (table.column) reference; the leading name + // only looked like an unqualified column. This happens for joins + // over dynamic inputs, where any name resolves as a dynamic column, + // so a real table-qualified reference like "a.id" would otherwise + // be rejected with a misleading error. + if len(path) >= 2 { + q, qerr := scope.resolveQualified(path[0], path[1]) + if qerr != nil { + t.error(n, qerr) + return badExpr, t.checker.unknown + } + if q != nil { + this := sem.NewThis(n, append(q, path[2:]...)) + return this, t.checker.this(n, this, inType) + } + } t.error(n, err) return badExpr, t.checker.unknown } diff --git a/compiler/ztests/sql/join-dynamic-qualified.yaml b/compiler/ztests/sql/join-dynamic-qualified.yaml new file mode 100644 index 000000000..83d303d1b --- /dev/null +++ b/compiler/ztests/sql/join-dynamic-qualified.yaml @@ -0,0 +1,18 @@ +script: | + super -s -dynamic -c "SELECT a.x FROM 'a.sup' AS a JOIN 'b.sup' AS b ON a.id = b.id" + +inputs: + - name: a.sup + data: | + {x:1,id:1} + {x:2,id:2} + - name: b.sup + data: | + {y:10,id:1} + {y:20,id:2} + +outputs: + - name: stdout + data: | + {x:1} + {x:2}