зеркало из https://github.com/github/vitess-gh.git
Added plan descriptions for a few more primitives
Signed-off-by: Andres Taylor <andres@planetscale.com>
This commit is contained in:
Родитель
2910261abf
Коммит
3576a2a2f6
|
@ -139,5 +139,5 @@ func wrapStreamExecute(prim Primitive, vcursor VCursor, bindVars map[string]*que
|
|||
}
|
||||
|
||||
func (f *fakePrimitive) description() PlanDescription {
|
||||
return PlanDescription{OperatorType: "fake - not implemented"}
|
||||
return PlanDescription{OperatorType: "fake"}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import (
|
|||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"vitess.io/vitess/go/sqltypes"
|
||||
"vitess.io/vitess/go/vt/key"
|
||||
|
@ -201,20 +202,27 @@ func (ms *MemorySort) description() PlanDescription {
|
|||
}
|
||||
|
||||
func orderByParamsToString(i interface{}) string {
|
||||
ob := i.(OrderbyParams)
|
||||
return ob.String()
|
||||
return i.(OrderbyParams).String()
|
||||
}
|
||||
|
||||
//GenericJoin will iterate over arrays, slices or maps, and executes the f function to get a
|
||||
//string representation of each element, and then uses strings.Join() join all the strings into a single one
|
||||
func GenericJoin(input interface{}, f func(interface{}) string) string {
|
||||
sl := reflect.ValueOf(input)
|
||||
str := ""
|
||||
for i := 0; i < sl.Len(); i++ {
|
||||
if len(str) != 0 {
|
||||
str += ","
|
||||
var keys []string
|
||||
switch sl.Kind() {
|
||||
case reflect.Slice:
|
||||
for i := 0; i < sl.Len(); i++ {
|
||||
keys = append(keys, f(sl.Index(i).Interface()))
|
||||
}
|
||||
str += f(sl.Index(i).Interface())
|
||||
case reflect.Map:
|
||||
for _, k := range sl.MapKeys() {
|
||||
keys = append(keys, f(k.Interface()))
|
||||
}
|
||||
default:
|
||||
panic("GenericJoin doesn't know how to deal with " + sl.Kind().String())
|
||||
}
|
||||
return str
|
||||
return strings.Join(keys, ", ")
|
||||
}
|
||||
|
||||
// sortHeap is sorted based on the orderBy params.
|
||||
|
|
|
@ -18,6 +18,9 @@ package engine
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
"vitess.io/vitess/go/vt/key"
|
||||
|
||||
"vitess.io/vitess/go/vt/proto/vtrpc"
|
||||
"vitess.io/vitess/go/vt/vterrors"
|
||||
|
@ -67,6 +70,14 @@ func (ap AggregateParams) isDistinct() bool {
|
|||
return ap.Opcode == AggregateCountDistinct || ap.Opcode == AggregateSumDistinct
|
||||
}
|
||||
|
||||
func (ap AggregateParams) String() string {
|
||||
if ap.Alias != "" {
|
||||
return fmt.Sprintf("%s(%d) AS %s", ap.Opcode.String(), ap.Col, ap.Alias)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s(%d)", ap.Opcode.String(), ap.Col)
|
||||
}
|
||||
|
||||
// AggregateOpcode is the aggregation Opcode.
|
||||
type AggregateOpcode int
|
||||
|
||||
|
@ -394,9 +405,26 @@ func createEmptyValueFor(opcode AggregateOpcode) (sqltypes.Value, error) {
|
|||
return sqltypes.NULL, vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, "unknown aggregation %v", opcode)
|
||||
}
|
||||
|
||||
func aggregateParamsToString(in interface{}) string {
|
||||
return in.(AggregateParams).String()
|
||||
}
|
||||
|
||||
func intToString(i interface{}) string {
|
||||
return strconv.Itoa(i.(int))
|
||||
}
|
||||
|
||||
func (oa *OrderedAggregate) description() PlanDescription {
|
||||
orderByIndexes := GenericJoin(oa.Aggregates, aggregateParamsToString)
|
||||
groupBy := GenericJoin(oa.Keys, intToString)
|
||||
other := map[string]string{
|
||||
"OrderBy": orderByIndexes,
|
||||
"GroupBy": groupBy,
|
||||
"Distinct": strconv.FormatBool(oa.HasDistinct),
|
||||
}
|
||||
return PlanDescription{
|
||||
OperatorType: "OrderedAggregation not implemented",
|
||||
Other: nil,
|
||||
OperatorType: "Aggregate",
|
||||
Variant: "Ordered",
|
||||
TargetDestination: key.DestinationVtGate{},
|
||||
Other: other,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"vitess.io/vitess/go/vt/key"
|
||||
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
|
||||
"vitess.io/vitess/go/vt/vtgate/vindexes"
|
||||
|
@ -25,16 +27,42 @@ import (
|
|||
// PlanDescription is used to create a serializable representation of the Primitive tree
|
||||
type PlanDescription struct {
|
||||
OperatorType string
|
||||
Variant string
|
||||
Variant string `json:",omitempty"`
|
||||
// Keyspace specifies the keyspace to send the query to.
|
||||
Keyspace *vindexes.Keyspace
|
||||
Keyspace *vindexes.Keyspace `json:",omitempty"`
|
||||
// TargetDestination specifies an explicit target destination to send the query to.
|
||||
TargetDestination key.Destination
|
||||
TargetDestination key.Destination `json:",omitempty"`
|
||||
// TargetTabletType specifies an explicit target destination tablet type
|
||||
// this is only used in conjunction with TargetDestination
|
||||
TargetTabletType topodatapb.TabletType
|
||||
Other map[string]string
|
||||
Inputs []PlanDescription
|
||||
TargetTabletType topodatapb.TabletType `json:",omitempty"`
|
||||
Other map[string]string `json:",omitempty"`
|
||||
Inputs []PlanDescription `json:",omitempty"`
|
||||
}
|
||||
|
||||
// MarshalJSON serializes the PlanDescription into a JSON representation.
|
||||
func (pd *PlanDescription) MarshalJSON() ([]byte, error) {
|
||||
var dest string
|
||||
if pd.TargetDestination != nil {
|
||||
dest = pd.TargetDestination.String()
|
||||
}
|
||||
out := struct {
|
||||
OperatorType string
|
||||
Variant string `json:",omitempty"`
|
||||
Keyspace *vindexes.Keyspace `json:",omitempty"`
|
||||
TargetDestination string `json:",omitempty"`
|
||||
TargetTabletType string `json:",omitempty"`
|
||||
Other map[string]string `json:",omitempty"`
|
||||
Inputs []PlanDescription `json:",omitempty"`
|
||||
}{
|
||||
OperatorType: pd.OperatorType,
|
||||
Variant: pd.Variant,
|
||||
Keyspace: pd.Keyspace,
|
||||
TargetDestination: dest,
|
||||
TargetTabletType: pd.TargetTabletType.String(),
|
||||
Other: pd.Other,
|
||||
Inputs: pd.Inputs,
|
||||
}
|
||||
return json.Marshal(out)
|
||||
}
|
||||
|
||||
//PrimitiveToPlanDescription transforms a primitive tree into a corresponding PlanDescription tree
|
||||
|
|
|
@ -19,6 +19,8 @@ package engine
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"vitess.io/vitess/go/vt/key"
|
||||
|
||||
"vitess.io/vitess/go/sqltypes"
|
||||
"vitess.io/vitess/go/vt/vterrors"
|
||||
|
||||
|
@ -31,11 +33,14 @@ var _ Primitive = (*PulloutSubquery)(nil)
|
|||
// PulloutSubquery executes a "pulled out" subquery and stores
|
||||
// the results in a bind variable.
|
||||
type PulloutSubquery struct {
|
||||
Opcode PulloutOpcode
|
||||
Opcode PulloutOpcode
|
||||
|
||||
// SubqueryResult and HasValues are used to send in the bindvar used in the query to the underlying primitive
|
||||
SubqueryResult string
|
||||
HasValues string
|
||||
Subquery Primitive
|
||||
Underlying Primitive
|
||||
|
||||
Subquery Primitive
|
||||
Underlying Primitive
|
||||
}
|
||||
|
||||
// Inputs returns the input primitives for this join
|
||||
|
@ -154,7 +159,11 @@ func (ps *PulloutSubquery) execSubquery(vcursor VCursor, bindVars map[string]*qu
|
|||
}
|
||||
|
||||
func (ps *PulloutSubquery) description() PlanDescription {
|
||||
return PlanDescription{OperatorType: "pullout subquery not implemented"}
|
||||
return PlanDescription{
|
||||
OperatorType: "Subquery",
|
||||
Variant: ps.Opcode.String(),
|
||||
TargetDestination: key.DestinationVtGate{},
|
||||
}
|
||||
}
|
||||
|
||||
// PulloutOpcode is a number representing the opcode
|
||||
|
|
|
@ -18,6 +18,7 @@ package engine
|
|||
|
||||
import (
|
||||
"vitess.io/vitess/go/sqltypes"
|
||||
"vitess.io/vitess/go/vt/key"
|
||||
querypb "vitess.io/vitess/go/vt/proto/query"
|
||||
)
|
||||
|
||||
|
@ -104,5 +105,12 @@ func (sq *Subquery) buildFields(inner *sqltypes.Result) []*querypb.Field {
|
|||
}
|
||||
|
||||
func (sq *Subquery) description() PlanDescription {
|
||||
return PlanDescription{OperatorType: "subquery - not implemented"}
|
||||
other := map[string]string{
|
||||
"Columns": GenericJoin(sq.Cols, intToString),
|
||||
}
|
||||
return PlanDescription{
|
||||
OperatorType: "Subquery",
|
||||
TargetDestination: key.DestinationVtGate{},
|
||||
Other: other,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -301,13 +301,9 @@ func getPlanOrErrorOutput(err error, plan *engine.Plan) string {
|
|||
}
|
||||
|
||||
descr := engine.PrimitiveToPlanDescription(plan.Instructions)
|
||||
sss, _ := json.MarshalIndent(descr, "", " ")
|
||||
fmt.Println(string(sss))
|
||||
|
||||
bout, _ := json.MarshalIndent(testPlan{
|
||||
Original: plan.Original,
|
||||
Instructions: plan.Instructions,
|
||||
}, "", " ")
|
||||
bout, _ := json.MarshalIndent(descr, " ", " ")
|
||||
fmt.Println(string(bout))
|
||||
return string(bout)
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче