mirror of https://github.com/pikami/cosmium.git
Added support for TOP statement
This commit is contained in:
parent
62ac9ddf6b
commit
b13434eeff
|
@ -28,6 +28,7 @@ type SelectStmt struct {
|
|||
SelectItems []SelectItem
|
||||
Table Table
|
||||
Filters interface{}
|
||||
Count int
|
||||
}
|
||||
|
||||
type Table struct {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,10 +3,10 @@ package nosql
|
|||
|
||||
import "github.com/pikami/cosmium/parsers"
|
||||
|
||||
func makeSelectStmt(columns, table, whereClause interface{}) (parsers.SelectStmt, error) {
|
||||
selectStmt := parsers.SelectStmt{
|
||||
func makeSelectStmt(columns, table, whereClause interface{}, count interface{}) (parsers.SelectStmt, error) {
|
||||
selectStmt := parsers.SelectStmt{
|
||||
SelectItems: columns.([]parsers.SelectItem),
|
||||
Table: table.(parsers.Table),
|
||||
Table: table.(parsers.Table),
|
||||
}
|
||||
|
||||
if filters, ok := whereClause.(parsers.ComparisonExpression); ok {
|
||||
|
@ -15,6 +15,10 @@ func makeSelectStmt(columns, table, whereClause interface{}) (parsers.SelectStmt
|
|||
selectStmt.Filters = filters
|
||||
}
|
||||
|
||||
if n, ok := count.(int); ok {
|
||||
selectStmt.Count = n
|
||||
}
|
||||
|
||||
return selectStmt, nil
|
||||
}
|
||||
|
||||
|
@ -98,10 +102,14 @@ Input <- selectStmt:SelectStmt {
|
|||
return selectStmt, nil
|
||||
}
|
||||
|
||||
SelectStmt <- Select ws columns:Selection ws
|
||||
SelectStmt <- Select ws topClause:TopClause? ws columns:Selection ws
|
||||
From ws table:TableName ws
|
||||
whereClause:(ws Where ws condition:Condition { return condition, nil })? {
|
||||
return makeSelectStmt(columns, table, whereClause)
|
||||
return makeSelectStmt(columns, table, whereClause, topClause)
|
||||
}
|
||||
|
||||
TopClause <- Top ws count:Integer {
|
||||
return count, nil
|
||||
}
|
||||
|
||||
Selection <- SelectValueSpec / ColumnList
|
||||
|
@ -178,6 +186,8 @@ ComparisonExpression <- left:(Literal / SelectItem) ws op:ComparisonOperator ws
|
|||
|
||||
Select <- ("select" / "SELECT")
|
||||
|
||||
Top <- ("top" / "TOP")
|
||||
|
||||
As <- ("as" / "AS")
|
||||
|
||||
From <- ("from" / "FROM")
|
||||
|
@ -190,9 +200,8 @@ ComparisonOperator <- "=" / "!=" / "<" / "<=" / ">" / ">=" {
|
|||
|
||||
Literal <- FloatLiteral / IntegerLiteral / StringLiteral / BooleanLiteral
|
||||
|
||||
IntegerLiteral <- [0-9]+ {
|
||||
intValue, _ := strconv.Atoi(string(c.text))
|
||||
return parsers.Constant{Type: parsers.ConstantTypeInteger, Value: intValue}, nil
|
||||
IntegerLiteral <- number:Integer {
|
||||
return parsers.Constant{Type: parsers.ConstantTypeInteger, Value: number.(int)}, nil
|
||||
}
|
||||
StringLiteral <- "\"" chars:StringCharacter* "\"" {
|
||||
return parsers.Constant{Type: parsers.ConstantTypeString,Value: joinStrings(chars.([]interface{}))}, nil
|
||||
|
@ -206,6 +215,10 @@ BooleanLiteral <- ("true" / "false") {
|
|||
return parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: boolValue}, nil
|
||||
}
|
||||
|
||||
Integer <- [0-9]+ {
|
||||
return strconv.Atoi(string(c.text))
|
||||
}
|
||||
|
||||
StringCharacter <- !('"' / "\\") . { return string(c.text), nil }
|
||||
/ "\\" seq:EscapeSequenceCharacter { return seq, nil }
|
||||
|
||||
|
|
|
@ -52,6 +52,20 @@ func Test_Parse(t *testing.T) {
|
|||
)
|
||||
})
|
||||
|
||||
t.Run("Should parse SELECT TOP", func(t *testing.T) {
|
||||
testQueryParse(
|
||||
t,
|
||||
`SELECT TOP 1 c.id FROM c`,
|
||||
parsers.SelectStmt{
|
||||
SelectItems: []parsers.SelectItem{
|
||||
{Path: []string{"c", "id"}},
|
||||
},
|
||||
Table: parsers.Table{Value: "c"},
|
||||
Count: 1,
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should parse SELECT VALUE", func(t *testing.T) {
|
||||
testQueryParse(
|
||||
t,
|
||||
|
|
|
@ -18,6 +18,17 @@ func Execute(query parsers.SelectStmt, data []RowType) []RowType {
|
|||
}
|
||||
}
|
||||
|
||||
// Apply result limit
|
||||
if query.Count > 0 {
|
||||
count := func() int {
|
||||
if len(result) < query.Count {
|
||||
return len(result)
|
||||
}
|
||||
return query.Count
|
||||
}()
|
||||
result = result[:count]
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,24 @@ func Test_Execute(t *testing.T) {
|
|||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute SELECT TOP", 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: 1,
|
||||
},
|
||||
mockData,
|
||||
[]memoryexecutor.RowType{
|
||||
map[string]interface{}{"id": "12345", "pk": 123},
|
||||
},
|
||||
)
|
||||
})
|
||||
|
||||
t.Run("Should execute SELECT VALUE", func(t *testing.T) {
|
||||
testQueryExecute(
|
||||
t,
|
||||
|
|
Loading…
Reference in New Issue