Commits

Kirill Simonov committed 34e9a59

Added tests for aggregates.

  • Participants
  • Parent commits 1352982

Comments (0)

Files changed (3)

test/input/library.yaml

            null()==null(), null()!==null()}
   # Coercion
   - uri: /{7=0.7e1, '13'=13.0, '13'!=='13.0'}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{true()=1}
     expect: 400
   - uri: /{'cinq'!=4.9}
   - uri: /{0<null(), ''>null(), null()>=null()}
   # Coercion
   - uri: /{175e-2>'875e-3', '2010-04-15'>=date('1991-08-20')}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{false()<true()}
     expect: 400
   - uri: /{'cinq'>4.9}
            null_if(null(), null())}
   # Coercion
   - uri: /{if_null(1, 0.1e1), null_if(1, 0.1e1)}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{if_null('cinq', 5)}
     expect: 400
   - uri: /{null_if('cinq', 5)}
   - uri: /{switch(date('2010-04-15'),
                   '1991-08-20', 'WWW',
                   '2010-04-15', 'HTSQL')}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{if('', 'then', 'else')}
     expect: 400
   - uri: /{switch(1, date('2010-04-15'), 1, date('1991-08-20'), 2)}
   - uri: /{integer(string('60'))}
   - uri: /{decimal(string('2.125'))}
   - uri: /{float(string('271828e-5'))}
-  # Incompatible operand
+  # Inadmissible operand
   - uri: /{integer('cinq')}
     expect: 400
   - uri: /{decimal(true())}
   - uri: /{7-2.125, 7-271828e-5, 2.125-271828e-5}
   - uri: /{7*2.125, 7*271828e-5, 2.125*271828e-5}
   - uri: /{7/2.125, 7/271828e-5, 2.125/271828e-5}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{'cinq'+7}
     expect: 400
   - uri: /{2.125-date('2010-04-15')}
   - uri: /{round(9973)}
   - uri: /{round(9973,-2)}
     ifndef: sqlite
-  # Incompatible operand
+  # Inadmissible operand
   - uri: /{round(271828e-5,2)}
     expect: 400
     ifndef: sqlite
     skip: true
   - uri: /{length(null())}
     skip: true
-  # Incompatible operand
+  # Inadmissible operand
   - uri: /{length(date(2010-04-15))}
     expect: 400
 
   - uri: /{'OMG'+'WTF'+'BBQ'}
   - uri: /{null()+'LOL', 'LOL'+null(),
            string(null())+string(null())}
-  # Incompatible operands
+  # Inadmissible operands
   - uri: /{string('LOL')+7}
     expect: 400
 
 
   # Conversion
   - uri: /{date(null()), date('2010-04-15')}
-  # Incompatible operand
+  # Inadmissible operand
   - uri: /{date('2010-13-07')}
     expect: 400
   - uri: /{date(true())}
            date('2010-04-15')-date('1991-08-20')}
     skip: true
 
+########################################################################
+
+- title: Aggregate functions
+  tests:
+
+  # Exists, Every, Count
+  - uri: /course?department='lang'
+  - uri: /{exists(course?department='lang'),
+           every(course?department='lang'),
+           count(course?department='lang')}
+  # Applied to an empty set
+  - uri: /course?department='str'
+  - uri: /{exists(course?department='str'),
+           every(course?department='str'),
+           count(course?department='str')}
+  # Applied to all-TRUE, all-FALSE, mixed sets
+  - uri: /course{department,number,credits,credits>3}
+                ?department={'me','mth','phys'}
+  - uri: /{exists(course{credits>3}?department='me'),
+           every(course{credits>3}?department='me'),
+           count(course{credits>3}?department='me')}
+  - uri: /{exists(course{credits>3}?department='mth'),
+           every(course{credits>3}?department='mth'),
+           count(course{credits>3}?department='mth')}
+  - uri: /{exists(course{credits>3}?department='phys'),
+           every(course{credits>3}?department='phys'),
+           count(course{credits>3}?department='phys')}
+  # Coercion
+  - uri: /department{code,school,boolean(school)}
+  - uri: /{exists(department{school}),
+           every(department{school}),
+           count(department{school})}
+  # Singular operand
+  - uri: /{exists(true())}
+    expect: 400
+  - uri: /{every(true())}
+    expect: 400
+  - uri: /{count(true())}
+    expect: 400
+
+  # Min, Max
+  - uri: /course{number,credits}?department='be'
+  - uri: /{min(course{credits}?department='be'),
+           max(course{credits}?department='be')}
+  # Applied to an empty set
+  - uri: /course?department='str'
+  - uri: /{min(course{credits}?department='str'),
+           max(course{credits}?department='str')}
+  # Non-numeric operands
+  - uri: /{min(student.dob), max(student.dob)}
+  - uri: /{min(student.name), max(student.name)}
+  # Inadmissible operand
+  - uri: /{min(student.is_active), max(student.is_active)}
+    expect: 400
+
+  # Sum, Avg
+  - uri: /{sum(course{credits}?department='be'),
+           count(course{credits}?department='be'),
+           avg(course{credits}?department='be')}
+  # Applied to an empty set
+  - uri: /{sum(course{credits}?department='str'),
+           count(course{credits}?department='str'),
+           avg(course{credits}?department='str')}
+  # Inadmissible operands
+  - uri: /{sum(student.dob)}
+    expect: 400
+  - uri: /{avg(student.name)}
+    expect: 400
+
+########################################################################
+
+- title: Table functions and operators
+  tests: []
+
+- title: Decorators
+  tests: []
+
+
 
 
 # FIXME: update and refurbish!

