forked from sourcenetwork/defradb
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add support for sum aggregate (sourcenetwork#121)
* Remove unnessecary object deconstruction * Correct count test description * Handle count generation errors * Replace query.Count struct with query.PropertyTransformation Makes it easier to share code between aggregates if they are parsed into the same struct * Generalize aggregate alias magic New implementation should happily support other aggregates out of the box * Move count plan planning to expand aggregate plans function * Extract hidden join logic to generic function * Add support for sum aggregate
- Loading branch information
1 parent
37d7b62
commit 3db855e
Showing
12 changed files
with
847 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
// Copyright 2020 Source Inc. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
package inline_array | ||
|
||
import ( | ||
"testing" | ||
|
||
testUtils "github.com/sourcenetwork/defradb/db/tests" | ||
) | ||
|
||
func TestQueryInlineIntegerArrayWithsWithSumAndNullArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of nil integer array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteIntegers: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"FavouriteIntegers": null | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": int64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQueryInlineIntegerArrayWithsWithSumAndEmptyArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of empty integer array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteIntegers: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"FavouriteIntegers": [] | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": int64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQueryInlineIntegerArrayWithsWithSumAndPopulatedArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of integer array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteIntegers: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "Shahzad", | ||
"FavouriteIntegers": [-1, 2, -1, 1, 0] | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "Shahzad", | ||
"_sum": int64(1), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQueryInlineFloatArrayWithsWithSumAndNullArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of nil float array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteFloats: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"FavouriteFloats": null | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": float64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQueryInlineFloatArrayWithsWithSumAndEmptyArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of empty float array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteFloats: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"FavouriteFloats": [] | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": float64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQueryInlineFloatArrayWithsWithSumAndPopulatedArray(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple inline array with no filter, sum of float array", | ||
Query: `query { | ||
users { | ||
Name | ||
_sum(field: {FavouriteFloats: {}}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"FavouriteFloats": [3.1425, 0.00000000001, 10] | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": float64(13.14250000001), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
// Copyright 2020 Source Inc. | ||
// | ||
// Use of this software is governed by the Business Source License | ||
// included in the file licenses/BSL.txt. | ||
// | ||
// As of the Change Date specified in that file, in accordance with | ||
// the Business Source License, use of this software will be governed | ||
// by the Apache License, Version 2.0, included in the file | ||
// licenses/APL.txt. | ||
package simple | ||
|
||
// TODO!!!!! once scalar are merged, this should be capable of summing int/float arrays - likely needs some tweaks in generator.go and query.go | ||
|
||
import ( | ||
"testing" | ||
|
||
testUtils "github.com/sourcenetwork/defradb/db/tests" | ||
) | ||
|
||
func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndSumOfUndefined(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple query with sum on unspecified field", | ||
Query: `query { | ||
users (groupBy: [Name]) { | ||
Name | ||
_sum | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"Age": 32 | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": int64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSum(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple query with group by string, sum on non-rendered group integer value", | ||
Query: `query { | ||
users(groupBy: [Name]) { | ||
Name | ||
_sum(field: {_group: Age}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"Age": 32 | ||
}`), | ||
(`{ | ||
"Name": "John", | ||
"Age": 38 | ||
}`), | ||
// It is important to test negative values here, due to the auto-typing of numbers | ||
(`{ | ||
"Name": "Alice", | ||
"Age": -19 | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": int64(70), | ||
}, | ||
{ | ||
"Name": "Alice", | ||
"_sum": int64(-19), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildNilSum(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple query with group by string, sum on non-rendered group nil and integer values", | ||
Query: `query { | ||
users(groupBy: [Name]) { | ||
Name | ||
_sum(field: {_group: Age}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"Age": 32 | ||
}`), | ||
// Age is undefined here | ||
(`{ | ||
"Name": "John" | ||
}`), | ||
(`{ | ||
"Name": "Alice", | ||
"Age": 19 | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "Alice", | ||
"_sum": int64(19), | ||
}, | ||
{ | ||
"Name": "John", | ||
"_sum": int64(32), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildEmptyFloatSum(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple query with group by string, sum on non-rendered group float (default) value", | ||
Query: `query { | ||
users(groupBy: [Name]) { | ||
Name | ||
_sum(field: {_group: HeightM}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"HeightM": 1.82 | ||
}`), | ||
(`{ | ||
"Name": "John", | ||
"HeightM": 1.89 | ||
}`), | ||
(`{ | ||
"Name": "Alice" | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": float64(3.71), | ||
}, | ||
{ | ||
"Name": "Alice", | ||
"_sum": float64(0), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} | ||
|
||
func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildFloatSum(t *testing.T) { | ||
test := testUtils.QueryTestCase{ | ||
Description: "Simple query with group by string, sum on non-rendered group float value", | ||
Query: `query { | ||
users(groupBy: [Name]) { | ||
Name | ||
_sum(field: {_group: HeightM}) | ||
} | ||
}`, | ||
Docs: map[int][]string{ | ||
0: { | ||
(`{ | ||
"Name": "John", | ||
"HeightM": 1.82 | ||
}`), | ||
(`{ | ||
"Name": "John", | ||
"HeightM": 1.89 | ||
}`), | ||
(`{ | ||
"Name": "Alice", | ||
"HeightM": 2.04 | ||
}`)}, | ||
}, | ||
Results: []map[string]interface{}{ | ||
{ | ||
"Name": "John", | ||
"_sum": float64(3.71), | ||
}, | ||
{ | ||
"Name": "Alice", | ||
"_sum": float64(2.04), | ||
}, | ||
}, | ||
} | ||
|
||
executeTestCase(t, test) | ||
} |
Oops, something went wrong.