Added support for 'SELECT VALUE' statement

This commit is contained in:
Pijus Kamandulis
2024-02-13 21:22:55 +02:00
parent 9c56d01d27
commit e89f2e5611
7 changed files with 431 additions and 310 deletions

View File

@@ -14,24 +14,33 @@ func Execute(query parsers.SelectStmt, data []RowType) []RowType {
for _, row := range data {
// Check if the row satisfies the filter conditions
if evaluateFilters(query.Filters, row) {
// Construct a new row based on the selected columns
newRow := make(map[string]interface{})
for _, column := range query.Columns {
destinationName := column.Alias
if destinationName == "" {
destinationName = column.Path[len(column.Path)-1]
}
newRow[destinationName] = getFieldValue(column, row)
}
// Add the new row to the result
result = append(result, newRow)
result = append(result, selectRow(query.SelectItems, row))
}
}
return result
}
func selectRow(selectItems []parsers.SelectItem, row RowType) interface{} {
// When the first value is top level, select it instead
if len(selectItems) > 0 && selectItems[0].IsTopLevel {
return getFieldValue(selectItems[0], row)
}
// Construct a new row based on the selected columns
newRow := make(map[string]interface{})
for _, column := range selectItems {
destinationName := column.Alias
if destinationName == "" {
destinationName = column.Path[len(column.Path)-1]
}
newRow[destinationName] = getFieldValue(column, row)
}
return newRow
}
// Helper function to evaluate filter conditions recursively
func evaluateFilters(expr ExpressionType, row RowType) bool {
if expr == nil {
@@ -74,7 +83,7 @@ func evaluateFilters(expr ExpressionType, row RowType) bool {
return false
}
func getFieldValue(field parsers.FieldPath, row RowType) interface{} {
func getFieldValue(field parsers.SelectItem, row RowType) interface{} {
value := row
for _, pathSegment := range field.Path[1:] {
if nestedValue, ok := value.(map[string]interface{}); ok {
@@ -88,7 +97,7 @@ func getFieldValue(field parsers.FieldPath, row RowType) interface{} {
func getExpressionParameterValue(parameter interface{}, row RowType) interface{} {
switch typedParameter := parameter.(type) {
case parsers.FieldPath:
case parsers.SelectItem:
return getFieldValue(typedParameter, row)
case parsers.Constant:
return typedParameter.Value

View File

@@ -27,11 +27,11 @@ func Test_Execute(t *testing.T) {
map[string]interface{}{"id": "67890", "pk": 456, "_self": "self2", "_rid": "rid2", "_ts": 789012, "isCool": true},
}
t.Run("Shoul execute simple SELECT", func(t *testing.T) {
t.Run("Should execute simple SELECT", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
Columns: []parsers.FieldPath{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{Path: []string{"c", "pk"}},
},
@@ -45,17 +45,34 @@ func Test_Execute(t *testing.T) {
)
})
t.Run("Shoul execute SELECT with single WHERE condition", func(t *testing.T) {
t.Run("Should execute SELECT VALUE", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
Columns: []parsers.FieldPath{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}, IsTopLevel: true},
},
Table: parsers.Table{Value: "c"},
},
mockData,
[]memoryexecutor.RowType{
"12345",
"67890",
},
)
})
t.Run("Should execute SELECT with single WHERE condition", func(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
},
Table: parsers.Table{Value: "c"},
Filters: parsers.ComparisonExpression{
Operation: "=",
Left: parsers.FieldPath{Path: []string{"c", "isCool"}},
Left: parsers.SelectItem{Path: []string{"c", "isCool"}},
Right: parsers.Constant{Type: parsers.ConstantTypeBoolean, Value: true},
},
},
@@ -70,7 +87,7 @@ func Test_Execute(t *testing.T) {
testQueryExecute(
t,
parsers.SelectStmt{
Columns: []parsers.FieldPath{
SelectItems: []parsers.SelectItem{
{Path: []string{"c", "id"}},
{Path: []string{"c", "_self"}, Alias: "self"},
},
@@ -80,12 +97,12 @@ func Test_Execute(t *testing.T) {
Expressions: []interface{}{
parsers.ComparisonExpression{
Operation: "=",
Left: parsers.FieldPath{Path: []string{"c", "id"}},
Left: parsers.SelectItem{Path: []string{"c", "id"}},
Right: parsers.Constant{Type: parsers.ConstantTypeString, Value: "67890"},
},
parsers.ComparisonExpression{
Operation: "=",
Left: parsers.FieldPath{Path: []string{"c", "pk"}},
Left: parsers.SelectItem{Path: []string{"c", "pk"}},
Right: parsers.Constant{Type: parsers.ConstantTypeInteger, Value: 456},
},
},