# Testing queries from documentation (CRUD):

Schema:
pony.orm.examples.estore

>>> Product.get(name="Product1")

SELECT "id", "name", "description", "picture", "price", "quantity"
FROM "Product"
WHERE "name" = ?

>>> Product.select(lambda p: p.price > 100)

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > 100

>>> x = 100
>>> Product.select(lambda p: p.price > x)

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > ?

>>> Product.select(lambda p: p.price > 100).order_by(lambda p: desc(p.price))

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > 100
ORDER BY "p"."price" DESC

>>> Product.select(lambda p: p.price > 100).order_by(desc(Product.price))

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > 100
ORDER BY "p"."price" DESC

>>> Product.select(lambda p: p.price > 100).order_by(desc(Product.price), Product.name)

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > 100
ORDER BY "p"."price" DESC, "p"."name"

>>> Product.select(lambda p: p.price > 100).order_by("desc(p.price), p.name")

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
WHERE "p"."price" > 100
ORDER BY "p"."price" DESC, "p"."name"

>>> Product.order_by(lambda p: desc(p.price))[:10]

SELECT "p"."id", "p"."name", "p"."description", "p"."picture", "p"."price", "p"."quantity"
FROM "Product" "p"
ORDER BY "p"."price" DESC
LIMIT 10


# Testing declarative queries from documentation:

# TODO

# Testing aggregation queries from documentation:

Schema:
pony.orm.examples.presentation

>>> sum(s.gpa for s in Student if s.group.number == 101)

SELECT coalesce(SUM("s"."gpa"), 0)
FROM "Student" "s"
WHERE "s"."group" = 101

>>> count(s for s in Student if s.gpa > 3)

SELECT COUNT(*)
FROM "Student" "s"
WHERE "s"."gpa" > 3


>>> min(s.name for s in Student if "Philosophy" in s.courses.name)

SELECT MIN("s"."name")
FROM "Student" "s"
WHERE 'Philosophy' IN (
    SELECT "t-1"."course_name"
    FROM "Course_Student" "t-1"
    WHERE "s"."id" = "t-1"."student"
    )

>>> max(s.dob for s in Student if s.group.number == 101)

SELECT MAX("s"."dob")
FROM "Student" "s"
WHERE "s"."group" = 101

>>> avg(s.gpa for s in Student if s.group.dept.number == 44)

SELECT AVG("s"."gpa")
FROM "Student" "s", "Group" "group-1"
WHERE "group-1"."dept" = 44
  AND "s"."group" = "group-1"."number"

>>> select(s for s in Student if s.group.number == 101 and s.dob == max(s.dob for s in Student if s.group.number == 101))

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
WHERE "s"."group" = 101
  AND "s"."dob" = (
    SELECT MAX("s"."dob")
    FROM "Student" "s"
    WHERE "s"."group" = 101
    )

>>> select(g for g in Group if avg(s.gpa for s in g.students) > 4.5)

SELECT "g"."number", "g"."major", "g"."dept"
FROM "Group" "g"
WHERE (
    SELECT AVG("s"."gpa")
    FROM "Student" "s"
    WHERE "g"."number" = "s"."group"
    ) > 4.5

>>> select(g for g in Group if avg(g.students.gpa) > 4.5)

SELECT "g"."number"
FROM "Group" "g"
  LEFT JOIN "Student" "student-1"
    ON "g"."number" = "student-1"."group"
GROUP BY "g"."number"
HAVING AVG("student-1"."gpa") > 4.5

>>> select((s.group, min(s.gpa), max(s.gpa)) for s in Student)

SELECT "s"."group", MIN("s"."gpa"), MAX("s"."gpa")
FROM "Student" "s"
GROUP BY "s"."group"

>>> count(s for s in Student if s.group.number == 101)

SELECT COUNT(*)
FROM "Student" "s"
WHERE "s"."group" = 101

>>> select((g, count(g.students)) for g in Group if g.dept.number == 44)

SELECT "g"."number", COUNT(DISTINCT "student-1"."id")
FROM "Group" "g"
  LEFT JOIN "Student" "student-1"
    ON "g"."number" = "student-1"."group"
WHERE "g"."dept" = 44
GROUP BY "g"."number"

>>> select((s.group, count(s)) for s in Student if s.group.dept.number == 44)

SELECT "s"."group", COUNT(DISTINCT "s"."id")
FROM "Student" "s", "Group" "group-1"
WHERE "group-1"."dept" = 44
  AND "s"."group" = "group-1"."number"
GROUP BY "s"."group"

