gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

function_call.go (3438B)


      1 package pgproto3
      2 
      3 import (
      4 	"encoding/binary"
      5 
      6 	"github.com/jackc/pgx/v5/internal/pgio"
      7 )
      8 
      9 type FunctionCall struct {
     10 	Function         uint32
     11 	ArgFormatCodes   []uint16
     12 	Arguments        [][]byte
     13 	ResultFormatCode uint16
     14 }
     15 
     16 // Frontend identifies this message as sendable by a PostgreSQL frontend.
     17 func (*FunctionCall) Frontend() {}
     18 
     19 // Decode decodes src into dst. src must contain the complete message with the exception of the initial 1 byte message
     20 // type identifier and 4 byte message length.
     21 func (dst *FunctionCall) Decode(src []byte) error {
     22 	*dst = FunctionCall{}
     23 	rp := 0
     24 	// Specifies the object ID of the function to call.
     25 	dst.Function = binary.BigEndian.Uint32(src[rp:])
     26 	rp += 4
     27 	// The number of argument format codes that follow (denoted C below).
     28 	// This can be zero to indicate that there are no arguments or that the arguments all use the default format (text);
     29 	// or one, in which case the specified format code is applied to all arguments;
     30 	// or it can equal the actual number of arguments.
     31 	nArgumentCodes := int(binary.BigEndian.Uint16(src[rp:]))
     32 	rp += 2
     33 	argumentCodes := make([]uint16, nArgumentCodes)
     34 	for i := 0; i < nArgumentCodes; i++ {
     35 		// The argument format codes. Each must presently be zero (text) or one (binary).
     36 		ac := binary.BigEndian.Uint16(src[rp:])
     37 		if ac != 0 && ac != 1 {
     38 			return &invalidMessageFormatErr{messageType: "FunctionCall"}
     39 		}
     40 		argumentCodes[i] = ac
     41 		rp += 2
     42 	}
     43 	dst.ArgFormatCodes = argumentCodes
     44 
     45 	// Specifies the number of arguments being supplied to the function.
     46 	nArguments := int(binary.BigEndian.Uint16(src[rp:]))
     47 	rp += 2
     48 	arguments := make([][]byte, nArguments)
     49 	for i := 0; i < nArguments; i++ {
     50 		// The length of the argument value, in bytes (this count does not include itself). Can be zero.
     51 		// As a special case, -1 indicates a NULL argument value. No value bytes follow in the NULL case.
     52 		argumentLength := int(binary.BigEndian.Uint32(src[rp:]))
     53 		rp += 4
     54 		if argumentLength == -1 {
     55 			arguments[i] = nil
     56 		} else {
     57 			// The value of the argument, in the format indicated by the associated format code. n is the above length.
     58 			argumentValue := src[rp : rp+argumentLength]
     59 			rp += argumentLength
     60 			arguments[i] = argumentValue
     61 		}
     62 	}
     63 	dst.Arguments = arguments
     64 	// The format code for the function result. Must presently be zero (text) or one (binary).
     65 	resultFormatCode := binary.BigEndian.Uint16(src[rp:])
     66 	if resultFormatCode != 0 && resultFormatCode != 1 {
     67 		return &invalidMessageFormatErr{messageType: "FunctionCall"}
     68 	}
     69 	dst.ResultFormatCode = resultFormatCode
     70 	return nil
     71 }
     72 
     73 // Encode encodes src into dst. dst will include the 1 byte message type identifier and the 4 byte message length.
     74 func (src *FunctionCall) Encode(dst []byte) []byte {
     75 	dst = append(dst, 'F')
     76 	sp := len(dst)
     77 	dst = pgio.AppendUint32(dst, 0) // Unknown length, set it at the end
     78 	dst = pgio.AppendUint32(dst, src.Function)
     79 	dst = pgio.AppendUint16(dst, uint16(len(src.ArgFormatCodes)))
     80 	for _, argFormatCode := range src.ArgFormatCodes {
     81 		dst = pgio.AppendUint16(dst, argFormatCode)
     82 	}
     83 	dst = pgio.AppendUint16(dst, uint16(len(src.Arguments)))
     84 	for _, argument := range src.Arguments {
     85 		if argument == nil {
     86 			dst = pgio.AppendInt32(dst, -1)
     87 		} else {
     88 			dst = pgio.AppendInt32(dst, int32(len(argument)))
     89 			dst = append(dst, argument...)
     90 		}
     91 	}
     92 	dst = pgio.AppendUint16(dst, src.ResultFormatCode)
     93 	pgio.SetInt32(dst[sp:], int32(len(dst[sp:])))
     94 	return dst
     95 }