зеркало из 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 {
|
func (f *fakePrimitive) description() PlanDescription {
|
||||||
return PlanDescription{OperatorType: "fake - not implemented"}
|
return PlanDescription{OperatorType: "fake"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"math"
|
"math"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"vitess.io/vitess/go/sqltypes"
|
"vitess.io/vitess/go/sqltypes"
|
||||||
"vitess.io/vitess/go/vt/key"
|
"vitess.io/vitess/go/vt/key"
|
||||||
|
@ -201,20 +202,27 @@ func (ms *MemorySort) description() PlanDescription {
|
||||||
}
|
}
|
||||||
|
|
||||||
func orderByParamsToString(i interface{}) string {
|
func orderByParamsToString(i interface{}) string {
|
||||||
ob := i.(OrderbyParams)
|
return i.(OrderbyParams).String()
|
||||||
return ob.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 {
|
func GenericJoin(input interface{}, f func(interface{}) string) string {
|
||||||
sl := reflect.ValueOf(input)
|
sl := reflect.ValueOf(input)
|
||||||
str := ""
|
var keys []string
|
||||||
for i := 0; i < sl.Len(); i++ {
|
switch sl.Kind() {
|
||||||
if len(str) != 0 {
|
case reflect.Slice:
|
||||||
str += ","
|
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.
|
// sortHeap is sorted based on the orderBy params.
|
||||||
|
|
|
@ -18,6 +18,9 @@ package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"vitess.io/vitess/go/vt/key"
|
||||||
|
|
||||||
"vitess.io/vitess/go/vt/proto/vtrpc"
|
"vitess.io/vitess/go/vt/proto/vtrpc"
|
||||||
"vitess.io/vitess/go/vt/vterrors"
|
"vitess.io/vitess/go/vt/vterrors"
|
||||||
|
@ -67,6 +70,14 @@ func (ap AggregateParams) isDistinct() bool {
|
||||||
return ap.Opcode == AggregateCountDistinct || ap.Opcode == AggregateSumDistinct
|
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.
|
// AggregateOpcode is the aggregation Opcode.
|
||||||
type AggregateOpcode int
|
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)
|
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 {
|
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{
|
return PlanDescription{
|
||||||
OperatorType: "OrderedAggregation not implemented",
|
OperatorType: "Aggregate",
|
||||||
Other: nil,
|
Variant: "Ordered",
|
||||||
|
TargetDestination: key.DestinationVtGate{},
|
||||||
|
Other: other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ limitations under the License.
|
||||||
package engine
|
package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
"vitess.io/vitess/go/vt/key"
|
"vitess.io/vitess/go/vt/key"
|
||||||
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
|
topodatapb "vitess.io/vitess/go/vt/proto/topodata"
|
||||||
"vitess.io/vitess/go/vt/vtgate/vindexes"
|
"vitess.io/vitess/go/vt/vtgate/vindexes"
|
||||||
|
@ -25,16 +27,42 @@ import (
|
||||||
// PlanDescription is used to create a serializable representation of the Primitive tree
|
// PlanDescription is used to create a serializable representation of the Primitive tree
|
||||||
type PlanDescription struct {
|
type PlanDescription struct {
|
||||||
OperatorType string
|
OperatorType string
|
||||||
Variant string
|
Variant string `json:",omitempty"`
|
||||||
// Keyspace specifies the keyspace to send the query to.
|
// 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 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
|
// TargetTabletType specifies an explicit target destination tablet type
|
||||||
// this is only used in conjunction with TargetDestination
|
// this is only used in conjunction with TargetDestination
|
||||||
TargetTabletType topodatapb.TabletType
|
TargetTabletType topodatapb.TabletType `json:",omitempty"`
|
||||||
Other map[string]string
|
Other map[string]string `json:",omitempty"`
|
||||||
Inputs []PlanDescription
|
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
|
//PrimitiveToPlanDescription transforms a primitive tree into a corresponding PlanDescription tree
|
||||||
|
|
|
@ -19,6 +19,8 @@ package engine
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"vitess.io/vitess/go/vt/key"
|
||||||
|
|
||||||
"vitess.io/vitess/go/sqltypes"
|
"vitess.io/vitess/go/sqltypes"
|
||||||
"vitess.io/vitess/go/vt/vterrors"
|
"vitess.io/vitess/go/vt/vterrors"
|
||||||
|
|
||||||
|
@ -31,11 +33,14 @@ var _ Primitive = (*PulloutSubquery)(nil)
|
||||||
// PulloutSubquery executes a "pulled out" subquery and stores
|
// PulloutSubquery executes a "pulled out" subquery and stores
|
||||||
// the results in a bind variable.
|
// the results in a bind variable.
|
||||||
type PulloutSubquery struct {
|
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
|
SubqueryResult string
|
||||||
HasValues string
|
HasValues string
|
||||||
Subquery Primitive
|
|
||||||
Underlying Primitive
|
Subquery Primitive
|
||||||
|
Underlying Primitive
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inputs returns the input primitives for this join
|
// 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 {
|
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
|
// PulloutOpcode is a number representing the opcode
|
||||||
|
|
|
@ -18,6 +18,7 @@ package engine
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"vitess.io/vitess/go/sqltypes"
|
"vitess.io/vitess/go/sqltypes"
|
||||||
|
"vitess.io/vitess/go/vt/key"
|
||||||
querypb "vitess.io/vitess/go/vt/proto/query"
|
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 {
|
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)
|
descr := engine.PrimitiveToPlanDescription(plan.Instructions)
|
||||||
sss, _ := json.MarshalIndent(descr, "", " ")
|
|
||||||
fmt.Println(string(sss))
|
|
||||||
|
|
||||||
bout, _ := json.MarshalIndent(testPlan{
|
bout, _ := json.MarshalIndent(descr, " ", " ")
|
||||||
Original: plan.Original,
|
fmt.Println(string(bout))
|
||||||
Instructions: plan.Instructions,
|
|
||||||
}, "", " ")
|
|
||||||
return string(bout)
|
return string(bout)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче