Skip to content

Commit 45520d9

Browse files
Bug fix issue 147: BUG with reading table that contains copied map (#149)
Issue with reading a table with a MAP column, but only when the table was created by copying an existing table. The bug was caused by an indexing issue when reading map values from an arrow batch. The occurrence of the bug was dependent on the configuration of batches the result set was broken down into. Added a new test using the arrow batch returned in the error scenario. Also fixed an existing test that had been masking this bug.
2 parents f88afbe + 3b7fbc2 commit 45520d9

File tree

3 files changed

+142
-4
lines changed

3 files changed

+142
-4
lines changed

internal/rows/arrowbased/arrowRows_test.go

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1221,7 +1221,7 @@ func TestArrowRowScanner(t *testing.T) {
12211221
"[\"2021-07-01 05:43:28 +0000 UTC\",\"-2022-08-13 14:01:01 +0000 UTC\",null]",
12221222
"[\"Gr8=\",\"D/8=\",null]",
12231223
"[[1,2,3],[4,5,6],null]",
1224-
"[{\"key1\":1,\"key2\":2},{\"key1\":1,\"key2\":2},null]",
1224+
"[{\"key1\":1,\"key2\":2},{\"key3\":3,\"key4\":4},null]",
12251225
"[{\"Field1\":77,\"Field2\":\"2020-12-31 00:00:00 +0000 UTC\"},{\"Field1\":13,\"Field2\":\"-2020-12-31 00:00:00 +0000 UTC\"},{\"Field1\":null,\"Field2\":null}]",
12261226
"[5.15,123.45,null]",
12271227
"[\"2020-12-31 00:00:00 +0000 UTC\",\"-2020-12-31 00:00:00 +0000 UTC\",null]",
@@ -1287,6 +1287,52 @@ func TestArrowRowScanner(t *testing.T) {
12871287

12881288
})
12891289

1290+
t.Run("Retrieve values - maps issue 147", func(t *testing.T) {
1291+
// This is a test for a bug reported as github issue 147
1292+
// After copying a table with a column of type 'MAP<STRING, STRING>' querying the copy
1293+
// would return the map value for the first row in all rows.
1294+
// This was caused by an indexing bug when retrieving map values that showed up based on
1295+
// how the result set was broken into arrow batches.
1296+
expected := [][]driver.Value{
1297+
{1, map[string]string{"name": "alice2"}},
1298+
{2, map[string]string{"name": "bob2"}},
1299+
{3, map[string]string{"name": "jon2"}},
1300+
}
1301+
1302+
executeStatementResp := cli_service.TExecuteStatementResp{}
1303+
loadTestData(t, "issue147.json", &executeStatementResp)
1304+
1305+
config := config.WithDefaults()
1306+
config.UseArrowNativeTimestamp = true
1307+
config.UseArrowNativeComplexTypes = true
1308+
config.UseArrowNativeDecimal = false
1309+
config.UseArrowNativeIntervalTypes = false
1310+
d, err := NewArrowRowScanner(executeStatementResp.DirectResults.ResultSetMetadata, executeStatementResp.DirectResults.ResultSet.Results, config, nil, context.Background())
1311+
assert.Nil(t, err)
1312+
1313+
ars := d.(*arrowRowScanner)
1314+
1315+
dest := make([]driver.Value, len(executeStatementResp.DirectResults.ResultSetMetadata.Schema.Columns))
1316+
1317+
for i := range expected {
1318+
err = ars.ScanRow(dest, int64(i))
1319+
assert.Nil(t, err)
1320+
1321+
var id int
1322+
s := dest[0].(string)
1323+
err := json.Unmarshal([]byte(s), &id)
1324+
assert.Nil(t, err)
1325+
assert.Equal(t, expected[i][0], id)
1326+
1327+
var foo map[string]string
1328+
s = dest[1].(string)
1329+
err = json.Unmarshal([]byte(s), &foo)
1330+
assert.Nil(t, err)
1331+
assert.Equal(t, expected[i][1], foo)
1332+
}
1333+
1334+
})
1335+
12901336
t.Run("Retrieve values - structs", func(t *testing.T) {
12911337
expected := []driver.Value{
12921338
"{\"f1\":1,\"f2\":\"-0450-11-13 00:00:00 +0000 UTC\",\"f3\":\"-2022-08-13 14:01:01 +0000 UTC\",\"f4\":{\"5\":5,\"6\":7},\"f5\":{\"ield1\":7,\"Field2\":\"-0450-11-13 00:00:00 +0000 UTC\"}}",

internal/rows/arrowbased/columnValues.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ func (mvc *mapValueContainer) Value(i int) (any, error) {
204204
len := e - s
205205
r := "{"
206206
for i := int64(0); i < len; i++ {
207-
k, err := mvc.keys.Value(int(i))
207+
k, err := mvc.keys.Value(int(i + s))
208208
if err != nil {
209209
return nil, err
210210
}
@@ -214,13 +214,13 @@ func (mvc *mapValueContainer) Value(i int) (any, error) {
214214
return nil, err
215215
}
216216

217-
v, err := mvc.values.Value(int(i))
217+
v, err := mvc.values.Value(int(i + s))
218218
if err != nil {
219219
return nil, err
220220
}
221221

222222
var b string
223-
if mvc.values.IsNull(int(i)) {
223+
if mvc.values.IsNull(int(i + s)) {
224224
b = "null"
225225
} else if mvc.complexValue {
226226
b = v.(string)
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
{
2+
"status": {
3+
"statusCode": "SUCCESS_STATUS"
4+
},
5+
"operationHandle": {
6+
"operationId": {
7+
"guid": "Ae4qWOAZGPWte+TeoMZC2w==",
8+
"secret": "M41SnYJyRuuEgstBlGaDnQ=="
9+
},
10+
"operationType": "EXECUTE_STATEMENT",
11+
"hasResultSet": true
12+
},
13+
"directResults": {
14+
"operationStatus": {
15+
"status": {
16+
"statusCode": "SUCCESS_STATUS"
17+
},
18+
"operationState": "FINISHED_STATE",
19+
"operationStarted": 1690227170051,
20+
"operationCompleted": 1690227170417
21+
},
22+
"resultSetMetadata": {
23+
"status": {
24+
"statusCode": "SUCCESS_STATUS"
25+
},
26+
"schema": {
27+
"columns": [
28+
{
29+
"columnName": "id",
30+
"typeDesc": {
31+
"types": [
32+
{
33+
"primitiveEntry": {
34+
"type": "STRING_TYPE"
35+
}
36+
}
37+
]
38+
},
39+
"position": 1,
40+
"comment": ""
41+
},
42+
{
43+
"columnName": "myMap",
44+
"typeDesc": {
45+
"types": [
46+
{
47+
"primitiveEntry": {
48+
"type": "MAP_TYPE"
49+
}
50+
}
51+
]
52+
},
53+
"position": 2,
54+
"comment": ""
55+
}
56+
]
57+
},
58+
"resultFormat": "ARROW_BASED_SET",
59+
"lz4Compressed": false,
60+
"arrowSchema": "/////6ACAAAQAAAAAAAKAA4ABgANAAgACgAAAAAABAAQAAAAAAEKAAwAAAAIAAQACgAAAAgAAAAIAAAAAAAAAAIAAAC0AQAABAAAAGb+//8UAAAA2AAAAIABAAAAABEBfAEAAAIAAACEAAAABAAAABz+//8IAAAAWAAAAE8AAAB7InR5cGUiOiJtYXAiLCJrZXlUeXBlIjoic3RyaW5nIiwidmFsdWVUeXBlIjoic3RyaW5nIiwidmFsdWVDb250YWluc051bGwiOnRydWV9ABcAAABTcGFyazpEYXRhVHlwZTpKc29uVHlwZQCY/v//CAAAABwAAAATAAAATUFQPFNUUklORywgU1RSSU5HPgAWAAAAU3Bhcms6RGF0YVR5cGU6U3FsTmFtZQAAAQAAAAQAAACq////FAAAABQAAACIAAAAAAAADYQAAAAAAAAAAgAAAEgAAAAEAAAAdv///xQAAAAUAAAAFAAAAAAABQEQAAAAAAAAAAAAAADo/v//BQAAAHZhbHVlABIAGAAUAAAAEwAMAAAACAAEABIAAAAUAAAAFAAAABQAAAAAAAAFEAAAAAAAAAAAAAAAKP///wMAAABrZXkANP///wcAAABlbnRyaWVzAET///8FAAAAbXlNYXAAEgAYABQAEwASAAwAAAAIAAQAEgAAABQAAACQAAAAlAAAAAAABQGQAAAAAgAAAEgAAAAEAAAAyP///wgAAAAUAAAACAAAACJzdHJpbmciAAAAABcAAABTcGFyazpEYXRhVHlwZTpKc29uVHlwZQAIAAwACAAEAAgAAAAIAAAAEAAAAAYAAABTVFJJTkcAABYAAABTcGFyazpEYXRhVHlwZTpTcWxOYW1lAAAAAAAABAAEAAQAAAACAAAAaWQAAAAAAAA=",
61+
"cacheLookupResult": "LOCAL_CACHE_HIT",
62+
"uncompressedBytes": 512,
63+
"compressedBytes": 512
64+
},
65+
"resultSet": {
66+
"status": {
67+
"statusCode": "SUCCESS_STATUS"
68+
},
69+
"hasMoreRows": false,
70+
"results": {
71+
"startRowOffset": 0,
72+
"rows": [],
73+
"arrowBatches": [
74+
{
75+
"batch": "/////2gBAAAUAAAAAAAAAAwAFgAOABUAEAAEAAwAAACQAAAAAAAAAAAABAAQAAAAAAMKABgADAAIAAQACgAAABQAAADYAAAAAwAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAQAAAAAAAAAIAAAAAAAAABAAAAAAAAAAGAAAAAAAAAADAAAAAAAAACAAAAAAAAAAAQAAAAAAAAAoAAAAAAAAABAAAAAAAAAAOAAAAAAAAAABAAAAAAAAAEAAAAAAAAAAAQAAAAAAAABIAAAAAAAAABAAAAAAAAAAWAAAAAAAAAAMAAAAAAAAAGgAAAAAAAAAAQAAAAAAAABwAAAAAAAAABAAAAAAAAAAgAAAAAAAAAAOAAAAAAAAAAAAAAAFAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAADAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAABAAAAAgAAAAMAAAAxMjMAAAAAAAcAAAAAAAAAAAAAAAEAAAACAAAAAwAAAAcAAAAAAAAABwAAAAAAAAAAAAAABAAAAAgAAAAMAAAAbmFtZW5hbWVuYW1lAAAAAAcAAAAAAAAAAAAAAAYAAAAKAAAADgAAAGFsaWNlMmJvYjJqb24yAAA=",
76+
"rowCount": 3
77+
}
78+
]
79+
}
80+
},
81+
"closeOperation": {
82+
"status": {
83+
"statusCode": "SUCCESS_STATUS"
84+
}
85+
}
86+
},
87+
"executionRejected": false,
88+
"maxClusterCapacity": 10,
89+
"queryCost": 0.5,
90+
"currentClusterLoad": 1,
91+
"idempotencyType": "IDEMPOTENT"
92+
}

0 commit comments

Comments
 (0)