Skip to content

Commit 33d876a

Browse files
committed
Fix panic on null cells
1 parent c1eee41 commit 33d876a

File tree

4 files changed

+56
-11
lines changed

4 files changed

+56
-11
lines changed

_test/import-xlsx.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ spec:
2323
unique: true
2424
- name: optimized
2525
type: boolean
26+
notnull: true # comment to get a null
2627
- name: count
2728
type: integer
2829
---

_test/test.csv

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ blue,#00f,false,-345
55
cyan,#0ff,true,678
66
magenta,#f0f,false,-678
77
yellow,#ff0,true,901
8-
black,#000,false,-901
8+
black,#000,false,-901
9+
grey,#aaa,false,
10+
white,#fff,,-222

_test/test.xlsx

57 Bytes
Binary file not shown.

resources/data.go

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"encoding/json"
88
"fmt"
99
"os"
10+
"reflect"
1011
"strings"
1112

1213
"github.com/cloudquery/plugin-sdk/schema"
@@ -118,16 +119,20 @@ func fetchData(ctx context.Context, meta schema.ClientMeta, parent *schema.Resou
118119
keys = strings.Split(line, *client.Specs.Separator)
119120
} else {
120121
values := strings.Split(line, *client.Specs.Separator)
121-
row := map[string]any{}
122-
//for i := 0; i < len(client.Specs.Columns); i++ {
123-
for i := 0; i < len(keys); i++ {
124-
for _, column := range client.Specs.Columns {
125-
if keys[i] == column.Name {
126-
row[client.Specs.Columns[i].Name] = values[i]
122+
if len(values) >= len(keys) {
123+
row := map[string]any{}
124+
for i := 0; i < len(keys); i++ {
125+
for _, column := range client.Specs.Columns {
126+
127+
if keys[i] == column.Name {
128+
row[client.Specs.Columns[i].Name] = values[i]
129+
}
127130
}
128131
}
132+
rows = append(rows, row)
133+
} else {
134+
client.Logger.Warn().Str("file", client.Specs.File).Str("line", line).Int("expected", len(keys)).Int("actual", len(values)).Msg("invalid number of columns")
129135
}
130-
rows = append(rows, row)
131136
}
132137
}
133138
case "xsl", "xlsx", "excel":
@@ -163,7 +168,13 @@ func fetchData(ctx context.Context, meta schema.ClientMeta, parent *schema.Resou
163168
values := xlsrow
164169
row := map[string]any{}
165170
for i := 0; i < len(keys); i++ {
166-
row[keys[i]] = values[i]
171+
if i < len(values) {
172+
// XLSX rows can be sparse, in which case all TRAILING empty cells are removed
173+
// from the returned slice; empty cells in the middle are still valid
174+
row[keys[i]] = values[i]
175+
} else {
176+
row[keys[i]] = nil
177+
}
167178
}
168179
rows = append(rows, row)
169180
}
@@ -187,7 +198,38 @@ func fetchData(ctx context.Context, meta schema.ClientMeta, parent *schema.Resou
187198
// and sets it into the resource being returned to CloudQuery.
188199
func fetchColumn(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, c schema.Column) error {
189200
client := meta.(*client.Client)
190-
client.Logger.Debug().Str("resource", format.ToJSON(resource)).Str("column", format.ToJSON(c)).Str("item type", fmt.Sprintf("%T", resource.Item)).Msg("fetching column...")
201+
// client.Logger.Debug().Str("resource", format.ToJSON(resource)).Str("column", format.ToJSON(c)).Str("item type", fmt.Sprintf("%T", resource.Item)).Msg("fetching column...")
191202
item := resource.Item.(map[string]any)
192-
return resource.Set(c.Name, item[c.Name])
203+
value := item[c.Name]
204+
client.Logger.Debug().Str("value", fmt.Sprintf("%v", value)).Str("type", fmt.Sprintf("%T", value)).Msg("checking value type")
205+
if value == nil {
206+
client.Logger.Warn().Msg("value is nil")
207+
if c.CreationOptions.NotNull {
208+
err := fmt.Errorf("invalid nil value for non-nullable column %s", c.Name)
209+
client.Logger.Error().Err(err).Str("name", c.Name).Msg("error setting column")
210+
return err
211+
}
212+
} else {
213+
client.Logger.Warn().Msg("value is NOT nil")
214+
if reflect.ValueOf(value).IsZero() {
215+
if !c.CreationOptions.NotNull {
216+
// column is nullable, let's null it
217+
client.Logger.Warn().Str("name", c.Name).Msg("nulling column value")
218+
value = nil
219+
} else {
220+
client.Logger.Warn().Msg("set default value for type")
221+
switch c.Type {
222+
case schema.TypeBool:
223+
value = false
224+
case schema.TypeInt:
225+
value = 0
226+
case schema.TypeString:
227+
value = ""
228+
}
229+
}
230+
}
231+
}
232+
// in XLSX some values may be null, in which case we must
233+
// be sure we're not asking cloudQuery to parse invalid values
234+
return resource.Set(c.Name, value)
193235
}

0 commit comments

Comments
 (0)