Skip to content
Snippets Groups Projects
Unverified Commit 93cda2a0 authored by ou yuanning's avatar ou yuanning Committed by GitHub
Browse files

Plan2 refactor (#2926)


* [Plan2] Initial commit of plan2 refactor

* update base_binder, finish bindExpr

* fix bind case expr bug

* improve date function

* Refactor plan2

* Add support for join tables

* Fix uninitialized map

* Fix bugs in addBinding

* update base binder

* Fix case sensitivity

* Suppress panics

* fix data_add/sub bug

* add wangjian's code back and change wangjian's code ut to use new binder for test

* Add the *dummy* subquery support

* fix typo

* add limit binder

* use BuildPlan to test,  fix ctetable is not init bug

* change bind subquery to fix build tpch error

* add distinct node, rename selectBinder to projectionBinder

* init support create plan

* change method arg

* fix bug and support agg

* distinct support

* cte support, tpch support, wangjian's ut pass

* fix ci error code

* fix deepcopy bug

* add distinct agg function support

* Don't let agglist bind to groupby

* add headings in Query and remove all ColName/TableName from new plan2

* fix projection pos bug

* fix join position bug

* add reset aggList's position

* Improve map performance

* fix result columns bug

* fix join position bug

* fix order by number  bug

* fix count(distinct 12) bug

* improve: return having bind error message in time

* support "select *" to throw "No table used" error

* fix case bug

* improve to check if function is agg/fun

* Fix join type

* push down onlist

* fix pushdown onlist bug

* fix bug: incorrect function name

* fix datetime/varchar +/- interval bug

* remove duplicate function

Co-authored-by: default avatarbRong Njam <longran1989@gmail.com>
Co-authored-by: default avatarnnsgmsone <nnsmgsone@outlook.com>
parent ee1450f8
No related branches found
No related tags found
No related merge requests found
Showing
with 6161 additions and 3489 deletions
......@@ -9,6 +9,7 @@ import (
proto "github.com/gogo/protobuf/proto"
io "io"
math "math"
math_bits "math/bits"
)
// Reference imports to suppress errors if they are not otherwise used.
......@@ -20,9 +21,9 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// DN dn node metadata
// DN dn shard metadata
type DN struct {
// ID the id of the DN. The ID is not modified after the DN is created.
ID uint64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
......@@ -57,7 +58,7 @@ func (m *DN) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_DN.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalTo(b)
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
......@@ -147,7 +148,7 @@ var fileDescriptor_56d9f74966f40d04 = []byte{
func (m *DN) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
......@@ -155,57 +156,68 @@ func (m *DN) Marshal() (dAtA []byte, err error) {
}
func (m *DN) MarshalTo(dAtA []byte) (int, error) {
var i int
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *DN) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.ID != 0 {
dAtA[i] = 0x8
i++
i = encodeVarintMetadata(dAtA, i, uint64(m.ID))
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if m.ReplicaID != 0 {
dAtA[i] = 0x10
i++
i = encodeVarintMetadata(dAtA, i, uint64(m.ReplicaID))
if len(m.Address) > 0 {
i -= len(m.Address)
copy(dAtA[i:], m.Address)
i = encodeVarintMetadata(dAtA, i, uint64(len(m.Address)))
i--
dAtA[i] = 0x32
}
if m.LogShardID != 0 {
dAtA[i] = 0x18
i++
i = encodeVarintMetadata(dAtA, i, uint64(m.LogShardID))
if len(m.End) > 0 {
i -= len(m.End)
copy(dAtA[i:], m.End)
i = encodeVarintMetadata(dAtA, i, uint64(len(m.End)))
i--
dAtA[i] = 0x2a
}
if len(m.Start) > 0 {
dAtA[i] = 0x22
i++
i -= len(m.Start)
copy(dAtA[i:], m.Start)
i = encodeVarintMetadata(dAtA, i, uint64(len(m.Start)))
i += copy(dAtA[i:], m.Start)
i--
dAtA[i] = 0x22
}
if len(m.End) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintMetadata(dAtA, i, uint64(len(m.End)))
i += copy(dAtA[i:], m.End)
if m.LogShardID != 0 {
i = encodeVarintMetadata(dAtA, i, uint64(m.LogShardID))
i--
dAtA[i] = 0x18
}
if len(m.Address) > 0 {
dAtA[i] = 0x32
i++
i = encodeVarintMetadata(dAtA, i, uint64(len(m.Address)))
i += copy(dAtA[i:], m.Address)
if m.ReplicaID != 0 {
i = encodeVarintMetadata(dAtA, i, uint64(m.ReplicaID))
i--
dAtA[i] = 0x10
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
if m.ID != 0 {
i = encodeVarintMetadata(dAtA, i, uint64(m.ID))
i--
dAtA[i] = 0x8
}
return i, nil
return len(dAtA) - i, nil
}
func encodeVarintMetadata(dAtA []byte, offset int, v uint64) int {
offset -= sovMetadata(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return offset + 1
return base
}
func (m *DN) Size() (n int) {
if m == nil {
......@@ -241,14 +253,7 @@ func (m *DN) Size() (n int) {
}
func sovMetadata(x uint64) (n int) {
for {
n++
x >>= 7
if x == 0 {
break
}
}
return n
return (math_bits.Len64(x|1) + 6) / 7
}
func sozMetadata(x uint64) (n int) {
return sovMetadata(uint64((x << 1) ^ uint64((int64(x) >> 63))))
......@@ -445,10 +450,7 @@ func (m *DN) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthMetadata
}
if (iNdEx + skippy) < 0 {
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthMetadata
}
if (iNdEx + skippy) > l {
......@@ -467,6 +469,7 @@ func (m *DN) Unmarshal(dAtA []byte) error {
func skipMetadata(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
......@@ -498,10 +501,8 @@ func skipMetadata(dAtA []byte) (n int, err error) {
break
}
}
return iNdEx, nil
case 1:
iNdEx += 8
return iNdEx, nil
case 2:
var length int
for shift := uint(0); ; shift += 7 {
......@@ -522,55 +523,30 @@ func skipMetadata(dAtA []byte) (n int, err error) {
return 0, ErrInvalidLengthMetadata
}
iNdEx += length
if iNdEx < 0 {
return 0, ErrInvalidLengthMetadata
}
return iNdEx, nil
case 3:
for {
var innerWire uint64
var start int = iNdEx
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowMetadata
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
innerWire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
innerWireType := int(innerWire & 0x7)
if innerWireType == 4 {
break
}
next, err := skipMetadata(dAtA[start:])
if err != nil {
return 0, err
}
iNdEx = start + next
if iNdEx < 0 {
return 0, ErrInvalidLengthMetadata
}
}
return iNdEx, nil
depth++
case 4:
return iNdEx, nil
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupMetadata
}
depth--
case 5:
iNdEx += 4
return iNdEx, nil
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthMetadata
}
if depth == 0 {
return iNdEx, nil
}
}
panic("unreachable")
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthMetadata = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowMetadata = fmt.Errorf("proto: integer overflow")
ErrInvalidLengthMetadata = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowMetadata = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupMetadata = fmt.Errorf("proto: unexpected end of group")
)
This diff is collapsed.
This diff is collapsed.
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"fmt"
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewBindContext(builder *QueryBuilder, parent *BindContext) *BindContext {
bc := &BindContext{
groupByAst: make(map[string]int32),
aggregateByAst: make(map[string]int32),
projectByExpr: make(map[string]int32),
aliasMap: make(map[string]int32),
bindingByTag: make(map[int32]*Binding),
bindingByTable: make(map[string]*Binding),
bindingByCol: make(map[string]*Binding),
cteTables: make(map[string]*plan.TableDef),
parent: parent,
}
return bc
}
func (bc *BindContext) mergeContexts(left, right *BindContext) error {
left.parent = bc
right.parent = bc
bc.leftChild = left
bc.rightChild = right
for _, binding := range left.bindings {
bc.bindings = append(bc.bindings, binding)
bc.bindingByTag[binding.tag] = binding
bc.bindingByTable[binding.table] = binding
}
for _, binding := range right.bindings {
if _, ok := bc.bindingByTable[binding.table]; ok {
return errors.New(errno.DuplicateTable, fmt.Sprintf("table name %q specified more than once", binding.table))
}
bc.bindings = append(bc.bindings, binding)
bc.bindingByTag[binding.tag] = binding
bc.bindingByTable[binding.table] = binding
}
for col, binding := range left.bindingByCol {
bc.bindingByCol[col] = binding
}
for col, binding := range right.bindingByCol {
if _, ok := bc.bindingByCol[col]; ok {
bc.bindingByCol[col] = nil
} else {
bc.bindingByCol[col] = binding
}
}
bc.bindingTree = &BindingTreeNode{
left: left.bindingTree,
right: right.bindingTree,
}
return nil
}
func (bc *BindContext) addUsingCol(col string, typ plan.Node_JoinFlag, left, right *BindContext) (*plan.Expr, error) {
leftBinding, ok := left.bindingByCol[col]
if !ok {
return nil, errors.New(errno.InvalidColumnReference, fmt.Sprintf("column %q specified in USING clause does not exist in left table", col))
}
if leftBinding == nil {
return nil, errors.New(errno.InvalidColumnReference, fmt.Sprintf("common column name %q appears more than once in left table", col))
}
rightBinding, ok := right.bindingByCol[col]
if !ok {
return nil, errors.New(errno.InvalidColumnReference, fmt.Sprintf("column %q specified in USING clause does not exist in right table", col))
}
if rightBinding == nil {
return nil, errors.New(errno.InvalidColumnReference, fmt.Sprintf("common column name %q appears more than once in right table", col))
}
if typ != plan.Node_RIGHT {
bc.bindingByCol[col] = leftBinding
bc.bindingTree.using = append(bc.bindingTree.using, NameTuple{
table: leftBinding.table,
col: col,
})
} else {
bc.bindingByCol[col] = rightBinding
bc.bindingTree.using = append(bc.bindingTree.using, NameTuple{
table: rightBinding.table,
col: col,
})
}
leftPos := leftBinding.colIdByName[col]
rightPos := rightBinding.colIdByName[col]
expr, err := bc.binder.(*TableBinder).bindFuncExprImplByPlanExpr("=", []*plan.Expr{
{
Typ: leftBinding.types[leftPos],
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: leftBinding.tag,
ColPos: leftPos,
},
},
},
{
Typ: rightBinding.types[rightPos],
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: rightBinding.tag,
ColPos: rightPos,
},
},
},
})
return expr, err
}
func (bc *BindContext) unfoldStar(table string) ([]tree.SelectExpr, []string, error) {
if len(table) == 0 {
// unfold *
var exprs []tree.SelectExpr
var names []string
bc.doUnfoldStar(bc.bindingTree, make(map[string]any), &exprs, &names)
return exprs, names, nil
} else {
// unfold tbl.*
binding, ok := bc.bindingByTable[table]
if !ok {
return nil, nil, errors.New(errno.UndefinedTable, fmt.Sprintf("missing FROM-clause entry for table %q", table))
}
exprs := make([]tree.SelectExpr, len(binding.cols))
names := make([]string, len(binding.cols))
for i, col := range binding.cols {
expr, _ := tree.NewUnresolvedName(table, col)
exprs[i] = tree.SelectExpr{Expr: expr}
names[i] = col
}
return exprs, names, nil
}
}
func (bc *BindContext) doUnfoldStar(root *BindingTreeNode, visitedUsingCols map[string]any, exprs *[]tree.SelectExpr, names *[]string) {
if root == nil {
return
}
if root.binding != nil {
for _, col := range root.binding.cols {
if _, ok := visitedUsingCols[col]; !ok {
expr, _ := tree.NewUnresolvedName(root.binding.table, col)
*exprs = append(*exprs, tree.SelectExpr{Expr: expr})
*names = append(*names, col)
}
}
return
}
var handledUsingCols []string
for _, using := range root.using {
if _, ok := visitedUsingCols[using.col]; !ok {
handledUsingCols = append(handledUsingCols, using.col)
visitedUsingCols[using.col] = nil
expr, _ := tree.NewUnresolvedName(using.table, using.col)
*exprs = append(*exprs, tree.SelectExpr{Expr: expr})
*names = append(*names, using.col)
}
}
bc.doUnfoldStar(root.left, visitedUsingCols, exprs, names)
bc.doUnfoldStar(root.right, visitedUsingCols, exprs, names)
for _, col := range handledUsingCols {
delete(visitedUsingCols, col)
}
}
func (bc *BindContext) qualifyColumnNames(astExpr tree.Expr) error {
switch exprImpl := astExpr.(type) {
case *tree.ParenExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.OrExpr:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.Right)
case *tree.NotExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.AndExpr:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.Right)
case *tree.UnaryExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.BinaryExpr:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.Right)
case *tree.ComparisonExpr:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.Right)
case *tree.FuncExpr:
for _, child := range exprImpl.Exprs {
err := bc.qualifyColumnNames(child)
if err != nil {
return err
}
}
case *tree.RangeCond:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
err = bc.qualifyColumnNames(exprImpl.From)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.To)
case *tree.UnresolvedName:
if !exprImpl.Star && exprImpl.NumParts == 1 {
col := exprImpl.Parts[0]
if binding, ok := bc.bindingByCol[col]; ok {
if binding != nil {
exprImpl.Parts[1] = binding.table
} else {
return errors.New(errno.AmbiguousColumn, fmt.Sprintf("column reference %q is ambiguous", col))
}
}
}
case *tree.CastExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.IsNullExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.IsNotNullExpr:
return bc.qualifyColumnNames(exprImpl.Expr)
case *tree.Tuple:
for _, child := range exprImpl.Exprs {
err := bc.qualifyColumnNames(child)
if err != nil {
return err
}
}
case *tree.CaseExpr:
err := bc.qualifyColumnNames(exprImpl.Expr)
if err != nil {
return err
}
for _, when := range exprImpl.Whens {
err = bc.qualifyColumnNames(when.Cond)
if err != nil {
return err
}
err = bc.qualifyColumnNames(when.Val)
if err != nil {
return err
}
}
return bc.qualifyColumnNames(exprImpl.Else)
case *tree.XorExpr:
err := bc.qualifyColumnNames(exprImpl.Left)
if err != nil {
return err
}
return bc.qualifyColumnNames(exprImpl.Right)
}
return nil
}
func (bc *BindContext) qualifyColumnNamesAndExpandAlias(astExpr tree.Expr, selectList tree.SelectExprs) (tree.Expr, error) {
var err error
switch exprImpl := astExpr.(type) {
case *tree.ParenExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.OrExpr:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.Right, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Right, selectList)
case *tree.NotExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.AndExpr:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.Right, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Right, selectList)
case *tree.UnaryExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.BinaryExpr:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.Right, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Right, selectList)
case *tree.ComparisonExpr:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.Right, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Right, selectList)
case *tree.FuncExpr:
for i := range exprImpl.Exprs {
exprImpl.Exprs[i], err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Exprs[i], selectList)
if err != nil {
return nil, err
}
}
case *tree.RangeCond:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.From, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.From, selectList)
if err != nil {
return nil, err
}
exprImpl.To, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.To, selectList)
case *tree.UnresolvedName:
if !exprImpl.Star && exprImpl.NumParts == 1 {
col := exprImpl.Parts[0]
if colPos, ok := bc.aliasMap[col]; ok {
astExpr = selectList[colPos].Expr
} else if binding, ok := bc.bindingByCol[col]; ok {
if binding != nil {
exprImpl.Parts[1] = binding.table
} else {
return nil, errors.New(errno.AmbiguousColumn, fmt.Sprintf("column reference %q is ambiguous", col))
}
}
}
case *tree.CastExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.IsNullExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.IsNotNullExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
case *tree.Tuple:
for i := range exprImpl.Exprs {
exprImpl.Exprs[i], err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Exprs[i], selectList)
if err != nil {
return nil, err
}
}
case *tree.CaseExpr:
exprImpl.Expr, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Expr, selectList)
if err != nil {
return nil, err
}
for _, when := range exprImpl.Whens {
when.Cond, err = bc.qualifyColumnNamesAndExpandAlias(when.Cond, selectList)
if err != nil {
return nil, err
}
when.Val, err = bc.qualifyColumnNamesAndExpandAlias(when.Val, selectList)
if err != nil {
return nil, err
}
}
exprImpl.Else, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Else, selectList)
case *tree.XorExpr:
exprImpl.Left, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Left, selectList)
if err != nil {
return nil, err
}
exprImpl.Right, err = bc.qualifyColumnNamesAndExpandAlias(exprImpl.Right, selectList)
}
return astExpr, err
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/pb/plan"
)
func (b *Binding) FindColumn(col string) int32 {
if id, ok := b.colIdByName[col]; ok {
return id
}
return NotFound
}
func NewBinding(tag, nodeId int32, table string, cols []string, types []*plan.Type) *Binding {
binding := &Binding{
tag: tag,
nodeId: nodeId,
table: table,
cols: cols,
types: types,
refCnts: make([]uint, len(cols)),
}
binding.colIdByName = make(map[string]int32)
for i, col := range cols {
if _, ok := binding.colIdByName[col]; ok {
binding.colIdByName[col] = AmbiguousName
} else {
binding.colIdByName[col] = int32(i)
}
}
return binding
}
......@@ -24,23 +24,40 @@ import (
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func BuildPlan(ctx CompilerContext, stmt tree.Statement) (*Plan, error) {
runBuildSelect := func(stmt *tree.Select) (*Plan, error) {
query, binderCtx := newQueryAndSelectCtx(plan.Query_SELECT)
nodeId, err := buildSelect(stmt, ctx, query, binderCtx)
query.Steps = append(query.Steps, nodeId)
return &Plan{
Plan: &plan.Plan_Query{
Query: query,
},
}, err
func runBuildSelectByBinder(stmtType plan.Query_StatementType, ctx CompilerContext, stmt *tree.Select) (*Plan, error) {
// query, binderCtx := newQueryAndSelectCtx(stmtType)
// nodeId, err := buildSelect(stmt, ctx, query, binderCtx)
// query.Steps = append(query.Steps, nodeId)
// return &Plan{
// Plan: &plan.Plan_Query{
// Query: query,
// },
// }, err
builder := NewQueryBuilder(stmtType, ctx)
bindCtx := NewBindContext(builder, nil)
rootId, err := builder.buildSelect(stmt, bindCtx, true)
builder.qry.Steps = append(builder.qry.Steps, rootId)
if err != nil {
return nil, err
}
query, err := builder.createQuery()
if err != nil {
return nil, err
}
return &Plan{
Plan: &plan.Plan_Query{
Query: query,
},
}, err
}
func BuildPlan(ctx CompilerContext, stmt tree.Statement) (*Plan, error) {
switch stmt := stmt.(type) {
case *tree.Select:
return runBuildSelect(stmt)
return runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt)
case *tree.ParenSelect:
return runBuildSelect(stmt.Select)
return runBuildSelectByBinder(plan.Query_SELECT, ctx, stmt.Select)
case *tree.Insert:
return buildInsert(stmt, ctx)
case *tree.Update:
......@@ -97,10 +114,19 @@ func GetResultColumnsFromPlan(p *Plan) []*ColDef {
getResultColumnsByProjectionlist := func(query *Query) []*ColDef {
lastNode := query.Nodes[len(query.Nodes)-1]
columns := make([]*ColDef, len(lastNode.ProjectList))
for idx, expr := range lastNode.ProjectList {
columns[idx] = &ColDef{
Name: expr.ColName,
Typ: expr.Typ,
if len(query.Headings) > 0 { // use refactor plan2
for idx, expr := range lastNode.ProjectList {
columns[idx] = &ColDef{
Name: query.Headings[idx],
Typ: expr.Typ,
}
}
} else {
for idx, expr := range lastNode.ProjectList {
columns[idx] = &ColDef{
Name: expr.ColName,
Typ: expr.Typ,
}
}
}
return columns
......
......@@ -16,6 +16,7 @@ package plan2
import (
"fmt"
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
......@@ -64,14 +65,12 @@ func buildDelete(stmt *tree.Delete, ctx CompilerContext) (*Plan, error) {
var useKey *ColDef = nil
var useProjectExprs tree.SelectExprs = nil
priKeys := ctx.GetPrimaryKeyDef(objRef.SchemaName, tableDef.Name)
if priKeys != nil {
for _, key := range priKeys {
e, _ := tree.NewUnresolvedName(key.Name)
if isDuplicated(e, &projectExprs) {
useProjectExprs = append(useProjectExprs, tree.SelectExpr{Expr: e})
useKey = key
break
}
for _, key := range priKeys {
e, _ := tree.NewUnresolvedName(key.Name)
if isDuplicated(e, &projectExprs) {
useProjectExprs = append(useProjectExprs, tree.SelectExpr{Expr: e})
useKey = key
break
}
}
if useKey == nil {
......@@ -125,34 +124,34 @@ func buildDelete(stmt *tree.Delete, ctx CompilerContext) (*Plan, error) {
}, nil
}
func checkColumns(projectExprs tree.SelectExprs, tableDef *TableDef) ([]string, error) {
var cols []string = nil
for _, e := range projectExprs {
col, _ := e.Expr.(*tree.UnresolvedName)
colName := col.Parts[0]
cols = append(cols, colName)
if !inTableDef(colName, tableDef) {
return nil, errors.New(errno.SyntaxErrororAccessRuleViolation, fmt.Sprintf("column '%v' not in table '%v'", colName, tableDef.Name))
}
}
return cols, nil
}
// func checkColumns(projectExprs tree.SelectExprs, tableDef *TableDef) ([]string, error) {
// var cols []string = nil
// for _, e := range projectExprs {
// col, _ := e.Expr.(*tree.UnresolvedName)
// colName := col.Parts[0]
// cols = append(cols, colName)
// if !inTableDef(colName, tableDef) {
// return nil, errors.New(errno.SyntaxErrororAccessRuleViolation, fmt.Sprintf("column '%v' not in table '%v'", colName, tableDef.Name))
// }
// }
// return cols, nil
// }
func inTableDef(colName string, tableDef *TableDef) bool {
for _, def := range tableDef.Cols {
if colName == def.Name {
return true
}
}
return false
}
// func inTableDef(colName string, tableDef *TableDef) bool {
// for _, def := range tableDef.Cols {
// if colName == def.Name {
// return true
// }
// }
// return false
// }
func buildStarProjection() tree.SelectExprs {
expr := tree.SelectExpr{
Expr: tree.UnqualifiedStar{},
}
return tree.SelectExprs{expr}
}
// func buildStarProjection() tree.SelectExprs {
// expr := tree.SelectExpr{
// Expr: tree.UnqualifiedStar{},
// }
// return tree.SelectExprs{expr}
// }
func buildProjectionFromExpr(expr tree.Expr, selectExprs *tree.SelectExprs) error {
switch e := expr.(type) {
......
......@@ -41,7 +41,7 @@ func TestExpr_1(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -82,7 +82,7 @@ func TestExpr_2(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -123,7 +123,7 @@ func TestExpr_3(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -165,7 +165,7 @@ func TestExpr_4(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -193,7 +193,7 @@ func TestExpr_5(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -221,7 +221,7 @@ func TestExpr_6(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -249,7 +249,7 @@ func TestExpr_7(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -277,7 +277,7 @@ func TestExpr_8(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -308,7 +308,7 @@ func TestExpr_9(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -336,7 +336,7 @@ func TestExpr_A(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......@@ -364,7 +364,7 @@ func TestExpr_B(t *testing.T) {
if !ok {
t.Fatalf("%+v", errors.New("return type is not right"))
}
expr := query.Query.Nodes[0].ProjectList[0]
expr := query.Query.Nodes[1].ProjectList[0]
exprF, ok := expr.Expr.(*plan.Expr_F)
if !ok {
t.Fatalf("%+v", errors.New("the parse expr type is not right"))
......
This diff is collapsed.
......@@ -344,7 +344,7 @@ func buildUnresolvedName(query *Query, node *Node, colName string, tableName str
// Search from parent queries
corrRef := &plan.CorrColRef{
NodeId: -1,
RelPos: -1,
ColPos: -1,
}
corrExpr := &Expr{
......@@ -356,10 +356,10 @@ func buildUnresolvedName(query *Query, node *Node, colName string, tableName str
for _, parentId := range binderCtx.subqueryParentIds {
for i, col := range query.Nodes[parentId].ProjectList {
if matchName(col) {
if corrRef.NodeId != -1 {
if corrRef.RelPos != -1 {
return nil, errors.New(errno.InvalidColumnReference, fmt.Sprintf("column '%v' in the field list is ambiguous", colName))
}
corrRef.NodeId = parentId
corrRef.RelPos = parentId
corrRef.ColPos = int32(i)
corrExpr.Typ = col.Typ
......@@ -1131,6 +1131,8 @@ func DeepCopyExpr(expr *Expr) *Expr {
Corr: &plan.CorrColRef{
NodeId: item.Corr.GetNodeId(),
ColPos: item.Corr.GetColPos(),
RelPos: item.Corr.GetRelPos(),
Depth: item.Corr.GetDepth(),
},
}
case *plan.Expr_T:
......
......@@ -14,6 +14,8 @@
package function
import "github.com/matrixorigin/matrixone/pkg/pb/plan"
const (
Distinct = 0x8000000000000000
DistinctMask = 0x7FFFFFFFFFFFFFFF
......@@ -299,3 +301,12 @@ var functionIdRegister = map[string]int32{
"cos": COS,
"cot": COT,
}
func GetFunctionIsWinfunByName(name string) bool {
fid, err := fromNameToFunctionId(name)
if err != nil {
return false
}
fs := functionRegister[fid]
return len(fs) > 0 && fs[0].Flag == plan.Function_WIN
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewGroupBinder(builder *QueryBuilder, ctx *BindContext) *GroupBinder {
b := &GroupBinder{}
b.builder = builder
b.ctx = ctx
b.impl = b
return b
}
func (b *GroupBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
expr, err := b.baseBindExpr(astExpr, depth)
if err != nil {
return nil, err
}
if _, ok := expr.Expr.(*plan.Expr_Corr); ok {
return nil, errors.New(errno.GroupingError, "correlated columns in GROUP BY clause not yet supported")
}
if isRoot {
astStr := tree.String(astExpr, dialect.MYSQL)
if _, ok := b.ctx.groupByAst[astStr]; ok {
return nil, nil
}
b.ctx.groupByAst[astStr] = int32(len(b.ctx.groups))
b.ctx.groups = append(b.ctx.groups, expr)
}
return expr, err
}
func (b *GroupBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
return b.baseBindColRef(astExpr, depth)
}
func (b *GroupBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.GroupingError, "GROUP BY clause cannot contain aggregate functions!")
}
func (b *GroupBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "GROUP BY clause cannot contain window functions!")
}
func (b *GroupBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return nil, errors.New(errno.GroupingError, "subquery in GROUP BY clause not yet supported")
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"fmt"
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
"github.com/matrixorigin/matrixone/pkg/sql/plan2/function"
)
func NewHavingBinder(builder *QueryBuilder, ctx *BindContext) *HavingBinder {
b := &HavingBinder{
insideAgg: false,
}
b.builder = builder
b.ctx = ctx
b.impl = b
return b
}
func (b *HavingBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
astStr := tree.String(astExpr, dialect.MYSQL)
if !b.insideAgg {
if colPos, ok := b.ctx.groupByAst[astStr]; ok {
return &plan.Expr{
Typ: b.ctx.groups[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.groupTag,
ColPos: colPos,
},
},
}, nil
}
}
if colPos, ok := b.ctx.aggregateByAst[astStr]; ok {
if !b.insideAgg {
return &plan.Expr{
Typ: b.ctx.aggregates[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.aggregateTag,
ColPos: colPos,
},
},
}, nil
} else {
return nil, errors.New(errno.GroupingError, "aggregate function calls cannot be nested")
}
}
return b.baseBindExpr(astExpr, depth)
}
func (b *HavingBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
if b.insideAgg {
return b.baseBindColRef(astExpr, depth)
} else {
return nil, errors.New(errno.GroupingError, fmt.Sprintf("column %q must appear in the GROUP BY clause or be used in an aggregate function", tree.String(astExpr, dialect.MYSQL)))
}
}
func (b *HavingBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
if b.insideAgg {
return nil, errors.New(errno.GroupingError, "aggregate function calls cannot be nested")
}
b.insideAgg = true
expr, err := b.bindFuncExprImplByAstExpr(funcName, astExpr.Exprs, depth)
if err != nil {
return nil, err
}
if astExpr.Type == tree.FUNC_TYPE_DISTINCT {
expr.GetF().Func.Obj = int64(int64(uint64(expr.GetF().Func.Obj) | function.Distinct))
}
b.insideAgg = false
colPos := int32(len(b.ctx.aggregates))
astStr := tree.String(astExpr, dialect.MYSQL)
b.ctx.aggregateByAst[astStr] = colPos
b.ctx.aggregates = append(b.ctx.aggregates, expr)
return &plan.Expr{
Typ: expr.Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.aggregateTag,
ColPos: colPos,
},
},
}, nil
}
func (b *HavingBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
if b.insideAgg {
return nil, errors.New(errno.GroupingError, "aggregate function calls cannot contain window function calls")
} else {
return nil, errors.New(errno.WindowingError, "window functions not allowed here")
}
}
func (b *HavingBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return b.baseBindSubquery(astExpr)
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewLimitBinder() *LimitBinder {
return &LimitBinder{}
}
func (b *LimitBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
switch astExpr.(type) {
case *tree.VarExpr, *tree.UnqualifiedStar:
// need check other expr
return nil, errors.New(errno.SyntaxErrororAccessRuleViolation, "unsupported expr in limit clause")
}
return b.baseBindExpr(astExpr, depth)
}
func (b *LimitBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.InvalidColumnReference, "column name not allowed in limit clause")
}
func (b *LimitBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.GroupingError, "aggregate functions not allowed in limit clause")
}
func (b *LimitBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "window functions not allowed in limit clause")
}
func (b *LimitBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "subquery functions not allowed in limit clause")
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"fmt"
"go/constant"
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewOrderBinder(projectionBinder *ProjectionBinder, selectList tree.SelectExprs) *OrderBinder {
return &OrderBinder{
ProjectionBinder: projectionBinder,
selectList: selectList,
}
}
func (b *OrderBinder) BindExpr(astExpr tree.Expr) (*plan.Expr, error) {
if colRef, ok := astExpr.(*tree.UnresolvedName); ok && colRef.NumParts == 1 {
if colPos, ok := b.ctx.aliasMap[colRef.Parts[0]]; ok {
return &plan.Expr{
Typ: b.ctx.projects[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.projectTag,
ColPos: colPos,
},
},
}, nil
}
}
if numVal, ok := astExpr.(*tree.NumVal); ok {
switch numVal.Value.Kind() {
case constant.Int:
colPos, _ := constant.Int64Val(numVal.Value)
if numVal.Negative() {
colPos = -colPos
}
if colPos < 1 || int(colPos) > len(b.ctx.projects) {
return nil, errors.New(errno.SyntaxError, fmt.Sprintf("ORDER BY position %v is not in select list", colPos))
}
colPos = colPos - 1
return &plan.Expr{
Typ: b.ctx.projects[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.projectTag,
ColPos: int32(colPos),
},
},
}, nil
default:
return nil, errors.New(errno.SyntaxError, "non-integer constant in ORDER BY")
}
}
astExpr, err := b.ctx.qualifyColumnNamesAndExpandAlias(astExpr, b.selectList)
if err != nil {
return nil, err
}
expr, err := b.ProjectionBinder.BindExpr(astExpr, 0, true)
if err != nil {
return nil, err
}
var colPos int32
var ok bool
exprStr := expr.String()
if colPos, ok = b.ctx.projectByExpr[exprStr]; !ok {
colPos = int32(len(b.ctx.projects))
b.ctx.projectByExpr[exprStr] = colPos
b.ctx.projects = append(b.ctx.projects, expr)
}
expr = &plan.Expr{
Typ: b.ctx.projects[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.projectTag,
ColPos: colPos,
},
},
}
return expr, err
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewProjectionBinder(builder *QueryBuilder, ctx *BindContext, havingBinder *HavingBinder) *ProjectionBinder {
b := &ProjectionBinder{
havingBinder: havingBinder,
}
b.builder = builder
b.ctx = ctx
b.impl = b
return b
}
func (b *ProjectionBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
astStr := tree.String(astExpr, dialect.MYSQL)
if colPos, ok := b.ctx.groupByAst[astStr]; ok {
return &plan.Expr{
Typ: b.ctx.groups[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.groupTag,
ColPos: colPos,
},
},
}, nil
}
if colPos, ok := b.ctx.aggregateByAst[astStr]; ok {
return &plan.Expr{
Typ: b.ctx.aggregates[colPos].Typ,
Expr: &plan.Expr_Col{
Col: &plan.ColRef{
RelPos: b.ctx.aggregateTag,
ColPos: colPos,
},
},
}, nil
}
return b.baseBindExpr(astExpr, depth)
}
func (b *ProjectionBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
return b.baseBindColRef(astExpr, depth)
}
func (b *ProjectionBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return b.havingBinder.BindAggFunc(funcName, astExpr, depth)
}
func (b *ProjectionBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "window functions not yet supported")
}
func (b *ProjectionBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return b.baseBindSubquery(astExpr)
}
This diff is collapsed.
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewTableBinder(builder *QueryBuilder, ctx *BindContext) *TableBinder {
b := &TableBinder{}
b.builder = builder
b.ctx = ctx
b.impl = b
return b
}
func (b *TableBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
return b.baseBindExpr(astExpr, depth)
}
func (b *TableBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
return b.baseBindColRef(astExpr, depth)
}
func (b *TableBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.GroupingError, "aggregate functions not allowed here")
}
func (b *TableBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "window functions not allowed here")
}
func (b *TableBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "subquery in JOIN condition not yet supported")
}
......@@ -15,6 +15,8 @@
package plan2
import (
"math"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
......@@ -87,3 +89,135 @@ type BinderContext struct {
// because the ProjectNode(after JoinNode) had coalesced the using cols
usingCols map[string]string
}
///////////////////////////////
// Data structures for refactor
///////////////////////////////
type QueryBuilder struct {
qry *plan.Query
compCtx CompilerContext
ctxByNode []*BindContext
tagsByNode [][]int32
nextTag int32
}
type BindContext struct {
binder Binder
cteTables map[string]*plan.TableDef
groupTag int32
aggregateTag int32
projectTag int32
groups []*plan.Expr
aggregates []*plan.Expr
projects []*plan.Expr
results []*plan.Expr
headings []string
groupByAst map[string]int32
aggregateByAst map[string]int32
projectByExpr map[string]int32
aliasMap map[string]int32
bindings []*Binding
bindingByTag map[int32]*Binding //rel_pos
bindingByTable map[string]*Binding
bindingByCol map[string]*Binding
// for join tables
bindingTree *BindingTreeNode
corrCols []*plan.CorrColRef
parent *BindContext
leftChild *BindContext
rightChild *BindContext
}
type NameTuple struct {
table string
col string
}
type BindingTreeNode struct {
using []NameTuple
binding *Binding
left *BindingTreeNode
right *BindingTreeNode
}
type Binder interface {
BindExpr(tree.Expr, int32, bool) (*plan.Expr, error)
BindColRef(*tree.UnresolvedName, int32) (*plan.Expr, error)
BindAggFunc(string, *tree.FuncExpr, int32) (*plan.Expr, error)
BindWinFunc(string, *tree.FuncExpr, int32) (*plan.Expr, error)
BindSubquery(*tree.Subquery) (*plan.Expr, error)
}
type baseBinder struct {
builder *QueryBuilder
ctx *BindContext
impl Binder
boundCols []string
}
type TableBinder struct {
baseBinder
}
type WhereBinder struct {
baseBinder
}
type GroupBinder struct {
baseBinder
}
type HavingBinder struct {
baseBinder
insideAgg bool
}
type ProjectionBinder struct {
baseBinder
havingBinder *HavingBinder
}
type OrderBinder struct {
*ProjectionBinder
selectList tree.SelectExprs
}
type LimitBinder struct {
baseBinder
}
var _ Binder = (*TableBinder)(nil)
var _ Binder = (*WhereBinder)(nil)
var _ Binder = (*GroupBinder)(nil)
var _ Binder = (*HavingBinder)(nil)
var _ Binder = (*ProjectionBinder)(nil)
var _ Binder = (*LimitBinder)(nil)
const (
NotFound int32 = math.MaxInt32
AmbiguousName int32 = math.MinInt32
)
type Binding struct {
tag int32
nodeId int32
table string
cols []string
types []*plan.Type
refCnts []uint
colIdByName map[string]int32
}
// Copyright 2022 Matrix Origin
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package plan2
import (
"github.com/matrixorigin/matrixone/pkg/errno"
"github.com/matrixorigin/matrixone/pkg/pb/plan"
"github.com/matrixorigin/matrixone/pkg/sql/errors"
"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
)
func NewWhereBinder(builder *QueryBuilder, ctx *BindContext) *WhereBinder {
b := &WhereBinder{}
b.builder = builder
b.ctx = ctx
b.impl = b
return b
}
func (b *WhereBinder) BindExpr(astExpr tree.Expr, depth int32, isRoot bool) (*plan.Expr, error) {
return b.baseBindExpr(astExpr, depth)
}
func (b *WhereBinder) BindColRef(astExpr *tree.UnresolvedName, depth int32) (*plan.Expr, error) {
return b.baseBindColRef(astExpr, depth)
}
func (b *WhereBinder) BindAggFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.GroupingError, "aggregate functions not allowed here")
}
func (b *WhereBinder) BindWinFunc(funcName string, astExpr *tree.FuncExpr, depth int32) (*plan.Expr, error) {
return nil, errors.New(errno.WindowingError, "window functions not allowed here")
}
func (b *WhereBinder) BindSubquery(astExpr *tree.Subquery) (*plan.Expr, error) {
return b.baseBindSubquery(astExpr)
}
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment