package compute
import (
"fmt"
"github.com/daviszhen/plan/pkg/common"
"github.com/daviszhen/plan/pkg/storage"
)
type LOT int
const (
LOT_Project LOT = 0
LOT_Filter LOT = 1
LOT_Scan LOT = 2
LOT_JOIN LOT = 3
LOT_AggGroup LOT = 4
LOT_Order LOT = 5
LOT_Limit LOT = 6
LOT_CreateSchema LOT = 7
LOT_CreateTable LOT = 8
LOT_Insert LOT = 9
)
func (lt LOT) String() string {
switch lt {
case LOT_Project:
return "Project"
case LOT_Filter:
return "Filter"
case LOT_Scan:
return "Scan"
case LOT_JOIN:
return "Join"
case LOT_AggGroup:
return "Aggregate"
case LOT_Order:
return "Order"
case LOT_Limit:
return "Limit"
case LOT_CreateSchema:
return "CreateSchema"
case LOT_CreateTable:
return "CreateTable"
case LOT_Insert:
return "Insert"
default:
panic(fmt.Sprintf("usp %d", lt))
}
}
type LOT_JoinType int
const (
LOT_JoinTypeCross LOT_JoinType = iota
LOT_JoinTypeLeft
LOT_JoinTypeInner
LOT_JoinTypeSEMI
LOT_JoinTypeANTI
LOT_JoinTypeSINGLE
LOT_JoinTypeMARK
LOT_JoinTypeAntiMARK
LOT_JoinTypeOUTER
)
func (lojt LOT_JoinType) String() string {
switch lojt {
case LOT_JoinTypeCross:
return "cross"
case LOT_JoinTypeLeft:
return "left"
case LOT_JoinTypeInner:
return "inner"
case LOT_JoinTypeMARK:
return "mark"
case LOT_JoinTypeAntiMARK:
return "anti_mark"
case LOT_JoinTypeSEMI:
return "semi"
case LOT_JoinTypeANTI:
return "anti semi"
default:
panic(fmt.Sprintf("usp %d", lojt))
}
}
type ScanType int
const (
ScanTypeTable ScanType = 0
ScanTypeValuesList ScanType = 1
ScanTypeCopyFrom ScanType = 2
)
func (st ScanType) String() string {
switch st {
case ScanTypeTable:
return "scan table"
case ScanTypeValuesList:
return "scan values list"
case ScanTypeCopyFrom:
return "scan copy from"
default:
panic("usp")
}
}
type ScanOption struct {
Kind string
Opt string
}
type ScanInfo struct {
ReturnedTypes []common.LType
Names []string
ColumnIds []int
FilePath string
Opts []*ScanOption
Format string
}
type LogicalOperator struct {
Typ LOT
Children []*LogicalOperator
Projects []*Expr
Index uint64
Index2 uint64
Database string
Table string
Alias string
Columns []string
Filters []*Expr
BelongCtx *BindContext
JoinTyp LOT_JoinType
OnConds []*Expr
Aggs []*Expr
GroupBys []*Expr
OrderBys []*Expr
Limit *Expr
Offset *Expr
Stats *Stats
hasEstimatedCard bool
estimatedCard uint64
estimatedProps *EstimatedProperties
Outputs []*Expr
IfNotExists bool
ColDefs []*storage.ColumnDefinition
Constraints []*storage.Constraint
TableEnt *storage.CatalogEntry
TableIndex int
ExpectedTypes []common.LType
IsValuesList bool
ScanTyp ScanType
Types []common.LType
Names []string
Values [][]*Expr
ColName2Idx map[string]int
ColumnIndexMap []int
ScanInfo *ScanInfo
Counts ColumnBindCountMap `json:"-"`
ColRefToPos ColumnBindPosMap `json:"-"`
}
func (lo *LogicalOperator) EstimatedCard(txn *storage.Txn) uint64 {
if lo.Typ == LOT_Scan {
return lo.TableEnt.GetStats2(0).Count()
}
if lo.hasEstimatedCard {
return lo.estimatedCard
}
maxCard := uint64(0)
for _, child := range lo.Children {
childCard := child.EstimatedCard(txn)
maxCard = max(maxCard, childCard)
}
lo.hasEstimatedCard = true
lo.estimatedCard = maxCard
return lo.estimatedCard
}
func (lo *LogicalOperator) String() string {
ret, err := ExplainLogicalPlan(lo)
if err != nil {
panic(err)
}
return ret
}
func pushFilter(node *LogicalOperator, expr *Expr) *LogicalOperator {
if node.Typ != LOT_Filter {
filter := &LogicalOperator{Typ: LOT_Filter, Children: []*LogicalOperator{node}}
node = filter
}
node.Filters = append(node.Filters, expr)
return node
}