Fix MAP columns dropping complex values with EnableArrow=1 (#1505)#1506
Closed
rileythomp wants to merge 1 commit into
Closed
Fix MAP columns dropping complex values with EnableArrow=1 (#1505)#1506rileythomp wants to merge 1 commit into
rileythomp wants to merge 1 commit into
Conversation
…s#1505) When complex datatype support is disabled (the default), a MAP column whose values are complex types (ARRAY/STRUCT/MAP) rendered with empty values: SELECT MAP(0, ARRAY(34277,0)) returned {0:} instead of {0:[34277,0]}. ComplexDataTypeParser.formatMapString called JsonNode.asText() on the value node, which returns "" for container (array/object) nodes. Delegate map formatting to the existing recursive parseToMap -> DatabricksMap.toString() path, which formats nested complex values correctly and reproduces identical output for scalar maps. Also harden DatabricksMap/DatabricksArray against null nested values (previously NPE). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Signed-off-by: Riley Thompson <rileythompson99@gmail.com>
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes incorrect string formatting for MAP columns with complex nested values when EnableArrow=1 and complex datatype support is disabled (default), addressing issue #1505 where nested map values could be dropped (e.g. {0:} instead of {0:[34277,0]}).
Changes:
- Updated
ComplexDataTypeParser.formatMapStringto use the recursive typed parsing path for MAPs so nested values (ARRAY/STRUCT/MAP) are preserved. - Hardened
DatabricksMapandDatabricksArrayconversions againstnullnested values. - Added unit and e2e regressions to catch dropped nested values on the Arrow path; updated changelog entry.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/test/java/com/databricks/jdbc/integration/e2e/ComplexTypeQueryTests.java | Strengthens e2e assertions to ensure map array values are not dropped (regression coverage for #1505). |
| src/test/java/com/databricks/jdbc/api/impl/ComplexDataTypeParserTest.java | Adds unit tests covering map-of-arrays, map-of-struct, nested-map, and null nested values. |
| src/main/java/com/databricks/jdbc/api/impl/DatabricksMap.java | Adds null guard in value conversion to avoid NPE for null nested values. |
| src/main/java/com/databricks/jdbc/api/impl/DatabricksArray.java | Adds null guard per element to avoid NPE and preserve nulls in nested arrays. |
| src/main/java/com/databricks/jdbc/api/impl/ComplexDataTypeParser.java | Routes MAP formatting through recursive parsing to correctly render nested complex values. |
| NEXT_CHANGELOG.md | Documents the MAP formatting fix and null-handling improvement. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+340
to
347
| // When the MAP type metadata is available, delegate to the recursive typed parser so | ||
| // that nested complex values (ARRAY/STRUCT/MAP) are formatted correctly. The | ||
| // hand-rolled loop below calls JsonNode.asText(), which returns "" for container nodes | ||
| // and therefore drops nested values (issue #1505). DatabricksMap#toString reproduces | ||
| // the same {key:value} output for scalar maps. | ||
| if (mapMetadata != null && mapMetadata.startsWith(DatabricksTypeUtil.MAP)) { | ||
| kv = MetadataParser.parseMapMetadata(mapMetadata).split(",", 2); | ||
| return parseToMap(node, mapMetadata).toString(); | ||
| } |
Collaborator
|
Can you please move the PR to ready for review if you want this to be reviewed |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
With
EnableArrow=1(and complex datatype support disabled, which is the default), selecting aMAPcolumn whose values are complex types returned malformed data — the map value was dropped while the key survived:With
EnableArrow=0the server returns the value pre-formatted as a string, so only the Arrow path was affected.Root cause
When complex datatype support is disabled,
ArrowStreamResult.getObjectWithComplexTypeHandlingreads the map as raw Arrow JSON (entry-array form, e.g.[{"key":0,"value":[34277,0]}]) and formats it viaComplexDataTypeParser.formatMapString. That hand-rolled formatter calledJsonNode.asText()on the value node, which returns""for any container (array/object) node — so array/struct/nested-map values were rendered empty.Fix
Delegate map formatting to the existing recursive parser:
parseToMap(node, mapMetadata).toString().parseToMapbuilds aDatabricksMapwhose nested values are recursively converted toDatabricksArray/DatabricksMap/DatabricksStruct, and theirtoString()methods already emit the canonical{key:value}/[a,b]format. This:{0:[34277,0]}for the reported case.formatMapStringtests).Also hardened
DatabricksMap.convertValueandDatabricksArray.convertElementsagainstnullnested values (previously threw an NPE onvalue.getClass()), so e.g. a null array value in a map now renders asnull.Scope / follow-up
Scoped to MAP-rooted columns (the reported bug). Top-level
ARRAY/STRUCTcolumns whose elements/fields are themselves maps still pass through raw Arrow output — a separate latent gap that can be addressed in a follow-up if desired.Test plan
ComplexDataTypeParserTestcovering the exact repro plus map-of-arrays, map-of-struct, nested-map, and null-complex-value cases, and the existing scalar-map regressions.testMapOfArrayse2e test so dropped array values would be caught.mvn test -pl jdbc-corepasses (3493 run; the single unrelated failure is a pre-existing DST/timezone test,Slf4jFormatterTest, expectingESTfor a June date).spotless:checkis clean.🤖 Generated with Claude Code