예제 #1
0
func ReadDataRow(m *Message) (*DataRow, error) {
	if t := m.MsgType(); t != MsgDataRowD {
		return nil, e.BadTypeCode(t)
	}
	b := m.Payload()
	fieldCount, err := ReadUint16(b)
	if err != nil {
		return nil, err
	}

	values := make([][]byte, fieldCount)

	for i := range values {
		fieldLen, err := ReadInt32(b)
		if err != nil {
			return nil, err
		}
		if fieldLen >= 0 {
			fieldData := make([]byte, fieldLen)
			io.ReadFull(b, fieldData)
			values[i] = fieldData
		} else if fieldLen == -1 {
			values[i] = nil
		} else {
			return nil, e.WrongSize("Invalid length %v for field %v",
				fieldLen, i)
		}
	}
	return &DataRow{values}, nil
}
예제 #2
0
func ReadRowDescription(msg *Message) (
	rd *RowDescription, err error) {
	if t := msg.MsgType(); t != MsgRowDescriptionT {
		return nil, e.BadTypeCode(t)
	}

	b := msg.Payload()
	fieldCount, err := ReadUint16(b)
	if err != nil {
		return nil, err
	}

	fields := make([]FieldDescription, fieldCount)
	for i := range fields {
		name, err := ReadCString(b)
		if err != nil {
			return nil, err
		}
		tableOid, err := ReadInt32(b)
		if err != nil {
			return nil, err
		}
		tableAttNo, err := ReadInt16(b)
		if err != nil {
			return nil, err
		}
		typeOid, err := ReadUint32(b)
		if err != nil {
			return nil, err
		}
		typLen, err := ReadInt16(b)
		if err != nil {
			return nil, err
		}
		atttypmod, err := ReadInt32(b)
		if err != nil {
			return nil, err
		}
		format, err := ReadInt16(b)
		if err != nil {
			return nil, err
		}

		fields[i] = FieldDescription{name, Oid(tableOid), tableAttNo,
			Oid(typeOid), typLen, atttypmod, EncFmt(format)}
	}

	return &RowDescription{fields}, nil
}
예제 #3
0
func ReadCommandComplete(m *Message) (*CommandComplete, error) {
	if t := m.MsgType(); t != MsgCommandCompleteC {
		return nil, e.BadTypeCode(t)
	}

	p := m.Payload()
	fullTag, err := ReadCString(p)
	if err != nil {
		return nil, err
	}

	cmdRe := regexp.MustCompile("(INSERT|DELETE|UPDATE|SELECT|MOVE|FETCH|COPY) (\\d+)(?: (\\d+))?")
	if match := cmdRe.FindStringSubmatch(fullTag); match != nil {
		var rowcountIdx int
		var rowcount uint64
		var oid uint32

		hasOid := len(match) == 4 && match[3] != ""
		tag := match[1]

		if hasOid {
			val, err := strconv.ParseUint(match[2], 10, 32)
			if err != nil {
				panic("Oh snap")
			}
			oid = uint32(val)
			rowcountIdx = 3
		} else {
			rowcountIdx = 2
			oid = 0
		}

		rowcount, err := strconv.ParseUint(match[rowcountIdx], 10, 64)
		if err != nil {
			panic("Oh snap")
		}

		return &CommandComplete{tag, rowcount, oid}, nil
	} else {
		return &CommandComplete{fullTag, 0, 0}, nil
	}
}
예제 #4
0
func ReadErrorResponse(msg *Message) (*ErrorResponse, error) {
	if t := msg.MsgType(); t != MsgErrorResponseE {
		return nil, e.BadTypeCode(t)
	}

	p := msg.Payload()
	details := make(map[byte]string)
	for {
		fieldCode, err := ReadByte(p)
		if err != nil {
			return nil, err
		}
		if fieldCode == 0 {
			break
		}
		fieldValue, err := ReadCString(p)
		if err != nil {
			return nil, err
		}
		details[fieldCode] = fieldValue
	}
	return &ErrorResponse{details}, nil
}
예제 #5
0
func ReadBackendKeyData(msg *Message) (*BackendKeyData, error) {
	if t := msg.MsgType(); t != MsgBackendKeyDataK {
		return nil, e.BadTypeCode(t)
	}

	const RIGHT_SZ = 12
	if msg.Size() != RIGHT_SZ {
		return nil, e.WrongSize("BackendKeyData is wrong size: "+
			"expected %v, got %v", RIGHT_SZ, msg.Size())
	}

	r := msg.Payload()
	pid, err := ReadUint32(r)
	if err != nil {
		return nil, err
	}

	key, err := ReadUint32(r)
	if err != nil {
		return nil, err
	}

	return &BackendKeyData{BackendPid: pid, SecretKey: key}, err
}