diff --git a/rows.go b/rows.go index b507b1b..c7802f0 100644 --- a/rows.go +++ b/rows.go @@ -4,8 +4,10 @@ import ( "database/sql/driver" "errors" "fmt" - gms "github.com/dolthub/go-mysql-server/sql" "io" + + gms "github.com/dolthub/go-mysql-server/sql" + "github.com/dolthub/go-mysql-server/sql/types" ) var _ driver.Rows = (*doltRows)(nil) @@ -58,6 +60,24 @@ func (rows *doltRows) Next(dest []driver.Value) error { if err != nil { return fmt.Errorf("error processing column %d: %w", i, err) } + } else if geomValue, ok := nextRow[i].(types.GeometryValue); ok { + dest[i] = geomValue.Serialize() + } else if enumType, ok := rows.sch[i].Type.(gms.EnumType); ok { + if v, _, err := enumType.Convert(nextRow[i]); err != nil { + return fmt.Errorf("could not convert to expected enum type for column %d: %w", i, err) + } else if enumStr, ok := enumType.At(int(v.(uint16))); !ok { + return fmt.Errorf("not a valid enum index for column %d: %v", i, v) + } else { + dest[i] = enumStr + } + } else if setType, ok := rows.sch[i].Type.(gms.SetType); ok { + if v, _, err := setType.Convert(nextRow[i]); err != nil { + return fmt.Errorf("could not convert to expected set type for column %d: %w", i, err) + } else if setStr, err := setType.BitsToString(v.(uint64)); err != nil { + return fmt.Errorf("could not convert value to set string for column %d: %w", i, err) + } else { + dest[i] = setStr + } } else { dest[i] = nextRow[i] } diff --git a/smoke_test.go b/smoke_test.go index 1efffcb..86b4a39 100644 --- a/smoke_test.go +++ b/smoke_test.go @@ -136,6 +136,43 @@ func TestQueryContextInitialization(t *testing.T) { require.NoError(t, conn.Close()) } +// TestTypes asserts that various MySQL types are returned as the expected Go type by the driver. +func TestTypes(t *testing.T) { + conn, cleanupFunc := initializeTestDatabaseConnection(t, false) + defer cleanupFunc() + + ctx := context.Background() + _, err := conn.ExecContext(ctx, ` +create table testtable ( + enum_col ENUM('a', 'b', 'c'), + set_col SET('a', 'b', 'c'), + json_col JSON, + blob_col BLOB, + text_col TEXT, + geom_col POINT, + date_col DATETIME +); + +insert into testtable values ('b', 'a,c', '{"key": 42}', 'data', 'text', Point(5, -5), NOW()); +`) + require.NoError(t, err) + + row := conn.QueryRowContext(ctx, "select * from testtable") + vals := make([]any, 7) + ptrs := make([]any, 7) + for i := range vals { + ptrs[i] = &vals[i] + } + require.NoError(t, row.Scan(ptrs...)) + require.Equal(t, "b", vals[0]) + require.Equal(t, "a,c", vals[1]) + require.Equal(t, `{"key": 42}`, vals[2]) + require.Equal(t, []byte(`data`), vals[3]) + require.Equal(t, "text", vals[4]) + require.IsType(t, []byte(nil), vals[5]) + require.IsType(t, time.Time{}, vals[6]) +} + // initializeTestDatabaseConnection create a test database called testdb and initialize a database/sql connection // using the Dolt driver. The connection, |conn|, is returned, and |cleanupFunc| is a function that the test function // should defer in order to properly dispose of test resources.