diff --git a/sql3/errors.go b/sql3/errors.go index 93f680d8b..b284da8b2 100644 --- a/sql3/errors.go +++ b/sql3/errors.go @@ -80,6 +80,7 @@ const ( // expected errors ErrExpectedColumnReference errors.Code = "ErrExpectedColumnReference" ErrExpectedSortExpressionReference errors.Code = "ErrExpectedSortExpressionReference" + ErrExpectedSortableExpression errors.Code = "ErrExpectedSortableExpression" // call errors ErrCallUnknownFunction errors.Code = "ErrCallUnknownFunction" @@ -531,6 +532,13 @@ func NewErrExpectedSortExpressionReference(line, col int) error { ) } +func NewErrExpectedSortableExpression(line, col int, typeName string) error { + return errors.New( + ErrExpectedSortExpressionReference, + fmt.Sprintf("[%d:%d] unable to sort a column of type '%s'", line, col, typeName), + ) +} + // calls func NewErrCallParameterCountMismatch(line, col int, functionName string, formalCount, actualCount int) error { diff --git a/sql3/parser/astdatatype.go b/sql3/parser/astdatatype.go index e811f00f4..f2491f9bd 100644 --- a/sql3/parser/astdatatype.go +++ b/sql3/parser/astdatatype.go @@ -9,6 +9,7 @@ import ( "github.com/featurebasedb/featurebase/v3/pql" ) +// TODO(pok) make all these lower case const ( FieldTypeBool = "BOOL" FieldTypeDecimal = "DECIMAL" diff --git a/sql3/planner/compileselect.go b/sql3/planner/compileselect.go index db70b4b2c..bd3f9365f 100644 --- a/sql3/planner/compileselect.go +++ b/sql3/planner/compileselect.go @@ -124,6 +124,12 @@ func (p *ExecutionPlanner) compileSelectStatement(stmt *parser.SelectStatement, // get the data type from the projection projDataType := projections[index].Type() + // don't let a sort happen on something unsortable right now + switch projDataType.(type) { + case *parser.DataTypeStringSet, *parser.DataTypeIDSet: + return nil, sql3.NewErrExpectedSortableExpression(0, 0, projDataType.TypeDescription()) + } + f := &OrderByExpression{ Index: index, ExprType: projDataType, diff --git a/sql3/test/defs/defs.go b/sql3/test/defs/defs.go index 9eec1db2d..c4a7f5fd5 100644 --- a/sql3/test/defs/defs.go +++ b/sql3/test/defs/defs.go @@ -15,6 +15,7 @@ var TableTests []TableTest = []TableTest{ selectTests, selectKeyedTests, + orderByTests, topTests, diff --git a/sql3/test/defs/defs_orderby.go b/sql3/test/defs/defs_orderby.go new file mode 100644 index 000000000..c97d51bcb --- /dev/null +++ b/sql3/test/defs/defs_orderby.go @@ -0,0 +1,39 @@ +package defs + +var orderByTests = TableTest{ + name: "orderByTests", + Table: tbl( + "order_by_test", + srcHdrs( + srcHdr("_id", fldTypeID), + srcHdr("an_int", fldTypeInt, "min 0", "max 100"), + srcHdr("an_id_set", fldTypeIDSet), + srcHdr("an_id", fldTypeID), + srcHdr("a_string", fldTypeString), + srcHdr("a_string_set", fldTypeStringSet), + srcHdr("a_decimal", fldTypeDecimal2), + ), + srcRows( + srcRow(int64(1), int64(11), []int64{11, 12, 13}, int64(101), "str1", []string{"a1", "b1", "c1"}, float64(123.45)), + srcRow(int64(2), int64(22), []int64{21, 22, 23}, int64(201), "str2", []string{"a2", "b2", "c2"}, float64(234.56)), + srcRow(int64(3), int64(33), []int64{31, 32, 33}, int64(301), "str3", []string{"a3", "b3", "c3"}, float64(345.67)), + srcRow(int64(4), int64(44), []int64{41, 42, 43}, int64(401), "str4", []string{"a4", "b4", "c4"}, float64(456.78)), + ), + ), + SQLTests: []SQLTest{ + { + name: "order-by-stringset", + SQLs: sqls( + "select * from order_by_test order by a_string_set asc", + ), + ExpErr: "unable to sort a column of type 'STRINGSET'", + }, + { + name: "order-by-idset", + SQLs: sqls( + "select * from order_by_test order by an_id_set asc", + ), + ExpErr: "unable to sort a column of type 'IDSET'", + }, + }, +}