diff --git a/conn.go b/conn.go index cab8f3753..75a3842ad 100644 --- a/conn.go +++ b/conn.go @@ -87,6 +87,7 @@ type parameterStatus struct { serverVersion int currentLocation *time.Location inHotStandby, defaultTransactionReadOnly sql.NullBool + isRedshift bool } type format int @@ -1554,6 +1555,8 @@ func (cn *conn) processParameterStatus(r *readBuf) { switch r.string() { default: // ignore + case "padb_version": + cn.parameterStatus.isRedshift = true case "server_version": var major1, major2 int _, err := fmt.Sscanf(r.string(), "%d.%d", &major1, &major2) diff --git a/rows.go b/rows.go index 2029bfed2..60a613471 100644 --- a/rows.go +++ b/rows.go @@ -161,6 +161,11 @@ func (rs *rows) ColumnTypeScanType(index int) reflect.Type { // ColumnTypeDatabaseTypeName return the database system type name. func (rs *rows) ColumnTypeDatabaseTypeName(index int) string { + if rs.cn.parameterStatus.isRedshift { + if n, ok := redshiftTypeName[rs.colTyps[index].OID]; ok { + return n + } + } return rs.colTyps[index].Name() } @@ -243,3 +248,26 @@ func (fd fieldDesc) PrecisionScale() (precision, scale int64, ok bool) { return 0, 0, false } } + +var redshiftTypeName = map[oid.Oid]string{ + 86: "PG_SHADOW", + 87: "PG_GROUP", + 88: "PG_DATABASE", + 90: "PG_TABLESPACE", + 635: "_SPECTRUM_ARRAY", + 636: "_SPECTRUM_MAP", + 637: "_SPECTRUM_STRUCT", + 1188: "INTERVALY2M", + 1189: "_INTERVALY2M", + 1190: "INTERVALD2S", + 1191: "_INTERVALD2S", + 2935: "HLLSKETCH", + 3000: "GEOMETRY", + 3001: "GEOGRAPHY", + 4000: "SUPER", + 4600: "USERITEM", + 4601: "_USERITEM", + 4602: "ROLEITEM", + 4603: "_ROLEITEM", + 6551: "VARBYTE", +} diff --git a/rows_test.go b/rows_test.go index 56d8a6f9a..71ae34823 100644 --- a/rows_test.go +++ b/rows_test.go @@ -41,6 +41,41 @@ func TestDataTypeName(t *testing.T) { } } +func TestDataTypeNameRedshift(t *testing.T) { + tts := []struct { + typ oid.Oid + name string + }{ + {635, "_SPECTRUM_ARRAY"}, + {636, "_SPECTRUM_MAP"}, + {637, "_SPECTRUM_STRUCT"}, + {4000, "SUPER"}, + } + + rs := &rows{ + cn: &conn{ + parameterStatus: parameterStatus{isRedshift: true}, + }, + rowsHeader: rowsHeader{ + colTyps: []fieldDesc{}, + }, + } + + for i, tt := range tts { + rs.colTyps = []fieldDesc{{OID: tt.typ}} + if name := rs.ColumnTypeDatabaseTypeName(0); name != tt.name { + t.Errorf("(%d) got: %s want: %s", i, name, tt.name) + } + } + + // Without Redshift flag + rs.cn.parameterStatus.isRedshift = false + rs.colTyps = []fieldDesc{{OID: 635}} + if name := rs.ColumnTypeDatabaseTypeName(0); name != "" { + t.Errorf("got: %q want: %q", name, "") // 635 is not in standard types map, so it returns empty string + } +} + func TestDataType(t *testing.T) { tts := []struct { typ oid.Oid