...
1 package pgproto3
2
3 import (
4 "encoding/binary"
5 "errors"
6 "math"
7
8 "github.com/jackc/pgx/v5/internal/pgio"
9 )
10
11 type FunctionCall struct {
12 Function uint32
13 ArgFormatCodes []uint16
14 Arguments [][]byte
15 ResultFormatCode uint16
16 }
17
18
19 func (*FunctionCall) Frontend() {}
20
21
22
23 func (dst *FunctionCall) Decode(src []byte) error {
24 *dst = FunctionCall{}
25 rp := 0
26
27 dst.Function = binary.BigEndian.Uint32(src[rp:])
28 rp += 4
29
30
31
32
33 nArgumentCodes := int(binary.BigEndian.Uint16(src[rp:]))
34 rp += 2
35 argumentCodes := make([]uint16, nArgumentCodes)
36 for i := 0; i < nArgumentCodes; i++ {
37
38 ac := binary.BigEndian.Uint16(src[rp:])
39 if ac != 0 && ac != 1 {
40 return &invalidMessageFormatErr{messageType: "FunctionCall"}
41 }
42 argumentCodes[i] = ac
43 rp += 2
44 }
45 dst.ArgFormatCodes = argumentCodes
46
47
48 nArguments := int(binary.BigEndian.Uint16(src[rp:]))
49 rp += 2
50 arguments := make([][]byte, nArguments)
51 for i := 0; i < nArguments; i++ {
52
53
54 argumentLength := int(binary.BigEndian.Uint32(src[rp:]))
55 rp += 4
56 if argumentLength == -1 {
57 arguments[i] = nil
58 } else {
59
60 argumentValue := src[rp : rp+argumentLength]
61 rp += argumentLength
62 arguments[i] = argumentValue
63 }
64 }
65 dst.Arguments = arguments
66
67 resultFormatCode := binary.BigEndian.Uint16(src[rp:])
68 if resultFormatCode != 0 && resultFormatCode != 1 {
69 return &invalidMessageFormatErr{messageType: "FunctionCall"}
70 }
71 dst.ResultFormatCode = resultFormatCode
72 return nil
73 }
74
75
76 func (src *FunctionCall) Encode(dst []byte) ([]byte, error) {
77 dst, sp := beginMessage(dst, 'F')
78 dst = pgio.AppendUint32(dst, src.Function)
79
80 if len(src.ArgFormatCodes) > math.MaxUint16 {
81 return nil, errors.New("too many arg format codes")
82 }
83 dst = pgio.AppendUint16(dst, uint16(len(src.ArgFormatCodes)))
84 for _, argFormatCode := range src.ArgFormatCodes {
85 dst = pgio.AppendUint16(dst, argFormatCode)
86 }
87
88 if len(src.Arguments) > math.MaxUint16 {
89 return nil, errors.New("too many arguments")
90 }
91 dst = pgio.AppendUint16(dst, uint16(len(src.Arguments)))
92 for _, argument := range src.Arguments {
93 if argument == nil {
94 dst = pgio.AppendInt32(dst, -1)
95 } else {
96 dst = pgio.AppendInt32(dst, int32(len(argument)))
97 dst = append(dst, argument...)
98 }
99 }
100 dst = pgio.AppendUint16(dst, src.ResultFormatCode)
101 return finishMessage(dst, sp)
102 }
103
View as plain text