Skip to content

Commit

Permalink
add nil error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
taniabogatsch committed Sep 13, 2024
1 parent 687be3f commit fbb2e4d
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 39 deletions.
5 changes: 5 additions & 0 deletions errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ func addIndexToError(err error, idx int) error {
return fmt.Errorf("%w: %s: %d", err, indexErrMsg, idx)
}

func interfaceIsNilError(interfaceName string) error {
return fmt.Errorf("%s: %s", interfaceIsNilErrMsg, interfaceName)
}

const (
driverErrMsg = "database/sql/driver"
duckdbErrMsg = "duckdb error"
Expand All @@ -60,6 +64,7 @@ const (
tryOtherFuncErrMsg = "please try this function instead"
indexErrMsg = "index"
unknownTypeErrMsg = "unknown type"
interfaceIsNilErrMsg = "interface is nil"
)

var (
Expand Down
26 changes: 0 additions & 26 deletions errors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,32 +304,6 @@ func TestErrAPISetValue(t *testing.T) {
testError(t, err, errAPI.Error(), columnCountErrMsg)
}

func TestErrTypeInfo(t *testing.T) {
t.Parallel()

var incorrectTypes []Type
incorrectTypes = append(incorrectTypes, TYPE_DECIMAL, TYPE_ENUM, TYPE_LIST, TYPE_STRUCT, TYPE_MAP)

for _, incorrect := range incorrectTypes {
_, err := NewTypeInfo(incorrect)
testError(t, err, errAPI.Error(), tryOtherFuncErrMsg)
}

var unsupportedTypes []Type
for k := range unsupportedTypeToStringMap {
unsupportedTypes = append(unsupportedTypes, k)
}

for _, unsupported := range unsupportedTypes {
_, err := NewTypeInfo(unsupported)
testError(t, err, errAPI.Error(), unsupportedTypeErrMsg)
}

// Invalid STRUCT entry.
_, err := NewStructEntry(nil, "")
testError(t, err, errAPI.Error(), errEmptyName.Error())
}

func TestDuckDBErrors(t *testing.T) {
db := openDB(t)
createTable(db, t, `CREATE TABLE duckdb_error_test(bar VARCHAR UNIQUE, baz INT32, u_1 UNION("string" VARCHAR))`)
Expand Down
38 changes: 32 additions & 6 deletions type_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,36 @@ func NewEnumInfo(first string, others ...string) TypeInfo {
}

// NewListInfo returns LIST type information.
func NewListInfo(childInfo TypeInfo) TypeInfo {
func NewListInfo(childInfo TypeInfo) (TypeInfo, error) {
if childInfo == nil {
return nil, getError(errAPI, interfaceIsNilError("childInfo"))
}

info := &typeInfo{
baseTypeInfo: baseTypeInfo{Type: TYPE_LIST},
childTypes: make([]TypeInfo, 1),
}
info.childTypes[0] = childInfo
return info
return info, nil
}

// NewStructInfo returns STRUCT type information.
func NewStructInfo(firstEntry StructEntry, others ...StructEntry) TypeInfo {
func NewStructInfo(firstEntry StructEntry, others ...StructEntry) (TypeInfo, error) {
if firstEntry == nil {
return nil, getError(errAPI, interfaceIsNilError("firstEntry"))
}
if firstEntry.Info() == nil {
return nil, getError(errAPI, interfaceIsNilError("firstEntry.Info()"))
}
for i, entry := range others {
if entry == nil {
return nil, getError(errAPI, addIndexToError(interfaceIsNilError("entry"), i))
}
if entry.Info() == nil {
return nil, getError(errAPI, addIndexToError(interfaceIsNilError("entry.Info()"), i))
}
}

info := &typeInfo{
baseTypeInfo: baseTypeInfo{
Type: TYPE_STRUCT,
Expand All @@ -138,18 +157,25 @@ func NewStructInfo(firstEntry StructEntry, others ...StructEntry) TypeInfo {
}
info.structEntries = append(info.structEntries, firstEntry)
info.structEntries = append(info.structEntries, others...)
return info
return info, nil
}

// NewMapInfo returns MAP type information.
func NewMapInfo(keyInfo TypeInfo, valueInfo TypeInfo) TypeInfo {
func NewMapInfo(keyInfo TypeInfo, valueInfo TypeInfo) (TypeInfo, error) {
if keyInfo == nil {
return nil, getError(errAPI, interfaceIsNilError("keyInfo"))
}
if valueInfo == nil {
return nil, getError(errAPI, interfaceIsNilError("valueInfo"))
}

info := &typeInfo{
baseTypeInfo: baseTypeInfo{Type: TYPE_MAP},
childTypes: make([]TypeInfo, 2),
}
info.childTypes[0] = keyInfo
info.childTypes[1] = valueInfo
return info
return info, nil
}

func (info *typeInfo) logicalType() C.duckdb_logical_type {
Expand Down
71 changes: 64 additions & 7 deletions type_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"
)

func TestTypeInterface(t *testing.T) {
func TestTypeInfo(t *testing.T) {
var primitiveTypes []Type
for k := range typeToStringMap {
_, inMap := unsupportedTypeToStringMap[k]
Expand All @@ -31,28 +31,85 @@ func TestTypeInterface(t *testing.T) {
// Create nested types.
decimalInfo := NewDecimalInfo(3, 2)
enumInfo := NewEnumInfo("hello", "world")
listInfo := NewListInfo(decimalInfo)
nestedListInfo := NewListInfo(listInfo)
listInfo, err := NewListInfo(decimalInfo)
require.NoError(t, err)
nestedListInfo, err := NewListInfo(listInfo)
require.NoError(t, err)

firstEntry, err := NewStructEntry(enumInfo, "hello")
require.NoError(t, err)
secondEntry, err := NewStructEntry(nestedListInfo, "world")
require.NoError(t, err)
structInfo := NewStructInfo(firstEntry, secondEntry)
structInfo, err := NewStructInfo(firstEntry, secondEntry)
require.NoError(t, err)

firstEntry, err = NewStructEntry(structInfo, "hello")
require.NoError(t, err)
secondEntry, err = NewStructEntry(listInfo, "world")
require.NoError(t, err)
nestedStructInfo := NewStructInfo(firstEntry, secondEntry)
nestedStructInfo, err := NewStructInfo(firstEntry, secondEntry)
require.NoError(t, err)

mapInfo := NewMapInfo(nestedStructInfo, nestedListInfo)
mapInfo, err := NewMapInfo(nestedStructInfo, nestedListInfo)
require.NoError(t, err)

typeInfos = append(typeInfos, decimalInfo, enumInfo, listInfo, nestedListInfo, structInfo, nestedStructInfo, mapInfo)

// Use each type as a child and to create the respective logical type.
for _, info := range typeInfos {
NewListInfo(info)
_, err = NewListInfo(info)
require.NoError(t, err)
}
}

func TestErrTypeInfo(t *testing.T) {
t.Parallel()

var incorrectTypes []Type
incorrectTypes = append(incorrectTypes, TYPE_DECIMAL, TYPE_ENUM, TYPE_LIST, TYPE_STRUCT, TYPE_MAP)

for _, incorrect := range incorrectTypes {
_, err := NewTypeInfo(incorrect)
testError(t, err, errAPI.Error(), tryOtherFuncErrMsg)
}

var unsupportedTypes []Type
for k := range unsupportedTypeToStringMap {
unsupportedTypes = append(unsupportedTypes, k)
}

for _, unsupported := range unsupportedTypes {
_, err := NewTypeInfo(unsupported)
testError(t, err, errAPI.Error(), unsupportedTypeErrMsg)
}

validInfo, err := NewTypeInfo(TYPE_FLOAT)
require.NoError(t, err)

// Invalid STRUCT entry.
_, err = NewStructEntry(validInfo, "")
testError(t, err, errAPI.Error(), errEmptyName.Error())

validStructEntry, err := NewStructEntry(validInfo, "hello")
require.NoError(t, err)
nilStructEntry, err := NewStructEntry(nil, "hello")
require.NoError(t, err)

// Invalid interfaces.
_, err = NewListInfo(nil)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)

_, err = NewStructInfo(nil)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)
_, err = NewStructInfo(validStructEntry, nil)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)
_, err = NewStructInfo(nilStructEntry, validStructEntry)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)
_, err = NewStructInfo(validStructEntry, nilStructEntry)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)

_, err = NewMapInfo(nil, validInfo)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)
_, err = NewMapInfo(validInfo, nil)
testError(t, err, errAPI.Error(), interfaceIsNilErrMsg)
}

0 comments on commit fbb2e4d

Please sign in to comment.