Repository: tobymao/sqlglot

Issue:
error in optimizer.qualify with mixed identifier quotation.
**Fully reproducible code snippet**:
```
from sqlglot import parse_one
from sqlglot.dialects.oracle import Oracle
from sqlglot.lineage import lineage
from sqlglot.optimizer.qualify import qualify

parser = Oracle()

sql = """
with base as
(

    select x.dummy as COL_1
    from dual x
)
select b."COL_1"
from base b
"""

ast = parse_one(sql, read=parser)
qualified = qualify(
        ast,
        dialect=parser,
        schema=None,
    )

```
error:
```
Exception has occurred: OptimizeError
Unknown column: COL_1
  File "C:\Users\itay5\Desktop\work\sql\main.py", line 20, in <module>
    qualified = qualify(
                ^^^^^^^^
sqlglot.errors.OptimizeError: Unknown column: COL_1
```
I get the same error while trying to use identify=False, and still no luck.




Discussion:
Hey, have you verified whether this query is valid in Oracle SQL? If it is, it might be a bug on our end w.r.t. how we've implemented Oracle's identifier resolution rules, so additional documentation on this topic would be much appreciated.
> Hey, have you verified whether this query is valid in Oracle SQL? If it is, it might be a bug on our end w.r.t. how we've implemented Oracle's identifier resolution rules, so additional documentation on this topic would be much appreciated.

Yeah I've verified with live SQL of oracle, couldn't link to it because it requires a user to log in. I'll try to look for some documentation 

https://livesql.oracle.com

If you will refer to section 8 of
https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm

"COL_1" and COL_1

Should be interpreted the same
Interesting, so it seems like Oracle has the same resolution semantics as Snowflake:

> Nonquoted identifiers are not case sensitive. Oracle interprets them as uppercase. Quoted identifiers are case sensitive.

I'll fix this, thanks for the report.

Resolving patch:
diff --git a/sqlglot/dialects/oracle.py b/sqlglot/dialects/oracle.py
--- a/sqlglot/dialects/oracle.py
+++ b/sqlglot/dialects/oracle.py
@@ -30,6 +30,9 @@ def _parse_xml_table(self: parser.Parser) -> exp.XMLTable:
 class Oracle(Dialect):
     ALIAS_POST_TABLESAMPLE = True
 
+    # See section 8: https://docs.oracle.com/cd/A97630_01/server.920/a96540/sql_elements9a.htm
+    RESOLVES_IDENTIFIERS_AS_UPPERCASE = True
+
     # https://docs.oracle.com/database/121/SQLRF/sql_elements004.htm#SQLRF00212
     # https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
     TIME_MAPPING = {


Test patch:
diff --git a/tests/fixtures/optimizer/qualify_columns.sql b/tests/fixtures/optimizer/qualify_columns.sql
--- a/tests/fixtures/optimizer/qualify_columns.sql
+++ b/tests/fixtures/optimizer/qualify_columns.sql
@@ -93,6 +93,16 @@ SELECT 2 AS "2" FROM x AS x GROUP BY 1;
 SELECT 'a' AS a FROM x GROUP BY 1;
 SELECT 'a' AS a FROM x AS x GROUP BY 1;
 
+# execute: false
+# dialect: oracle
+SELECT t."col" FROM tbl t;
+SELECT T."col" AS "col" FROM TBL T;
+
+# execute: false
+# dialect: oracle
+WITH base AS (SELECT x.dummy AS COL_1 FROM dual x) SELECT b."COL_1" FROM base b;
+WITH BASE AS (SELECT X.DUMMY AS COL_1 FROM DUAL X) SELECT B.COL_1 AS COL_1 FROM BASE B;
+
 # execute: false
 -- this query seems to be invalid in postgres and duckdb but valid in bigquery
 SELECT 2 a FROM x GROUP BY 1 HAVING a > 1;
diff --git a/tests/test_optimizer.py b/tests/test_optimizer.py
--- a/tests/test_optimizer.py
+++ b/tests/test_optimizer.py
@@ -242,7 +242,9 @@ def test_qualify_columns(self, logger):
             "CREATE FUNCTION `udfs`.`myTest`(`x` FLOAT64) AS (1)",
         )
 
-        self.check_file("qualify_columns", qualify_columns, execute=True, schema=self.schema)
+        self.check_file(
+            "qualify_columns", qualify_columns, execute=True, schema=self.schema, set_dialect=True
+        )
 
     def test_qualify_columns__with_invisible(self):
         schema = MappingSchema(self.schema, {"x": {"a"}, "y": {"b"}, "z": {"b"}})