internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: tobymao/sqlglot

Issue:
optimize doesn't work with parenthesis
```
e = parse_one("""
    with x as (
        select a from t0
    )
    (
        SELECT * FROM x
        UNION ALL
        SELECT * FROM x
        LIMIT 10
    )
    limit 10
""", dialect="postgres")

print(optimize(e).sql(pretty=True))
```
got
```
WITH "x" AS (
  SELECT
    "a"
  FROM "t0"
)
(
  WITH "cte_2" AS (
    SELECT
      *
    FROM "x" AS "x"
    LIMIT 10
  )
  SELECT
    * AS "*"
  FROM "x" AS "x"
  UNION ALL
  SELECT
    "cte_2"."*" AS "*"
  FROM "cte_2" AS "cte_2"
)
LIMIT 10
```
where the columns are not qualified.




Discussion:

Resolving patch:
diff --git a/sqlglot/optimizer/scope.py b/sqlglot/optimizer/scope.py
--- a/sqlglot/optimizer/scope.py
+++ b/sqlglot/optimizer/scope.py
@@ -515,7 +515,10 @@ def _traverse_scope(scope):
     elif isinstance(scope.expression, exp.Union):
         yield from _traverse_union(scope)
     elif isinstance(scope.expression, exp.Subquery):
-        yield from _traverse_subqueries(scope)
+        if scope.is_root:
+            yield from _traverse_select(scope)
+        else:
+            yield from _traverse_subqueries(scope)
     elif isinstance(scope.expression, exp.Table):
         yield from _traverse_tables(scope)
     elif isinstance(scope.expression, exp.UDTF):


