github.com/matrixorigin/matrixone@v0.7.0/pkg/sql/plan/function/builtin/ctl/table_stat.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 ctl
    16  
    17  import (
    18  	"strconv"
    19  
    20  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    21  	"github.com/matrixorigin/matrixone/pkg/container/bytejson"
    22  	"github.com/matrixorigin/matrixone/pkg/container/nulls"
    23  	"github.com/matrixorigin/matrixone/pkg/container/types"
    24  	"github.com/matrixorigin/matrixone/pkg/container/vector"
    25  	"github.com/matrixorigin/matrixone/pkg/defines"
    26  	"github.com/matrixorigin/matrixone/pkg/vm/engine"
    27  	"github.com/matrixorigin/matrixone/pkg/vm/process"
    28  )
    29  
    30  // MoTableRows returns an estimated row number of a table.
    31  func MoTableRows(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    32  	vec := vector.New(types.New(types.T_int64, 0, 0, 0))
    33  	count := vecs[0].Length()
    34  	dbs := vector.MustStrCols(vecs[0])
    35  	tbls := vector.MustStrCols(vecs[1])
    36  	e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine)
    37  	txn, err := proc.TxnClient.New()
    38  	if err != nil {
    39  		return nil, err
    40  	}
    41  	defer txn.Rollback(proc.Ctx)
    42  	if err := e.New(proc.Ctx, txn); err != nil {
    43  		return nil, err
    44  	}
    45  	defer e.Rollback(proc.Ctx, txn)
    46  	for i := 0; i < count; i++ {
    47  		db, err := e.Database(proc.Ctx, dbs[i], txn)
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  		rel, err := db.Relation(proc.Ctx, tbls[i])
    52  		if err != nil {
    53  			return nil, err
    54  		}
    55  		rel.Ranges(proc.Ctx, nil)
    56  		rows, err := rel.Rows(proc.Ctx)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		if err := vec.Append(rows, false, proc.Mp()); err != nil {
    61  			vec.Free(proc.Mp())
    62  			return nil, err
    63  		}
    64  	}
    65  	return vec, nil
    66  }
    67  
    68  // MoTableSize returns an estimated size of a table.
    69  func MoTableSize(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
    70  	vec := vector.New(types.New(types.T_int64, 0, 0, 0))
    71  	count := vecs[0].Length()
    72  	dbs := vector.MustStrCols(vecs[0])
    73  	tbls := vector.MustStrCols(vecs[1])
    74  	e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine)
    75  	txn, err := proc.TxnClient.New()
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	defer txn.Rollback(proc.Ctx)
    80  	if err := e.New(proc.Ctx, txn); err != nil {
    81  		return nil, err
    82  	}
    83  	defer e.Rollback(proc.Ctx, txn)
    84  	for i := 0; i < count; i++ {
    85  		db, err := e.Database(proc.Ctx, dbs[i], txn)
    86  		if err != nil {
    87  			return nil, err
    88  		}
    89  		rel, err := db.Relation(proc.Ctx, tbls[i])
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  		rel.Ranges(proc.Ctx, nil)
    94  		rows, err := rel.Rows(proc.Ctx)
    95  		if err != nil {
    96  			return nil, err
    97  		}
    98  		attrs, err := rel.TableColumns(proc.Ctx)
    99  		if err != nil {
   100  			return nil, err
   101  		}
   102  		size := int64(0)
   103  		for _, attr := range attrs {
   104  			size += rows * int64(attr.Type.TypeSize())
   105  		}
   106  		if err := vec.Append(size, false, proc.Mp()); err != nil {
   107  			vec.Free(proc.Mp())
   108  			return nil, err
   109  		}
   110  	}
   111  	return vec, nil
   112  
   113  }
   114  
   115  // MoTableColMax return the max value of the column
   116  func MoTableColMax(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   117  	count := vecs[0].Length()
   118  	dbs := vector.MustStrCols(vecs[0])
   119  	tbls := vector.MustStrCols(vecs[1])
   120  	cols := vector.MustStrCols(vecs[2])
   121  
   122  	returnType := types.T_varchar.ToType()
   123  	var resultVec *vector.Vector = nil
   124  	resultValues := make([]string, count)
   125  	resultNsp := nulls.NewWithSize(count)
   126  
   127  	if vecs[0].IsScalarNull() || vecs[1].IsScalarNull() || vecs[2].IsScalarNull() {
   128  		return proc.AllocScalarNullVector(returnType), nil
   129  	}
   130  
   131  	// set null row
   132  	nulls.Or(vecs[0].Nsp, vecs[1].Nsp, resultNsp)
   133  	nulls.Or(vecs[2].Nsp, resultNsp, resultNsp)
   134  
   135  	e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine)
   136  	txn, err := proc.TxnClient.New()
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  	defer txn.Rollback(proc.Ctx)
   141  	if err := e.New(proc.Ctx, txn); err != nil {
   142  		return nil, err
   143  	}
   144  	defer e.Rollback(proc.Ctx, txn)
   145  
   146  	for i := 0; i < count; i++ {
   147  		col := cols[i]
   148  		if col == "__mo_rowid" {
   149  			return nil, moerr.NewInvalidArg(proc.Ctx, "mo_table_col_max has bad input column", col)
   150  		}
   151  		if tbls[i] == "mo_database" || tbls[i] == "mo_tables" || tbls[i] == "mo_columns" || tbls[i] == "sys_async_task" {
   152  			return nil, moerr.NewInvalidArg(proc.Ctx, "mo_table_col_max has bad input table", tbls[i])
   153  		}
   154  
   155  		db, err := e.Database(proc.Ctx, dbs[i], txn)
   156  		if err != nil {
   157  			return nil, err
   158  		}
   159  		rel, err := db.Relation(proc.Ctx, tbls[i])
   160  		if err != nil {
   161  			return nil, err
   162  		}
   163  		rel.Ranges(proc.Ctx, nil)
   164  
   165  		tableColumns, err := rel.TableColumns(proc.Ctx)
   166  		if err != nil {
   167  			return nil, err
   168  		}
   169  
   170  		//Get table max and min value from zonemap
   171  		tableVal, _, err := rel.MaxAndMinValues(proc.Ctx)
   172  		if err != nil {
   173  			return nil, err
   174  		}
   175  
   176  		for j := 0; j < len(tableColumns); j++ {
   177  			if tableColumns[j].Name == col {
   178  				resultValues[i] = getVlaueInStr(tableVal[j][1])
   179  				break
   180  			}
   181  		}
   182  	}
   183  	resultVec = vector.NewWithStrings(types.T_varchar.ToType(), resultValues, resultNsp, proc.Mp())
   184  	return resultVec, nil
   185  }
   186  
   187  // MoTableColMax return the max value of the column
   188  func MoTableColMin(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
   189  	count := vecs[0].Length()
   190  	dbs := vector.MustStrCols(vecs[0])
   191  	tbls := vector.MustStrCols(vecs[1])
   192  	cols := vector.MustStrCols(vecs[2])
   193  
   194  	returnType := types.T_varchar.ToType()
   195  	var resultVec *vector.Vector = nil
   196  	resultValues := make([]string, count)
   197  	resultNsp := nulls.NewWithSize(count)
   198  
   199  	if vecs[0].IsScalarNull() || vecs[1].IsScalarNull() || vecs[2].IsScalarNull() {
   200  		return proc.AllocScalarNullVector(returnType), nil
   201  	}
   202  
   203  	// set null row
   204  	nulls.Or(vecs[0].Nsp, vecs[1].Nsp, resultNsp)
   205  	nulls.Or(vecs[2].Nsp, resultNsp, resultNsp)
   206  
   207  	e := proc.Ctx.Value(defines.EngineKey{}).(engine.Engine)
   208  	txn, err := proc.TxnClient.New()
   209  	if err != nil {
   210  		return nil, err
   211  	}
   212  	defer txn.Rollback(proc.Ctx)
   213  	if err := e.New(proc.Ctx, txn); err != nil {
   214  		return nil, err
   215  	}
   216  	defer e.Rollback(proc.Ctx, txn)
   217  
   218  	for i := 0; i < count; i++ {
   219  		col := cols[i]
   220  		if col == "__mo_rowid" {
   221  			return nil, moerr.NewInvalidArg(proc.Ctx, "mo_table_col_min has bad input column", col)
   222  		}
   223  		if tbls[i] == "mo_database" || tbls[i] == "mo_tables" || tbls[i] == "mo_columns" || tbls[i] == "sys_async_task" {
   224  			return nil, moerr.NewInvalidArg(proc.Ctx, "mo_table_col_min has bad input table:", tbls[i])
   225  		}
   226  
   227  		db, err := e.Database(proc.Ctx, dbs[i], txn)
   228  		if err != nil {
   229  			return nil, err
   230  		}
   231  		rel, err := db.Relation(proc.Ctx, tbls[i])
   232  		if err != nil {
   233  			return nil, err
   234  		}
   235  		rel.Ranges(proc.Ctx, nil)
   236  
   237  		tableColumns, err := rel.TableColumns(proc.Ctx)
   238  		if err != nil {
   239  			return nil, err
   240  		}
   241  
   242  		//Get table max and min value from zonemap
   243  		tableVal, _, err := rel.MaxAndMinValues(proc.Ctx)
   244  		if err != nil {
   245  			return nil, err
   246  		}
   247  
   248  		for j := 0; j < len(tableColumns); j++ {
   249  			if tableColumns[j].Name == col {
   250  				resultValues[i] = getVlaueInStr(tableVal[j][0])
   251  				break
   252  			}
   253  		}
   254  	}
   255  	resultVec = vector.NewWithStrings(types.T_varchar.ToType(), resultValues, resultNsp, proc.Mp())
   256  	return resultVec, nil
   257  }
   258  
   259  func getVlaueInStr(value any) string {
   260  	switch v := value.(type) {
   261  	case bool:
   262  		if v {
   263  			return "true"
   264  		} else {
   265  			return "false"
   266  		}
   267  	case uint8:
   268  		return strconv.FormatUint(uint64(v), 10)
   269  	case uint16:
   270  		return strconv.FormatUint(uint64(v), 10)
   271  	case uint32:
   272  		return strconv.FormatUint(uint64(v), 10)
   273  	case uint64:
   274  		return strconv.FormatUint(uint64(v), 10)
   275  	case int8:
   276  		return strconv.FormatInt(int64(v), 10)
   277  	case int16:
   278  		return strconv.FormatInt(int64(v), 10)
   279  	case int32:
   280  		return strconv.FormatInt(int64(v), 10)
   281  	case int64:
   282  		return strconv.FormatInt(int64(v), 10)
   283  	case float32:
   284  		return strconv.FormatFloat(float64(v), 'f', -1, 32)
   285  	case float64:
   286  		return strconv.FormatFloat(v, 'f', -1, 32)
   287  	case string:
   288  		return v
   289  	case []byte:
   290  		return string(v)
   291  	case int:
   292  		return strconv.FormatInt(int64(v), 10)
   293  	case uint:
   294  		return strconv.FormatUint(uint64(v), 10)
   295  	case types.Date:
   296  		return v.String()
   297  	case types.Time:
   298  		return v.String()
   299  	case types.Datetime:
   300  		return v.String()
   301  	case types.Timestamp:
   302  		return v.String()
   303  	case bytejson.ByteJson:
   304  		return v.String()
   305  	case types.Uuid:
   306  		return v.ToString()
   307  	case types.Decimal64:
   308  		return v.String()
   309  	case types.Decimal128:
   310  		return v.String()
   311  	default:
   312  		return ""
   313  	}
   314  }