comparison src/cjr_print.sml @ 867:e7f80d78075b

Moved query code into Settings
author Adam Chlipala <adamc@hcoop.net>
date Sun, 28 Jun 2009 16:03:00 -0400
parents 03e7f111fe99
children 06497beb265b
comparison
equal deleted inserted replaced
866:03e7f111fe99 867:e7f80d78075b
468 (box [string "PQgetlength(res, i, ", 468 (box [string "PQgetlength(res, i, ",
469 string (Int.toString i), 469 string (Int.toString i),
470 string ")"]), 470 string ")"]),
471 string ")"] 471 string ")"]
472 472
473 datatype sql_type = 473 datatype sql_type = datatype Settings.sql_type
474 Int 474 val isBlob = Settings.isBlob
475 | Float
476 | String
477 | Bool
478 | Time
479 | Blob
480 | Channel
481 | Client
482 | Nullable of sql_type
483
484 fun isBlob Blob = true
485 | isBlob (Nullable t) = isBlob t
486 | isBlob _ = false
487 475
488 fun isFile (t : typ) = 476 fun isFile (t : typ) =
489 case #1 t of 477 case #1 t of
490 TFfi ("Basis", "file") => true 478 TFfi ("Basis", "file") => true
491 | _ => false 479 | _ => false
1248 space) 1236 space)
1249 in 1237 in
1250 urlify' IS.empty 0 t 1238 urlify' IS.empty 0 t
1251 end 1239 end
1252 1240
1241 fun sql_type_in env (tAll as (t, loc)) =
1242 case t of
1243 TFfi ("Basis", "int") => Int
1244 | TFfi ("Basis", "float") => Float
1245 | TFfi ("Basis", "string") => String
1246 | TFfi ("Basis", "bool") => Bool
1247 | TFfi ("Basis", "time") => Time
1248 | TFfi ("Basis", "blob") => Blob
1249 | TFfi ("Basis", "channel") => Channel
1250 | TFfi ("Basis", "client") => Client
1251 | TOption t' => Nullable (sql_type_in env t')
1252 | _ => (ErrorMsg.errorAt loc "Don't know SQL equivalent of type";
1253 Print.eprefaces' [("Type", p_typ env tAll)];
1254 Int)
1255
1253 fun p_exp' par env (e, loc) = 1256 fun p_exp' par env (e, loc) =
1254 case e of 1257 case e of
1255 EPrim p => Prim.p_t_GCC p 1258 EPrim p => Prim.p_t_GCC p
1256 | ERel n => p_rel env n 1259 | ERel n => p_rel env n
1257 | ENamed n => p_enamed env n 1260 | ENamed n => p_enamed env n
1568 val outputs = exps @ tables 1571 val outputs = exps @ tables
1569 val outputs = ListMergeSort.sort (fn ((s1, _), (s2, _)) => String.compare (s1, s2) = GREATER) outputs 1572 val outputs = ListMergeSort.sort (fn ((s1, _), (s2, _)) => String.compare (s1, s2) = GREATER) outputs
1570 1573
1571 val wontLeakStrings = notLeaky env true state 1574 val wontLeakStrings = notLeaky env true state
1572 val wontLeakAnything = notLeaky env false state 1575 val wontLeakAnything = notLeaky env false state
1576
1577 val inputs =
1578 case prepared of
1579 NONE => []
1580 | SOME _ => getPargs query
1581
1582 fun doCols p_getcol =
1583 box [string "struct __uws_",
1584 string (Int.toString rnum),
1585 string " __uwr_r_",
1586 string (Int.toString (E.countERels env)),
1587 string ";",
1588 newline,
1589 p_typ env state,
1590 space,
1591 string "__uwr_acc_",
1592 string (Int.toString (E.countERels env + 1)),
1593 space,
1594 string "=",
1595 space,
1596 string "acc;",
1597 newline,
1598 newline,
1599 p_list_sepi (box []) (fn i =>
1600 fn (proj, t) =>
1601 box [string "__uwr_r_",
1602 string (Int.toString (E.countERels env)),
1603 string ".",
1604 string proj,
1605 space,
1606 string "=",
1607 space,
1608 p_getcol {wontLeakStrings = wontLeakStrings,
1609 col = i,
1610 typ = sql_type_in env t},
1611 string ";",
1612 newline]) outputs,
1613 newline,
1614 newline,
1615
1616 string "acc",
1617 space,
1618 string "=",
1619 space,
1620 p_exp (E.pushERel
1621 (E.pushERel env "r" (TRecord rnum, loc))
1622 "acc" state)
1623 body,
1624 string ";",
1625 newline]
1573 in 1626 in
1574 box [if wontLeakAnything then 1627 box [if wontLeakAnything then
1575 string "(uw_begin_region(ctx), " 1628 string "(uw_begin_region(ctx), "
1576 else 1629 else
1577 box [], 1630 box [],
1578 string "({", 1631 string "({",
1579 newline,
1580 string "PGconn *conn = uw_get_db(ctx);",
1581 newline, 1632 newline,
1582 p_typ env state, 1633 p_typ env state,
1583 space, 1634 space,
1584 string "acc", 1635 string "acc",
1585 space, 1636 space,
1586 string "=", 1637 string "=",
1587 space, 1638 space,
1588 p_exp env initial, 1639 p_exp env initial,
1589 string ";", 1640 string ";",
1590 newline, 1641 newline,
1591 string "int n, i, dummy = (uw_begin_region(ctx), 0);", 1642 string "int dummy = (uw_begin_region(ctx), 0);",
1592 newline, 1643 newline,
1593 1644
1594 case prepared of 1645 case prepared of
1595 NONE => box [string "char *query = ", 1646 NONE =>
1596 p_exp env query, 1647 box [string "char *query = ",
1597 string ";", 1648 p_exp env query,
1598 newline] 1649 string ";",
1599 | SOME _ => 1650 newline,
1600 let 1651 newline,
1601 val ets = getPargs query 1652
1602 in 1653 #query (Settings.currentDbms ())
1603 box [p_list_sepi newline 1654 {loc = loc,
1604 (fn i => fn (e, t) => 1655 numCols = length outputs,
1605 box [p_sql_type t, 1656 doCols = doCols}]
1606 space, 1657 | SOME (id, query) =>
1607 string "arg", 1658 box [p_list_sepi newline
1608 string (Int.toString (i + 1)), 1659 (fn i => fn (e, t) =>
1609 space, 1660 box [p_sql_type t,
1610 string "=", 1661 space,
1611 space, 1662 string "arg",
1612 p_exp env e, 1663 string (Int.toString (i + 1)),
1613 string ";"]) 1664 space,
1614 ets, 1665 string "=",
1615 newline, 1666 space,
1616 newline, 1667 p_exp env e,
1617 1668 string ";"])
1618 string "const int paramFormats[] = { ", 1669 inputs,
1619 p_list_sep (box [string ",", space]) 1670 newline,
1620 (fn (_, t) => if isBlob t then string "1" else string "0") ets, 1671 newline,
1621 string " };", 1672
1622 newline, 1673 #queryPrepared (Settings.currentDbms ())
1623 string "const int paramLengths[] = { ", 1674 {loc = loc,
1624 p_list_sepi (box [string ",", space]) 1675 id = id,
1625 (fn i => fn (_, Blob) => string ("arg" ^ Int.toString (i + 1) ^ ".size") 1676 query = query,
1626 | (_, Nullable Blob) => string ("arg" ^ Int.toString (i + 1) 1677 inputs = map #2 inputs,
1627 ^ "?arg" ^ Int.toString (i + 1) ^ "->size:0") 1678 numCols = length outputs,
1628 | _ => string "0") ets, 1679 doCols = doCols}],
1629 string " };", 1680 newline,
1630 newline, 1681
1631 string "const char *paramValues[] = { ",
1632 p_list_sepi (box [string ",", space])
1633 (fn i => fn (_, t) => p_ensql t (box [string "arg",
1634 string (Int.toString (i + 1))]))
1635 ets,
1636 string " };",
1637 newline,
1638 newline]
1639 end,
1640
1641 string "PGresult *res = ",
1642 case prepared of
1643 NONE => string "PQexecParams(conn, query, 0, NULL, NULL, NULL, NULL, 0);"
1644 | SOME (n, s) =>
1645 if #persistent (Settings.currentProtocol ()) then
1646 box [string "PQexecPrepared(conn, \"uw",
1647 string (Int.toString n),
1648 string "\", ",
1649 string (Int.toString (length (getPargs query))),
1650 string ", paramValues, paramLengths, paramFormats, 0);"]
1651 else
1652 box [string "PQexecParams(conn, \"",
1653 string (String.toString s),
1654 string "\", ",
1655 string (Int.toString (length (getPargs query))),
1656 string ", NULL, paramValues, paramLengths, paramFormats, 0);"],
1657 newline,
1658 newline,
1659
1660 string "if (res == NULL) uw_error(ctx, FATAL, \"Out of memory allocating query result.\");",
1661 newline,
1662 newline,
1663
1664 string "if (PQresultStatus(res) != PGRES_TUPLES_OK) {",
1665 newline,
1666 box [string "PQclear(res);",
1667 newline,
1668 string "uw_error(ctx, FATAL, \"",
1669 string (ErrorMsg.spanToString loc),
1670 string ": Query failed:\\n%s\\n%s\", ",
1671 case prepared of
1672 NONE => string "query"
1673 | SOME _ => p_exp env query,
1674 string ", PQerrorMessage(conn));",
1675 newline],
1676 string "}",
1677 newline,
1678 newline,
1679
1680 string "if (PQnfields(res) != ",
1681 string (Int.toString (length outputs)),
1682 string ") {",
1683 newline,
1684 box [string "int nf = PQnfields(res);",
1685 newline,
1686 string "PQclear(res);",
1687 newline,
1688 string "uw_error(ctx, FATAL, \"",
1689 string (ErrorMsg.spanToString loc),
1690 string ": Query returned %d columns instead of ",
1691 string (Int.toString (length outputs)),
1692 string ":\\n%s\\n%s\", ",
1693 case prepared of
1694 NONE => string "query"
1695 | SOME _ => p_exp env query,
1696 string ", nf, PQerrorMessage(conn));",
1697 newline],
1698 string "}",
1699 newline,
1700 newline,
1701
1702 string "uw_end_region(ctx);",
1703 newline,
1704 string "uw_push_cleanup(ctx, (void (*)(void *))PQclear, res);",
1705 newline,
1706 string "n = PQntuples(res);",
1707 newline,
1708 string "for (i = 0; i < n; ++i) {",
1709 newline,
1710 box [string "struct",
1711 space,
1712 string "__uws_",
1713 string (Int.toString rnum),
1714 space,
1715 string "__uwr_r_",
1716 string (Int.toString (E.countERels env)),
1717 string ";",
1718 newline,
1719 p_typ env state,
1720 space,
1721 string "__uwr_acc_",
1722 string (Int.toString (E.countERels env + 1)),
1723 space,
1724 string "=",
1725 space,
1726 string "acc;",
1727 newline,
1728 newline,
1729
1730 p_list_sepi (box []) (fn i =>
1731 fn (proj, t) =>
1732 box [string "__uwr_r_",
1733 string (Int.toString (E.countERels env)),
1734 string ".",
1735 string proj,
1736 space,
1737 string "=",
1738 space,
1739 p_getcol wontLeakStrings env t i,
1740 string ";",
1741 newline]) outputs,
1742
1743 newline,
1744 newline,
1745
1746 string "acc",
1747 space,
1748 string "=",
1749 space,
1750 p_exp (E.pushERel
1751 (E.pushERel env "r" (TRecord rnum, loc))
1752 "acc" state)
1753 body,
1754 string ";",
1755 newline],
1756 string "}",
1757 newline,
1758 newline,
1759 string "uw_pop_cleanup(ctx);",
1760 newline,
1761 if wontLeakAnything then 1682 if wontLeakAnything then
1762 box [string "uw_end_region(ctx);", 1683 box [string "uw_end_region(ctx);",
1763 newline] 1684 newline]
1764 else 1685 else
1765 box [], 1686 box [],