Prepare creates a prepared statement. If the name is empty, the anonymous prepared statement will be used. This allows Prepare to also to describe statements without creating a server-side prepared statement. Prepare does not send a PREPARE statement to the server. It uses the PostgreSQL Parse and
(ctx context.Context, name, sql string, paramOIDs []uint32)
| 948 | // case, the returned error will be an error where errors.As with a *PrepareError succeeds and the *PrepareError has |
| 949 | // ParseComplete set to true. |
| 950 | func (pgConn *PgConn) Prepare(ctx context.Context, name, sql string, paramOIDs []uint32) (*StatementDescription, error) { |
| 951 | if err := pgConn.lock(); err != nil { |
| 952 | return nil, err |
| 953 | } |
| 954 | defer pgConn.unlock() |
| 955 | |
| 956 | if ctx != context.Background() { |
| 957 | select { |
| 958 | case <-ctx.Done(): |
| 959 | return nil, newContextAlreadyDoneError(ctx) |
| 960 | default: |
| 961 | } |
| 962 | pgConn.contextWatcher.Watch(ctx) |
| 963 | defer pgConn.contextWatcher.Unwatch() |
| 964 | } |
| 965 | |
| 966 | pgConn.frontend.SendParse(&pgproto3.Parse{Name: name, Query: sql, ParameterOIDs: paramOIDs}) |
| 967 | pgConn.frontend.SendDescribe(&pgproto3.Describe{ObjectType: 'S', Name: name}) |
| 968 | pgConn.frontend.SendSync(&pgproto3.Sync{}) |
| 969 | err := pgConn.flushWithPotentialWriteReadDeadlock() |
| 970 | if err != nil { |
| 971 | pgConn.asyncClose() |
| 972 | return nil, err |
| 973 | } |
| 974 | |
| 975 | psd := &StatementDescription{Name: name, SQL: sql} |
| 976 | |
| 977 | var ParseComplete bool |
| 978 | var pgErr *PgError |
| 979 | |
| 980 | readloop: |
| 981 | for { |
| 982 | msg, err := pgConn.receiveMessage() |
| 983 | if err != nil { |
| 984 | pgConn.asyncClose() |
| 985 | return nil, normalizeTimeoutError(ctx, err) |
| 986 | } |
| 987 | |
| 988 | switch msg := msg.(type) { |
| 989 | case *pgproto3.ParseComplete: |
| 990 | ParseComplete = true |
| 991 | case *pgproto3.ParameterDescription: |
| 992 | psd.ParamOIDs = make([]uint32, len(msg.ParameterOIDs)) |
| 993 | copy(psd.ParamOIDs, msg.ParameterOIDs) |
| 994 | case *pgproto3.RowDescription: |
| 995 | psd.Fields = make([]FieldDescription, len(msg.Fields)) |
| 996 | convertRowDescription(psd.Fields, msg) |
| 997 | case *pgproto3.ErrorResponse: |
| 998 | pgErr = ErrorResponseToPgError(msg) |
| 999 | case *pgproto3.ReadyForQuery: |
| 1000 | break readloop |
| 1001 | } |
| 1002 | } |
| 1003 | |
| 1004 | if pgErr != nil { |
| 1005 | return nil, &PrepareError{err: pgErr, ParseComplete: ParseComplete} |
| 1006 | } |
| 1007 | return psd, nil |
nothing calls this directly
no test coverage detected