Test patch:
diff --git a/tests/fixtures/optimizer/optimizer.sql b/tests/fixtures/optimizer/optimizer.sql
--- a/tests/fixtures/optimizer/optimizer.sql
+++ b/tests/fixtures/optimizer/optimizer.sql
@@ -1115,3 +1115,32 @@ WITH `t` AS (
 SELECT
   `t`.`CoL` AS `CoL`
 FROM `t`;
+
+# title: top-level query is parenthesized
+# execute: false
+WITH x AS (
+  SELECT a FROM t
+)
+(
+  SELECT * FROM x
+  UNION ALL
+  SELECT * FROM x
+  LIMIT 10
+)
+LIMIT 10;
+(
+  WITH "cte" AS (
+    SELECT
+      "t"."a" AS "a"
+    FROM "t" AS "t"
+  )
+  SELECT
+    "cte"."a" AS "a"
+  FROM "cte" AS "cte"
+  UNION ALL
+  SELECT
+    "cte"."a" AS "a"
+  FROM "cte" AS "cte"
+  LIMIT 10
+)
+LIMIT 10;
Repository: tobymao/sqlglot

Issue:
When two ROW_NUMBER are used on the same line, the second ORDER BY disappears
I tried this on sqlglot 20.2.0. 
When there's two ROW_NUMBER clauses on the same line the second one is transpiled without the ORDER BY.

**Fully reproducible code snippet**
```
in_sql = '''
SELECT
    (ROW_NUMBER() OVER (PARTITION BY user ORDER BY date ASC) - ROW_NUMBER() OVER (PARTITION BY user, segment ORDER BY date ASC)) group_id
FROM example_table
'''
out_sql = sqlglot.transpile(in_sql, read='trino', write='spark', pretty=True)[0]
print(out_sql)
```

**Output**
```
SELECT
  (
    ROW_NUMBER() OVER (PARTITION BY user ORDER BY date ASC NULLS LAST) - ROW_NUMBER() OVER (PARTITION BY user, segment)
  ) AS group_id
FROM example_table
```


**Expected Output**
```
SELECT
  (
    ROW_NUMBER() OVER (PARTITION BY user ORDER BY date ASC NULLS LAST) - ROW_NUMBER() OVER (PARTITION BY user, segment ORDER BY date ASC NULLS LAST)
  ) AS group_id
FROM example_table
```



Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3269,7 +3269,7 @@ def _parse_set_operations(self, this: t.Optional[exp.Expression]) -> t.Optional[
                 expression=expression,
             )
 
-        if this and self.MODIFIERS_ATTACHED_TO_UNION:
+        if isinstance(this, exp.Union) and self.MODIFIERS_ATTACHED_TO_UNION:
             expression = this.expression
 
             if expression:


Test patch:
diff --git a/tests/fixtures/identity.sql b/tests/fixtures/identity.sql
--- a/tests/fixtures/identity.sql
+++ b/tests/fixtures/identity.sql
@@ -869,3 +869,4 @@ SELECT x FROM t1 UNION ALL SELECT x FROM t2 LIMIT 1
 SELECT x FROM t1 UNION ALL SELECT x FROM t2 UNION ALL SELECT x FROM t3 LIMIT 1
 WITH use(use) AS (SELECT 1) SELECT use FROM use
 SELECT recursive FROM t
+SELECT (ROW_NUMBER() OVER (PARTITION BY user ORDER BY date ASC) - ROW_NUMBER() OVER (PARTITION BY user, segment ORDER BY date ASC)) AS group_id FROM example_table
Repository: tobymao/sqlglot

Issue:
`INTERVAL DAY` used as a type is not parsed as a `sqlglot.exp.DataType` for the postgres dialect
**Fully reproducible code snippet**

Using `interval day` as the type fails to parse as a sqlglot `DataType` instance:

```
In [1]: import sqlglot as sg
Unable to set __version__, run `pip install -e .` or `python setup.py develop` first.

In [2]: sg.parse_one("create table t (x interval day)")
Out[2]:
(CREATE this:
  (SCHEMA this:
    (TABLE this:
      (IDENTIFIER this: t, quoted: False)), expressions:
    (COLUMNDEF this:
      (IDENTIFIER this: x, quoted: False), kind:
      (INTERVAL unit:
        (VAR this: day)))), kind: table, exists: False)
```

while parsing

```
create table t (x interval day to second)
```

returns a `DataType`:

```
In [3]: sg.parse_one("create table t (x interval day to second)")
Out[3]:
(CREATE this:
  (SCHEMA this:
    (TABLE this:
      (IDENTIFIER this: t, quoted: False)), expressions:
    (COLUMNDEF this:
      (IDENTIFIER this: x, quoted: False), kind:
      (DATATYPE this: Type.INTERVAL, expressions:
        (INTERVALSPAN this:
          (VAR this: day), expression:
          (VAR this: second))))), kind: table, exists: False)
```


**Official Documentation**

https://www.postgresql.org/docs/current/datatype-datetime.html

Here are the list of valid interval types for postgres:

![image](https://github.com/tobymao/sqlglot/assets/417981/abb1e3cc-4ff8-4862-b23f-bcf1ce70265d)


Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3599,7 +3599,7 @@ def _parse_types(
                     exp.DataType, this=exp.DataType.Type.INTERVAL, expressions=span
                 )
             else:
-                this = self.expression(exp.Interval, unit=unit)
+                this = self.expression(exp.DataType, this=self.expression(exp.Interval, unit=unit))
 
         if maybe_func and check_func:
             index2 = self._index


Test patch:
diff --git a/tests/dialects/test_postgres.py b/tests/dialects/test_postgres.py
--- a/tests/dialects/test_postgres.py
+++ b/tests/dialects/test_postgres.py
@@ -8,6 +8,11 @@ class TestPostgres(Validator):
     dialect = "postgres"
 
     def test_ddl(self):
+        expr = parse_one("CREATE TABLE t (x INTERVAL day)", read="postgres")
+        cdef = expr.find(exp.ColumnDef)
+        cdef.args["kind"].assert_is(exp.DataType)
+        self.assertEqual(expr.sql(dialect="postgres"), "CREATE TABLE t (x INTERVAL day)")
+
         self.validate_identity("CREATE INDEX idx_x ON x USING BTREE(x, y) WHERE (NOT y IS NULL)")
         self.validate_identity("CREATE TABLE test (elems JSONB[])")
         self.validate_identity("CREATE TABLE public.y (x TSTZRANGE NOT NULL)")
Repository: tobymao/sqlglot

Issue:
ParseError when using LIKE/ILIKE on an element in an object in Snowflake
I'm getting `ParseError: Invalid expression / Unexpected token` when using `LIKE` or `ILIKE` on an element within an object in Snowflake.

Example:
```
import sqlglot
sqlglot.parse(""" select parse_json('{"x": "hello"}'):x like 'hello' """, read="snowflake")
sqlglot.parse(""" select data:x like 'hello' from some_table """, read="snowflake")
```

Both of these cause the parsing error, but both are valid Snowflake statements.


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -328,6 +328,9 @@ def _parse_colon_get_path(
         if not self._match(TokenType.COLON):
             break
 
+    if self._match_set(self.RANGE_PARSERS):
+        this = self.RANGE_PARSERS[self._prev.token_type](self, this) or this
+
     return this
 
 


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -78,6 +78,14 @@ def test_snowflake(self):
         self.validate_identity(
             "SELECT a FROM test PIVOT(SUM(x) FOR y IN ('z', 'q')) AS x TABLESAMPLE (0.1)"
         )
+        self.validate_identity(
+            """SELECT PARSE_JSON('{"x": "hello"}'):x LIKE 'hello'""",
+            """SELECT GET_PATH(PARSE_JSON('{"x": "hello"}'), 'x') LIKE 'hello'""",
+        )
+        self.validate_identity(
+            """SELECT data:x LIKE 'hello' FROM some_table""",
+            """SELECT GET_PATH(data, 'x') LIKE 'hello' FROM some_table""",
+        )
         self.validate_identity(
             "SELECT SUM({ fn CONVERT(123, SQL_DOUBLE) })",
             "SELECT SUM(CAST(123 AS DOUBLE))",
Repository: tobymao/sqlglot

Issue:
INTERVAL '5' hours '30' minutes not working.
Not able to parse databricks query which contains `INTERVAL x hours y minutes`.

getting this error.

`sqlglot.errors.ParseError: Expecting ).`


Discussion:
https://docs.databricks.com/en/sql/language-manual/data-types/interval-type.html

looks like it works for base spark as well
Yes this is working for spark as well.
I plan to take a look into this soon.
It seems like this is also supported:

```
spark-sql (default)> select interval '5' hours '30' minutes '5' seconds '6' milliseconds '7' microseconds;
0 05:30:05.006007000
Time taken: 0.144 seconds, Fetched 1 row(s)
```

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3449,10 +3449,10 @@ def _parse_escape(self, this: t.Optional[exp.Expression]) -> t.Optional[exp.Expr
             return this
         return self.expression(exp.Escape, this=this, expression=self._parse_string())
 
-    def _parse_interval(self) -> t.Optional[exp.Interval]:
+    def _parse_interval(self, match_interval: bool = True) -> t.Optional[exp.Interval]:
         index = self._index
 
-        if not self._match(TokenType.INTERVAL):
+        if not self._match(TokenType.INTERVAL) and match_interval:
             return None
 
         if self._match(TokenType.STRING, advance=False):
@@ -3545,6 +3545,12 @@ def _parse_unary(self) -> t.Optional[exp.Expression]:
     def _parse_type(self, parse_interval: bool = True) -> t.Optional[exp.Expression]:
         interval = parse_interval and self._parse_interval()
         if interval:
+            # Convert INTERVAL 'val_1' unit_1 ... 'val_n' unit_n into a sum of intervals
+            while self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
+                interval = self.expression(  # type: ignore
+                    exp.Add, this=interval, expression=self._parse_interval(match_interval=False)
+                )
+
             return interval
 
         index = self._index


Test patch:
diff --git a/tests/dialects/test_spark.py b/tests/dialects/test_spark.py
--- a/tests/dialects/test_spark.py
+++ b/tests/dialects/test_spark.py
@@ -254,6 +254,14 @@ def test_spark(self):
         self.validate_identity("TRIM(LEADING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("TRIM(TRAILING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("SPLIT(str, pattern, lim)")
+        self.validate_identity(
+            "SELECT INTERVAL '5' HOURS '30' MINUTES '5' SECONDS '6' MILLISECONDS '7' MICROSECONDS",
+            "SELECT INTERVAL '5' HOURS + INTERVAL '30' MINUTES + INTERVAL '5' SECONDS + INTERVAL '6' MILLISECONDS + INTERVAL '7' MICROSECONDS",
+        )
+        self.validate_identity(
+            "SELECT INTERVAL 5 HOURS 30 MINUTES 5 SECONDS 6 MILLISECONDS 7 MICROSECONDS",
+            "SELECT INTERVAL '5' HOURS + INTERVAL '30' MINUTES + INTERVAL '5' SECONDS + INTERVAL '6' MILLISECONDS + INTERVAL '7' MICROSECONDS",
+        )
         self.validate_identity(
             "SELECT REGEXP_REPLACE('100-200', r'([^0-9])', '')",
             "SELECT REGEXP_REPLACE('100-200', '([^0-9])', '')",
Repository: tobymao/sqlglot

Issue:
sqlglot 20.8.0 incorrectly transpiles or fails to parse Snowflake REMOVE / RM syntax
Snowflake RM / REMOVE syntax is incorrectly transpiled or causes errors for the cases from the documentation: `"RM @parquet_stage;" -> "RM AS $parquet_stage;"` is rejected by Snowflake at runtime, the other cases cause ParseErrors.

## reference
https://docs.snowflake.com/en/sql-reference/sql/remove

## code
```
examples = [
    "RM @parquet_stage;",
    "REMOVE @parquet_stage;",
    "RM @%mytable/myobject;",
    "RM @%mytable/myobject/;",
    "RM @~ pattern='.*jun.*';",
    "REMOVE @%orders;",
    "REMOVE @mystage/path1/subpath2;",
]

import sqlglot
import sqlglot.errors

print(sqlglot.__version__)
for i, s in enumerate(examples):
    try:
        t = sqlglot.transpile(
            s.strip(), read="snowflake", write="snowflake", pretty=True
        )
        print(i, s, "->", t)
    except sqlglot.errors.ParseError as e:
        print(i, "error", e)
```
## output
```
20.8.0
0 RM @parquet_stage; -> ['RM AS $parquet_stage']
1 REMOVE @parquet_stage; -> ['REMOVE AS $parquet_stage']
2 error Required keyword: 'this' missing for <class 'sqlglot.expressions.Parameter'>. Line 1, Col: 5.
  RM @%mytable/myobject;
3 error Required keyword: 'this' missing for <class 'sqlglot.expressions.Parameter'>. Line 1, Col: 5.
  RM @%mytable/myobject/;
4 error Required keyword: 'this' missing for <class 'sqlglot.expressions.Parameter'>. Line 1, Col: 5.
  RM @~ pattern='.*jun.*';
5 error Required keyword: 'this' missing for <class 'sqlglot.expressions.Parameter'>. Line 1, Col: 9.
  REMOVE @%orders;
6 error Invalid expression / Unexpected token. Line 1, Col: 16.
  REMOVE @mystage/path1/subpath2;
```


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/snowflake.py b/sqlglot/dialects/snowflake.py
--- a/sqlglot/dialects/snowflake.py
+++ b/sqlglot/dialects/snowflake.py
@@ -663,7 +663,9 @@ class Tokenizer(tokens.Tokenizer):
             "MINUS": TokenType.EXCEPT,
             "NCHAR VARYING": TokenType.VARCHAR,
             "PUT": TokenType.COMMAND,
+            "REMOVE": TokenType.COMMAND,
             "RENAME": TokenType.REPLACE,
+            "RM": TokenType.COMMAND,
             "SAMPLE": TokenType.TABLE_SAMPLE,
             "SQL_DOUBLE": TokenType.DOUBLE,
             "SQL_VARCHAR": TokenType.VARCHAR,


Test patch:
diff --git a/tests/dialects/test_snowflake.py b/tests/dialects/test_snowflake.py
--- a/tests/dialects/test_snowflake.py
+++ b/tests/dialects/test_snowflake.py
@@ -39,6 +39,8 @@ def test_snowflake(self):
   )""",
         )
 
+        self.validate_identity("RM @parquet_stage")
+        self.validate_identity("REMOVE @parquet_stage")
         self.validate_identity("SELECT TIMESTAMP_FROM_PARTS(d, t)")
         self.validate_identity("SELECT GET_PATH(v, 'attr[0].name') FROM vartab")
         self.validate_identity("SELECT TO_ARRAY(CAST(x AS ARRAY))")
Repository: tobymao/sqlglot

Issue:
INTERVAL with multiple parts not supported
Sqlglot seems to fail on interval expressions with multiple parts:

```python
import sqlglot

print(
    sqlglot.parse_one(
        "select '2023-01-01'::timestamp + interval 23 hour + 59 minute + 59 seconds", dialect="databricks"
    )
)
```

This is valid in databricks/spark


Discussion:

Resolving patch:
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -3656,8 +3656,15 @@ def _parse_unary(self) -> t.Optional[exp.Expression]:
     def _parse_type(self, parse_interval: bool = True) -> t.Optional[exp.Expression]:
         interval = parse_interval and self._parse_interval()
         if interval:
-            # Convert INTERVAL 'val_1' unit_1 ... 'val_n' unit_n into a sum of intervals
-            while self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
+            # Convert INTERVAL 'val_1' unit_1 [+] ... [+] 'val_n' unit_n into a sum of intervals
+            while True:
+                index = self._index
+                self._match(TokenType.PLUS)
+
+                if not self._match_set((TokenType.STRING, TokenType.NUMBER), advance=False):
+                    self._retreat(index)
+                    break
+
                 interval = self.expression(  # type: ignore
                     exp.Add, this=interval, expression=self._parse_interval(match_interval=False)
                 )


Test patch:
diff --git a/tests/dialects/test_spark.py b/tests/dialects/test_spark.py
--- a/tests/dialects/test_spark.py
+++ b/tests/dialects/test_spark.py
@@ -250,6 +250,14 @@ def test_spark(self):
         self.validate_identity("TRIM(LEADING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("TRIM(TRAILING 'SL' FROM 'SSparkSQLS')")
         self.validate_identity("SPLIT(str, pattern, lim)")
+        self.validate_identity(
+            "SELECT CAST('2023-01-01' AS TIMESTAMP) + INTERVAL 23 HOUR + 59 MINUTE + 59 SECONDS",
+            "SELECT CAST('2023-01-01' AS TIMESTAMP) + INTERVAL '23' HOUR + INTERVAL '59' MINUTE + INTERVAL '59' SECONDS",
+        )
+        self.validate_identity(
+            "SELECT CAST('2023-01-01' AS TIMESTAMP) + INTERVAL '23' HOUR + '59' MINUTE + '59' SECONDS",
+            "SELECT CAST('2023-01-01' AS TIMESTAMP) + INTERVAL '23' HOUR + INTERVAL '59' MINUTE + INTERVAL '59' SECONDS",
+        )
         self.validate_identity(
             "SELECT INTERVAL '5' HOURS '30' MINUTES '5' SECONDS '6' MILLISECONDS '7' MICROSECONDS",
             "SELECT INTERVAL '5' HOURS + INTERVAL '30' MINUTES + INTERVAL '5' SECONDS + INTERVAL '6' MILLISECONDS + INTERVAL '7' MICROSECONDS",
Repository: tobymao/sqlglot

Issue:
DuckDB POSITIONAL JOIN syntax
DuckDB supports a unique positional join type which matches up rows of equal length tables, [documented here](https://duckdb.org/docs/sql/query_syntax/from#positional-joins). Currently sqlglot's duckdb dialect does not recognize this syntax and interprets it as an alias for a normal join.

Here's a minimal repro, using the example from the documentation:

```python
from sqlglot import parse_one

parsed = parse_one("""
SELECT df1.*, df2.*
FROM df1
POSITIONAL JOIN df2;
""", dialect="duckdb")

print(f"""
{parsed!r}
--------------------
{parsed.sql(dialect="duckdb", pretty=True)}
""")
```

Which prints

```
Select(
  expressions=[
    Column(
      this=Star(),
      table=Identifier(this=df1, quoted=False)),
    Column(
      this=Star(),
      table=Identifier(this=df2, quoted=False))],
  from=From(
    this=Table(
      this=Identifier(this=df1, quoted=False),
      alias=TableAlias(
        this=Identifier(this=POSITIONAL, quoted=False)))),
  joins=[
    Join(
      this=Table(
        this=Identifier(this=df2, quoted=False)))])
--------------------
SELECT
  df1.*,
  df2.*
FROM df1 AS POSITIONAL, df2
```


Discussion:

Resolving patch:
diff --git a/sqlglot/dialects/duckdb.py b/sqlglot/dialects/duckdb.py
--- a/sqlglot/dialects/duckdb.py
+++ b/sqlglot/dialects/duckdb.py
@@ -199,6 +199,7 @@ class Tokenizer(tokens.Tokenizer):
             "LOGICAL": TokenType.BOOLEAN,
             "ONLY": TokenType.ONLY,
             "PIVOT_WIDER": TokenType.PIVOT,
+            "POSITIONAL": TokenType.POSITIONAL,
             "SIGNED": TokenType.INT,
             "STRING": TokenType.VARCHAR,
             "UBIGINT": TokenType.UBIGINT,
diff --git a/sqlglot/parser.py b/sqlglot/parser.py
--- a/sqlglot/parser.py
+++ b/sqlglot/parser.py
@@ -507,8 +507,9 @@ class Parser(metaclass=_Parser):
     }
 
     JOIN_METHODS = {
-        TokenType.NATURAL,
         TokenType.ASOF,
+        TokenType.NATURAL,
+        TokenType.POSITIONAL,
     }
 
     JOIN_SIDES = {
diff --git a/sqlglot/tokens.py b/sqlglot/tokens.py
--- a/sqlglot/tokens.py
+++ b/sqlglot/tokens.py
@@ -317,6 +317,7 @@ class TokenType(AutoName):
     PERCENT = auto()
     PIVOT = auto()
     PLACEHOLDER = auto()
+    POSITIONAL = auto()
     PRAGMA = auto()
     PREWHERE = auto()
     PRIMARY_KEY = auto()


Test patch:
diff --git a/tests/dialects/test_duckdb.py b/tests/dialects/test_duckdb.py
--- a/tests/dialects/test_duckdb.py
+++ b/tests/dialects/test_duckdb.py
@@ -213,6 +213,7 @@ def test_duckdb(self):
             parse_one("a // b", read="duckdb").assert_is(exp.IntDiv).sql(dialect="duckdb"), "a // b"
         )
 
+        self.validate_identity("SELECT df1.*, df2.* FROM df1 POSITIONAL JOIN df2")
         self.validate_identity("MAKE_TIMESTAMP(1992, 9, 20, 13, 34, 27.123456)")
         self.validate_identity("MAKE_TIMESTAMP(1667810584123456)")
         self.validate_identity("SELECT EPOCH_MS(10) AS t")
Repository: tobymao/sqlglot

Issue:
Refactor `Dict` function type arguments to `Mapping` 
When writing `sqlglot` code against `pyright`, I encounter errors in my local IDE. The argument types for `lineage` (and probably others) are too narrow w.r.t. `Dict`/`Mapping` types.

From https://docs.python.org/3/library/typing.html#typing.Dict:

> Note that to annotate arguments, it is preferred to use an abstract collection type such as [Mapping](https://docs.python.org/3/library/typing.html#typing.Mapping) rather than to use [dict](https://docs.python.org/3/library/stdtypes.html#dict) or typing.Dict.


**Fully reproducible code snippet**
```python
from typing import Dict

from sqlglot import exp, parse_one
from sqlglot.lineage import lineage


sqlglot_sources: Dict[str, exp.Query] = {}

lineage(column="y", sql=parse_one("SELECT y from x"), sources=sqlglot_sources)
```

Results in the following error:

```
Argument of type "dict[str, Query]" cannot be assigned to parameter "sources" of type "Dict[str, str | Query] | None" in function "lineage"
  Type "dict[str, Query]" cannot be assigned to type "Dict[str, str | Query] | None"
    "dict[str, Query]" is incompatible with "Dict[str, str | Query]"
      Type parameter "_VT@dict" is invariant, but "Query" is not the same as "str | Query"
      Consider switching from "dict" to "Mapping" which is covariant in the value type
    "dict[str, Query]" is incompatible with "None"Pylance[reportArgumentType](https://github.com/microsoft/pyright/blob/main/docs/configuration.md#reportArgumentType)
```


Discussion:
If I understand this correctly, this change in the `lineage` prototype should suffice, right?

```diff
-    sources: t.Optional[t.Dict[str, str | exp.Query]] = None,
+    sources: t.Optional[t.Mapping[str, str | exp.Query]] = None,
```
I believe so. But I'm surprised there isn't an warning/error thrown by the `mypy` CI check. I would want the fix to incorporate that. The type signature is an easy change, but is prone to change in the future if not enforced.

FWIW, I'm using `typeCheckingMode: "basic"` in `pyright`, so I don't have any fancy configuration: https://microsoft.github.io/pyright/#/configuration?id=main-configuration-options

Resolving patch:
diff --git a/sqlglot/lineage.py b/sqlglot/lineage.py
--- a/sqlglot/lineage.py
+++ b/sqlglot/lineage.py
@@ -68,7 +68,7 @@ def lineage(
     column: str | exp.Column,
     sql: str | exp.Expression,
     schema: t.Optional[t.Dict | Schema] = None,
-    sources: t.Optional[t.Dict[str, str | exp.Query]] = None,
+    sources: t.Optional[t.Mapping[str, str | exp.Query]] = None,
     dialect: DialectType = None,
     **kwargs,
 ) -> Node:


Test patch: