Skip to content

Commit ccef264

Browse files
cloud-fanMaxGekk
authored andcommitted
[SPARK-57777][SQL][CONNECT] Distinguish explicit collation when rendering string literals to SQL
### What changes were proposed in this pull request? This PR makes `Literal.sql` render an explicit `collate` clause for any string literal whose type carries an explicit collation, **including an explicit `UTF8_BINARY`**, while still rendering the default (un-collated) `StringType` without a clause. `Literal.sql` previously had two arms for string literals: ```scala case (v: UTF8String, StringType) => // matched any UTF8_BINARY StringType by value equality "'" + escaped + "'" case (v: UTF8String, st: StringType) => // only reached for non-UTF8_BINARY collations "'" + escaped + "'" + st.typeName.substring(6) ``` The first arm matches via the `StringType` case object's `equals` (which compares `collationId` and `constraint`), so it collapsed both the *default* `StringType` and an *explicitly collated* `UTF8_BINARY` `StringType` into the same clause-less output. The two arms are now merged into one that decides the clause via `DataTypeUtils.isDefaultStringCharOrVarcharType` (the same singleton-identity check used elsewhere, e.g. by `ApplyDefaultCollation` and `SHOW CREATE TABLE`): ```scala case (v: UTF8String, st: StringType) => val collateClause = if (DataTypeUtils.isDefaultStringCharOrVarcharType(st)) "" else s" collate ${st.collationName}" "'" + escaped + "'" + collateClause ``` For non-default collations the produced string is byte-for-byte identical to the previous `st.typeName.substring(6)` output (`typeName` is `s"string collate $collationName"`). This PR also removes a test-only normalization in `PlanGenerationTestSuite` that stamped `UTF8_BINARY` onto every string-type proto whose `collation` field was empty before writing the golden files. That shim made the generated `query-tests` golden artifacts (`.proto.bin` / `.json`, and the downstream `.explain` files) misrepresent the real wire format: a default `StringType` is serialized with an **empty** `collation` field (the "undetermined / default collation" sentinel), not `UTF8_BINARY`. The affected golden files were regenerated so they now reflect what a real client actually sends. ### Why are the changes needed? A default `StringType` and an explicitly-`UTF8_BINARY` `StringType` are semantically different: the former is "undetermined" and is eligible to inherit a default collation during analysis (e.g. `CREATE TABLE ... DEFAULT COLLATION UTF8_LCASE AS SELECT 'x'`), while the latter is explicitly pinned and must not inherit. `Literal.sql` is used in view text, `SHOW CREATE TABLE`, error messages, etc.; rendering an explicitly-collated `UTF8_BINARY` literal without a `collate` clause loses that distinction and is not faithful on re-parse. This aligns string-literal SQL rendering with how the rest of the engine already distinguishes explicit collation. The test-normalization removal is a correctness fix for the Spark Connect golden files: they are meant to be a faithful record of the protocol, and they were showing `collate UTF8_BINARY` on default strings where the actual proto omits the collation. ### Does this PR introduce _any_ user-facing change? Yes. `Literal.sql` now appends ` collate UTF8_BINARY` when a string literal's type is an explicit (non-default) `UTF8_BINARY` `StringType`. A plain default string literal is unchanged (no clause), and literals with other explicit collations are unchanged. This affects SQL text generated from literals (e.g. view definitions, `SHOW CREATE TABLE`, error messages). ### How was this patch tested? Existing suites, all passing: - `catalyst/testOnly org.apache.spark.sql.catalyst.expressions.LiteralExpressionSuite` (49) - `connect-client-jvm/testOnly org.apache.spark.sql.PlanGenerationTestSuite` (727; golden files regenerated and reviewed) - `connect/testOnly org.apache.spark.sql.connect.ProtoToParsedPlanTestSuite` (732; explain golden regenerated) - `sql/testOnly org.apache.spark.sql.SQLQueryTestSuite` for the collation inputs (`collations-basic`, `view-with-default-collation`, `collations-padding-trim`, `collations-string-functions`, `collations-aliases`, `listagg-collations`) (12; no golden changes) - `sql/testOnly org.apache.spark.sql.execution.command.{v1,v2}.ShowCreateTableSuite` (47) The regenerated golden diff is limited to dropping the test-stamped `collation: "UTF8_BINARY"` from default-string proto types and the corresponding `CAST(NULL AS STRING COLLATE UTF8_BINARY)` -> `CAST(NULL AS STRING)` in one explain file. ### Was this patch authored or co-authored using generative AI tooling? Generated-by: Claude Code (Opus 4.8) Closes #56892 from cloud-fan/cloud-fan/string-literal-default-collation. Authored-by: Wenchen Fan <wenchen@databricks.com> Signed-off-by: Max Gekk <max.gekk@gmail.com> (cherry picked from commit a947296) Signed-off-by: Max Gekk <max.gekk@gmail.com>
1 parent 343e576 commit ccef264

