func (c *Conn) handleOKPacket(data []byte) (*mysql.Result, error) { var n int var pos int = 1 r := new(mysql.Result) r.AffectedRows, _, n = mysql.LengthEncodedInt(data[pos:]) pos += n r.InsertId, _, n = mysql.LengthEncodedInt(data[pos:]) pos += n if c.capability&mysql.CLIENT_PROTOCOL_41 > 0 { r.Status = binary.LittleEndian.Uint16(data[pos:]) c.status = r.Status pos += 2 //todo:strict_mode, check warnings as error //Warnings := binary.LittleEndian.Uint16(data[pos:]) //pos += 2 } else if c.capability&mysql.CLIENT_TRANSACTIONS > 0 { r.Status = binary.LittleEndian.Uint16(data[pos:]) c.status = r.Status pos += 2 } //info return r, nil }
//build select result with group by opt func (c *ClientConn) buildSelectGroupByResult(rs []*mysql.Result, stmt *sqlparser.Select) (*mysql.Result, error) { var err error var r *mysql.Result var groupByIndexs []int fieldLen := len(rs[0].Fields) startIndex := fieldLen - len(stmt.GroupBy) for startIndex < fieldLen { groupByIndexs = append(groupByIndexs, startIndex) startIndex++ } funcExprs := c.getFuncExprs(stmt) if len(funcExprs) == 0 { r, err = c.mergeGroupByWithoutFunc(rs, groupByIndexs) } else { r, err = c.mergeGroupByWithFunc(rs, groupByIndexs, funcExprs) } if err != nil { return nil, err } //build result names := make([]string, 0, 2) if 0 < len(r.Values) { r.Fields = r.Fields[:groupByIndexs[0]] for i := 0; i < len(r.Fields) && i < groupByIndexs[0]; i++ { names = append(names, string(r.Fields[i].Name)) } //delete group by columns in Values for i := 0; i < len(r.Values); i++ { r.Values[i] = r.Values[i][:groupByIndexs[0]] } r.Resultset, err = c.buildResultset(r.Fields, names, r.Values) if err != nil { return nil, err } } else { r.Resultset = c.newEmptyResultset(stmt) } return r, nil }
func (c *ClientConn) mergeExecResult(rs []*mysql.Result) error { r := new(mysql.Result) for _, v := range rs { r.Status |= v.Status r.AffectedRows += v.AffectedRows if r.InsertId == 0 { r.InsertId = v.InsertId } else if r.InsertId > v.InsertId { //last insert id is first gen id for multi row inserted //see http://dev.mysql.com/doc/refman/5.6/en/information-functions.html#function_last-insert-id r.InsertId = v.InsertId } } if r.InsertId > 0 { c.lastInsertId = int64(r.InsertId) } c.affectedRows = int64(r.AffectedRows) return c.writeOK(r) }
func (c *Conn) readResultRows(result *mysql.Result, isBinary bool) (err error) { var data []byte for { data, err = c.readPacket() if err != nil { return } // EOF Packet if c.isEOFPacket(data) { if c.capability&mysql.CLIENT_PROTOCOL_41 > 0 { //result.Warnings = binary.LittleEndian.Uint16(data[1:]) //todo add strict_mode, warning will be treat as error result.Status = binary.LittleEndian.Uint16(data[3:]) c.status = result.Status } break } result.RowDatas = append(result.RowDatas, data) } result.Values = make([][]interface{}, len(result.RowDatas)) for i := range result.Values { result.Values[i], err = result.RowDatas[i].Parse(result.Fields, isBinary) if err != nil { return err } } return nil }
func (c *ClientConn) loadResultWithFuncIntoMap(rs []*mysql.Result, groupByIndexs []int, funcExprs map[int]string) (map[string]*ResultRow, error) { resultMap := make(map[string]*ResultRow) rt := new(mysql.Result) rt.Resultset = new(mysql.Resultset) rt.Fields = rs[0].Fields //change Result into map for _, r := range rs { for i := 0; i < len(r.Values); i++ { keySlice := r.Values[i][groupByIndexs[0]:] mk, err := c.generateMapKey(keySlice) if err != nil { return nil, err } if v, ok := resultMap[mk]; ok { //init rt rt.Values = nil rt.RowDatas = nil //append v and r into rt, and calculate the function value rt.Values = append(rt.Values, r.Values[i], v.Value) rt.RowDatas = append(rt.RowDatas, r.RowDatas[i], v.RowData) resultTmp := []*mysql.Result{rt} for funcIndex, funcName := range funcExprs { funcValue, err := c.calFuncExprValue(funcName, resultTmp, funcIndex) if err != nil { return nil, err } //set the function value in group by resultMap[mk].Value[funcIndex] = funcValue } } else { //key is not exist resultMap[mk] = &ResultRow{ Value: r.Values[i], RowData: r.RowDatas[i], } } } } return resultMap, nil }
func (c *Conn) readResultColumns(result *mysql.Result) (err error) { var i int = 0 var data []byte for { data, err = c.readPacket() if err != nil { return } // EOF Packet if c.isEOFPacket(data) { if c.capability&mysql.CLIENT_PROTOCOL_41 > 0 { //result.Warnings = binary.LittleEndian.Uint16(data[1:]) //todo add strict_mode, warning will be treat as error result.Status = binary.LittleEndian.Uint16(data[3:]) c.status = result.Status } if i != len(result.Fields) { err = mysql.ErrMalformPacket } return } result.Fields[i], err = mysql.FieldData(data).Parse() if err != nil { return } result.FieldNames[string(result.Fields[i].Name)] = i i++ } }