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 }
//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 }