12 files changed

Lines changed: 26 additions & 38 deletions

File tree

sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/literals.scala

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -592,13 +592,20 @@ case class Literal (value: Any, dataType: DataType) extends LeafExpression {
592592
override def sql: String = (value, dataType) match {
593593
case (_, NullType | _: ArrayType | _: MapType | _: StructType) if value == null => "NULL"
594594
case _ if value == null => s"CAST(NULL AS ${dataType.sql})"
595-
case (v: UTF8String, StringType) =>
596-
// Escapes all backslashes and single quotes.
597-
"'" + v.toString.replace("\\", "\\\\").replace("'", "\\'") + "'"
598595
case (v: UTF8String, st: StringType) =>
596+
// Only render a `collate` clause for an explicit collation (including an explicit
597+
// `UTF8_BINARY`). The default `StringType` (the case object) has no explicit collation, so
598+
// it must render without a clause and stay distinguishable from an explicitly-collated
599+
// string on re-parse (e.g. so that default-collation resolution does not treat an
600+
// explicitly-collated literal as eligible for inheriting a default collation).
601+
val collateClause =
602+
if (DataTypeUtils.isDefaultStringCharOrVarcharType(st)) {
603+
""
604+
} else {
605+
s" collate ${st.collationName}"
606+
}
599607
// Escapes all backslashes and single quotes.
600-
"'" + v.toString.replace("\\", "\\\\").replace("'", "\\'") +
601-
"'" + st.typeName.substring(6)
608+
"'" + v.toString.replace("\\", "\\\\").replace("'", "\\'") + "'" + collateClause
602609
case (v: Byte, ByteType) => s"${v}Y"
603610
case (v: Short, ShortType) => s"${v}S"
604611
case (v: Long, LongType) => s"${v}L"

sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/LiteralExpressionSuite.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,4 +842,17 @@ class LiteralExpressionSuite extends SparkFunSuite with ExpressionEvalHelper {
842842
assert(lit.dataType === GeometryType(0))
843843
assert(lit.value.isInstanceOf[BinaryView])
844844
}
845+
846+
test("SPARK-57777: render explicit collation in string literal SQL") {
847+
// The default `StringType` (case object) has no explicit collation, so it renders
848+
// without a `collate` clause.
849+
assert(Literal(UTF8String.fromString("x"), StringType).sql === "'x'")
850+
// A non-default (non-singleton) `UTF8_BINARY` `StringType` is an explicit collation, so it
851+
// renders the clause and stays distinguishable from the default on re-parse.
852+
assert(Literal(UTF8String.fromString("x"), StringType("UTF8_BINARY")).sql ===
853+
"'x' collate UTF8_BINARY")
854+
// Other explicit collations are rendered as before.
855+
assert(Literal(UTF8String.fromString("x"), StringType("UTF8_LCASE")).sql ===
856+
"'x' collate UTF8_LCASE")
857+
}
845858
}

sql/connect/client/jvm/src/test/scala/org/apache/spark/sql/PlanGenerationTestSuite.scala

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,6 @@ class PlanGenerationTestSuite extends ConnectFunSuite with Logging {
198198
/**
199199
* Normalize proto messages for stable comparison:
200200
* - Trim JVM origin fields (lines, stack traces, anonymous function names)
201-
* - Populate default StringType collation when missing (UTF8_BINARY)
202201
*/
203202
private def normalizeProtoForComparison[T <: protobuf.Message](message: T): T = {
204203
def trim(builder: proto.JvmOrigin.Builder): Unit = {
@@ -221,17 +220,6 @@ class PlanGenerationTestSuite extends ConnectFunSuite with Logging {
221220
val builder = message.toBuilder
222221

223222
builder match {
224-
// For comparison only, we add UTF8_BINARY when StringType collation is missing
225-
// to ensure deterministic plan equality across environments.
226-
case dt: proto.DataType.Builder if dt.getKindCase == proto.DataType.KindCase.STRING =>
227-
val sb = dt.getStringBuilder
228-
if (sb.getCollation.isEmpty) {
229-
val defaultCollationName =
230-
CollationFactory
231-
.fetchCollation(CollationFactory.UTF8_BINARY_COLLATION_ID)
232-
.collationName
233-
sb.setCollation(defaultCollationName)
234-
}
235223
case exp: proto.Relation.Builder
236224
if exp.hasCommon && exp.getCommon.hasOrigin && exp.getCommon.getOrigin.hasJvmOrigin =>
237225
trim(exp.getCommonBuilder.getOriginBuilder.getJvmOriginBuilder)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
Project [id#0L, id#0L, 1 AS 1#0, null AS NULL#0, true AS true#0, 68 AS 68#0, 9872 AS 9872#0, -8726532 AS -8726532#0, 7834609328726532 AS 7834609328726532#0L, 2.718281828459045 AS 2.718281828459045#0, -0.8 AS -0.8#0, 89.97620 AS 89.97620#0, 89889.7667231 AS 89889.7667231#0, connect! AS connect!#0, T AS T#0, ABCDEFGHIJ AS ABCDEFGHIJ#0, 0x78797A7B7C7D7E7F808182838485868788898A8B8C8D8E AS X'78797A7B7C7D7E7F808182838485868788898A8B8C8D8E'#0, 0x0806 AS X'0806'#0, [8,6] AS ARRAY(8, 6)#0, null AS NULL#0, 2020-10-10 AS DATE '2020-10-10'#0, 8.997620 AS 8.997620#0, 2023-02-23 04:31:59.808 AS TIMESTAMP '2023-02-23 04:31:59.808'#0, 1969-12-31 16:00:12.345 AS TIMESTAMP '1969-12-31 16:00:12.345'#0, 2023-02-23 20:36:00 AS TIMESTAMP_NTZ '2023-02-23 20:36:00'#0, 2023-02-23 AS DATE '2023-02-23'#0, INTERVAL '0 00:03:20' DAY TO SECOND AS INTERVAL '0 00:03:20' DAY TO SECOND#0, INTERVAL '0-0' YEAR TO MONTH AS INTERVAL '0-0' YEAR TO MONTH#0, 23:59:59.999999999 AS TIME '23:59:59.999999999'#0, 2 months 20 days 0.0001 seconds AS INTERVAL '2 months 20 days 0.0001 seconds'#0, [18545,1677155519808000,12345000,1677184560000000,19411,200000000,0,86399999999999,2 months 20 days 0.0001 seconds] AS NAMED_STRUCT('_1', DATE '2020-10-10', '_2', TIMESTAMP '2023-02-23 04:31:59.808', '_3', TIMESTAMP '1969-12-31 16:00:12.345', '_4', TIMESTAMP_NTZ '2023-02-23 20:36:00', '_5', DATE '2023-02-23', '_6', INTERVAL '0 00:03:20' DAY TO SECOND, '_7', INTERVAL '0-0' YEAR TO MONTH, '_8', TIME '23:59:59.999999999', '_9', INTERVAL '2 months 20 days 0.0001 seconds')#0, 1 AS 1#0, [1,2,3] AS ARRAY(1, 2, 3)#0, [null,null] AS ARRAY(CAST(NULL AS INT), CAST(NULL AS INT))#0, [null,null,[1,a],[2,null]] AS ARRAY(NULL, NULL, NAMED_STRUCT('_1', 1, '_2', 'a'), NAMED_STRUCT('_1', 2, '_2', CAST(NULL AS STRING COLLATE UTF8_BINARY)))#0, [null,null,[1,a]] AS ARRAY(NULL, NULL, NAMED_STRUCT('_1', 1, '_2', 'a'))#0, [1,2,3] AS ARRAY(1, 2, 3)#0, map(keys: [a,b], values: [1,2]) AS MAP('a', 1, 'b', 2)#0, map(keys: [a,b], values: [null,null]) AS MAP('a', CAST(NULL AS INT), 'b', CAST(NULL AS INT))#0, [a,2,1.0] AS NAMED_STRUCT('_1', 'a', '_2', 2, '_3', 1.0D)#0, null AS NULL#0, [1] AS ARRAY(1)#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, [[1,2,3],[4,5,6],[7,8,9]] AS ARRAY(ARRAY(1, 2, 3), ARRAY(4, 5, 6), ARRAY(7, 8, 9))#0, [[1,2,[3,4]],[5,6,[]]] AS ARRAY(NAMED_STRUCT('_1', 1, '_2', '2', '_3', ARRAY('3', '4')), NAMED_STRUCT('_1', 5, '_2', '6', '_3', ARRAY()))#0, [[1,2],[3,4],[5,6]] AS ARRAY(NAMED_STRUCT('a', 1, 'b', '2'), NAMED_STRUCT('a', 3, 'b', '4'), NAMED_STRUCT('a', 5, 'b', '6'))#0, [keys: [a,b], values: [1,2],keys: [a,b], values: [3,4],keys: [a,b], values: [5,6]] AS ARRAY(MAP('a', 1, 'b', 2), MAP('a', 3, 'b', 4), MAP('a', 5, 'b', 6))#0, [keys: [a,b], values: [[1,2],[3,4]],keys: [a,b], values: [[5,6],[7,8]],keys: [a,b], values: [[],[]]] AS ARRAY(MAP('a', ARRAY('1', '2'), 'b', ARRAY('3', '4')), MAP('a', ARRAY('5', '6'), 'b', ARRAY('7', '8')), MAP('a', ARRAY(), 'b', ARRAY()))#0, map(keys: [1,2], values: [keys: [a,b], values: [1,2],keys: [a,b], values: [3,4]]) AS MAP(1, MAP('a', 1, 'b', 2), 2, MAP('a', 3, 'b', 4))#0, [[1,2,3],keys: [a,b], values: [1,2],[a,keys: [1,2], values: [a,b]]] AS NAMED_STRUCT('_1', ARRAY(1, 2, 3), '_2', MAP('a', 1, 'b', 2), '_3', NAMED_STRUCT('_1', 'a', '_2', MAP(1, 'a', 2, 'b')))#0]
1+
Project [id#0L, id#0L, 1 AS 1#0, null AS NULL#0, true AS true#0, 68 AS 68#0, 9872 AS 9872#0, -8726532 AS -8726532#0, 7834609328726532 AS 7834609328726532#0L, 2.718281828459045 AS 2.718281828459045#0, -0.8 AS -0.8#0, 89.97620 AS 89.97620#0, 89889.7667231 AS 89889.7667231#0, connect! AS connect!#0, T AS T#0, ABCDEFGHIJ AS ABCDEFGHIJ#0, 0x78797A7B7C7D7E7F808182838485868788898A8B8C8D8E AS X'78797A7B7C7D7E7F808182838485868788898A8B8C8D8E'#0, 0x0806 AS X'0806'#0, [8,6] AS ARRAY(8, 6)#0, null AS NULL#0, 2020-10-10 AS DATE '2020-10-10'#0, 8.997620 AS 8.997620#0, 2023-02-23 04:31:59.808 AS TIMESTAMP '2023-02-23 04:31:59.808'#0, 1969-12-31 16:00:12.345 AS TIMESTAMP '1969-12-31 16:00:12.345'#0, 2023-02-23 20:36:00 AS TIMESTAMP_NTZ '2023-02-23 20:36:00'#0, 2023-02-23 AS DATE '2023-02-23'#0, INTERVAL '0 00:03:20' DAY TO SECOND AS INTERVAL '0 00:03:20' DAY TO SECOND#0, INTERVAL '0-0' YEAR TO MONTH AS INTERVAL '0-0' YEAR TO MONTH#0, 23:59:59.999999999 AS TIME '23:59:59.999999999'#0, 2 months 20 days 0.0001 seconds AS INTERVAL '2 months 20 days 0.0001 seconds'#0, [18545,1677155519808000,12345000,1677184560000000,19411,200000000,0,86399999999999,2 months 20 days 0.0001 seconds] AS NAMED_STRUCT('_1', DATE '2020-10-10', '_2', TIMESTAMP '2023-02-23 04:31:59.808', '_3', TIMESTAMP '1969-12-31 16:00:12.345', '_4', TIMESTAMP_NTZ '2023-02-23 20:36:00', '_5', DATE '2023-02-23', '_6', INTERVAL '0 00:03:20' DAY TO SECOND, '_7', INTERVAL '0-0' YEAR TO MONTH, '_8', TIME '23:59:59.999999999', '_9', INTERVAL '2 months 20 days 0.0001 seconds')#0, 1 AS 1#0, [1,2,3] AS ARRAY(1, 2, 3)#0, [null,null] AS ARRAY(CAST(NULL AS INT), CAST(NULL AS INT))#0, [null,null,[1,a],[2,null]] AS ARRAY(NULL, NULL, NAMED_STRUCT('_1', 1, '_2', 'a'), NAMED_STRUCT('_1', 2, '_2', CAST(NULL AS STRING)))#0, [null,null,[1,a]] AS ARRAY(NULL, NULL, NAMED_STRUCT('_1', 1, '_2', 'a'))#0, [1,2,3] AS ARRAY(1, 2, 3)#0, map(keys: [a,b], values: [1,2]) AS MAP('a', 1, 'b', 2)#0, map(keys: [a,b], values: [null,null]) AS MAP('a', CAST(NULL AS INT), 'b', CAST(NULL AS INT))#0, [a,2,1.0] AS NAMED_STRUCT('_1', 'a', '_2', 2, '_3', 1.0D)#0, null AS NULL#0, [1] AS ARRAY(1)#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, map(keys: [1], values: [null]) AS MAP(1, CAST(NULL AS INT))#0, [[1,2,3],[4,5,6],[7,8,9]] AS ARRAY(ARRAY(1, 2, 3), ARRAY(4, 5, 6), ARRAY(7, 8, 9))#0, [[1,2,[3,4]],[5,6,[]]] AS ARRAY(NAMED_STRUCT('_1', 1, '_2', '2', '_3', ARRAY('3', '4')), NAMED_STRUCT('_1', 5, '_2', '6', '_3', ARRAY()))#0, [[1,2],[3,4],[5,6]] AS ARRAY(NAMED_STRUCT('a', 1, 'b', '2'), NAMED_STRUCT('a', 3, 'b', '4'), NAMED_STRUCT('a', 5, 'b', '6'))#0, [keys: [a,b], values: [1,2],keys: [a,b], values: [3,4],keys: [a,b], values: [5,6]] AS ARRAY(MAP('a', 1, 'b', 2), MAP('a', 3, 'b', 4), MAP('a', 5, 'b', 6))#0, [keys: [a,b], values: [[1,2],[3,4]],keys: [a,b], values: [[5,6],[7,8]],keys: [a,b], values: [[],[]]] AS ARRAY(MAP('a', ARRAY('1', '2'), 'b', ARRAY('3', '4')), MAP('a', ARRAY('5', '6'), 'b', ARRAY('7', '8')), MAP('a', ARRAY(), 'b', ARRAY()))#0, map(keys: [1,2], values: [keys: [a,b], values: [1,2],keys: [a,b], values: [3,4]]) AS MAP(1, MAP('a', 1, 'b', 2), 2, MAP('a', 3, 'b', 4))#0, [[1,2,3],keys: [a,b], values: [1,2],[a,keys: [1,2], values: [a,b]]] AS NAMED_STRUCT('_1', ARRAY(1, 2, 3), '_2', MAP('a', 1, 'b', 2), '_3', NAMED_STRUCT('_1', 'a', '_2', MAP(1, 'a', 2, 'b')))#0]
22
+- LocalRelation <empty>, [id#0L, a#0, b#0]

sql/connect/common/src/test/resources/query-tests/queries/csv_from_dataset.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"name": "c1",
1919
"dataType": {
2020
"string": {
21-
"collation": "UTF8_BINARY"
2221
}
2322
},
2423
"nullable": true
Binary file not shown.

sql/connect/common/src/test/resources/query-tests/queries/function_lit_array.json

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,6 @@
521521
"array": {
522522
"elementType": {
523523
"string": {
524-
"collation": "UTF8_BINARY"
525524
}
526525
},
527526
"containsNull": true
@@ -579,7 +578,6 @@
579578
"array": {
580579
"elementType": {
581580
"string": {
582-
"collation": "UTF8_BINARY"
583581
}
584582
},
585583
"containsNull": true
Binary file not shown.

sql/connect/common/src/test/resources/query-tests/queries/function_typedLit.json

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@
8282
},
8383
"dataType": {
8484
"string": {
85-
"collation": "UTF8_BINARY"
8685
}
8786
}
8887
},
@@ -958,7 +957,6 @@
958957
"name": "_2",
959958
"dataType": {
960959
"string": {
961-
"collation": "UTF8_BINARY"
962960
}
963961
},
964962
"nullable": true
@@ -1023,7 +1021,6 @@
10231021
"name": "_2",
10241022
"dataType": {
10251023
"string": {
1026-
"collation": "UTF8_BINARY"
10271024
}
10281025
},
10291026
"nullable": true
@@ -1106,7 +1103,6 @@
11061103
"map": {
11071104
"keyType": {
11081105
"string": {
1109-
"collation": "UTF8_BINARY"
11101106
}
11111107
},
11121108
"valueType": {
@@ -1157,7 +1153,6 @@
11571153
"map": {
11581154
"keyType": {
11591155
"string": {
1160-
"collation": "UTF8_BINARY"
11611156
}
11621157
},
11631158
"valueType": {
@@ -1202,7 +1197,6 @@
12021197
"name": "_1",
12031198
"dataType": {
12041199
"string": {
1205-
"collation": "UTF8_BINARY"
12061200
}
12071201
},
12081202
"nullable": true
@@ -1545,7 +1539,6 @@
15451539
"name": "_2",
15461540
"dataType": {
15471541
"string": {
1548-
"collation": "UTF8_BINARY"
15491542
}
15501543
},
15511544
"nullable": true
@@ -1555,7 +1548,6 @@
15551548
"array": {
15561549
"elementType": {
15571550
"string": {
1558-
"collation": "UTF8_BINARY"
15591551
}
15601552
},
15611553
"containsNull": true
@@ -1629,7 +1621,6 @@
16291621
"name": "b",
16301622
"dataType": {
16311623
"string": {
1632-
"collation": "UTF8_BINARY"
16331624
}
16341625
},
16351626
"nullable": true
@@ -1707,7 +1698,6 @@
17071698
"map": {
17081699
"keyType": {
17091700
"string": {
1710-
"collation": "UTF8_BINARY"
17111701
}
17121702
},
17131703
"valueType": {
@@ -1813,14 +1803,12 @@
18131803
"map": {
18141804
"keyType": {
18151805
"string": {
1816-
"collation": "UTF8_BINARY"
18171806
}
18181807
},
18191808
"valueType": {
18201809
"array": {
18211810
"elementType": {
18221811
"string": {
1823-
"collation": "UTF8_BINARY"
18241812
}
18251813
},
18261814
"containsNull": true
@@ -1896,7 +1884,6 @@
18961884
"map": {
18971885
"keyType": {
18981886
"string": {
1899-
"collation": "UTF8_BINARY"
19001887
}
19011888
},
19021889
"valueType": {
@@ -1992,7 +1979,6 @@
19921979
"map": {
19931980
"keyType": {
19941981
"string": {
1995-
"collation": "UTF8_BINARY"
19961982
}
19971983
},
19981984
"valueType": {
@@ -2010,7 +1996,6 @@
20101996
"name": "_1",
20111997
"dataType": {
20121998
"string": {
2013-
"collation": "UTF8_BINARY"
20141999
}
20152000
},
20162001
"nullable": true
@@ -2024,7 +2009,6 @@
20242009
},
20252010
"valueType": {
20262011
"string": {
2027-
"collation": "UTF8_BINARY"
20282012
}
20292013
},
20302014
"valueContainsNull": true
Binary file not shown.

0 commit comments

Comments
 (0)