github.com/matrixorigin/matrixone@v1.2.0/pkg/sql/plan/partition_hash.go (about)

     1  // Copyright 2022 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 plan
    16  
    17  import (
    18  	"context"
    19  	"github.com/matrixorigin/matrixone/pkg/container/types"
    20  	"github.com/matrixorigin/matrixone/pkg/pb/plan"
    21  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/dialect"
    22  	"github.com/matrixorigin/matrixone/pkg/sql/parsers/tree"
    23  )
    24  
    25  // hashPartitionBuilder processes Hash Partition
    26  type hashPartitionBuilder struct {
    27  }
    28  
    29  // buildHashPartition handle Hash Partitioning
    30  func (hpb *hashPartitionBuilder) build(ctx context.Context, partitionBinder *PartitionBinder, stmt *tree.CreateTable, tableDef *TableDef) error {
    31  	partitionSyntaxDef := stmt.PartitionOption
    32  	partitionCount, err := getValidPartitionCount(ctx, false, partitionSyntaxDef)
    33  	if err != nil {
    34  		return err
    35  	}
    36  	partitionType := partitionSyntaxDef.PartBy.PType.(*tree.HashType)
    37  	partitionDef := &plan.PartitionByDef{
    38  		PartitionNum:   partitionCount,
    39  		IsSubPartition: partitionSyntaxDef.PartBy.IsSubPartition,
    40  	}
    41  
    42  	partitionDef.Type = plan.PartitionType_HASH
    43  	if partitionType.Linear {
    44  		partitionDef.Type = plan.PartitionType_LINEAR_HASH
    45  	}
    46  
    47  	// build partition expr
    48  	err = buildPartitionExpr(ctx, tableDef, partitionBinder, partitionDef, partitionType.Expr)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	err = hpb.buildPartitionDefs(ctx, partitionBinder, partitionDef, partitionSyntaxDef.Partitions)
    54  	if err != nil {
    55  		return err
    56  	}
    57  
    58  	err = hpb.checkPartitionIntegrity(ctx, partitionBinder, tableDef, partitionDef)
    59  	if err != nil {
    60  		return err
    61  	}
    62  
    63  	err = hpb.buildEvalPartitionExpression(ctx, partitionBinder, stmt.PartitionOption, partitionDef)
    64  	if err != nil {
    65  		return err
    66  	}
    67  
    68  	partitionDef.PartitionMsg = tree.String(partitionSyntaxDef, dialect.MYSQL)
    69  	tableDef.Partition = partitionDef
    70  	return nil
    71  }
    72  
    73  // buildPartitionDefs decides the partition defs
    74  func (hpb *hashPartitionBuilder) buildPartitionDefs(ctx context.Context, _ *PartitionBinder,
    75  	partitionDef *plan.PartitionByDef, syntaxDefs []*tree.Partition) error {
    76  	return buildPartitionDefs(ctx, partitionDef, syntaxDefs)
    77  }
    78  
    79  /*
    80  checkTableDefPartition
    81  check partition keys
    82  check partition expr type
    83  check partition defs constraints
    84  */
    85  func (hpb *hashPartitionBuilder) checkPartitionIntegrity(ctx context.Context, partitionBinder *PartitionBinder, tableDef *TableDef, partitionDef *plan.PartitionByDef) error {
    86  	return checkPartitionIntegrity(ctx, partitionBinder, tableDef, partitionDef)
    87  }
    88  
    89  func (hpb *hashPartitionBuilder) buildEvalPartitionExpression(ctx context.Context, partitionBinder *PartitionBinder,
    90  	stmt *tree.PartitionOption, partitionDef *plan.PartitionByDef) error {
    91  	partitionType := stmt.PartBy.PType.(*tree.HashType)
    92  	// For the Hash partition, convert the partition information into the expression,such as: abs (hash_value (expr)) % partitionNum
    93  	hashExpr := partitionType.Expr
    94  	partitionAst := genPartitionAst(tree.Exprs{hashExpr}, int64(partitionDef.PartitionNum))
    95  
    96  	tempExpr, err := partitionBinder.baseBindExpr(partitionAst, 0, true)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	partitionExpression, err := appendCastBeforeExpr(ctx, tempExpr, plan.Type{
   101  		Id:          int32(types.T_int32),
   102  		NotNullable: true,
   103  	})
   104  	if err != nil {
   105  		return err
   106  	}
   107  	partitionDef.PartitionExpression = partitionExpression
   108  	return nil
   109  }