Skip to content

Commit 84d728e

Browse files
Support generalized round/floor/ceil functions.
1 parent 523b272 commit 84d728e

File tree

3 files changed

+91
-11
lines changed

3 files changed

+91
-11
lines changed

src/OpenDiffix.Core.Tests/Expression.Tests.fs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,12 +272,26 @@ module DefaultFunctionsTests =
272272
Null, Null
273273
]
274274

275+
runsBinary
276+
Round
277+
[
278+
Integer 3L, Integer 2L, Integer 4L
279+
Integer 3L, Real 2.5, Real 2.5
280+
Integer 3L, Integer -1L, Null
281+
Real 2.5, Integer 2L, Integer 2L
282+
Real 3.5, Real 2.0, Real 4.0
283+
Integer 1L, Real 0.5, Real 1.0
284+
Real 1.3245, Real 0.5, Real 1.5
285+
]
286+
275287
fails
276288
Round
277289
[ //
278290
[ Integer 5L ]
279291
[ Boolean true ]
280292
[ String "a" ]
293+
[ Integer 5L; String "a" ]
294+
[ String "a"; Real 1.0 ]
281295
]
282296

283297
[<Fact>]
@@ -292,12 +306,26 @@ module DefaultFunctionsTests =
292306
Null, Null
293307
]
294308

309+
runsBinary
310+
Ceil
311+
[
312+
Integer 3L, Integer 2L, Integer 4L
313+
Integer 3L, Real 2.5, Real 5.0
314+
Integer 3L, Integer -1L, Null
315+
Real 2.5, Integer 2L, Integer 4L
316+
Real 3.5, Real 2.0, Real 4.0
317+
Integer 1L, Real 0.5, Real 1.0
318+
Real 1.233, Real 0.5, Real 1.5
319+
]
320+
295321
fails
296322
Ceil
297323
[ //
298324
[ Integer 5L ]
299325
[ Boolean true ]
300326
[ String "a" ]
327+
[ Integer 5L; String "a" ]
328+
[ String "a"; Real 1.0 ]
301329
]
302330

303331
[<Fact>]
@@ -312,12 +340,26 @@ module DefaultFunctionsTests =
312340
Null, Null
313341
]
314342

343+
runsBinary
344+
Floor
345+
[
346+
Integer 3L, Integer 2L, Integer 2L
347+
Integer 3L, Real 2.5, Real 2.5
348+
Integer 3L, Integer -1L, Null
349+
Real 2.5, Integer 2L, Integer 2L
350+
Real 3.5, Real 2.0, Real 2.0
351+
Integer 1L, Real 0.5, Real 1.0
352+
Real 1.3245, Real 0.5, Real 1.0
353+
]
354+
315355
fails
316356
Floor
317357
[ //
318358
[ Integer 5L ]
319359
[ Boolean true ]
320360
[ String "a" ]
361+
[ Integer 5L; String "a" ]
362+
[ String "a"; Real 1.0 ]
321363
]
322364

323365
[<Fact>]

src/OpenDiffix.Core.Tests/QueryEngine.Tests.fs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,18 @@ type Tests(db: DBFixture) =
166166
let queryResult = runQuery "SELECT id FROM products LIMIT 3"
167167
queryResult |> should equal expected
168168

169+
[<Fact>]
170+
let ``query 12 - group with rounding`` () =
171+
let queryResult = runQuery "SELECT round(age, 5), count(*) FROM customers_small GROUP BY 1"
172+
173+
let expected =
174+
{
175+
Columns = [ { Name = "round"; Type = IntegerType }; { Name = "count"; Type = IntegerType } ]
176+
Rows = [ [| Integer 25L; Integer 7L |]; [| Integer 30L; Integer 7L |]; [| Integer 35L; Integer 6L |] ]
177+
}
178+
179+
queryResult |> should equal expected
180+
169181
[<Fact>]
170182
let ``Subquery wrappers produce consistent results`` () =
171183
equivalentQueries

src/OpenDiffix.Core/Expression.fs

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,11 @@ let typeOfScalarFunction fn args =
3333
| Length -> IntegerType
3434
| Round
3535
| Floor
36-
| Ceil -> IntegerType
36+
| Ceil ->
37+
match args with
38+
| [ _ ] -> IntegerType
39+
| [ _; amount ] -> typeOf amount
40+
| _ -> failwith $"Invalid arguments supplied to function `#{fn}`."
3741
| Abs -> args |> List.exactlyOne |> typeOf
3842
| Lower
3943
| Upper
@@ -104,6 +108,38 @@ let rec evaluateScalarFunction fn args =
104108
| And, [ Boolean b1; Boolean b2 ] -> Boolean(b1 && b2)
105109
| Or, [ Boolean b1; Boolean b2 ] -> Boolean(b1 || b2)
106110

