Commit cf13958
fix: support type coercion for MAP literals with NULL values in VALUES lists (#23521)
## Which issue does this PR close?
- Closes #23474.
## Rationale for this change
A bare `MAP {'k1': NULL}` literal infers a `Null` value type, producing
`Map("entries": Struct("key": Utf8, "value": Null))`. Placing it in a
VALUES list alongside concretely-typed map rows failed with:
Error during planning: Inconsistent data type across values list at row
1 column 0.
This is because `type_union_resolution_coercion` (the pairwise worker
behind `type_union_resolution`, which the VALUES builder uses to widen
row types) had recursion arms for `Dictionary`, `RunEndEncoded`,
`Struct`, and `List` (via `list_coercion`), but none for `Map`. Scalar
NULL inference across a VALUES list (`VALUES (1), (NULL)`) already
worked; the same inference just never reached into a map's value type.
This gap was noted in #23406, where the tests had to use a `CAST(NULL AS
BIGINT)` workaround.
## What changes are included in this PR?
- A one-line fix in
`datafusion/expr-common/src/type_coercion/binary.rs`: wire the existing
`map_coercion` helper (already used by `comparison_coercion` and
`type_union_coercion`) into `type_union_resolution_coercion`'s fallback
chain. The recursion into the map's key/value types then applies the
exact same rules as scalar VALUES coercion (`null_coercion` for NULL
inference, `binary_numeric_coercion` for numeric widening),
symmetrically in either row order.
- A unit test (`test_type_union_resolution_map`) covering Null + Int64
value types in both orders, Int64 + Null + Float64 widening, and Map vs.
Struct still refusing to unify.
- A new "map NULL value coercion in VALUES" section in
`datafusion/sqllogictest/test_files/map.slt` covering: the issue
reproducer, the reversed row order, all-NULL values (resulting type
`Map("entries": Struct("key": Utf8, "value": Null))`, verified via
`arrow_typeof`), multi-key rows with one NULL value, NULL scattered
across three rows, numeric widening to Float64, two-level nested maps,
NULL round-tripping as NULL through `SELECT`, and `INSERT INTO ...
VALUES`.
- Incompatible concrete value types still error: `(MAP {'k': 1}), (MAP
{'k': 'hello'})` follows the scalar VALUES rule (coerce to the numeric
type, then fail with `Cast error: Cannot cast string 'hello' to value of
Int64 type`, which is the same behavior as `VALUES (1), ('hello')`).
- A note above the #23406 tests documenting that the `CAST(NULL AS
BIGINT)` workaround is no longer required (those tests are left
unchanged).
## Are these changes tested?
Yes. New unit test in `datafusion-expr-common` and new sqllogictests in
`map.slt` as described above. The full sqllogictest suite (492 files)
passes locally with zero regressions, as do `cargo test -p
datafusion-expr -p datafusion-expr-common`, `cargo fmt`, and `cargo
clippy --workspace --all-targets -- -D warnings`.
## Are there any user-facing changes?
`VALUES` lists (and other contexts that use `type_union_resolution`,
such as `CASE`/`COALESCE`/array literals) now unify Map types whose
key/value types are coercible, including bare NULL map values. No API
changes; previously failing queries now succeed, and incompatible-type
errors are preserved.
---------
Co-authored-by: Jeffrey Vo <jeffrey.vo.australia@gmail.com>1 parent 0099876 commit cf13958
3 files changed
Lines changed: 200 additions & 0 deletions
File tree
- datafusion
- expr-common/src/type_coercion
- binary/tests
- sqllogictest/test_files
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
768 | 768 | | |
769 | 769 | | |
770 | 770 | | |
| 771 | + | |
771 | 772 | | |
772 | 773 | | |
773 | 774 | | |
| |||
Lines changed: 54 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
908 | 908 | | |
909 | 909 | | |
910 | 910 | | |
| 911 | + | |
| 912 | + | |
| 913 | + | |
| 914 | + | |
| 915 | + | |
| 916 | + | |
| 917 | + | |
| 918 | + | |
| 919 | + | |
| 920 | + | |
| 921 | + | |
| 922 | + | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
| 927 | + | |
| 928 | + | |
| 929 | + | |
| 930 | + | |
| 931 | + | |
| 932 | + | |
| 933 | + | |
| 934 | + | |
| 935 | + | |
| 936 | + | |
| 937 | + | |
| 938 | + | |
| 939 | + | |
| 940 | + | |
| 941 | + | |
| 942 | + | |
| 943 | + | |
| 944 | + | |
| 945 | + | |
| 946 | + | |
| 947 | + | |
| 948 | + | |
| 949 | + | |
| 950 | + | |
| 951 | + | |
| 952 | + | |
| 953 | + | |
| 954 | + | |
| 955 | + | |
| 956 | + | |
| 957 | + | |
| 958 | + | |
| 959 | + | |
| 960 | + | |
| 961 | + | |
| 962 | + | |
| 963 | + | |
| 964 | + | |
911 | 965 | | |
912 | 966 | | |
913 | 967 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
920 | 920 | | |
921 | 921 | | |
922 | 922 | | |
| 923 | + | |
| 924 | + | |
| 925 | + | |
| 926 | + | |
923 | 927 | | |
924 | 928 | | |
925 | 929 | | |
| |||
1048 | 1052 | | |
1049 | 1053 | | |
1050 | 1054 | | |
| 1055 | + | |
| 1056 | + | |
| 1057 | + | |
| 1058 | + | |
| 1059 | + | |
| 1060 | + | |
| 1061 | + | |
| 1062 | + | |
| 1063 | + | |
| 1064 | + | |
| 1065 | + | |
| 1066 | + | |
| 1067 | + | |
| 1068 | + | |
| 1069 | + | |
| 1070 | + | |
| 1071 | + | |
| 1072 | + | |
| 1073 | + | |
| 1074 | + | |
| 1075 | + | |
| 1076 | + | |
| 1077 | + | |
| 1078 | + | |
| 1079 | + | |
| 1080 | + | |
| 1081 | + | |
| 1082 | + | |
| 1083 | + | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
| 1093 | + | |
| 1094 | + | |
| 1095 | + | |
| 1096 | + | |
| 1097 | + | |
| 1098 | + | |
| 1099 | + | |
| 1100 | + | |
| 1101 | + | |
| 1102 | + | |
| 1103 | + | |
| 1104 | + | |
| 1105 | + | |
| 1106 | + | |
| 1107 | + | |
| 1108 | + | |
| 1109 | + | |
| 1110 | + | |
| 1111 | + | |
| 1112 | + | |
| 1113 | + | |
| 1114 | + | |
| 1115 | + | |
| 1116 | + | |
| 1117 | + | |
| 1118 | + | |
| 1119 | + | |
| 1120 | + | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
| 1126 | + | |
| 1127 | + | |
| 1128 | + | |
| 1129 | + | |
| 1130 | + | |
| 1131 | + | |
| 1132 | + | |
| 1133 | + | |
| 1134 | + | |
| 1135 | + | |
| 1136 | + | |
| 1137 | + | |
| 1138 | + | |
| 1139 | + | |
| 1140 | + | |
| 1141 | + | |
| 1142 | + | |
| 1143 | + | |
| 1144 | + | |
| 1145 | + | |
| 1146 | + | |
| 1147 | + | |
| 1148 | + | |
| 1149 | + | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
| 1156 | + | |
| 1157 | + | |
| 1158 | + | |
| 1159 | + | |
| 1160 | + | |
| 1161 | + | |
| 1162 | + | |
| 1163 | + | |
| 1164 | + | |
| 1165 | + | |
| 1166 | + | |
| 1167 | + | |
| 1168 | + | |
| 1169 | + | |
| 1170 | + | |
| 1171 | + | |
| 1172 | + | |
| 1173 | + | |
| 1174 | + | |
| 1175 | + | |
| 1176 | + | |
| 1177 | + | |
| 1178 | + | |
| 1179 | + | |
| 1180 | + | |
| 1181 | + | |
| 1182 | + | |
| 1183 | + | |
| 1184 | + | |
| 1185 | + | |
| 1186 | + | |
| 1187 | + | |
| 1188 | + | |
| 1189 | + | |
| 1190 | + | |
| 1191 | + | |
| 1192 | + | |
| 1193 | + | |
| 1194 | + | |
| 1195 | + | |
0 commit comments