-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using custom types + arrays as pggen.arg() #29
Comments
I think I just ran into the same bug. 6a49d2b lays some groundwork for fixing it. I think the fix requires adjusting the code generation when we have an array type of a composite type. |
I think I misunderstood. I've fixed a couple bugs related to custom types and arrays in outputs but not related to input. I started to look into supporting input fields and it's pretty painful. pggen would have to convert the input type into a p := newProductImageTypeArrayDecoder()
buf := make([]byte, 0, 256)
cn := q.conn.(*pgx.Conn)
if err := p.Set([][]interface{}{
{imgs[0].Source, []interface{}{imgs[0].Dimensions.Width, imgs[0].Dimensions.Height}},
{imgs[1].Source, []interface{}{imgs[1].Dimensions.Width, imgs[1].Dimensions.Height}},
},
); err != nil {
return nil, fmt.Errorf("set parameter: %w", err)
}
text, err := p.EncodeText(cn.ConnInfo(), buf)
if err != nil {
return nil, err
}
row := q.conn.QueryRow(ctx, arrayNested2ParamSQL, string(text)) |
isn't it cobbled together like in the scan function? I thought the generated encoder type (or Value how pgtype calls it) can be available like generated enum types in the package namespace. cannot the same Type/ArrayType be used then use (current version does not generating my composit type go types -> since commit 31e795 - "Introduce DeclarerSet...") |
I switched all decoders over to
I moved all composite type generation into factory functions in the leader file, like The problem is that the I'm guessing the asymmetry exists because it's pretty rare to use structs as query parameters. It's much more common to decode Postgres values into a Go struct. I'll investigate how pgx encodes query parameters but I don't think there's another mechanism. |
I mean, when I have multiple query sql files, structs (incl. decoder functions) are only generated for the first one (it ends in a corrupt go code where the Querier functions try to call unknown functions or return not existend types. |
okey I understand the issue. another idea would be:
advantages
honestly I must learn more about pgx/pgtype, I don't have an exact overview of it, how things work inside it. |
Yea, I figured out a way to do this similar to what you proposed.
type textEncoder struct {
pgtype.ValueTranscoder
}
func (t textEncoder) PreferredParamFormat() int16 { return pgtype.TextFormatCode }
func encodeDimensions(d Dimensions) textEncoder {
dec := newDimensionsDecoder()
dec.Set([]interface{}{d.Width, d.Height})
return textEncoder{ValueTranscoder: dec}
} |
This supports using composite and array types in pggen.arg functions, i.e. as query parameters. Related to #29.
When using the pgtype.Value Set method, we have to use interface{} slices all the way down. Create "assigner" functions that create an []interface slice for composite and array types that we can use from the top level encoder functions. Relates to #29.
- Generate an assigner for every composite and array type to avoid duplicating logic in the encoder and assigner methods. - When calling the array assigner, correctly delegate to the elem assigner if necessary. Relates to #29.
The triple nesting fails with the pgx bug so skip it. Relates to #29.
As expected, this was pretty painful to implement. It works for composite types and arrays of composite types. Give it a go. It breaks if you have triply nested composite types due to a pgx quoting bug: jackc/pgx#874 |
ok I understand now the inner working better. I have two OT questions..
I test pggen currently in a more complex environment, especially the new argument encoder and give then some feedback. |
Yea, I think I might switch the encoder over to
I don't think using
Do you mean using it to look up how to encode parameters? I didn't think about it that much. It's not needed; pggen knows how to encode all the types since they're all generated from the database. |
After jackc/pgtype#100, I think I can drop all the helpers to a single function.
I think I can use this to get the OID and enable binary decoding. Is that what you were getting at? |
Hm I don't get it. I just know that ConnInfo acts as a central type registration. // pgx automatically creates a DataType (oid, name, transcoder typ) by a db lookup (also composit types)
dataType, err := pgxtype.LoadDataType(ctx, conn, connInfo, typeName)
// then register it...
connInfo.RegisterDataType(dataType)
// now defines the destination type for that type
conn.ConnInfo().RegisterDefaultPgType(new(Person), "person") There is no real debug functions for ConnInfo (except |
Allows overriding the ValueTranscoder used by type name with NewQuerierConfig. We can't use the native RegisterDataType because Querier works with pgx.Conn, or pgxpool.Pool which both have query methods but don't both share ConnInfo. - Upgrade pgtype for jackc/pgx#874. Relates to #29 in that it lays the ground work for customizing types.
The original issue of an array of composite types works. Going to close. For example, pggen/example/composite/query.sql.go Line 19 in d158a45
|
Actual:
When using custom types as argument (or an array) the generated code just pass the generated []CustomType go argument to QueryRow()
However
[]CustomType
is not encodable by pgx, so it fails.Expected:
It should create a encodable pgtype Value
(pgtype.NewArrayType)
before passing it to the query.The text was updated successfully, but these errors were encountered: