func (q *DBQuerier) FindCompositeTypesScan(results pgx.BatchResults) ([]FindCompositeTypesRow, error) {
	rows, err := results.Query()
	if err != nil {
		return nil, fmt.Errorf("query FindCompositeTypesBatch: %w", err)
	}
	defer rows.Close()
	items := []FindCompositeTypesRow{}
	for rows.Next() {
		var item FindCompositeTypesRow
		if err := rows.Scan(&item.TableTypeName, &item.TableTypeOID, &item.TableName, &item.ColNames, &item.ColOIDs, &item.ColOrders, &item.ColNotNulls, &item.ColTypeNames); err != nil {
			return nil, fmt.Errorf("scan FindCompositeTypesBatch row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindCompositeTypesBatch rows: %w", err)
	}
	return items, err
}
FindCompositeTypesScan implements Querier.FindCompositeTypesScan.
package pg
import (
	"context"
	"fmt"
	"github.com/jackc/pgconn"
	"github.com/jackc/pgtype"
	"github.com/jackc/pgx/v4"
)
type Querier interface {
	FindEnumTypes(ctx context.Context, oids []uint32) ([]FindEnumTypesRow, error)
	FindEnumTypesBatch(batch genericBatch, oids []uint32)
	FindEnumTypesScan(results pgx.BatchResults) ([]FindEnumTypesRow, error)
	FindArrayTypes(ctx context.Context, oids []uint32) ([]FindArrayTypesRow, error)
	FindArrayTypesBatch(batch genericBatch, oids []uint32)
	FindArrayTypesScan(results pgx.BatchResults) ([]FindArrayTypesRow, error)
	FindCompositeTypes(ctx context.Context, oids []uint32) ([]FindCompositeTypesRow, error)
	FindCompositeTypesBatch(batch genericBatch, oids []uint32)
	FindCompositeTypesScan(results pgx.BatchResults) ([]FindCompositeTypesRow, error)
	FindDescendantOIDs(ctx context.Context, oids []uint32) ([]pgtype.OID, error)
	FindDescendantOIDsBatch(batch genericBatch, oids []uint32)
	FindDescendantOIDsScan(results pgx.BatchResults) ([]pgtype.OID, error)
	FindOIDByName(ctx context.Context, name string) (pgtype.OID, error)
	FindOIDByNameBatch(batch genericBatch, name string)
	FindOIDByNameScan(results pgx.BatchResults) (pgtype.OID, error)
	FindOIDName(ctx context.Context, oid pgtype.OID) (pgtype.Name, error)
	FindOIDNameBatch(batch genericBatch, oid pgtype.OID)
	FindOIDNameScan(results pgx.BatchResults) (pgtype.Name, error)
	FindOIDNames(ctx context.Context, oid []uint32) ([]FindOIDNamesRow, error)
	FindOIDNamesBatch(batch genericBatch, oid []uint32)
	FindOIDNamesScan(results pgx.BatchResults) ([]FindOIDNamesRow, 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, findEnumTypesSQL, findEnumTypesSQL); err != nil {
		return fmt.Errorf("prepare query 'FindEnumTypes': %w", err)
	}
	if _, err := p.Prepare(ctx, findArrayTypesSQL, findArrayTypesSQL); err != nil {
		return fmt.Errorf("prepare query 'FindArrayTypes': %w", err)
	}
	if _, err := p.Prepare(ctx, findCompositeTypesSQL, findCompositeTypesSQL); err != nil {
		return fmt.Errorf("prepare query 'FindCompositeTypes': %w", err)
	}
	if _, err := p.Prepare(ctx, findDescendantOIDsSQL, findDescendantOIDsSQL); err != nil {
		return fmt.Errorf("prepare query 'FindDescendantOIDs': %w", err)
	}
	if _, err := p.Prepare(ctx, findOIDByNameSQL, findOIDByNameSQL); err != nil {
		return fmt.Errorf("prepare query 'FindOIDByName': %w", err)
	}
	if _, err := p.Prepare(ctx, findOIDNameSQL, findOIDNameSQL); err != nil {
		return fmt.Errorf("prepare query 'FindOIDName': %w", err)
	}
	if _, err := p.Prepare(ctx, findOIDNamesSQL, findOIDNamesSQL); err != nil {
		return fmt.Errorf("prepare query 'FindOIDNames': %w", err)
	}
	return nil
}
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
}
const findEnumTypesSQL = `WITH enums AS (
  SELECT
    enumtypid::int8                                   AS enum_type,
    -- pg_enum row identifier.
    -- The OIDs for pg_enum rows follow a special rule: even-numbered OIDs
    -- are guaranteed to be ordered in the same way as the sort ordering of
    -- their enum type. That is, if two even OIDs belong to the same enum
    -- type, the smaller OID must have the smaller enumsortorder value.
    -- Odd-numbered OID values need bear no relationship to the sort order.
    -- This rule allows the enum comparison routines to avoid catalog
    -- lookups in many common cases. The routines that create and alter enum
    -- types attempt to assign even OIDs to enum values whenever possible.
    array_agg(oid::int8 ORDER BY enumsortorder)       AS enum_oids,
    -- The sort position of this enum value within its enum type. Starts as
    -- 1..n but can be fractional or negative.
    array_agg(enumsortorder ORDER BY enumsortorder)   AS enum_orders,
    -- The textual label for this enum value
    array_agg(enumlabel::text ORDER BY enumsortorder) AS enum_labels
  FROM pg_enum
  GROUP BY pg_enum.enumtypid)
SELECT
  typ.oid           AS oid,
  -- typename: Data type name.
  typ.typname::text AS type_name,
  enum.enum_oids    AS child_oids,
  enum.enum_orders  AS orders,
  enum.enum_labels  AS labels,
  -- typtype: b for a base type, c for a composite type (e.g., a table's
  -- row type), d for a domain, e for an enum type, p for a pseudo-type,
  -- or r for a range type.
  typ.typtype       AS type_kind,
  -- typdefault is null if the type has no associated default value. If
  -- typdefaultbin is not null, typdefault must contain a human-readable
  -- version of the default expression represented by typdefaultbin. If
  -- typdefaultbin is null and typdefault is not, then typdefault is the
  -- external representation of the type's default value, which can be fed
  -- to the type's input converter to produce a constant.
  COALESCE(typ.typdefault, '')    AS default_expr
FROM pg_type typ
  JOIN enums enum ON typ.oid = enum.enum_type
WHERE typ.typisdefined
  AND typ.typtype = 'e'
  AND typ.oid = ANY ($1::oid[]);`
