Skip to content

Commit

Permalink
solve SET SQL_SELECT_LIMIT using plans
Browse files Browse the repository at this point in the history
Signed-off-by: Andres Taylor <andres@planetscale.com>
  • Loading branch information
systay committed Aug 12, 2020
1 parent 39f06c7 commit bfef26e
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 27 deletions.
8 changes: 8 additions & 0 deletions go/vt/vtgate/engine/fake_vcursor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,10 @@ func (t noopVCursor) SetSkipQueryPlanCache(bool) {
panic("implement me")
}

func (t noopVCursor) SetSQLSelectLimit(int64) {
panic("implement me")
}

func (t noopVCursor) SetTarget(string) error {
panic("implement me")
}
Expand Down Expand Up @@ -375,6 +379,10 @@ func (f *loggingVCursor) SetSkipQueryPlanCache(bool) {
panic("implement me")
}

func (f *loggingVCursor) SetSQLSelectLimit(int64) {
panic("implement me")
}

func (f *loggingVCursor) nextResult() (*sqltypes.Result, error) {
if f.results == nil || f.curResult >= len(f.results) {
return &sqltypes.Result{}, f.resultErr
Expand Down
1 change: 1 addition & 0 deletions go/vt/vtgate/engine/primitive.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ type (
SetAutocommit(bool) error
SetClientFoundRows(bool)
SetSkipQueryPlanCache(bool)
SetSQLSelectLimit(int64)
}

// Plan represents the execution strategy for a given query.
Expand Down
18 changes: 18 additions & 0 deletions go/vt/vtgate/engine/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ const (
SkipQueryPlanCache = "skip_query_plan_cache"
TxReadOnly = "tx_read_only"
TransactionReadOnly = "transaction_read_only"
SQLSelectLimit = "sql_select_limit"
)

//MarshalJSON provides the type to SetOp for plan json
Expand Down Expand Up @@ -384,7 +385,24 @@ func (svss *SysVarSetAware) Execute(vcursor VCursor, env evalengine.ExpressionEn
case TxReadOnly, TransactionReadOnly:
// TODO (4127): This is a dangerous NOP.
}
case SQLSelectLimit:
value, err := svss.Expr.Evaluate(env)
if err != nil {
return err
}

v := value.Value()
switch {
case v.IsIntegral():
intValue, err := v.ToInt64()
if err != nil {
return err
}
vcursor.Session().SetSQLSelectLimit(intValue)
default:
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected value type for sql_select_limit: %T", value.Value().Type().String())

}
default:
return vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unsupported construct")
}
Expand Down
14 changes: 0 additions & 14 deletions go/vt/vtgate/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -478,20 +478,6 @@ func handleSessionSetting(name string, session *SafeSession, value interface{},
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid workload: %s", val)
}
session.GetOrCreateOptions().Workload = querypb.ExecuteOptions_Workload(out)
case "sql_select_limit":
var val int64

switch cast := value.(type) {
case int64:
val = cast
case string:
if !strings.EqualFold(cast, "default") {
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected string value for sql_select_limit: %v", value)
}
default:
return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "unexpected value type for sql_select_limit: %T", value)
}
session.GetOrCreateOptions().SqlSelectLimit = val
case "charset", "names":
val, ok := value.(string)
if !ok {
Expand Down
9 changes: 5 additions & 4 deletions go/vt/vtgate/executor_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,12 @@ func TestExecutorSet(t *testing.T) {
in: "set sql_select_limit = 5",
out: &vtgatepb.Session{Autocommit: true, Options: &querypb.ExecuteOptions{SqlSelectLimit: 5}},
}, {
in: "set sql_select_limit = DEFAULT",
out: &vtgatepb.Session{Autocommit: true, Options: &querypb.ExecuteOptions{SqlSelectLimit: 0}},
}, {
// TODO: re-enable when we support DEFAULT
// in: "set sql_select_limit = DEFAULT",
// out: &vtgatepb.Session{Autocommit: true, Options: &querypb.ExecuteOptions{SqlSelectLimit: 0}},
//}, {
in: "set sql_select_limit = 'asdfasfd'",
err: "unexpected string value for sql_select_limit: asdfasfd",
err: "unexpected value type for sql_select_limit: string",
}, {
in: "set autocommit = 1+1",
err: "System setting 'autocommit' can't be set to this value: 2 is not a boolean",
Expand Down
14 changes: 7 additions & 7 deletions go/vt/vtgate/planbuilder/set.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ type (
planFunc = func(expr *sqlparser.SetExpr, vschema ContextVSchema, ec *expressionConverter) (engine.SetOp, error)

expressionConverter struct {
tabletExpressions []*sqlparser.SetExpr
tabletExpressions []sqlparser.Expr
}

setting struct {
Expand Down Expand Up @@ -208,6 +208,7 @@ var vitessAware = []setting{
{name: engine.SkipQueryPlanCache, boolean: true},
{name: engine.TransactionReadOnly, boolean: true},
{name: engine.TxReadOnly, boolean: true},
{name: engine.SQLSelectLimit},
}

func init() {
Expand Down Expand Up @@ -243,7 +244,7 @@ func buildSetPlan(stmt *sqlparser.Set, vschema ContextVSchema) (engine.Primitive
// would have been explictly set to sqlparser.SessionStr before reaching this
// phase of planning
case "":
evalExpr, err := ec.convert(expr, false)
evalExpr, err := ec.convert(expr.Expr, false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -279,8 +280,7 @@ func buildSetPlan(stmt *sqlparser.Set, vschema ContextVSchema) (engine.Primitive
}, nil
}

func (ec *expressionConverter) convert(setExpr *sqlparser.SetExpr, boolean bool) (evalengine.Expr, error) {
astExpr := setExpr.Expr
func (ec *expressionConverter) convert(astExpr sqlparser.Expr, boolean bool) (evalengine.Expr, error) {
if boolean {
switch node := astExpr.(type) {
case *sqlparser.SQLVal:
Expand Down Expand Up @@ -317,7 +317,7 @@ func (ec *expressionConverter) convert(setExpr *sqlparser.SetExpr, boolean bool)
return nil, vterrors.Errorf(vtrpcpb.Code_UNIMPLEMENTED, "expression not supported for SET: %s", sqlparser.String(astExpr))
}
evalExpr = &evalengine.Column{Offset: len(ec.tabletExpressions)}
ec.tabletExpressions = append(ec.tabletExpressions, setExpr)
ec.tabletExpressions = append(ec.tabletExpressions, astExpr)
}
return evalExpr, nil
}
Expand All @@ -333,7 +333,7 @@ func (ec *expressionConverter) source(vschema ContextVSchema) (engine.Primitive,

var expr []string
for _, e := range ec.tabletExpressions {
expr = append(expr, sqlparser.String(e.Expr))
expr = append(expr, sqlparser.String(e))
}
query := fmt.Sprintf("select %s from dual", strings.Join(expr, ","))

Expand Down Expand Up @@ -413,7 +413,7 @@ func buildSetOpVarSet(boolean bool) planFunc {

func buildSetOpVitessAware(boolean bool) planFunc {
return func(astExpr *sqlparser.SetExpr, vschema ContextVSchema, ec *expressionConverter) (engine.SetOp, error) {
runtimeExpr, err := ec.convert(astExpr, boolean)
runtimeExpr, err := ec.convert(astExpr.Expr, boolean)
if err != nil {
return nil, err
}
Expand Down
9 changes: 7 additions & 2 deletions go/vt/vtgate/planbuilder/testdata/set_cases.txt
Original file line number Diff line number Diff line change
Expand Up @@ -427,10 +427,10 @@
}

# more vitess aware settings
"set client_found_rows = off, skip_query_plan_cache = ON"
"set client_found_rows = off, skip_query_plan_cache = ON, sql_select_limit=20"
{
"QueryType": "SET",
"Original": "set client_found_rows = off, skip_query_plan_cache = ON",
"Original": "set client_found_rows = off, skip_query_plan_cache = ON, sql_select_limit=20",
"Instructions": {
"OperatorType": "Set",
"Ops": [
Expand All @@ -443,6 +443,11 @@
"Type": "SysVarAware",
"Name": "skip_query_plan_cache",
"Expr": "INT64(1)"
},
{
"Type": "SysVarAware",
"Name": "sql_select_limit",
"Expr": "INT64(20)"
}
],
"Inputs": [
Expand Down
5 changes: 5 additions & 0 deletions go/vt/vtgate/vcursor_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,11 @@ func (vc *vcursorImpl) SetSkipQueryPlanCache(skipQueryPlanCache bool) {
vc.safeSession.GetOrCreateOptions().SkipQueryPlanCache = skipQueryPlanCache
}

//SetSkipQueryPlanCache implementes the SessionActions interface
func (vc *vcursorImpl) SetSQLSelectLimit(limit int64) {
vc.safeSession.GetOrCreateOptions().SqlSelectLimit = limit
}

// ParseDestinationTarget parses destination target string and sets default keyspace if possible.
func parseDestinationTarget(targetString string, vschema *vindexes.VSchema) (string, topodatapb.TabletType, key.Destination, error) {
destKeyspace, destTabletType, dest, err := topoprotopb.ParseDestination(targetString, defaultTabletType)
Expand Down

0 comments on commit bfef26e

Please sign in to comment.