diff --git a/postgres_pgtype/builtin_wrappers.go b/postgres_pgtype/builtin_wrappers.go new file mode 100644 index 00000000..06ff88ae --- /dev/null +++ b/postgres_pgtype/builtin_wrappers.go @@ -0,0 +1,955 @@ +package postgres_pgtype + +// +//import ( +// "errors" +// "fmt" +// "github.com/jackc/pgx/v5/pgtype" +// "math" +// "math/big" +// "net" +// "net/netip" +// "reflect" +// "time" +//) +// +//type int8Wrapper int8 +// +//func (w int8Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *int8Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type int16Wrapper int16 +// +//func (w int16Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *int16Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type int32Wrapper int32 +// +//func (w int32Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *int32Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type int64Wrapper int64 +// +//func (w int64Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *int64Wrapper) ScanInt64(v pgtype.Int8) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *int64") +// } +// +// *w = int64Wrapper(v.Int64) +// +// return nil +//} +// +//func (w int64Wrapper) Int64Value() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type intWrapper int +// +//func (w intWrapper) SkipUnderlyingTypePlan() {} +// +//func (w *intWrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type uint8Wrapper uint8 +// +//func (w uint8Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *uint8Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type uint16Wrapper uint16 +// +//func (w uint16Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *uint16Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type uint32Wrapper uint32 +// +//func (w uint32Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *uint32Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//type uint64Wrapper uint64 +// +//func (w uint64Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *uint64Wrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// if uint64(w) > uint64(math.MaxInt64) { +// return pgtype.Int8{}, fmt.Errorf("%d is greater than maximum value for int64", w) +// } +// +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//func (w *uint64Wrapper) ScanNumeric(v pgtype.Numeric) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *uint64") +// } +// +// bi, err := toBigInt(&v) +// if err != nil { +// return fmt.Errorf("cannot scan into *uint64: %w", err) +// } +// +// if !bi.IsUint64() { +// return fmt.Errorf("cannot scan %v into *uint64", bi.String()) +// } +// +// *w = uint64Wrapper(bi.Uint64()) +// +// return nil +//} +// +//func (w uint64Wrapper) NumericValue() (pgtype.Numeric, error) { +// return pgtype.Numeric{Int: new(big.Int).SetUint64(uint64(w)), Valid: true}, nil +//} +// +//type uintWrapper uint +// +//func (w uintWrapper) SkipUnderlyingTypePlan() {} +// +//func (w *uintWrapper) ScanInt64(v pgtype.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() (pgtype.Int8, error) { +// if uint64(w) > uint64(math.MaxInt64) { +// return pgtype.Int8{}, fmt.Errorf("%d is greater than maximum value for int64", w) +// } +// +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//func (w *uintWrapper) ScanNumeric(v pgtype.Numeric) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *uint") +// } +// +// bi, err := toBigInt(&v) +// if err != nil { +// return fmt.Errorf("cannot scan into *uint: %w", 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() (pgtype.Numeric, error) { +// return pgtype.Numeric{Int: new(big.Int).SetUint64(uint64(w)), Valid: true}, nil +//} +// +//type float32Wrapper float32 +// +//func (w float32Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *float32Wrapper) ScanInt64(v pgtype.Int8) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *float32") +// } +// +// *w = float32Wrapper(v.Int64) +// +// return nil +//} +// +//func (w float32Wrapper) Int64Value() (pgtype.Int8, error) { +// if w > math.MaxInt64 { +// return pgtype.Int8{}, fmt.Errorf("%f is greater than maximum value for int64", w) +// } +// +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//func (w *float32Wrapper) ScanFloat64(v pgtype.Float8) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *float32") +// } +// +// *w = float32Wrapper(v.Float64) +// +// return nil +//} +// +//func (w float32Wrapper) Float64Value() (pgtype.Float8, error) { +// return pgtype.Float8{Float64: float64(w), Valid: true}, nil +//} +// +//type float64Wrapper float64 +// +//func (w float64Wrapper) SkipUnderlyingTypePlan() {} +// +//func (w *float64Wrapper) ScanInt64(v pgtype.Int8) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *float64") +// } +// +// *w = float64Wrapper(v.Int64) +// +// return nil +//} +// +//func (w float64Wrapper) Int64Value() (pgtype.Int8, error) { +// if w > math.MaxInt64 { +// return pgtype.Int8{}, fmt.Errorf("%f is greater than maximum value for int64", w) +// } +// +// return pgtype.Int8{Int64: int64(w), Valid: true}, nil +//} +// +//func (w *float64Wrapper) ScanFloat64(v pgtype.Float8) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *float64") +// } +// +// *w = float64Wrapper(v.Float64) +// +// return nil +//} +// +//func (w float64Wrapper) Float64Value() (pgtype.Float8, error) { +// return pgtype.Float8{Float64: float64(w), Valid: true}, nil +//} +// +//type stringWrapper string +// +//func (w stringWrapper) SkipUnderlyingTypePlan() {} +// +//func (w *stringWrapper) ScanText(v pgtype.Text) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *string") +// } +// +// *w = stringWrapper(v.String) +// return nil +//} +// +//func (w stringWrapper) TextValue() (pgtype.Text, error) { +// return pgtype.Text{String: string(w), Valid: true}, nil +//} +// +//type timeWrapper time.Time +// +//func (w *timeWrapper) ScanDate(v pgtype.Date) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *time.Time") +// } +// +// switch v.InfinityModifier { +// case pgtype.Finite: +// *w = timeWrapper(v.Time) +// return nil +// case pgtype.Infinity: +// return fmt.Errorf("cannot scan Infinity into *time.Time") +// case pgtype.NegativeInfinity: +// return fmt.Errorf("cannot scan -Infinity into *time.Time") +// default: +// return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier) +// } +//} +// +//func (w timeWrapper) DateValue() (pgtype.Date, error) { +// return pgtype.Date{Time: time.Time(w), Valid: true}, nil +//} +// +//func (w *timeWrapper) ScanTimestamp(v pgtype.Timestamp) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *time.Time") +// } +// +// switch v.InfinityModifier { +// case pgtype.Finite: +// *w = timeWrapper(v.Time) +// return nil +// case pgtype.Infinity: +// return fmt.Errorf("cannot scan Infinity into *time.Time") +// case pgtype.NegativeInfinity: +// return fmt.Errorf("cannot scan -Infinity into *time.Time") +// default: +// return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier) +// } +//} +// +//func (w timeWrapper) TimestampValue() (pgtype.Timestamp, error) { +// return pgtype.Timestamp{Time: time.Time(w), Valid: true}, nil +//} +// +//func (w *timeWrapper) ScanTimestamptz(v pgtype.Timestamptz) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *time.Time") +// } +// +// switch v.InfinityModifier { +// case pgtype.Finite: +// *w = timeWrapper(v.Time) +// return nil +// case pgtype.Infinity: +// return fmt.Errorf("cannot scan Infinity into *time.Time") +// case pgtype.NegativeInfinity: +// return fmt.Errorf("cannot scan -Infinity into *time.Time") +// default: +// return fmt.Errorf("invalid InfinityModifier: %v", v.InfinityModifier) +// } +//} +// +//func (w timeWrapper) TimestamptzValue() (pgtype.Timestamptz, error) { +// return pgtype.Timestamptz{Time: time.Time(w), Valid: true}, nil +//} +// +//func (w *timeWrapper) ScanTime(v pgtype.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(1, 1, 1, int(hours), int(minutes), int(seconds), int(ns), time.UTC)) //sanek +// //*w = timeWrapper(time.Date(2000, 1, 1, int(hours), int(minutes), int(seconds), int(ns), time.UTC)) +// return nil +//} +// +//func (w timeWrapper) TimeValue() (pgtype.Time, error) { +// t := time.Time(w) +// usec := int64(t.Hour())*microsecondsPerHour + +// int64(t.Minute())*microsecondsPerMinute + +// int64(t.Second())*microsecondsPerSecond + +// int64(t.Nanosecond())/1000 +// return pgtype.Time{Microseconds: usec, Valid: true}, nil +//} +// +//type durationWrapper time.Duration +// +//func (w durationWrapper) SkipUnderlyingTypePlan() {} +// +//func (w *durationWrapper) ScanInterval(v pgtype.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() (pgtype.Interval, error) { +// return pgtype.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 pgtype.Hstore) error { +// *w = mapStringToPointerStringWrapper(v) +// return nil +//} +// +//func (w mapStringToPointerStringWrapper) HstoreValue() (pgtype.Hstore, error) { +// return pgtype.Hstore(w), nil +//} +// +//type mapStringToStringWrapper map[string]string +// +//func (w *mapStringToStringWrapper) ScanHstore(v pgtype.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() (pgtype.Hstore, error) { +// if w == nil { +// return nil, nil +// } +// +// hstore := make(pgtype.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() (pgtype.Text, error) { +// return pgtype.Text{String: w.s.String(), Valid: true}, nil +//} +// +//type byte16Wrapper [16]byte +// +//func (w *byte16Wrapper) ScanUUID(v pgtype.UUID) error { +// if !v.Valid { +// return fmt.Errorf("cannot scan NULL into *[16]byte") +// } +// *w = byte16Wrapper(v.Bytes) +// return nil +//} +// +//func (w byte16Wrapper) UUIDValue() (pgtype.UUID, error) { +// return pgtype.UUID{Bytes: [16]byte(w), Valid: true}, nil +//} +// +//type byteSliceWrapper []byte +// +//func (w byteSliceWrapper) SkipUnderlyingTypePlan() {} +// +//func (w *byteSliceWrapper) ScanText(v pgtype.Text) error { +// if !v.Valid { +// *w = nil +// return nil +// } +// +// *w = byteSliceWrapper(v.String) +// return nil +//} +// +//func (w byteSliceWrapper) TextValue() (pgtype.Text, error) { +// if w == nil { +// return pgtype.Text{}, nil +// } +// +// return pgtype.Text{String: string(w), Valid: true}, nil +//} +// +//func (w *byteSliceWrapper) ScanUUID(v pgtype.UUID) error { +// if !v.Valid { +// *w = nil +// return nil +// } +// *w = make(byteSliceWrapper, 16) +// copy(*w, v.Bytes[:]) +// return nil +//} +// +//func (w byteSliceWrapper) UUIDValue() (pgtype.UUID, error) { +// if w == nil { +// return pgtype.UUID{}, nil +// } +// +// uuid := pgtype.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() []pgtype.ArrayDimension { +// if a.slice.IsNil() { +// return nil +// } +// +// return []pgtype.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 []pgtype.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 []pgtype.ArrayDimension +//} +// +//func (a *anyMultiDimSliceArray) Dimensions() []pgtype.ArrayDimension { +// if a.slice.IsNil() { +// return nil +// } +// +// s := a.slice +// for { +// a.dims = append(a.dims, pgtype.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 []pgtype.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 []pgtype.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() []pgtype.ArrayDimension { +// return []pgtype.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 []pgtype.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() +//} diff --git a/postgres_pgtype/numeric.go b/postgres_pgtype/numeric.go new file mode 100644 index 00000000..f879b619 --- /dev/null +++ b/postgres_pgtype/numeric.go @@ -0,0 +1,31 @@ +package postgres_pgtype + +// +//import ( +// "math/big" +//) +// +//// PostgreSQL internal numeric storage uses 16-bit "digits" with base of 10,000 +//const nbase = 10000 +// +//const ( +// pgNumericNaN = 0x00000000c0000000 +// pgNumericNaNSign = 0xc000 +// +// pgNumericPosInf = 0x00000000d0000000 +// pgNumericPosInfSign = 0xd000 +// +// pgNumericNegInf = 0x00000000f0000000 +// pgNumericNegInfSign = 0xf000 +//) +// +//var big0 *big.Int = big.NewInt(0) +//var big1 *big.Int = big.NewInt(1) +//var big10 *big.Int = big.NewInt(10) +//var big100 *big.Int = big.NewInt(100) +//var big1000 *big.Int = big.NewInt(1000) +// +//var bigNBase *big.Int = big.NewInt(nbase) +//var bigNBaseX2 *big.Int = big.NewInt(nbase * nbase) +//var bigNBaseX3 *big.Int = big.NewInt(nbase * nbase * nbase) +//var bigNBaseX4 *big.Int = big.NewInt(nbase * nbase * nbase * nbase) diff --git a/postgres_pgtype/sanek.go b/postgres_pgtype/sanek.go index b974fdc7..f1d3692c 100644 --- a/postgres_pgtype/sanek.go +++ b/postgres_pgtype/sanek.go @@ -1,8 +1,48 @@ package postgres_pgtype -import "reflect" +import ( + "reflect" +) // getInterfaceName - возвращает имя типа интерфейса func getInterfaceName(v interface{}) string { return reflect.TypeOf(v).String() } + +//func toBigInt(n *pgtype.Numeric) (*big.Int, error) { +// if n.Exp == 0 { +// return n.Int, nil +// } +// +// num := &big.Int{} +// num.Set(n.Int) +// if n.Exp > 0 { +// mul := &big.Int{} +// mul.Exp(big10, big.NewInt(int64(n.Exp)), nil) +// num.Mul(num, mul) +// return num, nil +// } +// +// div := &big.Int{} +// div.Exp(big10, big.NewInt(int64(-n.Exp)), nil) +// remainder := &big.Int{} +// num.DivMod(num, div, remainder) +// if remainder.Cmp(big0) != 0 { +// return nil, fmt.Errorf("cannot convert %v to integer", n) +// } +// return num, nil +//} +// +//// cardinality returns the number of elements in an array of dimensions size. +//func cardinality(dimensions []pgtype.ArrayDimension) int { +// if len(dimensions) == 0 { +// return 0 +// } +// +// elementCount := int(dimensions[0].Length) +// for _, d := range dimensions[1:] { +// elementCount *= int(d.Length) +// } +// +// return elementCount +//} diff --git a/postgres_pgtype/time.go b/postgres_pgtype/time.go index 2e69a947..1fa61755 100644 --- a/postgres_pgtype/time.go +++ b/postgres_pgtype/time.go @@ -11,10 +11,10 @@ import ( "strconv" ) -//type TimeScanner interface { -// ScanTime(v Time) error -//} -// +type TimeScanner interface { + ScanTime(v Time) error +} + //type TimeValuer interface { // TimeValue() (Time, error) //} @@ -167,8 +167,7 @@ func (scanPlanBinaryTimeToTimeScanner) Scan(src []byte, dst any) error { scanner := (dst).(pgtype.TimeScanner) if src == nil { - return scanner.ScanTime(pgtype.Time{Valid: true}) - //return scanner.ScanTime(pgtype.Time{}) + return scanner.ScanTime(pgtype.Time{Valid: true, Microseconds: -63082281600000000}) //sanek минус 2000 лет } if len(src) != 8 { @@ -180,6 +179,24 @@ func (scanPlanBinaryTimeToTimeScanner) Scan(src []byte, dst any) error { return scanner.ScanTime(pgtype.Time{Microseconds: usec, Valid: true}) } +//func (scanPlanBinaryTimeToTimeScanner) Scan(src []byte, dst any) error { +// scanner := (dst).(TimeScanner) //sanek +// //scanner := (dst).(pgtype.TimeScanner) +// +// if src == nil { +// return scanner.ScanTime(Time{Valid: true}) +// //return scanner.ScanTime(pgtype.Time{}) +// } +// +// if len(src) != 8 { +// return fmt.Errorf("invalid length for time: %v", len(src)) +// } +// +// usec := int64(binary.BigEndian.Uint64(src)) +// +// return scanner.ScanTime(Time{Microseconds: usec, Valid: true}) +//} + type scanPlanBinaryTimeToTextScanner struct{} func (scanPlanBinaryTimeToTextScanner) Scan(src []byte, dst any) error {