spark3的bug
1.[SPARK-39936][SQL] Store schema in properties for Spark Views,spark视图保存到hive metastore时未清空tableschema导致解析失败
Hive DataType解析器主要发生在Hive的元数据存储(Hive Metastore)阶段。当Hive创建表或解析表结构时,Hive会使用DataType解析器来解析表中定义的数据类型。这个解析器会尝试解析和转换表的列、字段和分区的数据类型、长度、约束等信息。它会确保表定义与Hive的数据类型系统相匹配,并正确解析表结构,从而能够正确地进行数据的存储和查询。如果在解析过程中出现格式错误或不受支持的数据类型,解析器会抛出异常并中断解析过程。在这个阶段,Hive DataType解析器负责将用户定义的数据类型转换为Hive支持的数据类型,并确保数据的一致性和正确性。
[SPARK-39936][SQL] 在Spark视图中存储模式属性
这个pull request提出了什么样的改变?
通常我们将tableSchema存储在table属性中,而不是作为实际模式。我们通常这样做是因为它有助于绕过一些Hive-Metastore问题,包括与SparkSQLDataType解析器的解析问题。
然而,问题在于我们没有清空Spark视图的tableSchema(Spark视图本来就与Hive不兼容)。因此,Hive DataType解析器会尝试解析模式并导致错误。解决方法是在将Spark视图保存到Hive Metastore时清空tableSchema。
这修复了以下错误:
-- this works since we use backticks in `date-of-creation`
create table table_with_hyphen (f array<struct<validColumnTypeName:string>>) using parquet;
-- this should work since we use backticks in `date-of-creation` but will break without this bugfix
create or replace view view_with_hyphen as select f from table_with_hyphen;
2.[SPARK-40002][SQL] Don't push down limit through window using ntile,将nitle函数应用于limit的结果将会导致错误的结果
[
这个拉取请求提议的更改是更改"LimitPushDownThroughWindow",使其不再支持通过ntile函数将limit下推到窗口。
需要进行这些更改的原因是在无分区窗口中,目前ntile函数应用于limit的结果。这种行为会导致与Spark 3.1.3、Hive 2.3.9和PrestoDB 0.268产生冲突的结果。
举个例子:
假设有以下数据
Assume this data:
```
create table t1 stored as parquet as
select *
from range(101);
```
Also assume this query:
```
select id, ntile(10) over (order by id) as nt
from t1
limit 10;
```
With Spark 3.2.2, Spark 3.3.0, and master, the limit is applied before the ntile function:
```
+---+---+
|id |nt |
+---+---+
|0 |1 |
|1 |2 |
|2 |3 |
|3 |4 |
|4 |5 |
|5 |6 |
|6 |7 |
|7 |8 |
|8 |9 |
|9 |10 |
+---+---+
```
With Spark 3.1.3, and Hive 2.3.9, and Prestodb 0.268, the limit is applied _after_ ntile.
Spark 3.1.3:
```
+---+---+
|id |nt |
+---+---+
|0 |1 |
|1 |1 |
|2 |1 |
|3 |1 |
|4 |1 |
|5 |1 |
|6 |1 |
|7 |1 |
|8 |1 |
|9 |1 |
+---+---+
```
Hive 2.3.9:
```
+-----+-----+
| id | nt |
+-----+-----+
| 0 | 1 |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 1 |
| 5 | 1 |
| 6 | 1 |
| 7 | 1 |
| 8 | 1 |
| 9 | 1 |
+-----+-----+
10 rows selected (1.72 seconds)
```
Prestodb 0.268:
```
id | nt
----+----
0 | 1
1 | 1
2 | 1
3 | 1
4 | 1
5 | 1
6 | 1
7 | 1
8 | 1
9 | 1
(10 rows)
```
3. [SPARK-40963][SQL] Set nullable correctly in project created by ExtractGenerator,可能会导致错误的结果以及空指针问题
### 此拉取请求中提出了哪些更改?
在 `ExtractGenerator` 中创建新投影列表时,考虑到生成器是否为外部生成器,在设置生成器相关的输出属性的可空性时。
### 为什么需要这些更改?
这个拉取请求修复了一个可能导致结果不正确或引发`NullPointerException`的问题。这个问题有点难以重现,除非使用具有内联表的子查询。
例子:
```
select c1, explode(c4) as c5 from (
select c1, array(c3) as c4 from (
select c1, explode_outer(c2) as c3
from values
(1, array(1, 2)),
(2, array(2, 3)),
(3, null)
as data(c1, c2)
)
);
+---+---+
|c1 |c5 |
+---+---+
|1 |1 |
|1 |2 |
|2 |2 |
|2 |3 |
|3 |0 |
+---+---+
```
在最后一行中,`c5` 是0,但应为 `NULL`。
另一个例子:
```
select c1, exists(c4, x -> x is null) as c5 from (
select c1, array(c3) as c4 from (
select c1, explode_outer(c2) as c3
from values
(1, array(1, 2)),
(2, array(2, 3)),
(3, array())
as data(c1, c2)
)
);
+---+-----+
|c1 |c5 |
+---+-----+
|1 |false|
|1 |false|
|2 |false|
|2 |false|
|3 |false|
+---+-----+
```
在最后一行中,`false` 应该为 `true`。
在这两种情况下,在实例化 `CreateArray(c3)` 时,`c3` 的可空性是不正确的,因为由 `ExtractGenerator` 创建的新投影使用来自 `explode_outer(c2)` 的 `generatorOutput` 作为投影列表。`generatorOutput` 没有考虑到 `explode_outer(c2)` 是一个外部爆炸,因此丢失了可空性设置。
`UpdateAttributeNullability` 最终会为引用 `c3` 的属性修复可空性设置,但它不能修复来自第一个示例中的 `explode(c4)` 或来自第二个示例中的 `exists(c4, x -> x is null)` 的 `containsNull` 设置。
此示例将引发 `NullPointerException`:
```
select c1, inline_outer(c4) from (
select c1, array(c3) as c4 from (
select c1, explode_outer(c2) as c3
from values
(1, array(named_struct('a', 1, 'b', 2))),
(2, array(named_struct('a', 3, 'b', 4), named_struct('a', 5, 'b', 6))),
(3, array())
as data(c1, c2)
)
);
22/10/30 17:34:42 ERROR Executor: Exception in task 1.0 in stage 8.0 (TID 14)
java.lang.NullPointerException
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.generate_doConsume_1$(Unknown Source)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.generate_doConsume_0$(Unknown Source)
at org.apache.spark.sql.catalyst.expressions.GeneratedClass$GeneratedIteratorForCodegenStage1.processNext(Unknown Source)
at org.apache.spark.sql.execution.BufferedRowIterator.hasNext(BufferedRowIterator.java:43)
at org.apache.spark.sql.execution.WholeStageCodegenExec$$anon$1.hasNext(WholeStageCodegenExec.scala:760)
at org.apache.spark.sql.execution.SparkPlan.$anonfun$getByteArrayRdd$1(SparkPlan.scala:364)
```
### 这个 PR 是否引入了用户界面上的任何更改?
没有。
### 如何测试这个补丁?
5.[SPARK-41668][SQL] DECODE function returns wrong results when passed NULL,传NULL后DECODE返回结果有误