comparison src/postgres.sml @ 866:03e7f111fe99

Start of multi-DBMS support
author Adam Chlipala <adamc@hcoop.net>
date Sun, 28 Jun 2009 13:49:32 -0400
parents
children e7f80d78075b
comparison
equal deleted inserted replaced
865:ebefb0609ac3 866:03e7f111fe99
1 (* Copyright (c) 2008-2009, Adam Chlipala
2 * All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * - Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 * - Redistributions in binary form must reproduce the above copyright notice,
10 * this list of conditions and the following disclaimer in the documentation
11 * and/or other materials provided with the distribution.
12 * - The names of contributors may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 *)
27
28 structure Postgres :> POSTGRES = struct
29
30 open Settings
31 open Print.PD
32 open Print
33
34 fun init (dbstring, ss) =
35 box [if #persistent (currentProtocol ()) then
36 box [string "static void uw_db_prepare(uw_context ctx) {",
37 newline,
38 string "PGconn *conn = uw_get_db(ctx);",
39 newline,
40 string "PGresult *res;",
41 newline,
42 newline,
43
44 p_list_sepi newline (fn i => fn (s, n) =>
45 box [string "res = PQprepare(conn, \"uw",
46 string (Int.toString i),
47 string "\", \"",
48 string (String.toString s),
49 string "\", ",
50 string (Int.toString n),
51 string ", NULL);",
52 newline,
53 string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
54 newline,
55 box [string "char msg[1024];",
56 newline,
57 string "strncpy(msg, PQerrorMessage(conn), 1024);",
58 newline,
59 string "msg[1023] = 0;",
60 newline,
61 string "PQclear(res);",
62 newline,
63 string "PQfinish(conn);",
64 newline,
65 string "uw_error(ctx, FATAL, \"Unable to create prepared statement:\\n",
66 string (String.toString s),
67 string "\\n%s\", msg);",
68 newline],
69 string "}",
70 newline,
71 string "PQclear(res);",
72 newline])
73 ss,
74
75 string "}",
76 newline,
77 newline,
78
79 string "void uw_db_close(uw_context ctx) {",
80 newline,
81 string "PQfinish(uw_get_db(ctx));",
82 newline,
83 string "}",
84 newline,
85 newline,
86
87 string "int uw_db_begin(uw_context ctx) {",
88 newline,
89 string "PGconn *conn = uw_get_db(ctx);",
90 newline,
91 string "PGresult *res = PQexec(conn, \"BEGIN ISOLATION LEVEL SERIALIZABLE\");",
92 newline,
93 newline,
94 string "if (res == NULL) return 1;",
95 newline,
96 newline,
97 string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
98 box [string "PQclear(res);",
99 newline,
100 string "return 1;",
101 newline],
102 string "}",
103 newline,
104 string "return 0;",
105 newline,
106 string "}",
107 newline,
108 newline,
109
110 string "int uw_db_commit(uw_context ctx) {",
111 newline,
112 string "PGconn *conn = uw_get_db(ctx);",
113 newline,
114 string "PGresult *res = PQexec(conn, \"COMMIT\");",
115 newline,
116 newline,
117 string "if (res == NULL) return 1;",
118 newline,
119 newline,
120 string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
121 box [string "PQclear(res);",
122 newline,
123 string "return 1;",
124 newline],
125 string "}",
126 newline,
127 string "return 0;",
128 newline,
129 string "}",
130 newline,
131 newline,
132
133 string "int uw_db_rollback(uw_context ctx) {",
134 newline,
135 string "PGconn *conn = uw_get_db(ctx);",
136 newline,
137 string "PGresult *res = PQexec(conn, \"ROLLBACK\");",
138 newline,
139 newline,
140 string "if (res == NULL) return 1;",
141 newline,
142 newline,
143 string "if (PQresultStatus(res) != PGRES_COMMAND_OK) {",
144 box [string "PQclear(res);",
145 newline,
146 string "return 1;",
147 newline],
148 string "}",
149 newline,
150 string "return 0;",
151 newline,
152 string "}",
153 newline,
154 newline]
155 else
156 string "static void uw_db_prepare(uw_context ctx) { }",
157 newline,
158 newline,
159
160 string "void uw_db_init(uw_context ctx) {",
161 newline,
162 string "PGconn *conn = PQconnectdb(\"",
163 string (String.toString dbstring),
164 string "\");",
165 newline,
166 string "if (conn == NULL) uw_error(ctx, FATAL, ",
167 string "\"libpq can't allocate a connection.\");",
168 newline,
169 string "if (PQstatus(conn) != CONNECTION_OK) {",
170 newline,
171 box [string "char msg[1024];",
172 newline,
173 string "strncpy(msg, PQerrorMessage(conn), 1024);",
174 newline,
175 string "msg[1023] = 0;",
176 newline,
177 string "PQfinish(conn);",
178 newline,
179 string "uw_error(ctx, BOUNDED_RETRY, ",
180 string "\"Connection to Postgres server failed: %s\", msg);"],
181 newline,
182 string "}",
183 newline,
184 string "uw_set_db(ctx, conn);",
185 newline,
186 string "uw_db_validate(ctx);",
187 newline,
188 string "uw_db_prepare(ctx);",
189 newline,
190 string "}"]
191
192 val () = addDbms {name = "postgres",
193 header = "postgresql/libpq-fe.h",
194 link = "-lpq",
195 global_init = box [string "void uw_client_init() { }",
196 newline],
197 init = init}
198 val () = setDbms "postgres"
199
200 end