test/output/pgsql.yaml

             :
                 /{date(string('2010-13-07'))}
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+      - id: aggregate-functions
+        tests:
+        - uri: /course?department='lang'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='lang')                                                                      |
+            -+-------------------------------------------------------------------------------------------------+-
+             | department | number | title                        | credits | description                      |
+            -+------------+--------+------------------------------+---------+----------------------------------+-
+             | lang       |    201 | Introduction to Spanish      |       4 | Introduction to the Spanish      |
+             :            :        :                              :         : language, with an emphasis on    :
+             :            :        :                              :         : every day conversation and basic :
+             :            :        :                              :         : grammar.                         :
+             | lang       |    203 | Intermediate Spanish         |       3 | Continuation of fundamental      |
+             :            :        :                              :         : Spanish language learning,       :
+             :            :        :                              :         : including verb tenses, reading   :
+             :            :        :                              :         : skills, and basic conversation.  :
+             | lang       |    207 | Child Second Language        |       3 | Examines issues in child second  |
+             :            :        : Development                  :         : language acquisition, including  :
+             :            :        :                              :         : the critical period hypothesis   :
+             :            :        :                              :         : and universal grammar.           :
+             | lang       |    304 | Spanish Conversation Group   |       2 | Informal weekly conversation     |
+             :            :        :                              :         : group designed to improve        :
+             :            :        :                              :         : understanding of spoken Spanish. :
+             :            :        :                              :         : Suitable for both majors and     :
+             :            :        :                              :         : casual speakers who wish to      :
+             :            :        :                              :         : improve their skills for         :
+             :            :        :                              :         : personal enjoyment or travel.    :
+             | lang       |    305 | Second Language Syntax       |       3 | This course examines the form    |
+             :            :        :                              :         : and acquisition of nonnative     :
+             :            :        :                              :         : syntax. Consideration of whether :
+             :            :        :                              :         : nonnative grammars are           :
+             :            :        :                              :         : fundamentally different than     :
+             :            :        :                              :         : native grammars.                 :
+                                                                                                        (5 rows)
+
+             ----
+             /course?department='lang'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'lang')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course?department='lang'), every(course?department='lang'),
+            count(course?department='lang')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                      |
+            -+------------------------------------------------------------------------------------------------------+-
+             | exists(course?department='lang') | every(course?department='lang') | count(course?department='lang') |
+            -+----------------------------------+---------------------------------+---------------------------------+-
+             | true                             | true                            |                               5 |
+                                                                                                              (1 row)
+
+             ----
+             /{exists(course?department='lang'),every(course?department='lang'),count(course?department='lang')}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."course" AS "course_1"
+                           WHERE ("course_1"."department" = 'lang')),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."course" AS "course_1"
+                                WHERE FALSE
+                                      AND ("course_1"."department" = 'lang'))),
+                    COUNT(TRUE)
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'lang')
+        - uri: /course?department='str'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='str')                           |
+            -+-----------------------------------------------------+-
+             | department | number | title | credits | description |
+            -+------------+--------+-------+---------+-------------+-
+                                                           (no rows)
+
+             ----
+             /course?department='str'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'str')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course?department='str'), every(course?department='str'),
+            count(course?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                   |
+            -+---------------------------------------------------------------------------------------------------+-
+             | exists(course?department='str') | every(course?department='str') | count(course?department='str') |
+            -+---------------------------------+--------------------------------+--------------------------------+-
+             | false                           | true                           |                              0 |
+                                                                                                           (1 row)
+
+             ----
+             /{exists(course?department='str'),every(course?department='str'),count(course?department='str')}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."course" AS "course_1"
+                           WHERE ("course_1"."department" = 'str')),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."course" AS "course_1"
+                                WHERE FALSE
+                                      AND ("course_1"."department" = 'str'))),
+                    COUNT(TRUE)
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /course{department,number,credits,credits>3} ?department={'me','mth','phys'}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department={'me','mth','phys'})   |
+            -+-------------------------------------------+-
+             | department | number | credits | credits>3 |
+            -+------------+--------+---------+-----------+-
+             | me         |    111 |       3 | false     |
+             | me         |    344 |       4 | true      |
+             | me         |    501 |       3 | false     |
+             | me         |    627 |       4 | true      |
+             | me         |    712 |       3 | false     |
+             | mth        |    101 |       5 | true      |
+             | phys       |    211 |       3 | false     |
+             | phys       |    303 |       3 | false     |
+             | phys       |    388 |       2 | false     |
+             | phys       |    512 |       3 | false     |
+             | phys       |    713 |       3 | false     |
+             | phys       |    819 |       3 | false     |
+                                                 (12 rows)
+
+             ----
+             /course{department,number,credits,credits>3}?department={'me','mth','phys'}
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."credits",
+                    ("course"."credits" > 3)
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" IN ('me', 'mth', 'phys'))
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course{credits>3}?department='me'), every(course{credits>3}?department='me'),
+            count(course{credits>3}?department='me')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                 |
+            -+---------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='me') | every(course{credits>3}?department='me') | count(course{credits>3}?department='me') |
+            -+-------------------------------------------+------------------------------------------+------------------------------------------+-
+             | true                                      | false                                    |                                        2 |
+                                                                                                                                         (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='me'),every(course{credits>3}?department='me'),count(course{credits>3}?department='me')}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'me')),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'me'))),
+                    COUNT(NULLIF(("course"."credits" > 3), FALSE))
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'me')
+        - uri: /{exists(course{credits>3}?department='mth'), every(course{credits>3}?department='mth'),
+            count(course{credits>3}?department='mth')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                    |
+            -+------------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='mth') | every(course{credits>3}?department='mth') | count(course{credits>3}?department='mth') |
+            -+--------------------------------------------+-------------------------------------------+-------------------------------------------+-
+             | true                                       | true                                      |                                         1 |
+                                                                                                                                            (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='mth'),every(course{credits>3}?department='mth'),count(course{credits>3}?department='mth')}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'mth')),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'mth'))),
+                    COUNT(NULLIF(("course"."credits" > 3), FALSE))
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'mth')
+        - uri: /{exists(course{credits>3}?department='phys'), every(course{credits>3}?department='phys'),
+            count(course{credits>3}?department='phys')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                       |
+            -+---------------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='phys') | every(course{credits>3}?department='phys') | count(course{credits>3}?department='phys') |
+            -+---------------------------------------------+--------------------------------------------+--------------------------------------------+-
+             | false                                       | false                                      |                                          0 |
+                                                                                                                                               (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='phys'),every(course{credits>3}?department='phys'),count(course{credits>3}?department='phys')}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'phys')),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'phys'))),
+                    COUNT(NULLIF(("course"."credits" > 3), FALSE))
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'phys')
+        - uri: /department{code,school,boolean(school)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | department                        |
+            -+-----------------------------------+-
+             | code   | school | boolean(school) |
+            -+--------+--------+-----------------+-
+             | acc    | bus    | true            |
+             | arthis | art    | true            |
+             | astro  | ns     | true            |
+             | be     | egn    | true            |
+             | bursar |        | false           |
+             | capmrk | bus    | true            |
+             | career |        | false           |
+             | chem   | ns     | true            |
+             | comp   | egn    | true            |
+             | corpfi | bus    | true            |
+             | edpol  | edu    | true            |
+             | ee     | egn    | true            |
+             | eng    | la     | true            |
+             | hist   | la     | true            |
+             | lang   | la     | true            |
+             | me     | egn    | true            |
+             | mth    | ns     | true            |
+             | parent |        | false           |
+             | phys   | ns     | true            |
+             | pia    | mus    | true            |
+             | poli   | la     | true            |
+             | psych  | la     | true            |
+             | stdart | art    | true            |
+             | str    | mus    | true            |
+             | tched  | edu    | true            |
+             | voc    | mus    | true            |
+             | win    | mus    | true            |
+                                         (27 rows)
+
+             ----
+             /department{code,school,boolean(school)}
+             SELECT "department"."code",
+                    "department"."school",
+                    (NULLIF("department"."school", '') IS NOT NULL)
+             FROM "ad"."department" AS "department"
+             ORDER BY 1 ASC
+        - uri: /{exists(department{school}), every(department{school}), count(department{school})}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                    |
+            -+------------------------------------------------------------------------------------+-
+             | exists(department{school}) | every(department{school}) | count(department{school}) |
+            -+----------------------------+---------------------------+---------------------------+-
+             | true                       | false                     |                        24 |
+                                                                                            (1 row)
+
+             ----
+             /{exists(department{school}),every(department{school}),count(department{school})}
+             SELECT EXISTS(SELECT TRUE
+                           FROM "ad"."department" AS "department_1"
+                           WHERE (NULLIF("department_1"."school", '') IS NOT NULL)),
+                    (NOT EXISTS(SELECT TRUE
+                                FROM "ad"."department" AS "department_1"
+                                WHERE (NULLIF("department_1"."school", '') IS NULL))),
+                    COUNT(NULLIF((NULLIF("department"."school", '') IS NOT NULL), FALSE))
+             FROM "ad"."department" AS "department"
+        - uri: /{exists(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{exists(true())}
+                         ^^^^^^
+        - uri: /{every(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{every(true())}
+                        ^^^^^^
+        - uri: /{count(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{count(true())}
+                  ^^^^^^^^^^^^^
+        - uri: /course{number,credits}?department='be'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='be') |
+            -+--------------------------+-
+             | number     | credits     |
+            -+------------+-------------+-
+             |        112 |           3 |
+             |        308 |           3 |
+             |        415 |           8 |
+             |        509 |           3 |
+                                 (4 rows)
+
+             ----
+             /course{number,credits}?department='be'
+             SELECT "course"."number",
+                    "course"."credits"
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'be')
+             ORDER BY "course"."department" ASC, 1 ASC
+        - uri: /{min(course{credits}?department='be'), max(course{credits}?department='be')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                             |
+            -+-----------------------------------------------------------------------------+-
+             | min(course{credits}?department='be') | max(course{credits}?department='be') |
+            -+--------------------------------------+--------------------------------------+-
+             |                                    3 |                                    8 |
+                                                                                     (1 row)
+
+             ----
+             /{min(course{credits}?department='be'),max(course{credits}?department='be')}
+             SELECT MIN("course"."credits"),
+                    MAX("course"."credits")
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'be')
+        - uri: /course?department='str'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='str')                           |
+            -+-----------------------------------------------------+-
+             | department | number | title | credits | description |
+            -+------------+--------+-------+---------+-------------+-
+                                                           (no rows)
+
+             ----
+             /course?department='str'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'str')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{min(course{credits}?department='str'), max(course{credits}?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                               |
+            -+-------------------------------------------------------------------------------+-
+             | min(course{credits}?department='str') | max(course{credits}?department='str') |
+            -+---------------------------------------+---------------------------------------+-
+             |                                       |                                       |
+                                                                                       (1 row)
+
+             ----
+             /{min(course{credits}?department='str'),max(course{credits}?department='str')}
+             SELECT MIN("course"."credits"),
+                    MAX("course"."credits")
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /{min(student.dob), max(student.dob)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                     |
+            -+-------------------------------------+-
+             | min(student.dob) | max(student.dob) |
+            -+------------------+------------------+-
+             | 1981-04-20       | 2002-07-06       |
+                                             (1 row)
+
+             ----
+             /{min(student.dob),max(student.dob)}
+             SELECT MIN("student"."dob"),
+                    MAX("student"."dob")
+             FROM "ed"."student" AS "student"
+        - uri: /{min(student.name), max(student.name)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                            |
+            -+--------------------------------------------+-
+             | min(student.name)      | max(student.name) |
+            -+------------------------+-------------------+-
+             | Alicia Montez-Galliano | Valeria Rinaldi   |
+                                                    (1 row)
+
+             ----
+             /{min(student.name),max(student.name)}
+             SELECT MIN("student"."name"),
+                    MAX("student"."name")
+             FROM "ed"."student" AS "student"
+        - uri: /{min(student.is_active), max(student.is_active)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{min(student.is_active), max(student.is_active)}
+                  ^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /{sum(course{credits}?department='be'), count(course{credits}?department='be'),
+            avg(course{credits}?department='be')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                      |
+            -+----------------------------------------------------------------------------------------------------------------------+-
+             | sum(course{credits}?department='be') | count(course{credits}?department='be') | avg(course{credits}?department='be') |
+            -+--------------------------------------+----------------------------------------+--------------------------------------+-
+             |                                   17 |                                      4 |                   4.2500000000000000 |
+                                                                                                                              (1 row)
+
+             ----
+             /{sum(course{credits}?department='be'),count(course{credits}?department='be'),avg(course{credits}?department='be')}
+             SELECT COALESCE(SUM("course"."credits"), 0),
+                    COUNT(NULLIF(("course"."credits" IS NOT NULL), FALSE)),
+                    AVG(CAST("course"."credits" AS NUMERIC))
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'be')
+        - uri: /{sum(course{credits}?department='str'), count(course{credits}?department='str'),
+            avg(course{credits}?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                         |
+            -+-------------------------------------------------------------------------------------------------------------------------+-
+             | sum(course{credits}?department='str') | count(course{credits}?department='str') | avg(course{credits}?department='str') |
+            -+---------------------------------------+-----------------------------------------+---------------------------------------+-
+             |                                     0 |                                       0 |                                       |
+                                                                                                                                 (1 row)
+
+             ----
+             /{sum(course{credits}?department='str'),count(course{credits}?department='str'),avg(course{credits}?department='str')}
+             SELECT COALESCE(SUM("course"."credits"), 0),
+                    COUNT(NULLIF(("course"."credits" IS NOT NULL), FALSE)),
+                    AVG(CAST("course"."credits" AS NUMERIC))
+             FROM "ad"."course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /{sum(student.dob)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{sum(student.dob)}
+                  ^^^^^^^^^^^^^^^^
+        - uri: /{avg(student.name)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{avg(student.name)}
+                  ^^^^^^^^^^^^^^^^^
       - id: scalar-functions
         tests:
         - id: boolean-constants-and-logical-operators

test/output/sqlite.yaml

              /{date(string('birthday')),date(string('2010-13-07'))}
              SELECT DATE('birthday'),
                     DATE('2010-13-07')
+      - id: aggregate-functions
+        tests:
+        - uri: /course?department='lang'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='lang')                                                                      |
+            -+-------------------------------------------------------------------------------------------------+-
+             | department | number | title                        | credits | description                      |
+            -+------------+--------+------------------------------+---------+----------------------------------+-
+             | lang       |    201 | Introduction to Spanish      |       4 | Introduction to the Spanish      |
+             :            :        :                              :         : language, with an emphasis on    :
+             :            :        :                              :         : every day conversation and basic :
+             :            :        :                              :         : grammar.                         :
+             | lang       |    203 | Intermediate Spanish         |       3 | Continuation of fundamental      |
+             :            :        :                              :         : Spanish language learning,       :
+             :            :        :                              :         : including verb tenses, reading   :
+             :            :        :                              :         : skills, and basic conversation.  :
+             | lang       |    207 | Child Second Language        |       3 | Examines issues in child second  |
+             :            :        : Development                  :         : language acquisition, including  :
+             :            :        :                              :         : the critical period hypothesis   :
+             :            :        :                              :         : and universal grammar.           :
+             | lang       |    304 | Spanish Conversation Group   |       2 | Informal weekly conversation     |
+             :            :        :                              :         : group designed to improve        :
+             :            :        :                              :         : understanding of spoken Spanish. :
+             :            :        :                              :         : Suitable for both majors and     :
+             :            :        :                              :         : casual speakers who wish to      :
+             :            :        :                              :         : improve their skills for         :
+             :            :        :                              :         : personal enjoyment or travel.    :
+             | lang       |    305 | Second Language Syntax       |       3 | This course examines the form    |
+             :            :        :                              :         : and acquisition of nonnative     :
+             :            :        :                              :         : syntax. Consideration of whether :
+             :            :        :                              :         : nonnative grammars are           :
+             :            :        :                              :         : fundamentally different than     :
+             :            :        :                              :         : native grammars.                 :
+                                                                                                        (5 rows)
+
+             ----
+             /course?department='lang'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'lang')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course?department='lang'), every(course?department='lang'),
+            count(course?department='lang')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                      |
+            -+------------------------------------------------------------------------------------------------------+-
+             | exists(course?department='lang') | every(course?department='lang') | count(course?department='lang') |
+            -+----------------------------------+---------------------------------+---------------------------------+-
+             | true                             | true                            |                               5 |
+                                                                                                              (1 row)
+
+             ----
+             /{exists(course?department='lang'),every(course?department='lang'),count(course?department='lang')}
+             SELECT EXISTS(SELECT 1
+                           FROM "course" AS "course_1"
+                           WHERE ("course_1"."department" = 'lang')),
+                    (NOT EXISTS(SELECT 1
+                                FROM "course" AS "course_1"
+                                WHERE 0
+                                      AND ("course_1"."department" = 'lang'))),
+                    COUNT(1)
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'lang')
+        - uri: /course?department='str'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='str')                           |
+            -+-----------------------------------------------------+-
+             | department | number | title | credits | description |
+            -+------------+--------+-------+---------+-------------+-
+                                                           (no rows)
+
+             ----
+             /course?department='str'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'str')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course?department='str'), every(course?department='str'),
+            count(course?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                   |
+            -+---------------------------------------------------------------------------------------------------+-
+             | exists(course?department='str') | every(course?department='str') | count(course?department='str') |
+            -+---------------------------------+--------------------------------+--------------------------------+-
+             | false                           | true                           |                              0 |
+                                                                                                           (1 row)
+
+             ----
+             /{exists(course?department='str'),every(course?department='str'),count(course?department='str')}
+             SELECT EXISTS(SELECT 1
+                           FROM "course" AS "course_1"
+                           WHERE ("course_1"."department" = 'str')),
+                    (NOT EXISTS(SELECT 1
+                                FROM "course" AS "course_1"
+                                WHERE 0
+                                      AND ("course_1"."department" = 'str'))),
+                    COUNT(1)
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /course{department,number,credits,credits>3} ?department={'me','mth','phys'}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department={'me','mth','phys'})   |
+            -+-------------------------------------------+-
+             | department | number | credits | credits>3 |
+            -+------------+--------+---------+-----------+-
+             | me         |    111 |       3 | false     |
+             | me         |    344 |       4 | true      |
+             | me         |    501 |       3 | false     |
+             | me         |    627 |       4 | true      |
+             | me         |    712 |       3 | false     |
+             | mth        |    101 |       5 | true      |
+             | phys       |    211 |       3 | false     |
+             | phys       |    303 |       3 | false     |
+             | phys       |    388 |       2 | false     |
+             | phys       |    512 |       3 | false     |
+             | phys       |    713 |       3 | false     |
+             | phys       |    819 |       3 | false     |
+                                                 (12 rows)
+
+             ----
+             /course{department,number,credits,credits>3}?department={'me','mth','phys'}
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."credits",
+                    ("course"."credits" > 3)
+             FROM "course" AS "course"
+             WHERE ("course"."department" IN ('me', 'mth', 'phys'))
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{exists(course{credits>3}?department='me'), every(course{credits>3}?department='me'),
+            count(course{credits>3}?department='me')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                 |
+            -+---------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='me') | every(course{credits>3}?department='me') | count(course{credits>3}?department='me') |
+            -+-------------------------------------------+------------------------------------------+------------------------------------------+-
+             | true                                      | false                                    |                                        2 |
+                                                                                                                                         (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='me'),every(course{credits>3}?department='me'),count(course{credits>3}?department='me')}
+             SELECT EXISTS(SELECT 1
+                           FROM "course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'me')),
+                    (NOT EXISTS(SELECT 1
+                                FROM "course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'me'))),
+                    COUNT(NULLIF(("course"."credits" > 3), 0))
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'me')
+        - uri: /{exists(course{credits>3}?department='mth'), every(course{credits>3}?department='mth'),
+            count(course{credits>3}?department='mth')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                    |
+            -+------------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='mth') | every(course{credits>3}?department='mth') | count(course{credits>3}?department='mth') |
+            -+--------------------------------------------+-------------------------------------------+-------------------------------------------+-
+             | true                                       | true                                      |                                         1 |
+                                                                                                                                            (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='mth'),every(course{credits>3}?department='mth'),count(course{credits>3}?department='mth')}
+             SELECT EXISTS(SELECT 1
+                           FROM "course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'mth')),
+                    (NOT EXISTS(SELECT 1
+                                FROM "course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'mth'))),
+                    COUNT(NULLIF(("course"."credits" > 3), 0))
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'mth')
+        - uri: /{exists(course{credits>3}?department='phys'), every(course{credits>3}?department='phys'),
+            count(course{credits>3}?department='phys')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                                       |
+            -+---------------------------------------------------------------------------------------------------------------------------------------+-
+             | exists(course{credits>3}?department='phys') | every(course{credits>3}?department='phys') | count(course{credits>3}?department='phys') |
+            -+---------------------------------------------+--------------------------------------------+--------------------------------------------+-
+             | false                                       | false                                      |                                          0 |
+                                                                                                                                               (1 row)
+
+             ----
+             /{exists(course{credits>3}?department='phys'),every(course{credits>3}?department='phys'),count(course{credits>3}?department='phys')}
+             SELECT EXISTS(SELECT 1
+                           FROM "course" AS "course_1"
+                           WHERE ("course_1"."credits" > 3)
+                                 AND ("course_1"."department" = 'phys')),
+                    (NOT EXISTS(SELECT 1
+                                FROM "course" AS "course_1"
+                                WHERE (NOT ("course_1"."credits" > 3))
+                                      AND ("course_1"."department" = 'phys'))),
+                    COUNT(NULLIF(("course"."credits" > 3), 0))
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'phys')
+        - uri: /department{code,school,boolean(school)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | department                        |
+            -+-----------------------------------+-
+             | code   | school | boolean(school) |
+            -+--------+--------+-----------------+-
+             | acc    | bus    | true            |
+             | arthis | art    | true            |
+             | astro  | ns     | true            |
+             | be     | egn    | true            |
+             | bursar |        | false           |
+             | capmrk | bus    | true            |
+             | career |        | false           |
+             | chem   | ns     | true            |
+             | comp   | egn    | true            |
+             | corpfi | bus    | true            |
+             | edpol  | edu    | true            |
+             | ee     | egn    | true            |
+             | eng    | la     | true            |
+             | hist   | la     | true            |
+             | lang   | la     | true            |
+             | me     | egn    | true            |
+             | mth    | ns     | true            |
+             | parent |        | false           |
+             | phys   | ns     | true            |
+             | pia    | mus    | true            |
+             | poli   | la     | true            |
+             | psych  | la     | true            |
+             | stdart | art    | true            |
+             | str    | mus    | true            |
+             | tched  | edu    | true            |
+             | voc    | mus    | true            |
+             | win    | mus    | true            |
+                                         (27 rows)
+
+             ----
+             /department{code,school,boolean(school)}
+             SELECT "department"."code",
+                    "department"."school",
+                    (NULLIF("department"."school", '') IS NOT NULL)
+             FROM "department" AS "department"
+             ORDER BY 1 ASC
+        - uri: /{exists(department{school}), every(department{school}), count(department{school})}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                    |
+            -+------------------------------------------------------------------------------------+-
+             | exists(department{school}) | every(department{school}) | count(department{school}) |
+            -+----------------------------+---------------------------+---------------------------+-
+             | true                       | false                     |                        24 |
+                                                                                            (1 row)
+
+             ----
+             /{exists(department{school}),every(department{school}),count(department{school})}
+             SELECT EXISTS(SELECT 1
+                           FROM "department" AS "department_1"
+                           WHERE (NULLIF("department_1"."school", '') IS NOT NULL)),
+                    (NOT EXISTS(SELECT 1
+                                FROM "department" AS "department_1"
+                                WHERE (NULLIF("department_1"."school", '') IS NULL))),
+                    COUNT(NULLIF((NULLIF("department"."school", '') IS NOT NULL), 0))
+             FROM "department" AS "department"
+        - uri: /{exists(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{exists(true())}
+                         ^^^^^^
+        - uri: /{every(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{every(true())}
+                        ^^^^^^
+        - uri: /{count(true())}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            encode error: a plural operand is required:
+                /{count(true())}
+                  ^^^^^^^^^^^^^
+        - uri: /course{number,credits}?department='be'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='be') |
+            -+--------------------------+-
+             | number     | credits     |
+            -+------------+-------------+-
+             |        112 |           3 |
+             |        308 |           3 |
+             |        415 |           8 |
+             |        509 |           3 |
+                                 (4 rows)
+
+             ----
+             /course{number,credits}?department='be'
+             SELECT "course"."number",
+                    "course"."credits"
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'be')
+             ORDER BY "course"."department" ASC, 1 ASC
+        - uri: /{min(course{credits}?department='be'), max(course{credits}?department='be')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                             |
+            -+-----------------------------------------------------------------------------+-
+             | min(course{credits}?department='be') | max(course{credits}?department='be') |
+            -+--------------------------------------+--------------------------------------+-
+             |                                    3 |                                    8 |
+                                                                                     (1 row)
+
+             ----
+             /{min(course{credits}?department='be'),max(course{credits}?department='be')}
+             SELECT MIN("course"."credits"),
+                    MAX("course"."credits")
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'be')
+        - uri: /course?department='str'
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             | (course?department='str')                           |
+            -+-----------------------------------------------------+-
+             | department | number | title | credits | description |
+            -+------------+--------+-------+---------+-------------+-
+                                                           (no rows)
+
+             ----
+             /course?department='str'
+             SELECT "course"."department",
+                    "course"."number",
+                    "course"."title",
+                    "course"."credits",
+                    "course"."description"
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'str')
+             ORDER BY 1 ASC, 2 ASC
+        - uri: /{min(course{credits}?department='str'), max(course{credits}?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                               |
+            -+-------------------------------------------------------------------------------+-
+             | min(course{credits}?department='str') | max(course{credits}?department='str') |
+            -+---------------------------------------+---------------------------------------+-
+             |                                       |                                       |
+                                                                                       (1 row)
+
+             ----
+             /{min(course{credits}?department='str'),max(course{credits}?department='str')}
+             SELECT MIN("course"."credits"),
+                    MAX("course"."credits")
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /{min(student.dob), max(student.dob)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                     |
+            -+-------------------------------------+-
+             | min(student.dob) | max(student.dob) |
+            -+------------------+------------------+-
+             | 1981-04-20       | 2002-07-06       |
+                                             (1 row)
+
+             ----
+             /{min(student.dob),max(student.dob)}
+             SELECT MIN("student"."dob"),
+                    MAX("student"."dob")
+             FROM "student" AS "student"
+        - uri: /{min(student.name), max(student.name)}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                            |
+            -+--------------------------------------------+-
+             | min(student.name)      | max(student.name) |
+            -+------------------------+-------------------+-
+             | Alicia Montez-Galliano | Valeria Rinaldi   |
+                                                    (1 row)
+
+             ----
+             /{min(student.name),max(student.name)}
+             SELECT MIN("student"."name"),
+                    MAX("student"."name")
+             FROM "student" AS "student"
+        - uri: /{min(student.is_active), max(student.is_active)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{min(student.is_active), max(student.is_active)}
+                  ^^^^^^^^^^^^^^^^^^^^^^
+        - uri: /{sum(course{credits}?department='be'), count(course{credits}?department='be'),
+            avg(course{credits}?department='be')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                      |
+            -+----------------------------------------------------------------------------------------------------------------------+-
+             | sum(course{credits}?department='be') | count(course{credits}?department='be') | avg(course{credits}?department='be') |
+            -+--------------------------------------+----------------------------------------+--------------------------------------+-
+             |                                   17 |                                      4 |                                 4.25 |
+                                                                                                                              (1 row)
+
+             ----
+             /{sum(course{credits}?department='be'),count(course{credits}?department='be'),avg(course{credits}?department='be')}
+             SELECT COALESCE(SUM("course"."credits"), 0),
+                    COUNT(NULLIF(("course"."credits" IS NOT NULL), 0)),
+                    AVG(CAST("course"."credits" AS REAL))
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'be')
+        - uri: /{sum(course{credits}?department='str'), count(course{credits}?department='str'),
+            avg(course{credits}?department='str')}
+          status: 200 OK
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |2
+             |                                                                                                                         |
+            -+-------------------------------------------------------------------------------------------------------------------------+-
+             | sum(course{credits}?department='str') | count(course{credits}?department='str') | avg(course{credits}?department='str') |
+            -+---------------------------------------+-----------------------------------------+---------------------------------------+-
+             |                                     0 |                                       0 |                                       |
+                                                                                                                                 (1 row)
+
+             ----
+             /{sum(course{credits}?department='str'),count(course{credits}?department='str'),avg(course{credits}?department='str')}
+             SELECT COALESCE(SUM("course"."credits"), 0),
+                    COUNT(NULLIF(("course"."credits" IS NOT NULL), 0)),
+                    AVG(CAST("course"."credits" AS REAL))
+             FROM "course" AS "course"
+             WHERE ("course"."department" = 'str')
+        - uri: /{sum(student.dob)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{sum(student.dob)}
+                  ^^^^^^^^^^^^^^^^
+        - uri: /{avg(student.name)}
+          status: 400 Bad Request
+          headers:
+          - [Content-Type, text/plain; charset=UTF-8]
+          body: |
+            bind error: incompatible arguments:
+                /{avg(student.name)}
+                  ^^^^^^^^^^^^^^^^^
   - include: test/input/translation.yaml
     output:
       id: translation