func readCopyOutResponse(cn *pool.Conn) error { for { c, msgLen, err := readMessageType(cn) if err != nil { return err } switch c { case copyOutResponseMsg: _, err := cn.ReadN(msgLen) if err != nil { return err } return nil case errorResponseMsg: e, err := readError(cn) if err != nil { return err } return e case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return err } default: return fmt.Errorf("pg: readCopyOutResponse: unexpected message %#x", c) } } }
func readInt32(cn *pool.Conn) (int32, error) { b, err := cn.ReadN(4) if err != nil { return 0, err } return int32(binary.BigEndian.Uint32(b)), nil }
func startup(cn *pool.Conn, user, password, database string) error { writeStartupMsg(cn.Wr, user, database) if err := cn.Wr.Flush(); err != nil { return err } for { c, msgLen, err := readMessageType(cn) if err != nil { return err } switch c { case backendKeyDataMsg: processId, err := readInt32(cn) if err != nil { return err } secretKey, err := readInt32(cn) if err != nil { return err } cn.ProcessId = processId cn.SecretKey = secretKey case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return err } case authenticationOKMsg: if err := authenticate(cn, user, password); err != nil { return err } case readyForQueryMsg: _, err := cn.ReadN(msgLen) if err != nil { return err } return nil case errorResponseMsg: e, err := readError(cn) if err != nil { return err } return e default: return fmt.Errorf("pg: unknown startup message response: %q", c) } } }
func readNotification(cn *pool.Conn) (channel, payload string, err error) { for { c, msgLen, err := readMessageType(cn) if err != nil { return "", "", err } switch c { case commandCompleteMsg: _, err := cn.ReadN(msgLen) if err != nil { return "", "", err } case readyForQueryMsg: _, err := cn.ReadN(msgLen) if err != nil { return "", "", err } case errorResponseMsg: e, err := readError(cn) if err != nil { return "", "", err } return "", "", e case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return "", "", err } case notificationResponseMsg: _, err := readInt32(cn) if err != nil { return "", "", err } channel, err = readString(cn) if err != nil { return "", "", err } payload, err = readString(cn) if err != nil { return "", "", err } return channel, payload, nil default: return "", "", fmt.Errorf("pg: unexpected message %q", c) } } }
func readParseDescribeSync(cn *pool.Conn) (columns []string, e error) { for { c, msgLen, err := readMessageType(cn) if err != nil { return nil, err } switch c { case parseCompleteMsg: _, err := cn.ReadN(msgLen) if err != nil { return nil, err } case rowDescriptionMsg: // Response to the DESCRIBE message. columns, err = readRowDescription(cn) if err != nil { return nil, err } case parameterDescriptionMsg: // Response to the DESCRIBE message. _, err := cn.ReadN(msgLen) if err != nil { return nil, err } case noDataMsg: // Response to the DESCRIBE message. _, err := cn.ReadN(msgLen) if err != nil { return nil, err } case readyForQueryMsg: _, err := cn.ReadN(msgLen) if err != nil { return nil, err } return case errorResponseMsg: var err error e, err = readError(cn) if err != nil { return nil, err } case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return nil, err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return nil, err } default: if e != nil { return nil, e } return nil, fmt.Errorf("pg: readParseDescribeSync: unexpected message %#x", c) } } }
func readRowDescription(cn *pool.Conn) ([]string, error) { colNum, err := readInt16(cn) if err != nil { return nil, err } cols := make([]string, colNum) for i := int16(0); i < colNum; i++ { col, err := readString(cn) if err != nil { return nil, err } cols[i] = col if _, err := cn.ReadN(18); err != nil { return nil, err } } return cols, nil }
func logParameterStatus(cn *pool.Conn, msgLen int) error { if !glog.V(2) { _, err := cn.ReadN(msgLen) return err } name, err := readString(cn) if err != nil { return err } value, err := readString(cn) if err != nil { return err } glog.Infof("pg parameter status: %s=%q", name, value) return nil }
func logNotice(cn *pool.Conn, msgLen int) error { if !glog.V(2) { _, err := cn.ReadN(msgLen) return err } var level string var logger func(string, ...interface{}) for { c, err := cn.Rd.ReadByte() if err != nil { return err } if c == 0 { break } s, err := readString(cn) if err != nil { return err } switch c { case 'S': level = s switch level { case "DEBUG", "LOG", "INFO", "NOTICE": logger = glog.Infof case "WARNING": logger = glog.Warningf case "EXCEPTION": logger = glog.Errorf default: logger = glog.Fatalf } case 'M': logger("pg %s message: %s", level, s) } } return nil }
func readReadyForQuery(cn *pool.Conn) (res types.Result, e error) { for { c, msgLen, err := readMessageType(cn) if err != nil { return nil, err } switch c { case commandCompleteMsg: b, err := cn.ReadN(msgLen) if err != nil { return nil, err } res = types.ParseResult(b) case readyForQueryMsg: _, err := cn.ReadN(msgLen) if err != nil { return nil, err } return case errorResponseMsg: var err error e, err = readError(cn) if err != nil { return nil, err } case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return nil, err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return nil, err } default: if e != nil { return nil, e } return nil, fmt.Errorf("pg: readReadyForQuery: unexpected message %#x", c) } } }
func readBindMsg(cn *pool.Conn) (e error) { for { c, msgLen, err := readMessageType(cn) if err != nil { return err } switch c { case bindCompleteMsg: _, err := cn.ReadN(msgLen) if err != nil { return err } case readyForQueryMsg: // This is response to the SYNC message. _, err := cn.ReadN(msgLen) if err != nil { return err } return case errorResponseMsg: var err error e, err = readError(cn) if err != nil { return err } case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return err } default: if e != nil { return e } return fmt.Errorf("pg: readBindMsg: unexpected message %#x", c) } } }
func prepare(db *DB, cn *pool.Conn, q string) (*Stmt, error) { name := cn.NextId() writeParseDescribeSyncMsg(cn.Wr, name, q) if err := cn.Wr.Flush(); err != nil { db.freeConn(cn, err) return nil, err } columns, err := readParseDescribeSync(cn) if err != nil { db.freeConn(cn, err) return nil, err } stmt := &Stmt{ db: db, _cn: cn, name: name, columns: columns, } return stmt, nil }
func readDataRow(cn *pool.Conn, scanner orm.ColumnScanner, columns []string) (scanErr error) { colNum, err := readInt16(cn) if err != nil { return err } for colIdx := 0; colIdx < int(colNum); colIdx++ { l, err := readInt32(cn) if err != nil { return err } var b []byte if l != -1 { b, err = cn.ReadN(int(l)) if err != nil { return err } } if err := scanner.ScanColumn(colIdx, columns[colIdx], b); err != nil { scanErr = err } } return scanErr }
func readCopyData(cn *pool.Conn, w io.WriteCloser) (types.Result, error) { defer w.Close() for { c, msgLen, err := readMessageType(cn) if err != nil { return nil, err } switch c { case copyDataMsg: b, err := cn.ReadN(msgLen) if err != nil { return nil, err } _, err = w.Write(b) if err != nil { return nil, err } case copyDoneMsg: _, err := cn.ReadN(msgLen) if err != nil { return nil, err } case commandCompleteMsg: b, err := cn.ReadN(msgLen) if err != nil { return nil, err } return types.ParseResult(b), nil case errorResponseMsg: e, err := readError(cn) if err != nil { return nil, err } return nil, e case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return nil, err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return nil, err } default: return nil, fmt.Errorf("pg: readCopyData: unexpected message %#x", c) } } }
func enableSSL(cn *pool.Conn) error { writeSSLMsg(cn.Wr) if err := cn.Wr.Flush(); err != nil { return err } b := make([]byte, 1) _, err := io.ReadFull(cn.NetConn, b) if err != nil { return err } if b[0] != 'S' { return ErrSSLNotSupported } tlsConf := &tls.Config{ InsecureSkipVerify: true, } cn.NetConn = tls.Client(cn.NetConn, tlsConf) return nil }
func readExtQueryData(cn *pool.Conn, mod interface{}, columns []string) (res types.Result, e error) { coll, ok := mod.(orm.Collection) if !ok { coll, e = orm.NewModel(mod) if e != nil { coll = Discard } } var model orm.ColumnScanner for { c, msgLen, err := readMessageType(cn) if err != nil { return nil, err } switch c { case bindCompleteMsg: _, err := cn.ReadN(msgLen) if err != nil { return nil, err } case dataRowMsg: model = coll.NewModel() if err := readDataRow(cn, model, columns); err != nil { e = err } if err := coll.AddModel(model); err != nil { return nil, err } case commandCompleteMsg: // Response to the EXECUTE message. b, err := cn.ReadN(msgLen) if err != nil { return nil, err } res = types.ParseResult(b) case readyForQueryMsg: // Response to the SYNC message. _, err := cn.ReadN(msgLen) if err != nil { return nil, err } return case errorResponseMsg: var err error e, err = readError(cn) if err != nil { return nil, err } case noticeResponseMsg: if err := logNotice(cn, msgLen); err != nil { return nil, err } case parameterStatusMsg: if err := logParameterStatus(cn, msgLen); err != nil { return nil, err } default: if e != nil { return nil, e } return nil, fmt.Errorf("pg: readExtQueryData: unexpected message %#x", c) } } }
func authenticate(cn *pool.Conn, user, password string) error { num, err := readInt32(cn) if err != nil { return err } switch num { case 0: return nil case 3: writePasswordMsg(cn.Wr, password) if err := cn.Wr.Flush(); err != nil { return err } c, _, err := readMessageType(cn) if err != nil { return err } switch c { case authenticationOKMsg: num, err := readInt32(cn) if err != nil { return err } if num != 0 { return fmt.Errorf("pg: unexpected authentication code: %d", num) } return nil case errorResponseMsg: e, err := readError(cn) if err != nil { return err } return e default: return fmt.Errorf("pg: unknown password message response: %q", c) } case 5: b, err := cn.ReadN(4) if err != nil { return err } secret := "md5" + md5s(md5s(password+user)+string(b)) writePasswordMsg(cn.Wr, secret) if err := cn.Wr.Flush(); err != nil { return err } c, _, err := readMessageType(cn) if err != nil { return err } switch c { case authenticationOKMsg: num, err := readInt32(cn) if err != nil { return err } if num != 0 { return fmt.Errorf("pg: unexpected authentication code: %d", num) } return nil case errorResponseMsg: e, err := readError(cn) if err != nil { return err } return e default: return fmt.Errorf("pg: unknown password message response: %q", c) } default: return fmt.Errorf("pg: unknown authentication message response: %d", num) } }
func terminateConn(cn *pool.Conn) error { // Don't use cn.Buf because it is racy. _, err := cn.Write(terminateMessage) return err }