github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/explain/explain_expr.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 explain
    16  
    17  import (
    18  	"bytes"
    19  	"context"
    20  	"fmt"
    21  	"strconv"
    22  	"strings"
    23  
    24  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    25  	"github.com/matrixorigin/matrixone/pkg/container/types"
    26  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    27  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    28  	"github.com/matrixorigin/matrixone/pkg/sql/plan/function"
    29  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    30  )
    31  
    32  func describeMessage(m *plan.MsgHeader, buf *bytes.Buffer) {
    33  	buf.WriteString("[tag ")
    34  	fmt.Fprintf(buf, "%d", m.MsgTag)
    35  	buf.WriteString(" , type ")
    36  	msgType := process.MsgType(m.MsgType)
    37  	buf.WriteString(msgType.MessageName())
    38  	buf.WriteString("]")
    39  }
    40  
    41  func describeExpr(ctx context.Context, expr *plan.Expr, options *ExplainOptions, buf *bytes.Buffer) error {
    42  	switch exprImpl := expr.Expr.(type) {
    43  	case *plan.Expr_Col:
    44  		if len(exprImpl.Col.Name) > 0 {
    45  			buf.WriteString(exprImpl.Col.Name)
    46  		} else {
    47  			buf.WriteString("#[")
    48  			buf.WriteString(strconv.Itoa(int(exprImpl.Col.RelPos)))
    49  			buf.WriteString(",")
    50  			buf.WriteString(strconv.Itoa(int(exprImpl.Col.ColPos)))
    51  			buf.WriteString("]")
    52  		}
    53  
    54  	case *plan.Expr_Lit:
    55  		if exprImpl.Lit.Isnull {
    56  			buf.WriteString("(null)")
    57  			break
    58  		}
    59  
    60  		switch val := exprImpl.Lit.Value.(type) {
    61  		case *plan.Literal_I8Val:
    62  			fmt.Fprintf(buf, "%d", val.I8Val)
    63  		case *plan.Literal_I16Val:
    64  			fmt.Fprintf(buf, "%d", val.I16Val)
    65  		case *plan.Literal_I32Val:
    66  			fmt.Fprintf(buf, "%d", val.I32Val)
    67  		case *plan.Literal_I64Val:
    68  			fmt.Fprintf(buf, "%d", val.I64Val)
    69  		case *plan.Literal_U8Val:
    70  			fmt.Fprintf(buf, "%d", val.U8Val)
    71  		case *plan.Literal_U16Val:
    72  			fmt.Fprintf(buf, "%d", val.U16Val)
    73  		case *plan.Literal_U32Val:
    74  			fmt.Fprintf(buf, "%d", val.U32Val)
    75  		case *plan.Literal_U64Val:
    76  			fmt.Fprintf(buf, "%d", val.U64Val)
    77  		case *plan.Literal_Fval:
    78  			fmt.Fprintf(buf, "%v", strconv.FormatFloat(float64(val.Fval), 'f', -1, 32))
    79  		case *plan.Literal_Dval:
    80  			fmt.Fprintf(buf, "%v", strconv.FormatFloat(val.Dval, 'f', -1, 64))
    81  		case *plan.Literal_Dateval:
    82  			fmt.Fprintf(buf, "%s", types.Date(val.Dateval))
    83  		case *plan.Literal_Datetimeval:
    84  			fmt.Fprintf(buf, "%s", types.Datetime(val.Datetimeval).String2(expr.Typ.Scale))
    85  		case *plan.Literal_Timeval:
    86  			fmt.Fprintf(buf, "%s", types.Time(val.Timeval).String2(expr.Typ.Scale))
    87  		case *plan.Literal_Sval:
    88  			buf.WriteString("'" + val.Sval + "'")
    89  		case *plan.Literal_Bval:
    90  			fmt.Fprintf(buf, "%v", val.Bval)
    91  		case *plan.Literal_EnumVal:
    92  			fmt.Fprintf(buf, "%v", val.EnumVal)
    93  		case *plan.Literal_Decimal64Val:
    94  			fmt.Fprintf(buf, "%s", types.Decimal64(val.Decimal64Val.A).Format(expr.Typ.GetScale()))
    95  		case *plan.Literal_Decimal128Val:
    96  			fmt.Fprintf(buf, "%s",
    97  				types.Decimal128{B0_63: uint64(val.Decimal128Val.A), B64_127: uint64(val.Decimal128Val.B)}.Format(expr.Typ.GetScale()))
    98  		}
    99  
   100  	case *plan.Expr_F:
   101  		err := funcExprExplain(ctx, expr.GetF(), &expr.Typ, options, buf)
   102  		if err != nil {
   103  			return err
   104  		}
   105  	case *plan.Expr_W:
   106  		w := exprImpl.W
   107  		err := funcExprExplain(ctx, w.WindowFunc.GetF(), &expr.Typ, options, buf)
   108  		if err != nil {
   109  			return err
   110  		}
   111  
   112  		if len(w.PartitionBy) > 0 {
   113  			buf.WriteString("; Partition By: ")
   114  			for i, arg := range w.PartitionBy {
   115  				if i > 0 {
   116  					buf.WriteString(", ")
   117  				}
   118  				err = describeExpr(ctx, arg, options, buf)
   119  				if err != nil {
   120  					return err
   121  				}
   122  			}
   123  		}
   124  
   125  		if len(w.OrderBy) > 0 {
   126  			buf.WriteString("; Order By: ")
   127  			for i, arg := range w.OrderBy {
   128  				if i > 0 {
   129  					buf.WriteString(", ")
   130  				}
   131  				err = describeExpr(ctx, arg.Expr, options, buf)
   132  				if err != nil {
   133  					return err
   134  				}
   135  			}
   136  		}
   137  	case *plan.Expr_Sub:
   138  		subqryExpr := expr.Expr.(*plan.Expr_Sub)
   139  		buf.WriteString("subquery nodeId = " + strconv.FormatInt(int64(subqryExpr.Sub.NodeId), 10))
   140  	case *plan.Expr_Corr:
   141  		buf.WriteString("#[")
   142  		buf.WriteString(strconv.FormatInt(int64(exprImpl.Corr.RelPos), 10))
   143  		buf.WriteString(",")
   144  		buf.WriteString(strconv.FormatInt(int64(exprImpl.Corr.ColPos), 10))
   145  		buf.WriteString(":")
   146  		buf.WriteString(strconv.FormatInt(int64(exprImpl.Corr.Depth), 10))
   147  		buf.WriteString("]")
   148  	case *plan.Expr_V:
   149  		if exprImpl.V.System {
   150  			if exprImpl.V.Global {
   151  				buf.WriteString("@@global." + exprImpl.V.Name)
   152  			} else {
   153  				buf.WriteString("@@session." + exprImpl.V.Name)
   154  			}
   155  		} else {
   156  			buf.WriteString("@" + exprImpl.V.Name)
   157  		}
   158  	case *plan.Expr_P:
   159  		buf.WriteString("?")
   160  	case *plan.Expr_List:
   161  		exprlist := expr.Expr.(*plan.Expr_List)
   162  		if exprlist.List.List != nil {
   163  			exprListDescImpl := NewExprListDescribeImpl(exprlist.List.List)
   164  			err := exprListDescImpl.GetDescription(ctx, options, buf)
   165  			if err != nil {
   166  				return err
   167  			}
   168  		}
   169  	case *plan.Expr_Vec:
   170  		vec := vector.NewVec(types.T_any.ToType())
   171  		vec.UnmarshalBinary(exprImpl.Vec.Data)
   172  		if vec.Length() > 16 {
   173  			//don't display too long data in explain
   174  			originalLen := vec.Length()
   175  			vec.SetLength(16)
   176  			buf.WriteString(vec.String())
   177  			s := fmt.Sprintf("... %v values", originalLen)
   178  			buf.WriteString(s)
   179  		} else {
   180  			buf.WriteString(vec.String())
   181  		}
   182  		vec.Free(nil)
   183  	case *plan.Expr_T:
   184  		tt := types.T(expr.Typ.Id)
   185  		if tt == types.T_decimal64 || tt == types.T_decimal128 {
   186  			fmt.Fprintf(buf, "%s(%d, %d))", tt.String(), expr.Typ.Width, expr.Typ.Scale)
   187  		} else {
   188  			fmt.Fprintf(buf, "%s)", tt.String())
   189  		}
   190  	default:
   191  		panic("unsupported expr")
   192  	}
   193  	return nil
   194  }
   195  
   196  // generator function expression(Expr_F) explain information
   197  func funcExprExplain(ctx context.Context, funcExpr *plan.Function, Typ *plan.Type, options *ExplainOptions, buf *bytes.Buffer) error {
   198  	// SysFunsAndOperatorsMap
   199  	funcName := funcExpr.GetFunc().GetObjName()
   200  	funcDef := funcExpr.GetFunc()
   201  
   202  	layout, err := function.GetLayoutById(ctx, funcDef.Obj&function.DistinctMask)
   203  	if err != nil {
   204  		return moerr.NewInvalidInput(ctx, "invalid function or opreator '%s'", funcName)
   205  	}
   206  
   207  	switch layout {
   208  	case function.STANDARD_FUNCTION:
   209  		buf.WriteString(funcExpr.Func.GetObjName() + "(")
   210  		if len(funcExpr.Args) > 0 {
   211  			var first = true
   212  			for _, v := range funcExpr.Args {
   213  				if !first {
   214  					buf.WriteString(", ")
   215  				}
   216  				first = false
   217  				err = describeExpr(ctx, v, options, buf)
   218  				if err != nil {
   219  					return err
   220  				}
   221  			}
   222  		}
   223  		buf.WriteString(")")
   224  	case function.UNARY_ARITHMETIC_OPERATOR:
   225  		var opertator string
   226  		if funcExpr.Func.GetObjName() == "UNARY_PLUS" {
   227  			opertator = "+"
   228  		} else {
   229  			opertator = "-"
   230  		}
   231  		buf.WriteString("(" + opertator)
   232  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   233  		if err != nil {
   234  			return err
   235  		}
   236  		buf.WriteString(")")
   237  	case function.UNARY_LOGICAL_OPERATOR:
   238  		buf.WriteString("(" + funcExpr.Func.GetObjName() + " ")
   239  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   240  		if err != nil {
   241  			return err
   242  		}
   243  		buf.WriteString(")")
   244  		//result += "(" + funcExpr.Func.GetObjName() + " " + describeExpr + ")"
   245  	case function.BINARY_ARITHMETIC_OPERATOR:
   246  		fallthrough
   247  	case function.BINARY_LOGICAL_OPERATOR:
   248  		fallthrough
   249  	case function.COMPARISON_OPERATOR:
   250  		buf.WriteString("(")
   251  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   252  		if err != nil {
   253  			return err
   254  		}
   255  		buf.WriteString(" " + funcExpr.Func.GetObjName() + " ")
   256  		err = describeExpr(ctx, funcExpr.Args[1], options, buf)
   257  		if err != nil {
   258  			return err
   259  		}
   260  		buf.WriteString(")")
   261  	case function.CAST_EXPRESSION:
   262  		buf.WriteString(funcName)
   263  		buf.WriteString("(")
   264  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   265  		if err != nil {
   266  			return err
   267  		}
   268  		tt := types.T(Typ.Id)
   269  		if tt == types.T_decimal64 || tt == types.T_decimal128 {
   270  			fmt.Fprintf(buf, " AS %s(%d, %d))", tt.String(), Typ.Width, Typ.Scale)
   271  		} else {
   272  			fmt.Fprintf(buf, " AS %s)", tt.String())
   273  		}
   274  	case function.CASE_WHEN_EXPRESSION:
   275  		// TODO need rewrite to deal with case is nil
   276  		buf.WriteString("CASE")
   277  		// case when expression has two part(case when condition and else exression)
   278  		condSize := len(funcExpr.Args) - 1
   279  		for i := 0; i < condSize; i += 2 {
   280  			whenExpr := funcExpr.Args[i]
   281  			thenExpr := funcExpr.Args[i+1]
   282  			buf.WriteString(" WHEN ")
   283  			err = describeExpr(ctx, whenExpr, options, buf)
   284  			if err != nil {
   285  				return err
   286  			}
   287  			buf.WriteString(" THEN ")
   288  			err = describeExpr(ctx, thenExpr, options, buf)
   289  			if err != nil {
   290  				return err
   291  			}
   292  		}
   293  
   294  		if len(funcExpr.Args)%2 == 1 {
   295  			lastIndex := len(funcExpr.Args) - 1
   296  			elseExpr := funcExpr.Args[lastIndex]
   297  			// get else expression
   298  			buf.WriteString(" ELSE ")
   299  			err = describeExpr(ctx, elseExpr, options, buf)
   300  			if err != nil {
   301  				return err
   302  			}
   303  		}
   304  		buf.WriteString(" END")
   305  	case function.BETWEEN_AND_EXPRESSION:
   306  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   307  		if err != nil {
   308  			return err
   309  		}
   310  		buf.WriteString(" BETWEEN ")
   311  		err = describeExpr(ctx, funcExpr.Args[1], options, buf)
   312  		if err != nil {
   313  			return err
   314  		}
   315  		buf.WriteString(" AND ")
   316  		err = describeExpr(ctx, funcExpr.Args[2], options, buf)
   317  		if err != nil {
   318  			return err
   319  		}
   320  	case function.IN_PREDICATE:
   321  		if len(funcExpr.Args) != 2 {
   322  			panic("Nested query predicate,such as in,exist,all,any parameter number error!")
   323  		}
   324  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   325  		if err != nil {
   326  			return err
   327  		}
   328  		buf.WriteString(" " + funcExpr.Func.GetObjName() + " (")
   329  		err = describeExpr(ctx, funcExpr.Args[1], options, buf)
   330  		if err != nil {
   331  			return err
   332  		}
   333  		buf.WriteString(")")
   334  	case function.EXISTS_ANY_PREDICATE:
   335  		buf.WriteString(funcExpr.Func.GetObjName() + "(")
   336  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   337  		if err != nil {
   338  			return err
   339  		}
   340  		buf.WriteString(")")
   341  	case function.IS_EXPRESSION:
   342  		buf.WriteString("(")
   343  		err := describeExpr(ctx, funcExpr.Args[0], options, buf)
   344  		if err != nil {
   345  			return err
   346  		}
   347  		buf.WriteString(fmt.Sprintf(" IS %s)", strings.ToUpper(funcExpr.Func.GetObjName()[2:])))
   348  	case function.IS_NOT_EXPRESSION:
   349  		buf.WriteString("(")
   350  		err := describeExpr(ctx, funcExpr.Args[0], options, buf)
   351  		if err != nil {
   352  			return err
   353  		}
   354  		buf.WriteString(fmt.Sprintf(" IS NOT %s)", strings.ToUpper(funcExpr.Func.GetObjName()[5:])))
   355  	case function.NOPARAMETER_FUNCTION:
   356  		buf.WriteString(funcExpr.Func.GetObjName())
   357  	case function.DATE_INTERVAL_EXPRESSION:
   358  		buf.WriteString(funcExpr.Func.GetObjName() + " ")
   359  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   360  		if err != nil {
   361  			return err
   362  		}
   363  	case function.EXTRACT_FUNCTION:
   364  		buf.WriteString(funcExpr.Func.GetObjName() + "(")
   365  		err = describeExpr(ctx, funcExpr.Args[0], options, buf)
   366  		if err != nil {
   367  			return err
   368  		}
   369  		buf.WriteString(" from ")
   370  		err = describeExpr(ctx, funcExpr.Args[1], options, buf)
   371  		if err != nil {
   372  			return err
   373  		}
   374  		buf.WriteString(")")
   375  	case function.UNKNOW_KIND_FUNCTION:
   376  		return moerr.NewInvalidInput(ctx, "explain contains UNKNOW_KIND_FUNCTION")
   377  	}
   378  	return nil
   379  }