예제 #1
0
파일: plan.go 프로젝트: Alienero/Rambo
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
}
예제 #2
0
파일: plan.go 프로젝트: Alienero/Rambo
// 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
}
예제 #3
0
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
}
예제 #4
0
파일: plan.go 프로젝트: Alienero/Rambo
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
}