Tighten up ORDER BY (fb 507) (#2318)

* tighten up checks for order by expressions fixed ordering by expressions

* added testing to cover order by cases

* Add DecimalAgg member to proto GroupCount definition

In DAX, where we have split the orchestrator from the executor, and the
orchestrator can run on a different host, there are cases where
`GroupCount`s can travel over the wire via the Internal Client. In these
cases, when the group count contains a decimal aggregate, we need to
send that value as the appropriate type.

* fixed missing cases in order by and case block eval

Co-authored-by: Travis Turner <travis@molecula.com>
(cherry picked from commit 158cc669d9)
This commit is contained in:
pokeeffe-molecula 2022-11-30 11:32:37 -06:00 committed by Fletcher Haynes
parent b6ae088f24
commit eae8376181
12 changed files with 828 additions and 313 deletions

View file

@ -94,7 +94,6 @@ func TestDAXIntegration(t *testing.T) {
skips := []string{
"testinsert/test-5", // error messages differ
"percentile_test/test-6", // related to TODO in orchestrator.executePercentile
"groupby_test/test-6", // something to do with GroupCount.DecimalAgg=nil in orchestrator.executeGroupBy
"innerjointest/innerjoin-aggregate-groupby", // join test which won't work until we support multiple tables
}

View file

@ -16,6 +16,9 @@ func init() {
if err != nil {
panic(err)
}
if err := client.FromEnv(cli); err != nil {
panic(err)
}
cli.RegistryLogin(context.Background(), types.AuthConfig{})
DefaultClient = cli

View file

@ -1514,7 +1514,8 @@ func (s Serializer) decodeGroupCounts(a *pb.GroupCounts, b []*pb.GroupCount) *pi
Count: gc.Count,
// note: not renaming the `pb. structure members now
// to avoid breaking protobuf interactions.
Agg: gc.Agg,
Agg: gc.Agg,
DecimalAgg: s.decodeDecimalStruct(gc.DecimalAgg),
}
}
return pilosa.NewGroupCounts(a.Aggregate, other...)
@ -1703,9 +1704,10 @@ func (s Serializer) encodeGroupCounts(counts *pilosa.GroupCounts) *pb.GroupCount
}
for i, gc := range groups {
result.Groups[i] = &pb.GroupCount{
Group: s.encodeFieldRows(gc.Group),
Count: gc.Count,
Agg: gc.Agg,
Group: s.encodeFieldRows(gc.Group),
Count: gc.Count,
Agg: gc.Agg,
DecimalAgg: s.encodeDecimal(gc.DecimalAgg),
}
}
return result

View file

