github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/compile/sql_executor_context.go (about) 1 // Copyright 2023 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 compile 16 17 import ( 18 "context" 19 "strconv" 20 "sync" 21 22 "github.com/matrixorigin/matrixone/pkg/catalog" 23 "github.com/matrixorigin/matrixone/pkg/common/moerr" 24 "github.com/matrixorigin/matrixone/pkg/defines" 25 planpb "github.com/matrixorigin/matrixone/pkg/pb/plan" 26 pb "github.com/matrixorigin/matrixone/pkg/pb/statsinfo" 27 "github.com/matrixorigin/matrixone/pkg/sql/parsers/tree" 28 "github.com/matrixorigin/matrixone/pkg/sql/plan" 29 "github.com/matrixorigin/matrixone/pkg/sql/plan/function" 30 "github.com/matrixorigin/matrixone/pkg/sql/util" 31 "github.com/matrixorigin/matrixone/pkg/vm/engine" 32 "github.com/matrixorigin/matrixone/pkg/vm/process" 33 ) 34 35 var _ plan.CompilerContext = new(compilerContext) 36 37 type compilerContext struct { 38 ctx context.Context 39 defaultDB string 40 engine engine.Engine 41 proc *process.Process 42 statsCache *plan.StatsCache 43 44 buildAlterView bool 45 dbOfView, nameOfView string 46 sql string 47 mu sync.Mutex 48 } 49 50 func (c *compilerContext) GetViews() []string { 51 return nil 52 } 53 54 func (c *compilerContext) SetViews(views []string) {} 55 56 func (c *compilerContext) GetSnapshot() *plan.Snapshot { 57 return nil 58 } 59 60 func (c *compilerContext) SetSnapshot(snapshot *plan.Snapshot) { 61 } 62 63 func (c *compilerContext) ReplacePlan(execPlan *planpb.Execute) (*planpb.Plan, tree.Statement, error) { 64 //TODO implement me 65 panic("implement me") 66 } 67 68 func (c *compilerContext) CheckSubscriptionValid(subName, accName string, pubName string) error { 69 panic("not supported in internal sql executor") 70 } 71 72 func (c *compilerContext) ResolveSubscriptionTableById(tableId uint64, pubmeta *plan.SubscriptionMeta) (*plan.ObjectRef, *plan.TableDef) { 73 panic("not supported in internal sql executor") 74 } 75 76 func (c *compilerContext) IsPublishing(dbName string) (bool, error) { 77 panic("not supported in internal sql executor") 78 } 79 80 func (c *compilerContext) ResolveSnapshotWithSnapshotName(snapshotName string) (*plan.Snapshot, error) { 81 panic("not supported in internal sql executor") 82 } 83 84 func (c *compilerContext) CheckTimeStampValid(ts int64) (bool, error) { 85 panic("not supported in internal sql executor") 86 } 87 88 func (c *compilerContext) SetQueryingSubscription(meta *plan.SubscriptionMeta) { 89 panic("not supported in internal sql executor") 90 } 91 92 func (c *compilerContext) GetQueryingSubscription() *plan.SubscriptionMeta { 93 return nil 94 } 95 96 func newCompilerContext( 97 ctx context.Context, 98 defaultDB string, 99 eng engine.Engine, 100 proc *process.Process) *compilerContext { 101 return &compilerContext{ 102 ctx: ctx, 103 defaultDB: defaultDB, 104 engine: eng, 105 proc: proc, 106 } 107 } 108 109 func (c *compilerContext) ResolveUdf(name string, ast []*plan.Expr) (*function.Udf, error) { 110 panic("not supported in internal sql executor") 111 } 112 113 func (c *compilerContext) ResolveAccountIds(accountNames []string) ([]uint32, error) { 114 panic("not supported in internal sql executor") 115 } 116 117 func (c *compilerContext) Stats(obj *plan.ObjectRef, snapshot plan.Snapshot) (*pb.StatsInfo, error) { 118 ctx, t, err := c.getRelation(obj.GetSchemaName(), obj.GetObjName(), snapshot) 119 if err != nil { 120 return nil, err 121 } 122 return t.Stats(ctx, true) 123 } 124 125 func (c *compilerContext) GetStatsCache() *plan.StatsCache { 126 if c.statsCache == nil { 127 c.statsCache = plan.NewStatsCache() 128 } 129 return c.statsCache 130 } 131 132 func (c *compilerContext) GetSubscriptionMeta(dbName string, snapshot plan.Snapshot) (*plan.SubscriptionMeta, error) { 133 return nil, nil 134 } 135 136 func (c *compilerContext) GetProcess() *process.Process { 137 return c.proc 138 } 139 140 func (c *compilerContext) GetQueryResultMeta(uuid string) ([]*plan.ColDef, string, error) { 141 panic("not supported in internal sql executor") 142 } 143 144 func (c *compilerContext) DatabaseExists(name string, snapshot plan.Snapshot) bool { 145 ctx := c.GetContext() 146 txnOpt := c.proc.TxnOperator 147 148 if plan.IsSnapshotValid(&snapshot) && snapshot.TS.Less(c.proc.TxnOperator.Txn().SnapshotTS) { 149 txnOpt = c.proc.TxnOperator.CloneSnapshotOp(*snapshot.TS) 150 151 if snapshot.Tenant != nil { 152 ctx = context.WithValue(ctx, defines.TenantIDKey{}, snapshot.Tenant.TenantID) 153 } 154 } 155 156 _, err := c.engine.Database( 157 ctx, 158 name, 159 txnOpt, 160 ) 161 return err == nil 162 } 163 164 func (c *compilerContext) GetDatabaseId(dbName string, snapshot plan.Snapshot) (uint64, error) { 165 ctx := c.GetContext() 166 txnOpt := c.proc.TxnOperator 167 168 if plan.IsSnapshotValid(&snapshot) && snapshot.TS.Less(c.proc.TxnOperator.Txn().SnapshotTS) { 169 txnOpt = c.proc.TxnOperator.CloneSnapshotOp(*snapshot.TS) 170 171 if snapshot.Tenant != nil { 172 ctx = context.WithValue(ctx, defines.TenantIDKey{}, snapshot.Tenant.TenantID) 173 } 174 } 175 176 database, err := c.engine.Database(ctx, dbName, txnOpt) 177 178 if err != nil { 179 return 0, err 180 } 181 databaseId, err := strconv.ParseUint(database.GetDatabaseId(ctx), 10, 64) 182 if err != nil { 183 return 0, moerr.NewInternalError(ctx, "The databaseid of '%s' is not a valid number", dbName) 184 } 185 return databaseId, nil 186 } 187 188 func (c *compilerContext) DefaultDatabase() string { 189 return c.defaultDB 190 } 191 192 func (c *compilerContext) GetPrimaryKeyDef( 193 dbName string, 194 tableName string, 195 snapshot plan.Snapshot) []*plan.ColDef { 196 dbName, err := c.ensureDatabaseIsNotEmpty(dbName) 197 if err != nil { 198 return nil 199 } 200 ctx, relation, err := c.getRelation(dbName, tableName, snapshot) 201 if err != nil { 202 return nil 203 } 204 205 priKeys, err := relation.GetPrimaryKeys(ctx) 206 if err != nil { 207 return nil 208 } 209 if len(priKeys) == 0 { 210 return nil 211 } 212 213 priDefs := make([]*plan.ColDef, 0, len(priKeys)) 214 for _, key := range priKeys { 215 priDefs = append(priDefs, &plan.ColDef{ 216 Name: key.Name, 217 Typ: plan.Type{ 218 Id: int32(key.Type.Oid), 219 Width: key.Type.Width, 220 Scale: key.Type.Scale, 221 }, 222 Primary: key.Primary, 223 }) 224 } 225 return priDefs 226 } 227 228 func (c *compilerContext) GetRootSql() string { 229 return c.sql 230 } 231 232 func (c *compilerContext) SetRootSql(sql string) { 233 c.mu.Lock() 234 defer c.mu.Unlock() 235 c.sql = sql 236 } 237 238 func (c *compilerContext) GetUserName() string { 239 return "root" 240 } 241 242 func (c *compilerContext) GetAccountId() (uint32, error) { 243 return defines.GetAccountId(c.ctx) 244 } 245 246 func (c *compilerContext) GetContext() context.Context { 247 return c.ctx 248 } 249 250 func (c *compilerContext) ResolveById(tableId uint64, snapshot plan.Snapshot) (objRef *plan.ObjectRef, tableDef *plan.TableDef) { 251 ctx := c.GetContext() 252 txnOpt := c.proc.TxnOperator 253 254 if plan.IsSnapshotValid(&snapshot) && snapshot.TS.Less(c.proc.TxnOperator.Txn().SnapshotTS) { 255 txnOpt = c.proc.TxnOperator.CloneSnapshotOp(*snapshot.TS) 256 257 if snapshot.Tenant != nil { 258 ctx = context.WithValue(ctx, defines.TenantIDKey{}, snapshot.Tenant.TenantID) 259 } 260 } 261 262 dbName, tableName, _ := c.engine.GetNameById(ctx, txnOpt, tableId) 263 if dbName == "" || tableName == "" { 264 return nil, nil 265 } 266 return c.Resolve(dbName, tableName, snapshot) 267 } 268 269 func (c *compilerContext) Resolve(dbName string, tableName string, snapshot plan.Snapshot) (*plan.ObjectRef, *plan.TableDef) { 270 dbName, err := c.ensureDatabaseIsNotEmpty(dbName) 271 if err != nil { 272 return nil, nil 273 } 274 275 ctx, table, err := c.getRelation(dbName, tableName, snapshot) 276 if err != nil { 277 return nil, nil 278 } 279 return c.getTableDef(ctx, table, dbName, tableName) 280 } 281 282 func (c *compilerContext) ResolveVariable(varName string, isSystemVar bool, isGlobalVar bool) (interface{}, error) { 283 return nil, nil 284 } 285 286 func (c *compilerContext) SetBuildingAlterView(yesOrNo bool, dbName, viewName string) { 287 c.mu.Lock() 288 defer c.mu.Unlock() 289 c.buildAlterView = yesOrNo 290 c.dbOfView = dbName 291 c.nameOfView = viewName 292 } 293 294 func (c *compilerContext) GetBuildingAlterView() (bool, string, string) { 295 c.mu.Lock() 296 defer c.mu.Unlock() 297 return c.buildAlterView, c.dbOfView, c.nameOfView 298 } 299 300 func (c *compilerContext) ensureDatabaseIsNotEmpty(dbName string) (string, error) { 301 if len(dbName) == 0 { 302 dbName = c.DefaultDatabase() 303 } 304 if len(dbName) == 0 { 305 return "", moerr.NewNoDB(c.GetContext()) 306 } 307 return dbName, nil 308 } 309 310 func (c *compilerContext) getRelation( 311 dbName string, 312 tableName string, 313 snapshot plan.Snapshot) (context.Context, engine.Relation, error) { 314 dbName, err := c.ensureDatabaseIsNotEmpty(dbName) 315 if err != nil { 316 return nil, nil, err 317 } 318 319 ctx := c.GetContext() 320 txnOpt := c.proc.TxnOperator 321 322 if plan.IsSnapshotValid(&snapshot) && snapshot.TS.Less(c.proc.TxnOperator.Txn().SnapshotTS) { 323 txnOpt = c.proc.TxnOperator.CloneSnapshotOp(*snapshot.TS) 324 325 if snapshot.Tenant != nil { 326 ctx = context.WithValue(ctx, defines.TenantIDKey{}, snapshot.Tenant.TenantID) 327 } 328 } 329 330 db, err := c.engine.Database(ctx, dbName, txnOpt) 331 if err != nil { 332 return nil, nil, err 333 } 334 335 table, err := db.Relation(ctx, tableName, nil) 336 if err != nil { 337 return nil, nil, err 338 } 339 return ctx, table, nil 340 } 341 342 func (c *compilerContext) getTableDef( 343 ctx context.Context, 344 table engine.Relation, 345 dbName, tableName string) (*plan.ObjectRef, *plan.TableDef) { 346 tableId := table.GetTableID(ctx) 347 engineDefs, err := table.TableDefs(ctx) 348 if err != nil { 349 return nil, nil 350 } 351 352 var clusterByDef *plan.ClusterByDef 353 var cols []*plan.ColDef 354 var schemaVersion uint32 355 var defs []*plan.TableDefType 356 var properties []*plan.Property 357 var TableType, Createsql string 358 var partitionInfo *plan.PartitionByDef 359 var viewSql *plan.ViewDef 360 var foreignKeys []*plan.ForeignKeyDef 361 var primarykey *plan.PrimaryKeyDef 362 var indexes []*plan.IndexDef 363 var refChildTbls []uint64 364 var subscriptionName string 365 366 for _, def := range engineDefs { 367 if attr, ok := def.(*engine.AttributeDef); ok { 368 col := &plan.ColDef{ 369 ColId: attr.Attr.ID, 370 Name: attr.Attr.Name, 371 Typ: plan.Type{ 372 Id: int32(attr.Attr.Type.Oid), 373 Width: attr.Attr.Type.Width, 374 Scale: attr.Attr.Type.Scale, 375 AutoIncr: attr.Attr.AutoIncrement, 376 Table: tableName, 377 NotNullable: attr.Attr.Default != nil && !attr.Attr.Default.NullAbility, 378 Enumvalues: attr.Attr.EnumVlaues, 379 }, 380 Primary: attr.Attr.Primary, 381 Default: attr.Attr.Default, 382 OnUpdate: attr.Attr.OnUpdate, 383 Comment: attr.Attr.Comment, 384 ClusterBy: attr.Attr.ClusterBy, 385 Hidden: attr.Attr.IsHidden, 386 Seqnum: uint32(attr.Attr.Seqnum), 387 } 388 // Is it a composite primary key 389 //if attr.Attr.Name == catalog.CPrimaryKeyColName { 390 // continue 391 //} 392 if attr.Attr.ClusterBy { 393 clusterByDef = &plan.ClusterByDef{ 394 Name: attr.Attr.Name, 395 } 396 //if util.JudgeIsCompositeClusterByColumn(attr.Attr.Name) { 397 // continue 398 //} 399 } 400 cols = append(cols, col) 401 } else if pro, ok := def.(*engine.PropertiesDef); ok { 402 for _, p := range pro.Properties { 403 switch p.Key { 404 case catalog.SystemRelAttr_Kind: 405 TableType = p.Value 406 case catalog.SystemRelAttr_CreateSQL: 407 Createsql = p.Value 408 default: 409 } 410 properties = append(properties, &plan.Property{ 411 Key: p.Key, 412 Value: p.Value, 413 }) 414 } 415 } else if viewDef, ok := def.(*engine.ViewDef); ok { 416 viewSql = &plan.ViewDef{ 417 View: viewDef.View, 418 } 419 } else if c, ok := def.(*engine.ConstraintDef); ok { 420 for _, ct := range c.Cts { 421 switch k := ct.(type) { 422 case *engine.IndexDef: 423 indexes = k.Indexes 424 case *engine.ForeignKeyDef: 425 foreignKeys = k.Fkeys 426 case *engine.RefChildTableDef: 427 refChildTbls = k.Tables 428 case *engine.PrimaryKeyDef: 429 primarykey = k.Pkey 430 } 431 } 432 } else if commnetDef, ok := def.(*engine.CommentDef); ok { 433 properties = append(properties, &plan.Property{ 434 Key: catalog.SystemRelAttr_Comment, 435 Value: commnetDef.Comment, 436 }) 437 } else if partitionDef, ok := def.(*engine.PartitionDef); ok { 438 if partitionDef.Partitioned > 0 { 439 p := &plan.PartitionByDef{} 440 err = p.UnMarshalPartitionInfo(([]byte)(partitionDef.Partition)) 441 if err != nil { 442 return nil, nil 443 } 444 partitionInfo = p 445 } 446 } else if v, ok := def.(*engine.VersionDef); ok { 447 schemaVersion = v.Version 448 } 449 } 450 if len(properties) > 0 { 451 defs = append(defs, &plan.TableDefType{ 452 Def: &plan.TableDef_DefType_Properties{ 453 Properties: &plan.PropertiesDef{ 454 Properties: properties, 455 }, 456 }, 457 }) 458 } 459 460 if primarykey != nil && primarykey.PkeyColName == catalog.CPrimaryKeyColName { 461 //cols = append(cols, plan.MakeHiddenColDefByName(catalog.CPrimaryKeyColName)) 462 primarykey.CompPkeyCol = plan.GetColDefFromTable(cols, catalog.CPrimaryKeyColName) 463 } 464 if clusterByDef != nil && util.JudgeIsCompositeClusterByColumn(clusterByDef.Name) { 465 //cols = append(cols, plan.MakeHiddenColDefByName(clusterByDef.Name)) 466 clusterByDef.CompCbkeyCol = plan.GetColDefFromTable(cols, clusterByDef.Name) 467 } 468 rowIdCol := plan.MakeRowIdColDef() 469 cols = append(cols, rowIdCol) 470 471 //convert 472 obj := &plan.ObjectRef{ 473 SchemaName: dbName, 474 ObjName: tableName, 475 SubscriptionName: subscriptionName, 476 } 477 478 tableDef := &plan.TableDef{ 479 TblId: tableId, 480 Name: tableName, 481 Cols: cols, 482 Defs: defs, 483 TableType: TableType, 484 Createsql: Createsql, 485 Pkey: primarykey, 486 ViewSql: viewSql, 487 Partition: partitionInfo, 488 Fkeys: foreignKeys, 489 RefChildTbls: refChildTbls, 490 ClusterBy: clusterByDef, 491 Indexes: indexes, 492 Version: schemaVersion, 493 DbName: dbName, 494 } 495 return obj, tableDef 496 }