func (sei *session) buildSelectPlan(stmt *sqlparser.Select) (*Plan, error) { plan := &Plan{} var err error var tableName string switch v := (stmt.From[0]).(type) { case *sqlparser.AliasedTableExpr: tableName = sqlparser.String(v.Expr) case *sqlparser.JoinTableExpr: if ate, ok := (v.LeftExpr).(*sqlparser.AliasedTableExpr); ok { tableName = sqlparser.String(ate.Expr) } else { tableName = sqlparser.String(v) } default: tableName = sqlparser.String(v) } // get tableName t, err := sei.getMeta().GetTable(sei.user, sei.db, tableName) if err != nil { return nil, err } plan.Table = t // rewrite limit err = plan.rewriteLimit(stmt) if err != nil { return nil, err } // generate sql err = plan.generateSQL(stmt) return plan, err }
// limit func (p *Plan) rewriteLimit(stmt *sqlparser.Select) (err error) { origin := stmt.Limit // get offset and count if origin == nil { return } var offset, count int64 if origin.Offset == nil { offset = 0 } else { o, ok := origin.Offset.(sqlparser.NumVal) if !ok { err = fmt.Errorf("invalid select limit %s", sqlparser.String(stmt.Limit)) return } if offset, err = strconv.ParseInt(string([]byte(o)), 10, 64); err != nil { return } } o, ok := origin.Rowcount.(sqlparser.NumVal) if !ok { err = fmt.Errorf("invalid limit %s", sqlparser.String(stmt.Limit)) return } if count, err = strconv.ParseInt(string([]byte(o)), 10, 64); err != nil { return } if count < 0 { err = fmt.Errorf("invalid limit %s", sqlparser.String(stmt.Limit)) return } // rewrite limit stmt stmt.Limit.Offset = sqlparser.NumVal([]byte("0")) stmt.Limit.Rowcount = sqlparser.NumVal([]byte(strconv.FormatInt(count+offset, 10))) p.offset = offset p.count = count return }
func (sei *session) sortResultSet(set *mysql.Resultset, stmt *sqlparser.Select) error { if len(stmt.OrderBy) > 0 { glog.Info("Sort select results") ks := make([]mysql.SortKey, 0, len(stmt.OrderBy)) for _, o := range stmt.OrderBy { ks = append(ks, mysql.SortKey{ Direction: o.Direction, Name: sqlparser.String(o.Expr), }) } return set.Sort(ks) } return nil }
func (sei *session) buildUpdatePlan(stmt *sqlparser.Update) (*Plan, error) { plan := &Plan{} var err error var tableName = sqlparser.String(stmt.Table) // get tableName t, err := sei.getMeta().GetTable(sei.user, sei.db, tableName) if err != nil { return nil, err } plan.Table = t // generate sql err = plan.generateSQL(stmt) return plan, err }