1 Star 0 Fork 0

general252/pgx

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
builtin_wrappers.go 21.66 KB
一键复制 编辑 原始数据 按行查看 历史
LIN 提交于 2023-08-10 20:31 +08:00 . add
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952
package pgtype
import (
"errors"
"fmt"
"math"
"math/big"
"net"
"net/netip"
"reflect"
"time"
)
type int8Wrapper int8
func (w int8Wrapper) SkipUnderlyingTypePlan() {}
func (w *int8Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *int8")
}
if v.Int64 < math.MinInt8 {
return fmt.Errorf("%d is less than minimum value for int8", v.Int64)
}
if v.Int64 > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for int8", v.Int64)
}
*w = int8Wrapper(v.Int64)
return nil
}
func (w int8Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type int16Wrapper int16
func (w int16Wrapper) SkipUnderlyingTypePlan() {}
func (w *int16Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *int16")
}
if v.Int64 < math.MinInt16 {
return fmt.Errorf("%d is less than minimum value for int16", v.Int64)
}
if v.Int64 > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for int16", v.Int64)
}
*w = int16Wrapper(v.Int64)
return nil
}
func (w int16Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type int32Wrapper int32
func (w int32Wrapper) SkipUnderlyingTypePlan() {}
func (w *int32Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *int32")
}
if v.Int64 < math.MinInt32 {
return fmt.Errorf("%d is less than minimum value for int32", v.Int64)
}
if v.Int64 > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for int32", v.Int64)
}
*w = int32Wrapper(v.Int64)
return nil
}
func (w int32Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type int64Wrapper int64
func (w int64Wrapper) SkipUnderlyingTypePlan() {}
func (w *int64Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *int64")
}
*w = int64Wrapper(v.Int64)
return nil
}
func (w int64Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type intWrapper int
func (w intWrapper) SkipUnderlyingTypePlan() {}
func (w *intWrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *int")
}
if v.Int64 < math.MinInt {
return fmt.Errorf("%d is less than minimum value for int", v.Int64)
}
if v.Int64 > math.MaxInt {
return fmt.Errorf("%d is greater than maximum value for int", v.Int64)
}
*w = intWrapper(v.Int64)
return nil
}
func (w intWrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type uint8Wrapper uint8
func (w uint8Wrapper) SkipUnderlyingTypePlan() {}
func (w *uint8Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint8")
}
if v.Int64 < 0 {
return fmt.Errorf("%d is less than minimum value for uint8", v.Int64)
}
if v.Int64 > math.MaxUint8 {
return fmt.Errorf("%d is greater than maximum value for uint8", v.Int64)
}
*w = uint8Wrapper(v.Int64)
return nil
}
func (w uint8Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type uint16Wrapper uint16
func (w uint16Wrapper) SkipUnderlyingTypePlan() {}
func (w *uint16Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint16")
}
if v.Int64 < 0 {
return fmt.Errorf("%d is less than minimum value for uint16", v.Int64)
}
if v.Int64 > math.MaxUint16 {
return fmt.Errorf("%d is greater than maximum value for uint16", v.Int64)
}
*w = uint16Wrapper(v.Int64)
return nil
}
func (w uint16Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type uint32Wrapper uint32
func (w uint32Wrapper) SkipUnderlyingTypePlan() {}
func (w *uint32Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint32")
}
if v.Int64 < 0 {
return fmt.Errorf("%d is less than minimum value for uint32", v.Int64)
}
if v.Int64 > math.MaxUint32 {
return fmt.Errorf("%d is greater than maximum value for uint32", v.Int64)
}
*w = uint32Wrapper(v.Int64)
return nil
}
func (w uint32Wrapper) Int64Value() (Int8, error) {
return Int8{Int64: int64(w), Valid: true}, nil
}
type uint64Wrapper uint64
func (w uint64Wrapper) SkipUnderlyingTypePlan() {}
func (w *uint64Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint64")
}
if v.Int64 < 0 {
return fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
}
*w = uint64Wrapper(v.Int64)
return nil
}
func (w uint64Wrapper) Int64Value() (Int8, error) {
if uint64(w) > uint64(math.MaxInt64) {
return Int8{}, fmt.Errorf("%d is greater than maximum value for int64", w)
}
return Int8{Int64: int64(w), Valid: true}, nil
}
func (w *uint64Wrapper) ScanNumeric(v Numeric) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint64")
}
bi, err := v.toBigInt()
if err != nil {
return fmt.Errorf("cannot scan into *uint64: %v", err)
}
if !bi.IsUint64() {
return fmt.Errorf("cannot scan %v into *uint64", bi.String())
}
*w = uint64Wrapper(bi.Uint64())
return nil
}
func (w uint64Wrapper) NumericValue() (Numeric, error) {
return Numeric{Int: new(big.Int).SetUint64(uint64(w)), Valid: true}, nil
}
type uintWrapper uint
func (w uintWrapper) SkipUnderlyingTypePlan() {}
func (w *uintWrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint64")
}
if v.Int64 < 0 {
return fmt.Errorf("%d is less than minimum value for uint64", v.Int64)
}
if uint64(v.Int64) > math.MaxUint {
return fmt.Errorf("%d is greater than maximum value for uint", v.Int64)
}
*w = uintWrapper(v.Int64)
return nil
}
func (w uintWrapper) Int64Value() (Int8, error) {
if uint64(w) > uint64(math.MaxInt64) {
return Int8{}, fmt.Errorf("%d is greater than maximum value for int64", w)
}
return Int8{Int64: int64(w), Valid: true}, nil
}
func (w *uintWrapper) ScanNumeric(v Numeric) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *uint")
}
bi, err := v.toBigInt()
if err != nil {
return fmt.Errorf("cannot scan into *uint: %v", err)
}
if !bi.IsUint64() {
return fmt.Errorf("cannot scan %v into *uint", bi.String())
}
ui := bi.Uint64()
if math.MaxUint < ui {
return fmt.Errorf("cannot scan %v into *uint", ui)
}
*w = uintWrapper(ui)
return nil
}
func (w uintWrapper) NumericValue() (Numeric, error) {
return Numeric{Int: new(big.Int).SetUint64(uint64(w)), Valid: true}, nil
}
type float32Wrapper float32
func (w float32Wrapper) SkipUnderlyingTypePlan() {}
func (w *float32Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *float32")
}
*w = float32Wrapper(v.Int64)
return nil
}
func (w float32Wrapper) Int64Value() (Int8, error) {
if w > math.MaxInt64 {
return Int8{}, fmt.Errorf("%f is greater than maximum value for int64", w)
}
return Int8{Int64: int64(w), Valid: true}, nil
}
func (w *float32Wrapper) ScanFloat64(v Float8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *float32")
}
*w = float32Wrapper(v.Float64)
return nil
}
func (w float32Wrapper) Float64Value() (Float8, error) {
return Float8{Float64: float64(w), Valid: true}, nil
}
type float64Wrapper float64
func (w float64Wrapper) SkipUnderlyingTypePlan() {}
func (w *float64Wrapper) ScanInt64(v Int8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *float64")
}
*w = float64Wrapper(v.Int64)
return nil
}
func (w float64Wrapper) Int64Value() (Int8, error) {
if w > math.MaxInt64 {
return Int8{}, fmt.Errorf("%f is greater than maximum value for int64", w)
}
return Int8{Int64: int64(w), Valid: true}, nil
}
func (w *float64Wrapper) ScanFloat64(v Float8) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *float64")
}
*w = float64Wrapper(v.Float64)
return nil
}
func (w float64Wrapper) Float64Value() (Float8, error) {
return Float8{Float64: float64(w), Valid: true}, nil
}
type stringWrapper string
func (w stringWrapper) SkipUnderlyingTypePlan() {}
func (w *stringWrapper) ScanText(v Text) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *string")
}
*w = stringWrapper(v.String)
return nil
}
func (w stringWrapper) TextValue() (Text, error) {
return Text{String: string(w), Valid: true}, nil
}
type timeWrapper time.Time
func (w *timeWrapper) ScanDate(v Date) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *time.Time")
}
switch v.InfinityModifier {
case Finite:
*w = timeWrapper(v.Time)
return nil
case Infinity:
return fmt.Errorf("cannot scan Infinity into *time.Time")
case NegativeInfinity:
return fmt.Errorf("cannot scan -Infinity into *time.Time")
default:
return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier)
}
}
func (w timeWrapper) DateValue() (Date, error) {
return Date{Time: time.Time(w), Valid: true}, nil
}
func (w *timeWrapper) ScanTimestamp(v Timestamp) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *time.Time")
}
switch v.InfinityModifier {
case Finite:
*w = timeWrapper(v.Time)
return nil
case Infinity:
return fmt.Errorf("cannot scan Infinity into *time.Time")
case NegativeInfinity:
return fmt.Errorf("cannot scan -Infinity into *time.Time")
default:
return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier)
}
}
func (w timeWrapper) TimestampValue() (Timestamp, error) {
return Timestamp{Time: time.Time(w), Valid: true}, nil
}
func (w *timeWrapper) ScanTimestamptz(v Timestamptz) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *time.Time")
}
switch v.InfinityModifier {
case Finite:
*w = timeWrapper(v.Time)
return nil
case Infinity:
return fmt.Errorf("cannot scan Infinity into *time.Time")
case NegativeInfinity:
return fmt.Errorf("cannot scan -Infinity into *time.Time")
default:
return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier)
}
}
func (w timeWrapper) TimestamptzValue() (Timestamptz, error) {
return Timestamptz{Time: time.Time(w), Valid: true}, nil
}
func (w *timeWrapper) ScanTime(v Time) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *time.Time")
}
// 24:00:00 is max allowed time in PostgreSQL, but time.Time will normalize that to 00:00:00 the next day.
var maxRepresentableByTime int64 = 24*60*60*1000000 - 1
if v.Microseconds > maxRepresentableByTime {
return fmt.Errorf("%d microseconds cannot be represented as time.Time", v.Microseconds)
}
usec := v.Microseconds
hours := usec / microsecondsPerHour
usec -= hours * microsecondsPerHour
minutes := usec / microsecondsPerMinute
usec -= minutes * microsecondsPerMinute
seconds := usec / microsecondsPerSecond
usec -= seconds * microsecondsPerSecond
ns := usec * 1000
*w = timeWrapper(time.Date(2000, 1, 1, int(hours), int(minutes), int(seconds), int(ns), time.UTC))
return nil
}
func (w timeWrapper) TimeValue() (Time, error) {
t := time.Time(w)
usec := int64(t.Hour())*microsecondsPerHour +
int64(t.Minute())*microsecondsPerMinute +
int64(t.Second())*microsecondsPerSecond +
int64(t.Nanosecond())/1000
return Time{Microseconds: usec, Valid: true}, nil
}
type durationWrapper time.Duration
func (w durationWrapper) SkipUnderlyingTypePlan() {}
func (w *durationWrapper) ScanInterval(v Interval) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *time.Interval")
}
us := int64(v.Months)*microsecondsPerMonth + int64(v.Days)*microsecondsPerDay + v.Microseconds
*w = durationWrapper(time.Duration(us) * time.Microsecond)
return nil
}
func (w durationWrapper) IntervalValue() (Interval, error) {
return Interval{Microseconds: int64(w) / 1000, Valid: true}, nil
}
type netIPNetWrapper net.IPNet
func (w *netIPNetWrapper) ScanNetipPrefix(v netip.Prefix) error {
if !v.IsValid() {
return fmt.Errorf("cannot scan NULL into *net.IPNet")
}
*w = netIPNetWrapper{
IP: v.Addr().AsSlice(),
Mask: net.CIDRMask(v.Bits(), v.Addr().BitLen()),
}
return nil
}
func (w netIPNetWrapper) NetipPrefixValue() (netip.Prefix, error) {
ip, ok := netip.AddrFromSlice(w.IP)
if !ok {
return netip.Prefix{}, errors.New("invalid net.IPNet")
}
ones, _ := w.Mask.Size()
return netip.PrefixFrom(ip, ones), nil
}
type netIPWrapper net.IP
func (w netIPWrapper) SkipUnderlyingTypePlan() {}
func (w *netIPWrapper) ScanNetipPrefix(v netip.Prefix) error {
if !v.IsValid() {
*w = nil
return nil
}
if v.Addr().BitLen() != v.Bits() {
return fmt.Errorf("cannot scan %v to *net.IP", v)
}
*w = netIPWrapper(v.Addr().AsSlice())
return nil
}
func (w netIPWrapper) NetipPrefixValue() (netip.Prefix, error) {
if w == nil {
return netip.Prefix{}, nil
}
addr, ok := netip.AddrFromSlice([]byte(w))
if !ok {
return netip.Prefix{}, errors.New("invalid net.IP")
}
return netip.PrefixFrom(addr, addr.BitLen()), nil
}
type netipPrefixWrapper netip.Prefix
func (w *netipPrefixWrapper) ScanNetipPrefix(v netip.Prefix) error {
*w = netipPrefixWrapper(v)
return nil
}
func (w netipPrefixWrapper) NetipPrefixValue() (netip.Prefix, error) {
return netip.Prefix(w), nil
}
type netipAddrWrapper netip.Addr
func (w *netipAddrWrapper) ScanNetipPrefix(v netip.Prefix) error {
if !v.IsValid() {
*w = netipAddrWrapper(netip.Addr{})
return nil
}
if v.Addr().BitLen() != v.Bits() {
return fmt.Errorf("cannot scan %v to netip.Addr", v)
}
*w = netipAddrWrapper(v.Addr())
return nil
}
func (w netipAddrWrapper) NetipPrefixValue() (netip.Prefix, error) {
addr := (netip.Addr)(w)
if !addr.IsValid() {
return netip.Prefix{}, nil
}
return netip.PrefixFrom(addr, addr.BitLen()), nil
}
type mapStringToPointerStringWrapper map[string]*string
func (w *mapStringToPointerStringWrapper) ScanHstore(v Hstore) error {
*w = mapStringToPointerStringWrapper(v)
return nil
}
func (w mapStringToPointerStringWrapper) HstoreValue() (Hstore, error) {
return Hstore(w), nil
}
type mapStringToStringWrapper map[string]string
func (w *mapStringToStringWrapper) ScanHstore(v Hstore) error {
*w = make(mapStringToStringWrapper, len(v))
for k, v := range v {
if v == nil {
return fmt.Errorf("cannot scan NULL to string")
}
(*w)[k] = *v
}
return nil
}
func (w mapStringToStringWrapper) HstoreValue() (Hstore, error) {
if w == nil {
return nil, nil
}
hstore := make(Hstore, len(w))
for k, v := range w {
s := v
hstore[k] = &s
}
return hstore, nil
}
type fmtStringerWrapper struct {
s fmt.Stringer
}
func (w fmtStringerWrapper) TextValue() (Text, error) {
return Text{String: w.s.String(), Valid: true}, nil
}
type byte16Wrapper [16]byte
func (w *byte16Wrapper) ScanUUID(v UUID) error {
if !v.Valid {
return fmt.Errorf("cannot scan NULL into *[16]byte")
}
*w = byte16Wrapper(v.Bytes)
return nil
}
func (w byte16Wrapper) UUIDValue() (UUID, error) {
return UUID{Bytes: [16]byte(w), Valid: true}, nil
}
type byteSliceWrapper []byte
func (w byteSliceWrapper) SkipUnderlyingTypePlan() {}
func (w *byteSliceWrapper) ScanText(v Text) error {
if !v.Valid {
*w = nil
return nil
}
*w = byteSliceWrapper(v.String)
return nil
}
func (w byteSliceWrapper) TextValue() (Text, error) {
if w == nil {
return Text{}, nil
}
return Text{String: string(w), Valid: true}, nil
}
func (w *byteSliceWrapper) ScanUUID(v UUID) error {
if !v.Valid {
*w = nil
return nil
}
*w = make(byteSliceWrapper, 16)
copy(*w, v.Bytes[:])
return nil
}
func (w byteSliceWrapper) UUIDValue() (UUID, error) {
if w == nil {
return UUID{}, nil
}
uuid := UUID{Valid: true}
copy(uuid.Bytes[:], w)
return uuid, nil
}
// structWrapper implements CompositeIndexGetter for a struct.
type structWrapper struct {
s any
exportedFields []reflect.Value
}
func (w structWrapper) IsNull() bool {
return w.s == nil
}
func (w structWrapper) Index(i int) any {
if i >= len(w.exportedFields) {
return fmt.Errorf("%#v only has %d public fields - %d is out of bounds", w.s, len(w.exportedFields), i)
}
return w.exportedFields[i].Interface()
}
// ptrStructWrapper implements CompositeIndexScanner for a pointer to a struct.
type ptrStructWrapper struct {
s any
exportedFields []reflect.Value
}
func (w *ptrStructWrapper) ScanNull() error {
return fmt.Errorf("cannot scan NULL into %#v", w.s)
}
func (w *ptrStructWrapper) ScanIndex(i int) any {
if i >= len(w.exportedFields) {
return fmt.Errorf("%#v only has %d public fields - %d is out of bounds", w.s, len(w.exportedFields), i)
}
return w.exportedFields[i].Addr().Interface()
}
type anySliceArrayReflect struct {
slice reflect.Value
}
func (a anySliceArrayReflect) Dimensions() []ArrayDimension {
if a.slice.IsNil() {
return nil
}
return []ArrayDimension{{Length: int32(a.slice.Len()), LowerBound: 1}}
}
func (a anySliceArrayReflect) Index(i int) any {
return a.slice.Index(i).Interface()
}
func (a anySliceArrayReflect) IndexType() any {
return reflect.New(a.slice.Type().Elem()).Elem().Interface()
}
func (a *anySliceArrayReflect) SetDimensions(dimensions []ArrayDimension) error {
sliceType := a.slice.Type()
if dimensions == nil {
a.slice.Set(reflect.Zero(sliceType))
return nil
}
elementCount := cardinality(dimensions)
slice := reflect.MakeSlice(sliceType, elementCount, elementCount)
a.slice.Set(slice)
return nil
}
func (a *anySliceArrayReflect) ScanIndex(i int) any {
return a.slice.Index(i).Addr().Interface()
}
func (a *anySliceArrayReflect) ScanIndexType() any {
return reflect.New(a.slice.Type().Elem()).Interface()
}
type anyMultiDimSliceArray struct {
slice reflect.Value
dims []ArrayDimension
}
func (a *anyMultiDimSliceArray) Dimensions() []ArrayDimension {
if a.slice.IsNil() {
return nil
}
s := a.slice
for {
a.dims = append(a.dims, ArrayDimension{Length: int32(s.Len()), LowerBound: 1})
if s.Len() > 0 {
s = s.Index(0)
} else {
break
}
if s.Type().Kind() == reflect.Slice {
} else {
break
}
}
return a.dims
}
func (a *anyMultiDimSliceArray) Index(i int) any {
if len(a.dims) == 1 {
return a.slice.Index(i).Interface()
}
indexes := make([]int, len(a.dims))
for j := len(a.dims) - 1; j >= 0; j-- {
dimLen := int(a.dims[j].Length)
indexes[j] = i % dimLen
i = i / dimLen
}
v := a.slice
for _, si := range indexes {
v = v.Index(si)
}
return v.Interface()
}
func (a *anyMultiDimSliceArray) IndexType() any {
lowestSliceType := a.slice.Type()
for ; lowestSliceType.Elem().Kind() == reflect.Slice; lowestSliceType = lowestSliceType.Elem() {
}
return reflect.New(lowestSliceType.Elem()).Elem().Interface()
}
func (a *anyMultiDimSliceArray) SetDimensions(dimensions []ArrayDimension) error {
sliceType := a.slice.Type()
if dimensions == nil {
a.slice.Set(reflect.Zero(sliceType))
return nil
}
switch len(dimensions) {
case 0:
// Empty, but non-nil array
slice := reflect.MakeSlice(sliceType, 0, 0)
a.slice.Set(slice)
return nil
case 1:
elementCount := cardinality(dimensions)
slice := reflect.MakeSlice(sliceType, elementCount, elementCount)
a.slice.Set(slice)
return nil
default:
sliceDimensionCount := 1
lowestSliceType := sliceType
for ; lowestSliceType.Elem().Kind() == reflect.Slice; lowestSliceType = lowestSliceType.Elem() {
sliceDimensionCount++
}
if sliceDimensionCount != len(dimensions) {
return fmt.Errorf("PostgreSQL array has %d dimensions but slice has %d dimensions", len(dimensions), sliceDimensionCount)
}
elementCount := cardinality(dimensions)
flatSlice := reflect.MakeSlice(lowestSliceType, elementCount, elementCount)
multiDimSlice := a.makeMultidimensionalSlice(sliceType, dimensions, flatSlice, 0)
a.slice.Set(multiDimSlice)
// Now that a.slice is a multi-dimensional slice with the underlying data pointed at flatSlice change a.slice to
// flatSlice so ScanIndex only has to handle simple one dimensional slices.
a.slice = flatSlice
return nil
}
}
func (a *anyMultiDimSliceArray) makeMultidimensionalSlice(sliceType reflect.Type, dimensions []ArrayDimension, flatSlice reflect.Value, flatSliceIdx int) reflect.Value {
if len(dimensions) == 1 {
endIdx := flatSliceIdx + int(dimensions[0].Length)
return flatSlice.Slice3(flatSliceIdx, endIdx, endIdx)
}
sliceLen := int(dimensions[0].Length)
slice := reflect.MakeSlice(sliceType, sliceLen, sliceLen)
for i := 0; i < sliceLen; i++ {
subSlice := a.makeMultidimensionalSlice(sliceType.Elem(), dimensions[1:], flatSlice, flatSliceIdx+(i*int(dimensions[1].Length)))
slice.Index(i).Set(subSlice)
}
return slice
}
func (a *anyMultiDimSliceArray) ScanIndex(i int) any {
return a.slice.Index(i).Addr().Interface()
}
func (a *anyMultiDimSliceArray) ScanIndexType() any {
lowestSliceType := a.slice.Type()
for ; lowestSliceType.Elem().Kind() == reflect.Slice; lowestSliceType = lowestSliceType.Elem() {
}
return reflect.New(lowestSliceType.Elem()).Interface()
}
type anyArrayArrayReflect struct {
array reflect.Value
}
func (a anyArrayArrayReflect) Dimensions() []ArrayDimension {
return []ArrayDimension{{Length: int32(a.array.Len()), LowerBound: 1}}
}
func (a anyArrayArrayReflect) Index(i int) any {
return a.array.Index(i).Interface()
}
func (a anyArrayArrayReflect) IndexType() any {
return reflect.New(a.array.Type().Elem()).Elem().Interface()
}
func (a *anyArrayArrayReflect) SetDimensions(dimensions []ArrayDimension) error {
if dimensions == nil {
return fmt.Errorf("anyArrayArrayReflect: cannot scan NULL into %v", a.array.Type().String())
}
if len(dimensions) != 1 {
return fmt.Errorf("anyArrayArrayReflect: cannot scan multi-dimensional array into %v", a.array.Type().String())
}
if int(dimensions[0].Length) != a.array.Len() {
return fmt.Errorf("anyArrayArrayReflect: cannot scan array with length %v into %v", dimensions[0].Length, a.array.Type().String())
}
return nil
}
func (a *anyArrayArrayReflect) ScanIndex(i int) any {
return a.array.Index(i).Addr().Interface()
}
func (a *anyArrayArrayReflect) ScanIndexType() any {
return reflect.New(a.array.Type().Elem()).Interface()
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/general252/pgx.git
git@gitee.com:general252/pgx.git
general252
pgx
pgx
v1.1.0

搜索帮助