package  pgproto3 
 
import  ( 
	"bytes"  
	"fmt"  
	"io"  
	"strconv"  
	"strings"  
	"sync"  
	"time"  
) 
 
 
 
type  tracer struct  { 
	TracerOptions  
 
	mux sync .Mutex  
	w   io .Writer  
	buf *bytes .Buffer  
} 
 
 
type  TracerOptions  struct  { 
	 
	SuppressTimestamps bool  
 
	 
	RegressMode bool  
} 
 
func  (t  *tracer ) traceMessage (sender  byte , encodedLen  int32 , msg  Message ) { 
	switch  msg := msg .(type ) { 
	case  *AuthenticationCleartextPassword : 
		t .traceAuthenticationCleartextPassword (sender , encodedLen , msg ) 
	case  *AuthenticationGSS : 
		t .traceAuthenticationGSS (sender , encodedLen , msg ) 
	case  *AuthenticationGSSContinue : 
		t .traceAuthenticationGSSContinue (sender , encodedLen , msg ) 
	case  *AuthenticationMD5Password : 
		t .traceAuthenticationMD5Password (sender , encodedLen , msg ) 
	case  *AuthenticationOk : 
		t .traceAuthenticationOk (sender , encodedLen , msg ) 
	case  *AuthenticationSASL : 
		t .traceAuthenticationSASL (sender , encodedLen , msg ) 
	case  *AuthenticationSASLContinue : 
		t .traceAuthenticationSASLContinue (sender , encodedLen , msg ) 
	case  *AuthenticationSASLFinal : 
		t .traceAuthenticationSASLFinal (sender , encodedLen , msg ) 
	case  *BackendKeyData : 
		t .traceBackendKeyData (sender , encodedLen , msg ) 
	case  *Bind : 
		t .traceBind (sender , encodedLen , msg ) 
	case  *BindComplete : 
		t .traceBindComplete (sender , encodedLen , msg ) 
	case  *CancelRequest : 
		t .traceCancelRequest (sender , encodedLen , msg ) 
	case  *Close : 
		t .traceClose (sender , encodedLen , msg ) 
	case  *CloseComplete : 
		t .traceCloseComplete (sender , encodedLen , msg ) 
	case  *CommandComplete : 
		t .traceCommandComplete (sender , encodedLen , msg ) 
	case  *CopyBothResponse : 
		t .traceCopyBothResponse (sender , encodedLen , msg ) 
	case  *CopyData : 
		t .traceCopyData (sender , encodedLen , msg ) 
	case  *CopyDone : 
		t .traceCopyDone (sender , encodedLen , msg ) 
	case  *CopyFail : 
		t .traceCopyFail (sender , encodedLen , msg ) 
	case  *CopyInResponse : 
		t .traceCopyInResponse (sender , encodedLen , msg ) 
	case  *CopyOutResponse : 
		t .traceCopyOutResponse (sender , encodedLen , msg ) 
	case  *DataRow : 
		t .traceDataRow (sender , encodedLen , msg ) 
	case  *Describe : 
		t .traceDescribe (sender , encodedLen , msg ) 
	case  *EmptyQueryResponse : 
		t .traceEmptyQueryResponse (sender , encodedLen , msg ) 
	case  *ErrorResponse : 
		t .traceErrorResponse (sender , encodedLen , msg ) 
	case  *Execute : 
		t .TraceQueryute (sender , encodedLen , msg ) 
	case  *Flush : 
		t .traceFlush (sender , encodedLen , msg ) 
	case  *FunctionCall : 
		t .traceFunctionCall (sender , encodedLen , msg ) 
	case  *FunctionCallResponse : 
		t .traceFunctionCallResponse (sender , encodedLen , msg ) 
	case  *GSSEncRequest : 
		t .traceGSSEncRequest (sender , encodedLen , msg ) 
	case  *NoData : 
		t .traceNoData (sender , encodedLen , msg ) 
	case  *NoticeResponse : 
		t .traceNoticeResponse (sender , encodedLen , msg ) 
	case  *NotificationResponse : 
		t .traceNotificationResponse (sender , encodedLen , msg ) 
	case  *ParameterDescription : 
		t .traceParameterDescription (sender , encodedLen , msg ) 
	case  *ParameterStatus : 
		t .traceParameterStatus (sender , encodedLen , msg ) 
	case  *Parse : 
		t .traceParse (sender , encodedLen , msg ) 
	case  *ParseComplete : 
		t .traceParseComplete (sender , encodedLen , msg ) 
	case  *PortalSuspended : 
		t .tracePortalSuspended (sender , encodedLen , msg ) 
	case  *Query : 
		t .traceQuery (sender , encodedLen , msg ) 
	case  *ReadyForQuery : 
		t .traceReadyForQuery (sender , encodedLen , msg ) 
	case  *RowDescription : 
		t .traceRowDescription (sender , encodedLen , msg ) 
	case  *SSLRequest : 
		t .traceSSLRequest (sender , encodedLen , msg ) 
	case  *StartupMessage : 
		t .traceStartupMessage (sender , encodedLen , msg ) 
	case  *Sync : 
		t .traceSync (sender , encodedLen , msg ) 
	case  *Terminate : 
		t .traceTerminate (sender , encodedLen , msg ) 
	default : 
		t .writeTrace (sender , encodedLen , "Unknown" , nil ) 
	} 
} 
 
