[chore] Update a bunch of database dependencies (#1772)

* [chore] Update a bunch of database dependencies

* fix lil thing
This commit is contained in:
tobi 2023-05-12 14:33:40 +02:00 committed by GitHub
parent 66df974143
commit ec325fee14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
402 changed files with 35068 additions and 35401 deletions

42
go.mod
View file

@ -32,7 +32,7 @@ require (
github.com/gorilla/websocket v1.5.0
github.com/h2non/filetype v1.1.3
github.com/jackc/pgconn v1.14.0
github.com/jackc/pgx/v4 v4.18.1
github.com/jackc/pgx/v5 v5.3.1
github.com/microcosm-cc/bluemonday v1.0.23
github.com/miekg/dns v1.1.54
github.com/minio/minio-go/v7 v7.0.52
@ -46,18 +46,17 @@ require (
github.com/superseriousbusiness/oauth2/v4 v4.3.2-SSB.0.20230227143000-f4900831d6c8
github.com/tdewolff/minify/v2 v2.12.5
github.com/ulule/limiter/v3 v3.11.1
github.com/uptrace/bun v1.1.12
github.com/uptrace/bun/dialect/pgdialect v1.1.12
github.com/uptrace/bun/dialect/sqlitedialect v1.1.12
github.com/uptrace/bun/extra/bunotel v1.1.12
github.com/uptrace/bun v1.1.13
github.com/uptrace/bun/dialect/pgdialect v1.1.13
github.com/uptrace/bun/dialect/sqlitedialect v1.1.13
github.com/uptrace/bun/extra/bunotel v1.1.13
github.com/wagslane/go-password-validator v0.3.0
github.com/yuin/goldmark v1.5.4
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.40.0
go.opentelemetry.io/otel v1.14.0
go.opentelemetry.io/otel/exporters/jaeger v1.14.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0
go.opentelemetry.io/otel/sdk v1.14.0
go.opentelemetry.io/otel/trace v1.14.0
go.opentelemetry.io/otel v1.15.1
go.opentelemetry.io/otel/exporters/jaeger v1.15.1
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1
go.opentelemetry.io/otel/sdk v1.15.1
go.opentelemetry.io/otel/trace v1.15.1
go.uber.org/automaxprocs v1.5.2
golang.org/x/crypto v0.8.0
golang.org/x/exp v0.0.0-20220613132600-b0d781184e0d
@ -84,7 +83,7 @@ require (
codeberg.org/gruf/go-pools v1.1.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect
github.com/bytedance/sonic v1.8.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/cilium/ebpf v0.9.1 // indirect
github.com/containerd/cgroups/v3 v3.0.1 // indirect
@ -103,7 +102,7 @@ require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-errors/errors v1.4.1 // indirect
github.com/go-jose/go-jose/v3 v3.0.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
@ -125,7 +124,6 @@ require (
github.com/jackc/pgpassfile v1.0.0 // indirect
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
@ -133,7 +131,7 @@ require (
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/leodido/go-urn v1.2.3 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/minio/md5-simd v1.1.2 // indirect
github.com/minio/sha256-simd v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
@ -156,21 +154,21 @@ require (
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.9 // indirect
github.com/uptrace/opentelemetry-go-extra/otelsql v0.1.21 // indirect
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.0 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 // indirect
go.opentelemetry.io/otel/metric v0.36.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1 // indirect
go.opentelemetry.io/otel/metric v0.38.1 // indirect
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect
google.golang.org/grpc v1.53.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
lukechampine.com/uint128 v1.2.0 // indirect

113
go.sum
View file

@ -90,8 +90,6 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/KimMachineGun/automemlimit v0.2.6 h1:tQFriVTcIteUkV5EgU9iz03eDY36T8JU5RAjP2r6Kt0=
github.com/KimMachineGun/automemlimit v0.2.6/go.mod h1:pJhTW/nWJMj6SnWSU2TEKSlCaM+1N5Mej+IfS/5/Ol0=
github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/abema/go-mp4 v0.10.1 h1:wOhZgNxjduc8r4FJdwPa5x/gdBSSX+8MTnfNj/xkJaE=
github.com/abema/go-mp4 v0.10.1/go.mod h1:vPl9t5ZK7K0x68jh12/+ECWBCXoWuIDtNgPtU2f04ws=
@ -107,8 +105,8 @@ github.com/buckket/go-blurhash v1.1.0/go.mod h1:aT2iqo5W9vu9GpyoLErKfTHwgODsZp3b
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA=
github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/cenkalti/backoff/v4 v4.2.0 h1:HN5dHm3WBOgndBH6E8V0q2jIYIR3s9yglV8k/+MN3u4=
github.com/cenkalti/backoff/v4 v4.2.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
@ -131,7 +129,6 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
github.com/containerd/cgroups/v3 v3.0.1 h1:4hfGvu8rfGIwVIDd+nLzn/B9ZXx4BcCjzt5ToenJRaE=
github.com/containerd/cgroups/v3 v3.0.1/go.mod h1:/vtwk1VXrtoa5AaZLkypuOJgA/6DyPMZHJPGQNtlHnw=
@ -217,11 +214,9 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo=
github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
@ -247,8 +242,6 @@ github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
@ -367,7 +360,6 @@ github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW
github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s=
github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o=
github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY=
github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI=
github.com/jackc/pgconn v1.14.0 h1:vrbA9Ud87g6JdFWkHTJXppVce58qPIdP7N8y0Ml/A7Q=
github.com/jackc/pgconn v1.14.0/go.mod h1:9mBNlny0UvkgJdCDvdVHYSjI+8tD2rnKK69Wz8ti++E=
github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE=
@ -393,19 +385,13 @@ github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZ
github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg=
github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc=
github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw=
github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM=
github.com/jackc/pgtype v1.14.0 h1:y+xUdabmyMkJLyApYuPj38mW+aAIqCe5uuBB51rH3Vw=
github.com/jackc/pgtype v1.14.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4=
github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y=
github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM=
github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc=
github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs=
github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0=
github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE=
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
@ -446,20 +432,17 @@ github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNa
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2/go.mod h1:0KeJpeMD6o+O4hW7qJOT7vyQPKrWmj26uf5wMc/IiIs=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U=
github.com/microcosm-cc/bluemonday v1.0.23 h1:SMZe2IGa0NuHvnVNAZ+6B38gsTbi5e4sViiWJyDDqFY=
github.com/microcosm-cc/bluemonday v1.0.23/go.mod h1:mN70sk7UkkF8TUr2IGBpNN0jAgStuPzlK76QuruE/z4=
@ -526,8 +509,6 @@ github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZ
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
@ -611,16 +592,16 @@ github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ulule/limiter/v3 v3.11.1 h1:wm6YaA2JwIXc0S+z8TK8/neWMOTf4m20I5jL1dwLRcw=
github.com/ulule/limiter/v3 v3.11.1/go.mod h1:4nk/9RHEJthkjD+mmkqYxaPfD4pkB91PTH7k8ozB80g=
github.com/uptrace/bun v1.1.12 h1:sOjDVHxNTuM6dNGaba0wUuz7KvDE1BmNu9Gqs2gJSXQ=
github.com/uptrace/bun v1.1.12/go.mod h1:NPG6JGULBeQ9IU6yHp7YGELRa5Agmd7ATZdz4tGZ6z0=
github.com/uptrace/bun/dialect/pgdialect v1.1.12 h1:m/CM1UfOkoBTglGO5CUTKnIKKOApOYxkcP2qn0F9tJk=
github.com/uptrace/bun/dialect/pgdialect v1.1.12/go.mod h1:Ij6WIxQILxLlL2frUBxUBOZJtLElD2QQNDcu/PWDHTc=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.12 h1:Ud31nqZmebcQpl151nb108+vtcpxJ7kfXmbPYbALBiI=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.12/go.mod h1:Pwg7s31BdF3PMBlWTnYkEn2I9ASsvatt1Ln/AERCTV4=
github.com/uptrace/bun/extra/bunotel v1.1.12 h1:uWPU75j9dYGXMRC9jF0ASlndZZAcngoqZagH4w3kn54=
github.com/uptrace/bun/extra/bunotel v1.1.12/go.mod h1:QfszJGLzNaTTGvvg17cEEUyEwxXq2NJ7sRvrPYvYSIU=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.1.21 h1:iHkIlTU2P3xbSbVJbAiHL9IT+ekYV5empheF+652yeQ=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.1.21/go.mod h1:hiCFa1UeZITKXi8lhu2qwOD5LHXjdGMCUIQHbybxoF0=
github.com/uptrace/bun v1.1.13 h1:IrxlIJHzCHFwmIzx66A9vi6qx8rHsHFiiT9LqlafHZw=
github.com/uptrace/bun v1.1.13/go.mod h1:UsZPd0AuHOx2QkkKXnqkHnFBjVp5tKqI7s4A750u9v0=
github.com/uptrace/bun/dialect/pgdialect v1.1.13 h1:j9BecpkRA9SDVBwh6oKhC5rABk4B40s66OCcqBHSQXM=
github.com/uptrace/bun/dialect/pgdialect v1.1.13/go.mod h1:G9h6kk5qfTyACjTja7gqM7SbRc0rqRc9AWDjzxwA7nY=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.13 h1:ipYi26qS4xC9AVmArXqv4Rq+EJFtrsZfS+Ksqx21QVI=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.13/go.mod h1:pOUXT+1n1/cIJUwdq7w97NS6nA1kd01o8ZRWPy/JBMM=
github.com/uptrace/bun/extra/bunotel v1.1.13 h1:QE0fNJpA+4mZi7cJXPDp5eQ3p5J/+tbwT0BRrXGFhhU=
github.com/uptrace/bun/extra/bunotel v1.1.13/go.mod h1:ktwAHvvAlxy0G0z5Gl/HQDFOI7XOmWqbudDegdtZmfo=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.0 h1:7srBbziwY2NM8xtco+JMqsRu1FSvI1ZJn/eRtgcHtmg=
github.com/uptrace/opentelemetry-go-extra/otelsql v0.2.0/go.mod h1:OsbPyR3wEfyJVdlEaMLXBrBpIWkyxEb9iwDQcxkMkTI=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.14.0/go.mod h1:ol1PCaL0dX20wC0htZ7sYCsvCYmrouYra0zHzaclZhE=
@ -663,42 +644,33 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.40.0 h1:E4MMXDxufRnIHXhoTNOlNsdkWpC5HdLhfj84WNRKPkc=
go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.40.0/go.mod h1:A8+gHkpqTfMKxdKWq1pp360nAs096K26CH5Sm2YHDdA=
go.opentelemetry.io/contrib/propagators/b3 v1.15.0 h1:bMaonPyFcAvZ4EVzkUNkfnUHP5Zi63CIDlA3dRsEg8Q=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0 h1:CjbUNd4iN2hHmWekmOqZ+zSCU+dzZppG8XsV+A3oc8Q=
go.opentelemetry.io/otel/exporters/jaeger v1.14.0/go.mod h1:4Ay9kk5vELRrbg5z4cpP9EtmQRFap2Wb0woPG4lujZA=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0 h1:/fXHZHGvro6MVqV34fJzDhi7sHGpX3Ej/Qjmfn003ho=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.14.0/go.mod h1:UFG7EBMRdXyFstOwH028U0sVf+AvukSGhF0g8+dmNG8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0 h1:TKf2uAs2ueguzLaxOCBXNpHxfO/aC7PAdDsSH0IbeRQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.14.0/go.mod h1:HrbCVv40OOLTABmOn1ZWty6CHXkU8DK/Urc43tHug70=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0 h1:ap+y8RXX3Mu9apKVtOkM6WSFESLM8K3wNQyOU8sWHcc=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.14.0/go.mod h1:5w41DY6S9gZrbjuq6Y+753e96WfPha5IcsOSZTtullM=
go.opentelemetry.io/otel/metric v0.36.0 h1:t0lgGI+L68QWt3QtOIlqM9gXoxqxWLhZ3R/e5oOAY0Q=
go.opentelemetry.io/otel/metric v0.36.0/go.mod h1:wKVw57sd2HdSZAzyfOM9gTqqE8v7CbqWsYL6AyrH9qk=
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8=
go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc=
go.opentelemetry.io/otel/exporters/jaeger v1.15.1 h1:x3SLvwli0OyAJapNcOIzf1xXBRBA+HD3elrMQmFfmXo=
go.opentelemetry.io/otel/exporters/jaeger v1.15.1/go.mod h1:0Ck9b5oLL/bFZvfAEEqtrb1U0jZXjm5fWXMCOCG3vvM=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1 h1:XYDQtNzdb2T4uM1pku2m76eSMDJgqhJ+6KzkqgQBALc=
go.opentelemetry.io/otel/exporters/otlp/internal/retry v1.15.1/go.mod h1:uOTV75+LOzV+ODmL8ahRLWkFA3eQcSC2aAsbxIu4duk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1 h1:tyoeaUh8REKay72DVYsSEBYV18+fGONe+YYPaOxgLoE=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.15.1/go.mod h1:HUSnrjQQ19KX9ECjpQxufsF+3ioD3zISPMlauTPZu2g=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1 h1:pIfoG5IAZFzp9EUlJzdSkpUwpaUAAnD+Ru1nBLTACIQ=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.15.1/go.mod h1:poNKBqF5+nR/6ke2oGTDjHfksrsHDOHXAl2g4+9ONsY=
go.opentelemetry.io/otel/metric v0.38.1 h1:2MM7m6wPw9B8Qv8iHygoAgkbejed59uUR6ezR5T3X2s=
go.opentelemetry.io/otel/metric v0.38.1/go.mod h1:FwqNHD3I/5iX9pfrRGZIlYICrJv0rHEUl2Ln5vdIVnQ=
go.opentelemetry.io/otel/sdk v1.15.1 h1:5FKR+skgpzvhPQHIEfcwMYjCBr14LWzs3uSqKiQzETI=
go.opentelemetry.io/otel/sdk v1.15.1/go.mod h1:8rVtxQfrbmbHKfqzpQkT5EzZMcbMBwTzNAggbEAM0KA=
go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY=
go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.19.0 h1:IVN6GR+mhC4s5yfcTbmzHYODqvWAp3ZedA2SJPI1Nnw=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/automaxprocs v1.5.2 h1:2LxUOGiR3O6tw8ui5sZa2LAaHnsviZdVOUZw4fvbnME=
go.uber.org/automaxprocs v1.5.2/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -885,12 +857,12 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -931,8 +903,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@ -940,7 +910,6 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@ -1062,8 +1031,8 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc=
google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw=
google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag=
google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@ -1078,8 +1047,8 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View file

@ -33,8 +33,8 @@ import (
"codeberg.org/gruf/go-bytesize"
"github.com/google/uuid"
"github.com/jackc/pgx/v4"
"github.com/jackc/pgx/v4/stdlib"
"github.com/jackc/pgx/v5"
"github.com/jackc/pgx/v5/stdlib"
"github.com/superseriousbusiness/gotosocial/internal/config"
"github.com/superseriousbusiness/gotosocial/internal/db"
"github.com/superseriousbusiness/gotosocial/internal/db/bundb/migrations"
@ -94,14 +94,11 @@ func doMigration(ctx context.Context, db *bun.DB) error {
}
group, err := migrator.Migrate(ctx)
if err != nil {
if err.Error() == "migrate: there are no any migrations" {
return nil
}
if err != nil && !strings.Contains(err.Error(), "no migrations") {
return err
}
if group.ID == 0 {
if group == nil || group.ID == 0 {
log.Info(ctx, "there are no new migrations to run")
return nil
}
@ -132,9 +129,8 @@ func NewBunDBService(ctx context.Context, state *state.State) (db.DB, error) {
return nil, fmt.Errorf("database type %s not supported for bundb", t)
}
// Add database query hook
// Add database query hooks.
conn.DB.AddQueryHook(queryHook{})
if config.GetTracingEnabled() {
conn.DB.AddQueryHook(tracing.InstrumentBun())
}
@ -431,7 +427,6 @@ func deriveBunDBPGOptions() (*pgx.ConnConfig, error) {
cfg.TLSConfig = tlsConfig
}
cfg.Database = database
cfg.PreferSimpleProtocol = true
cfg.RuntimeParams["application_name"] = config.GetApplicationName()
return cfg, nil

View file

@ -6,7 +6,6 @@ linters:
disable-all: true
enable:
- asciicheck
- deadcode
- errcheck
- forcetypeassert
- gocritic
@ -18,10 +17,8 @@ linters:
- misspell
- revive
- staticcheck
- structcheck
- typecheck
- unused
- varcheck
issues:
exclude-use-default: false

View file

@ -20,35 +20,5 @@ package logr
// used whenever the caller is not interested in the logs. Logger instances
// produced by this function always compare as equal.
func Discard() Logger {
return Logger{
level: 0,
sink: discardLogSink{},
}
}
// discardLogSink is a LogSink that discards all messages.
type discardLogSink struct{}
// Verify that it actually implements the interface
var _ LogSink = discardLogSink{}
func (l discardLogSink) Init(RuntimeInfo) {
}
func (l discardLogSink) Enabled(int) bool {
return false
}
func (l discardLogSink) Info(int, string, ...interface{}) {
}
func (l discardLogSink) Error(error, string, ...interface{}) {
}
func (l discardLogSink) WithValues(...interface{}) LogSink {
return l
}
func (l discardLogSink) WithName(string) LogSink {
return l
return New(nil)
}

View file

@ -21,13 +21,13 @@ limitations under the License.
// github.com/go-logr/logr.LogSink with output through an arbitrary
// "write" function. See New and NewJSON for details.
//
// Custom LogSinks
// # Custom LogSinks
//
// For users who need more control, a funcr.Formatter can be embedded inside
// your own custom LogSink implementation. This is useful when the LogSink
// needs to implement additional methods, for example.
//
// Formatting
// # Formatting
//
// This will respect logr.Marshaler, fmt.Stringer, and error interfaces for
// values which are being logged. When rendering a struct, funcr will use Go's
@ -37,6 +37,7 @@ package funcr
import (
"bytes"
"encoding"
"encoding/json"
"fmt"
"path/filepath"
"reflect"
@ -217,7 +218,7 @@ func newFormatter(opts Options, outfmt outputFormat) Formatter {
prefix: "",
values: nil,
depth: 0,
opts: opts,
opts: &opts,
}
return f
}
@ -231,7 +232,7 @@ type Formatter struct {
values []interface{}
valuesStr string
depth int
opts Options
opts *Options
}
// outputFormat indicates which outputFormat to use.
@ -447,6 +448,7 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
if flags&flagRawStruct == 0 {
buf.WriteByte('{')
}
printComma := false // testing i>0 is not enough because of JSON omitted fields
for i := 0; i < t.NumField(); i++ {
fld := t.Field(i)
if fld.PkgPath != "" {
@ -478,9 +480,10 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
if omitempty && isEmpty(v.Field(i)) {
continue
}
if i > 0 {
if printComma {
buf.WriteByte(',')
}
printComma = true // if we got here, we are rendering a field
if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" {
buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct, depth+1))
continue
@ -500,6 +503,20 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
}
return buf.String()
case reflect.Slice, reflect.Array:
// If this is outputing as JSON make sure this isn't really a json.RawMessage.
// If so just emit "as-is" and don't pretty it as that will just print
// it as [X,Y,Z,...] which isn't terribly useful vs the string form you really want.
if f.outputFormat == outputJSON {
if rm, ok := value.(json.RawMessage); ok {
// If it's empty make sure we emit an empty value as the array style would below.
if len(rm) > 0 {
buf.Write(rm)
} else {
buf.WriteString("null")
}
return buf.String()
}
}
buf.WriteByte('[')
for i := 0; i < v.Len(); i++ {
if i > 0 {

View file

@ -21,7 +21,7 @@ limitations under the License.
// to back that API. Packages in the Go ecosystem can depend on this package,
// while callers can implement logging with whatever backend is appropriate.
//
// Usage
// # Usage
//
// Logging is done using a Logger instance. Logger is a concrete type with
// methods, which defers the actual logging to a LogSink interface. The main
@ -30,16 +30,20 @@ limitations under the License.
// "structured logging".
//
// With Go's standard log package, we might write:
// log.Printf("setting target value %s", targetValue)
//
// log.Printf("setting target value %s", targetValue)
//
// With logr's structured logging, we'd write:
// logger.Info("setting target", "value", targetValue)
//
// logger.Info("setting target", "value", targetValue)
//
// Errors are much the same. Instead of:
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
//
// log.Printf("failed to open the pod bay door for user %s: %v", user, err)
//
// We'd write:
// logger.Error(err, "failed to open the pod bay door", "user", user)
//
// logger.Error(err, "failed to open the pod bay door", "user", user)
//
// Info() and Error() are very similar, but they are separate methods so that
// LogSink implementations can choose to do things like attach additional
@ -47,7 +51,7 @@ limitations under the License.
// always logged, regardless of the current verbosity. If there is no error
// instance available, passing nil is valid.
//
// Verbosity
// # Verbosity
//
// Often we want to log information only when the application in "verbose
// mode". To write log lines that are more verbose, Logger has a V() method.
@ -58,20 +62,22 @@ limitations under the License.
// Error messages do not have a verbosity level and are always logged.
//
// Where we might have written:
// if flVerbose >= 2 {
// log.Printf("an unusual thing happened")
// }
//
// if flVerbose >= 2 {
// log.Printf("an unusual thing happened")
// }
//
// We can write:
// logger.V(2).Info("an unusual thing happened")
//
// Logger Names
// logger.V(2).Info("an unusual thing happened")
//
// # Logger Names
//
// Logger instances can have name strings so that all messages logged through
// that instance have additional context. For example, you might want to add
// a subsystem name:
//
// logger.WithName("compactor").Info("started", "time", time.Now())
// logger.WithName("compactor").Info("started", "time", time.Now())
//
// The WithName() method returns a new Logger, which can be passed to
// constructors or other functions for further use. Repeated use of WithName()
@ -82,25 +88,27 @@ limitations under the License.
// joining operation (e.g. whitespace, commas, periods, slashes, brackets,
// quotes, etc).
//
// Saved Values
// # Saved Values
//
// Logger instances can store any number of key/value pairs, which will be
// logged alongside all messages logged through that instance. For example,
// you might want to create a Logger instance per managed object:
//
// With the standard log package, we might write:
// log.Printf("decided to set field foo to value %q for object %s/%s",
// targetValue, object.Namespace, object.Name)
//
// log.Printf("decided to set field foo to value %q for object %s/%s",
// targetValue, object.Namespace, object.Name)
//
// With logr we'd write:
// // Elsewhere: set up the logger to log the object name.
// obj.logger = mainLogger.WithValues(
// "name", obj.name, "namespace", obj.namespace)
//
// // later on...
// obj.logger.Info("setting foo", "value", targetValue)
// // Elsewhere: set up the logger to log the object name.
// obj.logger = mainLogger.WithValues(
// "name", obj.name, "namespace", obj.namespace)
//
// Best Practices
// // later on...
// obj.logger.Info("setting foo", "value", targetValue)
//
// # Best Practices
//
// Logger has very few hard rules, with the goal that LogSink implementations
// might have a lot of freedom to differentiate. There are, however, some
@ -124,15 +132,15 @@ limitations under the License.
// around. For cases where passing a logger is optional, a pointer to Logger
// should be used.
//
// Key Naming Conventions
// # Key Naming Conventions
//
// Keys are not strictly required to conform to any specification or regex, but
// it is recommended that they:
// * be human-readable and meaningful (not auto-generated or simple ordinals)
// * be constant (not dependent on input data)
// * contain only printable characters
// * not contain whitespace or punctuation
// * use lower case for simple keys and lowerCamelCase for more complex ones
// - be human-readable and meaningful (not auto-generated or simple ordinals)
// - be constant (not dependent on input data)
// - contain only printable characters
// - not contain whitespace or punctuation
// - use lower case for simple keys and lowerCamelCase for more complex ones
//
// These guidelines help ensure that log data is processed properly regardless
// of the log implementation. For example, log implementations will try to
@ -141,51 +149,54 @@ limitations under the License.
// While users are generally free to use key names of their choice, it's
// generally best to avoid using the following keys, as they're frequently used
// by implementations:
// * "caller": the calling information (file/line) of a particular log line
// * "error": the underlying error value in the `Error` method
// * "level": the log level
// * "logger": the name of the associated logger
// * "msg": the log message
// * "stacktrace": the stack trace associated with a particular log line or
// error (often from the `Error` message)
// * "ts": the timestamp for a log line
// - "caller": the calling information (file/line) of a particular log line
// - "error": the underlying error value in the `Error` method
// - "level": the log level
// - "logger": the name of the associated logger
// - "msg": the log message
// - "stacktrace": the stack trace associated with a particular log line or
// error (often from the `Error` message)
// - "ts": the timestamp for a log line
//
// Implementations are encouraged to make use of these keys to represent the
// above concepts, when necessary (for example, in a pure-JSON output form, it
// would be necessary to represent at least message and timestamp as ordinary
// named values).
//
// Break Glass
// # Break Glass
//
// Implementations may choose to give callers access to the underlying
// logging implementation. The recommended pattern for this is:
// // Underlier exposes access to the underlying logging implementation.
// // Since callers only have a logr.Logger, they have to know which
// // implementation is in use, so this interface is less of an abstraction
// // and more of way to test type conversion.
// type Underlier interface {
// GetUnderlying() <underlying-type>
// }
//
// // Underlier exposes access to the underlying logging implementation.
// // Since callers only have a logr.Logger, they have to know which
// // implementation is in use, so this interface is less of an abstraction
// // and more of way to test type conversion.
// type Underlier interface {
// GetUnderlying() <underlying-type>
// }
//
// Logger grants access to the sink to enable type assertions like this:
// func DoSomethingWithImpl(log logr.Logger) {
// if underlier, ok := log.GetSink()(impl.Underlier) {
// implLogger := underlier.GetUnderlying()
// ...
// }
// }
//
// func DoSomethingWithImpl(log logr.Logger) {
// if underlier, ok := log.GetSink().(impl.Underlier); ok {
// implLogger := underlier.GetUnderlying()
// ...
// }
// }
//
// Custom `With*` functions can be implemented by copying the complete
// Logger struct and replacing the sink in the copy:
// // WithFooBar changes the foobar parameter in the log sink and returns a
// // new logger with that modified sink. It does nothing for loggers where
// // the sink doesn't support that parameter.
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
// if foobarLogSink, ok := log.GetSink()(FoobarSink); ok {
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
// }
// return log
// }
//
// // WithFooBar changes the foobar parameter in the log sink and returns a
// // new logger with that modified sink. It does nothing for loggers where
// // the sink doesn't support that parameter.
// func WithFoobar(log logr.Logger, foobar int) logr.Logger {
// if foobarLogSink, ok := log.GetSink().(FoobarSink); ok {
// log = log.WithSink(foobarLogSink.WithFooBar(foobar))
// }
// return log
// }
//
// Don't use New to construct a new Logger with a LogSink retrieved from an
// existing Logger. Source code attribution might not work correctly and
@ -201,11 +212,14 @@ import (
)
// New returns a new Logger instance. This is primarily used by libraries
// implementing LogSink, rather than end users.
// implementing LogSink, rather than end users. Passing a nil sink will create
// a Logger which discards all log lines.
func New(sink LogSink) Logger {
logger := Logger{}
logger.setSink(sink)
sink.Init(runtimeInfo)
if sink != nil {
sink.Init(runtimeInfo)
}
return logger
}
@ -244,7 +258,7 @@ type Logger struct {
// Enabled tests whether this Logger is enabled. For example, commandline
// flags might be used to set the logging verbosity and disable some info logs.
func (l Logger) Enabled() bool {
return l.sink.Enabled(l.level)
return l.sink != nil && l.sink.Enabled(l.level)
}
// Info logs a non-error message with the given key/value pairs as context.
@ -254,6 +268,9 @@ func (l Logger) Enabled() bool {
// information. The key/value pairs must alternate string keys and arbitrary
// values.
func (l Logger) Info(msg string, keysAndValues ...interface{}) {
if l.sink == nil {
return
}
if l.Enabled() {
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
withHelper.GetCallStackHelper()()
@ -273,6 +290,9 @@ func (l Logger) Info(msg string, keysAndValues ...interface{}) {
// triggered this log line, if present. The err parameter is optional
// and nil may be passed instead of an error instance.
func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
if l.sink == nil {
return
}
if withHelper, ok := l.sink.(CallStackHelperLogSink); ok {
withHelper.GetCallStackHelper()()
}
@ -284,6 +304,9 @@ func (l Logger) Error(err error, msg string, keysAndValues ...interface{}) {
// level means a log message is less important. Negative V-levels are treated
// as 0.
func (l Logger) V(level int) Logger {
if l.sink == nil {
return l
}
if level < 0 {
level = 0
}
@ -294,6 +317,9 @@ func (l Logger) V(level int) Logger {
// WithValues returns a new Logger instance with additional key/value pairs.
// See Info for documentation on how key/value pairs work.
func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
if l.sink == nil {
return l
}
l.setSink(l.sink.WithValues(keysAndValues...))
return l
}
@ -304,6 +330,9 @@ func (l Logger) WithValues(keysAndValues ...interface{}) Logger {
// contain only letters, digits, and hyphens (see the package documentation for
// more information).
func (l Logger) WithName(name string) Logger {
if l.sink == nil {
return l
}
l.setSink(l.sink.WithName(name))
return l
}
@ -324,6 +353,9 @@ func (l Logger) WithName(name string) Logger {
// WithCallDepth(1) because it works with implementions that support the
// CallDepthLogSink and/or CallStackHelperLogSink interfaces.
func (l Logger) WithCallDepth(depth int) Logger {
if l.sink == nil {
return l
}
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
l.setSink(withCallDepth.WithCallDepth(depth))
}
@ -345,6 +377,9 @@ func (l Logger) WithCallDepth(depth int) Logger {
// implementation does not support either of these, the original Logger will be
// returned.
func (l Logger) WithCallStackHelper() (func(), Logger) {
if l.sink == nil {
return func() {}, l
}
var helper func()
if withCallDepth, ok := l.sink.(CallDepthLogSink); ok {
l.setSink(withCallDepth.WithCallDepth(1))
@ -357,6 +392,11 @@ func (l Logger) WithCallStackHelper() (func(), Logger) {
return helper, l
}
// IsZero returns true if this logger is an uninitialized zero value
func (l Logger) IsZero() bool {
return l.sink == nil
}
// contextKey is how we find Loggers in a context.Context.
type contextKey struct{}
@ -442,7 +482,7 @@ type LogSink interface {
WithName(name string) LogSink
}
// CallDepthLogSink represents a Logger that knows how to climb the call stack
// CallDepthLogSink represents a LogSink that knows how to climb the call stack
// to identify the original call site and can offset the depth by a specified
// number of frames. This is useful for users who have helper functions
// between the "real" call site and the actual calls to Logger methods.
@ -467,7 +507,7 @@ type CallDepthLogSink interface {
WithCallDepth(depth int) LogSink
}
// CallStackHelperLogSink represents a Logger that knows how to climb
// CallStackHelperLogSink represents a LogSink that knows how to climb
// the call stack to identify the original call site and can skip
// intermediate helper functions if they mark themselves as
// helper. Go's testing package uses that approach.

View file

@ -1,169 +0,0 @@
package stmtcache
import (
"container/list"
"context"
"fmt"
"sync/atomic"
"github.com/jackc/pgconn"
)
var lruCount uint64
// LRU implements Cache with a Least Recently Used (LRU) cache.
type LRU struct {
conn *pgconn.PgConn
mode int
cap int
prepareCount int
m map[string]*list.Element
l *list.List
psNamePrefix string
stmtsToClear []string
}
// NewLRU creates a new LRU. mode is either ModePrepare or ModeDescribe. cap is the maximum size of the cache.
func NewLRU(conn *pgconn.PgConn, mode int, cap int) *LRU {
mustBeValidMode(mode)
mustBeValidCap(cap)
n := atomic.AddUint64(&lruCount, 1)
return &LRU{
conn: conn,
mode: mode,
cap: cap,
m: make(map[string]*list.Element),
l: list.New(),
psNamePrefix: fmt.Sprintf("lrupsc_%d", n),
}
}
// Get returns the prepared statement description for sql preparing or describing the sql on the server as needed.
func (c *LRU) Get(ctx context.Context, sql string) (*pgconn.StatementDescription, error) {
if ctx != context.Background() {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
}
// flush an outstanding bad statements
txStatus := c.conn.TxStatus()
if (txStatus == 'I' || txStatus == 'T') && len(c.stmtsToClear) > 0 {
for _, stmt := range c.stmtsToClear {
err := c.clearStmt(ctx, stmt)
if err != nil {
return nil, err
}
}
}
if el, ok := c.m[sql]; ok {
c.l.MoveToFront(el)
return el.Value.(*pgconn.StatementDescription), nil
}
if c.l.Len() == c.cap {
err := c.removeOldest(ctx)
if err != nil {
return nil, err
}
}
psd, err := c.prepare(ctx, sql)
if err != nil {
return nil, err
}
el := c.l.PushFront(psd)
c.m[sql] = el
return psd, nil
}
// Clear removes all entries in the cache. Any prepared statements will be deallocated from the PostgreSQL session.
func (c *LRU) Clear(ctx context.Context) error {
for c.l.Len() > 0 {
err := c.removeOldest(ctx)
if err != nil {
return err
}
}
return nil
}
func (c *LRU) StatementErrored(sql string, err error) {
pgErr, ok := err.(*pgconn.PgError)
if !ok {
return
}
// https://github.com/jackc/pgx/issues/1162
//
// We used to look for the message "cached plan must not change result type". However, that message can be localized.
// Unfortunately, error code "0A000" - "FEATURE NOT SUPPORTED" is used for many different errors and the only way to
// tell the difference is by the message. But all that happens is we clear a statement that we otherwise wouldn't
// have so it should be safe.
possibleInvalidCachedPlanError := pgErr.Code == "0A000"
if possibleInvalidCachedPlanError {
c.stmtsToClear = append(c.stmtsToClear, sql)
}
}
func (c *LRU) clearStmt(ctx context.Context, sql string) error {
elem, inMap := c.m[sql]
if !inMap {
// The statement probably fell off the back of the list. In that case, we've
// ensured that it isn't in the cache, so we can declare victory.
return nil
}
c.l.Remove(elem)
psd := elem.Value.(*pgconn.StatementDescription)
delete(c.m, psd.SQL)
if c.mode == ModePrepare {
return c.conn.Exec(ctx, fmt.Sprintf("deallocate %s", psd.Name)).Close()
}
return nil
}
// Len returns the number of cached prepared statement descriptions.
func (c *LRU) Len() int {
return c.l.Len()
}
// Cap returns the maximum number of cached prepared statement descriptions.
func (c *LRU) Cap() int {
return c.cap
}
// Mode returns the mode of the cache (ModePrepare or ModeDescribe)
func (c *LRU) Mode() int {
return c.mode
}
func (c *LRU) prepare(ctx context.Context, sql string) (*pgconn.StatementDescription, error) {
var name string
if c.mode == ModePrepare {
name = fmt.Sprintf("%s_%d", c.psNamePrefix, c.prepareCount)
c.prepareCount += 1
}
return c.conn.Prepare(ctx, name, sql, nil)
}
func (c *LRU) removeOldest(ctx context.Context) error {
oldest := c.l.Back()
c.l.Remove(oldest)
psd := oldest.Value.(*pgconn.StatementDescription)
delete(c.m, psd.SQL)
if c.mode == ModePrepare {
return c.conn.Exec(ctx, fmt.Sprintf("deallocate %s", psd.Name)).Close()
}
return nil
}

View file

@ -1,58 +0,0 @@
// Package stmtcache is a cache that can be used to implement lazy prepared statements.
package stmtcache
import (
"context"
"github.com/jackc/pgconn"
)
const (
ModePrepare = iota // Cache should prepare named statements.
ModeDescribe // Cache should prepare the anonymous prepared statement to only fetch the description of the statement.
)
// Cache prepares and caches prepared statement descriptions.
type Cache interface {
// Get returns the prepared statement description for sql preparing or describing the sql on the server as needed.
Get(ctx context.Context, sql string) (*pgconn.StatementDescription, error)
// Clear removes all entries in the cache. Any prepared statements will be deallocated from the PostgreSQL session.
Clear(ctx context.Context) error
// StatementErrored informs the cache that the given statement resulted in an error when it
// was last used against the database. In some cases, this will cause the cache to maer that
// statement as bad. The bad statement will instead be flushed during the next call to Get
// that occurs outside of a failed transaction.
StatementErrored(sql string, err error)
// Len returns the number of cached prepared statement descriptions.
Len() int
// Cap returns the maximum number of cached prepared statement descriptions.
Cap() int
// Mode returns the mode of the cache (ModePrepare or ModeDescribe)
Mode() int
}
// New returns the preferred cache implementation for mode and cap. mode is either ModePrepare or ModeDescribe. cap is
// the maximum size of the cache.
func New(conn *pgconn.PgConn, mode int, cap int) Cache {
mustBeValidMode(mode)
mustBeValidCap(cap)
return NewLRU(conn, mode, cap)
}
func mustBeValidMode(mode int) {
if mode != ModePrepare && mode != ModeDescribe {
panic("mode must be ModePrepare or ModeDescribe")
}
}
func mustBeValidCap(cap int) {
if cap < 1 {
panic("cache must have cap of >= 1")
}
}

View file

@ -1,164 +0,0 @@
# 1.14.0 (February 11, 2023)
* Fix: BC timestamp text format support (jozeflami)
* Add Scanner and Valuer interfaces to CIDR (Yurii Popivniak)
* Fix crash when nilifying pointer to sql.Scanner
# 1.13.0 (December 1, 2022)
* Fix: Reset jsonb before unmarshal (Tomas Odinas)
* Fix: return correct zero value when UUID conversion fails (ndrpnt)
* Fix: EncodeText for Lseg includes [ and ]
* Support sql Value and Scan for custom date type (Hubert Krauze)
* Support Ltree binary encoding (AmineChikhaoui)
* Fix: dates with "BC" (jozeflami)
# 1.12.0 (August 6, 2022)
* Add JSONArray (Jakob Ackermann)
* Support Inet from fmt.Stringer and encoding.TextMarshaler (Ville Skyttä)
* Support UUID from fmt.Stringer interface (Lasse Hyldahl Jensen)
* Fix: shopspring-numeric extension does not panic on NaN
* Numeric can be assigned to string
* Fix: Do not send IPv4 networks as IPv4-mapped IPv6 (William Storey)
* Fix: PlanScan for interface{}(nil) (James Hartig)
* Fix: *sql.Scanner for NULL handling (James Hartig)
* Timestamp[tz].Set() supports string (Harmen)
* Fix: Hstore AssignTo with map of *string (Diego Becciolini)
# 1.11.0 (April 21, 2022)
* Add multirange for numeric, int4, and int8 (Vu)
* JSONBArray now supports json.RawMessage (Jens Emil Schulz Østergaard)
* Add RecordArray (WGH)
* Add UnmarshalJSON to pgtype.Int2
* Hstore.Set accepts map[string]Text
# 1.10.0 (February 7, 2022)
* Normalize UTC timestamps to comply with stdlib (Torkel Rogstad)
* Assign Numeric to *big.Rat (Oleg Lomaka)
* Fix typo in float8 error message (Pinank Solanki)
* Scan type aliases for floating point types (Collin Forsyth)
# 1.9.1 (November 28, 2021)
* Fix: binary timestamp is assumed to be in UTC (restored behavior changed in v1.9.0)
# 1.9.0 (November 20, 2021)
* Fix binary hstore null decoding
* Add shopspring/decimal.NullDecimal support to integration (Eli Treuherz)
* Inet.Set supports bare IP address (Carl Dunham)
* Add zeronull.Float8
* Fix NULL being lost when scanning unknown OID into sql.Scanner
* Fix BPChar.AssignTo **rune
* Add support for fmt.Stringer and driver.Valuer in String fields encoding (Jan Dubsky)
* Fix really big timestamp(tz)s binary format parsing (e.g. year 294276) (Jim Tsao)
* Support `map[string]*string` as hstore (Adrian Sieger)
* Fix parsing text array with negative bounds
* Add infinity support for numeric (Jim Tsao)
# 1.8.1 (July 24, 2021)
* Cleaned up Go module dependency chain
# 1.8.0 (July 10, 2021)
* Maintain host bits for inet types (Cameron Daniel)
* Support pointers of wrapping structs (Ivan Daunis)
* Register JSONBArray at NewConnInfo() (Rueian)
* CompositeTextScanner handles backslash escapes
# 1.7.0 (March 25, 2021)
* Fix scanning int into **sql.Scanner implementor
* Add tsrange array type (Vasilii Novikov)
* Fix: escaped strings when they start or end with a newline char (Stephane Martin)
* Accept nil *time.Time in Time.Set
* Fix numeric NaN support
* Use Go 1.13 errors instead of xerrors
# 1.6.2 (December 3, 2020)
* Fix panic on assigning empty array to non-slice or array
* Fix text array parsing disambiguates NULL and "NULL"
* Fix Timestamptz.DecodeText with too short text
# 1.6.1 (October 31, 2020)
* Fix simple protocol empty array support
# 1.6.0 (October 24, 2020)
* Fix AssignTo pointer to pointer to slice and named types.
* Fix zero length array assignment (Simo Haasanen)
* Add float64, float32 convert to int2, int4, int8 (lqu3j)
* Support setting infinite timestamps (Erik Agsjö)
* Polygon improvements (duohedron)
* Fix Inet.Set with nil (Tomas Volf)
# 1.5.0 (September 26, 2020)
* Add slice of slice mapping to multi-dimensional arrays (Simo Haasanen)
* Fix JSONBArray
* Fix selecting empty array
* Text formatted values except bytea can be directly scanned to []byte
* Add JSON marshalling for UUID (bakmataliev)
* Improve point type conversions (bakmataliev)
# 1.4.2 (July 22, 2020)
* Fix encoding of a large composite data type (Yaz Saito)
# 1.4.1 (July 14, 2020)
* Fix ArrayType DecodeBinary empty array breaks future reads
# 1.4.0 (June 27, 2020)
* Add JSON support to ext/gofrs-uuid
* Performance improvements in Scan path
* Improved ext/shopspring-numeric binary decoding performance
* Add composite type support (Maxim Ivanov and Jack Christensen)
* Add better generic enum type support
* Add generic array type support
* Clarify and normalize Value semantics
* Fix hstore with empty string values
* Numeric supports NaN values (leighhopcroft)
* Add slice of pointer support to array types (megaturbo)
* Add jsonb array type (tserakhau)
* Allow converting intervals with months and days to duration
# 1.3.0 (March 30, 2020)
* Get implemented on T instead of *T
* Set will call Get on src if possible
* Range types Set method supports its own type, string, and nil
* Date.Set parses string
* Fix correct format verb for unknown type error (Robert Welin)
* Truncate nanoseconds in EncodeText for Timestamptz and Timestamp
# 1.2.0 (February 5, 2020)
* Add zeronull package for easier NULL <-> zero conversion
* Add JSON marshalling for shopspring-numeric extension
* Add JSON marshalling for Bool, Date, JSON/B, Timestamptz (Jeffrey Stiles)
* Fix null status in UnmarshalJSON for some types (Jeffrey Stiles)
# 1.1.0 (January 11, 2020)
* Add PostgreSQL time type support
* Add more automatic conversions of integer arrays of different types (Jean-Philippe Quéméner)
# 1.0.3 (November 16, 2019)
* Support initializing Array types from a slice of the value (Alex Gaynor)
# 1.0.2 (October 22, 2019)
* Fix scan into null into pointer to pointer implementing Decode* interface. (Jeremy Altavilla)
# 1.0.1 (September 19, 2019)
* Fix daterange OID

View file

@ -1,14 +0,0 @@
[![](https://godoc.org/github.com/jackc/pgtype?status.svg)](https://godoc.org/github.com/jackc/pgtype)
![CI](https://github.com/jackc/pgtype/workflows/CI/badge.svg)
---
This version is used with pgx `v4`. In pgx `v5` it is part of the https://github.com/jackc/pgx repository.
---
# pgtype
pgtype implements Go types for over 70 PostgreSQL types. pgtype is the type system underlying the
https://github.com/jackc/pgx PostgreSQL driver. These types support the binary format for enhanced performance with pgx.
They also support the database/sql `Scan` and `Value` interfaces and can be used with https://github.com/lib/pq.

View file

@ -1,138 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
)
// ACLItem is used for PostgreSQL's aclitem data type. A sample aclitem
// might look like this:
//
// postgres=arwdDxt/postgres
//
// Note, however, that because the user/role name part of an aclitem is
// an identifier, it follows all the usual formatting rules for SQL
// identifiers: if it contains spaces and other special characters,
// it should appear in double-quotes:
//
// postgres=arwdDxt/"role with spaces"
//
type ACLItem struct {
String string
Status Status
}
func (dst *ACLItem) Set(src interface{}) error {
if src == nil {
*dst = ACLItem{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case string:
*dst = ACLItem{String: value, Status: Present}
case *string:
if value == nil {
*dst = ACLItem{Status: Null}
} else {
*dst = ACLItem{String: *value, Status: Present}
}
default:
if originalSrc, ok := underlyingStringType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to ACLItem", value)
}
return nil
}
func (dst ACLItem) Get() interface{} {
switch dst.Status {
case Present:
return dst.String
case Null:
return nil
default:
return dst.Status
}
}
func (src *ACLItem) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *string:
*v = src.String
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *ACLItem) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = ACLItem{Status: Null}
return nil
}
*dst = ACLItem{String: string(src), Status: Present}
return nil
}
func (src ACLItem) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.String...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *ACLItem) Scan(src interface{}) error {
if src == nil {
*dst = ACLItem{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src ACLItem) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.String, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,428 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"fmt"
"reflect"
)
type ACLItemArray struct {
Elements []ACLItem
Dimensions []ArrayDimension
Status Status
}
func (dst *ACLItemArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = ACLItemArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = ACLItemArray{Status: Null}
} else if len(value) == 0 {
*dst = ACLItemArray{Status: Present}
} else {
elements := make([]ACLItem, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = ACLItemArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*string:
if value == nil {
*dst = ACLItemArray{Status: Null}
} else if len(value) == 0 {
*dst = ACLItemArray{Status: Present}
} else {
elements := make([]ACLItem, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = ACLItemArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []ACLItem:
if value == nil {
*dst = ACLItemArray{Status: Null}
} else if len(value) == 0 {
*dst = ACLItemArray{Status: Present}
} else {
*dst = ACLItemArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = ACLItemArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for ACLItemArray", src)
}
if elementsLength == 0 {
*dst = ACLItemArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to ACLItemArray", src)
}
*dst = ACLItemArray{
Elements: make([]ACLItem, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]ACLItem, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to ACLItemArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *ACLItemArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to ACLItemArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in ACLItemArray", err)
}
index++
return index, nil
}
func (dst ACLItemArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *ACLItemArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*string:
*v = make([]*string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *ACLItemArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from ACLItemArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *ACLItemArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = ACLItemArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []ACLItem
if len(uta.Elements) > 0 {
elements = make([]ACLItem, len(uta.Elements))
for i, s := range uta.Elements {
var elem ACLItem
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = ACLItemArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (src ACLItemArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *ACLItemArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src ACLItemArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,353 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
// ArrayType represents an array type. While it implements Value, this is only in service of its type conversion duties
// when registered as a data type in a ConnType. It should not be used directly as a Value. ArrayType is a convenience
// type for types that do not have a concrete array type.
type ArrayType struct {
elements []ValueTranscoder
dimensions []ArrayDimension
typeName string
newElement func() ValueTranscoder
elementOID uint32
status Status
}
func NewArrayType(typeName string, elementOID uint32, newElement func() ValueTranscoder) *ArrayType {
return &ArrayType{typeName: typeName, elementOID: elementOID, newElement: newElement}
}
func (at *ArrayType) NewTypeValue() Value {
return &ArrayType{
elements: at.elements,
dimensions: at.dimensions,
status: at.status,
typeName: at.typeName,
elementOID: at.elementOID,
newElement: at.newElement,
}
}
func (at *ArrayType) TypeName() string {
return at.typeName
}
func (dst *ArrayType) setNil() {
dst.elements = nil
dst.dimensions = nil
dst.status = Null
}
func (dst *ArrayType) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
dst.setNil()
return nil
}
sliceVal := reflect.ValueOf(src)
if sliceVal.Kind() != reflect.Slice {
return fmt.Errorf("cannot set non-slice")
}
if sliceVal.IsNil() {
dst.setNil()
return nil
}
dst.elements = make([]ValueTranscoder, sliceVal.Len())
for i := range dst.elements {
v := dst.newElement()
err := v.Set(sliceVal.Index(i).Interface())
if err != nil {
return err
}
dst.elements[i] = v
}
dst.dimensions = []ArrayDimension{{Length: int32(len(dst.elements)), LowerBound: 1}}
dst.status = Present
return nil
}
func (dst ArrayType) Get() interface{} {
switch dst.status {
case Present:
elementValues := make([]interface{}, len(dst.elements))
for i := range dst.elements {
elementValues[i] = dst.elements[i].Get()
}
return elementValues
case Null:
return nil
default:
return dst.status
}
}
func (src *ArrayType) AssignTo(dst interface{}) error {
ptrSlice := reflect.ValueOf(dst)
if ptrSlice.Kind() != reflect.Ptr {
return fmt.Errorf("cannot assign to non-pointer")
}
sliceVal := ptrSlice.Elem()
sliceType := sliceVal.Type()
if sliceType.Kind() != reflect.Slice {
return fmt.Errorf("cannot assign to pointer to non-slice")
}
switch src.status {
case Present:
slice := reflect.MakeSlice(sliceType, len(src.elements), len(src.elements))
elemType := sliceType.Elem()
for i := range src.elements {
ptrElem := reflect.New(elemType)
err := src.elements[i].AssignTo(ptrElem.Interface())
if err != nil {
return err
}
slice.Index(i).Set(ptrElem.Elem())
}
sliceVal.Set(slice)
return nil
case Null:
sliceVal.Set(reflect.Zero(sliceType))
return nil
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *ArrayType) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
dst.setNil()
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []ValueTranscoder
if len(uta.Elements) > 0 {
elements = make([]ValueTranscoder, len(uta.Elements))
for i, s := range uta.Elements {
elem := dst.newElement()
var elemSrc []byte
if s != "NULL" {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
dst.elements = elements
dst.dimensions = uta.Dimensions
dst.status = Present
return nil
}
func (dst *ArrayType) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
dst.setNil()
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
var elements []ValueTranscoder
if len(arrayHeader.Dimensions) == 0 {
dst.elements = elements
dst.dimensions = arrayHeader.Dimensions
dst.status = Present
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements = make([]ValueTranscoder, elementCount)
for i := range elements {
elem := dst.newElement()
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elem.DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
dst.elements = elements
dst.dimensions = arrayHeader.Dimensions
dst.status = Present
return nil
}
func (src ArrayType) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.dimensions))
dimElemCounts[len(src.dimensions)-1] = int(src.dimensions[len(src.dimensions)-1].Length)
for i := len(src.dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src ArrayType) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.dimensions,
ElementOID: int32(src.elementOID),
}
for i := range src.elements {
if src.elements[i].Get() == nil {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *ArrayType) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src ArrayType) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,45 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
type Bit Varbit
func (dst *Bit) Set(src interface{}) error {
return (*Varbit)(dst).Set(src)
}
func (dst Bit) Get() interface{} {
return (Varbit)(dst).Get()
}
func (src *Bit) AssignTo(dst interface{}) error {
return (*Varbit)(src).AssignTo(dst)
}
func (dst *Bit) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Varbit)(dst).DecodeBinary(ci, src)
}
func (src Bit) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Varbit)(src).EncodeBinary(ci, buf)
}
func (dst *Bit) DecodeText(ci *ConnInfo, src []byte) error {
return (*Varbit)(dst).DecodeText(ci, src)
}
func (src Bit) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Varbit)(src).EncodeText(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *Bit) Scan(src interface{}) error {
return (*Varbit)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Bit) Value() (driver.Value, error) {
return (Varbit)(src).Value()
}

View file

@ -1,217 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/json"
"fmt"
"strconv"
)
type Bool struct {
Bool bool
Status Status
}
func (dst *Bool) Set(src interface{}) error {
if src == nil {
*dst = Bool{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case bool:
*dst = Bool{Bool: value, Status: Present}
case string:
bb, err := strconv.ParseBool(value)
if err != nil {
return err
}
*dst = Bool{Bool: bb, Status: Present}
case *bool:
if value == nil {
*dst = Bool{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Bool{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingBoolType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Bool", value)
}
return nil
}
func (dst Bool) Get() interface{} {
switch dst.Status {
case Present:
return dst.Bool
case Null:
return nil
default:
return dst.Status
}
}
func (src *Bool) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *bool:
*v = src.Bool
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Bool) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Bool{Status: Null}
return nil
}
if len(src) != 1 {
return fmt.Errorf("invalid length for bool: %v", len(src))
}
*dst = Bool{Bool: src[0] == 't', Status: Present}
return nil
}
func (dst *Bool) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Bool{Status: Null}
return nil
}
if len(src) != 1 {
return fmt.Errorf("invalid length for bool: %v", len(src))
}
*dst = Bool{Bool: src[0] == 1, Status: Present}
return nil
}
func (src Bool) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.Bool {
buf = append(buf, 't')
} else {
buf = append(buf, 'f')
}
return buf, nil
}
func (src Bool) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.Bool {
buf = append(buf, 1)
} else {
buf = append(buf, 0)
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Bool) Scan(src interface{}) error {
if src == nil {
*dst = Bool{Status: Null}
return nil
}
switch src := src.(type) {
case bool:
*dst = Bool{Bool: src, Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Bool) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.Bool, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Bool) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
if src.Bool {
return []byte("true"), nil
} else {
return []byte("false"), nil
}
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Bool) UnmarshalJSON(b []byte) error {
var v *bool
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
if v == nil {
*dst = Bool{Status: Null}
} else {
*dst = Bool{Bool: *v, Status: Present}
}
return nil
}

View file

@ -1,517 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type BoolArray struct {
Elements []Bool
Dimensions []ArrayDimension
Status Status
}
func (dst *BoolArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = BoolArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []bool:
if value == nil {
*dst = BoolArray{Status: Null}
} else if len(value) == 0 {
*dst = BoolArray{Status: Present}
} else {
elements := make([]Bool, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = BoolArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*bool:
if value == nil {
*dst = BoolArray{Status: Null}
} else if len(value) == 0 {
*dst = BoolArray{Status: Present}
} else {
elements := make([]Bool, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = BoolArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Bool:
if value == nil {
*dst = BoolArray{Status: Null}
} else if len(value) == 0 {
*dst = BoolArray{Status: Present}
} else {
*dst = BoolArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = BoolArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for BoolArray", src)
}
if elementsLength == 0 {
*dst = BoolArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to BoolArray", src)
}
*dst = BoolArray{
Elements: make([]Bool, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Bool, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to BoolArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *BoolArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to BoolArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in BoolArray", err)
}
index++
return index, nil
}
func (dst BoolArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *BoolArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]bool:
*v = make([]bool, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*bool:
*v = make([]*bool, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *BoolArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from BoolArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from BoolArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *BoolArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = BoolArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Bool
if len(uta.Elements) > 0 {
elements = make([]Bool, len(uta.Elements))
for i, s := range uta.Elements {
var elem Bool
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = BoolArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *BoolArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = BoolArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = BoolArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Bool, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = BoolArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src BoolArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src BoolArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("bool"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "bool")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *BoolArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src BoolArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

165
vendor/github.com/jackc/pgtype/box.go generated vendored
View file

@ -1,165 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Box struct {
P [2]Vec2
Status Status
}
func (dst *Box) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to Box", src)
}
func (dst Box) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Box) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Box) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Box{Status: Null}
return nil
}
if len(src) < 11 {
return fmt.Errorf("invalid length for Box: %v", len(src))
}
str := string(src[1:])
var end int
end = strings.IndexByte(str, ',')
x1, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1:]
end = strings.IndexByte(str, ')')
y1, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+3:]
end = strings.IndexByte(str, ',')
x2, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1 : len(str)-1]
y2, err := strconv.ParseFloat(str, 64)
if err != nil {
return err
}
*dst = Box{P: [2]Vec2{{x1, y1}, {x2, y2}}, Status: Present}
return nil
}
func (dst *Box) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Box{Status: Null}
return nil
}
if len(src) != 32 {
return fmt.Errorf("invalid length for Box: %v", len(src))
}
x1 := binary.BigEndian.Uint64(src)
y1 := binary.BigEndian.Uint64(src[8:])
x2 := binary.BigEndian.Uint64(src[16:])
y2 := binary.BigEndian.Uint64(src[24:])
*dst = Box{
P: [2]Vec2{
{math.Float64frombits(x1), math.Float64frombits(y1)},
{math.Float64frombits(x2), math.Float64frombits(y2)},
},
Status: Present,
}
return nil
}
func (src Box) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, fmt.Sprintf(`(%s,%s),(%s,%s)`,
strconv.FormatFloat(src.P[0].X, 'f', -1, 64),
strconv.FormatFloat(src.P[0].Y, 'f', -1, 64),
strconv.FormatFloat(src.P[1].X, 'f', -1, 64),
strconv.FormatFloat(src.P[1].Y, 'f', -1, 64),
)...)
return buf, nil
}
func (src Box) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].Y))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].Y))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Box) Scan(src interface{}) error {
if src == nil {
*dst = Box{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Box) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,93 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
)
// BPChar is fixed-length, blank padded char type
// character(n), char(n)
type BPChar Text
// Set converts from src to dst.
func (dst *BPChar) Set(src interface{}) error {
return (*Text)(dst).Set(src)
}
// Get returns underlying value
func (dst BPChar) Get() interface{} {
return (Text)(dst).Get()
}
// AssignTo assigns from src to dst.
func (src *BPChar) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *rune:
runes := []rune(src.String)
if len(runes) == 1 {
*v = runes[0]
return nil
}
case *string:
*v = src.String
return nil
case *[]byte:
*v = make([]byte, len(src.String))
copy(*v, src.String)
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (BPChar) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *BPChar) DecodeText(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeText(ci, src)
}
func (dst *BPChar) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeBinary(ci, src)
}
func (BPChar) PreferredParamFormat() int16 {
return TextFormatCode
}
func (src BPChar) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeText(ci, buf)
}
func (src BPChar) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *BPChar) Scan(src interface{}) error {
return (*Text)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src BPChar) Value() (driver.Value, error) {
return (Text)(src).Value()
}
func (src BPChar) MarshalJSON() ([]byte, error) {
return (Text)(src).MarshalJSON()
}
func (dst *BPChar) UnmarshalJSON(b []byte) error {
return (*Text)(dst).UnmarshalJSON(b)
}

View file

@ -1,517 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type BPCharArray struct {
Elements []BPChar
Dimensions []ArrayDimension
Status Status
}
func (dst *BPCharArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = BPCharArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = BPCharArray{Status: Null}
} else if len(value) == 0 {
*dst = BPCharArray{Status: Present}
} else {
elements := make([]BPChar, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = BPCharArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*string:
if value == nil {
*dst = BPCharArray{Status: Null}
} else if len(value) == 0 {
*dst = BPCharArray{Status: Present}
} else {
elements := make([]BPChar, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = BPCharArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []BPChar:
if value == nil {
*dst = BPCharArray{Status: Null}
} else if len(value) == 0 {
*dst = BPCharArray{Status: Present}
} else {
*dst = BPCharArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = BPCharArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for BPCharArray", src)
}
if elementsLength == 0 {
*dst = BPCharArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to BPCharArray", src)
}
*dst = BPCharArray{
Elements: make([]BPChar, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]BPChar, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to BPCharArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *BPCharArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to BPCharArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in BPCharArray", err)
}
index++
return index, nil
}
func (dst BPCharArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *BPCharArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*string:
*v = make([]*string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *BPCharArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from BPCharArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from BPCharArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *BPCharArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = BPCharArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []BPChar
if len(uta.Elements) > 0 {
elements = make([]BPChar, len(uta.Elements))
for i, s := range uta.Elements {
var elem BPChar
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = BPCharArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *BPCharArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = BPCharArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = BPCharArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]BPChar, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = BPCharArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src BPCharArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src BPCharArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("bpchar"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "bpchar")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *BPCharArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src BPCharArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,163 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/hex"
"fmt"
)
type Bytea struct {
Bytes []byte
Status Status
}
func (dst *Bytea) Set(src interface{}) error {
if src == nil {
*dst = Bytea{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case []byte:
if value != nil {
*dst = Bytea{Bytes: value, Status: Present}
} else {
*dst = Bytea{Status: Null}
}
default:
if originalSrc, ok := underlyingBytesType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Bytea", value)
}
return nil
}
func (dst Bytea) Get() interface{} {
switch dst.Status {
case Present:
return dst.Bytes
case Null:
return nil
default:
return dst.Status
}
}
func (src *Bytea) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *[]byte:
buf := make([]byte, len(src.Bytes))
copy(buf, src.Bytes)
*v = buf
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
// DecodeText only supports the hex format. This has been the default since
// PostgreSQL 9.0.
func (dst *Bytea) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Bytea{Status: Null}
return nil
}
if len(src) < 2 || src[0] != '\\' || src[1] != 'x' {
return fmt.Errorf("invalid hex format")
}
buf := make([]byte, (len(src)-2)/2)
_, err := hex.Decode(buf, src[2:])
if err != nil {
return err
}
*dst = Bytea{Bytes: buf, Status: Present}
return nil
}
func (dst *Bytea) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Bytea{Status: Null}
return nil
}
*dst = Bytea{Bytes: src, Status: Present}
return nil
}
func (src Bytea) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, `\x`...)
buf = append(buf, hex.EncodeToString(src.Bytes)...)
return buf, nil
}
func (src Bytea) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.Bytes...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Bytea) Scan(src interface{}) error {
if src == nil {
*dst = Bytea{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
buf := make([]byte, len(src))
copy(buf, src)
*dst = Bytea{Bytes: buf, Status: Present}
return nil
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Bytea) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.Bytes, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,489 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type ByteaArray struct {
Elements []Bytea
Dimensions []ArrayDimension
Status Status
}
func (dst *ByteaArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = ByteaArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case [][]byte:
if value == nil {
*dst = ByteaArray{Status: Null}
} else if len(value) == 0 {
*dst = ByteaArray{Status: Present}
} else {
elements := make([]Bytea, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = ByteaArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Bytea:
if value == nil {
*dst = ByteaArray{Status: Null}
} else if len(value) == 0 {
*dst = ByteaArray{Status: Present}
} else {
*dst = ByteaArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = ByteaArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for ByteaArray", src)
}
if elementsLength == 0 {
*dst = ByteaArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to ByteaArray", src)
}
*dst = ByteaArray{
Elements: make([]Bytea, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Bytea, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to ByteaArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *ByteaArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to ByteaArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in ByteaArray", err)
}
index++
return index, nil
}
func (dst ByteaArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *ByteaArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[][]byte:
*v = make([][]byte, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *ByteaArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from ByteaArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from ByteaArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *ByteaArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = ByteaArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Bytea
if len(uta.Elements) > 0 {
elements = make([]Bytea, len(uta.Elements))
for i, s := range uta.Elements {
var elem Bytea
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = ByteaArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *ByteaArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = ByteaArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = ByteaArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Bytea, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = ByteaArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src ByteaArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src ByteaArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("bytea"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "bytea")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *ByteaArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src ByteaArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,61 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
// CID is PostgreSQL's Command Identifier type.
//
// When one does
//
// select cmin, cmax, * from some_table;
//
// it is the data type of the cmin and cmax hidden system columns.
//
// It is currently implemented as an unsigned four byte integer.
// Its definition can be found in src/include/c.h as CommandId
// in the PostgreSQL sources.
type CID pguint32
// Set converts from src to dst. Note that as CID is not a general
// number type Set does not do automatic type conversion as other number
// types do.
func (dst *CID) Set(src interface{}) error {
return (*pguint32)(dst).Set(src)
}
func (dst CID) Get() interface{} {
return (pguint32)(dst).Get()
}
// AssignTo assigns from src to dst. Note that as CID is not a general number
// type AssignTo does not do automatic type conversion as other number types do.
func (src *CID) AssignTo(dst interface{}) error {
return (*pguint32)(src).AssignTo(dst)
}
func (dst *CID) DecodeText(ci *ConnInfo, src []byte) error {
return (*pguint32)(dst).DecodeText(ci, src)
}
func (dst *CID) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*pguint32)(dst).DecodeBinary(ci, src)
}
func (src CID) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (pguint32)(src).EncodeText(ci, buf)
}
func (src CID) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (pguint32)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *CID) Scan(src interface{}) error {
return (*pguint32)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src CID) Value() (driver.Value, error) {
return (pguint32)(src).Value()
}

View file

@ -1,43 +0,0 @@
package pgtype
import "database/sql/driver"
type CIDR Inet
func (dst *CIDR) Set(src interface{}) error {
return (*Inet)(dst).Set(src)
}
func (dst CIDR) Get() interface{} {
return (Inet)(dst).Get()
}
func (src *CIDR) AssignTo(dst interface{}) error {
return (*Inet)(src).AssignTo(dst)
}
func (dst *CIDR) DecodeText(ci *ConnInfo, src []byte) error {
return (*Inet)(dst).DecodeText(ci, src)
}
func (dst *CIDR) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Inet)(dst).DecodeBinary(ci, src)
}
func (src CIDR) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Inet)(src).EncodeText(ci, buf)
}
func (src CIDR) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Inet)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *CIDR) Scan(src interface{}) error {
return (*Inet)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src CIDR) Value() (driver.Value, error) {
return (Inet)(src).Value()
}

View file

@ -1,546 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"net"
"reflect"
"github.com/jackc/pgio"
)
type CIDRArray struct {
Elements []CIDR
Dimensions []ArrayDimension
Status Status
}
func (dst *CIDRArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = CIDRArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []*net.IPNet:
if value == nil {
*dst = CIDRArray{Status: Null}
} else if len(value) == 0 {
*dst = CIDRArray{Status: Present}
} else {
elements := make([]CIDR, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = CIDRArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []net.IP:
if value == nil {
*dst = CIDRArray{Status: Null}
} else if len(value) == 0 {
*dst = CIDRArray{Status: Present}
} else {
elements := make([]CIDR, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = CIDRArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*net.IP:
if value == nil {
*dst = CIDRArray{Status: Null}
} else if len(value) == 0 {
*dst = CIDRArray{Status: Present}
} else {
elements := make([]CIDR, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = CIDRArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []CIDR:
if value == nil {
*dst = CIDRArray{Status: Null}
} else if len(value) == 0 {
*dst = CIDRArray{Status: Present}
} else {
*dst = CIDRArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = CIDRArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for CIDRArray", src)
}
if elementsLength == 0 {
*dst = CIDRArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to CIDRArray", src)
}
*dst = CIDRArray{
Elements: make([]CIDR, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]CIDR, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to CIDRArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *CIDRArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to CIDRArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in CIDRArray", err)
}
index++
return index, nil
}
func (dst CIDRArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *CIDRArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]*net.IPNet:
*v = make([]*net.IPNet, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]net.IP:
*v = make([]net.IP, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*net.IP:
*v = make([]*net.IP, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *CIDRArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from CIDRArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from CIDRArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *CIDRArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = CIDRArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []CIDR
if len(uta.Elements) > 0 {
elements = make([]CIDR, len(uta.Elements))
for i, s := range uta.Elements {
var elem CIDR
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = CIDRArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *CIDRArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = CIDRArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = CIDRArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]CIDR, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = CIDRArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src CIDRArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src CIDRArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("cidr"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "cidr")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *CIDRArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src CIDRArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,150 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Circle struct {
P Vec2
R float64
Status Status
}
func (dst *Circle) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to Circle", src)
}
func (dst Circle) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Circle) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Circle) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Circle{Status: Null}
return nil
}
if len(src) < 9 {
return fmt.Errorf("invalid length for Circle: %v", len(src))
}
str := string(src[2:])
end := strings.IndexByte(str, ',')
x, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1:]
end = strings.IndexByte(str, ')')
y, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+2 : len(str)-1]
r, err := strconv.ParseFloat(str, 64)
if err != nil {
return err
}
*dst = Circle{P: Vec2{x, y}, R: r, Status: Present}
return nil
}
func (dst *Circle) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Circle{Status: Null}
return nil
}
if len(src) != 24 {
return fmt.Errorf("invalid length for Circle: %v", len(src))
}
x := binary.BigEndian.Uint64(src)
y := binary.BigEndian.Uint64(src[8:])
r := binary.BigEndian.Uint64(src[16:])
*dst = Circle{
P: Vec2{math.Float64frombits(x), math.Float64frombits(y)},
R: math.Float64frombits(r),
Status: Present,
}
return nil
}
func (src Circle) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, fmt.Sprintf(`<(%s,%s),%s>`,
strconv.FormatFloat(src.P.X, 'f', -1, 64),
strconv.FormatFloat(src.P.Y, 'f', -1, 64),
strconv.FormatFloat(src.R, 'f', -1, 64),
)...)
return buf, nil
}
func (src Circle) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.P.X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P.Y))
buf = pgio.AppendUint64(buf, math.Float64bits(src.R))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Circle) Scan(src interface{}) error {
if src == nil {
*dst = Circle{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Circle) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,107 +0,0 @@
package pgtype
import "fmt"
// CompositeFields scans the fields of a composite type into the elements of the CompositeFields value. To scan a
// nullable value use a *CompositeFields. It will be set to nil in case of null.
//
// CompositeFields implements EncodeBinary and EncodeText. However, functionality is limited due to CompositeFields not
// knowing the PostgreSQL schema of the composite type. Prefer using a registered CompositeType.
type CompositeFields []interface{}
func (cf CompositeFields) DecodeBinary(ci *ConnInfo, src []byte) error {
if len(cf) == 0 {
return fmt.Errorf("cannot decode into empty CompositeFields")
}
if src == nil {
return fmt.Errorf("cannot decode unexpected null into CompositeFields")
}
scanner := NewCompositeBinaryScanner(ci, src)
for _, f := range cf {
scanner.ScanValue(f)
}
if scanner.Err() != nil {
return scanner.Err()
}
return nil
}
func (cf CompositeFields) DecodeText(ci *ConnInfo, src []byte) error {
if len(cf) == 0 {
return fmt.Errorf("cannot decode into empty CompositeFields")
}
if src == nil {
return fmt.Errorf("cannot decode unexpected null into CompositeFields")
}
scanner := NewCompositeTextScanner(ci, src)
for _, f := range cf {
scanner.ScanValue(f)
}
if scanner.Err() != nil {
return scanner.Err()
}
return nil
}
// EncodeText encodes composite fields into the text format. Prefer registering a CompositeType to using
// CompositeFields to encode directly.
func (cf CompositeFields) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
b := NewCompositeTextBuilder(ci, buf)
for _, f := range cf {
if textEncoder, ok := f.(TextEncoder); ok {
b.AppendEncoder(textEncoder)
} else {
b.AppendValue(f)
}
}
return b.Finish()
}
// EncodeBinary encodes composite fields into the binary format. Unlike CompositeType the schema of the destination is
// unknown. Prefer registering a CompositeType to using CompositeFields to encode directly. Because the binary
// composite format requires the OID of each field to be specified the only types that will work are those known to
// ConnInfo.
//
// In particular:
//
// * Nil cannot be used because there is no way to determine what type it.
// * Integer types must be exact matches. e.g. A Go int32 into a PostgreSQL bigint will fail.
// * No dereferencing will be done. e.g. *Text must be used instead of Text.
func (cf CompositeFields) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
b := NewCompositeBinaryBuilder(ci, buf)
for _, f := range cf {
dt, ok := ci.DataTypeForValue(f)
if !ok {
return nil, fmt.Errorf("Unknown OID for %#v", f)
}
if binaryEncoder, ok := f.(BinaryEncoder); ok {
b.AppendEncoder(dt.OID, binaryEncoder)
} else {
err := dt.Value.Set(f)
if err != nil {
return nil, err
}
if binaryEncoder, ok := dt.Value.(BinaryEncoder); ok {
b.AppendEncoder(dt.OID, binaryEncoder)
} else {
return nil, fmt.Errorf("Cannot encode binary format for %v", f)
}
}
}
return b.Finish()
}

View file

@ -1,682 +0,0 @@
package pgtype
import (
"encoding/binary"
"errors"
"fmt"
"reflect"
"strings"
"github.com/jackc/pgio"
)
type CompositeTypeField struct {
Name string
OID uint32
}
type CompositeType struct {
status Status
typeName string
fields []CompositeTypeField
valueTranscoders []ValueTranscoder
}
// NewCompositeType creates a CompositeType from fields and ci. ci is used to find the ValueTranscoders used
// for fields. All field OIDs must be previously registered in ci.
func NewCompositeType(typeName string, fields []CompositeTypeField, ci *ConnInfo) (*CompositeType, error) {
valueTranscoders := make([]ValueTranscoder, len(fields))
for i := range fields {
dt, ok := ci.DataTypeForOID(fields[i].OID)
if !ok {
return nil, fmt.Errorf("no data type registered for oid: %d", fields[i].OID)
}
value := NewValue(dt.Value)
valueTranscoder, ok := value.(ValueTranscoder)
if !ok {
return nil, fmt.Errorf("data type for oid does not implement ValueTranscoder: %d", fields[i].OID)
}
valueTranscoders[i] = valueTranscoder
}
return &CompositeType{typeName: typeName, fields: fields, valueTranscoders: valueTranscoders}, nil
}
// NewCompositeTypeValues creates a CompositeType from fields and values. fields and values must have the same length.
// Prefer NewCompositeType unless overriding the transcoding of fields is required.
func NewCompositeTypeValues(typeName string, fields []CompositeTypeField, values []ValueTranscoder) (*CompositeType, error) {
if len(fields) != len(values) {
return nil, errors.New("fields and valueTranscoders must have same length")
}
return &CompositeType{typeName: typeName, fields: fields, valueTranscoders: values}, nil
}
func (src CompositeType) Get() interface{} {
switch src.status {
case Present:
results := make(map[string]interface{}, len(src.valueTranscoders))
for i := range src.valueTranscoders {
results[src.fields[i].Name] = src.valueTranscoders[i].Get()
}
return results
case Null:
return nil
default:
return src.status
}
}
func (ct *CompositeType) NewTypeValue() Value {
a := &CompositeType{
typeName: ct.typeName,
fields: ct.fields,
valueTranscoders: make([]ValueTranscoder, len(ct.valueTranscoders)),
}
for i := range ct.valueTranscoders {
a.valueTranscoders[i] = NewValue(ct.valueTranscoders[i]).(ValueTranscoder)
}
return a
}
func (ct *CompositeType) TypeName() string {
return ct.typeName
}
func (ct *CompositeType) Fields() []CompositeTypeField {
return ct.fields
}
func (dst *CompositeType) Set(src interface{}) error {
if src == nil {
dst.status = Null
return nil
}
switch value := src.(type) {
case []interface{}:
if len(value) != len(dst.valueTranscoders) {
return fmt.Errorf("Number of fields don't match. CompositeType has %d fields", len(dst.valueTranscoders))
}
for i, v := range value {
if err := dst.valueTranscoders[i].Set(v); err != nil {
return err
}
}
dst.status = Present
case *[]interface{}:
if value == nil {
dst.status = Null
return nil
}
return dst.Set(*value)
default:
return fmt.Errorf("Can not convert %v to Composite", src)
}
return nil
}
// AssignTo should never be called on composite value directly
func (src CompositeType) AssignTo(dst interface{}) error {
switch src.status {
case Present:
switch v := dst.(type) {
case []interface{}:
if len(v) != len(src.valueTranscoders) {
return fmt.Errorf("Number of fields don't match. CompositeType has %d fields", len(src.valueTranscoders))
}
for i := range src.valueTranscoders {
if v[i] == nil {
continue
}
err := assignToOrSet(src.valueTranscoders[i], v[i])
if err != nil {
return fmt.Errorf("unable to assign to dst[%d]: %v", i, err)
}
}
return nil
case *[]interface{}:
return src.AssignTo(*v)
default:
if isPtrStruct, err := src.assignToPtrStruct(dst); isPtrStruct {
return err
}
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func assignToOrSet(src Value, dst interface{}) error {
assignToErr := src.AssignTo(dst)
if assignToErr != nil {
// Try to use get / set instead -- this avoids every type having to be able to AssignTo type of self.
setSucceeded := false
if setter, ok := dst.(Value); ok {
err := setter.Set(src.Get())
setSucceeded = err == nil
}
if !setSucceeded {
return assignToErr
}
}
return nil
}
func (src CompositeType) assignToPtrStruct(dst interface{}) (bool, error) {
dstValue := reflect.ValueOf(dst)
if dstValue.Kind() != reflect.Ptr {
return false, nil
}
if dstValue.IsNil() {
return false, nil
}
dstElemValue := dstValue.Elem()
dstElemType := dstElemValue.Type()
if dstElemType.Kind() != reflect.Struct {
return false, nil
}
exportedFields := make([]int, 0, dstElemType.NumField())
for i := 0; i < dstElemType.NumField(); i++ {
sf := dstElemType.Field(i)
if sf.PkgPath == "" {
exportedFields = append(exportedFields, i)
}
}
if len(exportedFields) != len(src.valueTranscoders) {
return false, nil
}
for i := range exportedFields {
err := assignToOrSet(src.valueTranscoders[i], dstElemValue.Field(exportedFields[i]).Addr().Interface())
if err != nil {
return true, fmt.Errorf("unable to assign to field %s: %v", dstElemType.Field(exportedFields[i]).Name, err)
}
}
return true, nil
}
func (src CompositeType) EncodeBinary(ci *ConnInfo, buf []byte) (newBuf []byte, err error) {
switch src.status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
b := NewCompositeBinaryBuilder(ci, buf)
for i := range src.valueTranscoders {
b.AppendEncoder(src.fields[i].OID, src.valueTranscoders[i])
}
return b.Finish()
}
// DecodeBinary implements BinaryDecoder interface.
// Opposite to Record, fields in a composite act as a "schema"
// and decoding fails if SQL value can't be assigned due to
// type mismatch
func (dst *CompositeType) DecodeBinary(ci *ConnInfo, buf []byte) error {
if buf == nil {
dst.status = Null
return nil
}
scanner := NewCompositeBinaryScanner(ci, buf)
for _, f := range dst.valueTranscoders {
scanner.ScanDecoder(f)
}
if scanner.Err() != nil {
return scanner.Err()
}
dst.status = Present
return nil
}
func (dst *CompositeType) DecodeText(ci *ConnInfo, buf []byte) error {
if buf == nil {
dst.status = Null
return nil
}
scanner := NewCompositeTextScanner(ci, buf)
for _, f := range dst.valueTranscoders {
scanner.ScanDecoder(f)
}
if scanner.Err() != nil {
return scanner.Err()
}
dst.status = Present
return nil
}
func (src CompositeType) EncodeText(ci *ConnInfo, buf []byte) (newBuf []byte, err error) {
switch src.status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
b := NewCompositeTextBuilder(ci, buf)
for _, f := range src.valueTranscoders {
b.AppendEncoder(f)
}
return b.Finish()
}
type CompositeBinaryScanner struct {
ci *ConnInfo
rp int
src []byte
fieldCount int32
fieldBytes []byte
fieldOID uint32
err error
}
// NewCompositeBinaryScanner a scanner over a binary encoded composite balue.
func NewCompositeBinaryScanner(ci *ConnInfo, src []byte) *CompositeBinaryScanner {
rp := 0
if len(src[rp:]) < 4 {
return &CompositeBinaryScanner{err: fmt.Errorf("Record incomplete %v", src)}
}
fieldCount := int32(binary.BigEndian.Uint32(src[rp:]))
rp += 4
return &CompositeBinaryScanner{
ci: ci,
rp: rp,
src: src,
fieldCount: fieldCount,
}
}
// ScanDecoder calls Next and decodes the result with d.
func (cfs *CompositeBinaryScanner) ScanDecoder(d BinaryDecoder) {
if cfs.err != nil {
return
}
if cfs.Next() {
cfs.err = d.DecodeBinary(cfs.ci, cfs.fieldBytes)
} else {
cfs.err = errors.New("read past end of composite")
}
}
// ScanDecoder calls Next and scans the result into d.
func (cfs *CompositeBinaryScanner) ScanValue(d interface{}) {
if cfs.err != nil {
return
}
if cfs.Next() {
cfs.err = cfs.ci.Scan(cfs.OID(), BinaryFormatCode, cfs.Bytes(), d)
} else {
cfs.err = errors.New("read past end of composite")
}
}
// Next advances the scanner to the next field. It returns false after the last field is read or an error occurs. After
// Next returns false, the Err method can be called to check if any errors occurred.
func (cfs *CompositeBinaryScanner) Next() bool {
if cfs.err != nil {
return false
}
if cfs.rp == len(cfs.src) {
return false
}
if len(cfs.src[cfs.rp:]) < 8 {
cfs.err = fmt.Errorf("Record incomplete %v", cfs.src)
return false
}
cfs.fieldOID = binary.BigEndian.Uint32(cfs.src[cfs.rp:])
cfs.rp += 4
fieldLen := int(int32(binary.BigEndian.Uint32(cfs.src[cfs.rp:])))
cfs.rp += 4
if fieldLen >= 0 {
if len(cfs.src[cfs.rp:]) < fieldLen {
cfs.err = fmt.Errorf("Record incomplete rp=%d src=%v", cfs.rp, cfs.src)
return false
}
cfs.fieldBytes = cfs.src[cfs.rp : cfs.rp+fieldLen]
cfs.rp += fieldLen
} else {
cfs.fieldBytes = nil
}
return true
}
func (cfs *CompositeBinaryScanner) FieldCount() int {
return int(cfs.fieldCount)
}
// Bytes returns the bytes of the field most recently read by Scan().
func (cfs *CompositeBinaryScanner) Bytes() []byte {
return cfs.fieldBytes
}
// OID returns the OID of the field most recently read by Scan().
func (cfs *CompositeBinaryScanner) OID() uint32 {
return cfs.fieldOID
}
// Err returns any error encountered by the scanner.
func (cfs *CompositeBinaryScanner) Err() error {
return cfs.err
}
type CompositeTextScanner struct {
ci *ConnInfo
rp int
src []byte
fieldBytes []byte
err error
}
// NewCompositeTextScanner a scanner over a text encoded composite value.
func NewCompositeTextScanner(ci *ConnInfo, src []byte) *CompositeTextScanner {
if len(src) < 2 {
return &CompositeTextScanner{err: fmt.Errorf("Record incomplete %v", src)}
}
if src[0] != '(' {
return &CompositeTextScanner{err: fmt.Errorf("composite text format must start with '('")}
}
if src[len(src)-1] != ')' {
return &CompositeTextScanner{err: fmt.Errorf("composite text format must end with ')'")}
}
return &CompositeTextScanner{
ci: ci,
rp: 1,
src: src,
}
}
// ScanDecoder calls Next and decodes the result with d.
func (cfs *CompositeTextScanner) ScanDecoder(d TextDecoder) {
if cfs.err != nil {
return
}
if cfs.Next() {
cfs.err = d.DecodeText(cfs.ci, cfs.fieldBytes)
} else {
cfs.err = errors.New("read past end of composite")
}
}
// ScanDecoder calls Next and scans the result into d.
func (cfs *CompositeTextScanner) ScanValue(d interface{}) {
if cfs.err != nil {
return
}
if cfs.Next() {
cfs.err = cfs.ci.Scan(0, TextFormatCode, cfs.Bytes(), d)
} else {
cfs.err = errors.New("read past end of composite")
}
}
// Next advances the scanner to the next field. It returns false after the last field is read or an error occurs. After
// Next returns false, the Err method can be called to check if any errors occurred.
func (cfs *CompositeTextScanner) Next() bool {
if cfs.err != nil {
return false
}
if cfs.rp == len(cfs.src) {
return false
}
switch cfs.src[cfs.rp] {
case ',', ')': // null
cfs.rp++
cfs.fieldBytes = nil
return true
case '"': // quoted value
cfs.rp++
cfs.fieldBytes = make([]byte, 0, 16)
for {
ch := cfs.src[cfs.rp]
if ch == '"' {
cfs.rp++
if cfs.src[cfs.rp] == '"' {
cfs.fieldBytes = append(cfs.fieldBytes, '"')
cfs.rp++
} else {
break
}
} else if ch == '\\' {
cfs.rp++
cfs.fieldBytes = append(cfs.fieldBytes, cfs.src[cfs.rp])
cfs.rp++
} else {
cfs.fieldBytes = append(cfs.fieldBytes, ch)
cfs.rp++
}
}
cfs.rp++
return true
default: // unquoted value
start := cfs.rp
for {
ch := cfs.src[cfs.rp]
if ch == ',' || ch == ')' {
break
}
cfs.rp++
}
cfs.fieldBytes = cfs.src[start:cfs.rp]
cfs.rp++
return true
}
}
// Bytes returns the bytes of the field most recently read by Scan().
func (cfs *CompositeTextScanner) Bytes() []byte {
return cfs.fieldBytes
}
// Err returns any error encountered by the scanner.
func (cfs *CompositeTextScanner) Err() error {
return cfs.err
}
type CompositeBinaryBuilder struct {
ci *ConnInfo
buf []byte
startIdx int
fieldCount uint32
err error
}
func NewCompositeBinaryBuilder(ci *ConnInfo, buf []byte) *CompositeBinaryBuilder {
startIdx := len(buf)
buf = append(buf, 0, 0, 0, 0) // allocate room for number of fields
return &CompositeBinaryBuilder{ci: ci, buf: buf, startIdx: startIdx}
}
func (b *CompositeBinaryBuilder) AppendValue(oid uint32, field interface{}) {
if b.err != nil {
return
}
dt, ok := b.ci.DataTypeForOID(oid)
if !ok {
b.err = fmt.Errorf("unknown data type for OID: %d", oid)
return
}
err := dt.Value.Set(field)
if err != nil {
b.err = err
return
}
binaryEncoder, ok := dt.Value.(BinaryEncoder)
if !ok {
b.err = fmt.Errorf("unable to encode binary for OID: %d", oid)
return
}
b.AppendEncoder(oid, binaryEncoder)
}
func (b *CompositeBinaryBuilder) AppendEncoder(oid uint32, field BinaryEncoder) {
if b.err != nil {
return
}
b.buf = pgio.AppendUint32(b.buf, oid)
lengthPos := len(b.buf)
b.buf = pgio.AppendInt32(b.buf, -1)
fieldBuf, err := field.EncodeBinary(b.ci, b.buf)
if err != nil {
b.err = err
return
}
if fieldBuf != nil {
binary.BigEndian.PutUint32(fieldBuf[lengthPos:], uint32(len(fieldBuf)-len(b.buf)))
b.buf = fieldBuf
}
b.fieldCount++
}
func (b *CompositeBinaryBuilder) Finish() ([]byte, error) {
if b.err != nil {
return nil, b.err
}
binary.BigEndian.PutUint32(b.buf[b.startIdx:], b.fieldCount)
return b.buf, nil
}
type CompositeTextBuilder struct {
ci *ConnInfo
buf []byte
startIdx int
fieldCount uint32
err error
fieldBuf [32]byte
}
func NewCompositeTextBuilder(ci *ConnInfo, buf []byte) *CompositeTextBuilder {
buf = append(buf, '(') // allocate room for number of fields
return &CompositeTextBuilder{ci: ci, buf: buf}
}
func (b *CompositeTextBuilder) AppendValue(field interface{}) {
if b.err != nil {
return
}
if field == nil {
b.buf = append(b.buf, ',')
return
}
dt, ok := b.ci.DataTypeForValue(field)
if !ok {
b.err = fmt.Errorf("unknown data type for field: %v", field)
return
}
err := dt.Value.Set(field)
if err != nil {
b.err = err
return
}
textEncoder, ok := dt.Value.(TextEncoder)
if !ok {
b.err = fmt.Errorf("unable to encode text for value: %v", field)
return
}
b.AppendEncoder(textEncoder)
}
func (b *CompositeTextBuilder) AppendEncoder(field TextEncoder) {
if b.err != nil {
return
}
fieldBuf, err := field.EncodeText(b.ci, b.fieldBuf[0:0])
if err != nil {
b.err = err
return
}
if fieldBuf != nil {
b.buf = append(b.buf, quoteCompositeFieldIfNeeded(string(fieldBuf))...)
}
b.buf = append(b.buf, ',')
}
func (b *CompositeTextBuilder) Finish() ([]byte, error) {
if b.err != nil {
return nil, b.err
}
b.buf[len(b.buf)-1] = ')'
return b.buf, nil
}
var quoteCompositeReplacer = strings.NewReplacer(`\`, `\\`, `"`, `\"`)
func quoteCompositeField(src string) string {
return `"` + quoteCompositeReplacer.Replace(src) + `"`
}
func quoteCompositeFieldIfNeeded(src string) string {
if src == "" || src[0] == ' ' || src[len(src)-1] == ' ' || strings.ContainsAny(src, `(),"\`) {
return quoteCompositeField(src)
}
return src
}

View file

@ -1,41 +0,0 @@
package pgtype
import (
"database/sql/driver"
"errors"
)
func DatabaseSQLValue(ci *ConnInfo, src Value) (interface{}, error) {
if valuer, ok := src.(driver.Valuer); ok {
return valuer.Value()
}
if textEncoder, ok := src.(TextEncoder); ok {
buf, err := textEncoder.EncodeText(ci, nil)
if err != nil {
return nil, err
}
return string(buf), nil
}
if binaryEncoder, ok := src.(BinaryEncoder); ok {
buf, err := binaryEncoder.EncodeBinary(ci, nil)
if err != nil {
return nil, err
}
return buf, nil
}
return nil, errors.New("cannot convert to database/sql compatible value")
}
func EncodeValueText(src TextEncoder) (interface{}, error) {
buf, err := src.EncodeText(nil, make([]byte, 0, 32))
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), err
}

View file

@ -1,324 +0,0 @@
package pgtype
import (
"database/sql"
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/jackc/pgio"
)
type Date struct {
Time time.Time
Status Status
InfinityModifier InfinityModifier
}
const (
negativeInfinityDayOffset = -2147483648
infinityDayOffset = 2147483647
)
func (dst *Date) Set(src interface{}) error {
if src == nil {
*dst = Date{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
if value, ok := src.(interface{ Value() (driver.Value, error) }); ok {
v, err := value.Value()
if err != nil {
return fmt.Errorf("cannot get value %v for Date: %v", value, err)
}
return dst.Set(v)
}
switch value := src.(type) {
case time.Time:
*dst = Date{Time: value, Status: Present}
case *time.Time:
if value == nil {
*dst = Date{Status: Null}
} else {
return dst.Set(*value)
}
case string:
return dst.DecodeText(nil, []byte(value))
case *string:
if value == nil {
*dst = Date{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingTimeType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Date", value)
}
return nil
}
func (dst Date) Get() interface{} {
switch dst.Status {
case Present:
if dst.InfinityModifier != None {
return dst.InfinityModifier
}
return dst.Time
case Null:
return nil
default:
return dst.Status
}
}
func (src *Date) AssignTo(dst interface{}) error {
if scanner, ok := dst.(sql.Scanner); ok {
var err error
switch src.Status {
case Present:
if src.InfinityModifier != None {
err = scanner.Scan(src.InfinityModifier.String())
} else {
err = scanner.Scan(src.Time)
}
case Null:
err = scanner.Scan(nil)
}
if err != nil {
return fmt.Errorf("unable assign %v to %T: %s", src, dst, err)
}
return nil
}
switch src.Status {
case Present:
switch v := dst.(type) {
case *time.Time:
if src.InfinityModifier != None {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
*v = src.Time
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Date) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Date{Status: Null}
return nil
}
sbuf := string(src)
switch sbuf {
case "infinity":
*dst = Date{Status: Present, InfinityModifier: Infinity}
case "-infinity":
*dst = Date{Status: Present, InfinityModifier: -Infinity}
default:
if strings.HasSuffix(sbuf, " BC") {
t, err := time.ParseInLocation("2006-01-02", strings.TrimRight(sbuf, " BC"), time.UTC)
t2 := time.Date(1-t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
if err != nil {
return err
}
*dst = Date{Time: t2, Status: Present}
return nil
}
t, err := time.ParseInLocation("2006-01-02", sbuf, time.UTC)
if err != nil {
return err
}
*dst = Date{Time: t, Status: Present}
}
return nil
}
func (dst *Date) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Date{Status: Null}
return nil
}
if len(src) != 4 {
return fmt.Errorf("invalid length for date: %v", len(src))
}
dayOffset := int32(binary.BigEndian.Uint32(src))
switch dayOffset {
case infinityDayOffset:
*dst = Date{Status: Present, InfinityModifier: Infinity}
case negativeInfinityDayOffset:
*dst = Date{Status: Present, InfinityModifier: -Infinity}
default:
t := time.Date(2000, 1, int(1+dayOffset), 0, 0, 0, 0, time.UTC)
*dst = Date{Time: t, Status: Present}
}
return nil
}
func (src Date) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var s string
switch src.InfinityModifier {
case None:
s = src.Time.Format("2006-01-02")
case Infinity:
s = "infinity"
case NegativeInfinity:
s = "-infinity"
}
return append(buf, s...), nil
}
func (src Date) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var daysSinceDateEpoch int32
switch src.InfinityModifier {
case None:
tUnix := time.Date(src.Time.Year(), src.Time.Month(), src.Time.Day(), 0, 0, 0, 0, time.UTC).Unix()
dateEpoch := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC).Unix()
secSinceDateEpoch := tUnix - dateEpoch
daysSinceDateEpoch = int32(secSinceDateEpoch / 86400)
case Infinity:
daysSinceDateEpoch = infinityDayOffset
case NegativeInfinity:
daysSinceDateEpoch = negativeInfinityDayOffset
}
return pgio.AppendInt32(buf, daysSinceDateEpoch), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Date) Scan(src interface{}) error {
if src == nil {
*dst = Date{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
case time.Time:
*dst = Date{Time: src, Status: Present}
return nil
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Date) Value() (driver.Value, error) {
switch src.Status {
case Present:
if src.InfinityModifier != None {
return src.InfinityModifier.String(), nil
}
return src.Time, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Date) MarshalJSON() ([]byte, error) {
switch src.Status {
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
if src.Status != Present {
return nil, errBadStatus
}
var s string
switch src.InfinityModifier {
case None:
s = src.Time.Format("2006-01-02")
case Infinity:
s = "infinity"
case NegativeInfinity:
s = "-infinity"
}
return json.Marshal(s)
}
func (dst *Date) UnmarshalJSON(b []byte) error {
var s *string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
if s == nil {
*dst = Date{Status: Null}
return nil
}
switch *s {
case "infinity":
*dst = Date{Status: Present, InfinityModifier: Infinity}
case "-infinity":
*dst = Date{Status: Present, InfinityModifier: -Infinity}
default:
t, err := time.ParseInLocation("2006-01-02", *s, time.UTC)
if err != nil {
return err
}
*dst = Date{Time: t, Status: Present}
}
return nil
}

View file

@ -1,518 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"time"
"github.com/jackc/pgio"
)
type DateArray struct {
Elements []Date
Dimensions []ArrayDimension
Status Status
}
func (dst *DateArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = DateArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []time.Time:
if value == nil {
*dst = DateArray{Status: Null}
} else if len(value) == 0 {
*dst = DateArray{Status: Present}
} else {
elements := make([]Date, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = DateArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*time.Time:
if value == nil {
*dst = DateArray{Status: Null}
} else if len(value) == 0 {
*dst = DateArray{Status: Present}
} else {
elements := make([]Date, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = DateArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Date:
if value == nil {
*dst = DateArray{Status: Null}
} else if len(value) == 0 {
*dst = DateArray{Status: Present}
} else {
*dst = DateArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = DateArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for DateArray", src)
}
if elementsLength == 0 {
*dst = DateArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to DateArray", src)
}
*dst = DateArray{
Elements: make([]Date, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Date, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to DateArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *DateArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to DateArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in DateArray", err)
}
index++
return index, nil
}
func (dst DateArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *DateArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]time.Time:
*v = make([]time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*time.Time:
*v = make([]*time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *DateArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from DateArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from DateArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *DateArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = DateArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Date
if len(uta.Elements) > 0 {
elements = make([]Date, len(uta.Elements))
for i, s := range uta.Elements {
var elem Date
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = DateArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *DateArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = DateArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = DateArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Date, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = DateArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src DateArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src DateArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("date"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "date")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *DateArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src DateArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Daterange struct {
Lower Date
Upper Date
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Daterange) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Daterange{Status: Null}
return nil
}
switch value := src.(type) {
case Daterange:
*dst = value
case *Daterange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Daterange", src)
}
return nil
}
func (dst Daterange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Daterange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Daterange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Daterange{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Daterange{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Daterange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Daterange{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Daterange{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Daterange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Daterange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Daterange) Scan(src interface{}) error {
if src == nil {
*dst = Daterange{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Daterange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,428 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"fmt"
"reflect"
)
type EnumArray struct {
Elements []GenericText
Dimensions []ArrayDimension
Status Status
}
func (dst *EnumArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = EnumArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = EnumArray{Status: Null}
} else if len(value) == 0 {
*dst = EnumArray{Status: Present}
} else {
elements := make([]GenericText, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = EnumArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*string:
if value == nil {
*dst = EnumArray{Status: Null}
} else if len(value) == 0 {
*dst = EnumArray{Status: Present}
} else {
elements := make([]GenericText, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = EnumArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []GenericText:
if value == nil {
*dst = EnumArray{Status: Null}
} else if len(value) == 0 {
*dst = EnumArray{Status: Present}
} else {
*dst = EnumArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = EnumArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for EnumArray", src)
}
if elementsLength == 0 {
*dst = EnumArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to EnumArray", src)
}
*dst = EnumArray{
Elements: make([]GenericText, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]GenericText, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to EnumArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *EnumArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to EnumArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in EnumArray", err)
}
index++
return index, nil
}
func (dst EnumArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *EnumArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*string:
*v = make([]*string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *EnumArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from EnumArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from EnumArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *EnumArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = EnumArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []GenericText
if len(uta.Elements) > 0 {
elements = make([]GenericText, len(uta.Elements))
for i, s := range uta.Elements {
var elem GenericText
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = EnumArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (src EnumArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *EnumArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src EnumArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,168 +0,0 @@
package pgtype
import "fmt"
// EnumType represents an enum type. While it implements Value, this is only in service of its type conversion duties
// when registered as a data type in a ConnType. It should not be used directly as a Value.
type EnumType struct {
value string
status Status
typeName string // PostgreSQL type name
members []string // enum members
membersMap map[string]string // map to quickly lookup member and reuse string instead of allocating
}
// NewEnumType initializes a new EnumType. It retains a read-only reference to members. members must not be changed.
func NewEnumType(typeName string, members []string) *EnumType {
et := &EnumType{typeName: typeName, members: members}
et.membersMap = make(map[string]string, len(members))
for _, m := range members {
et.membersMap[m] = m
}
return et
}
func (et *EnumType) NewTypeValue() Value {
return &EnumType{
value: et.value,
status: et.status,
typeName: et.typeName,
members: et.members,
membersMap: et.membersMap,
}
}
func (et *EnumType) TypeName() string {
return et.typeName
}
func (et *EnumType) Members() []string {
return et.members
}
// Set assigns src to dst. Set purposely does not check that src is a member. This allows continued error free
// operation in the event the PostgreSQL enum type is modified during a connection.
func (dst *EnumType) Set(src interface{}) error {
if src == nil {
dst.status = Null
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case string:
dst.value = value
dst.status = Present
case *string:
if value == nil {
dst.status = Null
} else {
dst.value = *value
dst.status = Present
}
case []byte:
if value == nil {
dst.status = Null
} else {
dst.value = string(value)
dst.status = Present
}
default:
if originalSrc, ok := underlyingStringType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to enum %s", value, dst.typeName)
}
return nil
}
func (dst EnumType) Get() interface{} {
switch dst.status {
case Present:
return dst.value
case Null:
return nil
default:
return dst.status
}
}
func (src *EnumType) AssignTo(dst interface{}) error {
switch src.status {
case Present:
switch v := dst.(type) {
case *string:
*v = src.value
return nil
case *[]byte:
*v = make([]byte, len(src.value))
copy(*v, src.value)
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (EnumType) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *EnumType) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
dst.status = Null
return nil
}
// Lookup the string in membersMap to avoid an allocation.
if s, found := dst.membersMap[string(src)]; found {
dst.value = s
} else {
// If an enum type is modified after the initial connection it is possible to receive an unexpected value.
// Gracefully handle this situation. Purposely NOT modifying members and membersMap to allow for sharing members
// and membersMap between connections.
dst.value = string(src)
}
dst.status = Present
return nil
}
func (dst *EnumType) DecodeBinary(ci *ConnInfo, src []byte) error {
return dst.DecodeText(ci, src)
}
func (EnumType) PreferredParamFormat() int16 {
return TextFormatCode
}
func (src EnumType) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.value...), nil
}
func (src EnumType) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return src.EncodeText(ci, buf)
}

View file

@ -1,282 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Float4 struct {
Float float32
Status Status
}
func (dst *Float4) Set(src interface{}) error {
if src == nil {
*dst = Float4{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case float32:
*dst = Float4{Float: value, Status: Present}
case float64:
*dst = Float4{Float: float32(value), Status: Present}
case int8:
*dst = Float4{Float: float32(value), Status: Present}
case uint8:
*dst = Float4{Float: float32(value), Status: Present}
case int16:
*dst = Float4{Float: float32(value), Status: Present}
case uint16:
*dst = Float4{Float: float32(value), Status: Present}
case int32:
f32 := float32(value)
if int32(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case uint32:
f32 := float32(value)
if uint32(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case int64:
f32 := float32(value)
if int64(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case uint64:
f32 := float32(value)
if uint64(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case int:
f32 := float32(value)
if int(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case uint:
f32 := float32(value)
if uint(f32) == value {
*dst = Float4{Float: f32, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float32", value)
}
case string:
num, err := strconv.ParseFloat(value, 32)
if err != nil {
return err
}
*dst = Float4{Float: float32(num), Status: Present}
case *float64:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *int8:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Float4{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Float8", value)
}
return nil
}
func (dst Float4) Get() interface{} {
switch dst.Status {
case Present:
return dst.Float
case Null:
return nil
default:
return dst.Status
}
}
func (src *Float4) AssignTo(dst interface{}) error {
return float64AssignTo(float64(src.Float), src.Status, dst)
}
func (dst *Float4) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float4{Status: Null}
return nil
}
n, err := strconv.ParseFloat(string(src), 32)
if err != nil {
return err
}
*dst = Float4{Float: float32(n), Status: Present}
return nil
}
func (dst *Float4) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float4{Status: Null}
return nil
}
if len(src) != 4 {
return fmt.Errorf("invalid length for float4: %v", len(src))
}
n := int32(binary.BigEndian.Uint32(src))
*dst = Float4{Float: math.Float32frombits(uint32(n)), Status: Present}
return nil
}
func (src Float4) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, strconv.FormatFloat(float64(src.Float), 'f', -1, 32)...)
return buf, nil
}
func (src Float4) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint32(buf, math.Float32bits(src.Float))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Float4) Scan(src interface{}) error {
if src == nil {
*dst = Float4{Status: Null}
return nil
}
switch src := src.(type) {
case float64:
*dst = Float4{Float: float32(src), Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Float4) Value() (driver.Value, error) {
switch src.Status {
case Present:
return float64(src.Float), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,517 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type Float4Array struct {
Elements []Float4
Dimensions []ArrayDimension
Status Status
}
func (dst *Float4Array) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Float4Array{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []float32:
if value == nil {
*dst = Float4Array{Status: Null}
} else if len(value) == 0 {
*dst = Float4Array{Status: Present}
} else {
elements := make([]Float4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Float4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*float32:
if value == nil {
*dst = Float4Array{Status: Null}
} else if len(value) == 0 {
*dst = Float4Array{Status: Present}
} else {
elements := make([]Float4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Float4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Float4:
if value == nil {
*dst = Float4Array{Status: Null}
} else if len(value) == 0 {
*dst = Float4Array{Status: Present}
} else {
*dst = Float4Array{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = Float4Array{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for Float4Array", src)
}
if elementsLength == 0 {
*dst = Float4Array{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Float4Array", src)
}
*dst = Float4Array{
Elements: make([]Float4, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Float4, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to Float4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *Float4Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to Float4Array")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in Float4Array", err)
}
index++
return index, nil
}
func (dst Float4Array) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Float4Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]float32:
*v = make([]float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float32:
*v = make([]*float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *Float4Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from Float4Array")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from Float4Array")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *Float4Array) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float4Array{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Float4
if len(uta.Elements) > 0 {
elements = make([]Float4, len(uta.Elements))
for i, s := range uta.Elements {
var elem Float4
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Float4Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *Float4Array) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float4Array{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = Float4Array{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Float4, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Float4Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src Float4Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src Float4Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("float4"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "float4")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Float4Array) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Float4Array) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,272 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Float8 struct {
Float float64
Status Status
}
func (dst *Float8) Set(src interface{}) error {
if src == nil {
*dst = Float8{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case float32:
*dst = Float8{Float: float64(value), Status: Present}
case float64:
*dst = Float8{Float: value, Status: Present}
case int8:
*dst = Float8{Float: float64(value), Status: Present}
case uint8:
*dst = Float8{Float: float64(value), Status: Present}
case int16:
*dst = Float8{Float: float64(value), Status: Present}
case uint16:
*dst = Float8{Float: float64(value), Status: Present}
case int32:
*dst = Float8{Float: float64(value), Status: Present}
case uint32:
*dst = Float8{Float: float64(value), Status: Present}
case int64:
f64 := float64(value)
if int64(f64) == value {
*dst = Float8{Float: f64, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float64", value)
}
case uint64:
f64 := float64(value)
if uint64(f64) == value {
*dst = Float8{Float: f64, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float64", value)
}
case int:
f64 := float64(value)
if int(f64) == value {
*dst = Float8{Float: f64, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float64", value)
}
case uint:
f64 := float64(value)
if uint(f64) == value {
*dst = Float8{Float: f64, Status: Present}
} else {
return fmt.Errorf("%v cannot be exactly represented as float64", value)
}
case string:
num, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
*dst = Float8{Float: float64(num), Status: Present}
case *float64:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *int8:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Float8{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Float8", value)
}
return nil
}
func (dst Float8) Get() interface{} {
switch dst.Status {
case Present:
return dst.Float
case Null:
return nil
default:
return dst.Status
}
}
func (src *Float8) AssignTo(dst interface{}) error {
return float64AssignTo(src.Float, src.Status, dst)
}
func (dst *Float8) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float8{Status: Null}
return nil
}
n, err := strconv.ParseFloat(string(src), 64)
if err != nil {
return err
}
*dst = Float8{Float: n, Status: Present}
return nil
}
func (dst *Float8) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float8{Status: Null}
return nil
}
if len(src) != 8 {
return fmt.Errorf("invalid length for float8: %v", len(src))
}
n := int64(binary.BigEndian.Uint64(src))
*dst = Float8{Float: math.Float64frombits(uint64(n)), Status: Present}
return nil
}
func (src Float8) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, strconv.FormatFloat(float64(src.Float), 'f', -1, 64)...)
return buf, nil
}
func (src Float8) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.Float))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Float8) Scan(src interface{}) error {
if src == nil {
*dst = Float8{Status: Null}
return nil
}
switch src := src.(type) {
case float64:
*dst = Float8{Float: src, Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Float8) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.Float, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,517 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type Float8Array struct {
Elements []Float8
Dimensions []ArrayDimension
Status Status
}
func (dst *Float8Array) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Float8Array{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []float64:
if value == nil {
*dst = Float8Array{Status: Null}
} else if len(value) == 0 {
*dst = Float8Array{Status: Present}
} else {
elements := make([]Float8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Float8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*float64:
if value == nil {
*dst = Float8Array{Status: Null}
} else if len(value) == 0 {
*dst = Float8Array{Status: Present}
} else {
elements := make([]Float8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Float8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Float8:
if value == nil {
*dst = Float8Array{Status: Null}
} else if len(value) == 0 {
*dst = Float8Array{Status: Present}
} else {
*dst = Float8Array{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = Float8Array{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for Float8Array", src)
}
if elementsLength == 0 {
*dst = Float8Array{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Float8Array", src)
}
*dst = Float8Array{
Elements: make([]Float8, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Float8, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to Float8Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *Float8Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to Float8Array")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in Float8Array", err)
}
index++
return index, nil
}
func (dst Float8Array) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Float8Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]float64:
*v = make([]float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float64:
*v = make([]*float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *Float8Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from Float8Array")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from Float8Array")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *Float8Array) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float8Array{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Float8
if len(uta.Elements) > 0 {
elements = make([]Float8, len(uta.Elements))
for i, s := range uta.Elements {
var elem Float8
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Float8Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *Float8Array) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Float8Array{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = Float8Array{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Float8, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Float8Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src Float8Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src Float8Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("float8"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "float8")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Float8Array) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Float8Array) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,39 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
// GenericBinary is a placeholder for binary format values that no other type exists
// to handle.
type GenericBinary Bytea
func (dst *GenericBinary) Set(src interface{}) error {
return (*Bytea)(dst).Set(src)
}
func (dst GenericBinary) Get() interface{} {
return (Bytea)(dst).Get()
}
func (src *GenericBinary) AssignTo(dst interface{}) error {
return (*Bytea)(src).AssignTo(dst)
}
func (dst *GenericBinary) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Bytea)(dst).DecodeBinary(ci, src)
}
func (src GenericBinary) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Bytea)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *GenericBinary) Scan(src interface{}) error {
return (*Bytea)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src GenericBinary) Value() (driver.Value, error) {
return (Bytea)(src).Value()
}

View file

@ -1,39 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
// GenericText is a placeholder for text format values that no other type exists
// to handle.
type GenericText Text
func (dst *GenericText) Set(src interface{}) error {
return (*Text)(dst).Set(src)
}
func (dst GenericText) Get() interface{} {
return (Text)(dst).Get()
}
func (src *GenericText) AssignTo(dst interface{}) error {
return (*Text)(src).AssignTo(dst)
}
func (dst *GenericText) DecodeText(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeText(ci, src)
}
func (src GenericText) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeText(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *GenericText) Scan(src interface{}) error {
return (*Text)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src GenericText) Value() (driver.Value, error) {
return (Text)(src).Value()
}

View file

@ -1,489 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type HstoreArray struct {
Elements []Hstore
Dimensions []ArrayDimension
Status Status
}
func (dst *HstoreArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = HstoreArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []map[string]string:
if value == nil {
*dst = HstoreArray{Status: Null}
} else if len(value) == 0 {
*dst = HstoreArray{Status: Present}
} else {
elements := make([]Hstore, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = HstoreArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Hstore:
if value == nil {
*dst = HstoreArray{Status: Null}
} else if len(value) == 0 {
*dst = HstoreArray{Status: Present}
} else {
*dst = HstoreArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = HstoreArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for HstoreArray", src)
}
if elementsLength == 0 {
*dst = HstoreArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to HstoreArray", src)
}
*dst = HstoreArray{
Elements: make([]Hstore, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Hstore, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to HstoreArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *HstoreArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to HstoreArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in HstoreArray", err)
}
index++
return index, nil
}
func (dst HstoreArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *HstoreArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]map[string]string:
*v = make([]map[string]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *HstoreArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from HstoreArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from HstoreArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *HstoreArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = HstoreArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Hstore
if len(uta.Elements) > 0 {
elements = make([]Hstore, len(uta.Elements))
for i, s := range uta.Elements {
var elem Hstore
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = HstoreArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *HstoreArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = HstoreArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = HstoreArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Hstore, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = HstoreArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src HstoreArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src HstoreArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("hstore"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "hstore")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *HstoreArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src HstoreArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,304 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding"
"fmt"
"net"
"strings"
)
// Network address family is dependent on server socket.h value for AF_INET.
// In practice, all platforms appear to have the same value. See
// src/include/utils/inet.h for more information.
const (
defaultAFInet = 2
defaultAFInet6 = 3
)
// Inet represents both inet and cidr PostgreSQL types.
type Inet struct {
IPNet *net.IPNet
Status Status
}
func (dst *Inet) Set(src interface{}) error {
if src == nil {
*dst = Inet{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case net.IPNet:
*dst = Inet{IPNet: &value, Status: Present}
case net.IP:
if len(value) == 0 {
*dst = Inet{Status: Null}
} else {
bitCount := len(value) * 8
mask := net.CIDRMask(bitCount, bitCount)
*dst = Inet{IPNet: &net.IPNet{Mask: mask, IP: value}, Status: Present}
}
case string:
ip, ipnet, err := net.ParseCIDR(value)
if err != nil {
ip := net.ParseIP(value)
if ip == nil {
return fmt.Errorf("unable to parse inet address: %s", value)
}
if ipv4 := maybeGetIPv4(value, ip); ipv4 != nil {
ipnet = &net.IPNet{IP: ipv4, Mask: net.CIDRMask(32, 32)}
} else {
ipnet = &net.IPNet{IP: ip, Mask: net.CIDRMask(128, 128)}
}
} else {
ipnet.IP = ip
if ipv4 := maybeGetIPv4(value, ipnet.IP); ipv4 != nil {
ipnet.IP = ipv4
if len(ipnet.Mask) == 16 {
ipnet.Mask = ipnet.Mask[12:] // Not sure this is ever needed.
}
}
}
*dst = Inet{IPNet: ipnet, Status: Present}
case *net.IPNet:
if value == nil {
*dst = Inet{Status: Null}
} else {
return dst.Set(*value)
}
case *net.IP:
if value == nil {
*dst = Inet{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Inet{Status: Null}
} else {
return dst.Set(*value)
}
default:
if tv, ok := src.(encoding.TextMarshaler); ok {
text, err := tv.MarshalText()
if err != nil {
return fmt.Errorf("cannot marshal %v: %w", value, err)
}
return dst.Set(string(text))
}
if sv, ok := src.(fmt.Stringer); ok {
return dst.Set(sv.String())
}
if originalSrc, ok := underlyingPtrType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Inet", value)
}
return nil
}
// Convert the net.IP to IPv4, if appropriate.
//
// When parsing a string to a net.IP using net.ParseIP() and the like, we get a
// 16 byte slice for IPv4 addresses as well as IPv6 addresses. This function
// calls To4() to convert them to a 4 byte slice. This is useful as it allows
// users of the net.IP check for IPv4 addresses based on the length and makes
// it clear we are handling IPv4 as opposed to IPv6 or IPv4-mapped IPv6
// addresses.
func maybeGetIPv4(input string, ip net.IP) net.IP {
// Do not do this if the provided input looks like IPv6. This is because
// To4() on IPv4-mapped IPv6 addresses converts them to IPv4, which behave
// different in some cases.
if strings.Contains(input, ":") {
return nil
}
return ip.To4()
}
func (dst Inet) Get() interface{} {
switch dst.Status {
case Present:
return dst.IPNet
case Null:
return nil
default:
return dst.Status
}
}
func (src *Inet) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *net.IPNet:
*v = net.IPNet{
IP: make(net.IP, len(src.IPNet.IP)),
Mask: make(net.IPMask, len(src.IPNet.Mask)),
}
copy(v.IP, src.IPNet.IP)
copy(v.Mask, src.IPNet.Mask)
return nil
case *net.IP:
if oneCount, bitCount := src.IPNet.Mask.Size(); oneCount != bitCount {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
*v = make(net.IP, len(src.IPNet.IP))
copy(*v, src.IPNet.IP)
return nil
default:
if tv, ok := dst.(encoding.TextUnmarshaler); ok {
if err := tv.UnmarshalText([]byte(src.IPNet.String())); err != nil {
return fmt.Errorf("cannot unmarshal %v to %T: %w", src, dst, err)
}
return nil
}
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Inet) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Inet{Status: Null}
return nil
}
var ipnet *net.IPNet
var err error
if ip := net.ParseIP(string(src)); ip != nil {
if ipv4 := ip.To4(); ipv4 != nil {
ip = ipv4
}
bitCount := len(ip) * 8
mask := net.CIDRMask(bitCount, bitCount)
ipnet = &net.IPNet{Mask: mask, IP: ip}
} else {
ip, ipnet, err = net.ParseCIDR(string(src))
if err != nil {
return err
}
if ipv4 := ip.To4(); ipv4 != nil {
ip = ipv4
}
ones, _ := ipnet.Mask.Size()
*ipnet = net.IPNet{IP: ip, Mask: net.CIDRMask(ones, len(ip)*8)}
}
*dst = Inet{IPNet: ipnet, Status: Present}
return nil
}
func (dst *Inet) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Inet{Status: Null}
return nil
}
if len(src) != 8 && len(src) != 20 {
return fmt.Errorf("Received an invalid size for an inet: %d", len(src))
}
// ignore family
bits := src[1]
// ignore is_cidr
addressLength := src[3]
var ipnet net.IPNet
ipnet.IP = make(net.IP, int(addressLength))
copy(ipnet.IP, src[4:])
if ipv4 := ipnet.IP.To4(); ipv4 != nil {
ipnet.IP = ipv4
}
ipnet.Mask = net.CIDRMask(int(bits), len(ipnet.IP)*8)
*dst = Inet{IPNet: &ipnet, Status: Present}
return nil
}
func (src Inet) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.IPNet.String()...), nil
}
// EncodeBinary encodes src into w.
func (src Inet) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var family byte
switch len(src.IPNet.IP) {
case net.IPv4len:
family = defaultAFInet
case net.IPv6len:
family = defaultAFInet6
default:
return nil, fmt.Errorf("Unexpected IP length: %v", len(src.IPNet.IP))
}
buf = append(buf, family)
ones, _ := src.IPNet.Mask.Size()
buf = append(buf, byte(ones))
// is_cidr is ignored on server
buf = append(buf, 0)
buf = append(buf, byte(len(src.IPNet.IP)))
return append(buf, src.IPNet.IP...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Inet) Scan(src interface{}) error {
if src == nil {
*dst = Inet{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Inet) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,546 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"net"
"reflect"
"github.com/jackc/pgio"
)
type InetArray struct {
Elements []Inet
Dimensions []ArrayDimension
Status Status
}
func (dst *InetArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = InetArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []*net.IPNet:
if value == nil {
*dst = InetArray{Status: Null}
} else if len(value) == 0 {
*dst = InetArray{Status: Present}
} else {
elements := make([]Inet, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = InetArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []net.IP:
if value == nil {
*dst = InetArray{Status: Null}
} else if len(value) == 0 {
*dst = InetArray{Status: Present}
} else {
elements := make([]Inet, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = InetArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*net.IP:
if value == nil {
*dst = InetArray{Status: Null}
} else if len(value) == 0 {
*dst = InetArray{Status: Present}
} else {
elements := make([]Inet, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = InetArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Inet:
if value == nil {
*dst = InetArray{Status: Null}
} else if len(value) == 0 {
*dst = InetArray{Status: Present}
} else {
*dst = InetArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = InetArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for InetArray", src)
}
if elementsLength == 0 {
*dst = InetArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to InetArray", src)
}
*dst = InetArray{
Elements: make([]Inet, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Inet, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to InetArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *InetArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to InetArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in InetArray", err)
}
index++
return index, nil
}
func (dst InetArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *InetArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]*net.IPNet:
*v = make([]*net.IPNet, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]net.IP:
*v = make([]net.IP, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*net.IP:
*v = make([]*net.IP, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *InetArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from InetArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from InetArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *InetArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = InetArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Inet
if len(uta.Elements) > 0 {
elements = make([]Inet, len(uta.Elements))
for i, s := range uta.Elements {
var elem Inet
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = InetArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *InetArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = InetArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = InetArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Inet, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = InetArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src InetArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src InetArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("inet"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "inet")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *InetArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src InetArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,321 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Int2 struct {
Int int16
Status Status
}
func (dst *Int2) Set(src interface{}) error {
if src == nil {
*dst = Int2{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case int8:
*dst = Int2{Int: int16(value), Status: Present}
case uint8:
*dst = Int2{Int: int16(value), Status: Present}
case int16:
*dst = Int2{Int: int16(value), Status: Present}
case uint16:
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case int32:
if value < math.MinInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case uint32:
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case int64:
if value < math.MinInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case uint64:
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case int:
if value < math.MinInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case uint:
if value > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case string:
num, err := strconv.ParseInt(value, 10, 16)
if err != nil {
return err
}
*dst = Int2{Int: int16(num), Status: Present}
case float32:
if value > math.MaxInt16 {
return fmt.Errorf("%f is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case float64:
if value > math.MaxInt16 {
return fmt.Errorf("%f is greater than maximum value for Int2", value)
}
*dst = Int2{Int: int16(value), Status: Present}
case *int8:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
case *float64:
if value == nil {
*dst = Int2{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int2", value)
}
return nil
}
func (dst Int2) Get() interface{} {
switch dst.Status {
case Present:
return dst.Int
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int2) AssignTo(dst interface{}) error {
return int64AssignTo(int64(src.Int), src.Status, dst)
}
func (dst *Int2) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int2{Status: Null}
return nil
}
n, err := strconv.ParseInt(string(src), 10, 16)
if err != nil {
return err
}
*dst = Int2{Int: int16(n), Status: Present}
return nil
}
func (dst *Int2) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int2{Status: Null}
return nil
}
if len(src) != 2 {
return fmt.Errorf("invalid length for int2: %v", len(src))
}
n := int16(binary.BigEndian.Uint16(src))
*dst = Int2{Int: n, Status: Present}
return nil
}
func (src Int2) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, strconv.FormatInt(int64(src.Int), 10)...), nil
}
func (src Int2) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return pgio.AppendInt16(buf, src.Int), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int2) Scan(src interface{}) error {
if src == nil {
*dst = Int2{Status: Null}
return nil
}
switch src := src.(type) {
case int64:
if src < math.MinInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", src)
}
if src > math.MaxInt16 {
return fmt.Errorf("%d is greater than maximum value for Int2", src)
}
*dst = Int2{Int: int16(src), Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int2) Value() (driver.Value, error) {
switch src.Status {
case Present:
return int64(src.Int), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Int2) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
return []byte(strconv.FormatInt(int64(src.Int), 10)), nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Int2) UnmarshalJSON(b []byte) error {
var n *int16
err := json.Unmarshal(b, &n)
if err != nil {
return err
}
if n == nil {
*dst = Int2{Status: Null}
} else {
*dst = Int2{Int: *n, Status: Present}
}
return nil
}

View file

@ -1,909 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type Int2Array struct {
Elements []Int2
Dimensions []ArrayDimension
Status Status
}
func (dst *Int2Array) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int2Array{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []int16:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int16:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint16:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint16:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int32:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int32:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint32:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint32:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int64:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int64:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint64:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint64:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
elements := make([]Int2, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int2Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Int2:
if value == nil {
*dst = Int2Array{Status: Null}
} else if len(value) == 0 {
*dst = Int2Array{Status: Present}
} else {
*dst = Int2Array{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = Int2Array{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for Int2Array", src)
}
if elementsLength == 0 {
*dst = Int2Array{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int2Array", src)
}
*dst = Int2Array{
Elements: make([]Int2, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Int2, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to Int2Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *Int2Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to Int2Array")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in Int2Array", err)
}
index++
return index, nil
}
func (dst Int2Array) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int2Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]int16:
*v = make([]int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int16:
*v = make([]*int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint16:
*v = make([]uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint16:
*v = make([]*uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int32:
*v = make([]int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int32:
*v = make([]*int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint32:
*v = make([]uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint32:
*v = make([]*uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int:
*v = make([]int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int:
*v = make([]*int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint:
*v = make([]uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint:
*v = make([]*uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *Int2Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from Int2Array")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from Int2Array")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *Int2Array) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int2Array{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Int2
if len(uta.Elements) > 0 {
elements = make([]Int2, len(uta.Elements))
for i, s := range uta.Elements {
var elem Int2
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Int2Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *Int2Array) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int2Array{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = Int2Array{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Int2, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Int2Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src Int2Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src Int2Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("int2"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "int2")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int2Array) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int2Array) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,312 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Int4 struct {
Int int32
Status Status
}
func (dst *Int4) Set(src interface{}) error {
if src == nil {
*dst = Int4{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case int8:
*dst = Int4{Int: int32(value), Status: Present}
case uint8:
*dst = Int4{Int: int32(value), Status: Present}
case int16:
*dst = Int4{Int: int32(value), Status: Present}
case uint16:
*dst = Int4{Int: int32(value), Status: Present}
case int32:
*dst = Int4{Int: int32(value), Status: Present}
case uint32:
if value > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case int64:
if value < math.MinInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
if value > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case uint64:
if value > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case int:
if value < math.MinInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
if value > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case uint:
if value > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case string:
num, err := strconv.ParseInt(value, 10, 32)
if err != nil {
return err
}
*dst = Int4{Int: int32(num), Status: Present}
case float32:
if value > math.MaxInt32 {
return fmt.Errorf("%f is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case float64:
if value > math.MaxInt32 {
return fmt.Errorf("%f is greater than maximum value for Int4", value)
}
*dst = Int4{Int: int32(value), Status: Present}
case *int8:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
case *float64:
if value == nil {
*dst = Int4{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int4", value)
}
return nil
}
func (dst Int4) Get() interface{} {
switch dst.Status {
case Present:
return dst.Int
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int4) AssignTo(dst interface{}) error {
return int64AssignTo(int64(src.Int), src.Status, dst)
}
func (dst *Int4) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4{Status: Null}
return nil
}
n, err := strconv.ParseInt(string(src), 10, 32)
if err != nil {
return err
}
*dst = Int4{Int: int32(n), Status: Present}
return nil
}
func (dst *Int4) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4{Status: Null}
return nil
}
if len(src) != 4 {
return fmt.Errorf("invalid length for int4: %v", len(src))
}
n := int32(binary.BigEndian.Uint32(src))
*dst = Int4{Int: n, Status: Present}
return nil
}
func (src Int4) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, strconv.FormatInt(int64(src.Int), 10)...), nil
}
func (src Int4) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return pgio.AppendInt32(buf, src.Int), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int4) Scan(src interface{}) error {
if src == nil {
*dst = Int4{Status: Null}
return nil
}
switch src := src.(type) {
case int64:
if src < math.MinInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", src)
}
if src > math.MaxInt32 {
return fmt.Errorf("%d is greater than maximum value for Int4", src)
}
*dst = Int4{Int: int32(src), Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int4) Value() (driver.Value, error) {
switch src.Status {
case Present:
return int64(src.Int), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Int4) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
return []byte(strconv.FormatInt(int64(src.Int), 10)), nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Int4) UnmarshalJSON(b []byte) error {
var n *int32
err := json.Unmarshal(b, &n)
if err != nil {
return err
}
if n == nil {
*dst = Int4{Status: Null}
} else {
*dst = Int4{Int: *n, Status: Present}
}
return nil
}

View file

@ -1,909 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type Int4Array struct {
Elements []Int4
Dimensions []ArrayDimension
Status Status
}
func (dst *Int4Array) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int4Array{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []int16:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int16:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint16:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint16:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int32:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int32:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint32:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint32:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int64:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int64:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint64:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint64:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
elements := make([]Int4, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Int4:
if value == nil {
*dst = Int4Array{Status: Null}
} else if len(value) == 0 {
*dst = Int4Array{Status: Present}
} else {
*dst = Int4Array{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = Int4Array{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for Int4Array", src)
}
if elementsLength == 0 {
*dst = Int4Array{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int4Array", src)
}
*dst = Int4Array{
Elements: make([]Int4, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Int4, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to Int4Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *Int4Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to Int4Array")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in Int4Array", err)
}
index++
return index, nil
}
func (dst Int4Array) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int4Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]int16:
*v = make([]int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int16:
*v = make([]*int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint16:
*v = make([]uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint16:
*v = make([]*uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int32:
*v = make([]int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int32:
*v = make([]*int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint32:
*v = make([]uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint32:
*v = make([]*uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int:
*v = make([]int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int:
*v = make([]*int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint:
*v = make([]uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint:
*v = make([]*uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *Int4Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from Int4Array")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from Int4Array")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *Int4Array) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4Array{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Int4
if len(uta.Elements) > 0 {
elements = make([]Int4, len(uta.Elements))
for i, s := range uta.Elements {
var elem Int4
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Int4Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *Int4Array) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4Array{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = Int4Array{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Int4, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Int4Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src Int4Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src Int4Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("int4"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "int4")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int4Array) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int4Array) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,239 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"github.com/jackc/pgio"
)
type Int4multirange struct {
Ranges []Int4range
Status Status
}
func (dst *Int4multirange) Set(src interface{}) error {
//untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int4multirange{Status: Null}
return nil
}
switch value := src.(type) {
case Int4multirange:
*dst = value
case *Int4multirange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
case []Int4range:
if value == nil {
*dst = Int4multirange{Status: Null}
} else if len(value) == 0 {
*dst = Int4multirange{Status: Present}
} else {
elements := make([]Int4range, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4multirange{
Ranges: elements,
Status: Present,
}
}
case []*Int4range:
if value == nil {
*dst = Int4multirange{Status: Null}
} else if len(value) == 0 {
*dst = Int4multirange{Status: Present}
} else {
elements := make([]Int4range, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int4multirange{
Ranges: elements,
Status: Present,
}
}
default:
return fmt.Errorf("cannot convert %v to Int4multirange", src)
}
return nil
}
func (dst Int4multirange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int4multirange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Int4multirange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4multirange{Status: Null}
return nil
}
utmr, err := ParseUntypedTextMultirange(string(src))
if err != nil {
return err
}
var elements []Int4range
if len(utmr.Elements) > 0 {
elements = make([]Int4range, len(utmr.Elements))
for i, s := range utmr.Elements {
var elem Int4range
elemSrc := []byte(s)
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Int4multirange{Ranges: elements, Status: Present}
return nil
}
func (dst *Int4multirange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4multirange{Status: Null}
return nil
}
rp := 0
numElems := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
if numElems == 0 {
*dst = Int4multirange{Status: Present}
return nil
}
elements := make([]Int4range, numElems)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err := elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Int4multirange{Ranges: elements, Status: Present}
return nil
}
func (src Int4multirange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, '{')
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Ranges {
if i > 0 {
buf = append(buf, ',')
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
return nil, fmt.Errorf("multi-range does not allow null range")
} else {
buf = append(buf, string(elemBuf)...)
}
}
buf = append(buf, '}')
return buf, nil
}
func (src Int4multirange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt32(buf, int32(len(src.Ranges)))
for i := range src.Ranges {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int4multirange) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int4multirange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Int4range struct {
Lower Int4
Upper Int4
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Int4range) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int4range{Status: Null}
return nil
}
switch value := src.(type) {
case Int4range:
*dst = value
case *Int4range:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Int4range", src)
}
return nil
}
func (dst Int4range) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int4range) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Int4range) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4range{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Int4range{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Int4range) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int4range{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Int4range{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Int4range) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Int4range) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int4range) Scan(src interface{}) error {
if src == nil {
*dst = Int4range{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int4range) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,298 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
type Int8 struct {
Int int64
Status Status
}
func (dst *Int8) Set(src interface{}) error {
if src == nil {
*dst = Int8{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case int8:
*dst = Int8{Int: int64(value), Status: Present}
case uint8:
*dst = Int8{Int: int64(value), Status: Present}
case int16:
*dst = Int8{Int: int64(value), Status: Present}
case uint16:
*dst = Int8{Int: int64(value), Status: Present}
case int32:
*dst = Int8{Int: int64(value), Status: Present}
case uint32:
*dst = Int8{Int: int64(value), Status: Present}
case int64:
*dst = Int8{Int: int64(value), Status: Present}
case uint64:
if value > math.MaxInt64 {
return fmt.Errorf("%d is greater than maximum value for Int8", value)
}
*dst = Int8{Int: int64(value), Status: Present}
case int:
if int64(value) < math.MinInt64 {
return fmt.Errorf("%d is greater than maximum value for Int8", value)
}
if int64(value) > math.MaxInt64 {
return fmt.Errorf("%d is greater than maximum value for Int8", value)
}
*dst = Int8{Int: int64(value), Status: Present}
case uint:
if uint64(value) > math.MaxInt64 {
return fmt.Errorf("%d is greater than maximum value for Int8", value)
}
*dst = Int8{Int: int64(value), Status: Present}
case string:
num, err := strconv.ParseInt(value, 10, 64)
if err != nil {
return err
}
*dst = Int8{Int: num, Status: Present}
case float32:
if value > math.MaxInt64 {
return fmt.Errorf("%f is greater than maximum value for Int8", value)
}
*dst = Int8{Int: int64(value), Status: Present}
case float64:
if value > math.MaxInt64 {
return fmt.Errorf("%f is greater than maximum value for Int8", value)
}
*dst = Int8{Int: int64(value), Status: Present}
case *int8:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
case *float64:
if value == nil {
*dst = Int8{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int8", value)
}
return nil
}
func (dst Int8) Get() interface{} {
switch dst.Status {
case Present:
return dst.Int
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int8) AssignTo(dst interface{}) error {
return int64AssignTo(int64(src.Int), src.Status, dst)
}
func (dst *Int8) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8{Status: Null}
return nil
}
n, err := strconv.ParseInt(string(src), 10, 64)
if err != nil {
return err
}
*dst = Int8{Int: n, Status: Present}
return nil
}
func (dst *Int8) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8{Status: Null}
return nil
}
if len(src) != 8 {
return fmt.Errorf("invalid length for int8: %v", len(src))
}
n := int64(binary.BigEndian.Uint64(src))
*dst = Int8{Int: n, Status: Present}
return nil
}
func (src Int8) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, strconv.FormatInt(src.Int, 10)...), nil
}
func (src Int8) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return pgio.AppendInt64(buf, src.Int), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int8) Scan(src interface{}) error {
if src == nil {
*dst = Int8{Status: Null}
return nil
}
switch src := src.(type) {
case int64:
*dst = Int8{Int: src, Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int8) Value() (driver.Value, error) {
switch src.Status {
case Present:
return int64(src.Int), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Int8) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
return []byte(strconv.FormatInt(src.Int, 10)), nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Int8) UnmarshalJSON(b []byte) error {
var n *int64
err := json.Unmarshal(b, &n)
if err != nil {
return err
}
if n == nil {
*dst = Int8{Status: Null}
} else {
*dst = Int8{Int: *n, Status: Present}
}
return nil
}

View file

@ -1,909 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type Int8Array struct {
Elements []Int8
Dimensions []ArrayDimension
Status Status
}
func (dst *Int8Array) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int8Array{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []int16:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int16:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint16:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint16:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int32:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int32:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint32:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint32:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int64:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int64:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint64:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint64:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
elements := make([]Int8, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8Array{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Int8:
if value == nil {
*dst = Int8Array{Status: Null}
} else if len(value) == 0 {
*dst = Int8Array{Status: Present}
} else {
*dst = Int8Array{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = Int8Array{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for Int8Array", src)
}
if elementsLength == 0 {
*dst = Int8Array{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Int8Array", src)
}
*dst = Int8Array{
Elements: make([]Int8, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Int8, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to Int8Array, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *Int8Array) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to Int8Array")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in Int8Array", err)
}
index++
return index, nil
}
func (dst Int8Array) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int8Array) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]int16:
*v = make([]int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int16:
*v = make([]*int16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint16:
*v = make([]uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint16:
*v = make([]*uint16, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int32:
*v = make([]int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int32:
*v = make([]*int32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint32:
*v = make([]uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint32:
*v = make([]*uint32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int:
*v = make([]int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int:
*v = make([]*int, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint:
*v = make([]uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint:
*v = make([]*uint, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *Int8Array) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from Int8Array")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from Int8Array")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *Int8Array) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8Array{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Int8
if len(uta.Elements) > 0 {
elements = make([]Int8, len(uta.Elements))
for i, s := range uta.Elements {
var elem Int8
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Int8Array{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *Int8Array) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8Array{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = Int8Array{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Int8, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Int8Array{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src Int8Array) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src Int8Array) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("int8"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "int8")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int8Array) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int8Array) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,239 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"github.com/jackc/pgio"
)
type Int8multirange struct {
Ranges []Int8range
Status Status
}
func (dst *Int8multirange) Set(src interface{}) error {
//untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int8multirange{Status: Null}
return nil
}
switch value := src.(type) {
case Int8multirange:
*dst = value
case *Int8multirange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
case []Int8range:
if value == nil {
*dst = Int8multirange{Status: Null}
} else if len(value) == 0 {
*dst = Int8multirange{Status: Present}
} else {
elements := make([]Int8range, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8multirange{
Ranges: elements,
Status: Present,
}
}
case []*Int8range:
if value == nil {
*dst = Int8multirange{Status: Null}
} else if len(value) == 0 {
*dst = Int8multirange{Status: Present}
} else {
elements := make([]Int8range, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Int8multirange{
Ranges: elements,
Status: Present,
}
}
default:
return fmt.Errorf("cannot convert %v to Int8multirange", src)
}
return nil
}
func (dst Int8multirange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int8multirange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Int8multirange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8multirange{Status: Null}
return nil
}
utmr, err := ParseUntypedTextMultirange(string(src))
if err != nil {
return err
}
var elements []Int8range
if len(utmr.Elements) > 0 {
elements = make([]Int8range, len(utmr.Elements))
for i, s := range utmr.Elements {
var elem Int8range
elemSrc := []byte(s)
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Int8multirange{Ranges: elements, Status: Present}
return nil
}
func (dst *Int8multirange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8multirange{Status: Null}
return nil
}
rp := 0
numElems := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
if numElems == 0 {
*dst = Int8multirange{Status: Present}
return nil
}
elements := make([]Int8range, numElems)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err := elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Int8multirange{Ranges: elements, Status: Present}
return nil
}
func (src Int8multirange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, '{')
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Ranges {
if i > 0 {
buf = append(buf, ',')
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
return nil, fmt.Errorf("multi-range does not allow null range")
} else {
buf = append(buf, string(elemBuf)...)
}
}
buf = append(buf, '}')
return buf, nil
}
func (src Int8multirange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt32(buf, int32(len(src.Ranges)))
for i := range src.Ranges {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int8multirange) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int8multirange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Int8range struct {
Lower Int8
Upper Int8
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Int8range) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Int8range{Status: Null}
return nil
}
switch value := src.(type) {
case Int8range:
*dst = value
case *Int8range:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Int8range", src)
}
return nil
}
func (dst Int8range) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Int8range) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Int8range) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8range{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Int8range{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Int8range) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Int8range{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Int8range{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Int8range) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Int8range) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Int8range) Scan(src interface{}) error {
if src == nil {
*dst = Int8range{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Int8range) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,257 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"strconv"
"strings"
"time"
"github.com/jackc/pgio"
)
const (
microsecondsPerSecond = 1000000
microsecondsPerMinute = 60 * microsecondsPerSecond
microsecondsPerHour = 60 * microsecondsPerMinute
microsecondsPerDay = 24 * microsecondsPerHour
microsecondsPerMonth = 30 * microsecondsPerDay
)
type Interval struct {
Microseconds int64
Days int32
Months int32
Status Status
}
func (dst *Interval) Set(src interface{}) error {
if src == nil {
*dst = Interval{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case time.Duration:
*dst = Interval{Microseconds: int64(value) / 1000, Status: Present}
default:
if originalSrc, ok := underlyingPtrType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Interval", value)
}
return nil
}
func (dst Interval) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Interval) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *time.Duration:
us := int64(src.Months)*microsecondsPerMonth + int64(src.Days)*microsecondsPerDay + src.Microseconds
*v = time.Duration(us) * time.Microsecond
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Interval) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Interval{Status: Null}
return nil
}
var microseconds int64
var days int32
var months int32
parts := strings.Split(string(src), " ")
for i := 0; i < len(parts)-1; i += 2 {
scalar, err := strconv.ParseInt(parts[i], 10, 64)
if err != nil {
return fmt.Errorf("bad interval format")
}
switch parts[i+1] {
case "year", "years":
months += int32(scalar * 12)
case "mon", "mons":
months += int32(scalar)
case "day", "days":
days = int32(scalar)
}
}
if len(parts)%2 == 1 {
timeParts := strings.SplitN(parts[len(parts)-1], ":", 3)
if len(timeParts) != 3 {
return fmt.Errorf("bad interval format")
}
var negative bool
if timeParts[0][0] == '-' {
negative = true
timeParts[0] = timeParts[0][1:]
}
hours, err := strconv.ParseInt(timeParts[0], 10, 64)
if err != nil {
return fmt.Errorf("bad interval hour format: %s", timeParts[0])
}
minutes, err := strconv.ParseInt(timeParts[1], 10, 64)
if err != nil {
return fmt.Errorf("bad interval minute format: %s", timeParts[1])
}
secondParts := strings.SplitN(timeParts[2], ".", 2)
seconds, err := strconv.ParseInt(secondParts[0], 10, 64)
if err != nil {
return fmt.Errorf("bad interval second format: %s", secondParts[0])
}
var uSeconds int64
if len(secondParts) == 2 {
uSeconds, err = strconv.ParseInt(secondParts[1], 10, 64)
if err != nil {
return fmt.Errorf("bad interval decimal format: %s", secondParts[1])
}
for i := 0; i < 6-len(secondParts[1]); i++ {
uSeconds *= 10
}
}
microseconds = hours * microsecondsPerHour
microseconds += minutes * microsecondsPerMinute
microseconds += seconds * microsecondsPerSecond
microseconds += uSeconds
if negative {
microseconds = -microseconds
}
}
*dst = Interval{Months: months, Days: days, Microseconds: microseconds, Status: Present}
return nil
}
func (dst *Interval) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Interval{Status: Null}
return nil
}
if len(src) != 16 {
return fmt.Errorf("Received an invalid size for an interval: %d", len(src))
}
microseconds := int64(binary.BigEndian.Uint64(src))
days := int32(binary.BigEndian.Uint32(src[8:]))
months := int32(binary.BigEndian.Uint32(src[12:]))
*dst = Interval{Microseconds: microseconds, Days: days, Months: months, Status: Present}
return nil
}
func (src Interval) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.Months != 0 {
buf = append(buf, strconv.FormatInt(int64(src.Months), 10)...)
buf = append(buf, " mon "...)
}
if src.Days != 0 {
buf = append(buf, strconv.FormatInt(int64(src.Days), 10)...)
buf = append(buf, " day "...)
}
absMicroseconds := src.Microseconds
if absMicroseconds < 0 {
absMicroseconds = -absMicroseconds
buf = append(buf, '-')
}
hours := absMicroseconds / microsecondsPerHour
minutes := (absMicroseconds % microsecondsPerHour) / microsecondsPerMinute
seconds := (absMicroseconds % microsecondsPerMinute) / microsecondsPerSecond
microseconds := absMicroseconds % microsecondsPerSecond
timeStr := fmt.Sprintf("%02d:%02d:%02d.%06d", hours, minutes, seconds, microseconds)
return append(buf, timeStr...), nil
}
// EncodeBinary encodes src into w.
func (src Interval) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt64(buf, src.Microseconds)
buf = pgio.AppendInt32(buf, src.Days)
return pgio.AppendInt32(buf, src.Months), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Interval) Scan(src interface{}) error {
if src == nil {
*dst = Interval{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Interval) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,209 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/json"
"errors"
"fmt"
"reflect"
)
type JSON struct {
Bytes []byte
Status Status
}
func (dst *JSON) Set(src interface{}) error {
if src == nil {
*dst = JSON{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case string:
*dst = JSON{Bytes: []byte(value), Status: Present}
case *string:
if value == nil {
*dst = JSON{Status: Null}
} else {
*dst = JSON{Bytes: []byte(*value), Status: Present}
}
case []byte:
if value == nil {
*dst = JSON{Status: Null}
} else {
*dst = JSON{Bytes: value, Status: Present}
}
// Encode* methods are defined on *JSON. If JSON is passed directly then the
// struct itself would be encoded instead of Bytes. This is clearly a footgun
// so detect and return an error. See https://github.com/jackc/pgx/issues/350.
case JSON:
return errors.New("use pointer to pgtype.JSON instead of value")
// Same as above but for JSONB (because they share implementation)
case JSONB:
return errors.New("use pointer to pgtype.JSONB instead of value")
default:
buf, err := json.Marshal(value)
if err != nil {
return err
}
*dst = JSON{Bytes: buf, Status: Present}
}
return nil
}
func (dst JSON) Get() interface{} {
switch dst.Status {
case Present:
var i interface{}
err := json.Unmarshal(dst.Bytes, &i)
if err != nil {
return dst
}
return i
case Null:
return nil
default:
return dst.Status
}
}
func (src *JSON) AssignTo(dst interface{}) error {
switch v := dst.(type) {
case *string:
if src.Status == Present {
*v = string(src.Bytes)
} else {
return fmt.Errorf("cannot assign non-present status to %T", dst)
}
case **string:
if src.Status == Present {
s := string(src.Bytes)
*v = &s
return nil
} else {
*v = nil
return nil
}
case *[]byte:
if src.Status != Present {
*v = nil
} else {
buf := make([]byte, len(src.Bytes))
copy(buf, src.Bytes)
*v = buf
}
default:
data := src.Bytes
if data == nil || src.Status != Present {
data = []byte("null")
}
p := reflect.ValueOf(dst).Elem()
p.Set(reflect.Zero(p.Type()))
return json.Unmarshal(data, dst)
}
return nil
}
func (JSON) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *JSON) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSON{Status: Null}
return nil
}
*dst = JSON{Bytes: src, Status: Present}
return nil
}
func (dst *JSON) DecodeBinary(ci *ConnInfo, src []byte) error {
return dst.DecodeText(ci, src)
}
func (JSON) PreferredParamFormat() int16 {
return TextFormatCode
}
func (src JSON) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.Bytes...), nil
}
func (src JSON) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return src.EncodeText(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *JSON) Scan(src interface{}) error {
if src == nil {
*dst = JSON{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src JSON) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.Bytes, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src JSON) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
return src.Bytes, nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *JSON) UnmarshalJSON(b []byte) error {
if b == nil || string(b) == "null" {
*dst = JSON{Status: Null}
} else {
*dst = JSON{Bytes: b, Status: Present}
}
return nil
}

View file

@ -1,546 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type JSONArray struct {
Elements []JSON
Dimensions []ArrayDimension
Status Status
}
func (dst *JSONArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = JSONArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = JSONArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONArray{Status: Present}
} else {
elements := make([]JSON, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case [][]byte:
if value == nil {
*dst = JSONArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONArray{Status: Present}
} else {
elements := make([]JSON, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []json.RawMessage:
if value == nil {
*dst = JSONArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONArray{Status: Present}
} else {
elements := make([]JSON, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []JSON:
if value == nil {
*dst = JSONArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONArray{Status: Present}
} else {
*dst = JSONArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = JSONArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for JSONArray", src)
}
if elementsLength == 0 {
*dst = JSONArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to JSONArray", src)
}
*dst = JSONArray{
Elements: make([]JSON, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]JSON, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to JSONArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *JSONArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to JSONArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in JSONArray", err)
}
index++
return index, nil
}
func (dst JSONArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *JSONArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[][]byte:
*v = make([][]byte, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]json.RawMessage:
*v = make([]json.RawMessage, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *JSONArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from JSONArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from JSONArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *JSONArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSONArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []JSON
if len(uta.Elements) > 0 {
elements = make([]JSON, len(uta.Elements))
for i, s := range uta.Elements {
var elem JSON
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = JSONArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *JSONArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSONArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = JSONArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]JSON, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = JSONArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src JSONArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src JSONArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("json"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "json")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *JSONArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src JSONArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,85 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
)
type JSONB JSON
func (dst *JSONB) Set(src interface{}) error {
return (*JSON)(dst).Set(src)
}
func (dst JSONB) Get() interface{} {
return (JSON)(dst).Get()
}
func (src *JSONB) AssignTo(dst interface{}) error {
return (*JSON)(src).AssignTo(dst)
}
func (JSONB) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *JSONB) DecodeText(ci *ConnInfo, src []byte) error {
return (*JSON)(dst).DecodeText(ci, src)
}
func (dst *JSONB) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSONB{Status: Null}
return nil
}
if len(src) == 0 {
return fmt.Errorf("jsonb too short")
}
if src[0] != 1 {
return fmt.Errorf("unknown jsonb version number %d", src[0])
}
*dst = JSONB{Bytes: src[1:], Status: Present}
return nil
}
func (JSONB) PreferredParamFormat() int16 {
return TextFormatCode
}
func (src JSONB) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (JSON)(src).EncodeText(ci, buf)
}
func (src JSONB) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, 1)
return append(buf, src.Bytes...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *JSONB) Scan(src interface{}) error {
return (*JSON)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src JSONB) Value() (driver.Value, error) {
return (JSON)(src).Value()
}
func (src JSONB) MarshalJSON() ([]byte, error) {
return (JSON)(src).MarshalJSON()
}
func (dst *JSONB) UnmarshalJSON(b []byte) error {
return (*JSON)(dst).UnmarshalJSON(b)
}

View file

@ -1,546 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type JSONBArray struct {
Elements []JSONB
Dimensions []ArrayDimension
Status Status
}
func (dst *JSONBArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = JSONBArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = JSONBArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONBArray{Status: Present}
} else {
elements := make([]JSONB, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONBArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case [][]byte:
if value == nil {
*dst = JSONBArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONBArray{Status: Present}
} else {
elements := make([]JSONB, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONBArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []json.RawMessage:
if value == nil {
*dst = JSONBArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONBArray{Status: Present}
} else {
elements := make([]JSONB, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = JSONBArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []JSONB:
if value == nil {
*dst = JSONBArray{Status: Null}
} else if len(value) == 0 {
*dst = JSONBArray{Status: Present}
} else {
*dst = JSONBArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = JSONBArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for JSONBArray", src)
}
if elementsLength == 0 {
*dst = JSONBArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to JSONBArray", src)
}
*dst = JSONBArray{
Elements: make([]JSONB, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]JSONB, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to JSONBArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *JSONBArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to JSONBArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in JSONBArray", err)
}
index++
return index, nil
}
func (dst JSONBArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *JSONBArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[][]byte:
*v = make([][]byte, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]json.RawMessage:
*v = make([]json.RawMessage, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *JSONBArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from JSONBArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from JSONBArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *JSONBArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSONBArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []JSONB
if len(uta.Elements) > 0 {
elements = make([]JSONB, len(uta.Elements))
for i, s := range uta.Elements {
var elem JSONB
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = JSONBArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *JSONBArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = JSONBArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = JSONBArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]JSONB, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = JSONBArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src JSONBArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src JSONBArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("jsonb"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "jsonb")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *JSONBArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src JSONBArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,148 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Line struct {
A, B, C float64
Status Status
}
func (dst *Line) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to Line", src)
}
func (dst Line) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Line) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Line) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Line{Status: Null}
return nil
}
if len(src) < 7 {
return fmt.Errorf("invalid length for Line: %v", len(src))
}
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 3)
if len(parts) < 3 {
return fmt.Errorf("invalid format for line")
}
a, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
return err
}
b, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
return err
}
c, err := strconv.ParseFloat(parts[2], 64)
if err != nil {
return err
}
*dst = Line{A: a, B: b, C: c, Status: Present}
return nil
}
func (dst *Line) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Line{Status: Null}
return nil
}
if len(src) != 24 {
return fmt.Errorf("invalid length for Line: %v", len(src))
}
a := binary.BigEndian.Uint64(src)
b := binary.BigEndian.Uint64(src[8:])
c := binary.BigEndian.Uint64(src[16:])
*dst = Line{
A: math.Float64frombits(a),
B: math.Float64frombits(b),
C: math.Float64frombits(c),
Status: Present,
}
return nil
}
func (src Line) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, fmt.Sprintf(`{%s,%s,%s}`,
strconv.FormatFloat(src.A, 'f', -1, 64),
strconv.FormatFloat(src.B, 'f', -1, 64),
strconv.FormatFloat(src.C, 'f', -1, 64),
)...)
return buf, nil
}
func (src Line) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.A))
buf = pgio.AppendUint64(buf, math.Float64bits(src.B))
buf = pgio.AppendUint64(buf, math.Float64bits(src.C))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Line) Scan(src interface{}) error {
if src == nil {
*dst = Line{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Line) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,165 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Lseg struct {
P [2]Vec2
Status Status
}
func (dst *Lseg) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to Lseg", src)
}
func (dst Lseg) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Lseg) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Lseg) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Lseg{Status: Null}
return nil
}
if len(src) < 11 {
return fmt.Errorf("invalid length for Lseg: %v", len(src))
}
str := string(src[2:])
var end int
end = strings.IndexByte(str, ',')
x1, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1:]
end = strings.IndexByte(str, ')')
y1, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+3:]
end = strings.IndexByte(str, ',')
x2, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1 : len(str)-2]
y2, err := strconv.ParseFloat(str, 64)
if err != nil {
return err
}
*dst = Lseg{P: [2]Vec2{{x1, y1}, {x2, y2}}, Status: Present}
return nil
}
func (dst *Lseg) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Lseg{Status: Null}
return nil
}
if len(src) != 32 {
return fmt.Errorf("invalid length for Lseg: %v", len(src))
}
x1 := binary.BigEndian.Uint64(src)
y1 := binary.BigEndian.Uint64(src[8:])
x2 := binary.BigEndian.Uint64(src[16:])
y2 := binary.BigEndian.Uint64(src[24:])
*dst = Lseg{
P: [2]Vec2{
{math.Float64frombits(x1), math.Float64frombits(y1)},
{math.Float64frombits(x2), math.Float64frombits(y2)},
},
Status: Present,
}
return nil
}
func (src Lseg) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, fmt.Sprintf(`[(%s,%s),(%s,%s)]`,
strconv.FormatFloat(src.P[0].X, 'f', -1, 64),
strconv.FormatFloat(src.P[0].Y, 'f', -1, 64),
strconv.FormatFloat(src.P[1].X, 'f', -1, 64),
strconv.FormatFloat(src.P[1].Y, 'f', -1, 64),
)...)
return buf, nil
}
func (src Lseg) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[0].Y))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P[1].Y))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Lseg) Scan(src interface{}) error {
if src == nil {
*dst = Lseg{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Lseg) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,72 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
)
type Ltree Text
func (dst *Ltree) Set(src interface{}) error {
return (*Text)(dst).Set(src)
}
func (dst Ltree) Get() interface{} {
return (Text)(dst).Get()
}
func (src *Ltree) AssignTo(dst interface{}) error {
return (*Text)(src).AssignTo(dst)
}
func (src Ltree) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeText(ci, buf)
}
func (src Ltree) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, 1)
return append(buf, src.String...), nil
}
func (Ltree) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *Ltree) DecodeText(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeText(ci, src)
}
func (dst *Ltree) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Ltree{Status: Null}
return nil
}
// Get Ltree version, only 1 is allowed
version := src[0]
if version != 1 {
return fmt.Errorf("unsupported ltree version %d", version)
}
ltreeStr := string(src[1:])
*dst = Ltree{String: ltreeStr, Status: Present}
return nil
}
func (Ltree) PreferredParamFormat() int16 {
return TextFormatCode
}
func (dst *Ltree) Scan(src interface{}) error {
return (*Text)(dst).Scan(src)
}
func (src Ltree) Value() (driver.Value, error) {
return (Text)(src).Value()
}

View file

@ -1,173 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"net"
)
type Macaddr struct {
Addr net.HardwareAddr
Status Status
}
func (dst *Macaddr) Set(src interface{}) error {
if src == nil {
*dst = Macaddr{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case net.HardwareAddr:
addr := make(net.HardwareAddr, len(value))
copy(addr, value)
*dst = Macaddr{Addr: addr, Status: Present}
case string:
addr, err := net.ParseMAC(value)
if err != nil {
return err
}
*dst = Macaddr{Addr: addr, Status: Present}
case *net.HardwareAddr:
if value == nil {
*dst = Macaddr{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Macaddr{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingPtrType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Macaddr", value)
}
return nil
}
func (dst Macaddr) Get() interface{} {
switch dst.Status {
case Present:
return dst.Addr
case Null:
return nil
default:
return dst.Status
}
}
func (src *Macaddr) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *net.HardwareAddr:
*v = make(net.HardwareAddr, len(src.Addr))
copy(*v, src.Addr)
return nil
case *string:
*v = src.Addr.String()
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Macaddr) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Macaddr{Status: Null}
return nil
}
addr, err := net.ParseMAC(string(src))
if err != nil {
return err
}
*dst = Macaddr{Addr: addr, Status: Present}
return nil
}
func (dst *Macaddr) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Macaddr{Status: Null}
return nil
}
if len(src) != 6 {
return fmt.Errorf("Received an invalid size for a macaddr: %d", len(src))
}
addr := make(net.HardwareAddr, 6)
copy(addr, src)
*dst = Macaddr{Addr: addr, Status: Present}
return nil
}
func (src Macaddr) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.Addr.String()...), nil
}
// EncodeBinary encodes src into w.
func (src Macaddr) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.Addr...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Macaddr) Scan(src interface{}) error {
if src == nil {
*dst = Macaddr{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Macaddr) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,518 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"net"
"reflect"
"github.com/jackc/pgio"
)
type MacaddrArray struct {
Elements []Macaddr
Dimensions []ArrayDimension
Status Status
}
func (dst *MacaddrArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = MacaddrArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []net.HardwareAddr:
if value == nil {
*dst = MacaddrArray{Status: Null}
} else if len(value) == 0 {
*dst = MacaddrArray{Status: Present}
} else {
elements := make([]Macaddr, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = MacaddrArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*net.HardwareAddr:
if value == nil {
*dst = MacaddrArray{Status: Null}
} else if len(value) == 0 {
*dst = MacaddrArray{Status: Present}
} else {
elements := make([]Macaddr, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = MacaddrArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Macaddr:
if value == nil {
*dst = MacaddrArray{Status: Null}
} else if len(value) == 0 {
*dst = MacaddrArray{Status: Present}
} else {
*dst = MacaddrArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = MacaddrArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for MacaddrArray", src)
}
if elementsLength == 0 {
*dst = MacaddrArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to MacaddrArray", src)
}
*dst = MacaddrArray{
Elements: make([]Macaddr, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Macaddr, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to MacaddrArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *MacaddrArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to MacaddrArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in MacaddrArray", err)
}
index++
return index, nil
}
func (dst MacaddrArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *MacaddrArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]net.HardwareAddr:
*v = make([]net.HardwareAddr, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*net.HardwareAddr:
*v = make([]*net.HardwareAddr, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *MacaddrArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from MacaddrArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from MacaddrArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *MacaddrArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = MacaddrArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Macaddr
if len(uta.Elements) > 0 {
elements = make([]Macaddr, len(uta.Elements))
for i, s := range uta.Elements {
var elem Macaddr
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = MacaddrArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *MacaddrArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = MacaddrArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = MacaddrArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Macaddr, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = MacaddrArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src MacaddrArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src MacaddrArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("macaddr"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "macaddr")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *MacaddrArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src MacaddrArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,83 +0,0 @@
package pgtype
import (
"bytes"
"fmt"
)
type UntypedTextMultirange struct {
Elements []string
}
func ParseUntypedTextMultirange(src string) (*UntypedTextMultirange, error) {
utmr := &UntypedTextMultirange{}
utmr.Elements = make([]string, 0)
buf := bytes.NewBufferString(src)
skipWhitespace(buf)
r, _, err := buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid array: %v", err)
}
if r != '{' {
return nil, fmt.Errorf("invalid multirange, expected '{': %v", err)
}
parseValueLoop:
for {
r, _, err = buf.ReadRune()
if err != nil {
return nil, fmt.Errorf("invalid multirange: %v", err)
}
switch r {
case ',': // skip range separator
case '}':
break parseValueLoop
default:
buf.UnreadRune()
value, err := parseRange(buf)
if err != nil {
return nil, fmt.Errorf("invalid multirange value: %v", err)
}
utmr.Elements = append(utmr.Elements, value)
}
}
skipWhitespace(buf)
if buf.Len() > 0 {
return nil, fmt.Errorf("unexpected trailing data: %v", buf.String())
}
return utmr, nil
}
func parseRange(buf *bytes.Buffer) (string, error) {
s := &bytes.Buffer{}
boundSepRead := false
for {
r, _, err := buf.ReadRune()
if err != nil {
return "", err
}
switch r {
case ',', '}':
if r == ',' && !boundSepRead {
boundSepRead = true
break
}
buf.UnreadRune()
return s.String(), nil
}
s.WriteRune(r)
}
}

View file

@ -1,58 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
// Name is a type used for PostgreSQL's special 63-byte
// name data type, used for identifiers like table names.
// The pg_class.relname column is a good example of where the
// name data type is used.
//
// Note that the underlying Go data type of pgx.Name is string,
// so there is no way to enforce the 63-byte length. Inputting
// a longer name into PostgreSQL will result in silent truncation
// to 63 bytes.
//
// Also, if you have custom-compiled PostgreSQL and set
// NAMEDATALEN to a different value, obviously that number of
// bytes applies, rather than the default 63.
type Name Text
func (dst *Name) Set(src interface{}) error {
return (*Text)(dst).Set(src)
}
func (dst Name) Get() interface{} {
return (Text)(dst).Get()
}
func (src *Name) AssignTo(dst interface{}) error {
return (*Text)(src).AssignTo(dst)
}
func (dst *Name) DecodeText(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeText(ci, src)
}
func (dst *Name) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeBinary(ci, src)
}
func (src Name) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeText(ci, buf)
}
func (src Name) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (Text)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *Name) Scan(src interface{}) error {
return (*Text)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Name) Value() (driver.Value, error) {
return (Text)(src).Value()
}

View file

@ -1,239 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"github.com/jackc/pgio"
)
type Nummultirange struct {
Ranges []Numrange
Status Status
}
func (dst *Nummultirange) Set(src interface{}) error {
//untyped nil and typed nil interfaces are different
if src == nil {
*dst = Nummultirange{Status: Null}
return nil
}
switch value := src.(type) {
case Nummultirange:
*dst = value
case *Nummultirange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
case []Numrange:
if value == nil {
*dst = Nummultirange{Status: Null}
} else if len(value) == 0 {
*dst = Nummultirange{Status: Present}
} else {
elements := make([]Numrange, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Nummultirange{
Ranges: elements,
Status: Present,
}
}
case []*Numrange:
if value == nil {
*dst = Nummultirange{Status: Null}
} else if len(value) == 0 {
*dst = Nummultirange{Status: Present}
} else {
elements := make([]Numrange, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = Nummultirange{
Ranges: elements,
Status: Present,
}
}
default:
return fmt.Errorf("cannot convert %v to Nummultirange", src)
}
return nil
}
func (dst Nummultirange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Nummultirange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Nummultirange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Nummultirange{Status: Null}
return nil
}
utmr, err := ParseUntypedTextMultirange(string(src))
if err != nil {
return err
}
var elements []Numrange
if len(utmr.Elements) > 0 {
elements = make([]Numrange, len(utmr.Elements))
for i, s := range utmr.Elements {
var elem Numrange
elemSrc := []byte(s)
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = Nummultirange{Ranges: elements, Status: Present}
return nil
}
func (dst *Nummultirange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Nummultirange{Status: Null}
return nil
}
rp := 0
numElems := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
if numElems == 0 {
*dst = Nummultirange{Status: Present}
return nil
}
elements := make([]Numrange, numElems)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err := elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = Nummultirange{Ranges: elements, Status: Present}
return nil
}
func (src Nummultirange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, '{')
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Ranges {
if i > 0 {
buf = append(buf, ',')
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
return nil, fmt.Errorf("multi-range does not allow null range")
} else {
buf = append(buf, string(elemBuf)...)
}
}
buf = append(buf, '}')
return buf, nil
}
func (src Nummultirange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt32(buf, int32(len(src.Ranges)))
for i := range src.Ranges {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Nummultirange) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Nummultirange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,853 +0,0 @@
package pgtype
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"math/big"
"strconv"
"strings"
"github.com/jackc/pgio"
)
// 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 bigMaxInt8 *big.Int = big.NewInt(math.MaxInt8)
var bigMinInt8 *big.Int = big.NewInt(math.MinInt8)
var bigMaxInt16 *big.Int = big.NewInt(math.MaxInt16)
var bigMinInt16 *big.Int = big.NewInt(math.MinInt16)
var bigMaxInt32 *big.Int = big.NewInt(math.MaxInt32)
var bigMinInt32 *big.Int = big.NewInt(math.MinInt32)
var bigMaxInt64 *big.Int = big.NewInt(math.MaxInt64)
var bigMinInt64 *big.Int = big.NewInt(math.MinInt64)
var bigMaxInt *big.Int = big.NewInt(int64(maxInt))
var bigMinInt *big.Int = big.NewInt(int64(minInt))
var bigMaxUint8 *big.Int = big.NewInt(math.MaxUint8)
var bigMaxUint16 *big.Int = big.NewInt(math.MaxUint16)
var bigMaxUint32 *big.Int = big.NewInt(math.MaxUint32)
var bigMaxUint64 *big.Int = (&big.Int{}).SetUint64(uint64(math.MaxUint64))
var bigMaxUint *big.Int = (&big.Int{}).SetUint64(uint64(maxUint))
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)
type Numeric struct {
Int *big.Int
Exp int32
Status Status
NaN bool
InfinityModifier InfinityModifier
}
func (dst *Numeric) Set(src interface{}) error {
if src == nil {
*dst = Numeric{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case float32:
if math.IsNaN(float64(value)) {
*dst = Numeric{Status: Present, NaN: true}
return nil
} else if math.IsInf(float64(value), 1) {
*dst = Numeric{Status: Present, InfinityModifier: Infinity}
return nil
} else if math.IsInf(float64(value), -1) {
*dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity}
return nil
}
num, exp, err := parseNumericString(strconv.FormatFloat(float64(value), 'f', -1, 64))
if err != nil {
return err
}
*dst = Numeric{Int: num, Exp: exp, Status: Present}
case float64:
if math.IsNaN(value) {
*dst = Numeric{Status: Present, NaN: true}
return nil
} else if math.IsInf(value, 1) {
*dst = Numeric{Status: Present, InfinityModifier: Infinity}
return nil
} else if math.IsInf(value, -1) {
*dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity}
return nil
}
num, exp, err := parseNumericString(strconv.FormatFloat(value, 'f', -1, 64))
if err != nil {
return err
}
*dst = Numeric{Int: num, Exp: exp, Status: Present}
case int8:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case uint8:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case int16:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case uint16:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case int32:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case uint32:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case int64:
*dst = Numeric{Int: big.NewInt(value), Status: Present}
case uint64:
*dst = Numeric{Int: (&big.Int{}).SetUint64(value), Status: Present}
case int:
*dst = Numeric{Int: big.NewInt(int64(value)), Status: Present}
case uint:
*dst = Numeric{Int: (&big.Int{}).SetUint64(uint64(value)), Status: Present}
case string:
num, exp, err := parseNumericString(value)
if err != nil {
return err
}
*dst = Numeric{Int: num, Exp: exp, Status: Present}
case *float64:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *float32:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *int8:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *uint8:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *int16:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *uint16:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *int32:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *uint32:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *int64:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *uint64:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *int:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *uint:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case *string:
if value == nil {
*dst = Numeric{Status: Null}
} else {
return dst.Set(*value)
}
case InfinityModifier:
*dst = Numeric{InfinityModifier: value, Status: Present}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Numeric", value)
}
return nil
}
func (dst Numeric) Get() interface{} {
switch dst.Status {
case Present:
if dst.InfinityModifier != None {
return dst.InfinityModifier
}
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Numeric) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *float32:
f, err := src.toFloat64()
if err != nil {
return err
}
return float64AssignTo(f, src.Status, dst)
case *float64:
f, err := src.toFloat64()
if err != nil {
return err
}
return float64AssignTo(f, src.Status, dst)
case *int:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(bigMaxInt) > 0 {
return fmt.Errorf("%v is greater than maximum value for %T", normalizedInt, *v)
}
if normalizedInt.Cmp(bigMinInt) < 0 {
return fmt.Errorf("%v is less than minimum value for %T", normalizedInt, *v)
}
*v = int(normalizedInt.Int64())
case *int8:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(bigMaxInt8) > 0 {
return fmt.Errorf("%v is greater than maximum value for %T", normalizedInt, *v)
}
if normalizedInt.Cmp(bigMinInt8) < 0 {
return fmt.Errorf("%v is less than minimum value for %T", normalizedInt, *v)
}
*v = int8(normalizedInt.Int64())
case *int16:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(bigMaxInt16) > 0 {
return fmt.Errorf("%v is greater than maximum value for %T", normalizedInt, *v)
}
if normalizedInt.Cmp(bigMinInt16) < 0 {
return fmt.Errorf("%v is less than minimum value for %T", normalizedInt, *v)
}
*v = int16(normalizedInt.Int64())
case *int32:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(bigMaxInt32) > 0 {
return fmt.Errorf("%v is greater than maximum value for %T", normalizedInt, *v)
}
if normalizedInt.Cmp(bigMinInt32) < 0 {
return fmt.Errorf("%v is less than minimum value for %T", normalizedInt, *v)
}
*v = int32(normalizedInt.Int64())
case *int64:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(bigMaxInt64) > 0 {
return fmt.Errorf("%v is greater than maximum value for %T", normalizedInt, *v)
}
if normalizedInt.Cmp(bigMinInt64) < 0 {
return fmt.Errorf("%v is less than minimum value for %T", normalizedInt, *v)
}
*v = normalizedInt.Int64()
case *uint:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(big0) < 0 {
return fmt.Errorf("%d is less than zero for %T", normalizedInt, *v)
} else if normalizedInt.Cmp(bigMaxUint) > 0 {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = uint(normalizedInt.Uint64())
case *uint8:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(big0) < 0 {
return fmt.Errorf("%d is less than zero for %T", normalizedInt, *v)
} else if normalizedInt.Cmp(bigMaxUint8) > 0 {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = uint8(normalizedInt.Uint64())
case *uint16:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(big0) < 0 {
return fmt.Errorf("%d is less than zero for %T", normalizedInt, *v)
} else if normalizedInt.Cmp(bigMaxUint16) > 0 {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = uint16(normalizedInt.Uint64())
case *uint32:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(big0) < 0 {
return fmt.Errorf("%d is less than zero for %T", normalizedInt, *v)
} else if normalizedInt.Cmp(bigMaxUint32) > 0 {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = uint32(normalizedInt.Uint64())
case *uint64:
normalizedInt, err := src.toBigInt()
if err != nil {
return err
}
if normalizedInt.Cmp(big0) < 0 {
return fmt.Errorf("%d is less than zero for %T", normalizedInt, *v)
} else if normalizedInt.Cmp(bigMaxUint64) > 0 {
return fmt.Errorf("%d is greater than maximum value for %T", normalizedInt, *v)
}
*v = normalizedInt.Uint64()
case *big.Rat:
rat, err := src.toBigRat()
if err != nil {
return err
}
v.Set(rat)
case *string:
buf, err := encodeNumericText(*src, nil)
if err != nil {
return err
}
*v = string(buf)
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return nil
}
func (dst *Numeric) toBigInt() (*big.Int, error) {
if dst.Exp == 0 {
return dst.Int, nil
}
num := &big.Int{}
num.Set(dst.Int)
if dst.Exp > 0 {
mul := &big.Int{}
mul.Exp(big10, big.NewInt(int64(dst.Exp)), nil)
num.Mul(num, mul)
return num, nil
}
div := &big.Int{}
div.Exp(big10, big.NewInt(int64(-dst.Exp)), nil)
remainder := &big.Int{}
num.DivMod(num, div, remainder)
if remainder.Cmp(big0) != 0 {
return nil, fmt.Errorf("cannot convert %v to integer", dst)
}
return num, nil
}
func (dst *Numeric) toBigRat() (*big.Rat, error) {
if dst.NaN {
return nil, fmt.Errorf("%v is not a number", dst)
} else if dst.InfinityModifier == Infinity {
return nil, fmt.Errorf("%v is infinity", dst)
} else if dst.InfinityModifier == NegativeInfinity {
return nil, fmt.Errorf("%v is -infinity", dst)
}
num := new(big.Rat).SetInt(dst.Int)
if dst.Exp > 0 {
mul := new(big.Int).Exp(big10, big.NewInt(int64(dst.Exp)), nil)
num.Mul(num, new(big.Rat).SetInt(mul))
} else if dst.Exp < 0 {
mul := new(big.Int).Exp(big10, big.NewInt(int64(-dst.Exp)), nil)
num.Quo(num, new(big.Rat).SetInt(mul))
}
return num, nil
}
func (src *Numeric) toFloat64() (float64, error) {
if src.NaN {
return math.NaN(), nil
} else if src.InfinityModifier == Infinity {
return math.Inf(1), nil
} else if src.InfinityModifier == NegativeInfinity {
return math.Inf(-1), nil
}
buf := make([]byte, 0, 32)
buf = append(buf, src.Int.String()...)
buf = append(buf, 'e')
buf = append(buf, strconv.FormatInt(int64(src.Exp), 10)...)
f, err := strconv.ParseFloat(string(buf), 64)
if err != nil {
return 0, err
}
return f, nil
}
func (dst *Numeric) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Numeric{Status: Null}
return nil
}
if string(src) == "NaN" {
*dst = Numeric{Status: Present, NaN: true}
return nil
} else if string(src) == "Infinity" {
*dst = Numeric{Status: Present, InfinityModifier: Infinity}
return nil
} else if string(src) == "-Infinity" {
*dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity}
return nil
}
num, exp, err := parseNumericString(string(src))
if err != nil {
return err
}
*dst = Numeric{Int: num, Exp: exp, Status: Present}
return nil
}
func parseNumericString(str string) (n *big.Int, exp int32, err error) {
parts := strings.SplitN(str, ".", 2)
digits := strings.Join(parts, "")
if len(parts) > 1 {
exp = int32(-len(parts[1]))
} else {
for len(digits) > 1 && digits[len(digits)-1] == '0' && digits[len(digits)-2] != '-' {
digits = digits[:len(digits)-1]
exp++
}
}
accum := &big.Int{}
if _, ok := accum.SetString(digits, 10); !ok {
return nil, 0, fmt.Errorf("%s is not a number", str)
}
return accum, exp, nil
}
func (dst *Numeric) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Numeric{Status: Null}
return nil
}
if len(src) < 8 {
return fmt.Errorf("numeric incomplete %v", src)
}
rp := 0
ndigits := binary.BigEndian.Uint16(src[rp:])
rp += 2
weight := int16(binary.BigEndian.Uint16(src[rp:]))
rp += 2
sign := binary.BigEndian.Uint16(src[rp:])
rp += 2
dscale := int16(binary.BigEndian.Uint16(src[rp:]))
rp += 2
if sign == pgNumericNaNSign {
*dst = Numeric{Status: Present, NaN: true}
return nil
} else if sign == pgNumericPosInfSign {
*dst = Numeric{Status: Present, InfinityModifier: Infinity}
return nil
} else if sign == pgNumericNegInfSign {
*dst = Numeric{Status: Present, InfinityModifier: NegativeInfinity}
return nil
}
if ndigits == 0 {
*dst = Numeric{Int: big.NewInt(0), Status: Present}
return nil
}
if len(src[rp:]) < int(ndigits)*2 {
return fmt.Errorf("numeric incomplete %v", src)
}
accum := &big.Int{}
for i := 0; i < int(ndigits+3)/4; i++ {
int64accum, bytesRead, digitsRead := nbaseDigitsToInt64(src[rp:])
rp += bytesRead
if i > 0 {
var mul *big.Int
switch digitsRead {
case 1:
mul = bigNBase
case 2:
mul = bigNBaseX2
case 3:
mul = bigNBaseX3
case 4:
mul = bigNBaseX4
default:
return fmt.Errorf("invalid digitsRead: %d (this can't happen)", digitsRead)
}
accum.Mul(accum, mul)
}
accum.Add(accum, big.NewInt(int64accum))
}
exp := (int32(weight) - int32(ndigits) + 1) * 4
if dscale > 0 {
fracNBaseDigits := int16(int32(ndigits) - int32(weight) - 1)
fracDecimalDigits := fracNBaseDigits * 4
if dscale > fracDecimalDigits {
multCount := int(dscale - fracDecimalDigits)
for i := 0; i < multCount; i++ {
accum.Mul(accum, big10)
exp--
}
} else if dscale < fracDecimalDigits {
divCount := int(fracDecimalDigits - dscale)
for i := 0; i < divCount; i++ {
accum.Div(accum, big10)
exp++
}
}
}
reduced := &big.Int{}
remainder := &big.Int{}
if exp >= 0 {
for {
reduced.DivMod(accum, big10, remainder)
if remainder.Cmp(big0) != 0 {
break
}
accum.Set(reduced)
exp++
}
}
if sign != 0 {
accum.Neg(accum)
}
*dst = Numeric{Int: accum, Exp: exp, Status: Present}
return nil
}
func nbaseDigitsToInt64(src []byte) (accum int64, bytesRead, digitsRead int) {
digits := len(src) / 2
if digits > 4 {
digits = 4
}
rp := 0
for i := 0; i < digits; i++ {
if i > 0 {
accum *= nbase
}
accum += int64(binary.BigEndian.Uint16(src[rp:]))
rp += 2
}
return accum, rp, digits
}
func (src Numeric) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.NaN {
buf = append(buf, "NaN"...)
return buf, nil
} else if src.InfinityModifier == Infinity {
buf = append(buf, "Infinity"...)
return buf, nil
} else if src.InfinityModifier == NegativeInfinity {
buf = append(buf, "-Infinity"...)
return buf, nil
}
buf = append(buf, src.Int.String()...)
buf = append(buf, 'e')
buf = append(buf, strconv.FormatInt(int64(src.Exp), 10)...)
return buf, nil
}
func (src Numeric) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.NaN {
buf = pgio.AppendUint64(buf, pgNumericNaN)
return buf, nil
} else if src.InfinityModifier == Infinity {
buf = pgio.AppendUint64(buf, pgNumericPosInf)
return buf, nil
} else if src.InfinityModifier == NegativeInfinity {
buf = pgio.AppendUint64(buf, pgNumericNegInf)
return buf, nil
}
var sign int16
if src.Int.Cmp(big0) < 0 {
sign = 16384
}
absInt := &big.Int{}
wholePart := &big.Int{}
fracPart := &big.Int{}
remainder := &big.Int{}
absInt.Abs(src.Int)
// Normalize absInt and exp to where exp is always a multiple of 4. This makes
// converting to 16-bit base 10,000 digits easier.
var exp int32
switch src.Exp % 4 {
case 1, -3:
exp = src.Exp - 1
absInt.Mul(absInt, big10)
case 2, -2:
exp = src.Exp - 2
absInt.Mul(absInt, big100)
case 3, -1:
exp = src.Exp - 3
absInt.Mul(absInt, big1000)
default:
exp = src.Exp
}
if exp < 0 {
divisor := &big.Int{}
divisor.Exp(big10, big.NewInt(int64(-exp)), nil)
wholePart.DivMod(absInt, divisor, fracPart)
fracPart.Add(fracPart, divisor)
} else {
wholePart = absInt
}
var wholeDigits, fracDigits []int16
for wholePart.Cmp(big0) != 0 {
wholePart.DivMod(wholePart, bigNBase, remainder)
wholeDigits = append(wholeDigits, int16(remainder.Int64()))
}
if fracPart.Cmp(big0) != 0 {
for fracPart.Cmp(big1) != 0 {
fracPart.DivMod(fracPart, bigNBase, remainder)
fracDigits = append(fracDigits, int16(remainder.Int64()))
}
}
buf = pgio.AppendInt16(buf, int16(len(wholeDigits)+len(fracDigits)))
var weight int16
if len(wholeDigits) > 0 {
weight = int16(len(wholeDigits) - 1)
if exp > 0 {
weight += int16(exp / 4)
}
} else {
weight = int16(exp/4) - 1 + int16(len(fracDigits))
}
buf = pgio.AppendInt16(buf, weight)
buf = pgio.AppendInt16(buf, sign)
var dscale int16
if src.Exp < 0 {
dscale = int16(-src.Exp)
}
buf = pgio.AppendInt16(buf, dscale)
for i := len(wholeDigits) - 1; i >= 0; i-- {
buf = pgio.AppendInt16(buf, wholeDigits[i])
}
for i := len(fracDigits) - 1; i >= 0; i-- {
buf = pgio.AppendInt16(buf, fracDigits[i])
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Numeric) Scan(src interface{}) error {
if src == nil {
*dst = Numeric{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Numeric) Value() (driver.Value, error) {
switch src.Status {
case Present:
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
return string(buf), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func encodeNumericText(n Numeric, buf []byte) (newBuf []byte, err error) {
// if !n.Valid {
// return nil, nil
// }
if n.NaN {
buf = append(buf, "NaN"...)
return buf, nil
} else if n.InfinityModifier == Infinity {
buf = append(buf, "Infinity"...)
return buf, nil
} else if n.InfinityModifier == NegativeInfinity {
buf = append(buf, "-Infinity"...)
return buf, nil
}
buf = append(buf, n.numberTextBytes()...)
return buf, nil
}
// numberString returns a string of the number. undefined if NaN, infinite, or NULL
func (n Numeric) numberTextBytes() []byte {
intStr := n.Int.String()
buf := &bytes.Buffer{}
exp := int(n.Exp)
if exp > 0 {
buf.WriteString(intStr)
for i := 0; i < exp; i++ {
buf.WriteByte('0')
}
} else if exp < 0 {
if len(intStr) <= -exp {
buf.WriteString("0.")
leadingZeros := -exp - len(intStr)
for i := 0; i < leadingZeros; i++ {
buf.WriteByte('0')
}
buf.WriteString(intStr)
} else if len(intStr) > -exp {
dpPos := len(intStr) + exp
buf.WriteString(intStr[:dpPos])
buf.WriteByte('.')
buf.WriteString(intStr[dpPos:])
}
} else {
buf.WriteString(intStr)
}
return buf.Bytes()
}

View file

@ -1,685 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type NumericArray struct {
Elements []Numeric
Dimensions []ArrayDimension
Status Status
}
func (dst *NumericArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = NumericArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []float32:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*float32:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []float64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*float64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []int64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*int64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []uint64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*uint64:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
elements := make([]Numeric, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = NumericArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Numeric:
if value == nil {
*dst = NumericArray{Status: Null}
} else if len(value) == 0 {
*dst = NumericArray{Status: Present}
} else {
*dst = NumericArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = NumericArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for NumericArray", src)
}
if elementsLength == 0 {
*dst = NumericArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to NumericArray", src)
}
*dst = NumericArray{
Elements: make([]Numeric, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Numeric, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to NumericArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *NumericArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to NumericArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in NumericArray", err)
}
index++
return index, nil
}
func (dst NumericArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *NumericArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]float32:
*v = make([]float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float32:
*v = make([]*float32, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]float64:
*v = make([]float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*float64:
*v = make([]*float64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]int64:
*v = make([]int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*int64:
*v = make([]*int64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]uint64:
*v = make([]uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*uint64:
*v = make([]*uint64, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *NumericArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from NumericArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from NumericArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *NumericArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = NumericArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Numeric
if len(uta.Elements) > 0 {
elements = make([]Numeric, len(uta.Elements))
for i, s := range uta.Elements {
var elem Numeric
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = NumericArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *NumericArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = NumericArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = NumericArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Numeric, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = NumericArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src NumericArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src NumericArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("numeric"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "numeric")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *NumericArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src NumericArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Numrange struct {
Lower Numeric
Upper Numeric
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Numrange) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Numrange{Status: Null}
return nil
}
switch value := src.(type) {
case Numrange:
*dst = value
case *Numrange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Numrange", src)
}
return nil
}
func (dst Numrange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Numrange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Numrange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Numrange{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Numrange{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Numrange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Numrange{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Numrange{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Numrange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Numrange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Numrange) Scan(src interface{}) error {
if src == nil {
*dst = Numrange{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Numrange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,81 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"strconv"
"github.com/jackc/pgio"
)
// OID (Object Identifier Type) is, according to
// https://www.postgresql.org/docs/current/static/datatype-oid.html, used
// internally by PostgreSQL as a primary key for various system tables. It is
// currently implemented as an unsigned four-byte integer. Its definition can be
// found in src/include/postgres_ext.h in the PostgreSQL sources. Because it is
// so frequently required to be in a NOT NULL condition OID cannot be NULL. To
// allow for NULL OIDs use OIDValue.
type OID uint32
func (dst *OID) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
return fmt.Errorf("cannot decode nil into OID")
}
n, err := strconv.ParseUint(string(src), 10, 32)
if err != nil {
return err
}
*dst = OID(n)
return nil
}
func (dst *OID) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
return fmt.Errorf("cannot decode nil into OID")
}
if len(src) != 4 {
return fmt.Errorf("invalid length: %v", len(src))
}
n := binary.BigEndian.Uint32(src)
*dst = OID(n)
return nil
}
func (src OID) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return append(buf, strconv.FormatUint(uint64(src), 10)...), nil
}
func (src OID) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return pgio.AppendUint32(buf, uint32(src)), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *OID) Scan(src interface{}) error {
if src == nil {
return fmt.Errorf("cannot scan NULL into %T", src)
}
switch src := src.(type) {
case int64:
*dst = OID(src)
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src OID) Value() (driver.Value, error) {
return int64(src), nil
}

View file

@ -1,55 +0,0 @@
package pgtype
import (
"database/sql/driver"
)
// OIDValue (Object Identifier Type) is, according to
// https://www.postgresql.org/docs/current/static/datatype-OIDValue.html, used
// internally by PostgreSQL as a primary key for various system tables. It is
// currently implemented as an unsigned four-byte integer. Its definition can be
// found in src/include/postgres_ext.h in the PostgreSQL sources.
type OIDValue pguint32
// Set converts from src to dst. Note that as OIDValue is not a general
// number type Set does not do automatic type conversion as other number
// types do.
func (dst *OIDValue) Set(src interface{}) error {
return (*pguint32)(dst).Set(src)
}
func (dst OIDValue) Get() interface{} {
return (pguint32)(dst).Get()
}
// AssignTo assigns from src to dst. Note that as OIDValue is not a general number
// type AssignTo does not do automatic type conversion as other number types do.
func (src *OIDValue) AssignTo(dst interface{}) error {
return (*pguint32)(src).AssignTo(dst)
}
func (dst *OIDValue) DecodeText(ci *ConnInfo, src []byte) error {
return (*pguint32)(dst).DecodeText(ci, src)
}
func (dst *OIDValue) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*pguint32)(dst).DecodeBinary(ci, src)
}
func (src OIDValue) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
return (pguint32)(src).EncodeText(ci, buf)
}
func (src OIDValue) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return (pguint32)(src).EncodeBinary(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *OIDValue) Scan(src interface{}) error {
return (*pguint32)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src OIDValue) Value() (driver.Value, error) {
return (pguint32)(src).Value()
}

View file

@ -1,195 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Path struct {
P []Vec2
Closed bool
Status Status
}
func (dst *Path) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to Path", src)
}
func (dst Path) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Path) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Path) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Path{Status: Null}
return nil
}
if len(src) < 7 {
return fmt.Errorf("invalid length for Path: %v", len(src))
}
closed := src[0] == '('
points := make([]Vec2, 0)
str := string(src[2:])
for {
end := strings.IndexByte(str, ',')
x, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1:]
end = strings.IndexByte(str, ')')
y, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
points = append(points, Vec2{x, y})
if end+3 < len(str) {
str = str[end+3:]
} else {
break
}
}
*dst = Path{P: points, Closed: closed, Status: Present}
return nil
}
func (dst *Path) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Path{Status: Null}
return nil
}
if len(src) < 5 {
return fmt.Errorf("invalid length for Path: %v", len(src))
}
closed := src[0] == 1
pointCount := int(binary.BigEndian.Uint32(src[1:]))
rp := 5
if 5+pointCount*16 != len(src) {
return fmt.Errorf("invalid length for Path with %d points: %v", pointCount, len(src))
}
points := make([]Vec2, pointCount)
for i := 0; i < len(points); i++ {
x := binary.BigEndian.Uint64(src[rp:])
rp += 8
y := binary.BigEndian.Uint64(src[rp:])
rp += 8
points[i] = Vec2{math.Float64frombits(x), math.Float64frombits(y)}
}
*dst = Path{
P: points,
Closed: closed,
Status: Present,
}
return nil
}
func (src Path) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var startByte, endByte byte
if src.Closed {
startByte = '('
endByte = ')'
} else {
startByte = '['
endByte = ']'
}
buf = append(buf, startByte)
for i, p := range src.P {
if i > 0 {
buf = append(buf, ',')
}
buf = append(buf, fmt.Sprintf(`(%s,%s)`,
strconv.FormatFloat(p.X, 'f', -1, 64),
strconv.FormatFloat(p.Y, 'f', -1, 64),
)...)
}
return append(buf, endByte), nil
}
func (src Path) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var closeByte byte
if src.Closed {
closeByte = 1
}
buf = append(buf, closeByte)
buf = pgio.AppendInt32(buf, int32(len(src.P)))
for _, p := range src.P {
buf = pgio.AppendUint64(buf, math.Float64bits(p.X))
buf = pgio.AppendUint64(buf, math.Float64bits(p.Y))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Path) Scan(src interface{}) error {
if src == nil {
*dst = Path{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Path) Value() (driver.Value, error) {
return EncodeValueText(src)
}

File diff suppressed because it is too large Load diff

View file

@ -1,162 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"github.com/jackc/pgio"
)
// pguint32 is the core type that is used to implement PostgreSQL types such as
// CID and XID.
type pguint32 struct {
Uint uint32
Status Status
}
// Set converts from src to dst. Note that as pguint32 is not a general
// number type Set does not do automatic type conversion as other number
// types do.
func (dst *pguint32) Set(src interface{}) error {
switch value := src.(type) {
case int64:
if value < 0 {
return fmt.Errorf("%d is less than minimum value for pguint32", value)
}
if value > math.MaxUint32 {
return fmt.Errorf("%d is greater than maximum value for pguint32", value)
}
*dst = pguint32{Uint: uint32(value), Status: Present}
case uint32:
*dst = pguint32{Uint: value, Status: Present}
default:
return fmt.Errorf("cannot convert %v to pguint32", value)
}
return nil
}
func (dst pguint32) Get() interface{} {
switch dst.Status {
case Present:
return dst.Uint
case Null:
return nil
default:
return dst.Status
}
}
// AssignTo assigns from src to dst. Note that as pguint32 is not a general number
// type AssignTo does not do automatic type conversion as other number types do.
func (src *pguint32) AssignTo(dst interface{}) error {
switch v := dst.(type) {
case *uint32:
if src.Status == Present {
*v = src.Uint
} else {
return fmt.Errorf("cannot assign %v into %T", src, dst)
}
case **uint32:
if src.Status == Present {
n := src.Uint
*v = &n
} else {
*v = nil
}
}
return nil
}
func (dst *pguint32) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = pguint32{Status: Null}
return nil
}
n, err := strconv.ParseUint(string(src), 10, 32)
if err != nil {
return err
}
*dst = pguint32{Uint: uint32(n), Status: Present}
return nil
}
func (dst *pguint32) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = pguint32{Status: Null}
return nil
}
if len(src) != 4 {
return fmt.Errorf("invalid length: %v", len(src))
}
n := binary.BigEndian.Uint32(src)
*dst = pguint32{Uint: n, Status: Present}
return nil
}
func (src pguint32) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, strconv.FormatUint(uint64(src.Uint), 10)...), nil
}
func (src pguint32) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return pgio.AppendUint32(buf, src.Uint), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *pguint32) Scan(src interface{}) error {
if src == nil {
*dst = pguint32{Status: Null}
return nil
}
switch src := src.(type) {
case uint32:
*dst = pguint32{Uint: src, Status: Present}
return nil
case int64:
*dst = pguint32{Uint: uint32(src), Status: Present}
return nil
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src pguint32) Value() (driver.Value, error) {
switch src.Status {
case Present:
return int64(src.Uint), nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,214 +0,0 @@
package pgtype
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Vec2 struct {
X float64
Y float64
}
type Point struct {
P Vec2
Status Status
}
func (dst *Point) Set(src interface{}) error {
if src == nil {
dst.Status = Null
return nil
}
err := fmt.Errorf("cannot convert %v to Point", src)
var p *Point
switch value := src.(type) {
case string:
p, err = parsePoint([]byte(value))
case []byte:
p, err = parsePoint(value)
default:
return err
}
if err != nil {
return err
}
*dst = *p
return nil
}
func parsePoint(src []byte) (*Point, error) {
if src == nil || bytes.Compare(src, []byte("null")) == 0 {
return &Point{Status: Null}, nil
}
if len(src) < 5 {
return nil, fmt.Errorf("invalid length for point: %v", len(src))
}
if src[0] == '"' && src[len(src)-1] == '"' {
src = src[1 : len(src)-1]
}
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
if len(parts) < 2 {
return nil, fmt.Errorf("invalid format for point")
}
x, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
return nil, err
}
y, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
return nil, err
}
return &Point{P: Vec2{x, y}, Status: Present}, nil
}
func (dst Point) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Point) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Point) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Point{Status: Null}
return nil
}
if len(src) < 5 {
return fmt.Errorf("invalid length for point: %v", len(src))
}
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
if len(parts) < 2 {
return fmt.Errorf("invalid format for point")
}
x, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
return err
}
y, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
return err
}
*dst = Point{P: Vec2{x, y}, Status: Present}
return nil
}
func (dst *Point) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Point{Status: Null}
return nil
}
if len(src) != 16 {
return fmt.Errorf("invalid length for point: %v", len(src))
}
x := binary.BigEndian.Uint64(src)
y := binary.BigEndian.Uint64(src[8:])
*dst = Point{
P: Vec2{math.Float64frombits(x), math.Float64frombits(y)},
Status: Present,
}
return nil
}
func (src Point) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, fmt.Sprintf(`(%s,%s)`,
strconv.FormatFloat(src.P.X, 'f', -1, 64),
strconv.FormatFloat(src.P.Y, 'f', -1, 64),
)...), nil
}
func (src Point) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint64(buf, math.Float64bits(src.P.X))
buf = pgio.AppendUint64(buf, math.Float64bits(src.P.Y))
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Point) Scan(src interface{}) error {
if src == nil {
*dst = Point{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Point) Value() (driver.Value, error) {
return EncodeValueText(src)
}
func (src Point) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
var buff bytes.Buffer
buff.WriteByte('"')
buff.WriteString(fmt.Sprintf("(%g,%g)", src.P.X, src.P.Y))
buff.WriteByte('"')
return buff.Bytes(), nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Point) UnmarshalJSON(point []byte) error {
p, err := parsePoint(point)
if err != nil {
return err
}
*dst = *p
return nil
}

View file

@ -1,226 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"math"
"strconv"
"strings"
"github.com/jackc/pgio"
)
type Polygon struct {
P []Vec2
Status Status
}
// Set converts src to dest.
//
// src can be nil, string, []float64, and []pgtype.Vec2.
//
// If src is string the format must be ((x1,y1),(x2,y2),...,(xn,yn)).
// Important that there are no spaces in it.
func (dst *Polygon) Set(src interface{}) error {
if src == nil {
dst.Status = Null
return nil
}
err := fmt.Errorf("cannot convert %v to Polygon", src)
var p *Polygon
switch value := src.(type) {
case string:
p, err = stringToPolygon(value)
case []Vec2:
p = &Polygon{Status: Present, P: value}
err = nil
case []float64:
p, err = float64ToPolygon(value)
default:
return err
}
if err != nil {
return err
}
*dst = *p
return nil
}
func stringToPolygon(src string) (*Polygon, error) {
p := &Polygon{}
err := p.DecodeText(nil, []byte(src))
return p, err
}
func float64ToPolygon(src []float64) (*Polygon, error) {
p := &Polygon{Status: Null}
if len(src) == 0 {
return p, nil
}
if len(src)%2 != 0 {
p.Status = Undefined
return p, fmt.Errorf("invalid length for polygon: %v", len(src))
}
p.Status = Present
p.P = make([]Vec2, 0)
for i := 0; i < len(src); i += 2 {
p.P = append(p.P, Vec2{X: src[i], Y: src[i+1]})
}
return p, nil
}
func (dst Polygon) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Polygon) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Polygon) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Polygon{Status: Null}
return nil
}
if len(src) < 7 {
return fmt.Errorf("invalid length for Polygon: %v", len(src))
}
points := make([]Vec2, 0)
str := string(src[2:])
for {
end := strings.IndexByte(str, ',')
x, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
str = str[end+1:]
end = strings.IndexByte(str, ')')
y, err := strconv.ParseFloat(str[:end], 64)
if err != nil {
return err
}
points = append(points, Vec2{x, y})
if end+3 < len(str) {
str = str[end+3:]
} else {
break
}
}
*dst = Polygon{P: points, Status: Present}
return nil
}
func (dst *Polygon) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Polygon{Status: Null}
return nil
}
if len(src) < 5 {
return fmt.Errorf("invalid length for Polygon: %v", len(src))
}
pointCount := int(binary.BigEndian.Uint32(src))
rp := 4
if 4+pointCount*16 != len(src) {
return fmt.Errorf("invalid length for Polygon with %d points: %v", pointCount, len(src))
}
points := make([]Vec2, pointCount)
for i := 0; i < len(points); i++ {
x := binary.BigEndian.Uint64(src[rp:])
rp += 8
y := binary.BigEndian.Uint64(src[rp:])
rp += 8
points[i] = Vec2{math.Float64frombits(x), math.Float64frombits(y)}
}
*dst = Polygon{
P: points,
Status: Present,
}
return nil
}
func (src Polygon) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, '(')
for i, p := range src.P {
if i > 0 {
buf = append(buf, ',')
}
buf = append(buf, fmt.Sprintf(`(%s,%s)`,
strconv.FormatFloat(p.X, 'f', -1, 64),
strconv.FormatFloat(p.Y, 'f', -1, 64),
)...)
}
return append(buf, ')'), nil
}
func (src Polygon) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt32(buf, int32(len(src.P)))
for _, p := range src.P {
buf = pgio.AppendUint64(buf, math.Float64bits(p.X))
buf = pgio.AppendUint64(buf, math.Float64bits(p.Y))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Polygon) Scan(src interface{}) error {
if src == nil {
*dst = Polygon{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Polygon) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,152 +0,0 @@
package pgtype
import (
"fmt"
"math"
"strconv"
)
// QChar is for PostgreSQL's special 8-bit-only "char" type more akin to the C
// language's char type, or Go's byte type. (Note that the name in PostgreSQL
// itself is "char", in double-quotes, and not char.) It gets used a lot in
// PostgreSQL's system tables to hold a single ASCII character value (eg
// pg_class.relkind). It is named Qchar for quoted char to disambiguate from SQL
// standard type char.
//
// Not all possible values of QChar are representable in the text format.
// Therefore, QChar does not implement TextEncoder and TextDecoder. In
// addition, database/sql Scanner and database/sql/driver Value are not
// implemented.
type QChar struct {
Int int8
Status Status
}
func (dst *QChar) Set(src interface{}) error {
if src == nil {
*dst = QChar{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case int8:
*dst = QChar{Int: value, Status: Present}
case uint8:
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case int16:
if value < math.MinInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case uint16:
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case int32:
if value < math.MinInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case uint32:
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case int64:
if value < math.MinInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case uint64:
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case int:
if value < math.MinInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case uint:
if value > math.MaxInt8 {
return fmt.Errorf("%d is greater than maximum value for QChar", value)
}
*dst = QChar{Int: int8(value), Status: Present}
case string:
num, err := strconv.ParseInt(value, 10, 8)
if err != nil {
return err
}
*dst = QChar{Int: int8(num), Status: Present}
default:
if originalSrc, ok := underlyingNumberType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to QChar", value)
}
return nil
}
func (dst QChar) Get() interface{} {
switch dst.Status {
case Present:
return dst.Int
case Null:
return nil
default:
return dst.Status
}
}
func (src *QChar) AssignTo(dst interface{}) error {
return int64AssignTo(int64(src.Int), src.Status, dst)
}
func (dst *QChar) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = QChar{Status: Null}
return nil
}
if len(src) != 1 {
return fmt.Errorf(`invalid length for "char": %v`, len(src))
}
*dst = QChar{Int: int8(src[0]), Status: Present}
return nil
}
func (src QChar) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, byte(src.Int)), nil
}

View file

@ -1,126 +0,0 @@
package pgtype
import (
"fmt"
"reflect"
)
// Record is the generic PostgreSQL record type such as is created with the
// "row" function. Record only implements BinaryDecoder and Value. The text
// format output format from PostgreSQL does not include type information and is
// therefore impossible to decode. No encoders are implemented because
// PostgreSQL does not support input of generic records.
type Record struct {
Fields []Value
Status Status
}
func (dst *Record) Set(src interface{}) error {
if src == nil {
*dst = Record{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case []Value:
*dst = Record{Fields: value, Status: Present}
default:
return fmt.Errorf("cannot convert %v to Record", src)
}
return nil
}
func (dst Record) Get() interface{} {
switch dst.Status {
case Present:
return dst.Fields
case Null:
return nil
default:
return dst.Status
}
}
func (src *Record) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *[]Value:
*v = make([]Value, len(src.Fields))
copy(*v, src.Fields)
return nil
case *[]interface{}:
*v = make([]interface{}, len(src.Fields))
for i := range *v {
(*v)[i] = src.Fields[i].Get()
}
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func prepareNewBinaryDecoder(ci *ConnInfo, fieldOID uint32, v *Value) (BinaryDecoder, error) {
var binaryDecoder BinaryDecoder
if dt, ok := ci.DataTypeForOID(fieldOID); ok {
binaryDecoder, _ = dt.Value.(BinaryDecoder)
} else {
return nil, fmt.Errorf("unknown oid while decoding record: %v", fieldOID)
}
if binaryDecoder == nil {
return nil, fmt.Errorf("no binary decoder registered for: %v", fieldOID)
}
// Duplicate struct to scan into
binaryDecoder = reflect.New(reflect.ValueOf(binaryDecoder).Elem().Type()).Interface().(BinaryDecoder)
*v = binaryDecoder.(Value)
return binaryDecoder, nil
}
func (dst *Record) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Record{Status: Null}
return nil
}
scanner := NewCompositeBinaryScanner(ci, src)
fields := make([]Value, scanner.FieldCount())
for i := 0; scanner.Next(); i++ {
binaryDecoder, err := prepareNewBinaryDecoder(ci, scanner.OID(), &fields[i])
if err != nil {
return err
}
if err = binaryDecoder.DecodeBinary(ci, scanner.Bytes()); err != nil {
return err
}
}
if scanner.Err() != nil {
return scanner.Err()
}
*dst = Record{Fields: fields, Status: Present}
return nil
}

View file

@ -1,318 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"encoding/binary"
"fmt"
"reflect"
)
type RecordArray struct {
Elements []Record
Dimensions []ArrayDimension
Status Status
}
func (dst *RecordArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = RecordArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case [][]Value:
if value == nil {
*dst = RecordArray{Status: Null}
} else if len(value) == 0 {
*dst = RecordArray{Status: Present}
} else {
elements := make([]Record, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = RecordArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Record:
if value == nil {
*dst = RecordArray{Status: Null}
} else if len(value) == 0 {
*dst = RecordArray{Status: Present}
} else {
*dst = RecordArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = RecordArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for RecordArray", src)
}
if elementsLength == 0 {
*dst = RecordArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to RecordArray", src)
}
*dst = RecordArray{
Elements: make([]Record, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Record, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to RecordArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *RecordArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to RecordArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in RecordArray", err)
}
index++
return index, nil
}
func (dst RecordArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *RecordArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[][]Value:
*v = make([][]Value, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *RecordArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from RecordArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from RecordArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *RecordArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = RecordArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = RecordArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Record, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = RecordArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}

View file

@ -1,212 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/json"
"fmt"
)
type Text struct {
String string
Status Status
}
func (dst *Text) Set(src interface{}) error {
if src == nil {
*dst = Text{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case string:
*dst = Text{String: value, Status: Present}
case *string:
if value == nil {
*dst = Text{Status: Null}
} else {
*dst = Text{String: *value, Status: Present}
}
case []byte:
if value == nil {
*dst = Text{Status: Null}
} else {
*dst = Text{String: string(value), Status: Present}
}
case fmt.Stringer:
if value == fmt.Stringer(nil) {
*dst = Text{Status: Null}
} else {
*dst = Text{String: value.String(), Status: Present}
}
default:
// Cannot be part of the switch: If Value() returns nil on
// non-string, we should still try to checks the underlying type
// using reflection.
//
// For example the struct might implement driver.Valuer with
// pointer receiver and fmt.Stringer with value receiver.
if value, ok := src.(driver.Valuer); ok {
if value == driver.Valuer(nil) {
*dst = Text{Status: Null}
return nil
} else {
v, err := value.Value()
if err != nil {
return fmt.Errorf("driver.Valuer Value() method failed: %w", err)
}
// Handles also v == nil case.
if s, ok := v.(string); ok {
*dst = Text{String: s, Status: Present}
return nil
}
}
}
if originalSrc, ok := underlyingStringType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Text", value)
}
return nil
}
func (dst Text) Get() interface{} {
switch dst.Status {
case Present:
return dst.String
case Null:
return nil
default:
return dst.Status
}
}
func (src *Text) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *string:
*v = src.String
return nil
case *[]byte:
*v = make([]byte, len(src.String))
copy(*v, src.String)
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (Text) PreferredResultFormat() int16 {
return TextFormatCode
}
func (dst *Text) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Text{Status: Null}
return nil
}
*dst = Text{String: string(src), Status: Present}
return nil
}
func (dst *Text) DecodeBinary(ci *ConnInfo, src []byte) error {
return dst.DecodeText(ci, src)
}
func (Text) PreferredParamFormat() int16 {
return TextFormatCode
}
func (src Text) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.String...), nil
}
func (src Text) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
return src.EncodeText(ci, buf)
}
// Scan implements the database/sql Scanner interface.
func (dst *Text) Scan(src interface{}) error {
if src == nil {
*dst = Text{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Text) Value() (driver.Value, error) {
switch src.Status {
case Present:
return src.String, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Text) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
return json.Marshal(src.String)
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *Text) UnmarshalJSON(b []byte) error {
var s *string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
if s == nil {
*dst = Text{Status: Null}
} else {
*dst = Text{String: *s, Status: Present}
}
return nil
}

View file

@ -1,517 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type TextArray struct {
Elements []Text
Dimensions []ArrayDimension
Status Status
}
func (dst *TextArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = TextArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []string:
if value == nil {
*dst = TextArray{Status: Null}
} else if len(value) == 0 {
*dst = TextArray{Status: Present}
} else {
elements := make([]Text, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TextArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*string:
if value == nil {
*dst = TextArray{Status: Null}
} else if len(value) == 0 {
*dst = TextArray{Status: Present}
} else {
elements := make([]Text, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TextArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Text:
if value == nil {
*dst = TextArray{Status: Null}
} else if len(value) == 0 {
*dst = TextArray{Status: Present}
} else {
*dst = TextArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = TextArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for TextArray", src)
}
if elementsLength == 0 {
*dst = TextArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to TextArray", src)
}
*dst = TextArray{
Elements: make([]Text, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Text, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to TextArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *TextArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to TextArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in TextArray", err)
}
index++
return index, nil
}
func (dst TextArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TextArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*string:
*v = make([]*string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *TextArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from TextArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from TextArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *TextArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TextArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Text
if len(uta.Elements) > 0 {
elements = make([]Text, len(uta.Elements))
for i, s := range uta.Elements {
var elem Text
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = TextArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *TextArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TextArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = TextArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Text, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = TextArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src TextArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src TextArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("text"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "text")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TextArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TextArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

156
vendor/github.com/jackc/pgtype/tid.go generated vendored
View file

@ -1,156 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"strconv"
"strings"
"github.com/jackc/pgio"
)
// TID is PostgreSQL's Tuple Identifier type.
//
// When one does
//
// select ctid, * from some_table;
//
// it is the data type of the ctid hidden system column.
//
// It is currently implemented as a pair unsigned two byte integers.
// Its conversion functions can be found in src/backend/utils/adt/tid.c
// in the PostgreSQL sources.
type TID struct {
BlockNumber uint32
OffsetNumber uint16
Status Status
}
func (dst *TID) Set(src interface{}) error {
return fmt.Errorf("cannot convert %v to TID", src)
}
func (dst TID) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TID) AssignTo(dst interface{}) error {
if src.Status == Present {
switch v := dst.(type) {
case *string:
*v = fmt.Sprintf(`(%d,%d)`, src.BlockNumber, src.OffsetNumber)
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
}
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *TID) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TID{Status: Null}
return nil
}
if len(src) < 5 {
return fmt.Errorf("invalid length for tid: %v", len(src))
}
parts := strings.SplitN(string(src[1:len(src)-1]), ",", 2)
if len(parts) < 2 {
return fmt.Errorf("invalid format for tid")
}
blockNumber, err := strconv.ParseUint(parts[0], 10, 32)
if err != nil {
return err
}
offsetNumber, err := strconv.ParseUint(parts[1], 10, 16)
if err != nil {
return err
}
*dst = TID{BlockNumber: uint32(blockNumber), OffsetNumber: uint16(offsetNumber), Status: Present}
return nil
}
func (dst *TID) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TID{Status: Null}
return nil
}
if len(src) != 6 {
return fmt.Errorf("invalid length for tid: %v", len(src))
}
*dst = TID{
BlockNumber: binary.BigEndian.Uint32(src),
OffsetNumber: binary.BigEndian.Uint16(src[4:]),
Status: Present,
}
return nil
}
func (src TID) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, fmt.Sprintf(`(%d,%d)`, src.BlockNumber, src.OffsetNumber)...)
return buf, nil
}
func (src TID) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendUint32(buf, src.BlockNumber)
buf = pgio.AppendUint16(buf, src.OffsetNumber)
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TID) Scan(src interface{}) error {
if src == nil {
*dst = TID{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TID) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,231 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"strconv"
"time"
"github.com/jackc/pgio"
)
// Time represents the PostgreSQL time type. The PostgreSQL time is a time of day without time zone.
//
// Time is represented as the number of microseconds since midnight in the same way that PostgreSQL does. Other time
// and date types in pgtype can use time.Time as the underlying representation. However, pgtype.Time type cannot due
// to needing to handle 24:00:00. time.Time converts that to 00:00:00 on the following day.
type Time struct {
Microseconds int64 // Number of microseconds since midnight
Status Status
}
// Set converts src into a Time and stores in dst.
func (dst *Time) Set(src interface{}) error {
if src == nil {
*dst = Time{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case time.Time:
usec := int64(value.Hour())*microsecondsPerHour +
int64(value.Minute())*microsecondsPerMinute +
int64(value.Second())*microsecondsPerSecond +
int64(value.Nanosecond())/1000
*dst = Time{Microseconds: usec, Status: Present}
case *time.Time:
if value == nil {
*dst = Time{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingTimeType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Time", value)
}
return nil
}
func (dst Time) Get() interface{} {
switch dst.Status {
case Present:
return dst.Microseconds
case Null:
return nil
default:
return dst.Status
}
}
func (src *Time) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *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 src.Microseconds > maxRepresentableByTime {
return fmt.Errorf("%d microseconds cannot be represented as time.Time", src.Microseconds)
}
usec := src.Microseconds
hours := usec / microsecondsPerHour
usec -= hours * microsecondsPerHour
minutes := usec / microsecondsPerMinute
usec -= minutes * microsecondsPerMinute
seconds := usec / microsecondsPerSecond
usec -= seconds * microsecondsPerSecond
ns := usec * 1000
*v = time.Date(2000, 1, 1, int(hours), int(minutes), int(seconds), int(ns), time.UTC)
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
// DecodeText decodes from src into dst.
func (dst *Time) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Time{Status: Null}
return nil
}
s := string(src)
if len(s) < 8 {
return fmt.Errorf("cannot decode %v into Time", s)
}
hours, err := strconv.ParseInt(s[0:2], 10, 64)
if err != nil {
return fmt.Errorf("cannot decode %v into Time", s)
}
usec := hours * microsecondsPerHour
minutes, err := strconv.ParseInt(s[3:5], 10, 64)
if err != nil {
return fmt.Errorf("cannot decode %v into Time", s)
}
usec += minutes * microsecondsPerMinute
seconds, err := strconv.ParseInt(s[6:8], 10, 64)
if err != nil {
return fmt.Errorf("cannot decode %v into Time", s)
}
usec += seconds * microsecondsPerSecond
if len(s) > 9 {
fraction := s[9:]
n, err := strconv.ParseInt(fraction, 10, 64)
if err != nil {
return fmt.Errorf("cannot decode %v into Time", s)
}
for i := len(fraction); i < 6; i++ {
n *= 10
}
usec += n
}
*dst = Time{Microseconds: usec, Status: Present}
return nil
}
// DecodeBinary decodes from src into dst.
func (dst *Time) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Time{Status: Null}
return nil
}
if len(src) != 8 {
return fmt.Errorf("invalid length for time: %v", len(src))
}
usec := int64(binary.BigEndian.Uint64(src))
*dst = Time{Microseconds: usec, Status: Present}
return nil
}
// EncodeText writes the text encoding of src into w.
func (src Time) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
usec := src.Microseconds
hours := usec / microsecondsPerHour
usec -= hours * microsecondsPerHour
minutes := usec / microsecondsPerMinute
usec -= minutes * microsecondsPerMinute
seconds := usec / microsecondsPerSecond
usec -= seconds * microsecondsPerSecond
s := fmt.Sprintf("%02d:%02d:%02d.%06d", hours, minutes, seconds, usec)
return append(buf, s...), nil
}
// EncodeBinary writes the binary encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Time) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return pgio.AppendInt64(buf, src.Microseconds), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Time) Scan(src interface{}) error {
if src == nil {
*dst = Time{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
case time.Time:
return dst.Set(src)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Time) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,261 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"strings"
"time"
"github.com/jackc/pgio"
)
const pgTimestampFormat = "2006-01-02 15:04:05.999999999"
// Timestamp represents the PostgreSQL timestamp type. The PostgreSQL
// timestamp does not have a time zone. This presents a problem when
// translating to and from time.Time which requires a time zone. It is highly
// recommended to use timestamptz whenever possible. Timestamp methods either
// convert to UTC or return an error on non-UTC times.
type Timestamp struct {
Time time.Time // Time must always be in UTC.
Status Status
InfinityModifier InfinityModifier
}
// Set converts src into a Timestamp and stores in dst. If src is a
// time.Time in a non-UTC time zone, the time zone is discarded.
func (dst *Timestamp) Set(src interface{}) error {
if src == nil {
*dst = Timestamp{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case time.Time:
*dst = Timestamp{Time: time.Date(value.Year(), value.Month(), value.Day(), value.Hour(), value.Minute(), value.Second(), value.Nanosecond(), time.UTC), Status: Present}
case *time.Time:
if value == nil {
*dst = Timestamp{Status: Null}
} else {
return dst.Set(*value)
}
case string:
return dst.DecodeText(nil, []byte(value))
case *string:
if value == nil {
*dst = Timestamp{Status: Null}
} else {
return dst.Set(*value)
}
case InfinityModifier:
*dst = Timestamp{InfinityModifier: value, Status: Present}
default:
if originalSrc, ok := underlyingTimeType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Timestamp", value)
}
return nil
}
func (dst Timestamp) Get() interface{} {
switch dst.Status {
case Present:
if dst.InfinityModifier != None {
return dst.InfinityModifier
}
return dst.Time
case Null:
return nil
default:
return dst.Status
}
}
func (src *Timestamp) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *time.Time:
if src.InfinityModifier != None {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
*v = src.Time
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
// DecodeText decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Timestamp{Status: Null}
return nil
}
sbuf := string(src)
switch sbuf {
case "infinity":
*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
case "-infinity":
*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
default:
if strings.HasSuffix(sbuf, " BC") {
t, err := time.Parse(pgTimestampFormat, strings.TrimRight(sbuf, " BC"))
t2 := time.Date(1-t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
if err != nil {
return err
}
*dst = Timestamp{Time: t2, Status: Present}
return nil
}
tim, err := time.Parse(pgTimestampFormat, sbuf)
if err != nil {
return err
}
*dst = Timestamp{Time: tim, Status: Present}
}
return nil
}
// DecodeBinary decodes from src into dst. The decoded time is considered to
// be in UTC.
func (dst *Timestamp) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Timestamp{Status: Null}
return nil
}
if len(src) != 8 {
return fmt.Errorf("invalid length for timestamp: %v", len(src))
}
microsecSinceY2K := int64(binary.BigEndian.Uint64(src))
switch microsecSinceY2K {
case infinityMicrosecondOffset:
*dst = Timestamp{Status: Present, InfinityModifier: Infinity}
case negativeInfinityMicrosecondOffset:
*dst = Timestamp{Status: Present, InfinityModifier: -Infinity}
default:
tim := time.Unix(
microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000,
(microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000),
).UTC()
*dst = Timestamp{Time: tim, Status: Present}
}
return nil
}
// EncodeText writes the text encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.Time.Location() != time.UTC {
return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
}
var s string
switch src.InfinityModifier {
case None:
s = src.Time.Truncate(time.Microsecond).Format(pgTimestampFormat)
case Infinity:
s = "infinity"
case NegativeInfinity:
s = "-infinity"
}
return append(buf, s...), nil
}
// EncodeBinary writes the binary encoding of src into w. If src.Time is not in
// the UTC time zone it returns an error.
func (src Timestamp) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if src.Time.Location() != time.UTC {
return nil, fmt.Errorf("cannot encode non-UTC time into timestamp")
}
var microsecSinceY2K int64
switch src.InfinityModifier {
case None:
microsecSinceUnixEpoch := src.Time.Unix()*1000000 + int64(src.Time.Nanosecond())/1000
microsecSinceY2K = microsecSinceUnixEpoch - microsecFromUnixEpochToY2K
case Infinity:
microsecSinceY2K = infinityMicrosecondOffset
case NegativeInfinity:
microsecSinceY2K = negativeInfinityMicrosecondOffset
}
return pgio.AppendInt64(buf, microsecSinceY2K), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Timestamp) Scan(src interface{}) error {
if src == nil {
*dst = Timestamp{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
case time.Time:
*dst = Timestamp{Time: src, Status: Present}
return nil
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Timestamp) Value() (driver.Value, error) {
switch src.Status {
case Present:
if src.InfinityModifier != None {
return src.InfinityModifier.String(), nil
}
return src.Time, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}

View file

@ -1,518 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"time"
"github.com/jackc/pgio"
)
type TimestampArray struct {
Elements []Timestamp
Dimensions []ArrayDimension
Status Status
}
func (dst *TimestampArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = TimestampArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []time.Time:
if value == nil {
*dst = TimestampArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestampArray{Status: Present}
} else {
elements := make([]Timestamp, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TimestampArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*time.Time:
if value == nil {
*dst = TimestampArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestampArray{Status: Present}
} else {
elements := make([]Timestamp, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TimestampArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Timestamp:
if value == nil {
*dst = TimestampArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestampArray{Status: Present}
} else {
*dst = TimestampArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = TimestampArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for TimestampArray", src)
}
if elementsLength == 0 {
*dst = TimestampArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to TimestampArray", src)
}
*dst = TimestampArray{
Elements: make([]Timestamp, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Timestamp, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to TimestampArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *TimestampArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to TimestampArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in TimestampArray", err)
}
index++
return index, nil
}
func (dst TimestampArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TimestampArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]time.Time:
*v = make([]time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*time.Time:
*v = make([]*time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *TimestampArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from TimestampArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from TimestampArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *TimestampArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TimestampArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Timestamp
if len(uta.Elements) > 0 {
elements = make([]Timestamp, len(uta.Elements))
for i, s := range uta.Elements {
var elem Timestamp
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = TimestampArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *TimestampArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TimestampArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = TimestampArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Timestamp, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = TimestampArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src TimestampArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src TimestampArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("timestamp"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "timestamp")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TimestampArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TimestampArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,322 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"encoding/json"
"fmt"
"time"
"github.com/jackc/pgio"
)
const pgTimestamptzHourFormat = "2006-01-02 15:04:05.999999999Z07"
const pgTimestamptzMinuteFormat = "2006-01-02 15:04:05.999999999Z07:00"
const pgTimestamptzSecondFormat = "2006-01-02 15:04:05.999999999Z07:00:00"
const microsecFromUnixEpochToY2K = 946684800 * 1000000
const (
negativeInfinityMicrosecondOffset = -9223372036854775808
infinityMicrosecondOffset = 9223372036854775807
)
type Timestamptz struct {
Time time.Time
Status Status
InfinityModifier InfinityModifier
}
func (dst *Timestamptz) Set(src interface{}) error {
if src == nil {
*dst = Timestamptz{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
switch value := src.(type) {
case time.Time:
*dst = Timestamptz{Time: value, Status: Present}
case *time.Time:
if value == nil {
*dst = Timestamptz{Status: Null}
} else {
return dst.Set(*value)
}
case string:
return dst.DecodeText(nil, []byte(value))
case *string:
if value == nil {
*dst = Timestamptz{Status: Null}
} else {
return dst.Set(*value)
}
case InfinityModifier:
*dst = Timestamptz{InfinityModifier: value, Status: Present}
default:
if originalSrc, ok := underlyingTimeType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to Timestamptz", value)
}
return nil
}
func (dst Timestamptz) Get() interface{} {
switch dst.Status {
case Present:
if dst.InfinityModifier != None {
return dst.InfinityModifier
}
return dst.Time
case Null:
return nil
default:
return dst.Status
}
}
func (src *Timestamptz) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *time.Time:
if src.InfinityModifier != None {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
*v = src.Time
return nil
default:
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
return fmt.Errorf("unable to assign to %T", dst)
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (dst *Timestamptz) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Timestamptz{Status: Null}
return nil
}
sbuf := string(src)
switch sbuf {
case "infinity":
*dst = Timestamptz{Status: Present, InfinityModifier: Infinity}
case "-infinity":
*dst = Timestamptz{Status: Present, InfinityModifier: -Infinity}
default:
var format string
if len(sbuf) >= 9 && (sbuf[len(sbuf)-9] == '-' || sbuf[len(sbuf)-9] == '+') {
format = pgTimestamptzSecondFormat
} else if len(sbuf) >= 6 && (sbuf[len(sbuf)-6] == '-' || sbuf[len(sbuf)-6] == '+') {
format = pgTimestamptzMinuteFormat
} else {
format = pgTimestamptzHourFormat
}
tim, err := time.Parse(format, sbuf)
if err != nil {
return err
}
*dst = Timestamptz{Time: normalizePotentialUTC(tim), Status: Present}
}
return nil
}
func (dst *Timestamptz) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Timestamptz{Status: Null}
return nil
}
if len(src) != 8 {
return fmt.Errorf("invalid length for timestamptz: %v", len(src))
}
microsecSinceY2K := int64(binary.BigEndian.Uint64(src))
switch microsecSinceY2K {
case infinityMicrosecondOffset:
*dst = Timestamptz{Status: Present, InfinityModifier: Infinity}
case negativeInfinityMicrosecondOffset:
*dst = Timestamptz{Status: Present, InfinityModifier: -Infinity}
default:
tim := time.Unix(
microsecFromUnixEpochToY2K/1000000+microsecSinceY2K/1000000,
(microsecFromUnixEpochToY2K%1000000*1000)+(microsecSinceY2K%1000000*1000),
)
*dst = Timestamptz{Time: tim, Status: Present}
}
return nil
}
func (src Timestamptz) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var s string
switch src.InfinityModifier {
case None:
s = src.Time.UTC().Truncate(time.Microsecond).Format(pgTimestamptzSecondFormat)
case Infinity:
s = "infinity"
case NegativeInfinity:
s = "-infinity"
}
return append(buf, s...), nil
}
func (src Timestamptz) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var microsecSinceY2K int64
switch src.InfinityModifier {
case None:
microsecSinceUnixEpoch := src.Time.Unix()*1000000 + int64(src.Time.Nanosecond())/1000
microsecSinceY2K = microsecSinceUnixEpoch - microsecFromUnixEpochToY2K
case Infinity:
microsecSinceY2K = infinityMicrosecondOffset
case NegativeInfinity:
microsecSinceY2K = negativeInfinityMicrosecondOffset
}
return pgio.AppendInt64(buf, microsecSinceY2K), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Timestamptz) Scan(src interface{}) error {
if src == nil {
*dst = Timestamptz{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
case time.Time:
*dst = Timestamptz{Time: src, Status: Present}
return nil
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Timestamptz) Value() (driver.Value, error) {
switch src.Status {
case Present:
if src.InfinityModifier != None {
return src.InfinityModifier.String(), nil
}
if src.Time.Location().String() == time.UTC.String() {
return src.Time.UTC(), nil
}
return src.Time, nil
case Null:
return nil, nil
default:
return nil, errUndefined
}
}
func (src Timestamptz) MarshalJSON() ([]byte, error) {
switch src.Status {
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
if src.Status != Present {
return nil, errBadStatus
}
var s string
switch src.InfinityModifier {
case None:
s = src.Time.Format(time.RFC3339Nano)
case Infinity:
s = "infinity"
case NegativeInfinity:
s = "-infinity"
}
return json.Marshal(s)
}
func (dst *Timestamptz) UnmarshalJSON(b []byte) error {
var s *string
err := json.Unmarshal(b, &s)
if err != nil {
return err
}
if s == nil {
*dst = Timestamptz{Status: Null}
return nil
}
switch *s {
case "infinity":
*dst = Timestamptz{Status: Present, InfinityModifier: Infinity}
case "-infinity":
*dst = Timestamptz{Status: Present, InfinityModifier: -Infinity}
default:
// PostgreSQL uses ISO 8601 for to_json function and casting from a string to timestamptz
tim, err := time.Parse(time.RFC3339Nano, *s)
if err != nil {
return err
}
*dst = Timestamptz{Time: normalizePotentialUTC(tim), Status: Present}
}
return nil
}
// Normalize timestamps in UTC location to behave similarly to how the Golang
// standard library does it: UTC timestamps lack a .loc value.
//
// Reason for this: when comparing two timestamps with reflect.DeepEqual (generally
// speaking not a good idea, but several testing libraries (for example testify)
// does this), their location data needs to be equal for them to be considered
// equal.
func normalizePotentialUTC(timestamp time.Time) time.Time {
if timestamp.Location().String() != time.UTC.String() {
return timestamp
}
return timestamp.UTC()
}

View file

@ -1,518 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"time"
"github.com/jackc/pgio"
)
type TimestamptzArray struct {
Elements []Timestamptz
Dimensions []ArrayDimension
Status Status
}
func (dst *TimestamptzArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = TimestamptzArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []time.Time:
if value == nil {
*dst = TimestamptzArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestamptzArray{Status: Present}
} else {
elements := make([]Timestamptz, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TimestamptzArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*time.Time:
if value == nil {
*dst = TimestamptzArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestamptzArray{Status: Present}
} else {
elements := make([]Timestamptz, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = TimestamptzArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []Timestamptz:
if value == nil {
*dst = TimestamptzArray{Status: Null}
} else if len(value) == 0 {
*dst = TimestamptzArray{Status: Present}
} else {
*dst = TimestamptzArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = TimestamptzArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for TimestamptzArray", src)
}
if elementsLength == 0 {
*dst = TimestamptzArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to TimestamptzArray", src)
}
*dst = TimestamptzArray{
Elements: make([]Timestamptz, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Timestamptz, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to TimestamptzArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *TimestamptzArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to TimestamptzArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in TimestamptzArray", err)
}
index++
return index, nil
}
func (dst TimestamptzArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TimestamptzArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]time.Time:
*v = make([]time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*time.Time:
*v = make([]*time.Time, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *TimestamptzArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from TimestamptzArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from TimestamptzArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *TimestamptzArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TimestamptzArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Timestamptz
if len(uta.Elements) > 0 {
elements = make([]Timestamptz, len(uta.Elements))
for i, s := range uta.Elements {
var elem Timestamptz
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = TimestamptzArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *TimestamptzArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TimestamptzArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = TimestamptzArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Timestamptz, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = TimestamptzArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src TimestamptzArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src TimestamptzArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("timestamptz"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "timestamptz")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TimestamptzArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TimestamptzArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Tsrange struct {
Lower Timestamp
Upper Timestamp
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Tsrange) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Tsrange{Status: Null}
return nil
}
switch value := src.(type) {
case Tsrange:
*dst = value
case *Tsrange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Tsrange", src)
}
return nil
}
func (dst Tsrange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Tsrange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Tsrange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Tsrange{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Tsrange{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Tsrange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Tsrange{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Tsrange{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Tsrange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Tsrange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Tsrange) Scan(src interface{}) error {
if src == nil {
*dst = Tsrange{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Tsrange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,470 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type TsrangeArray struct {
Elements []Tsrange
Dimensions []ArrayDimension
Status Status
}
func (dst *TsrangeArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = TsrangeArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []Tsrange:
if value == nil {
*dst = TsrangeArray{Status: Null}
} else if len(value) == 0 {
*dst = TsrangeArray{Status: Present}
} else {
*dst = TsrangeArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = TsrangeArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for TsrangeArray", src)
}
if elementsLength == 0 {
*dst = TsrangeArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to TsrangeArray", src)
}
*dst = TsrangeArray{
Elements: make([]Tsrange, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Tsrange, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to TsrangeArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *TsrangeArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to TsrangeArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in TsrangeArray", err)
}
index++
return index, nil
}
func (dst TsrangeArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TsrangeArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]Tsrange:
*v = make([]Tsrange, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *TsrangeArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from TsrangeArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from TsrangeArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *TsrangeArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TsrangeArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Tsrange
if len(uta.Elements) > 0 {
elements = make([]Tsrange, len(uta.Elements))
for i, s := range uta.Elements {
var elem Tsrange
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = TsrangeArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *TsrangeArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TsrangeArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = TsrangeArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Tsrange, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = TsrangeArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src TsrangeArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src TsrangeArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("tsrange"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "tsrange")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TsrangeArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TsrangeArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,267 +0,0 @@
package pgtype
import (
"database/sql/driver"
"fmt"
"github.com/jackc/pgio"
)
type Tstzrange struct {
Lower Timestamptz
Upper Timestamptz
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *Tstzrange) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = Tstzrange{Status: Null}
return nil
}
switch value := src.(type) {
case Tstzrange:
*dst = value
case *Tstzrange:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to Tstzrange", src)
}
return nil
}
func (dst Tstzrange) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *Tstzrange) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *Tstzrange) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Tstzrange{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = Tstzrange{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *Tstzrange) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = Tstzrange{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = Tstzrange{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src Tstzrange) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src Tstzrange) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *Tstzrange) Scan(src interface{}) error {
if src == nil {
*dst = Tstzrange{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Tstzrange) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,470 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type TstzrangeArray struct {
Elements []Tstzrange
Dimensions []ArrayDimension
Status Status
}
func (dst *TstzrangeArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = TstzrangeArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case []Tstzrange:
if value == nil {
*dst = TstzrangeArray{Status: Null}
} else if len(value) == 0 {
*dst = TstzrangeArray{Status: Present}
} else {
*dst = TstzrangeArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = TstzrangeArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for TstzrangeArray", src)
}
if elementsLength == 0 {
*dst = TstzrangeArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to TstzrangeArray", src)
}
*dst = TstzrangeArray{
Elements: make([]Tstzrange, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]Tstzrange, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to TstzrangeArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *TstzrangeArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to TstzrangeArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in TstzrangeArray", err)
}
index++
return index, nil
}
func (dst TstzrangeArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *TstzrangeArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[]Tstzrange:
*v = make([]Tstzrange, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *TstzrangeArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from TstzrangeArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from TstzrangeArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *TstzrangeArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TstzrangeArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []Tstzrange
if len(uta.Elements) > 0 {
elements = make([]Tstzrange, len(uta.Elements))
for i, s := range uta.Elements {
var elem Tstzrange
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = TstzrangeArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *TstzrangeArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = TstzrangeArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = TstzrangeArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]Tstzrange, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = TstzrangeArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src TstzrangeArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src TstzrangeArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("tstzrange"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "tstzrange")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *TstzrangeArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src TstzrangeArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

View file

@ -1,512 +0,0 @@
// Code generated by erb. DO NOT EDIT.
<%
# defaults when not explicitly set on command line
binary_format ||= "true"
text_format ||= "true"
text_null ||= "NULL"
encode_binary ||= binary_format
decode_binary ||= binary_format
%>
package pgtype
import (
"bytes"
"fmt"
"io"
"github.com/jackc/pgio"
)
type <%= pgtype_array_type %> struct {
Elements []<%= pgtype_element_type %>
Dimensions []ArrayDimension
Status Status
}
func (dst *<%= pgtype_array_type %>) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = <%= pgtype_array_type %>{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
<% go_array_types.split(",").each do |t| %>
<% if t != "[]#{pgtype_element_type}" %>
case <%= t %>:
if value == nil {
*dst = <%= pgtype_array_type %>{Status: Null}
} else if len(value) == 0 {
*dst = <%= pgtype_array_type %>{Status: Present}
} else {
elements := make([]<%= pgtype_element_type %>, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = <%= pgtype_array_type %>{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
<% end %>
<% end %>
case []<%= pgtype_element_type %>:
if value == nil {
*dst = <%= pgtype_array_type %>{Status: Null}
} else if len(value) == 0 {
*dst = <%= pgtype_array_type %>{Status: Present}
} else {
*dst = <%= pgtype_array_type %>{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status : Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = <%= pgtype_array_type %>{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for <%= pgtype_array_type %>", src)
}
if elementsLength == 0 {
*dst = <%= pgtype_array_type %>{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to <%= pgtype_array_type %>", src)
}
*dst = <%= pgtype_array_type %> {
Elements: make([]<%= pgtype_element_type %>, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]<%= pgtype_element_type %>, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to <%= pgtype_array_type %>, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *<%= pgtype_array_type %>) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to <%= pgtype_array_type %>")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in <%= pgtype_array_type %>", err)
}
index++
return index, nil
}
func (dst <%= pgtype_array_type %>) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *<%= pgtype_array_type %>) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1{
// Attempt to match to select common types:
switch v := dst.(type) {
<% go_array_types.split(",").each do |t| %>
case *<%= t %>:
*v = make(<%= t %>, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
<% end %>
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *<%= pgtype_array_type %>) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr(){
return 0, fmt.Errorf("cannot assign all values from <%= pgtype_array_type %>")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from <%= pgtype_array_type %>")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
<% if text_format == "true" %>
func (dst *<%= pgtype_array_type %>) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= pgtype_array_type %>{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []<%= pgtype_element_type %>
if len(uta.Elements) > 0 {
elements = make([]<%= pgtype_element_type %>, len(uta.Elements))
for i, s := range uta.Elements {
var elem <%= pgtype_element_type %>
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = <%= pgtype_array_type %>{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
<% end %>
<% if decode_binary == "true" %>
func (dst *<%= pgtype_array_type %>) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= pgtype_array_type %>{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = <%= pgtype_array_type %>{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]<%= pgtype_element_type %>, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp:rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = <%= pgtype_array_type %>{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
<% end %>
<% if text_format == "true" %>
func (src <%= pgtype_array_type %>) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `<%= text_null %>`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
<% end %>
<% if encode_binary == "true" %>
func (src <%= pgtype_array_type %>) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("<%= element_type_name %>"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "<%= element_type_name %>")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
<% end %>
<% if text_format == "true" %>
// Scan implements the database/sql Scanner interface.
func (dst *<%= pgtype_array_type %>) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src <%= pgtype_array_type %>) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}
<% end %>

View file

@ -1,31 +0,0 @@
erb pgtype_array_type=Int2Array pgtype_element_type=Int2 go_array_types=[]int16,[]*int16,[]uint16,[]*uint16,[]int32,[]*int32,[]uint32,[]*uint32,[]int64,[]*int64,[]uint64,[]*uint64,[]int,[]*int,[]uint,[]*uint element_type_name=int2 typed_array.go.erb > int2_array.go
erb pgtype_array_type=Int4Array pgtype_element_type=Int4 go_array_types=[]int16,[]*int16,[]uint16,[]*uint16,[]int32,[]*int32,[]uint32,[]*uint32,[]int64,[]*int64,[]uint64,[]*uint64,[]int,[]*int,[]uint,[]*uint element_type_name=int4 typed_array.go.erb > int4_array.go
erb pgtype_array_type=Int8Array pgtype_element_type=Int8 go_array_types=[]int16,[]*int16,[]uint16,[]*uint16,[]int32,[]*int32,[]uint32,[]*uint32,[]int64,[]*int64,[]uint64,[]*uint64,[]int,[]*int,[]uint,[]*uint element_type_name=int8 typed_array.go.erb > int8_array.go
erb pgtype_array_type=BoolArray pgtype_element_type=Bool go_array_types=[]bool,[]*bool element_type_name=bool typed_array.go.erb > bool_array.go
erb pgtype_array_type=DateArray pgtype_element_type=Date go_array_types=[]time.Time,[]*time.Time element_type_name=date typed_array.go.erb > date_array.go
erb pgtype_array_type=TimestamptzArray pgtype_element_type=Timestamptz go_array_types=[]time.Time,[]*time.Time element_type_name=timestamptz typed_array.go.erb > timestamptz_array.go
erb pgtype_array_type=TstzrangeArray pgtype_element_type=Tstzrange go_array_types=[]Tstzrange element_type_name=tstzrange typed_array.go.erb > tstzrange_array.go
erb pgtype_array_type=TsrangeArray pgtype_element_type=Tsrange go_array_types=[]Tsrange element_type_name=tsrange typed_array.go.erb > tsrange_array.go
erb pgtype_array_type=TimestampArray pgtype_element_type=Timestamp go_array_types=[]time.Time,[]*time.Time element_type_name=timestamp typed_array.go.erb > timestamp_array.go
erb pgtype_array_type=Float4Array pgtype_element_type=Float4 go_array_types=[]float32,[]*float32 element_type_name=float4 typed_array.go.erb > float4_array.go
erb pgtype_array_type=Float8Array pgtype_element_type=Float8 go_array_types=[]float64,[]*float64 element_type_name=float8 typed_array.go.erb > float8_array.go
erb pgtype_array_type=InetArray pgtype_element_type=Inet go_array_types=[]*net.IPNet,[]net.IP,[]*net.IP element_type_name=inet typed_array.go.erb > inet_array.go
erb pgtype_array_type=MacaddrArray pgtype_element_type=Macaddr go_array_types=[]net.HardwareAddr,[]*net.HardwareAddr element_type_name=macaddr typed_array.go.erb > macaddr_array.go
erb pgtype_array_type=CIDRArray pgtype_element_type=CIDR go_array_types=[]*net.IPNet,[]net.IP,[]*net.IP element_type_name=cidr typed_array.go.erb > cidr_array.go
erb pgtype_array_type=TextArray pgtype_element_type=Text go_array_types=[]string,[]*string element_type_name=text typed_array.go.erb > text_array.go
erb pgtype_array_type=VarcharArray pgtype_element_type=Varchar go_array_types=[]string,[]*string element_type_name=varchar typed_array.go.erb > varchar_array.go
erb pgtype_array_type=BPCharArray pgtype_element_type=BPChar go_array_types=[]string,[]*string element_type_name=bpchar typed_array.go.erb > bpchar_array.go
erb pgtype_array_type=ByteaArray pgtype_element_type=Bytea go_array_types=[][]byte element_type_name=bytea typed_array.go.erb > bytea_array.go
erb pgtype_array_type=ACLItemArray pgtype_element_type=ACLItem go_array_types=[]string,[]*string element_type_name=aclitem binary_format=false typed_array.go.erb > aclitem_array.go
erb pgtype_array_type=HstoreArray pgtype_element_type=Hstore go_array_types=[]map[string]string element_type_name=hstore typed_array.go.erb > hstore_array.go
erb pgtype_array_type=NumericArray pgtype_element_type=Numeric go_array_types=[]float32,[]*float32,[]float64,[]*float64,[]int64,[]*int64,[]uint64,[]*uint64 element_type_name=numeric typed_array.go.erb > numeric_array.go
erb pgtype_array_type=UUIDArray pgtype_element_type=UUID go_array_types=[][16]byte,[][]byte,[]string,[]*string element_type_name=uuid typed_array.go.erb > uuid_array.go
erb pgtype_array_type=JSONArray pgtype_element_type=JSON go_array_types=[]string,[][]byte,[]json.RawMessage element_type_name=json typed_array.go.erb > json_array.go
erb pgtype_array_type=JSONBArray pgtype_element_type=JSONB go_array_types=[]string,[][]byte,[]json.RawMessage element_type_name=jsonb typed_array.go.erb > jsonb_array.go
# While the binary format is theoretically possible it is only practical to use the text format.
erb pgtype_array_type=EnumArray pgtype_element_type=GenericText go_array_types=[]string,[]*string binary_format=false typed_array.go.erb > enum_array.go
erb pgtype_array_type=RecordArray pgtype_element_type=Record go_array_types=[][]Value element_type_name=record text_null=NULL encode_binary=false text_format=false typed_array.go.erb > record_array.go
goimports -w *_array.go

View file

@ -1,239 +0,0 @@
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"github.com/jackc/pgio"
)
type <%= multirange_type %> struct {
Ranges []<%= range_type %>
Status Status
}
func (dst *<%= multirange_type %>) Set(src interface{}) error {
//untyped nil and typed nil interfaces are different
if src == nil {
*dst = <%= multirange_type %>{Status: Null}
return nil
}
switch value := src.(type) {
case <%= multirange_type %>:
*dst = value
case *<%= multirange_type %>:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
case []<%= range_type %>:
if value == nil {
*dst = <%= multirange_type %>{Status: Null}
} else if len(value) == 0 {
*dst = <%= multirange_type %>{Status: Present}
} else {
elements := make([]<%= range_type %>, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = <%= multirange_type %>{
Ranges: elements,
Status: Present,
}
}
case []*<%= range_type %>:
if value == nil {
*dst = <%= multirange_type %>{Status: Null}
} else if len(value) == 0 {
*dst = <%= multirange_type %>{Status: Present}
} else {
elements := make([]<%= range_type %>, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = <%= multirange_type %>{
Ranges: elements,
Status: Present,
}
}
default:
return fmt.Errorf("cannot convert %v to <%= multirange_type %>", src)
}
return nil
}
func (dst <%= multirange_type %>) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *<%= multirange_type %>) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *<%= multirange_type %>) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= multirange_type %>{Status: Null}
return nil
}
utmr, err := ParseUntypedTextMultirange(string(src))
if err != nil {
return err
}
var elements []<%= range_type %>
if len(utmr.Elements) > 0 {
elements = make([]<%= range_type %>, len(utmr.Elements))
for i, s := range utmr.Elements {
var elem <%= range_type %>
elemSrc := []byte(s)
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = <%= multirange_type %>{Ranges: elements, Status: Present}
return nil
}
func (dst *<%= multirange_type %>) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= multirange_type %>{Status: Null}
return nil
}
rp := 0
numElems := int(binary.BigEndian.Uint32(src[rp:]))
rp += 4
if numElems == 0 {
*dst = <%= multirange_type %>{Status: Present}
return nil
}
elements := make([]<%= range_type %>, numElems)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err := elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = <%= multirange_type %>{Ranges: elements, Status: Present}
return nil
}
func (src <%= multirange_type %>) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = append(buf, '{')
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Ranges {
if i > 0 {
buf = append(buf, ',')
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
return nil, fmt.Errorf("multi-range does not allow null range")
} else {
buf = append(buf, string(elemBuf)...)
}
}
buf = append(buf, '}')
return buf, nil
}
func (src <%= multirange_type %>) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
buf = pgio.AppendInt32(buf, int32(len(src.Ranges)))
for i := range src.Ranges {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Ranges[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *<%= multirange_type %>) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src <%= multirange_type %>) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,8 +0,0 @@
erb range_type=Numrange multirange_type=Nummultirange typed_multirange.go.erb > num_multirange.go
erb range_type=Int4range multirange_type=Int4multirange typed_multirange.go.erb > int4_multirange.go
erb range_type=Int8range multirange_type=Int8multirange typed_multirange.go.erb > int8_multirange.go
# TODO
# erb range_type=Tsrange multirange_type=Tsmultirange typed_multirange.go.erb > ts_multirange.go
# erb range_type=Tstzrange multirange_type=Tstzmultirange typed_multirange.go.erb > tstz_multirange.go
# erb range_type=Daterange multirange_type=Datemultirange typed_multirange.go.erb > date_multirange.go
goimports -w *multirange.go

View file

@ -1,269 +0,0 @@
package pgtype
import (
"bytes"
"database/sql/driver"
"fmt"
"io"
"github.com/jackc/pgio"
)
type <%= range_type %> struct {
Lower <%= element_type %>
Upper <%= element_type %>
LowerType BoundType
UpperType BoundType
Status Status
}
func (dst *<%= range_type %>) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = <%= range_type %>{Status: Null}
return nil
}
switch value := src.(type) {
case <%= range_type %>:
*dst = value
case *<%= range_type %>:
*dst = *value
case string:
return dst.DecodeText(nil, []byte(value))
default:
return fmt.Errorf("cannot convert %v to <%= range_type %>", src)
}
return nil
}
func (dst <%= range_type %>) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *<%= range_type %>) AssignTo(dst interface{}) error {
return fmt.Errorf("cannot assign %v to %T", src, dst)
}
func (dst *<%= range_type %>) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= range_type %>{Status: Null}
return nil
}
utr, err := ParseUntypedTextRange(string(src))
if err != nil {
return err
}
*dst = <%= range_type %>{Status: Present}
dst.LowerType = utr.LowerType
dst.UpperType = utr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeText(ci, []byte(utr.Lower)); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeText(ci, []byte(utr.Upper)); err != nil {
return err
}
}
return nil
}
func (dst *<%= range_type %>) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = <%= range_type %>{Status: Null}
return nil
}
ubr, err := ParseUntypedBinaryRange(src)
if err != nil {
return err
}
*dst = <%= range_type %>{Status: Present}
dst.LowerType = ubr.LowerType
dst.UpperType = ubr.UpperType
if dst.LowerType == Empty {
return nil
}
if dst.LowerType == Inclusive || dst.LowerType == Exclusive {
if err := dst.Lower.DecodeBinary(ci, ubr.Lower); err != nil {
return err
}
}
if dst.UpperType == Inclusive || dst.UpperType == Exclusive {
if err := dst.Upper.DecodeBinary(ci, ubr.Upper); err != nil {
return err
}
}
return nil
}
func (src <%= range_type %>) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
switch src.LowerType {
case Exclusive, Unbounded:
buf = append(buf, '(')
case Inclusive:
buf = append(buf, '[')
case Empty:
return append(buf, "empty"...), nil
default:
return nil, fmt.Errorf("unknown lower bound type %v", src.LowerType)
}
var err error
if src.LowerType != Unbounded {
buf, err = src.Lower.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
}
buf = append(buf, ',')
if src.UpperType != Unbounded {
buf, err = src.Upper.EncodeText(ci, buf)
if err != nil {
return nil, err
} else if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
}
switch src.UpperType {
case Exclusive, Unbounded:
buf = append(buf, ')')
case Inclusive:
buf = append(buf, ']')
default:
return nil, fmt.Errorf("unknown upper bound type %v", src.UpperType)
}
return buf, nil
}
func (src <%= range_type %>) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
var rangeType byte
switch src.LowerType {
case Inclusive:
rangeType |= lowerInclusiveMask
case Unbounded:
rangeType |= lowerUnboundedMask
case Exclusive:
case Empty:
return append(buf, emptyMask), nil
default:
return nil, fmt.Errorf("unknown LowerType: %v", src.LowerType)
}
switch src.UpperType {
case Inclusive:
rangeType |= upperInclusiveMask
case Unbounded:
rangeType |= upperUnboundedMask
case Exclusive:
default:
return nil, fmt.Errorf("unknown UpperType: %v", src.UpperType)
}
buf = append(buf, rangeType)
var err error
if src.LowerType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Lower.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Lower cannot be null unless LowerType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
if src.UpperType != Unbounded {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
buf, err = src.Upper.EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if buf == nil {
return nil, fmt.Errorf("Upper cannot be null unless UpperType is Unbounded")
}
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *<%= range_type %>) Scan(src interface{}) error {
if src == nil {
*dst = <%= range_type %>{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src <%= range_type %>) Value() (driver.Value, error) {
return EncodeValueText(src)
}

View file

@ -1,7 +0,0 @@
erb range_type=Int4range element_type=Int4 typed_range.go.erb > int4range.go
erb range_type=Int8range element_type=Int8 typed_range.go.erb > int8range.go
erb range_type=Tsrange element_type=Timestamp typed_range.go.erb > tsrange.go
erb range_type=Tstzrange element_type=Timestamptz typed_range.go.erb > tstzrange.go
erb range_type=Daterange element_type=Date typed_range.go.erb > daterange.go
erb range_type=Numrange element_type=Numeric typed_range.go.erb > numrange.go
goimports -w *range.go

View file

@ -1,44 +0,0 @@
package pgtype
import "database/sql/driver"
// Unknown represents the PostgreSQL unknown type. It is either a string literal
// or NULL. It is used when PostgreSQL does not know the type of a value. In
// general, this will only be used in pgx when selecting a null value without
// type information. e.g. SELECT NULL;
type Unknown struct {
String string
Status Status
}
func (dst *Unknown) Set(src interface{}) error {
return (*Text)(dst).Set(src)
}
func (dst Unknown) Get() interface{} {
return (Text)(dst).Get()
}
// AssignTo assigns from src to dst. Note that as Unknown is not a general number
// type AssignTo does not do automatic type conversion as other number types do.
func (src *Unknown) AssignTo(dst interface{}) error {
return (*Text)(src).AssignTo(dst)
}
func (dst *Unknown) DecodeText(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeText(ci, src)
}
func (dst *Unknown) DecodeBinary(ci *ConnInfo, src []byte) error {
return (*Text)(dst).DecodeBinary(ci, src)
}
// Scan implements the database/sql Scanner interface.
func (dst *Unknown) Scan(src interface{}) error {
return (*Text)(dst).Scan(src)
}
// Value implements the database/sql/driver Valuer interface.
func (src Unknown) Value() (driver.Value, error) {
return (Text)(src).Value()
}

View file

@ -1,231 +0,0 @@
package pgtype
import (
"bytes"
"database/sql/driver"
"encoding/hex"
"fmt"
)
type UUID struct {
Bytes [16]byte
Status Status
}
func (dst *UUID) Set(src interface{}) error {
if src == nil {
*dst = UUID{Status: Null}
return nil
}
switch value := src.(type) {
case interface{ Get() interface{} }:
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
case fmt.Stringer:
value2 := value.String()
return dst.Set(value2)
case [16]byte:
*dst = UUID{Bytes: value, Status: Present}
case []byte:
if value != nil {
if len(value) != 16 {
return fmt.Errorf("[]byte must be 16 bytes to convert to UUID: %d", len(value))
}
*dst = UUID{Status: Present}
copy(dst.Bytes[:], value)
} else {
*dst = UUID{Status: Null}
}
case string:
uuid, err := parseUUID(value)
if err != nil {
return err
}
*dst = UUID{Bytes: uuid, Status: Present}
case *string:
if value == nil {
*dst = UUID{Status: Null}
} else {
return dst.Set(*value)
}
default:
if originalSrc, ok := underlyingUUIDType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to UUID", value)
}
return nil
}
func (dst UUID) Get() interface{} {
switch dst.Status {
case Present:
return dst.Bytes
case Null:
return nil
default:
return dst.Status
}
}
func (src *UUID) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
switch v := dst.(type) {
case *[16]byte:
*v = src.Bytes
return nil
case *[]byte:
*v = make([]byte, 16)
copy(*v, src.Bytes[:])
return nil
case *string:
*v = encodeUUID(src.Bytes)
return nil
default:
if nextDst, retry := GetAssignToDstType(v); retry {
return src.AssignTo(nextDst)
}
}
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot assign %v into %T", src, dst)
}
// parseUUID converts a string UUID in standard form to a byte array.
func parseUUID(src string) (dst [16]byte, err error) {
switch len(src) {
case 36:
src = src[0:8] + src[9:13] + src[14:18] + src[19:23] + src[24:]
case 32:
// dashes already stripped, assume valid
default:
// assume invalid.
return dst, fmt.Errorf("cannot parse UUID %v", src)
}
buf, err := hex.DecodeString(src)
if err != nil {
return dst, err
}
copy(dst[:], buf)
return dst, err
}
// encodeUUID converts a uuid byte array to UUID standard string form.
func encodeUUID(src [16]byte) string {
return fmt.Sprintf("%x-%x-%x-%x-%x", src[0:4], src[4:6], src[6:8], src[8:10], src[10:16])
}
func (dst *UUID) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = UUID{Status: Null}
return nil
}
if len(src) != 36 {
return fmt.Errorf("invalid length for UUID: %v", len(src))
}
buf, err := parseUUID(string(src))
if err != nil {
return err
}
*dst = UUID{Bytes: buf, Status: Present}
return nil
}
func (dst *UUID) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = UUID{Status: Null}
return nil
}
if len(src) != 16 {
return fmt.Errorf("invalid length for UUID: %v", len(src))
}
*dst = UUID{Status: Present}
copy(dst.Bytes[:], src)
return nil
}
func (src UUID) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, encodeUUID(src.Bytes)...), nil
}
func (src UUID) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
return append(buf, src.Bytes[:]...), nil
}
// Scan implements the database/sql Scanner interface.
func (dst *UUID) Scan(src interface{}) error {
if src == nil {
*dst = UUID{Status: Null}
return nil
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src UUID) Value() (driver.Value, error) {
return EncodeValueText(src)
}
func (src UUID) MarshalJSON() ([]byte, error) {
switch src.Status {
case Present:
var buff bytes.Buffer
buff.WriteByte('"')
buff.WriteString(encodeUUID(src.Bytes))
buff.WriteByte('"')
return buff.Bytes(), nil
case Null:
return []byte("null"), nil
case Undefined:
return nil, errUndefined
}
return nil, errBadStatus
}
func (dst *UUID) UnmarshalJSON(src []byte) error {
if bytes.Compare(src, []byte("null")) == 0 {
return dst.Set(nil)
}
if len(src) != 38 {
return fmt.Errorf("invalid length for UUID: %v", len(src))
}
return dst.Set(string(src[1 : len(src)-1]))
}

View file

@ -1,573 +0,0 @@
// Code generated by erb. DO NOT EDIT.
package pgtype
import (
"database/sql/driver"
"encoding/binary"
"fmt"
"reflect"
"github.com/jackc/pgio"
)
type UUIDArray struct {
Elements []UUID
Dimensions []ArrayDimension
Status Status
}
func (dst *UUIDArray) Set(src interface{}) error {
// untyped nil and typed nil interfaces are different
if src == nil {
*dst = UUIDArray{Status: Null}
return nil
}
if value, ok := src.(interface{ Get() interface{} }); ok {
value2 := value.Get()
if value2 != value {
return dst.Set(value2)
}
}
// Attempt to match to select common types:
switch value := src.(type) {
case [][16]byte:
if value == nil {
*dst = UUIDArray{Status: Null}
} else if len(value) == 0 {
*dst = UUIDArray{Status: Present}
} else {
elements := make([]UUID, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = UUIDArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case [][]byte:
if value == nil {
*dst = UUIDArray{Status: Null}
} else if len(value) == 0 {
*dst = UUIDArray{Status: Present}
} else {
elements := make([]UUID, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = UUIDArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []string:
if value == nil {
*dst = UUIDArray{Status: Null}
} else if len(value) == 0 {
*dst = UUIDArray{Status: Present}
} else {
elements := make([]UUID, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = UUIDArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []*string:
if value == nil {
*dst = UUIDArray{Status: Null}
} else if len(value) == 0 {
*dst = UUIDArray{Status: Present}
} else {
elements := make([]UUID, len(value))
for i := range value {
if err := elements[i].Set(value[i]); err != nil {
return err
}
}
*dst = UUIDArray{
Elements: elements,
Dimensions: []ArrayDimension{{Length: int32(len(elements)), LowerBound: 1}},
Status: Present,
}
}
case []UUID:
if value == nil {
*dst = UUIDArray{Status: Null}
} else if len(value) == 0 {
*dst = UUIDArray{Status: Present}
} else {
*dst = UUIDArray{
Elements: value,
Dimensions: []ArrayDimension{{Length: int32(len(value)), LowerBound: 1}},
Status: Present,
}
}
default:
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
reflectedValue := reflect.ValueOf(src)
if !reflectedValue.IsValid() || reflectedValue.IsZero() {
*dst = UUIDArray{Status: Null}
return nil
}
dimensions, elementsLength, ok := findDimensionsFromValue(reflectedValue, nil, 0)
if !ok {
return fmt.Errorf("cannot find dimensions of %v for UUIDArray", src)
}
if elementsLength == 0 {
*dst = UUIDArray{Status: Present}
return nil
}
if len(dimensions) == 0 {
if originalSrc, ok := underlyingSliceType(src); ok {
return dst.Set(originalSrc)
}
return fmt.Errorf("cannot convert %v to UUIDArray", src)
}
*dst = UUIDArray{
Elements: make([]UUID, elementsLength),
Dimensions: dimensions,
Status: Present,
}
elementCount, err := dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
// Maybe the target was one dimension too far, try again:
if len(dst.Dimensions) > 1 {
dst.Dimensions = dst.Dimensions[:len(dst.Dimensions)-1]
elementsLength = 0
for _, dim := range dst.Dimensions {
if elementsLength == 0 {
elementsLength = int(dim.Length)
} else {
elementsLength *= int(dim.Length)
}
}
dst.Elements = make([]UUID, elementsLength)
elementCount, err = dst.setRecursive(reflectedValue, 0, 0)
if err != nil {
return err
}
} else {
return err
}
}
if elementCount != len(dst.Elements) {
return fmt.Errorf("cannot convert %v to UUIDArray, expected %d dst.Elements, but got %d instead", src, len(dst.Elements), elementCount)
}
}
return nil
}
func (dst *UUIDArray) setRecursive(value reflect.Value, index, dimension int) (int, error) {
switch value.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(dst.Dimensions) == dimension {
break
}
valueLen := value.Len()
if int32(valueLen) != dst.Dimensions[dimension].Length {
return 0, fmt.Errorf("multidimensional arrays must have array expressions with matching dimensions")
}
for i := 0; i < valueLen; i++ {
var err error
index, err = dst.setRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if !value.CanInterface() {
return 0, fmt.Errorf("cannot convert all values to UUIDArray")
}
if err := dst.Elements[index].Set(value.Interface()); err != nil {
return 0, fmt.Errorf("%v in UUIDArray", err)
}
index++
return index, nil
}
func (dst UUIDArray) Get() interface{} {
switch dst.Status {
case Present:
return dst
case Null:
return nil
default:
return dst.Status
}
}
func (src *UUIDArray) AssignTo(dst interface{}) error {
switch src.Status {
case Present:
if len(src.Dimensions) <= 1 {
// Attempt to match to select common types:
switch v := dst.(type) {
case *[][16]byte:
*v = make([][16]byte, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[][]byte:
*v = make([][]byte, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]string:
*v = make([]string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
case *[]*string:
*v = make([]*string, len(src.Elements))
for i := range src.Elements {
if err := src.Elements[i].AssignTo(&((*v)[i])); err != nil {
return err
}
}
return nil
}
}
// Try to convert to something AssignTo can use directly.
if nextDst, retry := GetAssignToDstType(dst); retry {
return src.AssignTo(nextDst)
}
// Fallback to reflection if an optimised match was not found.
// The reflection is necessary for arrays and multidimensional slices,
// but it comes with a 20-50% performance penalty for large arrays/slices
value := reflect.ValueOf(dst)
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
switch value.Kind() {
case reflect.Array, reflect.Slice:
default:
return fmt.Errorf("cannot assign %T to %T", src, dst)
}
if len(src.Elements) == 0 {
if value.Kind() == reflect.Slice {
value.Set(reflect.MakeSlice(value.Type(), 0, 0))
return nil
}
}
elementCount, err := src.assignToRecursive(value, 0, 0)
if err != nil {
return err
}
if elementCount != len(src.Elements) {
return fmt.Errorf("cannot assign %v, needed to assign %d elements, but only assigned %d", dst, len(src.Elements), elementCount)
}
return nil
case Null:
return NullAssignTo(dst)
}
return fmt.Errorf("cannot decode %#v into %T", src, dst)
}
func (src *UUIDArray) assignToRecursive(value reflect.Value, index, dimension int) (int, error) {
switch kind := value.Kind(); kind {
case reflect.Array:
fallthrough
case reflect.Slice:
if len(src.Dimensions) == dimension {
break
}
length := int(src.Dimensions[dimension].Length)
if reflect.Array == kind {
typ := value.Type()
if typ.Len() != length {
return 0, fmt.Errorf("expected size %d array, but %s has size %d array", length, typ, typ.Len())
}
value.Set(reflect.New(typ).Elem())
} else {
value.Set(reflect.MakeSlice(value.Type(), length, length))
}
var err error
for i := 0; i < length; i++ {
index, err = src.assignToRecursive(value.Index(i), index, dimension+1)
if err != nil {
return 0, err
}
}
return index, nil
}
if len(src.Dimensions) != dimension {
return 0, fmt.Errorf("incorrect dimensions, expected %d, found %d", len(src.Dimensions), dimension)
}
if !value.CanAddr() {
return 0, fmt.Errorf("cannot assign all values from UUIDArray")
}
addr := value.Addr()
if !addr.CanInterface() {
return 0, fmt.Errorf("cannot assign all values from UUIDArray")
}
if err := src.Elements[index].AssignTo(addr.Interface()); err != nil {
return 0, err
}
index++
return index, nil
}
func (dst *UUIDArray) DecodeText(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = UUIDArray{Status: Null}
return nil
}
uta, err := ParseUntypedTextArray(string(src))
if err != nil {
return err
}
var elements []UUID
if len(uta.Elements) > 0 {
elements = make([]UUID, len(uta.Elements))
for i, s := range uta.Elements {
var elem UUID
var elemSrc []byte
if s != "NULL" || uta.Quoted[i] {
elemSrc = []byte(s)
}
err = elem.DecodeText(ci, elemSrc)
if err != nil {
return err
}
elements[i] = elem
}
}
*dst = UUIDArray{Elements: elements, Dimensions: uta.Dimensions, Status: Present}
return nil
}
func (dst *UUIDArray) DecodeBinary(ci *ConnInfo, src []byte) error {
if src == nil {
*dst = UUIDArray{Status: Null}
return nil
}
var arrayHeader ArrayHeader
rp, err := arrayHeader.DecodeBinary(ci, src)
if err != nil {
return err
}
if len(arrayHeader.Dimensions) == 0 {
*dst = UUIDArray{Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
elementCount := arrayHeader.Dimensions[0].Length
for _, d := range arrayHeader.Dimensions[1:] {
elementCount *= d.Length
}
elements := make([]UUID, elementCount)
for i := range elements {
elemLen := int(int32(binary.BigEndian.Uint32(src[rp:])))
rp += 4
var elemSrc []byte
if elemLen >= 0 {
elemSrc = src[rp : rp+elemLen]
rp += elemLen
}
err = elements[i].DecodeBinary(ci, elemSrc)
if err != nil {
return err
}
}
*dst = UUIDArray{Elements: elements, Dimensions: arrayHeader.Dimensions, Status: Present}
return nil
}
func (src UUIDArray) EncodeText(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
if len(src.Dimensions) == 0 {
return append(buf, '{', '}'), nil
}
buf = EncodeTextArrayDimensions(buf, src.Dimensions)
// dimElemCounts is the multiples of elements that each array lies on. For
// example, a single dimension array of length 4 would have a dimElemCounts of
// [4]. A multi-dimensional array of lengths [3,5,2] would have a
// dimElemCounts of [30,10,2]. This is used to simplify when to render a '{'
// or '}'.
dimElemCounts := make([]int, len(src.Dimensions))
dimElemCounts[len(src.Dimensions)-1] = int(src.Dimensions[len(src.Dimensions)-1].Length)
for i := len(src.Dimensions) - 2; i > -1; i-- {
dimElemCounts[i] = int(src.Dimensions[i].Length) * dimElemCounts[i+1]
}
inElemBuf := make([]byte, 0, 32)
for i, elem := range src.Elements {
if i > 0 {
buf = append(buf, ',')
}
for _, dec := range dimElemCounts {
if i%dec == 0 {
buf = append(buf, '{')
}
}
elemBuf, err := elem.EncodeText(ci, inElemBuf)
if err != nil {
return nil, err
}
if elemBuf == nil {
buf = append(buf, `NULL`...)
} else {
buf = append(buf, QuoteArrayElementIfNeeded(string(elemBuf))...)
}
for _, dec := range dimElemCounts {
if (i+1)%dec == 0 {
buf = append(buf, '}')
}
}
}
return buf, nil
}
func (src UUIDArray) EncodeBinary(ci *ConnInfo, buf []byte) ([]byte, error) {
switch src.Status {
case Null:
return nil, nil
case Undefined:
return nil, errUndefined
}
arrayHeader := ArrayHeader{
Dimensions: src.Dimensions,
}
if dt, ok := ci.DataTypeForName("uuid"); ok {
arrayHeader.ElementOID = int32(dt.OID)
} else {
return nil, fmt.Errorf("unable to find oid for type name %v", "uuid")
}
for i := range src.Elements {
if src.Elements[i].Status == Null {
arrayHeader.ContainsNull = true
break
}
}
buf = arrayHeader.EncodeBinary(ci, buf)
for i := range src.Elements {
sp := len(buf)
buf = pgio.AppendInt32(buf, -1)
elemBuf, err := src.Elements[i].EncodeBinary(ci, buf)
if err != nil {
return nil, err
}
if elemBuf != nil {
buf = elemBuf
pgio.SetInt32(buf[sp:], int32(len(buf[sp:])-4))
}
}
return buf, nil
}
// Scan implements the database/sql Scanner interface.
func (dst *UUIDArray) Scan(src interface{}) error {
if src == nil {
return dst.DecodeText(nil, nil)
}
switch src := src.(type) {
case string:
return dst.DecodeText(nil, []byte(src))
case []byte:
srcCopy := make([]byte, len(src))
copy(srcCopy, src)
return dst.DecodeText(nil, srcCopy)
}
return fmt.Errorf("cannot scan %T", src)
}
// Value implements the database/sql/driver Valuer interface.
func (src UUIDArray) Value() (driver.Value, error) {
buf, err := src.EncodeText(nil, nil)
if err != nil {
return nil, err
}
if buf == nil {
return nil, nil
}
return string(buf), nil
}

Some files were not shown because too many files have changed in this diff Show more