>>> select((g, count(s for s in g.students if s.gpa <= 3), count(s for s in g.students if s.gpa > 3 and s.gpa <= 4), count(s for s in g.students if s.gpa > 4)) for g in Group)

SELECT "g"."number", (
    SELECT COUNT(DISTINCT "s"."id")
    FROM "Student" "s"
    WHERE "g"."number" = "s"."group"
      AND "s"."gpa" <= 3
    ), (
    SELECT COUNT(DISTINCT "s"."id")
    FROM "Student" "s"
    WHERE "g"."number" = "s"."group"
      AND "s"."gpa" > 3
      AND "s"."gpa" <= 4
    ), (
    SELECT COUNT(DISTINCT "s"."id")
    FROM "Student" "s"
    WHERE "g"."number" = "s"."group"
      AND "s"."gpa" > 4
    )
FROM "Group" "g"

>>> select((s.group, count(s.gpa <= 3), count(s.gpa > 3 and s.gpa <= 4), count(s.gpa > 4)) for s in Student)

SELECT "s"."group", COUNT(case when "s"."gpa" <= 3 then 1 else null end), COUNT(case when "s"."gpa" > 3 AND "s"."gpa" <= 4 then 1 else null end), COUNT(case when "s"."gpa" > 4 then 1 else null end)
FROM "Student" "s"
GROUP BY "s"."group"

>>> left_join((g, count(s.gpa <= 3), count(s.gpa > 3 and s.gpa <= 4), count(s.gpa > 4)) for g in Group for s in g.students)

SELECT "g"."number", COUNT(case when "s"."gpa" <= 3 then 1 else null end), COUNT(case when "s"."gpa" > 3 AND "s"."gpa" <= 4 then 1 else null end), COUNT(case when "s"."gpa" > 4 then 1 else null end)
FROM "Group" "g"
  LEFT JOIN "Student" "s"
    ON "g"."number" = "s"."group"
GROUP BY "g"."number"

>>> select((s.dob.year, avg(s.gpa)) for s in Student)

SELECT cast(substr("s"."dob", 1, 4) as integer), AVG("s"."gpa")
FROM "Student" "s"
GROUP BY cast(substr("s"."dob", 1, 4) as integer)

Schema:
pony.orm.examples.estore

>>> select((item.order, sum(item.price * item.quantity)) for item in OrderItem if item.order.id == 123)

SELECT "item"."order", coalesce(SUM(("item"."price" * "item"."quantity")), 0)
FROM "OrderItem" "item"
WHERE "item"."order" = 123
GROUP BY "item"."order"

>>> select((order, sum(order.items.price * order.items.quantity)) for order in Order if order.id == 123)

SELECT "order"."id", coalesce(SUM(("orderitem-1"."price" * "orderitem-1"."quantity")), 0)
FROM "Order" "order"
  LEFT JOIN "OrderItem" "orderitem-1"
    ON "order"."id" = "orderitem-1"."order"
WHERE "order"."id" = 123
GROUP BY "order"."id"

>>> select((item.order, item.order.total_price, sum(item.price * item.quantity)) for item in OrderItem if item.order.total_price < sum(item.price * item.quantity))

SELECT "item"."order", "order-1"."total_price", coalesce(SUM(("item"."price" * "item"."quantity")), 0)
FROM "OrderItem" "item", "Order" "order-1"
WHERE "item"."order" = "order-1"."id"
GROUP BY "item"."order", "order-1"."total_price"
HAVING "order-1"."total_price" < coalesce(SUM(("item"."price" * "item"."quantity")), 0)

>>> select(c for c in Customer for p in c.orders.items.product if 'Tablets' in p.categories.name and count(p) > 1)

SELECT DISTINCT "c"."id"
FROM "Customer" "c", "Order" "order-1", "OrderItem" "orderitem-1"
WHERE 'Tablets' IN (
    SELECT "category-1"."name"
    FROM "Category_Product" "t-1", "Category" "category-1"
    WHERE "orderitem-1"."product" = "t-1"."product"
      AND "t-1"."category" = "category-1"."id"
    )
  AND "c"."id" = "order-1"."customer"
  AND "order-1"."id" = "orderitem-1"."order"
GROUP BY "c"."id"
HAVING COUNT(DISTINCT "orderitem-1"."product") > 1

Schema:
pony.orm.examples.presentation

>>> select((s.group, count(s)) for s in Student  if s.group.dept.number == 44 and avg(s.gpa) > 4)

SELECT "s"."group", COUNT(DISTINCT "s"."id")
FROM "Student" "s", "Group" "group-1"
WHERE "group-1"."dept" = 44
  AND "s"."group" = "group-1"."number"
