mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
* delete implementation with test coverage
* optimize IN expressions; stop linter complaining
* fixed some uncovered query cases
* skip test in DAX for now
(cherry picked from commit 021219935f)
122 lines
3.9 KiB
Go
122 lines
3.9 KiB
Go
// Copyright 2021 Molecula Corp. All rights reserved.
|
|
|
|
package planner
|
|
|
|
import (
|
|
"context"
|
|
|
|
pilosa "github.com/featurebasedb/featurebase/v3"
|
|
"github.com/featurebasedb/featurebase/v3/logger"
|
|
"github.com/featurebasedb/featurebase/v3/sql3"
|
|
"github.com/featurebasedb/featurebase/v3/sql3/parser"
|
|
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
|
|
)
|
|
|
|
// ExecutionPlanner compiles SQL text into a query plan
|
|
type ExecutionPlanner struct {
|
|
executor pilosa.Executor
|
|
schemaAPI pilosa.SchemaAPI
|
|
systemAPI pilosa.SystemAPI
|
|
systemLayerAPI pilosa.SystemLayerAPI
|
|
importer pilosa.Importer
|
|
logger logger.Logger
|
|
sql string
|
|
}
|
|
|
|
func NewExecutionPlanner(executor pilosa.Executor, schemaAPI pilosa.SchemaAPI, systemAPI pilosa.SystemAPI, systemLayerAPI pilosa.SystemLayerAPI, importer pilosa.Importer, logger logger.Logger, sql string) *ExecutionPlanner {
|
|
return &ExecutionPlanner{
|
|
executor: executor,
|
|
schemaAPI: newSystemTableDefintionsWrapper(schemaAPI),
|
|
systemAPI: systemAPI,
|
|
systemLayerAPI: systemLayerAPI,
|
|
importer: importer,
|
|
logger: logger,
|
|
sql: sql,
|
|
}
|
|
}
|
|
|
|
// CompilePlan takes an AST (parser.Statement) and compiles into a query plan returning the root
|
|
// PlanOperator
|
|
// The act of compiling includes an analysis step that does semantic analysis of the AST, this includes
|
|
// type checking, and sometimes AST rewriting. The compile phase uses the type-checked and rewritten AST
|
|
// to produce a query plan.
|
|
func (p *ExecutionPlanner) CompilePlan(ctx context.Context, stmt parser.Statement) (types.PlanOperator, error) {
|
|
// call analyze first
|
|
err := p.analyzePlan(stmt)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var rootOperator types.PlanOperator
|
|
switch stmt := stmt.(type) {
|
|
case *parser.SelectStatement:
|
|
rootOperator, err = p.compileSelectStatement(stmt, false)
|
|
case *parser.ShowTablesStatement:
|
|
rootOperator, err = p.compileShowTablesStatement(stmt)
|
|
case *parser.ShowColumnsStatement:
|
|
rootOperator, err = p.compileShowColumnsStatement(stmt)
|
|
case *parser.ShowCreateTableStatement:
|
|
rootOperator, err = p.compileShowCreateTableStatement(stmt)
|
|
case *parser.CreateTableStatement:
|
|
rootOperator, err = p.compileCreateTableStatement(stmt)
|
|
case *parser.AlterTableStatement:
|
|
rootOperator, err = p.compileAlterTableStatement(stmt)
|
|
case *parser.DropTableStatement:
|
|
rootOperator, err = p.compileDropTableStatement(stmt)
|
|
case *parser.InsertStatement:
|
|
rootOperator, err = p.compileInsertStatement(stmt)
|
|
case *parser.BulkInsertStatement:
|
|
rootOperator, err = p.compileBulkInsertStatement(stmt)
|
|
case *parser.DeleteStatement:
|
|
rootOperator, err = p.compileDeleteStatement(stmt)
|
|
default:
|
|
return nil, sql3.NewErrInternalf("cannot plan statement: %T", stmt)
|
|
}
|
|
// Optimize the plan.
|
|
if err == nil {
|
|
rootOperator, err = p.optimizePlan(ctx, rootOperator)
|
|
}
|
|
return rootOperator, err
|
|
}
|
|
|
|
func (p *ExecutionPlanner) analyzePlan(stmt parser.Statement) error {
|
|
switch stmt := stmt.(type) {
|
|
case *parser.SelectStatement:
|
|
_, err := p.analyzeSelectStatement(stmt)
|
|
return err
|
|
case *parser.ShowTablesStatement:
|
|
return nil
|
|
case *parser.ShowColumnsStatement:
|
|
return nil
|
|
case *parser.ShowCreateTableStatement:
|
|
return nil
|
|
case *parser.CreateTableStatement:
|
|
return p.analyzeCreateTableStatement(stmt)
|
|
case *parser.AlterTableStatement:
|
|
return p.analyzeAlterTableStatement(stmt)
|
|
case *parser.DropTableStatement:
|
|
return nil
|
|
case *parser.InsertStatement:
|
|
return p.analyzeInsertStatement(stmt)
|
|
case *parser.BulkInsertStatement:
|
|
return p.analyzeBulkInsertStatement(stmt)
|
|
case *parser.DeleteStatement:
|
|
return p.analyzeDeleteStatement(stmt)
|
|
default:
|
|
return sql3.NewErrInternalf("cannot analyze statement: %T", stmt)
|
|
}
|
|
}
|
|
|
|
type accessType byte
|
|
|
|
const (
|
|
accessTypeReadData accessType = iota
|
|
accessTypeWriteData
|
|
accessTypeCreateObject
|
|
accessTypeAlterObject
|
|
accessTypeDropObject
|
|
)
|
|
|
|
func (p *ExecutionPlanner) checkAccess(ctx context.Context, objectName string, _ accessType) error {
|
|
return nil
|
|
}
|