type FindEnumTypesRow struct {
	OID         pgtype.OID   `json:"oid"`
	TypeName    string       `json:"type_name"`
	ChildOIDs   []int        `json:"child_oids"`
	Orders      []float32    `json:"orders"`
	Labels      []string     `json:"labels"`
	TypeKind    pgtype.QChar `json:"type_kind"`
	DefaultExpr string       `json:"default_expr"`
}
// FindEnumTypes implements Querier.FindEnumTypes.
func (q *DBQuerier) FindEnumTypes(ctx context.Context, oids []uint32) ([]FindEnumTypesRow, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "FindEnumTypes")
	rows, err := q.conn.Query(ctx, findEnumTypesSQL, oids)
	if err != nil {
		return nil, fmt.Errorf("query FindEnumTypes: %w", err)
	}
	defer rows.Close()
	items := []FindEnumTypesRow{}
	for rows.Next() {
		var item FindEnumTypesRow
		if err := rows.Scan(&item.OID, &item.TypeName, &item.ChildOIDs, &item.Orders, &item.Labels, &item.TypeKind, &item.DefaultExpr); err != nil {
			return nil, fmt.Errorf("scan FindEnumTypes row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindEnumTypes rows: %w", err)
	}
	return items, err
}
// FindEnumTypesBatch implements Querier.FindEnumTypesBatch.
func (q *DBQuerier) FindEnumTypesBatch(batch genericBatch, oids []uint32) {
	batch.Queue(findEnumTypesSQL, oids)
}
// FindEnumTypesScan implements Querier.FindEnumTypesScan.
func (q *DBQuerier) FindEnumTypesScan(results pgx.BatchResults) ([]FindEnumTypesRow, error) {
	rows, err := results.Query()
	if err != nil {
		return nil, fmt.Errorf("query FindEnumTypesBatch: %w", err)
	}
	defer rows.Close()
	items := []FindEnumTypesRow{}
	for rows.Next() {
		var item FindEnumTypesRow
		if err := rows.Scan(&item.OID, &item.TypeName, &item.ChildOIDs, &item.Orders, &item.Labels, &item.TypeKind, &item.DefaultExpr); err != nil {
			return nil, fmt.Errorf("scan FindEnumTypesBatch row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindEnumTypesBatch rows: %w", err)
	}
	return items, err
}
const findArrayTypesSQL = `SELECT
  arr_typ.oid           AS oid,
  -- typename: Data type name.
  arr_typ.typname::text AS type_name,
  elem_typ.oid          AS elem_oid,
  -- typtype: b for a base type, c for a composite type (e.g., a table's
  -- row type), d for a domain, e for an enum type, p for a pseudo-type,
  -- or r for a range type.
  arr_typ.typtype       AS type_kind
FROM pg_type arr_typ
  JOIN pg_type elem_typ ON arr_typ.typelem = elem_typ.oid
WHERE arr_typ.typisdefined
  AND arr_typ.typtype = 'b' -- Array types are base types
  -- If typelem is not 0 then it identifies another row in pg_type. The current
  -- type can then be subscripted like an array yielding values of type typelem.
  -- A “true” array type is variable length (typlen = -1), but some
  -- fixed-length (typlen > 0) types also have nonzero typelem, for example
  -- name and point. If a fixed-length type has a typelem then its internal
  -- representation must be some number of values of the typelem data type with
  -- no other data. Variable-length array types have a header defined by the
  -- array subroutines.
  AND arr_typ.typelem > 0
  -- For a fixed-size type, typlen is the number of bytes in the internal
  -- representation of the type. But for a variable-length type, typlen is
  -- negative. -1 indicates a "varlena" type (one that has a length word), -2
  -- indicates a null-terminated C string.
  AND arr_typ.typlen = -1
  AND arr_typ.oid = ANY ($1::oid[]);`
type FindArrayTypesRow struct {
	OID      pgtype.OID   `json:"oid"`
	TypeName string       `json:"type_name"`
	ElemOID  pgtype.OID   `json:"elem_oid"`
	TypeKind pgtype.QChar `json:"type_kind"`
}
func (q *DBQuerier) FindArrayTypes(ctx context.Context, oids []uint32) ([]FindArrayTypesRow, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "FindArrayTypes")
	rows, err := q.conn.Query(ctx, findArrayTypesSQL, oids)
	if err != nil {
		return nil, fmt.Errorf("query FindArrayTypes: %w", err)
	}
	defer rows.Close()
	items := []FindArrayTypesRow{}
	for rows.Next() {
		var item FindArrayTypesRow
		if err := rows.Scan(&item.OID, &item.TypeName, &item.ElemOID, &item.TypeKind); err != nil {
			return nil, fmt.Errorf("scan FindArrayTypes row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindArrayTypes rows: %w", err)
	}
	return items, err
}
func (q *DBQuerier) FindArrayTypesBatch(batch genericBatch, oids []uint32) {
	batch.Queue(findArrayTypesSQL, oids)
}
func (q *DBQuerier) FindArrayTypesScan(results pgx.BatchResults) ([]FindArrayTypesRow, error) {
	rows, err := results.Query()
	if err != nil {
		return nil, fmt.Errorf("query FindArrayTypesBatch: %w", err)
	}
	defer rows.Close()
	items := []FindArrayTypesRow{}
	for rows.Next() {
		var item FindArrayTypesRow
		if err := rows.Scan(&item.OID, &item.TypeName, &item.ElemOID, &item.TypeKind); err != nil {
			return nil, fmt.Errorf("scan FindArrayTypesBatch row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindArrayTypesBatch rows: %w", err)
	}
	return items, err
}
const findCompositeTypesSQL = `WITH table_cols AS (
  SELECT
    cls.relname                                         AS table_name,
    cls.oid                                             AS table_oid,
    array_agg(attr.attname::text ORDER BY attr.attnum)  AS col_names,
    array_agg(attr.atttypid::int8 ORDER BY attr.attnum) AS col_oids,
    array_agg(attr.attnum::int8 ORDER BY attr.attnum)   AS col_orders,
    array_agg(attr.attnotnull ORDER BY attr.attnum)     AS col_not_nulls,
    array_agg(typ.typname::text ORDER BY attr.attnum)   AS col_type_names
  FROM pg_attribute attr
    JOIN pg_class cls ON attr.attrelid = cls.oid
    JOIN pg_type typ ON typ.oid = attr.atttypid
  WHERE attr.attnum > 0 -- Postgres represents system columns with attnum <= 0
    AND NOT attr.attisdropped
  GROUP BY cls.relname, cls.oid
)
SELECT
  typ.typname::text AS table_type_name,
  typ.oid           AS table_type_oid,
  table_name,
  col_names,
  col_oids,
  col_orders,
  col_not_nulls,
  col_type_names
FROM pg_type typ
  JOIN table_cols cols ON typ.typrelid = cols.table_oid
WHERE typ.oid = ANY ($1::oid[])
  AND typ.typtype = 'c';`
type FindCompositeTypesRow struct {
	TableTypeName string           `json:"table_type_name"`
	TableTypeOID  pgtype.OID       `json:"table_type_oid"`
	TableName     pgtype.Name      `json:"table_name"`
	ColNames      []string         `json:"col_names"`
	ColOIDs       []int            `json:"col_oids"`
	ColOrders     []int            `json:"col_orders"`
	ColNotNulls   pgtype.BoolArray `json:"col_not_nulls"`
	ColTypeNames  []string         `json:"col_type_names"`
}
func (q *DBQuerier) FindCompositeTypes(ctx context.Context, oids []uint32) ([]FindCompositeTypesRow, error) {
	ctx = context.WithValue(ctx, "pggen_query_name", "FindCompositeTypes")
	rows, err := q.conn.Query(ctx, findCompositeTypesSQL, oids)
	if err != nil {
		return nil, fmt.Errorf("query FindCompositeTypes: %w", err)
	}
	defer rows.Close()
	items := []FindCompositeTypesRow{}
	for rows.Next() {
		var item FindCompositeTypesRow
		if err := rows.Scan(&item.TableTypeName, &item.TableTypeOID, &item.TableName, &item.ColNames, &item.ColOIDs, &item.ColOrders, &item.ColNotNulls, &item.ColTypeNames); err != nil {
			return nil, fmt.Errorf("scan FindCompositeTypes row: %w", err)
		}
		items = append(items, item)
	}
	if err := rows.Err(); err != nil {
		return nil, fmt.Errorf("close FindCompositeTypes rows: %w", err)
	}
	return items, err
}
func (q *DBQuerier) FindCompositeTypesBatch(batch genericBatch, oids []uint32) {
	batch.Queue(findCompositeTypesSQL, oids)
}