package pkg import ( "context" "fmt" "github.com/jackc/pgtype" "github.com/jackc/pgx/v4" ) type NewInvoiceProductArray []*invoiceProductForm func (src NewInvoiceProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "new_invoice_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { var productId interface{} = form.ProductId.Val if form.ProductId.Val == "" { productId = nil } values = append(values, []interface{}{ productId, form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } type EditedInvoiceProductArray []*invoiceProductForm func (src EditedInvoiceProductArray) EncodeBinary(ci *pgtype.ConnInfo, buf []byte) ([]byte, error) { typeName := "edited_invoice_product[]" dt, ok := ci.DataTypeForName(typeName) if !ok { return nil, fmt.Errorf("unable to find oid for type name %v", typeName) } var values [][]interface{} for _, form := range src { var invoiceProductId interface{} = nil if form.InvoiceProductId.Val != "" { if id := form.InvoiceProductId.Integer(); id > 0 { invoiceProductId = id } } values = append(values, []interface{}{ invoiceProductId, form.ProductId.Val, form.Name.Val, form.Description.Val, form.Price.Val, form.Quantity.Val, form.Discount.Float64() / 100.0, form.Tax.Selected, }) } array := pgtype.NewValue(dt.Value).(pgtype.ValueTranscoder) if err := array.Set(values); err != nil { return nil, err } return array.EncodeBinary(ci, buf) } func registerPgTypes(ctx context.Context, conn *pgx.Conn) error { if _, err := conn.Exec(ctx, "set role to admin"); err != nil { return err } tagNameOID, err := registerPgType(ctx, conn, &pgtype.Text{}, "tag_name") if err != nil { return err } tagNameArray := pgtype.NewArrayType("tag_name[]", tagNameOID, func() pgtype.ValueTranscoder { return &pgtype.Text{} }) if _, err := registerPgType(ctx, conn, tagNameArray, tagNameArray.TypeName()); err != nil { return err } discountRateOID, err := registerPgType(ctx, conn, &pgtype.Numeric{}, "discount_rate") if err != nil { return err } newInvoiceProduct, err := pgtype.NewCompositeType( "new_invoice_product", []pgtype.CompositeTypeField{ {"product_id", pgtype.Int4OID}, {"name", pgtype.TextOID}, {"description", pgtype.TextOID}, {"price", pgtype.TextOID}, {"quantity", pgtype.Int4OID}, {"discount_rate", discountRateOID}, {"tax", pgtype.Int4ArrayOID}, }, conn.ConnInfo(), ) if err != nil { return err } newInvoiceProductOID, err := registerPgType(ctx, conn, newInvoiceProduct, newInvoiceProduct.TypeName()) if err != nil { return err } newInvoiceProductArray := pgtype.NewArrayType("new_invoice_product[]", newInvoiceProductOID, func() pgtype.ValueTranscoder { value := newInvoiceProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, newInvoiceProductArray, newInvoiceProductArray.TypeName()) if err != nil { return err } editedInvoiceProduct, err := pgtype.NewCompositeType( "edited_invoice_product", []pgtype.CompositeTypeField{ {"invoice_product_id", pgtype.Int4OID}, {"product_id", pgtype.Int4OID}, {"name", pgtype.TextOID}, {"description", pgtype.TextOID}, {"price", pgtype.TextOID}, {"quantity", pgtype.Int4OID}, {"discount_rate", discountRateOID}, {"tax", pgtype.Int4ArrayOID}, }, conn.ConnInfo(), ) if err != nil { return err } editedInvoiceProductOID, err := registerPgType(ctx, conn, editedInvoiceProduct, editedInvoiceProduct.TypeName()) if err != nil { return err } editedInvoiceProductArray := pgtype.NewArrayType("edited_invoice_product[]", editedInvoiceProductOID, func() pgtype.ValueTranscoder { value := editedInvoiceProduct.NewTypeValue() return value.(pgtype.ValueTranscoder) }) _, err = registerPgType(ctx, conn, editedInvoiceProductArray, editedInvoiceProductArray.TypeName()) if err != nil { return err } _, err = conn.Exec(ctx, "reset role") return err } func registerPgType(ctx context.Context, conn *pgx.Conn, value pgtype.Value, name string) (oid uint32, err error) { if err = conn.QueryRow(ctx, "select $1::regtype::oid", name).Scan(&oid); err != nil { return } conn.ConnInfo().RegisterDataType(pgtype.DataType{Value: value, Name: name, OID: oid}) return }