github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/util/util.go (about) 1 // Copyright 2021 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 util 16 17 import ( 18 "fmt" 19 "go/constant" 20 "strconv" 21 "strings" 22 23 "github.com/matrixorigin/matrixone/pkg/catalog" 24 "github.com/matrixorigin/matrixone/pkg/container/batch" 25 "github.com/matrixorigin/matrixone/pkg/container/vector" 26 "github.com/matrixorigin/matrixone/pkg/defines" 27 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 28 "github.com/matrixorigin/matrixone/pkg/vm/process" 29 ) 30 31 func CopyBatch(bat *batch.Batch, proc *process.Process) (*batch.Batch, error) { 32 rbat := batch.NewWithSize(len(bat.Vecs)) 33 rbat.Attrs = append(rbat.Attrs, bat.Attrs...) 34 for i, srcVec := range bat.Vecs { 35 vec := proc.GetVector(*srcVec.GetType()) 36 if err := vector.GetUnionAllFunction(*srcVec.GetType(), proc.Mp())(vec, srcVec); err != nil { 37 rbat.Clean(proc.Mp()) 38 return nil, err 39 } 40 rbat.SetVector(int32(i), vec) 41 } 42 rbat.SetRowCount(bat.RowCount()) 43 return rbat, nil 44 } 45 46 func SplitTableAndColumn(name string) (string, string) { 47 var schema string 48 49 { // determine if it is a function call 50 i, j := strings.Index(name, "("), strings.Index(name, ")") 51 if i >= 0 && j >= 0 && j > i { 52 return "", name 53 } 54 } 55 xs := strings.Split(name, ".") 56 for i := 0; i < len(xs)-1; i++ { 57 if i > 0 { 58 schema += "." 59 } 60 schema += xs[i] 61 } 62 return schema, xs[len(xs)-1] 63 } 64 65 func TableIsLoggingTable(dbName string, tableName string) bool { 66 if tableName == "statement_info" && dbName == "system" { 67 return true 68 } else if tableName == "metric" && dbName == "system_metrics" { 69 return true 70 } else if tableName == catalog.MO_SQL_STMT_CU && dbName == catalog.MO_SYSTEM_METRICS { 71 return true 72 } 73 return false 74 } 75 76 // TableIsClusterTable check the table type is cluster table 77 func TableIsClusterTable(tableType string) bool { 78 return tableType == catalog.SystemClusterRel 79 } 80 func DbIsSystemDb(dbName string) bool { 81 if dbName == catalog.MO_CATALOG { 82 return true 83 } 84 if dbName == catalog.MO_DATABASE { 85 return true 86 } 87 if dbName == catalog.MO_TABLES { 88 return true 89 } 90 if dbName == catalog.MO_COLUMNS { 91 return true 92 } 93 if dbName == catalog.MOTaskDB { 94 return true 95 } 96 if dbName == "information_schema" { 97 return true 98 } 99 if dbName == "system" { 100 return true 101 } 102 if dbName == "system_metrics" { 103 return true 104 } 105 return false 106 } 107 108 // Build the filter condition AST expression for mo_database, as follows: 109 // account_id = cur_accountId or (account_id = 0 and datname in ('mo_catalog')) 110 func BuildMoDataBaseFilter(curAccountId uint64) tree.Expr { 111 // left is: account_id = cur_accountId 112 left := makeAccountIdEqualAst(curAccountId) 113 114 datnameColName := &tree.UnresolvedName{ 115 NumParts: 1, 116 Parts: tree.NameParts{catalog.SystemDBAttr_Name}, 117 } 118 119 mo_catalogConst := tree.NewNumValWithType(constant.MakeString(catalog.MO_CATALOG), catalog.MO_CATALOG, false, tree.P_char) 120 inValues := tree.NewTuple(tree.Exprs{mo_catalogConst}) 121 // datname in ('mo_catalog') 122 inExpr := tree.NewComparisonExpr(tree.IN, datnameColName, inValues) 123 124 // account_id = 0 125 accountIdEqulZero := makeAccountIdEqualAst(0) 126 // andExpr is:account_id = 0 and datname in ('mo_catalog') 127 andExpr := tree.NewAndExpr(accountIdEqulZero, inExpr) 128 129 // right is:(account_id = 0 and datname in ('mo_catalog')) 130 right := tree.NewParentExpr(andExpr) 131 // return is: account_id = cur_accountId or (account_id = 0 and datname in ('mo_catalog')) 132 return tree.NewOrExpr(left, right) 133 } 134 135 func BuildSysStatementInfoFilter(acctName string) tree.Expr { 136 equalAccount := makeStringEqualAst("account", strings.Split(acctName, ":")[0]) 137 return equalAccount 138 } 139 140 func BuildSysMetricFilter(acctName string) tree.Expr { 141 equalAccount := makeStringEqualAst("account", strings.Split(acctName, ":")[0]) 142 return equalAccount 143 } 144 145 // Build the filter condition AST expression for mo_tables, as follows: 146 // account_id = cur_account_id or (account_id = 0 and (relname in ('mo_tables','mo_database','mo_columns') or relkind = 'cluster')) 147 func BuildMoTablesFilter(curAccountId uint64) tree.Expr { 148 // left is: account_id = cur_accountId 149 left := makeAccountIdEqualAst(curAccountId) 150 151 relnameColName := &tree.UnresolvedName{ 152 NumParts: 1, 153 Parts: tree.NameParts{catalog.SystemRelAttr_Name}, 154 } 155 156 mo_databaseConst := tree.NewNumValWithType(constant.MakeString(catalog.MO_DATABASE), catalog.MO_DATABASE, false, tree.P_char) 157 mo_tablesConst := tree.NewNumValWithType(constant.MakeString(catalog.MO_TABLES), catalog.MO_TABLES, false, tree.P_char) 158 mo_columnsConst := tree.NewNumValWithType(constant.MakeString(catalog.MO_COLUMNS), catalog.MO_COLUMNS, false, tree.P_char) 159 inValues := tree.NewTuple(tree.Exprs{mo_databaseConst, mo_tablesConst, mo_columnsConst}) 160 161 // relname in ('mo_tables','mo_database','mo_columns') 162 inExpr := tree.NewComparisonExpr(tree.IN, relnameColName, inValues) 163 //relkindEqualAst := makeRelkindEqualAst("cluster") 164 165 relkindEqualAst := makeStringEqualAst(catalog.SystemRelAttr_Kind, "cluster") 166 167 // (relname in ('mo_tables','mo_database','mo_columns') or relkind = 'cluster') 168 tempExpr := tree.NewOrExpr(inExpr, relkindEqualAst) 169 tempExpr2 := tree.NewParentExpr(tempExpr) 170 // account_id = 0 171 accountIdEqulZero := makeAccountIdEqualAst(0) 172 // andExpr is: account_id = 0 and (relname in ('mo_tables','mo_database','mo_columns') or relkind = 'cluster') 173 andExpr := tree.NewAndExpr(accountIdEqulZero, tempExpr2) 174 175 // right is: (account_id = 0 and (relname in ('mo_tables','mo_database','mo_columns') or relkind = 'cluster')) 176 right := tree.NewParentExpr(andExpr) 177 178 // return is: account_id = cur_account_id or (account_id = 0 and (relname in ('mo_tables','mo_database','mo_columns') or relkind = 'cluster')); 179 return tree.NewOrExpr(left, right) 180 } 181 182 // Build the filter condition AST expression for mo_columns, as follows: 183 // account_id = current_id or (account_id = 0 and attr_databse in mo_catalog and att_relname not in other tables) 184 func BuildMoColumnsFilter(curAccountId uint64) tree.Expr { 185 // left is: account_id = cur_accountId 186 left := makeAccountIdEqualAst(curAccountId) 187 188 att_relnameColName := &tree.UnresolvedName{ 189 NumParts: 1, 190 Parts: tree.NameParts{catalog.SystemColAttr_RelName}, 191 } 192 193 att_dblnameColName := &tree.UnresolvedName{ 194 NumParts: 1, 195 Parts: tree.NameParts{catalog.SystemColAttr_DBName}, 196 } 197 198 mo_catalogConst := tree.NewNumValWithType(constant.MakeString(catalog.MO_CATALOG), catalog.MO_CATALOG, false, tree.P_char) 199 inValues := tree.NewTuple(tree.Exprs{mo_catalogConst}) 200 // datname in ('mo_catalog') 201 inExpr := tree.NewComparisonExpr(tree.IN, att_dblnameColName, inValues) 202 203 mo_userConst := tree.NewNumValWithType(constant.MakeString("mo_user"), "mo_user", false, tree.P_char) 204 mo_roleConst := tree.NewNumValWithType(constant.MakeString("mo_role"), "mo_role", false, tree.P_char) 205 mo_user_grantConst := tree.NewNumValWithType(constant.MakeString("mo_user_grant"), "mo_user_grant", false, tree.P_char) 206 mo_role_grantConst := tree.NewNumValWithType(constant.MakeString("mo_role_grant"), "mo_role_grant", false, tree.P_char) 207 mo_role_privsConst := tree.NewNumValWithType(constant.MakeString("mo_role_privs"), "mo_role_privs", false, tree.P_char) 208 mo_user_defined_functionConst := tree.NewNumValWithType(constant.MakeString("mo_user_defined_function"), "mo_user_defined_function", false, tree.P_char) 209 mo_mysql_compatibility_modeConst := tree.NewNumValWithType(constant.MakeString("mo_mysql_compatibility_mode"), "mo_mysql_compatibility_mode", false, tree.P_char) 210 mo_indexes := tree.NewNumValWithType(constant.MakeString("mo_indexes"), "mo_indexes", false, tree.P_char) 211 mo_table_partitions := tree.NewNumValWithType(constant.MakeString("mo_table_partitions"), "mo_table_partitions", false, tree.P_char) 212 mo_pubs := tree.NewNumValWithType(constant.MakeString("mo_pubs"), "mo_pubs", false, tree.P_char) 213 mo_stored_procedure := tree.NewNumValWithType(constant.MakeString("mo_stored_procedure"), "mo_stored_procedure", false, tree.P_char) 214 mo_stages := tree.NewNumValWithType(constant.MakeString("mo_stages"), "mo_stages", false, tree.P_char) 215 mo_snapshots := tree.NewNumValWithType(constant.MakeString("mo_snapshots"), "mo_snapshots", false, tree.P_char) 216 217 mo_locks := tree.NewNumValWithType(constant.MakeString("mo_locks"), "mo_locks", false, tree.P_char) 218 mo_variables := tree.NewNumValWithType(constant.MakeString("mo_variables"), "mo_variables", false, tree.P_char) 219 mo_transactions := tree.NewNumValWithType(constant.MakeString("mo_transactions"), "mo_transactions", false, tree.P_char) 220 mo_cache := tree.NewNumValWithType(constant.MakeString("mo_cache"), "mo_cache", false, tree.P_char) 221 mo_sessions := tree.NewNumValWithType(constant.MakeString("mo_sessions"), "mo_sessions", false, tree.P_char) 222 mo_configurations := tree.NewNumValWithType(constant.MakeString("mo_configurations"), "mo_configurations", false, tree.P_char) 223 224 notInValues := tree.NewTuple(tree.Exprs{ 225 mo_userConst, 226 mo_roleConst, 227 mo_user_grantConst, 228 mo_role_grantConst, 229 mo_role_privsConst, 230 mo_user_defined_functionConst, 231 mo_mysql_compatibility_modeConst, 232 mo_indexes, 233 mo_table_partitions, 234 mo_pubs, 235 mo_stored_procedure, 236 mo_stages, 237 mo_snapshots, 238 mo_locks, 239 mo_variables, 240 mo_transactions, 241 mo_cache, 242 mo_sessions, 243 mo_configurations, 244 }) 245 246 notInexpr := tree.NewComparisonExpr(tree.NOT_IN, att_relnameColName, notInValues) 247 248 // account_id = 0 249 accountIdEqulZero := makeAccountIdEqualAst(0) 250 // andExpr is:account_id = 0 and datname in ('mo_catalog') 251 andExpr := tree.NewAndExpr(accountIdEqulZero, inExpr) 252 andExpr = tree.NewAndExpr(andExpr, notInexpr) 253 254 // right is:(account_id = 0 and datname in ('mo_catalog')) 255 right := tree.NewParentExpr(andExpr) 256 // return is: account_id = cur_accountId or (account_id = 0 and datname in ('mo_catalog')) 257 return tree.NewOrExpr(left, right) 258 } 259 260 // build equal ast expr: colName = 'xxx' 261 func makeStringEqualAst(lColName, rValue string) tree.Expr { 262 relkindColName := &tree.UnresolvedName{ 263 NumParts: 1, 264 Parts: tree.NameParts{lColName}, 265 } 266 clusterConst := tree.NewNumValWithType(constant.MakeString(rValue), rValue, false, tree.P_char) 267 return tree.NewComparisonExpr(tree.EQUAL, relkindColName, clusterConst) 268 } 269 270 // build ast expr: account_id = cur_accountId 271 func makeAccountIdEqualAst(curAccountId uint64) tree.Expr { 272 accountIdColName := &tree.UnresolvedName{ 273 NumParts: 1, 274 Parts: tree.NameParts{"account_id"}, 275 } 276 curAccountIdConst := tree.NewNumValWithType(constant.MakeUint64(uint64(curAccountId)), strconv.Itoa(int(curAccountId)), false, tree.P_int64) 277 return tree.NewComparisonExpr(tree.EQUAL, accountIdColName, curAccountIdConst) 278 } 279 280 var ( 281 clusterTableAttributeName = "account_id" 282 clusterTableAttributeType = &tree.T{InternalType: tree.InternalType{ 283 Family: tree.IntFamily, 284 Width: 32, 285 Oid: uint32(defines.MYSQL_TYPE_LONG), 286 Unsigned: true, 287 }} 288 ) 289 290 func GetClusterTableAttributeName() string { 291 return clusterTableAttributeName 292 } 293 294 func GetClusterTableAttributeType() *tree.T { 295 return clusterTableAttributeType 296 } 297 298 func IsClusterTableAttribute(name string) bool { 299 return name == clusterTableAttributeName 300 } 301 302 const partitionDelimiter = "%!%" 303 304 // IsValidNameForPartitionTable 305 // the name forms the partition table does not have the partitionDelimiter 306 func IsValidNameForPartitionTable(name string) bool { 307 return !strings.Contains(name, partitionDelimiter) 308 } 309 310 // MakeNameOfPartitionTable 311 // !!!NOTE!!! With assumption: the partition name and the table name does not have partitionDelimiter. 312 // partition table name format : %!%partition_name%!%table_name 313 func MakeNameOfPartitionTable(partitionName, tableName string) (bool, string) { 314 if strings.Contains(partitionName, partitionDelimiter) || 315 strings.Contains(tableName, partitionDelimiter) { 316 return false, "" 317 } 318 if len(partitionName) == 0 || 319 len(tableName) == 0 { 320 return false, "" 321 } 322 return true, fmt.Sprintf("%s%s%s%s", partitionDelimiter, partitionName, partitionDelimiter, tableName) 323 } 324 325 // SplitNameOfPartitionTable splits the partition table name into partition name and origin table name 326 func SplitNameOfPartitionTable(name string) (bool, string, string) { 327 if !strings.HasPrefix(name, partitionDelimiter) { 328 return false, "", "" 329 } 330 partNameIdx := len(partitionDelimiter) 331 if partNameIdx >= len(name) { 332 return false, "", "" 333 } 334 left := name[partNameIdx:] 335 secondIdx := strings.Index(left, partitionDelimiter) 336 if secondIdx < 0 { 337 return false, "", "" 338 } 339 340 if secondIdx == 0 { 341 return false, "", "" 342 } 343 partName := left[:secondIdx] 344 345 tableNameIdx := secondIdx + len(partitionDelimiter) 346 if tableNameIdx >= len(left) { 347 return false, "", "" 348 } 349 tableName := left[tableNameIdx:] 350 return true, partName, tableName 351 }