2
0

Convert inet and cidr to codec

This commit is contained in:
Jack Christensen
2022-01-15 09:48:21 -06:00
parent f743007fb4
commit 05598d4ca6
9 changed files with 318 additions and 2043 deletions
+67 -7
View File
@@ -262,11 +262,11 @@ func NewConnInfo() *ConnInfo {
ci.RegisterDataType(DataType{Name: "_bool", OID: BoolArrayOID, Codec: &ArrayCodec{ElementCodec: BoolCodec{}, ElementOID: BoolOID}})
ci.RegisterDataType(DataType{Name: "_bpchar", OID: BPCharArrayOID, Codec: &ArrayCodec{ElementCodec: TextCodec{}, ElementOID: BPCharOID}})
ci.RegisterDataType(DataType{Name: "_bytea", OID: ByteaArrayOID, Codec: &ArrayCodec{ElementCodec: ByteaCodec{}, ElementOID: ByteaOID}})
ci.RegisterDataType(DataType{Value: &CIDRArray{}, Name: "_cidr", OID: CIDRArrayOID})
ci.RegisterDataType(DataType{Name: "_cidr", OID: CIDRArrayOID, Codec: &ArrayCodec{ElementCodec: InetCodec{}, ElementOID: CIDROID}})
ci.RegisterDataType(DataType{Name: "_date", OID: DateArrayOID, Codec: &ArrayCodec{ElementCodec: DateCodec{}, ElementOID: DateOID}})
ci.RegisterDataType(DataType{Value: &Float4Array{}, Name: "_float4", OID: Float4ArrayOID})
ci.RegisterDataType(DataType{Value: &Float8Array{}, Name: "_float8", OID: Float8ArrayOID})
ci.RegisterDataType(DataType{Value: &InetArray{}, Name: "_inet", OID: InetArrayOID})
ci.RegisterDataType(DataType{Name: "_inet", OID: InetArrayOID, Codec: &ArrayCodec{ElementCodec: InetCodec{}, ElementOID: InetOID}})
ci.RegisterDataType(DataType{Name: "_int2", OID: Int2ArrayOID, Codec: &ArrayCodec{ElementCodec: Int2Codec{}, ElementOID: Int2OID}})
ci.RegisterDataType(DataType{Name: "_int4", OID: Int4ArrayOID, Codec: &ArrayCodec{ElementCodec: Int4Codec{}, ElementOID: Int4OID}})
ci.RegisterDataType(DataType{Name: "_int8", OID: Int8ArrayOID, Codec: &ArrayCodec{ElementCodec: Int8Codec{}, ElementOID: Int8OID}})
@@ -293,13 +293,13 @@ func NewConnInfo() *ConnInfo {
ci.RegisterDataType(DataType{Name: "bytea", OID: ByteaOID, Codec: ByteaCodec{}})
ci.RegisterDataType(DataType{Value: &QChar{}, Name: "char", OID: QCharOID})
ci.RegisterDataType(DataType{Name: "cid", OID: CIDOID, Codec: Uint32Codec{}})
ci.RegisterDataType(DataType{Value: &CIDR{}, Name: "cidr", OID: CIDROID})
ci.RegisterDataType(DataType{Name: "cidr", OID: CIDROID, Codec: InetCodec{}})
ci.RegisterDataType(DataType{Name: "circle", OID: CircleOID, Codec: CircleCodec{}})
ci.RegisterDataType(DataType{Name: "date", OID: DateOID, Codec: DateCodec{}})
// ci.RegisterDataType(DataType{Value: &Daterange{}, Name: "daterange", OID: DaterangeOID})
ci.RegisterDataType(DataType{Value: &Float4{}, Name: "float4", OID: Float4OID})
ci.RegisterDataType(DataType{Value: &Float8{}, Name: "float8", OID: Float8OID})
ci.RegisterDataType(DataType{Value: &Inet{}, Name: "inet", OID: InetOID})
ci.RegisterDataType(DataType{Name: "inet", OID: InetOID, Codec: InetCodec{}})
ci.RegisterDataType(DataType{Name: "int2", OID: Int2OID, Codec: Int2Codec{}})
ci.RegisterDataType(DataType{Name: "int4", OID: Int4OID, Codec: Int4Codec{}})
// ci.RegisterDataType(DataType{Value: &Int4range{}, Name: "int4range", OID: Int4rangeOID})
@@ -336,15 +336,26 @@ func NewConnInfo() *ConnInfo {
ci.RegisterDataType(DataType{Name: "xid", OID: XIDOID, Codec: Uint32Codec{}})
registerDefaultPgTypeVariants := func(name, arrayName string, value interface{}) {
// T
ci.RegisterDefaultPgType(value, name)
valueType := reflect.TypeOf(value)
// *T
valueType := reflect.TypeOf(value)
ci.RegisterDefaultPgType(reflect.New(valueType).Interface(), name)
// []T
sliceType := reflect.SliceOf(valueType)
ci.RegisterDefaultPgType(reflect.MakeSlice(sliceType, 0, 0).Interface(), arrayName)
// *[]T
ci.RegisterDefaultPgType(reflect.New(sliceType).Interface(), arrayName)
// []*T
sliceOfPointerType := reflect.SliceOf(reflect.TypeOf(reflect.New(valueType).Interface()))
ci.RegisterDefaultPgType(reflect.MakeSlice(sliceOfPointerType, 0, 0).Interface(), arrayName)
// *[]*T
ci.RegisterDefaultPgType(reflect.New(sliceOfPointerType).Interface(), arrayName)
}
// Integer types that directly map to a PostgreSQL type
@@ -368,8 +379,7 @@ func NewConnInfo() *ConnInfo {
registerDefaultPgTypeVariants("bytea", "_bytea", []byte(nil))
registerDefaultPgTypeVariants("inet", "_inet", net.IP{})
ci.RegisterDefaultPgType((*net.IPNet)(nil), "cidr")
ci.RegisterDefaultPgType([]*net.IPNet(nil), "_cidr")
registerDefaultPgTypeVariants("cidr", "_cidr", net.IPNet{})
return ci
}
@@ -816,6 +826,10 @@ func tryWrapBuiltinTypeScanPlan(dst interface{}) (plan WrappedScanPlanNextSetter
switch dst := dst.(type) {
case *time.Time:
return &wrapTimeScanPlan{}, (*timeWrapper)(dst), true
case *net.IPNet:
return &wrapNetIPNetScanPlan{}, (*netIPNetWrapper)(dst), true
case *net.IP:
return &wrapNetIPScanPlan{}, (*netIPWrapper)(dst), true
}
return nil, nil, false
@@ -831,6 +845,26 @@ func (plan *wrapTimeScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, s
return plan.next.Scan(ci, oid, formatCode, src, (*timeWrapper)(dst.(*time.Time)))
}
type wrapNetIPNetScanPlan struct {
next ScanPlan
}
func (plan *wrapNetIPNetScanPlan) SetNext(next ScanPlan) { plan.next = next }
func (plan *wrapNetIPNetScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
return plan.next.Scan(ci, oid, formatCode, src, (*netIPNetWrapper)(dst.(*net.IPNet)))
}
type wrapNetIPScanPlan struct {
next ScanPlan
}
func (plan *wrapNetIPScanPlan) SetNext(next ScanPlan) { plan.next = next }
func (plan *wrapNetIPScanPlan) Scan(ci *ConnInfo, oid uint32, formatCode int16, src []byte, dst interface{}) error {
return plan.next.Scan(ci, oid, formatCode, src, (*netIPWrapper)(dst.(*net.IP)))
}
type pointerEmptyInterfaceScanPlan struct {
codec Codec
}
@@ -901,6 +935,7 @@ func (ci *ConnInfo) PlanScan(oid uint32, formatCode int16, dst interface{}) Scan
if oid == 0 {
if dataType, ok := ci.DataTypeForValue(dst); ok {
dt = dataType
oid = dt.OID // Preserve assumed OID in case we are recursively called below.
}
} else {
if dataType, ok := ci.DataTypeForOID(oid); ok {
@@ -1031,6 +1066,7 @@ func (ci *ConnInfo) PlanEncode(oid uint32, format int16, value interface{}) Enco
if oid == 0 {
if dataType, ok := ci.DataTypeForValue(value); ok {
dt = dataType
oid = dt.OID // Preserve assumed OID in case we are recursively called below.
}
} else {
if dataType, ok := ci.DataTypeForOID(oid); ok {
@@ -1166,6 +1202,10 @@ func tryWrapBuiltinTypeEncodePlan(value interface{}) (plan WrappedEncodePlanNext
return &wrapStringEncodePlan{}, stringWrapper(value), true
case time.Time:
return &wrapTimeEncodePlan{}, timeWrapper(value), true
case net.IPNet:
return &wrapNetIPNetEncodePlan{}, netIPNetWrapper(value), true
case net.IP:
return &wrapNetIPEncodePlan{}, netIPWrapper(value), true
}
return nil, nil, false
@@ -1311,6 +1351,26 @@ func (plan *wrapTimeEncodePlan) Encode(value interface{}, buf []byte) (newBuf []
return plan.next.Encode(timeWrapper(value.(time.Time)), buf)
}
type wrapNetIPNetEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetIPNetEncodePlan) SetNext(next EncodePlan) { plan.next = next }
func (plan *wrapNetIPNetEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
return plan.next.Encode(netIPNetWrapper(value.(net.IPNet)), buf)
}
type wrapNetIPEncodePlan struct {
next EncodePlan
}
func (plan *wrapNetIPEncodePlan) SetNext(next EncodePlan) { plan.next = next }
func (plan *wrapNetIPEncodePlan) Encode(value interface{}, buf []byte) (newBuf []byte, err error) {
return plan.next.Encode(netIPWrapper(value.(net.IP)), buf)
}
// Encode appends the encoded bytes of value to buf. If value is the SQL value NULL then append nothing and return
// (nil, nil). The caller of Encode is responsible for writing the correct NULL value or the length of the data
// written.