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
|
SelectItems []SelectItem
|
||||||
Table Table
|
Table Table
|
||||||
Filters interface{}
|
Filters interface{}
|
||||||
|
Count int
|
||||||
}
|
}
|
||||||
|
|
||||||
type Table struct {
|
type Table struct {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@ package nosql
|
||||||
|
|
||||||
import "github.com/pikami/cosmium/parsers"
|
import "github.com/pikami/cosmium/parsers"
|
||||||
|
|
||||||
func makeSelectStmt(columns, table, whereClause interface{}) (parsers.SelectStmt, error) {
|
func makeSelectStmt(columns, table, whereClause interface{}, count interface{}) (parsers.SelectStmt, error) {
|
||||||
selectStmt := parsers.SelectStmt{
|
selectStmt := parsers.SelectStmt{
|
||||||
SelectItems: columns.([]parsers.SelectItem),
|
SelectItems: columns.([]parsers.SelectItem),
|
||||||
Table: table.(parsers.Table),
|
Table: table.(parsers.Table),
|
||||||
|
@ -15,6 +15,10 @@ func makeSelectStmt(columns, table, whereClause interface{}) (parsers.SelectStmt
|
||||||
selectStmt.Filters = filters
|
selectStmt.Filters = filters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if n, ok := count.(int); ok {
|
||||||
|
selectStmt.Count = n
|
||||||
|
}
|
||||||
|
|
||||||
return selectStmt, nil
|
return selectStmt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,10 +102,14 @@ Input <- selectStmt:SelectStmt {
|
||||||
return selectStmt, nil
|
return selectStmt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectStmt <- Select ws columns:Selection ws
|
SelectStmt <- Select ws topClause:TopClause? ws columns:Selection 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 })? {
|
||||||
return makeSelectStmt(columns, table, whereClause)
|
return makeSelectStmt(columns, table, whereClause, topClause)
|
||||||
|
}
|
||||||
|
|
||||||
|
TopClause <- Top ws count:Integer {
|
||||||
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
Selection <- SelectValueSpec / ColumnList
|
Selection <- SelectValueSpec / ColumnList
|
||||||
|
@ -178,6 +186,8 @@ ComparisonExpression <- left:(Literal / SelectItem) ws op:ComparisonOperator ws
|
||||||
|
|
||||||
Select <- ("select" / "SELECT")
|
Select <- ("select" / "SELECT")
|
||||||
|
|
||||||
|
Top <- ("top" / "TOP")
|
||||||
|
|
||||||
As <- ("as" / "AS")
|
As <- ("as" / "AS")
|
||||||
|
|
||||||
From <- ("from" / "FROM")
|
From <- ("from" / "FROM")
|
||||||
|
@ -190,9 +200,8 @@ ComparisonOperator <- "=" / "!=" / "<" / "<=" / ">" / ">=" {
|
||||||
|
|
||||||
Literal <- FloatLiteral / IntegerLiteral / StringLiteral / BooleanLiteral
|
Literal <- FloatLiteral / IntegerLiteral / StringLiteral / BooleanLiteral
|
||||||
|
|
||||||
IntegerLiteral <- [0-9]+ {
|
IntegerLiteral <- number:Integer {
|
||||||
intValue, _ := strconv.Atoi(string(c.text))
|
return parsers.Constant{Type: parsers.ConstantTypeInteger, Value: number.(int)}, nil
|
||||||
return parsers.Constant{Type: parsers.ConstantTypeInteger, Value: intValue}, nil
|
|
||||||
}
|
}
|
||||||
StringLiteral <- "\"" chars:StringCharacter* "\"" {
|
StringLiteral <- "\"" chars:StringCharacter* "\"" {
|
||||||
return parsers.Constant{Type: parsers.ConstantTypeString,Value: joinStrings(chars.([]interface{}))}, nil
|
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
|
return parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: boolValue}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Integer <- [0-9]+ {
|
||||||
|
return strconv.Atoi(string(c.text))
|
||||||
|
}
|
||||||
|
|
||||||
StringCharacter <- !('"' / "\\") . { return string(c.text), nil }
|
StringCharacter <- !('"' / "\\") . { return string(c.text), nil }
|
||||||
/ "\\" seq:EscapeSequenceCharacter { return seq, 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) {
|
t.Run("Should parse SELECT VALUE", func(t *testing.T) {
|
||||||
testQueryParse(
|
testQueryParse(
|
||||||
t,
|
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
|
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) {
|
t.Run("Should execute SELECT VALUE", func(t *testing.T) {
|
||||||
testQueryExecute(
|
testQueryExecute(
|
||||||
t,
|
t,
|
||||||
|
|
Loading…
Reference in New Issue