GROUP BY "s"."group"
HAVING AVG("s"."gpa") > 4

>>> select(g for g in Group if max(g.students.gpa) < 4)

SELECT "g"."number"
FROM "Group" "g"
  LEFT JOIN "Student" "student-1"
    ON "g"."number" = "student-1"."group"
GROUP BY "g"."number"
HAVING MAX("student-1"."gpa") < 4

>>> select(g for g in Group if JOIN(max(g.students.gpa) < 4))

SELECT "g"."number"
FROM "Group" "g"
  LEFT JOIN (
    SELECT "student-1"."group" AS "group", MAX("student-1"."gpa") AS "expr-1"
    FROM "Student" "student-1"
    GROUP BY "student-1"."group"
    ) "t-1"
    ON "g"."number" = "t-1"."group"
WHERE "t-1"."expr-1" < 4
GROUP BY "g"."number"

>>> select(s.group for s in Student if max(s.gpa) < 4)

SELECT "s"."group"
FROM "Student" "s"
GROUP BY "s"."group"
HAVING MAX("s"."gpa") < 4

>>> select((s.group, avg(s.gpa)) for s in Student).order_by(lambda: avg(s.gpa))

SELECT "s"."group", AVG("s"."gpa")
FROM "Student" "s"
GROUP BY "s"."group"
ORDER BY AVG("s"."gpa")

>>> select((s.group, avg(s.gpa)) for s in Student).order_by(lambda: desc(avg(s.gpa)))

SELECT "s"."group", AVG("s"."gpa")
FROM "Student" "s"
GROUP BY "s"."group"
ORDER BY AVG("s"."gpa") DESC

>>> select((s.group, avg(s.gpa)) for s in Student).order_by(2)

SELECT "s"."group", AVG("s"."gpa")
FROM "Student" "s"
GROUP BY "s"."group"
ORDER BY 2

>>> select((s.group, avg(s.gpa)) for s in Student).order_by(-2)

SELECT "s"."group", AVG("s"."gpa")
FROM "Student" "s"
GROUP BY "s"."group"
ORDER BY 2 DESC

>>> select(sum(s.gpa) for s in Student)

SELECT coalesce(SUM("s"."gpa"), 0)
FROM "Student" "s"

>>> select(s.gpa for s in Student).sum()

SELECT coalesce(SUM("s"."gpa"), 0)
FROM "Student" "s"


# Other tests

Schema:
pony.orm.examples.presentation

>>> select(s for s in Student if s.gpa > 3)

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
WHERE "s"."gpa" > 3

Oracle:
SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."GPA" > 3

>>> select(s for s in Student if s.group.number == 1)

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
WHERE "s"."group" = 1

Oracle:
SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."GROUP" = 1

>>> select(c for c in Course if count(c.students) > 3)

SELECT "c"."name", "c"."semester"
FROM "Course" "c"
  LEFT JOIN "Course_Student" "t-1"
    ON "c"."name" = "t-1"."course_name" AND "c"."semester" = "t-1"."course_semester"
GROUP BY "c"."name", "c"."semester"
HAVING COUNT(DISTINCT "t-1"."student") > 3

Oracle:

SELECT "c"."NAME", "c"."SEMESTER"
FROM "COURSE" "c"
  LEFT JOIN "COURSE_STUDENT" "t-1"
    ON "c"."NAME" = "t-1"."COURSE_NAME" AND "c"."SEMESTER" = "t-1"."COURSE_SEMESTER"
GROUP BY "c"."NAME", "c"."SEMESTER"
HAVING COUNT(DISTINCT "t-1"."STUDENT") > 3

>>> select(s for s in Student if count(s.courses) > 3)

SELECT "s"."id"
FROM "Student" "s"
  LEFT JOIN "Course_Student" "t-1"
    ON "s"."id" = "t-1"."student"
GROUP BY "s"."id"
HAVING COUNT("t-1"."ROWID") > 3

Oracle:

SELECT "s"."ID"
FROM "STUDENT" "s"
  LEFT JOIN "COURSE_STUDENT" "t-1"
    ON "s"."ID" = "t-1"."STUDENT"
GROUP BY "s"."ID"
HAVING COUNT("t-1"."ROWID") > 3

>>> select(s for s in Student).for_update()[:3]

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
LIMIT 3

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."ROWID" IN (
    SELECT * FROM (
        SELECT "s"."ROWID" AS "row-id"
        FROM "STUDENT" "s"
    ) WHERE ROWNUM <= 3
    )
