-- ========================================== -- SPARQL SUM()/AVG() Aggregate Tests -- ========================================== -- Test 1: sum/avg of integers WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+---------------------------------------------------- "60"^^ | "20.0"^^ (1 row) -- Test 2: sum/avg of decimals WITH j (val) AS ( VALUES ('"10.5"^^'::rdfnode), ('"20.3"^^'::rdfnode), ('"30.2"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ----------------------------------------------------+------------------------------------------------------------------- "61.0"^^ | "20.3333333333333333"^^ (1 row) -- Test 3: sum/avg of integer + decimal WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20.5"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ----------------------------------------------------+------------------------------------------------------------------- "60.5"^^ | "20.1666666666666667"^^ (1 row) -- Test 4: sum/avg of decimal + float WITH j (val) AS ( VALUES ('"10.5"^^'::rdfnode), ('"20.3"^^'::rdfnode), ('"5"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+----------------------------------------------------------------- "35.8"^^ | "11.9333333333333333"^^ (1 row) -- Test 5: sum/avg of integer + decimal + double WITH j (val) AS ( VALUES ('"10.4"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30.4"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ---------------------------------------------------+------------------------------------------------------------------ "60.8"^^ | "20.2666666666666667"^^ (1 row) -- Test 6: sum/avg of single value WITH j (val) AS ( VALUES ('"42"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+---------------------------------------------------- "42"^^ | "42.0"^^ (1 row) -- Test 7: sum/avg with integer subtypes (xsd:int, xsd:long) WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+---------------------------------------------------- "60"^^ | "20.0"^^ (1 row) -- Test 8: sum/avg with all four numeric types WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"5.5"^^'::rdfnode), ('"2.5"^^'::rdfnode), ('"3.0"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ---------------------------------------------------+----------------------------------------------------------------- "21.0"^^ | "5.2500000000000000"^^ (1 row) -- Test 9: sum/avg with integer + float (type promotion) WITH j (val) AS ( VALUES ('"100"^^'::rdfnode), ('"0.1"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ---------------------------------------------------+----------------------------------------------------------------- "100.1"^^ | "50.0500000000000000"^^ (1 row) -- Test 10: sum/avg with negative integers WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"-5"^^'::rdfnode), ('"-3"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -------------------------------------------------+---------------------------------------------------------------------- "2"^^ | "0.66666666666666666667"^^ (1 row) -- Test 11: sum/avg resulting in negative value WITH j (val) AS ( VALUES ('"5"^^'::rdfnode), ('"-20"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ---------------------------------------------------+------------------------------------------------------------------- "-15"^^ | "-7.5000000000000000"^^ (1 row) -- Test 12: sum/avg with zero values WITH j (val) AS ( VALUES ('"0"^^'::rdfnode), ('"10"^^'::rdfnode), ('"0"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+------------------------------------------------------------------ "10"^^ | "3.3333333333333333"^^ (1 row) -- Test 13: sum/avg resulting in zero WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"-10"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -------------------------------------------------+--------------------------------------------------- "0"^^ | "0.0"^^ (1 row) -- Test 14: sum/avg with NULL values WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), (NULL::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+---------------------------------------------------- "40"^^ | "20.0"^^ (1 row) -- Test 15: sum/avg of all NULLs WITH j (val) AS ( VALUES (NULL::rdfnode), (NULL::rdfnode), (NULL::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 16: sum/avg of empty set (no rows) WITH j (val) AS ( VALUES ('"10"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j WHERE val IS NULL; sum | avg -----+----- | (1 row) -- Test 17: sum/avg with xsd:string mixed in WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 18: sum/avg with non-numeric only WITH j (val) AS ( VALUES ('"not-a-number"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 19: sum/avg on multiple xsd:string WITH j (val) AS ( VALUES ('"apple"^^'::rdfnode), ('"banana"^^'::rdfnode) ) SELECT sparql.avg(val), sparql.sum(val) FROM j; avg | sum -----+----- | (1 row) -- Test 20: sum/avg on xsd:date WITH j (val) AS ( VALUES ('"2023-01-01"^^'::rdfnode), ('"2023-06-15"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 21: sum/avg on xsd:dateTime WITH j (val) AS ( VALUES ('"2023-01-01T10:30:00"^^'::rdfnode), ('"2023-06-15T15:45:00"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 22: sum/avg on xsd:time WITH j (val) AS ( VALUES ('"10:30:00"^^'::rdfnode), ('"15:45:00"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 23: sum/avg on xsd:duration WITH j (val) AS ( VALUES ('"P1Y"^^'::rdfnode), ('"P2M"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 24: sum/avg on xsd:boolean WITH j (val) AS ( VALUES ('"true"^^'::rdfnode), ('"false"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 25: sum/avg with mixed numeric and xsd:date WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"2023-01-01"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- Test 26: sum/avg with mixed numeric and xsd:string WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"text"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -----+----- | (1 row) -- ========================================== -- SPARQL MIN/MAX() Aggregate Tests -- ========================================== -- Test 27: min/max of integers WITH j (val) AS ( VALUES ('"30"^^'::rdfnode), ('"10"^^'::rdfnode), ('"20"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "10"^^ | "30"^^ (1 row) -- Test 28: min/max of decimals WITH j (val) AS ( VALUES ('"30.2"^^'::rdfnode), ('"10.5"^^'::rdfnode), ('"20.3"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+---------------------------------------------------- "10.5"^^ | "30.2"^^ (1 row) -- Test 29: min/max of integer + decimal WITH j (val) AS ( VALUES ('"30"^^'::rdfnode), ('"10.5"^^'::rdfnode), ('"20"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+-------------------------------------------------- "10.5"^^ | "30"^^ (1 row) -- Test 30: min/max with float values WITH j (val) AS ( VALUES ('"30.5"^^'::rdfnode), ('"10.1"^^'::rdfnode), ('"20.3"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "10.1"^^ | "30.5"^^ (1 row) -- Test 31: min/max with mixed types WITH j (val) AS ( VALUES ('"30"^^'::rdfnode), ('"5.5"^^'::rdfnode), ('"10.0"^^'::rdfnode), ('"20.0"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ---------------------------------------------------+-------------------------------------------------- "5.5"^^ | "30"^^ (1 row) -- Test 32: min/max of single value WITH j (val) AS ( VALUES ('"42"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "42"^^ | "42"^^ (1 row) -- Test 33: min/max with negative integers WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"-5"^^'::rdfnode), ('"3"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "-5"^^ | "10"^^ (1 row) -- Test 34: min/max with all negative values WITH j (val) AS ( VALUES ('"-10"^^'::rdfnode), ('"-5"^^'::rdfnode), ('"-20"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ---------------------------------------------------+-------------------------------------------------- "-20"^^ | "-5"^^ (1 row) -- Test 35: min/max with zero values WITH j (val) AS ( VALUES ('"0"^^'::rdfnode), ('"10"^^'::rdfnode), ('"-5"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "-5"^^ | "10"^^ (1 row) -- Test 36: min/max with NULL values WITH j (val) AS ( VALUES ('"30"^^'::rdfnode), (NULL::rdfnode), ('"10"^^'::rdfnode), (NULL::rdfnode), ('"20"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "10"^^ | "30"^^ (1 row) -- Test 37: min/max of all NULLs WITH j (val) AS ( VALUES (NULL::rdfnode), (NULL::rdfnode), (NULL::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -----+----- | (1 row) -- Test 38: min/max of empty set (no rows) WITH j (val) AS ( VALUES ('"10"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j WHERE val IS NULL; min | max -----+----- | (1 row) -- Test 39: min/max with equal values WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"10.0"^^'::rdfnode), ('"10"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "10"^^ | "10"^^ (1 row) -- Test 40: min/max on multiple strings WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"apple"^^'::rdfnode), ('"mango"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+---------------------------------------------------- "apple"^^ | "zebra"^^ (1 row) -- Test 41: min/max on dates WITH j (val) AS ( VALUES ('"2023-06-15"^^'::rdfnode), ('"2021-01-01"^^'::rdfnode), ('"2025-12-31"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -------------------------------------------------------+------------------------------------------------------- "2021-01-01"^^ | "2025-12-31"^^ (1 row) -- Test 42: min/max on single non-numeric value → should return that value WITH j (val) AS ( VALUES ('"single-string"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ------------------------------------------------------------+------------------------------------------------------------ "single-string"^^ | "single-string"^^ (1 row) -- Test 43: min/max with numeric + string WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"42"^^'::rdfnode), ('"mango"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+-------------------------------------------------- "mango"^^ | "42"^^ (1 row) -- Test 44: min/max with numeric + date WITH j (val) AS ( VALUES ('"2023-06-15"^^'::rdfnode), ('"100"^^'::rdfnode), ('"2021-01-01"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ---------------------------------------------------+------------------------------------------------------- "100"^^ | "2023-06-15"^^ (1 row) -- Test 45: min/max with date + string WITH j (val) AS ( VALUES ('"apple"^^'::rdfnode), ('"2023-06-15"^^'::rdfnode), ('"zebra"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+------------------------------------------------------- "apple"^^ | "2023-06-15"^^ (1 row) -- Test 46: min/max with numeric + dateTime WITH j (val) AS ( VALUES ('"2023-06-15T10:30:00"^^'::rdfnode), ('"5"^^'::rdfnode), ('"2021-01-01T00:00:00"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -------------------------------------------------+-------------------------------------------------------------------- "5"^^ | "2023-06-15T10:30:00"^^ (1 row) -- Test 47: min/max with multiple category types WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"42"^^'::rdfnode), ('"2023-06-15"^^'::rdfnode), ('"10:30:00"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+----------------------------------------------------- "zebra"^^ | "10:30:00"^^ (1 row) -- Test 48: min/max with IRI + numeric + string WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"42"^^'::rdfnode), (''::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ---------------------------------+-------------------------------------------------- | "42"^^ (1 row) -- Test 49: min/max with lang-tagged + numeric WITH j (val) AS ( VALUES ('"42"^^'::rdfnode), ('"hello"@en'::rdfnode), ('"100"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ------------+--------------------------------------------------- "hello"@en | "100"^^ (1 row) -- Test 50: min/max with plain literal + numeric WITH j (val) AS ( VALUES ('"42"^^'::rdfnode), ('"plain-text"'::rdfnode), ('"100"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------+--------------------------------------------------- "plain-text" | "100"^^ (1 row) -- Test 51: min/max with time + duration WITH j (val) AS ( VALUES ('"P1Y"^^'::rdfnode), ('"10:30:00"^^'::rdfnode), ('"P2M"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -----------------------------------------------------+---------------------------------------------------- "10:30:00"^^ | "P1Y"^^ (1 row) -- Test 52: min/max with comprehensive mix (IRI, lang, plain, numeric, temporal, string) WITH j (val) AS ( VALUES ('"string-value"^^'::rdfnode), (''::rdfnode), ('"42"^^'::rdfnode), ('"labeled"@en'::rdfnode), ('"plain"'::rdfnode), ('"2023-06-15"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -------------------------+------------------------------------------------------- | "2023-06-15"^^ (1 row) -- Test 53: min/max with multiple numerics of different types in mix WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"5.5"^^'::rdfnode), ('"100"^^'::rdfnode), ('"2023-01-01"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+------------------------------------------------------- "zebra"^^ | "2023-01-01"^^ (1 row) -- Test 54: min/max with multiple temporals of different types WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"2023-06-15"^^'::rdfnode), ('"2025-12-31"^^'::rdfnode), ('"2021-01-01T00:00:00"^^'::rdfnode), ('"apple"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+------------------------------------------------------- "apple"^^ | "2025-12-31"^^ (1 row) -- Test 55: min/max with NULL in mixed-type set WITH j (val) AS ( VALUES ('"zebra"^^'::rdfnode), ('"42"^^'::rdfnode), (NULL::rdfnode), ('"2023-06-15"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ----------------------------------------------------+------------------------------------------------------- "zebra"^^ | "2023-06-15"^^ (1 row) -- ========================================== -- SPARQL GROUP_CONCAT() Aggregate Tests -- ========================================== -- Test 56: GROUP_CONCAT with default separator (space) WITH j (val) AS ( VALUES ('"apple"^^'::rdfnode), ('"banana"^^'::rdfnode), ('"cherry"^^'::rdfnode) ) SELECT sparql.group_concat(val, ' ') FROM j; group_concat ----------------------- "apple banana cherry" (1 row) -- Test 57: GROUP_CONCAT with custom separator (comma) WITH j (val) AS ( VALUES ('"apple"^^'::rdfnode), ('"banana"^^'::rdfnode), ('"cherry"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat ------------------------- "apple, banana, cherry" (1 row) -- Test 58: GROUP_CONCAT with integers WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.group_concat(val, '-') FROM j; group_concat -------------- "10-20-30" (1 row) -- Test 59: GROUP_CONCAT with mixed types WITH j (val) AS ( VALUES ('"42"^^'::rdfnode), ('"hello"^^'::rdfnode), ('"3.14"^^'::rdfnode) ) SELECT sparql.group_concat(val, ' | ') FROM j; group_concat --------------------- "42 | hello | 3.14" (1 row) -- Test 60: GROUP_CONCAT with IRIs WITH j (val) AS ( VALUES (''::rdfnode), (''::rdfnode), (''::rdfnode) ) SELECT sparql.group_concat(val, '; ') FROM j; group_concat -------------------------------------------------------------------------------------------- "http://example.org/resource1; http://example.org/resource2; http://example.org/resource3" (1 row) -- Test 61: GROUP_CONCAT with language-tagged strings WITH j (val) AS ( VALUES ('"hello"@en'::rdfnode), ('"bonjour"@fr'::rdfnode), ('"hola"@es'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat ------------------------ "hello, bonjour, hola" (1 row) -- Test 62: GROUP_CONCAT with NULL value WITH j (val) AS ( VALUES ('"apple"^^'::rdfnode), (NULL::rdfnode), ('"cherry"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat ----------------- "apple, cherry" (1 row) -- Test 63: GROUP_CONCAT with all NULL WITH j (val) AS ( VALUES (NULL::rdfnode), (NULL::rdfnode), (NULL::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat -------------- (1 row) -- Test 64: GROUP_CONCAT with empty set SELECT sparql.group_concat(val, ', ') FROM (SELECT NULL::rdfnode AS val WHERE false) AS j; group_concat -------------- (1 row) -- Test 65: GROUP_CONCAT with single value WITH j (val) AS ( VALUES ('"only-one"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat -------------- "only-one" (1 row) -- Test 66: GROUP_CONCAT with dates WITH j (val) AS ( VALUES ('"2024-01-15"^^'::rdfnode), ('"2024-02-20"^^'::rdfnode), ('"2024-03-25"^^'::rdfnode) ) SELECT sparql.group_concat(val, ' to ') FROM j; group_concat ------------------------------------------ "2024-01-15 to 2024-02-20 to 2024-03-25" (1 row) -- Test 67: GROUP_CONCAT with booleans WITH j (val) AS ( VALUES ('"true"^^'::rdfnode), ('"false"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat --------------- "true, false" (1 row) -- Test 68: GROUP_CONCAT with empty string separator WITH j (val) AS ( VALUES ('"a"^^'::rdfnode), ('"b"^^'::rdfnode), ('"c"^^'::rdfnode) ) SELECT sparql.group_concat(val, '') FROM j; group_concat -------------- "abc" (1 row) -- Test 69: GROUP_CONCAT with newline separator WITH j (val) AS ( VALUES ('"line1"^^'::rdfnode), ('"line2"^^'::rdfnode), ('"line3"^^'::rdfnode) ) SELECT sparql.group_concat(val, E'\n') FROM j; group_concat -------------- "line1 + line2 + line3" (1 row) -- Test 70: GROUP_CONCAT with very long separator WITH j (val) AS ( VALUES ('"first"^^'::rdfnode), ('"second"^^'::rdfnode) ) SELECT sparql.group_concat(val, ' --- SEPARATOR --- ') FROM j; group_concat ---------------------------------- "first --- SEPARATOR --- second" (1 row) -- Test 71: GROUP_CONCAT with decimals WITH j (val) AS ( VALUES ('"10.50"^^'::rdfnode), ('"20.30"^^'::rdfnode), ('"30.20"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat ----------------------- "10.50, 20.30, 30.20" (1 row) -- ========================================== -- SPARQL SAMPLE() Aggregate Tests -- ========================================== -- Test 72: SAMPLE with single integer value WITH j (val) AS ( VALUES ('"42"^^'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------------------------------------------------- "42"^^ (1 row) -- Test 73: SAMPLE with multiple integers WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30"^^'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------------------------------------------------- "10"^^ (1 row) -- Test 74: SAMPLE with NULLs at start WITH j (val) AS ( VALUES (NULL::rdfnode), (NULL::rdfnode), ('"42"^^'::rdfnode), ('"99"^^'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------------------------------------------------- "42"^^ (1 row) -- Test 75: SAMPLE with all NULLs WITH j (val) AS ( VALUES (NULL::rdfnode), (NULL::rdfnode), (NULL::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------- (1 row) -- Test 76: SAMPLE with empty set WITH j (val) AS ( SELECT NULL::rdfnode WHERE false ) SELECT sparql.sample(val) FROM j; sample -------- (1 row) -- Test 77: SAMPLE with mixed numeric types WITH j (val) AS ( VALUES ('"10.5"^^'::rdfnode), ('"20"^^'::rdfnode), ('"30.7"^^'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample ---------------------------------------------------- "10.5"^^ (1 row) -- Test 78: SAMPLE with strings WITH j (val) AS ( VALUES ('"apple"'::rdfnode), ('"banana"'::rdfnode), ('"cherry"'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample --------- "apple" (1 row) -- Test 79: SAMPLE with IRIs WITH j (val) AS ( VALUES (''::rdfnode), (''::rdfnode), (''::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------------------------------- (1 row) -- Test 80: SAMPLE with language-tagged literals WITH j (val) AS ( VALUES ('"hello"@en'::rdfnode), ('"bonjour"@fr'::rdfnode), ('"hola"@es'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample ------------ "hello"@en (1 row) -- Test 81: SAMPLE with mixed types (IRI, literal, numeric) → should return first value WITH j (val) AS ( VALUES (''::rdfnode), ('"some text"'::rdfnode), ('"42"^^'::rdfnode), ('"hello"@en'::rdfnode) ) SELECT sparql.sample(val) FROM j; sample -------------------------------- (1 row) /* == Corner Cases == */ -- Test 82: sum/avg with very large integers near PostgreSQL numeric limits WITH j (val) AS ( VALUES ('"999999999999999999999999999"^^'::rdfnode), ('"1"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg ----------------------------------------------------------------------------+----------------------------------------------------------------------------- "1000000000000000000000000000"^^ | "500000000000000000000000000.0"^^ (1 row) -- Test 83: sum/avg with infinity WITH j (val) AS ( VALUES ('"INF"^^'::rdfnode), ('"10"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg -------------------------------------------------------+------------------------------------------------------- "Infinity"^^ | "Infinity"^^ (1 row) -- Test 84: sum/avg with NaN WITH j (val) AS ( VALUES ('"NaN"^^'::rdfnode), ('"10"^^'::rdfnode) ) SELECT sparql.sum(val), sparql.avg(val) FROM j; sum | avg --------------------------------------------------+-------------------------------------------------- "NaN"^^ | "NaN"^^ (1 row) -- Test 85: min/max with blank nodes WITH j (val) AS ( VALUES ('_:b1'::rdfnode), ('_:b2'::rdfnode), ('"42"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ------+-------------------------------------------------- _:b1 | "42"^^ (1 row) -- Test 86: min/max with same text, different languages WITH j (val) AS ( VALUES ('"hello"@en'::rdfnode), ('"hello"@en-US'::rdfnode), ('"hello"@en-GB'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max ------------+--------------- "hello"@en | "hello"@en-US (1 row) -- Test 87: GROUP_CONCAT with quotes, separators in values WITH j (val) AS ( VALUES ('"text with ""quotes"""^^'::rdfnode), ('"text, with, commas"^^'::rdfnode) ) SELECT sparql.group_concat(val, ', ') FROM j; group_concat -------------------------------------------- "text with \"quotes\", text, with, commas" (1 row) -- Test 88: min/max when 10 (int) vs 10.0 (decimal) vs 10.0 (float) WITH j (val) AS ( VALUES ('"10"^^'::rdfnode), ('"10.0"^^'::rdfnode), ('"10.0"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max --------------------------------------------------+-------------------------------------------------- "10"^^ | "10"^^ (1 row) -- Test 89: min/max with empty strings and whitespace WITH j (val) AS ( VALUES ('""^^'::rdfnode), ('" "^^'::rdfnode), ('"a"^^'::rdfnode) ) SELECT sparql.min(val), sparql.max(val) FROM j; min | max -----------------------------------------------+------------------------------------------------ ""^^ | "a"^^ (1 row)