github.com/jackc/pgx/v5@v5.5.5/pgtype/composite_test.go (about) 1 package pgtype_test 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 pgx "github.com/jackc/pgx/v5" 9 "github.com/jackc/pgx/v5/pgtype" 10 "github.com/stretchr/testify/require" 11 ) 12 13 func TestCompositeCodecTranscode(t *testing.T) { 14 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") 15 16 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { 17 18 _, err := conn.Exec(ctx, `drop type if exists ct_test; 19 20 create type ct_test as ( 21 a text, 22 b int4 23 );`) 24 require.NoError(t, err) 25 defer conn.Exec(ctx, "drop type ct_test") 26 27 dt, err := conn.LoadType(ctx, "ct_test") 28 require.NoError(t, err) 29 conn.TypeMap().RegisterType(dt) 30 31 formats := []struct { 32 name string 33 code int16 34 }{ 35 {name: "TextFormat", code: pgx.TextFormatCode}, 36 {name: "BinaryFormat", code: pgx.BinaryFormatCode}, 37 } 38 39 for _, format := range formats { 40 var a string 41 var b int32 42 43 err := conn.QueryRow(ctx, "select $1::ct_test", pgx.QueryResultFormats{format.code}, 44 pgtype.CompositeFields{"hi", int32(42)}, 45 ).Scan( 46 pgtype.CompositeFields{&a, &b}, 47 ) 48 require.NoErrorf(t, err, "%v", format.name) 49 require.EqualValuesf(t, "hi", a, "%v", format.name) 50 require.EqualValuesf(t, 42, b, "%v", format.name) 51 } 52 }) 53 } 54 55 type point3d struct { 56 X, Y, Z float64 57 } 58 59 func (p point3d) IsNull() bool { 60 return false 61 } 62 63 func (p point3d) Index(i int) any { 64 switch i { 65 case 0: 66 return p.X 67 case 1: 68 return p.Y 69 case 2: 70 return p.Z 71 default: 72 panic("invalid index") 73 } 74 } 75 76 func (p *point3d) ScanNull() error { 77 return fmt.Errorf("cannot scan NULL into point3d") 78 } 79 80 func (p *point3d) ScanIndex(i int) any { 81 switch i { 82 case 0: 83 return &p.X 84 case 1: 85 return &p.Y 86 case 2: 87 return &p.Z 88 default: 89 panic("invalid index") 90 } 91 } 92 93 func TestCompositeCodecTranscodeStruct(t *testing.T) { 94 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") 95 96 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { 97 98 _, err := conn.Exec(ctx, `drop type if exists point3d; 99 100 create type point3d as ( 101 x float8, 102 y float8, 103 z float8 104 );`) 105 require.NoError(t, err) 106 defer conn.Exec(ctx, "drop type point3d") 107 108 dt, err := conn.LoadType(ctx, "point3d") 109 require.NoError(t, err) 110 conn.TypeMap().RegisterType(dt) 111 112 formats := []struct { 113 name string 114 code int16 115 }{ 116 {name: "TextFormat", code: pgx.TextFormatCode}, 117 {name: "BinaryFormat", code: pgx.BinaryFormatCode}, 118 } 119 120 for _, format := range formats { 121 input := point3d{X: 1, Y: 2, Z: 3} 122 var output point3d 123 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) 124 require.NoErrorf(t, err, "%v", format.name) 125 require.Equalf(t, input, output, "%v", format.name) 126 } 127 }) 128 } 129 130 func TestCompositeCodecTranscodeStructWrapper(t *testing.T) { 131 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") 132 133 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { 134 135 _, err := conn.Exec(ctx, `drop type if exists point3d; 136 137 create type point3d as ( 138 x float8, 139 y float8, 140 z float8 141 );`) 142 require.NoError(t, err) 143 defer conn.Exec(ctx, "drop type point3d") 144 145 dt, err := conn.LoadType(ctx, "point3d") 146 require.NoError(t, err) 147 conn.TypeMap().RegisterType(dt) 148 149 formats := []struct { 150 name string 151 code int16 152 }{ 153 {name: "TextFormat", code: pgx.TextFormatCode}, 154 {name: "BinaryFormat", code: pgx.BinaryFormatCode}, 155 } 156 157 type anotherPoint struct { 158 X, Y, Z float64 159 } 160 161 for _, format := range formats { 162 input := anotherPoint{X: 1, Y: 2, Z: 3} 163 var output anotherPoint 164 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) 165 require.NoErrorf(t, err, "%v", format.name) 166 require.Equalf(t, input, output, "%v", format.name) 167 } 168 }) 169 } 170 171 func TestCompositeCodecDecodeValue(t *testing.T) { 172 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") 173 174 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { 175 176 _, err := conn.Exec(ctx, `drop type if exists point3d; 177 178 create type point3d as ( 179 x float8, 180 y float8, 181 z float8 182 );`) 183 require.NoError(t, err) 184 defer conn.Exec(ctx, "drop type point3d") 185 186 dt, err := conn.LoadType(ctx, "point3d") 187 require.NoError(t, err) 188 conn.TypeMap().RegisterType(dt) 189 190 formats := []struct { 191 name string 192 code int16 193 }{ 194 {name: "TextFormat", code: pgx.TextFormatCode}, 195 {name: "BinaryFormat", code: pgx.BinaryFormatCode}, 196 } 197 198 for _, format := range formats { 199 rows, err := conn.Query(ctx, "select '(1,2,3)'::point3d", pgx.QueryResultFormats{format.code}) 200 require.NoErrorf(t, err, "%v", format.name) 201 require.True(t, rows.Next()) 202 values, err := rows.Values() 203 require.NoErrorf(t, err, "%v", format.name) 204 require.Lenf(t, values, 1, "%v", format.name) 205 require.Equalf(t, map[string]any{"x": 1.0, "y": 2.0, "z": 3.0}, values[0], "%v", format.name) 206 require.False(t, rows.Next()) 207 require.NoErrorf(t, rows.Err(), "%v", format.name) 208 } 209 }) 210 } 211 212 // Test for composite type from table instead of create type. Table types have system / hidden columns like tableoid, 213 // cmax, xmax, etc. These are not included when sending or receiving composite types. 214 // 215 // https://github.com/jackc/pgx/issues/1576 216 func TestCompositeCodecTranscodeStructWrapperForTable(t *testing.T) { 217 skipCockroachDB(t, "Server does not support composite types (see https://github.com/cockroachdb/cockroach/issues/27792)") 218 219 defaultConnTestRunner.RunTest(context.Background(), t, func(ctx context.Context, t testing.TB, conn *pgx.Conn) { 220 221 _, err := conn.Exec(ctx, `drop table if exists point3d; 222 223 create table point3d ( 224 x float8, 225 y float8, 226 z float8 227 );`) 228 require.NoError(t, err) 229 defer conn.Exec(ctx, "drop table point3d") 230 231 dt, err := conn.LoadType(ctx, "point3d") 232 require.NoError(t, err) 233 conn.TypeMap().RegisterType(dt) 234 235 formats := []struct { 236 name string 237 code int16 238 }{ 239 {name: "TextFormat", code: pgx.TextFormatCode}, 240 {name: "BinaryFormat", code: pgx.BinaryFormatCode}, 241 } 242 243 type anotherPoint struct { 244 X, Y, Z float64 245 } 246 247 for _, format := range formats { 248 input := anotherPoint{X: 1, Y: 2, Z: 3} 249 var output anotherPoint 250 err := conn.QueryRow(ctx, "select $1::point3d", pgx.QueryResultFormats{format.code}, input).Scan(&output) 251 require.NoErrorf(t, err, "%v", format.name) 252 require.Equalf(t, input, output, "%v", format.name) 253 } 254 }) 255 }