diff --git a/src/test/java/org/mobilitydb/spark/AggregatesCatalogTest.java b/src/test/java/org/mobilitydb/spark/AggregatesCatalogTest.java index bba52063..6827e146 100644 --- a/src/test/java/org/mobilitydb/spark/AggregatesCatalogTest.java +++ b/src/test/java/org/mobilitydb/spark/AggregatesCatalogTest.java @@ -41,9 +41,9 @@ /** * Every aggregate overload the typed Spark SQL surface registers, over two rows of sample values, * against the answer MobilityDB gives over the same rows in the time zone UTC; and the names it - * registers, the catalog's but for the raster aggregates, which #_catalog_aggregates of JMEOS's - * codegen_jvm.py leaves out. A value whose text carries a coordinate or a float is written with - * six decimals, as MobilityDuck's test/sql/aggregates_catalog.test writes it over the same rows. + * registers, every aggregate name of the catalog. A value whose text carries a coordinate or a + * float is written with six decimals, as MobilityDuck's test/sql/aggregates_catalog.test writes it + * over the same rows. */ class AggregatesCatalogTest { @@ -70,8 +70,13 @@ static void stopSpark() { } } + /** The value of the query's first row. */ + private static Object value(String sql) { + return spark.sql(sql).collectAsList().get(0).get(0); + } + private static String answer(String sql) { - return (String) spark.sql(sql).collectAsList().get(0).get(0); + return (String) value(sql); } /** Each aggregate name of the catalog the surface registers, registered. */ @@ -81,9 +86,12 @@ Stream theNameIsRegistered() { "appendSequenceAgg", "extent", "mergeAgg", + "rasterUnion", + "sameAlignmentAgg", "setUnionAgg", "spanUnionAgg", "spansetUnionAgg", + "summaryStatsAgg", "tAndAgg", "tAvg", "tCentroid", @@ -102,12 +110,6 @@ Stream theNameIsRegistered() { .map(name -> DynamicTest.dynamicTest(name, () -> assertEquals(true, spark.catalog().functionExists(name)))); } - /** Each aggregate name of the catalog whose every entry is over a raster, not registered. */ - @TestFactory - Stream theNameIsNotRegistered() { - return Stream.of("rasterUnion", "sameAlignmentAgg", "summaryStatsAgg") - .map(name -> DynamicTest.dynamicTest(name, () -> assertEquals(false, spark.catalog().functionExists(name)))); - } /** Each overload: its signature, its query over two rows, and MobilityDB's answer. */ private static final String[][] OVERLOADS = { @@ -540,6 +542,21 @@ Stream theNameIsNotRegistered() { {"mergeAgg(ttext)", "SELECT asText(mergeAgg(v)) FROM (SELECT /*+ REPARTITION(2) */ ttextFromText(s) AS v FROM VALUES ('\"a\"@2020-01-01'), ('\"b\"@2020-01-02') AS t(s))", "{\"a\"@2020-01-01 00:00:00+00, \"b\"@2020-01-02 00:00:00+00}"}, + {"rasterUnion(raster)", + "SELECT rasterAsHexWKB(rasterUnion(v), 'NDR') FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + "0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000060003004A003C1CC60000803F00000040000040400000803F000000400000404000008040003C1CC60000C04000008040003C1CC60000C0400000E04000000041000010410000E04000000041000010414600000A0014001E000A0014001E00280032003C00280032003C00460050005A00460050005A00"}, + {"rasterUnion(raster, INT)", + "SELECT rasterAsHexWKB(rasterUnion(v, 2), 'NDR') FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + "0100000100000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000060003004600000A0014001E000A0014001E00280032003C00280032003C00460050005A00460050005A00"}, + {"rasterUnion(raster, VARCHAR)", + "SELECT rasterAsHexWKB(rasterUnion(v, 'MAX'), 'NDR') FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + "0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000060003004A003C1CC60000803F00000040000040400000803F000000400000404000008040003C1CC60000C04000008040003C1CC60000C0400000E04000000041000010410000E04000000041000010414600000A0014001E000A0014001E00280032003C00280032003C00460050005A00460050005A00"}, + {"rasterUnion(raster, INT, VARCHAR)", + "SELECT rasterAsHexWKB(rasterUnion(v, 1, 'SUM'), 'NDR') FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + "0100000100000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000060003004A003C1CC60000803F00000040000040400000803F000000400000404000008040003C1CC60000C04000008040003C1CC60000C0400000E04000000041000010410000E0400000004100001041"}, + {"sameAlignmentAgg(raster)", + "SELECT CASE WHEN sameAlignmentAgg(v) THEN 'true' ELSE 'false' END FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + "true"}, {"setUnionAgg(cbuffer)", "SELECT asText(setUnionAgg(v), 6) FROM (SELECT /*+ REPARTITION(2) */ cbufferFromText(s) AS v FROM VALUES ('Cbuffer(Point(1 1),0.5)'), ('Cbuffer(Point(2 2),0.5)') AS t(s))", "{\"Cbuffer(POINT(1 1),0.5)\", \"Cbuffer(POINT(2 2),0.5)\"}"}, @@ -906,4 +923,27 @@ Stream theOverloadAnswersWhatMobilityDBAnswers() { return Stream.of(OVERLOADS) .map(c -> DynamicTest.dynamicTest(c[0], () -> assertEquals(c[2], answer(c[1])))); } + + /** Each overload of summaryStatsAgg: its query over the two rasters of the raster cases + * of #OVERLOADS and the six fields of the summarystats record MobilityDB answers, count, + * sum, mean, standard deviation, minimum and maximum, read here in the order of the + * record, as no SQL function of the surface reads a field of it. */ + private static final Object[][] SUMMARIES = { + {"summaryStatsAgg(raster, BOOLEAN)", + "SELECT summaryStatsAgg(v, true) FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + new double[] {16, 80, 5, 2.7386127875258306, 1, 9}}, + {"summaryStatsAgg(raster, INT, BOOLEAN)", + "SELECT summaryStatsAgg(v, 2, true) FROM (SELECT /*+ REPARTITION(2) */ rasterFromHexWKB(s) AS v FROM VALUES ('0100000200000000000000F03F000000000000F0BF0000000000000000000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00'), ('0100000200000000000000F03F000000000000F0BF0000000000000840000000000000084000000000000000000000000000000000110F0000030003004A003C1CC60000803F000000400000404000008040003C1CC60000C0400000E04000000041000010410600000A0014001E00280032003C00460050005A00') AS t(s))", + new double[] {18, 900, 50, 25.81988897471611, 10, 90}}}; + + @TestFactory + Stream theSummaryAnswersWhatMobilityDBAnswers() { + return Stream.of(SUMMARIES) + .map(c -> DynamicTest.dynamicTest((String) c[0], () -> { + double[] expected = (double[]) c[2]; + for (int i = 0; i < expected.length; i++) { + assertEquals(expected[i], ((Number) ((org.apache.spark.sql.Row) value((String) c[1])).get(i)).doubleValue(), "field " + i); + } + })); + } }