Mercurial > urweb
comparison src/postgres.sml @ 870:7fa9a37a34b3
Move all DBMS initialization to #init
author | Adam Chlipala <adamc@hcoop.net> |
---|---|
date | Tue, 30 Jun 2009 15:45:10 -0400 |
parents | 64ba57fa20bf |
children | 3ae6b655ced0 |
comparison
equal
deleted
inserted
replaced
869:64ba57fa20bf | 870:7fa9a37a34b3 |
---|---|
29 | 29 |
30 open Settings | 30 open Settings |
31 open Print.PD | 31 open Print.PD |
32 open Print | 32 open Print |
33 | 33 |
34 fun init (dbstring, ss) = | 34 val ident = String.translate (fn #"'" => "PRIME" |
35 | ch => str ch) | |
36 | |
37 fun p_sql_type_base t = | |
38 case t of | |
39 Int => "int8" | |
40 | Float => "float8" | |
41 | String => "text" | |
42 | Bool => "bool" | |
43 | Time => "timestamp" | |
44 | Blob => "bytea" | |
45 | Channel => "int8" | |
46 | Client => "int4" | |
47 | Nullable t => p_sql_type_base t | |
48 | |
49 fun init {dbstring, prepared = ss, tables, sequences} = | |
35 box [if #persistent (currentProtocol ()) then | 50 box [if #persistent (currentProtocol ()) then |
36 box [string "static void uw_db_prepare(uw_context ctx) {", | 51 box [string "static void uw_db_validate(uw_context ctx) {", |
52 newline, | |
53 string "PGconn *conn = uw_get_db(ctx);", | |
54 newline, | |
55 string "PGresult *res;", | |
56 newline, | |
57 newline, | |
58 p_list_sep newline | |
59 (fn (s, xts) => | |
60 let | |
61 val sl = CharVector.map Char.toLower s | |
62 | |
63 val q = "SELECT COUNT(*) FROM pg_class WHERE relname = '" | |
64 ^ sl ^ "'" | |
65 | |
66 val q' = String.concat ["SELECT COUNT(*) FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '", | |
67 sl, | |
68 "') AND (", | |
69 String.concatWith " OR " | |
70 (map (fn (x, t) => | |
71 String.concat ["(attname = 'uw_", | |
72 CharVector.map | |
73 Char.toLower (ident x), | |
74 "' AND atttypid = (SELECT oid FROM pg_type", | |
75 " WHERE typname = '", | |
76 p_sql_type_base t, | |
77 "') AND attnotnull = ", | |
78 if isNotNull t then | |
79 "TRUE" | |
80 else | |
81 "FALSE", | |
82 ")"]) xts), | |
83 ")"] | |
84 | |
85 val q'' = String.concat ["SELECT COUNT(*) FROM pg_attribute WHERE attrelid = (SELECT oid FROM pg_class WHERE relname = '", | |
86 sl, | |
87 "') AND attname LIKE 'uw_%'"] | |
88 in | |
89 box [string "res = PQexec(conn, \"", | |
90 string q, | |
91 string "\");", | |
92 newline, | |
93 newline, | |
94 string "if (res == NULL) {", | |
95 newline, | |
96 box [string "PQfinish(conn);", | |
97 newline, | |
98 string "uw_error(ctx, FATAL, \"Out of memory allocating query result.\");", | |
99 newline], | |
100 string "}", | |
101 newline, | |
102 newline, | |
103 string "if (PQresultStatus(res) != PGRES_TUPLES_OK) {", | |
104 newline, | |
105 box [string "char msg[1024];", | |
106 newline, | |
107 string "strncpy(msg, PQerrorMessage(conn), 1024);", | |
108 newline, | |
109 string "msg[1023] = 0;", | |
110 newline, | |
111 string "PQclear(res);", | |
112 newline, | |
113 string "PQfinish(conn);", | |
114 newline, | |
115 string "uw_error(ctx, FATAL, \"Query failed:\\n", | |
116 string q, | |
117 string "\\n%s\", msg);", | |
118 newline], | |
119 string "}", | |
120 newline, | |
121 newline, | |
122 string "if (strcmp(PQgetvalue(res, 0, 0), \"1\")) {", | |
123 newline, | |
124 box [string "PQclear(res);", | |
125 newline, | |
126 string "PQfinish(conn);", | |
127 newline, | |
128 string "uw_error(ctx, FATAL, \"Table '", | |
129 string s, | |
130 string "' does not exist.\");", | |
131 newline], | |
132 string "}", | |
133 newline, | |
134 newline, | |
135 string "PQclear(res);", | |
136 newline, | |
137 | |
138 string "res = PQexec(conn, \"", | |
139 string q', | |
140 string "\");", | |
141 newline, | |
142 newline, | |
143 string "if (res == NULL) {", | |
144 newline, | |
145 box [string "PQfinish(conn);", | |
146 newline, | |
147 string "uw_error(ctx, FATAL, \"Out of memory allocating query result.\");", | |
148 newline], | |
149 string "}", | |
150 newline, | |
151 newline, | |
152 string "if (PQresultStatus(res) != PGRES_TUPLES_OK) {", | |
153 newline, | |
154 box [string "char msg[1024];", | |
155 newline, | |
156 string "strncpy(msg, PQerrorMessage(conn), 1024);", | |
157 newline, | |
158 string "msg[1023] = 0;", | |
159 newline, | |
160 string "PQclear(res);", | |
161 newline, | |
162 string "PQfinish(conn);", | |
163 newline, | |
164 string "uw_error(ctx, FATAL, \"Query failed:\\n", | |
165 string q', | |
166 string "\\n%s\", msg);", | |
167 newline], | |
168 string "}", | |
169 newline, | |
170 newline, | |
171 string "if (strcmp(PQgetvalue(res, 0, 0), \"", | |
172 string (Int.toString (length xts)), | |
173 string "\")) {", | |
174 newline, | |
175 box [string "PQclear(res);", | |
176 newline, | |
177 string "PQfinish(conn);", | |
178 newline, | |
179 string "uw_error(ctx, FATAL, \"Table '", | |
180 string s, | |
181 string "' has the wrong column types.\");", | |
182 newline], | |
183 string "}", | |
184 newline, | |
185 newline, | |
186 string "PQclear(res);", | |
187 newline, | |
188 newline, | |
189 | |
190 string "res = PQexec(conn, \"", | |
191 string q'', | |
192 string "\");", | |
193 newline, | |
194 newline, | |
195 string "if (res == NULL) {", | |
196 newline, | |
197 box [string "PQfinish(conn);", | |
198 newline, | |
199 string "uw_error(ctx, FATAL, \"Out of memory allocating query result.\");", | |
200 newline], | |
201 string "}", | |
202 newline, | |
203 newline, | |
204 string "if (PQresultStatus(res) != PGRES_TUPLES_OK) {", | |
205 newline, | |
206 box [string "char msg[1024];", | |
207 newline, | |
208 string "strncpy(msg, PQerrorMessage(conn), 1024);", | |
209 newline, | |
210 string "msg[1023] = 0;", | |
211 newline, | |
212 string "PQclear(res);", | |
213 newline, | |
214 string "PQfinish(conn);", | |
215 newline, | |
216 string "uw_error(ctx, FATAL, \"Query failed:\\n", | |
217 string q'', | |
218 string "\\n%s\", msg);", | |
219 newline], | |
220 string "}", | |
221 newline, | |
222 newline, | |
223 string "if (strcmp(PQgetvalue(res, 0, 0), \"", | |
224 string (Int.toString (length xts)), | |
225 string "\")) {", | |
226 newline, | |
227 box [string "PQclear(res);", | |
228 newline, | |
229 string "PQfinish(conn);", | |
230 newline, | |
231 string "uw_error(ctx, FATAL, \"Table '", | |
232 string s, | |
233 string "' has extra columns.\");", | |
234 newline], | |
235 string "}", | |
236 newline, | |
237 newline, | |
238 string "PQclear(res);", | |
239 newline] | |
240 end) tables, | |
241 | |
242 p_list_sep newline | |
243 (fn s => | |
244 let | |
245 val sl = CharVector.map Char.toLower s | |
246 | |
247 val q = "SELECT COUNT(*) FROM pg_class WHERE relname = '" | |
248 ^ sl ^ "' AND relkind = 'S'" | |
249 in | |
250 box [string "res = PQexec(conn, \"", | |
251 string q, | |
252 string "\");", | |
253 newline, | |
254 newline, | |
255 string "if (res == NULL) {", | |
256 newline, | |
257 box [string "PQfinish(conn);", | |
258 newline, | |
259 string "uw_error(ctx, FATAL, \"Out of memory allocating query result.\");", | |
260 newline], | |
261 string "}", | |
262 newline, | |
263 newline, | |
264 string "if (PQresultStatus(res) != PGRES_TUPLES_OK) {", | |
265 newline, | |
266 box [string "char msg[1024];", | |
267 newline, | |
268 string "strncpy(msg, PQerrorMessage(conn), 1024);", | |
269 newline, | |
270 string "msg[1023] = 0;", | |
271 newline, | |
272 string "PQclear(res);", | |
273 newline, | |
274 string "PQfinish(conn);", | |
275 newline, | |
276 string "uw_error(ctx, FATAL, \"Query failed:\\n", | |
277 string q, | |
278 string "\\n%s\", msg);", | |
279 newline], | |
280 string "}", | |
281 newline, | |
282 newline, | |
283 string "if (strcmp(PQgetvalue(res, 0, 0), \"1\")) {", | |
284 newline, | |
285 box [string "PQclear(res);", | |
286 newline, | |
287 string "PQfinish(conn);", | |
288 newline, | |
289 string "uw_error(ctx, FATAL, \"Sequence '", | |
290 string s, | |
291 string "' does not exist.\");", | |
292 newline], | |
293 string "}", | |
294 newline, | |
295 newline, | |
296 string "PQclear(res);", | |
297 newline] | |
298 end) sequences, | |
299 | |
300 string "}", | |
301 | |
302 string "static void uw_db_prepare(uw_context ctx) {", | |
37 newline, | 303 newline, |
38 string "PGconn *conn = uw_get_db(ctx);", | 304 string "PGconn *conn = uw_get_db(ctx);", |
39 newline, | 305 newline, |
40 string "PGresult *res;", | 306 string "PGresult *res;", |
41 newline, | 307 newline, |
151 newline, | 417 newline, |
152 string "}", | 418 string "}", |
153 newline, | 419 newline, |
154 newline] | 420 newline] |
155 else | 421 else |
156 string "static void uw_db_prepare(uw_context ctx) { }", | 422 box [string "static void uw_db_validate(uw_context ctx) { }", |
423 newline, | |
424 string "static void uw_db_prepare(uw_context ctx) { }"], | |
425 | |
157 newline, | 426 newline, |
158 newline, | 427 newline, |
159 | 428 |
160 string "void uw_db_init(uw_context ctx) {", | 429 string "void uw_db_init(uw_context ctx) {", |
161 newline, | 430 newline, |
220 string ") ? NULL : ", | 489 string ") ? NULL : ", |
221 case t of | 490 case t of |
222 String => getter t | 491 String => getter t |
223 | _ => box [string "({", | 492 | _ => box [string "({", |
224 newline, | 493 newline, |
225 p_sql_type t, | 494 string (p_sql_type t), |
226 space, | 495 space, |
227 string "*tmp = uw_malloc(ctx, sizeof(", | 496 string "*tmp = uw_malloc(ctx, sizeof(", |
228 p_sql_type t, | 497 string (p_sql_type t), |
229 string "));", | 498 string "));", |
230 newline, | 499 newline, |
231 string "*tmp = ", | 500 string "*tmp = ", |
232 getter t, | 501 getter t, |
233 string ";", | 502 string ";", |
239 | _ => | 508 | _ => |
240 box [string "(PQgetisnull(res, i, ", | 509 box [string "(PQgetisnull(res, i, ", |
241 string (Int.toString i), | 510 string (Int.toString i), |
242 string ") ? ", | 511 string ") ? ", |
243 box [string "({", | 512 box [string "({", |
244 p_sql_type t, | 513 string (p_sql_type t), |
245 space, | 514 space, |
246 string "tmp;", | 515 string "tmp;", |
247 newline, | 516 newline, |
248 string "uw_error(ctx, FATAL, \"Unexpectedly NULL field #", | 517 string "uw_error(ctx, FATAL, \"Unexpectedly NULL field #", |
249 string (Int.toString i), | 518 string (Int.toString i), |