We have splitted up the create/update code in two distinct part as prepartion for the
[handlerosm.git] / handler_osm_put.c
blob36d4b123d7ac609827a19418ab8c300d081f1153
1 #include <cherokee/common-internal.h>
2 #include <cherokee/cherokee.h>
3 #include <Mapi.h>
4 #include <axl.h>
6 #include "handler_osm.h"
7 #include "handler_osm_db.h"
8 #include "handler_osm_put.h"
9 #include "handler_osm_sql.h"
11 static ret_t result_node_last_id(cherokee_handler_osm_t *hdl, MapiHdl *hdl1, cherokee_buffer_t *buf) {
12 cherokee_buffer_add_va (buf, "%d", mapi_get_last_id(*hdl1));
13 return ret_ok;
16 static ret_t node_update_or_insert (cherokee_handler_osm_t *hdl, MapiHdl *hdl1, cherokee_buffer_t *buf) {
17 if (mapi_rows_affected(*hdl1) == 0)
18 return ret_error;
20 return ret_ok;
23 static void do_members(cherokee_handler_osm_t *hdl, axlNode *node, unsigned long int relationid, unsigned short int update) {
24 axlNode * member;
25 if ((member = axl_node_get_first_child(node)) != NULL) {
26 cherokee_buffer_t members_node = CHEROKEE_BUF_INIT;
27 cherokee_buffer_t members_way = CHEROKEE_BUF_INIT;
28 cherokee_buffer_t members_relation = CHEROKEE_BUF_INIT;
29 unsigned long int idx = 0;
30 do {
31 if (NODE_CMP_NAME (member, "member") &&
32 axl_node_has_attribute(member, "type") &&
33 axl_node_has_attribute(member, "ref") &&
34 axl_node_has_attribute(member, "role")) {
36 unsigned long int ref = strtod(axl_node_get_attribute_value(member, "ref"), NULL);
37 if (errno != ERANGE && ref > 0) {
38 const char *type = axl_node_get_attribute_value(member, "type");
39 const char *role = axl_node_get_attribute_value(member, "role");
41 if (strcmp(type, "node") == 0) {
42 cherokee_buffer_add_va (&members_node, "%lu, ", ref);
43 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
44 if (update == 1) {
45 cherokee_buffer_add_va (&sql1, "UPDATE relation_members_node SET to_node = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref, role, relationid, idx);
47 if (update == 0 || run_sql(hdl, &sql1, NULL, node_update_or_insert) == ret_error) {
48 cherokee_buffer_mrproper(&sql1);
49 cherokee_buffer_add_va (&sql1, "INSERT INTO relation_members_node (relation, idx, to_node, role) VALUES (%lu, %lu, %lu, '%s')", relationid, idx, ref, role);
50 run_sql(hdl, &sql1, NULL, NULL);
52 cherokee_buffer_mrproper(&sql1);
53 } else if (strcmp(type, "way") == 0) {
54 cherokee_buffer_add_va (&members_way, "%lu, ", ref);
55 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
56 if (update == 1) {
57 cherokee_buffer_add_va (&sql1, "UPDATE relation_members_way SET to_way = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref, role, relationid, idx);
59 if (update == 0 || run_sql(hdl, &sql1, NULL, node_update_or_insert) == ret_error) {
60 cherokee_buffer_mrproper(&sql1);
61 cherokee_buffer_add_va (&sql1, "INSERT INTO relation_members_way (relation, idx, to_way, role) VALUES (%lu, %lu, %lu, '%s')", relationid, idx, ref, role);
62 run_sql(hdl, &sql1, NULL, NULL);
64 cherokee_buffer_mrproper(&sql1);
65 } else if (strcmp(type, "relation") == 0) {
66 cherokee_buffer_add_va (&members_relation, "%lu, ", ref);
67 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
68 if (update == 1) {
69 cherokee_buffer_add_va (&sql1, "UPDATE relation_members_relation SET to_relation = %lu, role = '%s' WHERE relation = %lu AND idx = %lu", ref, role, relationid, idx);
71 if (update == 0 || run_sql(hdl, &sql1, NULL, node_update_or_insert) == ret_error) {
72 cherokee_buffer_mrproper(&sql1);
73 cherokee_buffer_add_va (&sql1, "INSERT INTO relation_members_relation (relation, idx, to_relation, role) VALUES (%lu, %lu, %lu, '%s')", relationid, idx, ref, role);
74 run_sql(hdl, &sql1, NULL, NULL);
76 cherokee_buffer_mrproper(&sql1);
77 } else {
78 TRACE("osm", "%s: New type?\n", type);
80 idx++;
83 } while ((member = axl_node_get_next(member)) != NULL);
85 if (members_node.len > 0) {
86 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
87 cherokee_buffer_drop_ending(&members_node, 2);
88 cherokee_buffer_add_va (&sql1, "DELETE FROM relation_members_node WHERE relation = %lu AND to_node NOT IN (%s)", relationid, members_node.buf);
89 run_sql(hdl, &sql1, NULL, NULL);
90 cherokee_buffer_mrproper(&sql1);
92 cherokee_buffer_mrproper(&members_node);
94 if (members_way.len > 0) {
95 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
96 cherokee_buffer_drop_ending(&members_way, 2);
97 cherokee_buffer_add_va (&sql1, "DELETE FROM relation_members_way WHERE relation = %lu AND to_way NOT IN (%s)", relationid, members_way.buf);
98 run_sql(hdl, &sql1, NULL, NULL);
99 cherokee_buffer_mrproper(&sql1);
101 cherokee_buffer_mrproper(&members_way);
103 if (members_relation.len > 0) {
104 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
105 cherokee_buffer_drop_ending(&members_relation, 2);
106 cherokee_buffer_add_va (&sql1, "DELETE FROM relation_members_relation WHERE relation = %lu AND to_relation NOT IN (%s)", relationid, members_relation.buf);
107 run_sql(hdl, &sql1, NULL, NULL);
108 cherokee_buffer_mrproper(&sql1);
110 cherokee_buffer_mrproper(&members_relation);
116 static void do_nds(cherokee_handler_osm_t *hdl, axlNode *node, unsigned long int wayid, unsigned short int update) {
117 axlNode * nd;
118 if ((nd = axl_node_get_first_child(node)) != NULL) {
119 cherokee_buffer_t nds = CHEROKEE_BUF_INIT;
120 unsigned long int idx = 0;
121 do {
122 if (NODE_CMP_NAME (nd, "nd") &&
123 axl_node_has_attribute(nd, "ref")) {
125 unsigned long int ref = strtod(axl_node_get_attribute_value(nd, "ref"), NULL);
126 if (errno != ERANGE && ref > 0) {
127 cherokee_buffer_add_va (&nds, "%lu, ", ref);
129 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
130 if (update == 1) {
131 cherokee_buffer_add_va (&sql1, "UPDATE way_nds SET to_node = %lu WHERE way = %lu AND idx = %lu", ref, wayid, idx);
133 if (update == 0 || run_sql(hdl, &sql1, NULL, node_update_or_insert) == ret_error) {
134 cherokee_buffer_mrproper(&sql1);
135 cherokee_buffer_add_va (&sql1, "INSERT INTO way_nds (way, idx, to_node) VALUES (%lu, %lu, %lu)", wayid, idx, ref);
136 run_sql(hdl, &sql1, NULL, NULL);
138 cherokee_buffer_mrproper(&sql1);
139 idx++;
142 } while ((nd = axl_node_get_next(nd)) != NULL);
144 if (nds.len > 0) {
145 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
146 cherokee_buffer_drop_ending(&nds, 2);
147 cherokee_buffer_add_va (&sql1, "DELETE FROM way_nds WHERE relation = %lu AND to_node NOT IN (%s)", wayid, nds.buf);
148 run_sql(hdl, &sql1, NULL, NULL);
149 cherokee_buffer_mrproper(&sql1);
152 cherokee_buffer_mrproper(&nds);
156 static void do_tags(cherokee_handler_osm_t *hdl, axlNode *node, unsigned long int nodeid, unsigned short int update, char *create_sql, char *update_sql, char *delete_sql) {
157 axlNode * tag;
158 if ((tag = axl_node_get_first_child(node)) != NULL) {
159 cherokee_buffer_t keys = CHEROKEE_BUF_INIT;
160 do {
161 if (NODE_CMP_NAME (tag, "tag") &&
162 axl_node_has_attribute(tag, "k") &&
163 axl_node_has_attribute(tag, "v")) {
164 const char * key = axl_node_get_attribute_value(tag, "k");
165 size_t keylen = strlen(key);
167 if (keylen > 0 && keylen < 256) {
168 const char * value = axl_node_get_attribute_value(tag, "v");
169 size_t valuelen = strlen(value);
170 cherokee_buffer_add_va (&keys, "\'%s\', ", key);
172 if (valuelen > 0 && valuelen < 256) {
173 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
174 if (update == 1) {
175 cherokee_buffer_add_va (&sql1, update_sql,
176 value,
177 nodeid,
181 if (update == 0 || run_sql(hdl, &sql1, NULL, node_update_or_insert) == ret_error) {
182 cherokee_buffer_mrproper(&sql1);
183 cherokee_buffer_add_va (&sql1, create_sql,
184 nodeid,
185 key,
186 value);
187 run_sql(hdl, &sql1, NULL, NULL);
189 cherokee_buffer_mrproper(&sql1);
193 } while ((tag = axl_node_get_next(tag)) != NULL);
195 if (keys.len > 0) {
196 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
197 cherokee_buffer_drop_ending(&keys, 2);
198 cherokee_buffer_add_va (&sql1, delete_sql, nodeid, keys.buf);
199 run_sql(hdl, &sql1, NULL, NULL);
200 cherokee_buffer_mrproper(&sql1);
203 cherokee_buffer_mrproper(&keys);
207 static ret_t
208 create_node(cherokee_handler_osm_t *hdl, axlNode * node) {
209 cherokee_connection_t *conn = HANDLER_CONN(hdl);
210 cherokee_buffer_t *buf;
211 buf = &hdl->buffer;
213 if (NODE_CMP_NAME (node, "node")) {
214 if (axl_node_has_attribute(node, "lat") &&
215 axl_node_has_attribute(node, "lon")) {
216 double lat, lon;
217 lat = strtod(axl_node_get_attribute_value(node, "lat"), NULL);
218 if (errno == ERANGE) {
219 conn->error_code = http_bad_request;
220 return ret_error;
223 lon = strtod(axl_node_get_attribute_value(node, "lon"), NULL);
224 if (errno == ERANGE) {
225 conn->error_code = http_bad_request;
226 return ret_error;
227 } else {
228 /* TODO: more error checking */
229 long testid = 0;
230 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
232 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
233 run_sql(hdl, &sql1, buf, NULL);
234 cherokee_buffer_mrproper(&sql1);
236 cherokee_buffer_add_va (&sql1, SQL_NODE_CREATE, lon, lat, 0);
237 run_sql(hdl, &sql1, buf, result_node_last_id);
238 cherokee_buffer_mrproper(&sql1);
240 testid = strtol(buf->buf, (char **) NULL, 10);
241 if (errno != ERANGE && testid > 0) {
242 do_tags(hdl, node, testid, 0, SQL_NODE_CREATE_NODE_TAG, SQL_NODE_UPDATE_NODE_TAG, SQL_NODE_DELETE_NODE_TAG);
244 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
245 run_sql(hdl, &sql1, buf, NULL);
246 cherokee_buffer_mrproper(&sql1);
247 } else {
248 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
249 run_sql(hdl, &sql1, buf, NULL);
250 cherokee_buffer_mrproper(&sql1);
254 } else if (NODE_CMP_NAME (node, "way")) {
255 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
256 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
257 run_sql(hdl, &sql1, buf, NULL);
258 cherokee_buffer_mrproper(&sql1);
260 cherokee_buffer_add_va (&sql1, SQL_WAY_CREATE, 0);
261 run_sql(hdl, &sql1, buf, result_node_last_id);
262 cherokee_buffer_mrproper(&sql1);
264 long testid = 0;
265 testid = strtol(buf->buf, (char **) NULL, 10);
266 if (errno != ERANGE && testid > 0) {
267 do_tags(hdl, node, testid, 0, SQL_WAY_CREATE_NODE_TAG, SQL_WAY_UPDATE_NODE_TAG, SQL_WAY_DELETE_NODE_TAG);
268 do_nds(hdl, node, testid, 0); /* this sequence otherwise we screw up type= */
270 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
271 run_sql(hdl, &sql1, buf, NULL);
272 cherokee_buffer_mrproper(&sql1);
273 } else {
274 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
275 run_sql(hdl, &sql1, buf, NULL);
276 cherokee_buffer_mrproper(&sql1);
278 } else if (NODE_CMP_NAME (node, "relation")) {
279 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
280 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
281 run_sql(hdl, &sql1, buf, NULL);
282 cherokee_buffer_mrproper(&sql1);
284 cherokee_buffer_add_va (&sql1, SQL_RELATION_CREATE, 0);
285 run_sql(hdl, &sql1, buf, result_node_last_id);
286 cherokee_buffer_mrproper(&sql1);
288 long testid = 0;
289 testid = strtol(buf->buf, (char **) NULL, 10);
290 if (errno != ERANGE && testid > 0) {
291 do_members(hdl, node, testid, 0);
292 do_tags(hdl, node, testid, 0, SQL_RELATION_CREATE_NODE_TAG, SQL_RELATION_UPDATE_NODE_TAG, SQL_RELATION_DELETE_NODE_TAG);
294 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
295 run_sql(hdl, &sql1, buf, NULL);
296 cherokee_buffer_mrproper(&sql1);
297 } else {
298 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
299 run_sql(hdl, &sql1, buf, NULL);
300 cherokee_buffer_mrproper(&sql1);
303 return ret_ok;
306 static ret_t
307 update_node(cherokee_handler_osm_t *hdl, axlNode * node, unsigned long int nodeid) {
308 cherokee_connection_t *conn = HANDLER_CONN(hdl);
309 cherokee_buffer_t *buf;
310 buf = &hdl->buffer;
312 if (NODE_CMP_NAME (node, "node")) {
313 if (axl_node_has_attribute(node, "lat") &&
314 axl_node_has_attribute(node, "lon")) {
315 double lat, lon;
316 lat = strtod(axl_node_get_attribute_value(node, "lat"), NULL);
317 if (errno == ERANGE) {
318 conn->error_code = http_bad_request;
319 return ret_error;
322 lon = strtod(axl_node_get_attribute_value(node, "lon"), NULL);
323 if (errno == ERANGE) {
324 conn->error_code = http_bad_request;
325 return ret_error;
326 } else {
327 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
328 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
329 run_sql(hdl, &sql1, NULL, NULL);
330 cherokee_buffer_mrproper(&sql1);
331 cherokee_buffer_add_va (&sql1, SQL_NODE_UPDATE_BY_ID, lon, lat, 0, nodeid);
332 run_sql(hdl, &sql1, NULL, NULL);
333 cherokee_buffer_mrproper(&sql1);
335 do_tags(hdl, node, nodeid, 1, SQL_NODE_CREATE_NODE_TAG, SQL_NODE_UPDATE_NODE_TAG, SQL_NODE_DELETE_NODE_TAG);
337 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
338 run_sql(hdl, &sql1, buf, NULL);
339 cherokee_buffer_mrproper(&sql1);
342 } else if (NODE_CMP_NAME (node, "way")) {
343 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
344 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
345 run_sql(hdl, &sql1, buf, NULL);
346 cherokee_buffer_mrproper(&sql1);
348 cherokee_buffer_add_va (&sql1, SQL_RELATION_UPDATE, 0, nodeid);
349 run_sql(hdl, &sql1, NULL, NULL);
350 cherokee_buffer_mrproper(&sql1);
352 do_tags(hdl, node, nodeid, 1, SQL_WAY_CREATE_NODE_TAG, SQL_WAY_UPDATE_NODE_TAG, SQL_WAY_DELETE_NODE_TAG);
353 do_nds(hdl, node, nodeid, 1); /* this sequence otherwise we screw up type = */
355 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
356 run_sql(hdl, &sql1, buf, NULL);
357 cherokee_buffer_mrproper(&sql1);
358 } else if (NODE_CMP_NAME (node, "relation")) {
359 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
360 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
361 run_sql(hdl, &sql1, buf, NULL);
362 cherokee_buffer_mrproper(&sql1);
364 cherokee_buffer_add_va (&sql1, SQL_RELATION_UPDATE, 0, nodeid);
365 run_sql(hdl, &sql1, NULL, NULL);
366 cherokee_buffer_mrproper(&sql1);
368 do_members(hdl, node, nodeid, 1);
369 do_tags(hdl, node, nodeid, 1, SQL_RELATION_CREATE_NODE_TAG, SQL_RELATION_UPDATE_NODE_TAG, SQL_RELATION_DELETE_NODE_TAG);
371 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
372 run_sql(hdl, &sql1, buf, NULL);
373 cherokee_buffer_mrproper(&sql1);
375 return ret_ok;
380 ret_t
381 cherokee_handler_osm_init_put (cherokee_handler_osm_t *hdl)
383 off_t postl;
384 ret_t ret = ret_ok;
385 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
386 cherokee_connection_t *conn = HANDLER_CONN(hdl);
387 axlDoc * doc;
388 axlError * error;
390 /* Check for the post info
392 cherokee_post_get_len (&conn->post, &postl);
393 if (postl <= 0 || postl >= (INT_MAX-1)) {
394 conn->error_code = http_bad_request;
395 return ret_error;
399 /* Process line per line
401 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
403 TRACE("post", "%s\n", post.buf);
405 doc = axl_doc_parse (post.buf, post.len, &error);
407 if (doc == NULL) {
408 printf ("Error found: %s\n", axl_error_get (error));
409 axl_error_free (error);
410 ret = ret_error;
411 } else {
412 axlNode * node = axl_doc_get_root (doc);
413 node = axl_node_get_first_child (node);
414 unsigned long int nodeid = 0;
416 if (axl_node_has_attribute(node, "id")) {
417 const char *id = axl_node_get_attribute_value(node, "id");
418 nodeid = strtoul(id, (char **) NULL, 10);
419 TRACE("osm", "%lu\n", nodeid);
422 /* het mooiste zou zijn om het onderstaande in twee functies te zetten
423 * update vs create.
424 * Als dat gebeurd is kan hier (of in de 'update' code gechecked worden
425 * op 'root' of op normale user en aan de hand daarvan weer switchen op
426 * empty == create of full == update)
429 if (nodeid != 0) {
430 /* UPDATE */
431 ret = update_node(hdl, node, nodeid);
432 } else {
433 /* CREATE */
434 ret = create_node(hdl, node);
437 axl_doc_free (doc);
440 cherokee_buffer_mrproper (&post);
441 return ret;