docs: def resolve_column(self, ref):
      "ref is a NameX or AttrX. return (canonical_table_name, column_name)."
      if isinstance(ref, sqparse2.AttrX):
        if ref.parent.name not in self:
          raise ScopeUnkError('unk table or table alias', ref.parent.name)
        return ref.parent.name, ref.attr.name
      elif isinstance(ref, sqparse2.NameX):
        matches = set()
        for name, target in self.names.items():
          if isinstance(target, SyntheticTable):
            if ref.name in target.columns(self):
              matches.add(name)
          elif isinstance(target, table.Table):
            try: target.get_column(ref.name)
            except KeyError: pass
            else: matches.add(name)
          else:
            raise TypeError('expected SyntheticTable', type(target), target)
        if not matches: raise ScopeUnkError(ref)
        elif len(matches) > 1: raise ScopeCollisionError(matches, ref)
        else: return list(matches)[0], ref.name
      else:
        raise TypeError('unexpected', type(ref), ref)