Repository: tobymao/sqlglot
Issue category: Bug Report

Issue:
`sqlglot.optimizer.qualify_columns.qualify_columns` fails on `table.*` inside `UNION ALL`
### Explanation

When using `qualify_columns` on a SQL query that contains a `UNION ALL` and one of the statement uses the `SELECT table.*` notation, `qualify_columns` raises an `sqlglot.errors.OptimizeError: Unknown table: p` error.

### Fully reproducible code snippet

```py
from sqlglot import parse_one
from sqlglot.schema import MappingSchema
from sqlglot.optimizer.qualify_columns import qualify_columns

SQL_DIALECT = "snowflake"

print(qualify_columns(parse_one("""
SELECT p.*
FROM p

UNION ALL

SELECT p2.*
FROM p2
""", dialect="snowflake"), schema=MappingSchema(dialect=SQL_DIALECT)).sql(pretty=True, dialect=SQL_DIALECT))
```

Running this snippet raises an error:
```
Traceback (most recent call last):
  File "test_sqlglot.py", line 7, in <module>
    print(qualify_columns(parse_one("""
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "sqlglot/optimizer/qualify_columns.py", line 81, in qualify_columns
    _expand_stars(
  File "sqlglot/optimizer/qualify_columns.py", line 623, in _expand_stars
    raise OptimizeError(f"Unknown table: {table}")
sqlglot.errors.OptimizeError: Unknown table: p
```

Looks like, inside `_expand_stars`, `scope.sources` is an empty list. In that exact case, `scope` represents the entire query (with both SELECT and the UNION ALL in between), and `scope_type` is ROOT (not UNION).


Again, happy to make a PR.


Hints:

Patch:
diff --git a/sqlglot/optimizer/qualify_columns.py b/sqlglot/optimizer/qualify_columns.py
index 4880a615c6..ca5684407c 100644
--- a/sqlglot/optimizer/qualify_columns.py
+++ b/sqlglot/optimizer/qualify_columns.py
@@ -75,7 +75,7 @@ def qualify_columns(
         if not schema.empty and expand_alias_refs:
             _expand_alias_refs(scope, resolver)
 
-        if not isinstance(scope.expression, exp.UDTF):
+        if isinstance(scope.expression, exp.Select):
             if expand_stars:
                 _expand_stars(
                     scope,


Test patch:
diff --git a/tests/fixtures/optimizer/qualify_columns.sql b/tests/fixtures/optimizer/qualify_columns.sql
index 2640145bed..735c71a5e7 100644
--- a/tests/fixtures/optimizer/qualify_columns.sql
+++ b/tests/fixtures/optimizer/qualify_columns.sql
@@ -190,6 +190,10 @@ SELECT x._col_0 AS _col_0, x._col_1 AS _col_1 FROM (VALUES (1, 2)) AS x(_col_0,
 SELECT SOME_UDF(data).* FROM t;
 SELECT SOME_UDF(t.data).* FROM t AS t;
 
+# execute: false
+SELECT p.* FROM p UNION ALL SELECT p2.* FROM p2;
+SELECT p.* FROM p AS p UNION ALL SELECT p2.* FROM p2 AS p2;
+
 # execute: false
 # allow_partial_qualification: true
 # validate_qualify_columns: false