111+
| Round, [ Real r ] -> r |> round |> int64 |> Integer
112+
| Round, [ _; Integer amount ] when amount <= 0L -> Null
113+
| Round, [ _; Real amount ] when amount <= 0.0 -> Null
114+
| Round, [ Integer value; Integer amount ] -> (float value / float amount) |> round |> int64 |> (*) amount |> Integer
115+
| Round, [ Integer value; Real amount ] -> (float value / amount) |> round |> (*) amount |> Real
116+
| Round, [ Real value; Integer amount ] -> (value / float amount) |> round |> int64 |> (*) amount |> Integer
117+
| Round, [ Real value; Real amount ] -> (value / amount) |> round |> (*) amount |> Real
118+
119+
| Ceil, [ Real r ] -> r |> ceil |> int64 |> Integer
120+
| Ceil, [ _; Integer amount ] when amount <= 0L -> Null
121+
| Ceil, [ _; Real amount ] when amount <= 0.0 -> Null
122+
| Ceil, [ Integer value; Integer amount ] -> (float value / float amount) |> ceil |> int64 |> (*) amount |> Integer
123+
| Ceil, [ Integer value; Real amount ] -> (float value / amount) |> ceil |> (*) amount |> Real
124+
| Ceil, [ Real value; Integer amount ] -> (value / float amount) |> ceil |> int64 |> (*) amount |> Integer
125+
| Ceil, [ Real value; Real amount ] -> (value / amount) |> ceil |> (*) amount |> Real
126+
127+
| Floor, [ Real r ] -> r |> floor |> int64 |> Integer
128+
| Floor, [ _; Integer amount ] when amount <= 0L -> Null
129+
| Floor, [ _; Real amount ] when amount <= 0.0 -> Null
130+
| Floor, [ Integer value; Integer amount ] -> (float value / float amount) |> floor |> int64 |> (*) amount |> Integer
131+
| Floor, [ Integer value; Real amount ] -> (float value / amount) |> floor |> (*) amount |> Real
132+
| Floor, [ Real value; Integer amount ] -> (value / float amount) |> floor |> int64 |> (*) amount |> Integer
133+
| Floor, [ Real value; Real amount ] -> (value / amount) |> floor |> (*) amount |> Real
134+
135+
| Abs, [ Real r ] -> r |> abs |> Real
136+
| Abs, [ Integer i ] -> i |> abs |> Integer
137+
138+
| WidthBucket, [ Integer v; Integer b; Integer t; Integer c ] ->
139+
widthBucket (float v) (float b) (float t) c |> Integer
140+
| WidthBucket, [ Real v; Real b; Real t; Integer c ] -> widthBucket v b t c |> Integer
141+
142+
// Treat mixed integer/real binary operations as real/real operations.
107143
| _, [ Integer i; Real r ] -> evaluateScalarFunction fn [ Real(double i); Real r ]
108144
| _, [ Real r; Integer i ] -> evaluateScalarFunction fn [ Real r; Real(double i) ]
109145

@@ -124,16 +160,6 @@ let rec evaluateScalarFunction fn args =
124160
| Gt, [ v1; v2 ] -> Boolean(v1 > v2)
125161
| GtE, [ v1; v2 ] -> Boolean(v1 >= v2)
126162

127-
| Round, [ Real r ] -> r |> round |> int64 |> Integer
128-
| Ceil, [ Real r ] -> r |> ceil |> int64 |> Integer
129-
| Floor, [ Real r ] -> r |> floor |> int64 |> Integer
130-
| Abs, [ Real r ] -> r |> abs |> Real
131-
| Abs, [ Integer i ] -> i |> abs |> Integer
132-
133-
| WidthBucket, [ Integer v; Integer b; Integer t; Integer c ] ->
134-
widthBucket (float v) (float b) (float t) c |> Integer
135-
| WidthBucket, [ Real v; Real b; Real t; Integer c ] -> widthBucket v b t c |> Integer
136-
137163
| Length, [ String s ] -> Integer(int64 s.Length)
138164

139165
| Lower, [ String s ] -> String(s.ToLower())

0 commit comments

Comments
 (0)