func  (t  *tracer ) traceAuthenticationCleartextPassword (sender  byte , encodedLen  int32 , msg  *AuthenticationCleartextPassword ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationCleartextPassword" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationGSS (sender  byte , encodedLen  int32 , msg  *AuthenticationGSS ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationGSS" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationGSSContinue (sender  byte , encodedLen  int32 , msg  *AuthenticationGSSContinue ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationGSSContinue" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationMD5Password (sender  byte , encodedLen  int32 , msg  *AuthenticationMD5Password ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationMD5Password" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationOk (sender  byte , encodedLen  int32 , msg  *AuthenticationOk ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationOk" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationSASL (sender  byte , encodedLen  int32 , msg  *AuthenticationSASL ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationSASL" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationSASLContinue (sender  byte , encodedLen  int32 , msg  *AuthenticationSASLContinue ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationSASLContinue" , nil ) 
} 
 
func  (t  *tracer ) traceAuthenticationSASLFinal (sender  byte , encodedLen  int32 , msg  *AuthenticationSASLFinal ) { 
	t .writeTrace (sender , encodedLen , "AuthenticationSASLFinal" , nil ) 
} 
 
func  (t  *tracer ) traceBackendKeyData (sender  byte , encodedLen  int32 , msg  *BackendKeyData ) { 
	t .writeTrace (sender , encodedLen , "BackendKeyData" , func () { 
		if  t .RegressMode  { 
			t .buf .WriteString ("\t NNNN NNNN" ) 
		} else  { 
			fmt .Fprintf (t .buf , "\t %d %d" , msg .ProcessID , msg .SecretKey ) 
		} 
	}) 
} 
 
func  (t  *tracer ) traceBind (sender  byte , encodedLen  int32 , msg  *Bind ) { 
	t .writeTrace (sender , encodedLen , "Bind" , func () { 
		fmt .Fprintf (t .buf , "\t %s %s %d" , traceDoubleQuotedString ([]byte (msg .DestinationPortal )), traceDoubleQuotedString ([]byte (msg .PreparedStatement )), len (msg .ParameterFormatCodes )) 
		for  _ , fc  := range  msg .ParameterFormatCodes  { 
			fmt .Fprintf (t .buf , " %d" , fc ) 
		} 
		fmt .Fprintf (t .buf , " %d" , len (msg .Parameters )) 
		for  _ , p  := range  msg .Parameters  { 
			fmt .Fprintf (t .buf , " %s" , traceSingleQuotedString (p )) 
		} 
		fmt .Fprintf (t .buf , " %d" , len (msg .ResultFormatCodes )) 
		for  _ , fc  := range  msg .ResultFormatCodes  { 
			fmt .Fprintf (t .buf , " %d" , fc ) 
		} 
	}) 
} 
 
func  (t  *tracer ) traceBindComplete (sender  byte , encodedLen  int32 , msg  *BindComplete ) { 
	t .writeTrace (sender , encodedLen , "BindComplete" , nil ) 
} 
 
func  (t  *tracer ) traceCancelRequest (sender  byte , encodedLen  int32 , msg  *CancelRequest ) { 
	t .writeTrace (sender , encodedLen , "CancelRequest" , nil ) 
} 
 
func  (t  *tracer ) traceClose (sender  byte , encodedLen  int32 , msg  *Close ) { 
	t .writeTrace (sender , encodedLen , "Close" , nil ) 
} 
 
func  (t  *tracer ) traceCloseComplete (sender  byte , encodedLen  int32 , msg  *CloseComplete ) { 
	t .writeTrace (sender , encodedLen , "CloseComplete" , nil ) 
} 
 
func  (t  *tracer ) traceCommandComplete (sender  byte , encodedLen  int32 , msg  *CommandComplete ) { 
	t .writeTrace (sender , encodedLen , "CommandComplete" , func () { 
		fmt .Fprintf (t .buf , "\t %s" , traceDoubleQuotedString (msg .CommandTag )) 
	}) 
} 
 
func  (t  *tracer ) traceCopyBothResponse (sender  byte , encodedLen  int32 , msg  *CopyBothResponse ) { 
	t .writeTrace (sender , encodedLen , "CopyBothResponse" , nil ) 
} 
 
func  (t  *tracer ) traceCopyData (sender  byte , encodedLen  int32 , msg  *CopyData ) { 
	t .writeTrace (sender , encodedLen , "CopyData" , nil ) 
} 
 
func  (t  *tracer ) traceCopyDone (sender  byte , encodedLen  int32 , msg  *CopyDone ) { 
	t .writeTrace (sender , encodedLen , "CopyDone" , nil ) 
} 
 
func  (t  *tracer ) traceCopyFail (sender  byte , encodedLen  int32 , msg  *CopyFail ) { 
	t .writeTrace (sender , encodedLen , "CopyFail" , func () { 
		fmt .Fprintf (t .buf , "\t %s" , traceDoubleQuotedString ([]byte (msg .Message ))) 
	}) 
} 
 
func  (t  *tracer ) traceCopyInResponse (sender  byte , encodedLen  int32 , msg  *CopyInResponse ) { 
	t .writeTrace (sender , encodedLen , "CopyInResponse" , nil ) 
} 
 
func  (t  *tracer ) traceCopyOutResponse (sender  byte , encodedLen  int32 , msg  *CopyOutResponse ) { 
	t .writeTrace (sender , encodedLen , "CopyOutResponse" , nil ) 
} 
 
func  (t  *tracer ) traceDataRow (sender  byte , encodedLen  int32 , msg  *DataRow ) { 
	t .writeTrace (sender , encodedLen , "DataRow" , func () { 
		fmt .Fprintf (t .buf , "\t %d" , len (msg .Values )) 
		for  _ , v  := range  msg .Values  { 
			if  v  == nil  { 
				t .buf .WriteString (" -1" ) 
			} else  { 
				fmt .Fprintf (t .buf , " %d %s" , len (v ), traceSingleQuotedString (v )) 
			} 
		} 
	}) 
} 
 
func  (t  *tracer ) traceDescribe (sender  byte , encodedLen  int32 , msg  *Describe ) { 
	t .writeTrace (sender , encodedLen , "Describe" , func () { 
		fmt .Fprintf (t .buf , "\t %c %s" , msg .ObjectType , traceDoubleQuotedString ([]byte (msg .Name ))) 
	}) 
} 
 
func  (t  *tracer ) traceEmptyQueryResponse (sender  byte , encodedLen  int32 , msg  *EmptyQueryResponse ) { 
	t .writeTrace (sender , encodedLen , "EmptyQueryResponse" , nil ) 
} 
 
func  (t  *tracer ) traceErrorResponse (sender  byte , encodedLen  int32 , msg  *ErrorResponse ) { 
	t .writeTrace (sender , encodedLen , "ErrorResponse" , nil ) 
} 
 
func  (t  *tracer ) TraceQueryute (sender  byte , encodedLen  int32 , msg  *Execute ) { 
	t .writeTrace (sender , encodedLen , "Execute" , func () { 
		fmt .Fprintf (t .buf , "\t %s %d" , traceDoubleQuotedString ([]byte (msg .Portal )), msg .MaxRows ) 
	}) 
} 
 
func  (t  *tracer ) traceFlush (sender  byte , encodedLen  int32 , msg  *Flush ) { 
	t .writeTrace (sender , encodedLen , "Flush" , nil ) 
} 
 
func  (t  *tracer ) traceFunctionCall (sender  byte , encodedLen  int32 , msg  *FunctionCall ) { 
	t .writeTrace (sender , encodedLen , "FunctionCall" , nil ) 
} 
 
func  (t  *tracer ) traceFunctionCallResponse (sender  byte , encodedLen  int32 , msg  *FunctionCallResponse ) { 
	t .writeTrace (sender , encodedLen , "FunctionCallResponse" , nil ) 
} 
 
func  (t  *tracer ) traceGSSEncRequest (sender  byte , encodedLen  int32 , msg  *GSSEncRequest ) { 
	t .writeTrace (sender , encodedLen , "GSSEncRequest" , nil ) 
} 
 
func  (t  *tracer ) traceNoData (sender  byte , encodedLen  int32 , msg  *NoData ) { 
	t .writeTrace (sender , encodedLen , "NoData" , nil ) 
} 
 
func  (t  *tracer ) traceNoticeResponse (sender  byte , encodedLen  int32 , msg  *NoticeResponse ) { 
	t .writeTrace (sender , encodedLen , "NoticeResponse" , nil ) 
} 
 
func  (t  *tracer ) traceNotificationResponse (sender  byte , encodedLen  int32 , msg  *NotificationResponse ) { 
	t .writeTrace (sender , encodedLen , "NotificationResponse" , func () { 
		fmt .Fprintf (t .buf , "\t %d %s %s" , msg .PID , traceDoubleQuotedString ([]byte (msg .Channel )), traceDoubleQuotedString ([]byte (msg .Payload ))) 
	}) 
} 
 
func  (t  *tracer ) traceParameterDescription (sender  byte , encodedLen  int32 , msg  *ParameterDescription ) { 
	t .writeTrace (sender , encodedLen , "ParameterDescription" , nil ) 
} 
 
func  (t  *tracer ) traceParameterStatus (sender  byte , encodedLen  int32 , msg  *ParameterStatus ) { 
	t .writeTrace (sender , encodedLen , "ParameterStatus" , func () { 
		fmt .Fprintf (t .buf , "\t %s %s" , traceDoubleQuotedString ([]byte (msg .Name )), traceDoubleQuotedString ([]byte (msg .Value ))) 
	}) 
} 
 
func  (t  *tracer ) traceParse (sender  byte , encodedLen  int32 , msg  *Parse ) { 
	t .writeTrace (sender , encodedLen , "Parse" , func () { 
		fmt .Fprintf (t .buf , "\t %s %s %d" , traceDoubleQuotedString ([]byte (msg .Name )), traceDoubleQuotedString ([]byte (msg .Query )), len (msg .ParameterOIDs )) 
		for  _ , oid  := range  msg .ParameterOIDs  { 
			fmt .Fprintf (t .buf , " %d" , oid ) 
		} 
	}) 
} 
 
func  (t  *tracer ) traceParseComplete (sender  byte , encodedLen  int32 , msg  *ParseComplete ) { 
	t .writeTrace (sender , encodedLen , "ParseComplete" , nil ) 
} 
 
func  (t  *tracer ) tracePortalSuspended (sender  byte , encodedLen  int32 , msg  *PortalSuspended ) { 
	t .writeTrace (sender , encodedLen , "PortalSuspended" , nil ) 
} 
 
func  (t  *tracer ) traceQuery (sender  byte , encodedLen  int32 , msg  *Query ) { 
	t .writeTrace (sender , encodedLen , "Query" , func () { 
		fmt .Fprintf (t .buf , "\t %s" , traceDoubleQuotedString ([]byte (msg .String ))) 
	}) 
} 
 
func  (t  *tracer ) traceReadyForQuery (sender  byte , encodedLen  int32 , msg  *ReadyForQuery ) { 
	t .writeTrace (sender , encodedLen , "ReadyForQuery" , func () { 
		fmt .Fprintf (t .buf , "\t %c" , msg .TxStatus ) 
	}) 
} 
 
func  (t  *tracer ) traceRowDescription (sender  byte , encodedLen  int32 , msg  *RowDescription ) { 
	t .writeTrace (sender , encodedLen , "RowDescription" , func () { 
		fmt .Fprintf (t .buf , "\t %d" , len (msg .Fields )) 
		for  _ , fd  := range  msg .Fields  { 
			fmt .Fprintf (t .buf , ` %s %d %d %d %d %d %d` , traceDoubleQuotedString (fd .Name ), fd .TableOID , fd .TableAttributeNumber , fd .DataTypeOID , fd .DataTypeSize , fd .TypeModifier , fd .Format ) 
		} 
	}) 
} 
 
func  (t  *tracer ) traceSSLRequest (sender  byte , encodedLen  int32 , msg  *SSLRequest ) { 
	t .writeTrace (sender , encodedLen , "SSLRequest" , nil ) 
} 
 
func  (t  *tracer ) traceStartupMessage (sender  byte , encodedLen  int32 , msg  *StartupMessage ) { 
	t .writeTrace (sender , encodedLen , "StartupMessage" , nil ) 
} 
 
func  (t  *tracer ) traceSync (sender  byte , encodedLen  int32 , msg  *Sync ) { 
	t .writeTrace (sender , encodedLen , "Sync" , nil ) 
} 
 
func  (t  *tracer ) traceTerminate (sender  byte , encodedLen  int32 , msg  *Terminate ) { 
	t .writeTrace (sender , encodedLen , "Terminate" , nil ) 
} 
 
func  (t  *tracer ) writeTrace (sender  byte , encodedLen  int32 , msgType  string , writeDetails  func ()) { 
	t .mux .Lock () 
	defer  t .mux .Unlock () 
	defer  func () { 
		if  t .buf .Cap () > 1024  { 
			t .buf  = &bytes .Buffer {} 
		} else  { 
			t .buf .Reset () 
		} 
	}() 
 
	if  !t .SuppressTimestamps  { 
		now  := time .Now () 
		t .buf .WriteString (now .Format ("2006-01-02 15:04:05.000000" )) 
		t .buf .WriteByte ('\t' ) 
	} 
 
	t .buf .WriteByte (sender ) 
	t .buf .WriteByte ('\t' ) 
	t .buf .WriteString (msgType ) 
	t .buf .WriteByte ('\t' ) 
	t .buf .WriteString (strconv .FormatInt (int64 (encodedLen ), 10 )) 
 
	if  writeDetails  != nil  { 
		writeDetails () 
	} 
 
	t .buf .WriteByte ('\n' ) 
	t .buf .WriteTo (t .w ) 
} 
 
 
 
func  traceDoubleQuotedString(buf  []byte ) string  { 
	return  `"`  + string (buf ) + `"`  
} 
 
 
 
func  traceSingleQuotedString(buf  []byte ) string  { 
	sb  := &strings .Builder {} 
 
	sb .WriteByte ('\'' ) 
	for  _ , b  := range  buf  { 
		if  b  < 32  || b  > 126  { 
			fmt .Fprintf (sb , `\x%x` , b ) 
		} else  { 
			sb .WriteByte (b ) 
		} 
	} 
	sb .WriteByte ('\'' ) 
 
	return  sb .String () 
} 
  
The pages are generated with Golds   v0.6.7 . (GOOS=linux GOARCH=amd64)
Golds  is a Go 101  project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @Go100and1  (reachable from the left QR code) to get the latest news of Golds .