FOR UPDATE

>>> select(s for s in Student).order_by(Student.name).for_update()[:3]

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
ORDER BY "s"."name"
LIMIT 3

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."ROWID" IN (
    SELECT * FROM (
        SELECT "s"."ROWID" AS "row-id"
        FROM "STUDENT" "s"
        ORDER BY "s"."NAME"
    ) WHERE ROWNUM <= 3
    )
ORDER BY "s"."NAME"
FOR UPDATE

>>> select(s for s in Student).order_by(Student.name).for_update()[3:6]

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
ORDER BY "s"."name"
LIMIT 3 OFFSET 3

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."ROWID" IN (
    SELECT t."row-id" FROM (
        SELECT t.*, ROWNUM "row-num" FROM (
            SELECT "s"."ROWID" AS "row-id"
            FROM "STUDENT" "s"
            ORDER BY "s"."NAME"
        ) t WHERE ROWNUM <= 6
    ) t WHERE "row-num" > 3
    )
ORDER BY "s"."NAME"
FOR UPDATE

>>> select(s for s in Student).for_update()[3:6]

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
LIMIT 3 OFFSET 3

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."ROWID" IN (
    SELECT t."row-id" FROM (
        SELECT t.*, ROWNUM "row-num" FROM (
            SELECT "s"."ROWID" AS "row-id"
            FROM "STUDENT" "s"
        ) t WHERE ROWNUM <= 6
    ) t WHERE "row-num" > 3
    )
FOR UPDATE

>>> select((g, count(s)) for g in Group for s in g.students)

SELECT "g"."number", COUNT(DISTINCT "s"."id")
FROM "Group" "g", "Student" "s"
WHERE "g"."number" = "s"."group"
GROUP BY "g"."number"

Oracle:

SELECT "g"."NUMBER", COUNT(DISTINCT "s"."ID")
FROM "GROUP" "g", "STUDENT" "s"
WHERE "g"."NUMBER" = "s"."GROUP"
GROUP BY "g"."NUMBER"

PostgreSQL:

SELECT "g"."number", COUNT(DISTINCT "s"."id")
FROM "group" "g", "student" "s"
WHERE "g"."number" = "s"."group"
GROUP BY "g"."number"

>>> select((s, count(c)) for s in Student for c in s.courses)

SELECT DISTINCT "s"."id", COUNT(DISTINCT "c"."ROWID")
FROM "Student" "s", "Course_Student" "t-1", "Course" "c"
WHERE "s"."id" = "t-1"."student"
  AND "t-1"."course_name" = "c"."name"
  AND "t-1"."course_semester" = "c"."semester"
GROUP BY "s"."id"

Oracle:

SELECT DISTINCT "s"."ID", COUNT(DISTINCT "c"."ROWID")
FROM "STUDENT" "s", "COURSE_STUDENT" "t-1", "COURSE" "c"
WHERE "s"."ID" = "t-1"."STUDENT"
  AND "t-1"."COURSE_NAME" = "c"."NAME"
  AND "t-1"."COURSE_SEMESTER" = "c"."SEMESTER"
GROUP BY "s"."ID"

PostgreSQL:

SELECT DISTINCT "s"."id", COUNT(DISTINCT case when ("t-1"."course_name", "t-1"."course_semester") IS NULL then null else ("t-1"."course_name", "t-1"."course_semester") end)
FROM "student" "s", "course_student" "t-1"
WHERE "s"."id" = "t-1"."student"
GROUP BY "s"."id"

>>> x = '123'
>>> select(s for s in Student if s.tel == x)[:]

SELECT "s"."id", "s"."name", "s"."dob", "s"."tel", "s"."gpa", "s"."group"
FROM "Student" "s"
WHERE "s"."tel" = ?

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."TEL" = :p1

>>> x = ''
>>> select(s for s in Student if s.tel == x)[:]

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."TEL" IS NULL

>>> x = ''
>>> select(s for s in Student).filter(lambda s: s.tel == x)[:]

Oracle:

SELECT "s"."ID", "s"."NAME", "s"."DOB", "s"."TEL", "s"."GPA", "s"."GROUP"
FROM "STUDENT" "s"
WHERE "s"."TEL" IS NULL

>>> select(s.name for s in Student if s.name in (s.name for s in Student if count() > 1))[:]

SELECT DISTINCT "s"."name"
FROM "Student" "s"
WHERE "s"."name" IN (
    SELECT "s"."name"
    FROM "Student" "s"
    GROUP BY "s"."name"
    HAVING COUNT(*) > 1
    )
