github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/build.go (about)

     1  // Copyright 2021 - 2022 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package plan
    16  
    17  import (
    18  	"context"
    19  	gotrace "runtime/trace"
    20  	"time"
    21  
    22  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    25  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    26  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    27  	v2 "github.com/matrixorigin/matrixone/pkg/util/metric/v2"
    28  )
    29  
    30  func runBuildSelectByBinder(stmtType plan.Query_StatementType, ctx CompilerContext, stmt *tree.Select, isPrepareStmt bool) (*Plan, error) {
    31  	start := time.Now()
    32  	defer func() {
    33  		v2.TxnStatementBuildSelectHistogram.Observe(time.Since(start).Seconds())
    34  	}()
    35  
    36  	builder := NewQueryBuilder(stmtType, ctx, isPrepareStmt)
    37  	bindCtx := NewBindContext(builder, nil)
    38  	if IsSnapshotValid(ctx.GetSnapshot()) {
    39  		bindCtx.snapshot = ctx.GetSnapshot()
    40  	}
    41  
    42  	rootId, err := builder.buildSelect(stmt, bindCtx, true)
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	ctx.SetViews(bindCtx.views)
    47  
    48  	builder.qry.Steps = append(builder.qry.Steps, rootId)
    49  	query, err := builder.createQuery()
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  	return &Plan{
    54  		Plan: &plan.Plan_Query{
    55  			Query: query,
    56  		},
    57  	}, err
    58  }
    59  
    60  func buildExplainAnalyze(ctx CompilerContext, stmt *tree.ExplainAnalyze, isPrepareStmt bool) (*Plan, error) {
    61  	start := time.Now()
    62  	defer func() {
    63  		v2.TxnStatementBuildExplainHistogram.Observe(time.Since(start).Seconds())
    64  	}()
    65  	//get query optimizer and execute Optimize
    66  	plan, err := BuildPlan(ctx, stmt.Statement, isPrepareStmt)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	//if it is the plan of the EXECUTE, replace it by the plan generated by the PREPARE.
    71  	//At the same time, replace the param var by the param val
    72  	if plan.GetDcl() != nil && plan.GetDcl().GetExecute() != nil {
    73  		execPlan := plan.GetDcl().GetExecute()
    74  		replaced, _, err := ctx.ReplacePlan(execPlan)
    75  		if err != nil {
    76  			return nil, err
    77  		}
    78  		plan = replaced
    79  	}
    80  	if plan.GetQuery() == nil {
    81  		return nil, moerr.NewNotSupported(ctx.GetContext(), "the sql query plan does not support explain.")
    82  	}
    83  	return plan, nil
    84  }
    85  
    86  func BuildPlan(ctx CompilerContext, stmt tree.Statement, isPrepareStmt bool) (*Plan, error) {
    87  	start := time.Now()
    88  	defer func() {
    89  		v2.TxnStatementBuildPlanHistogram.Observe(time.Since(start).Seconds())
    90  	}()
    91  	_, task := gotrace.NewTask(context.TODO(), "plan.BuildPlan")
    92  	defer task.End()
    93  	switch stmt := stmt.(type) {
    94  	case *tree.Select:
    95  		return runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt, isPrepareStmt)
    96  	case *tree.ParenSelect:
    97  		return runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt.Select, isPrepareStmt)
    98  	case *tree.ExplainAnalyze:
    99  		return buildExplainAnalyze(ctx, stmt, isPrepareStmt)
   100  	case *tree.Insert:
   101  		return buildInsert(stmt, ctx, false, isPrepareStmt)
   102  	case *tree.Replace:
   103  		return buildReplace(stmt, ctx, isPrepareStmt)
   104  	case *tree.Update:
   105  		return buildTableUpdate(stmt, ctx, isPrepareStmt)
   106  	case *tree.Delete:
   107  		return buildDelete(stmt, ctx, isPrepareStmt)
   108  	case *tree.BeginTransaction:
   109  		return buildBeginTransaction(stmt, ctx)
   110  	case *tree.CommitTransaction:
   111  		return buildCommitTransaction(stmt, ctx)
   112  	case *tree.RollbackTransaction:
   113  		return buildRollbackTransaction(stmt, ctx)
   114  	case *tree.CreateDatabase:
   115  		return buildCreateDatabase(stmt, ctx)
   116  	case *tree.DropDatabase:
   117  		return buildDropDatabase(stmt, ctx)
   118  	case *tree.CreateTable:
   119  		return buildCreateTable(stmt, ctx)
   120  	case *tree.DropTable:
   121  		return buildDropTable(stmt, ctx)
   122  	case *tree.TruncateTable:
   123  		return buildTruncateTable(stmt, ctx)
   124  	case *tree.CreateSequence:
   125  		return buildCreateSequence(stmt, ctx)
   126  	case *tree.DropSequence:
   127  		return buildDropSequence(stmt, ctx)
   128  	case *tree.AlterSequence:
   129  		return buildAlterSequence(stmt, ctx)
   130  	case *tree.DropView:
   131  		return buildDropView(stmt, ctx)
   132  	case *tree.CreateView:
   133  		return buildCreateView(stmt, ctx)
   134  	case *tree.CreateSource:
   135  		return buildCreateSource(stmt, ctx)
   136  	case *tree.AlterView:
   137  		return buildAlterView(stmt, ctx)
   138  	case *tree.AlterTable:
   139  		return buildAlterTable(stmt, ctx)
   140  	case *tree.CreateIndex:
   141  		return buildCreateIndex(stmt, ctx)
   142  	case *tree.DropIndex:
   143  		return buildDropIndex(stmt, ctx)
   144  	case *tree.ShowCreateDatabase:
   145  		return buildShowCreateDatabase(stmt, ctx)
   146  	case *tree.ShowCreateTable:
   147  		return buildShowCreateTable(stmt, ctx)
   148  	case *tree.ShowCreateView:
   149  		return buildShowCreateView(stmt, ctx)
   150  	case *tree.ShowDatabases:
   151  		return buildShowDatabases(stmt, ctx)
   152  	case *tree.ShowTables:
   153  		return buildShowTables(stmt, ctx)
   154  	case *tree.ShowSequences:
   155  		return buildShowSequences(stmt, ctx)
   156  	case *tree.ShowColumns:
   157  		return buildShowColumns(stmt, ctx)
   158  	case *tree.ShowTableStatus:
   159  		return buildShowTableStatus(stmt, ctx)
   160  	case *tree.ShowTarget:
   161  		return buildShowTarget(stmt, ctx)
   162  	case *tree.ShowIndex:
   163  		return buildShowIndex(stmt, ctx)
   164  	case *tree.ShowGrants:
   165  		return buildShowGrants(stmt, ctx)
   166  	case *tree.ShowVariables:
   167  		return buildShowVariables(stmt, ctx)
   168  	case *tree.ShowStatus:
   169  		return buildShowStatus(stmt, ctx)
   170  	case *tree.ShowProcessList:
   171  		return buildShowProcessList(ctx)
   172  	case *tree.ShowLocks:
   173  		return buildShowLocks(stmt, ctx)
   174  	case *tree.ShowNodeList:
   175  		return buildShowNodeList(stmt, ctx)
   176  	case *tree.ShowFunctionOrProcedureStatus:
   177  		return buildShowFunctionOrProcedureStatus(stmt, ctx)
   178  	case *tree.ShowTableNumber:
   179  		return buildShowTableNumber(stmt, ctx)
   180  	case *tree.ShowColumnNumber:
   181  		return buildShowColumnNumber(stmt, ctx)
   182  	case *tree.ShowTableValues:
   183  		return buildShowTableValues(stmt, ctx)
   184  	case *tree.ShowRolesStmt:
   185  		return buildShowRoles(stmt, ctx)
   186  	case *tree.SetVar:
   187  		return buildSetVariables(stmt, ctx)
   188  	case *tree.Execute:
   189  		return buildExecute(stmt, ctx)
   190  	case *tree.Deallocate:
   191  		return buildDeallocate(stmt, ctx)
   192  	case *tree.Load:
   193  		return buildLoad(stmt, ctx, isPrepareStmt)
   194  	case *tree.PrepareStmt, *tree.PrepareString:
   195  		return buildPrepare(stmt, ctx)
   196  	case *tree.Do, *tree.Declare:
   197  		return nil, moerr.NewNotSupported(ctx.GetContext(), tree.String(stmt, dialect.MYSQL))
   198  	case *tree.ValuesStatement:
   199  		return buildValues(stmt, ctx, isPrepareStmt)
   200  	case *tree.LockTableStmt:
   201  		return buildLockTables(stmt, ctx)
   202  	case *tree.UnLockTableStmt:
   203  		return buildUnLockTables(stmt, ctx)
   204  	case *tree.ShowPublications:
   205  		return buildShowPublication(stmt, ctx)
   206  	case *tree.ShowCreatePublications:
   207  		return buildShowCreatePublications(stmt, ctx)
   208  	case *tree.ShowStages:
   209  		return buildShowStages(stmt, ctx)
   210  	case *tree.ShowSnapShots:
   211  		return buildShowSnapShots(stmt, ctx)
   212  	case *tree.CreateAccount:
   213  		return buildCreateAccount(stmt, ctx, isPrepareStmt)
   214  	case *tree.AlterAccount:
   215  		return buildAlterAccount(stmt, ctx, isPrepareStmt)
   216  	case *tree.DropAccount:
   217  		return buildDropAccount(stmt, ctx, isPrepareStmt)
   218  	case *tree.ShowAccountUpgrade:
   219  		return buildShowAccountUpgrade(stmt, ctx)
   220  	default:
   221  		return nil, moerr.NewInternalError(ctx.GetContext(), "statement: '%v'", tree.String(stmt, dialect.MYSQL))
   222  	}
   223  }
   224  
   225  // GetExecType get executor will execute base AP or TP
   226  func GetExecTypeFromPlan(pn *Plan) ExecInfo {
   227  	defInfo := ExecInfo{
   228  		Typ:        ExecTypeAP,
   229  		WithGPU:    false,
   230  		WithBigMem: false,
   231  		CnNumbers:  2,
   232  	}
   233  	if IsTpQuery(pn.GetQuery()) {
   234  		defInfo.Typ = ExecTypeTP
   235  	}
   236  	return defInfo
   237  }
   238  
   239  // GetResultColumnsFromPlan
   240  func GetResultColumnsFromPlan(p *Plan) []*ColDef {
   241  	getResultColumnsByProjectionlist := func(query *Query) []*ColDef {
   242  		lastNode := query.Nodes[query.Steps[len(query.Steps)-1]]
   243  		columns := make([]*ColDef, len(lastNode.ProjectList))
   244  		for idx, expr := range lastNode.ProjectList {
   245  			columns[idx] = &ColDef{
   246  				Name: query.Headings[idx],
   247  				Typ:  expr.Typ,
   248  			}
   249  
   250  			if exprCol, ok := expr.Expr.(*plan.Expr_Col); ok {
   251  				if col := exprCol.Col; col != nil {
   252  					columns[idx].TblName = col.TblName
   253  					columns[idx].DbName = col.DbName
   254  				}
   255  			}
   256  		}
   257  
   258  		return columns
   259  	}
   260  
   261  	switch logicPlan := p.Plan.(type) {
   262  	case *plan.Plan_Query:
   263  		switch logicPlan.Query.StmtType {
   264  		case plan.Query_SELECT:
   265  			return getResultColumnsByProjectionlist(logicPlan.Query)
   266  		default:
   267  			// insert/update/delete statement will return nil
   268  			return nil
   269  		}
   270  	case *plan.Plan_Tcl:
   271  		// begin/commmit/rollback statement will return nil
   272  		return nil
   273  	case *plan.Plan_Ddl:
   274  		switch logicPlan.Ddl.DdlType {
   275  		case plan.DataDefinition_SHOW_VARIABLES:
   276  			typ := plan.Type{
   277  				Id:    int32(types.T_varchar),
   278  				Width: 1024,
   279  			}
   280  			return []*ColDef{
   281  				{Typ: typ, Name: "Variable_name"},
   282  				{Typ: typ, Name: "Value"},
   283  			}
   284  		default:
   285  			// show statement(except show variables) will return a query
   286  			if logicPlan.Ddl.Query != nil {
   287  				return getResultColumnsByProjectionlist(logicPlan.Ddl.Query)
   288  			}
   289  			return nil
   290  		}
   291  	}
   292  	return nil
   293  }