func (q *DBQuerier) ParamNested2Batch(batch genericBatch, image ProductImageType) {
	batch.Queue(paramNested2SQL, q.types.newProductImageTypeInit(image))
}
ParamNested2Batch implements Querier.ParamNested2Batch.
package complex_params
import (
	"context"
	"fmt"
	"github.com/jackc/pgconn"
	"github.com/jackc/pgtype"
	"github.com/jackc/pgx/v4"
)
type Querier interface {
	ParamArrayInt(ctx context.Context, ints []int) ([]int, error)
	ParamArrayIntBatch(batch genericBatch, ints []int)
	ParamArrayIntScan(results pgx.BatchResults) ([]int, error)
	ParamNested1(ctx context.Context, dimensions Dimensions) (Dimensions, error)
	ParamNested1Batch(batch genericBatch, dimensions Dimensions)
	ParamNested1Scan(results pgx.BatchResults) (Dimensions, error)
	ParamNested2(ctx context.Context, image ProductImageType) (ProductImageType, error)
	ParamNested2Batch(batch genericBatch, image ProductImageType)
	ParamNested2Scan(results pgx.BatchResults) (ProductImageType, error)
	ParamNested2Array(ctx context.Context, images []ProductImageType) ([]ProductImageType, error)
	ParamNested2ArrayBatch(batch genericBatch, images []ProductImageType)
	ParamNested2ArrayScan(results pgx.BatchResults) ([]ProductImageType, error)
	ParamNested3(ctx context.Context, imageSet ProductImageSetType) (ProductImageSetType, error)
	ParamNested3Batch(batch genericBatch, imageSet ProductImageSetType)
	ParamNested3Scan(results pgx.BatchResults) (ProductImageSetType, error)
}
type DBQuerier struct {
	conn  genericConn    
	types *typeResolver  
}
var _ Querier = &DBQuerier{}
type genericConn interface {
	Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
	QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row
	Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)
}
type genericBatch interface {
	Queue(query string, arguments ...interface{})
}
func NewQuerier(conn genericConn) *DBQuerier {
	return NewQuerierConfig(conn, QuerierConfig{})
}
type QuerierConfig struct {
	DataTypes []pgtype.DataType
}
func NewQuerierConfig(conn genericConn, cfg QuerierConfig) *DBQuerier {
	return &DBQuerier{conn: conn, types: newTypeResolver(cfg.DataTypes)}
}
func (q *DBQuerier) WithTx(tx pgx.Tx) (*DBQuerier, error) {
	return &DBQuerier{conn: tx}, nil
}
type preparer interface {
	Prepare(ctx context.Context, name, sql string) (sd *pgconn.StatementDescription, err error)
}
func PrepareAllQueries(ctx context.Context, p preparer) error {
	if _, err := p.Prepare(ctx, paramArrayIntSQL, paramArrayIntSQL); err != nil {
		return fmt.Errorf("prepare query 'ParamArrayInt': %w", err)
	}
	if _, err := p.Prepare(ctx, paramNested1SQL, paramNested1SQL); err != nil {
		return fmt.Errorf("prepare query 'ParamNested1': %w", err)
	}
	if _, err := p.Prepare(ctx, paramNested2SQL, paramNested2SQL); err != nil {
		return fmt.Errorf("prepare query 'ParamNested2': %w", err)
	}
	if _, err := p.Prepare(ctx, paramNested2ArraySQL, paramNested2ArraySQL); err != nil {
		return fmt.Errorf("prepare query 'ParamNested2Array': %w", err)
	}
	if _, err := p.Prepare(ctx, paramNested3SQL, paramNested3SQL); err != nil {
		return fmt.Errorf("prepare query 'ParamNested3': %w", err)
	}
	return nil
}
type Dimensions struct {
	Width  int `json:"width"`
	Height int `json:"height"`
}
type ProductImageSetType struct {
	Name      string             `json:"name"`
	OrigImage ProductImageType   `json:"orig_image"`
	Images    []ProductImageType `json:"images"`
}
type ProductImageType struct {
	Source     string     `json:"source"`
	Dimensions Dimensions `json:"dimensions"`
}
type typeResolver struct {
	connInfo *pgtype.ConnInfo  
}
func newTypeResolver(types []pgtype.DataType) *typeResolver {
	ci := pgtype.NewConnInfo()
	for _, typ := range types {
		if txt, ok := typ.Value.(textPreferrer); ok && typ.OID != unknownOID {
			typ.Value = txt.ValueTranscoder
		}
		ci.RegisterDataType(typ)
	}
	return &typeResolver{connInfo: ci}
}
func (tr *typeResolver) findValue(name string) (uint32, pgtype.ValueTranscoder, bool) {
	typ, ok := tr.connInfo.DataTypeForName(name)
	if !ok {
		return 0, nil, false
	}
	v := pgtype.NewValue(typ.Value)
	return typ.OID, v.(pgtype.ValueTranscoder), true
}
func (tr *typeResolver) setValue(vt pgtype.ValueTranscoder, val interface{}) pgtype.ValueTranscoder {
	if err := vt.Set(val); err != nil {
		panic(fmt.Sprintf("set ValueTranscoder %T to %+v: %s", vt, val, err))
	}
	return vt
}
type compositeField struct {
	name       string                  
	typeName   string                  
	defaultVal pgtype.ValueTranscoder  
}
func (tr *typeResolver) newCompositeValue(name string, fields ...compositeField) pgtype.ValueTranscoder {
	if _, val, ok := tr.findValue(name); ok {
		return val
	}
	fs := make([]pgtype.CompositeTypeField, len(fields))
	vals := make([]pgtype.ValueTranscoder, len(fields))
	isBinaryOk := true
	for i, field := range fields {
		oid, val, ok := tr.findValue(field.typeName)
		if !ok {
			oid = unknownOID
			val = field.defaultVal
		}
		isBinaryOk = isBinaryOk && oid != unknownOID
		fs[i] = pgtype.CompositeTypeField{Name: field.name, OID: oid}
		vals[i] = val
	}
	typ, _ := pgtype.NewCompositeTypeValues(name, fs, vals)
	if !isBinaryOk {
		return textPreferrer{typ, name}
	}
	return typ
}
func (tr *typeResolver) newArrayValue(name, elemName string, defaultVal func() pgtype.ValueTranscoder) pgtype.ValueTranscoder {
	if _, val, ok := tr.findValue(name); ok {
		return val
	}
	elemOID, elemVal, ok := tr.findValue(elemName)
	elemValFunc := func() pgtype.ValueTranscoder {
		return pgtype.NewValue(elemVal).(pgtype.ValueTranscoder)
	}
	if !ok {
		elemOID = unknownOID
		elemValFunc = defaultVal
	}
	typ := pgtype.NewArrayType(name, elemOID, elemValFunc)
	if elemOID == unknownOID {
		return textPreferrer{typ, name}
	}
	return typ
}
func (tr *typeResolver) newDimensions() pgtype.ValueTranscoder {
	return tr.newCompositeValue(
		"dimensions",
		compositeField{"width", "int4", &pgtype.Int4{}},
		compositeField{"height", "int4", &pgtype.Int4{}},
	)
}
func (tr *typeResolver) newDimensionsInit(v Dimensions) pgtype.ValueTranscoder {
	return tr.setValue(tr.newDimensions(), tr.newDimensionsRaw(v))
}
func (tr *typeResolver) newDimensionsRaw(v Dimensions) []interface{} {
	return []interface{}{
		v.Width,
		v.Height,
	}
}
func (tr *typeResolver) newProductImageSetType() pgtype.ValueTranscoder {
	return tr.newCompositeValue(
		"product_image_set_type",
		compositeField{"name", "text", &pgtype.Text{}},
		compositeField{"orig_image", "product_image_type", tr.newProductImageType()},
		compositeField{"images", "_product_image_type", tr.newProductImageTypeArray()},
	)
}
func (tr *typeResolver) newProductImageSetTypeInit(v ProductImageSetType) pgtype.ValueTranscoder {
	return tr.setValue(tr.newProductImageSetType(), tr.newProductImageSetTypeRaw(v))
}
func (tr *typeResolver) newProductImageSetTypeRaw(v ProductImageSetType) []interface{} {
	return []interface{}{
		v.Name,
		tr.newProductImageTypeRaw(v.OrigImage),
		tr.newProductImageTypeArrayRaw(v.Images),
	}
}
func (tr *typeResolver) newProductImageType() pgtype.ValueTranscoder {
	return tr.newCompositeValue(
		"product_image_type",
		compositeField{"source", "text", &pgtype.Text{}},
		compositeField{"dimensions", "dimensions", tr.newDimensions()},
	)
}
func (tr *typeResolver) newProductImageTypeInit(v ProductImageType) pgtype.ValueTranscoder {
	return tr.setValue(tr.newProductImageType(), tr.newProductImageTypeRaw(v))
}
func (tr *typeResolver) newProductImageTypeRaw(v ProductImageType) []interface{} {
	return []interface{}{
		v.Source,
		tr.newDimensionsRaw(v.Dimensions),
	}
}
func (tr *typeResolver) newProductImageTypeArray() pgtype.ValueTranscoder {
	return tr.newArrayValue("_product_image_type", "product_image_type", tr.newProductImageType)
}
func (tr *typeResolver) newProductImageTypeArrayInit(ps []ProductImageType) pgtype.ValueTranscoder {
	dec := tr.newProductImageTypeArray()
	if err := dec.Set(tr.newProductImageTypeArrayRaw(ps)); err != nil {
		panic("encode []ProductImageType: " + err.Error())  
	}
	return textPreferrer{ValueTranscoder: dec, typeName: "_product_image_type"}
}
func (tr *typeResolver) newProductImageTypeArrayRaw(vs []ProductImageType) []interface{} {
	elems := make([]interface{}, len(vs))
	for i, v := range vs {
		elems[i] = tr.newProductImageTypeRaw(v)
	}
	return elems
}
const paramArrayIntSQL = `SELECT $1::bigint[];`
func (q *DBQuerier) ParamArrayInt(ctx context.Context, ints []int) ([]int, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "ParamArrayInt")
	row := q.conn.QueryRow(ctx, paramArrayIntSQL, ints)
	item := []int{}
	if err := row.Scan(&item); err != nil {
		return item, fmt.Errorf("query ParamArrayInt: %w", err)
	}
	return item, nil
}
func (q *DBQuerier) ParamArrayIntBatch(batch genericBatch, ints []int) {
	batch.Queue(paramArrayIntSQL, ints)
}
func (q *DBQuerier) ParamArrayIntScan(results pgx.BatchResults) ([]int, error) {
	row := results.QueryRow()
	item := []int{}
	if err := row.Scan(&item); err != nil {
		return item, fmt.Errorf("scan ParamArrayIntBatch row: %w", err)
	}
	return item, nil
}
const paramNested1SQL = `SELECT $1::dimensions;`
func (q *DBQuerier) ParamNested1(ctx context.Context, dimensions Dimensions) (Dimensions, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "ParamNested1")
	row := q.conn.QueryRow(ctx, paramNested1SQL, q.types.newDimensionsInit(dimensions))
	var item Dimensions
	dimensionsRow := q.types.newDimensions()
	if err := row.Scan(dimensionsRow); err != nil {
		return item, fmt.Errorf("query ParamNested1: %w", err)
	}
	if err := dimensionsRow.AssignTo(&item); err != nil {
		return item, fmt.Errorf("assign ParamNested1 row: %w", err)
	}
	return item, nil
}
func (q *DBQuerier) ParamNested1Batch(batch genericBatch, dimensions Dimensions) {
	batch.Queue(paramNested1SQL, q.types.newDimensionsInit(dimensions))
}
func (q *DBQuerier) ParamNested1Scan(results pgx.BatchResults) (Dimensions, error) {
	row := results.QueryRow()
	var item Dimensions
	dimensionsRow := q.types.newDimensions()
	if err := row.Scan(dimensionsRow); err != nil {
		return item, fmt.Errorf("scan ParamNested1Batch row: %w", err)
	}
	if err := dimensionsRow.AssignTo(&item); err != nil {
		return item, fmt.Errorf("assign ParamNested1 row: %w", err)
	}
	return item, nil
}
const paramNested2SQL = `SELECT $1::product_image_type;`
func (q *DBQuerier) ParamNested2(ctx context.Context, image ProductImageType) (ProductImageType, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "ParamNested2")
	row := q.conn.QueryRow(ctx, paramNested2SQL, q.types.newProductImageTypeInit(image))
	var item ProductImageType
	productImageTypeRow := q.types.newProductImageType()
	if err := row.Scan(productImageTypeRow); err != nil {
		return item, fmt.Errorf("query ParamNested2: %w", err)
	}
	if err := productImageTypeRow.AssignTo(&item); err != nil {
		return item, fmt.Errorf("assign ParamNested2 row: %w", err)
	}
	return item, nil
}