code: func checkRangePartitioningKeysConstraints(sctx sessionctx.Context, s *ast.CreateTableStmt, tblInfo *model.TableInfo, constraints []*ast.Constraint) error {
  	// Returns directly if there is no constraint in the partition table.
  	// TODO: Remove the test 's.Partition.Expr == nil' when we support 'PARTITION BY RANGE COLUMNS'
  	if len(constraints) == 0 || s.Partition.Expr == nil {
  		return nil
  	}
  
  	// Parse partitioning key, extract the column names in the partitioning key to slice.
  	buf := new(bytes.Buffer)
  	s.Partition.Expr.Format(buf)
  	partCols, err := extractPartitionColumns(sctx, buf.String(), tblInfo)
  	if err != nil {
  		return err
  	}
  
  	// Checks that the partitioning key is included in the constraint.
  	// Every unique key on the table must use every column in the table's partitioning expression.
  	// See https://dev.mysql.com/doc/refman/5.7/en/partitioning-limitations-partitioning-keys-unique-keys.html
  	for _, constraint := range constraints {
  		switch constraint.Tp {
  		case ast.ConstraintPrimaryKey, ast.ConstraintUniq, ast.ConstraintUniqKey, ast.ConstraintUniqIndex:
  			if !checkUniqueKeyIncludePartKey(partCols, constraint.Keys) {
  				if constraint.Tp == ast.ConstraintPrimaryKey {
  					return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("PRIMARY KEY")
  				}
  				return ErrUniqueKeyNeedAllFieldsInPf.GenWithStackByArgs("UNIQUE INDEX")
  			}
  		}
  	}
  	return nil
  }
docs: // checkRangePartitioningKeysConstraints checks that the range partitioning key is included in the table constraint.