@ -6792,7 +6792,10 @@ func (m *IndexMeta) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7261,7 +7264,10 @@ func (m *FieldOptions) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7344,7 +7350,10 @@ func (m *ImportResponse) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7529,7 +7538,10 @@ func (m *BlockDataRequest) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7732,7 +7744,10 @@ func (m *BlockDataResponse) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -7859,7 +7874,10 @@ func (m *Cache) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8006,7 +8024,7 @@ func (m *MaxShards) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > postIndex {
@ -8023,7 +8041,10 @@ func (m *MaxShards) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8157,7 +8178,10 @@ func (m *CreateShardMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8240,7 +8264,10 @@ func (m *DeleteIndexMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8410,7 +8437,10 @@ func (m *CreateIndexMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8612,7 +8642,10 @@ func (m *CreateFieldMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8735,7 +8768,10 @@ func (m *UpdateFieldMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8850,7 +8886,10 @@ func (m *FieldUpdate) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -8965,7 +9004,10 @@ func (m *DeleteFieldMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9099,7 +9141,10 @@ func (m *DeleteAvailableShardMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9269,7 +9314,10 @@ func (m *Field) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9354,7 +9402,10 @@ func (m *Schema) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9526,7 +9577,10 @@ func (m *Index) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9660,7 +9714,10 @@ func (m *URI) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9867,7 +9924,10 @@ func (m *Node) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -9982,7 +10042,10 @@ func (m *NodeStateMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10088,7 +10151,10 @@ func (m *NodeEventMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10245,7 +10311,10 @@ func (m *NodeStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10381,7 +10450,10 @@ func (m *IndexStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10559,7 +10631,10 @@ func (m *FieldStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10744,7 +10819,10 @@ func (m *ClusterStatus) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -10897,7 +10975,10 @@ func (m *BSIGroup) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11044,7 +11125,10 @@ func (m *CreateViewMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11191,7 +11275,10 @@ func (m *DeleteViewMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11473,7 +11560,10 @@ func (m *ResizeInstruction) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11675,7 +11765,10 @@ func (m *ResizeSource) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11813,7 +11906,10 @@ func (m *TranslationResizeSource) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -11951,7 +12047,10 @@ func (m *ResizeInstructionComplete) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12066,7 +12165,10 @@ func (m *Topology) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12117,7 +12219,10 @@ func (m *RecalculateCaches) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12168,7 +12273,10 @@ func (m *LoadSchemaMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12287,7 +12395,10 @@ func (m *TransactionMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12484,7 +12595,10 @@ func (m *Transaction) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12535,7 +12649,10 @@ func (m *TransactionStats) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12586,7 +12703,10 @@ func (m *ResizeAbortMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12701,7 +12821,10 @@ func (m *ResizeNodeMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -12980,7 +13103,10 @@ func (m *FieldOperation) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -13283,7 +13409,7 @@ func (m *ShardIngestOperation) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > postIndex {
@ -13300,7 +13426,10 @@ func (m *ShardIngestOperation) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -13385,7 +13514,10 @@ func (m *ShardIngestOperations) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -13534,7 +13666,7 @@ func (m *ShardedIngestRequest) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > postIndex {
@ -13551,7 +13683,10 @@ func (m *ShardedIngestRequest) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {
@ -13634,7 +13769,10 @@ func (m *DeleteDataframeMessage) Unmarshal(dAtA []byte) error {
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
if skippy < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) < 0 {
return ErrInvalidLengthPrivate
}
if (iNdEx + skippy) > l {

File diff suppressed because it is too large Load diff

View file

@ -102,6 +102,7 @@ message GroupCount{
repeated FieldRow Group = 1;
uint64 Count = 2;
int64 Agg = 3;
Decimal DecimalAgg = 4;
}
message ValCount {

View file

@ -78,7 +78,8 @@ const (
ErrConflictingColumnConstraint errors.Code = "ErrConflictingColumnConstraint"
// expected errors
ErrExpectedColumnReference errors.Code = "ErrExpectedColumnReference"
ErrExpectedColumnReference errors.Code = "ErrExpectedColumnReference"
ErrExpectedSortExpressionReference errors.Code = "ErrExpectedSortExpressionReference"
// call errors
ErrCallUnknownFunction errors.Code = "ErrCallUnknownFunction"
@ -523,6 +524,13 @@ func NewErrExpectedColumnReference(line, col int) error {
)
}
func NewErrExpectedSortExpressionReference(line, col int) error {
return errors.New(
ErrExpectedSortExpressionReference,
fmt.Sprintf("[%d:%d] column reference, alias reference or column position expected", line, col),
)
}
// calls
func NewErrCallParameterCountMismatch(line, col int, functionName string, formalCount, actualCount int) error {

View file

@ -117,12 +117,16 @@ func (p *ExecutionPlanner) compileSelectStatement(stmt *parser.SelectStatement,
if len(stmt.OrderingTerms) > 0 {
orderByFields := make([]*OrderByExpression, 0)
for _, ot := range stmt.OrderingTerms {
otExpr, err := p.compileExpr(ot.X)
index, err := p.compileOrderingTermExpr(ot.X)
if err != nil {
return nil, err
}
// get the data type from the projection
projDataType := projections[index].Type()
f := &OrderByExpression{
Expr: otExpr,
Index: index,
ExprType: projDataType,
}
f.Order = orderByAsc
if ot.Desc.IsValid() {
@ -424,13 +428,11 @@ func (p *ExecutionPlanner) analyzeSelectStatement(stmt *parser.SelectStatement)
}
for _, term := range stmt.OrderingTerms {
expr, err = p.analyzeExpression(term.X, stmt)
expr, err := p.analyzeOrderingTermExpression(term.X, stmt)
if err != nil {
return err
}
if expr != nil {
term.X = expr
}
term.X = expr
}
return nil

View file

@ -875,6 +875,14 @@ func (n *casePlanExpression) Evaluate(currentRow []interface{}) (interface{}, er
return b, nil
}
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t'", bok)
case *parser.DataTypeBool:
b, bok := evalBlockBody.(bool)
if bok {
return b, nil
}
return nil, sql3.NewErrInternalf("unexpected type conversion error '%t'", bok)
case *parser.DataTypeString:
s, sok := evalBlockBody.(string)
if sok {
@ -2726,6 +2734,29 @@ func (p *ExecutionPlanner) compileCallExpr(expr *parser.Call) (_ types.PlanExpre
}
}
func (p *ExecutionPlanner) compileOrderingTermExpr(expr parser.Expr) (index int, err error) {
if expr == nil {
return 0, nil
}
switch thisExpr := expr.(type) {
case *parser.QualifiedRef:
return thisExpr.ColumnIndex, nil
case *parser.IntegerLit:
val, err := strconv.ParseInt(thisExpr.Value, 10, 64)
if err != nil {
return 0, err
}
// subtract one because ordering terms are 1 based, not 0 based
return int(val - 1), nil
default:
return 0, sql3.NewErrInternalf("unexpected ordering expression type: %T", expr)
}
}
// wildCardToRegexp converts a wildcard pattern to a regular expression pattern.
// used by the LIKE/NOT LIKE operator
func wildCardToRegexp(pattern string) string {

View file

@ -3,6 +3,7 @@
package planner
import (
"strconv"
"strings"
"github.com/featurebasedb/featurebase/v3/sql3"
@ -741,3 +742,80 @@ func (p *ExecutionPlanner) analyzeCaseBlockExpression(expr *parser.CaseBlock, ca
return expr, nil
}
func (p *ExecutionPlanner) analyzeOrderingTermExpression(expr parser.Expr, scope parser.Statement) (parser.Expr, error) {
if expr == nil {
return nil, nil
}
// ordering terms need to be either a column name, an alias name or an integer literal representing
// position of column in the select list
switch thisExpr := expr.(type) {
case *parser.Ident:
switch sc := scope.(type) {
case *parser.SelectStatement:
// go find the first ident in the projection list that matches
columnIndex := 0
found := false
for idx, proj := range sc.Columns {
// if the expression is a qualified ref, check the name
colExpr, ok := proj.Expr.(*parser.QualifiedRef)
if ok && strings.EqualFold(thisExpr.Name, colExpr.Column.Name) {
columnIndex = idx
found = true
break
}
// try the alias is there is one
if proj.Alias != nil && strings.EqualFold(thisExpr.Name, proj.Alias.Name) {
columnIndex = idx
found = true
break
}
}
if !found {
return nil, sql3.NewErrColumnNotFound(thisExpr.NamePos.Line, thisExpr.NamePos.Column, thisExpr.Name)
}
// turn *parser.Ident into *parser.QualifiedRef
ident := &parser.QualifiedRef{
Table: &parser.Ident{
Name: "",
NamePos: parser.Pos{Line: 0, Column: 0},
},
Column: &parser.Ident{
Name: thisExpr.Name,
NamePos: thisExpr.NamePos,
},
ColumnIndex: columnIndex,
// since this is a ordring term, we don't care about the type
RefDataType: parser.NewDataTypeVoid(),
}
return ident, nil
default:
return nil, sql3.NewErrInternalf("unhandled scope type '%T'", sc)
}
case *parser.IntegerLit:
switch sc := scope.(type) {
case *parser.SelectStatement:
// check to see if the offset is in the range
value, err := strconv.ParseInt(thisExpr.Value, 10, 64)
if err != nil {
return nil, sql3.NewErrInternalf("unexpected integer literal value")
}
if value < 1 || value > int64(len(sc.Columns)) {
return nil, sql3.NewErrExpectedSortExpressionReference(0, 0)
}
default:
return nil, sql3.NewErrInternalf("unhandled scope type '%T'", sc)
}
default:
return nil, sql3.NewErrExpectedSortExpressionReference(expr.Pos().Line, expr.Pos().Column)
}
return expr, nil
}

View file

@ -8,9 +8,10 @@ import (
"sort"
"time"
"github.com/featurebasedb/featurebase/v3/sql3"
"github.com/featurebasedb/featurebase/v3/sql3/parser"
"github.com/featurebasedb/featurebase/v3/sql3/planner/types"
"github.com/molecula/featurebase/v3/pql"
"github.com/molecula/featurebase/v3/sql3"
"github.com/molecula/featurebase/v3/sql3/parser"
"github.com/molecula/featurebase/v3/sql3/planner/types"
)
// orderByOrder is the direction of the order by (ascending or descending).
@ -31,7 +32,8 @@ const (
// OrderByExpression is the expression on which an order by can be computed
type OrderByExpression struct {
Expr types.PlanExpression
Index int
ExprType parser.ExprDataType
Order orderByOrder
NullOrdering nullOrdering
}
@ -94,7 +96,8 @@ func (n *PlanOpOrderBy) Plan() map[string]interface{} {
ps := make([]interface{}, 0)
for _, e := range n.orderByFields {
ps = append(ps, &map[string]interface{}{
"expr": e.Expr.Plan(),
"index": e.Index,
"exprType": e.ExprType.TypeName(),
"order": e.Order,
"nullOrdering": e.NullOrdering,
})
@ -204,17 +207,8 @@ func (s *OrderBySorter) Less(i, j int) bool {
a := s.Rows[i]
b := s.Rows[j]
for _, sf := range s.SortFields {
av, err := sf.Expr.Evaluate(a)
if err != nil {
s.LastError = sql3.NewErrInternalf("unable to sort '%s'", err.Error())
return false
}
bv, err := sf.Expr.Evaluate(b)
if err != nil {
s.LastError = sql3.NewErrInternalf("unable to sort '%s'", err.Error())
return false
}
av := a[sf.Index]
bv := b[sf.Index]
if sf.Order == orderByDesc {
av, bv = bv, av
@ -228,7 +222,7 @@ func (s *OrderBySorter) Less(i, j int) bool {
return sf.NullOrdering != nullOrderingFirst
}
switch sf.Expr.Type().(type) {
switch sf.ExprType.(type) {
case *parser.DataTypeInt, *parser.DataTypeID:
avInt, aok := av.(int64)
bvInt, bok := bv.(int64)
@ -253,6 +247,30 @@ func (s *OrderBySorter) Less(i, j int) bool {
}
return true
case *parser.DataTypeString:
avString, aok := av.(string)
bvString, bok := bv.(string)
if !(aok && bok) {
s.LastError = sql3.NewErrInternalf("unexpected type conversion result")
return false
}
if avString > bvString {
return false
}
return true
case *parser.DataTypeDecimal:
avDecimal, aok := av.(pql.Decimal)
bvDecimal, bok := bv.(pql.Decimal)
if !(aok && bok) {
s.LastError = sql3.NewErrInternalf("unexpected type conversion result")
return false
}
if avDecimal.GreaterThan(bvDecimal) {
return false
}
return true
case *parser.DataTypeTimestamp:
avTime, aok := av.(time.Time)
bvTime, bok := bv.(time.Time)
@ -266,7 +284,7 @@ func (s *OrderBySorter) Less(i, j int) bool {
return true
default:
s.LastError = sql3.NewErrInternalf("unhandled data type '%T'", sf.Expr.Type())
s.LastError = sql3.NewErrInternalf("unhandled data type '%T'", sf.ExprType)
return false
}
}

View file

@ -27,6 +27,64 @@ var groupByTests = TableTest{
),
),
SQLTests: []SQLTest{
{
SQLs: sqls(
"SELECT COUNT(*), i1 FROM groupby_test group by i1 order by count(*) asc",
"SELECT COUNT(_id), i1 FROM groupby_test group by i1 order by count(*) asc",
),
ExpErr: "column reference, alias reference or column position expected",
},
{
SQLs: sqls(
"SELECT COUNT(*), i1 FROM groupby_test group by i1 order by 2 asc",
"SELECT COUNT(_id), i1 FROM groupby_test group by i1 order by 2 asc",
),
ExpHdrs: hdrs(
hdr("", fldTypeInt),
hdr("i1", fldTypeInt),
),
ExpRows: rows(
row(int64(2), int64(10)),
row(int64(1), int64(11)),
row(int64(2), int64(12)),
row(int64(1), int64(13)),
),
Compare: CompareExactOrdered,
},
{
SQLs: sqls(
"SELECT COUNT(*), i1 as c FROM groupby_test group by i1 order by c asc",
"SELECT COUNT(_id), i1 as c FROM groupby_test group by i1 order by c asc",
),
ExpHdrs: hdrs(
hdr("", fldTypeInt),
hdr("c", fldTypeInt),
),
ExpRows: rows(
row(int64(2), int64(10)),
row(int64(1), int64(11)),
row(int64(2), int64(12)),
row(int64(1), int64(13)),
),
Compare: CompareExactOrdered,
},
{
SQLs: sqls(
"SELECT COUNT(*), i1 as c FROM groupby_test group by i1 order by i1 asc",
"SELECT COUNT(_id), i1 as c FROM groupby_test group by i1 order by i1 asc",
),
ExpHdrs: hdrs(
hdr("", fldTypeInt),
hdr("c", fldTypeInt),
),
ExpRows: rows(
row(int64(2), int64(10)),
row(int64(1), int64(11)),
row(int64(2), int64(12)),
row(int64(1), int64(13)),
),
Compare: CompareExactOrdered,
},
{
SQLs: sqls(
"SELECT COUNT(*), i1 FROM groupby_test group by i1",