Implement OFFSET LIMIT

This commit is contained in:
Pijus Kamandulis 2024-03-11 22:02:10 +02:00
parent 5b66828bd0
commit 398584368f
6 changed files with 1118 additions and 975 deletions

View File

@ -36,7 +36,7 @@ Cosmium strives to support the core features of Cosmos DB, including:
| WHERE | Yes | | WHERE | Yes |
| ORDER BY | Yes | | ORDER BY | Yes |
| GROUP BY | Yes | | GROUP BY | Yes |
| OFFSET LIMIT | No | | OFFSET LIMIT | Yes |
### Keywords ### Keywords
| Keyword | Implemented | | Keyword | Implemented |

View File

@ -6,6 +6,7 @@ type SelectStmt struct {
Filters interface{} Filters interface{}
Distinct bool Distinct bool
Count int Count int
Offset int
Parameters map[string]interface{} Parameters map[string]interface{}
OrderExpressions []OrderExpression OrderExpressions []OrderExpression
GroupBy []SelectItem GroupBy []SelectItem

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ func makeSelectStmt(
columns, table, columns, table,
whereClause interface{}, distinctClause interface{}, whereClause interface{}, distinctClause interface{},
count interface{}, groupByClause interface{}, orderList interface{}, count interface{}, groupByClause interface{}, orderList interface{},
offsetClause interface{},
) (parsers.SelectStmt, error) { ) (parsers.SelectStmt, error) {
selectStmt := parsers.SelectStmt{ selectStmt := parsers.SelectStmt{
SelectItems: columns.([]parsers.SelectItem), SelectItems: columns.([]parsers.SelectItem),
@ -26,6 +27,16 @@ func makeSelectStmt(
selectStmt.Count = n selectStmt.Count = n
} }
if offsetArr, ok := offsetClause.([]interface{}); ok && len(offsetArr) == 2 {
if n, ok := offsetArr[0].(int); ok {
selectStmt.Offset = n
}
if n, ok := offsetArr[1].(int); ok {
selectStmt.Count = n
}
}
if orderExpressions, ok := orderList.([]parsers.OrderExpression); ok { if orderExpressions, ok := orderList.([]parsers.OrderExpression); ok {
selectStmt.OrderExpressions = orderExpressions selectStmt.OrderExpressions = orderExpressions
} }
@ -154,9 +165,10 @@ SelectStmt <- Select ws
From ws table:TableName ws From ws table:TableName ws
whereClause:(ws Where ws condition:Condition { return condition, nil })? whereClause:(ws Where ws condition:Condition { return condition, nil })?
groupByClause:(ws GroupBy ws columns:ColumnList { return columns, nil })? groupByClause:(ws GroupBy ws columns:ColumnList { return columns, nil })?
orderByClause:OrderByClause? { orderByClause:OrderByClause?
offsetClause:OffsetClause? {
return makeSelectStmt(columns, table, whereClause, return makeSelectStmt(columns, table, whereClause,
distinctClause, topClause, groupByClause, orderByClause) distinctClause, topClause, groupByClause, orderByClause, offsetClause)
} }
DistinctClause <- "DISTINCT"i DistinctClause <- "DISTINCT"i
@ -165,6 +177,10 @@ TopClause <- Top ws count:Integer {
return count, nil return count, nil
} }
OffsetClause <- "OFFSET"i ws offset:IntegerLiteral ws "LIMIT"i ws limit:IntegerLiteral {
return []interface{}{offset.(parsers.Constant).Value, limit.(parsers.Constant).Value}, nil
}
Selection <- SelectValueSpec / ColumnList / SelectAsterisk Selection <- SelectValueSpec / ColumnList / SelectAsterisk
SelectAsterisk <- "*" { SelectAsterisk <- "*" {

View File

@ -50,6 +50,21 @@ func Test_Parse_Select(t *testing.T) {
) )
}) })
t.Run("Should parse SELECT OFFSET", func(t *testing.T) {
testQueryParse(
t,
`SELECT c.id FROM c OFFSET 3 LIMIT 5`,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
},
Table: parsers.Table{Value: "c"},
Count: 5,
Offset: 3,
},
)
})
t.Run("Should parse SELECT VALUE", func(t *testing.T) { t.Run("Should parse SELECT VALUE", func(t *testing.T) {
testQueryParse( testQueryParse(
t, t,

View File

@ -71,6 +71,32 @@ func Test_Execute_Select(t *testing.T) {
) )
}) })
t.Run("Should execute SELECT OFFSET", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{Path: []string{"c", "pk"}},
},
Table: parsers.Table{Value: "c"},
Count: 2,
Offset: 1,
OrderExpressions: []parsers.OrderExpression{
{
SelectItem: parsers.SelectItem{Path: []string{"c", "id"}},
Direction: parsers.OrderDirectionDesc,
},
},
},
mockData,
[]memoryexecutor.RowType{
map[string]interface{}{"id": "67890", "pk": 456},
map[string]interface{}{"id": "456", "pk": 456},
},
)
})
t.Run("Should execute SELECT VALUE", func(t *testing.T) { t.Run("Should execute SELECT VALUE", func(t *testing.T) {
testQueryExecute( testQueryExecute(
t, t,