Updates with respect to the SQL table lat/lon y/x bug.
[handlerosm.git] / handler_osm_put.c
blob023a1ef49de011bccf435ca7eb022854ed7168d6
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 ret_t
208 cherokee_handler_osm_init_put (cherokee_handler_osm_t *hdl)
210 off_t postl;
211 ret_t ret = ret_ok;
212 cherokee_buffer_t post = CHEROKEE_BUF_INIT;
213 cherokee_buffer_t *buf;
214 cherokee_connection_t *conn = HANDLER_CONN(hdl);
215 axlDoc * doc;
216 axlError * error;
218 /* Check for the post info
220 cherokee_post_get_len (&conn->post, &postl);
221 if (postl <= 0 || postl >= (INT_MAX-1)) {
222 conn->error_code = http_bad_request;
223 return ret_error;
226 buf = &hdl->buffer;
228 /* Process line per line
230 cherokee_post_walk_read (&conn->post, &post, (cuint_t) postl);
232 TRACE("post", "%s\n", post.buf);
234 doc = axl_doc_parse (post.buf, post.len, &error);
236 if (doc == NULL) {
237 printf ("Error found: %s\n", axl_error_get (error));
238 axl_error_free (error);
239 return ret_error;
240 } else {
241 axlNode * node = axl_doc_get_root (doc);
242 node = axl_node_get_first_child (node);
243 unsigned long int nodeid = 0;
245 if (axl_node_has_attribute(node, "id")) {
246 const char *id = axl_node_get_attribute_value(node, "id");
247 nodeid = strtoul(id, (char **) NULL, 10);
248 TRACE("osm", "%lu\n", nodeid);
251 if (nodeid != 0) {
252 /* UPDATE */
253 if (NODE_CMP_NAME (node, "node")) {
254 if (axl_node_has_attribute(node, "lat") &&
255 axl_node_has_attribute(node, "lon")) {
256 double lat, lon;
257 lat = strtod(axl_node_get_attribute_value(node, "lat"), NULL);
258 if (errno == ERANGE) {
259 conn->error_code = http_bad_request;
260 return ret_error;
263 lon = strtod(axl_node_get_attribute_value(node, "lon"), NULL);
264 if (errno == ERANGE) {
265 conn->error_code = http_bad_request;
266 return ret_error;
267 } else {
268 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
269 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
270 run_sql(hdl, &sql1, NULL, NULL);
271 cherokee_buffer_mrproper(&sql1);
272 cherokee_buffer_add_va (&sql1, SQL_NODE_UPDATE_BY_ID, lat, lon, 0, nodeid);
273 run_sql(hdl, &sql1, NULL, NULL);
274 cherokee_buffer_mrproper(&sql1);
276 do_tags(hdl, node, nodeid, 1, SQL_NODE_CREATE_NODE_TAG, SQL_NODE_UPDATE_NODE_TAG, SQL_NODE_DELETE_NODE_TAG);
278 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
279 run_sql(hdl, &sql1, buf, NULL);
280 cherokee_buffer_mrproper(&sql1);
283 } else if (NODE_CMP_NAME (node, "way")) {
284 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
285 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
286 run_sql(hdl, &sql1, buf, NULL);
287 cherokee_buffer_mrproper(&sql1);
289 cherokee_buffer_add_va (&sql1, SQL_RELATION_UPDATE, 0, nodeid);
290 run_sql(hdl, &sql1, NULL, NULL);
291 cherokee_buffer_mrproper(&sql1);
293 do_tags(hdl, node, nodeid, 1, SQL_WAY_CREATE_NODE_TAG, SQL_WAY_UPDATE_NODE_TAG, SQL_WAY_DELETE_NODE_TAG);
294 do_nds(hdl, node, nodeid, 1); /* this sequence otherwise we screw up type = */
296 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
297 run_sql(hdl, &sql1, buf, NULL);
298 cherokee_buffer_mrproper(&sql1);
299 } else if (NODE_CMP_NAME (node, "relation")) {
300 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
301 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
302 run_sql(hdl, &sql1, buf, NULL);
303 cherokee_buffer_mrproper(&sql1);
305 cherokee_buffer_add_va (&sql1, SQL_RELATION_UPDATE, 0, nodeid);
306 run_sql(hdl, &sql1, NULL, NULL);
307 cherokee_buffer_mrproper(&sql1);
309 do_members(hdl, node, nodeid, 1);
310 do_tags(hdl, node, nodeid, 1, SQL_RELATION_CREATE_NODE_TAG, SQL_RELATION_UPDATE_NODE_TAG, SQL_RELATION_DELETE_NODE_TAG);
312 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
313 run_sql(hdl, &sql1, buf, NULL);
314 cherokee_buffer_mrproper(&sql1);
316 } else {
317 /* CREATE */
318 if (NODE_CMP_NAME (node, "node")) {
319 if (axl_node_has_attribute(node, "lat") &&
320 axl_node_has_attribute(node, "lon")) {
321 double lat, lon;
322 lat = strtod(axl_node_get_attribute_value(node, "lat"), NULL);
323 if (errno == ERANGE) {
324 conn->error_code = http_bad_request;
325 return ret_error;
328 lon = strtod(axl_node_get_attribute_value(node, "lon"), NULL);
329 if (errno == ERANGE) {
330 conn->error_code = http_bad_request;
331 return ret_error;
332 } else {
333 /* TODO: more error checking */
334 long testid = 0;
335 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
337 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
338 run_sql(hdl, &sql1, buf, NULL);
339 cherokee_buffer_mrproper(&sql1);
341 cherokee_buffer_add_va (&sql1, SQL_NODE_CREATE, lat, lon, 0);
342 run_sql(hdl, &sql1, buf, result_node_last_id);
343 cherokee_buffer_mrproper(&sql1);
345 testid = strtol(buf->buf, (char **) NULL, 10);
346 if (errno != ERANGE && testid > 0) {
347 nodeid = testid;
349 do_tags(hdl, node, nodeid, 0, SQL_NODE_CREATE_NODE_TAG, SQL_NODE_UPDATE_NODE_TAG, SQL_NODE_DELETE_NODE_TAG);
351 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
352 run_sql(hdl, &sql1, buf, NULL);
353 cherokee_buffer_mrproper(&sql1);
354 } else {
355 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
356 run_sql(hdl, &sql1, buf, NULL);
357 cherokee_buffer_mrproper(&sql1);
361 } else if (NODE_CMP_NAME (node, "way")) {
362 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
363 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
364 run_sql(hdl, &sql1, buf, NULL);
365 cherokee_buffer_mrproper(&sql1);
367 cherokee_buffer_add_va (&sql1, SQL_WAY_CREATE, 0);
368 run_sql(hdl, &sql1, buf, result_node_last_id);
369 cherokee_buffer_mrproper(&sql1);
371 long testid = 0;
372 testid = strtol(buf->buf, (char **) NULL, 10);
373 if (errno != ERANGE && testid > 0) {
374 nodeid = testid;
376 do_tags(hdl, node, nodeid, 0, SQL_WAY_CREATE_NODE_TAG, SQL_WAY_UPDATE_NODE_TAG, SQL_WAY_DELETE_NODE_TAG);
377 do_nds(hdl, node, nodeid, 0); /* this sequence otherwise we screw up type= */
379 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
380 run_sql(hdl, &sql1, buf, NULL);
381 cherokee_buffer_mrproper(&sql1);
382 } else {
383 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
384 run_sql(hdl, &sql1, buf, NULL);
385 cherokee_buffer_mrproper(&sql1);
387 } else if (NODE_CMP_NAME (node, "relation")) {
388 cherokee_buffer_t sql1 = CHEROKEE_BUF_INIT;
389 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_START);
390 run_sql(hdl, &sql1, buf, NULL);
391 cherokee_buffer_mrproper(&sql1);
393 cherokee_buffer_add_va (&sql1, SQL_RELATION_CREATE, 0);
394 run_sql(hdl, &sql1, buf, result_node_last_id);
395 cherokee_buffer_mrproper(&sql1);
397 long testid = 0;
398 testid = strtol(buf->buf, (char **) NULL, 10);
399 if (errno != ERANGE && testid > 0) {
400 nodeid = testid;
401 do_members(hdl, node, nodeid, 0);
402 do_tags(hdl, node, nodeid, 0, SQL_RELATION_CREATE_NODE_TAG, SQL_RELATION_UPDATE_NODE_TAG, SQL_RELATION_DELETE_NODE_TAG);
404 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_COMMIT);
405 run_sql(hdl, &sql1, buf, NULL);
406 cherokee_buffer_mrproper(&sql1);
407 } else {
408 cherokee_buffer_add_str (&sql1, SQL_TRANSACTION_ROLLBACK);
409 run_sql(hdl, &sql1, buf, NULL);
410 cherokee_buffer_mrproper(&sql1);
414 axl_doc_free (doc);
417 cherokee_buffer_mrproper (&post);
418 return ret;