source: subversion/sites/rails_port_branches/api06/db/migrate/017_populate_node_tags_and_remove_helper.c @ 11390

Revision 11390, 5.3 KB checked in by smsm1, 5 years ago (diff)

Fixing the error messages

Line 
1#include <mysql.h>
2#include <stdint.h>
3#include <stdio.h>
4#include <stdlib.h>
5#include <string.h>
6
7static void exit_mysql_err(MYSQL *mysql) {
8  const char *err = mysql_error(mysql);
9  if (err) {
10    fprintf(stderr, "017_populate_node_tags_and_remove_helper: MySQL error: %s\n", err);
11  } else {
12    fprintf(stderr, "017_populate_node_tags_and_remove_helper: MySQL error\n");
13  }
14  abort();
15  exit(EXIT_FAILURE);
16}
17
18static void write_csv_col(FILE *f, const char *str, char end) {
19  char *out = (char *) malloc(2 * strlen(str) + 4);
20  char *o = out;
21  size_t len;
22
23  *(o++) = '\"';
24  for (; *str; str++) {
25    if (*str == '\0') {
26      break;
27    } else if (*str == '\"') {
28      *(o++) = '\"';
29      *(o++) = '\"';
30    } else {
31      *(o++) = *str;
32    }
33  }
34  *(o++) = '\"';
35  *(o++) = end;
36  *(o++) = '\0';
37
38  len = strlen(out);
39  if (fwrite(out, len, 1, f) != 1) {
40    perror("fwrite");
41    exit(EXIT_FAILURE);
42  }
43
44  free(out);
45}
46
47static void unescape(char *str) {
48  char *i = str, *o = str, tmp;
49
50  while (*i) {
51    if (*i == '\\') {
52      i++;
53      switch (tmp = *i++) {
54        case 's': *o++ = ';'; break;
55        case 'e': *o++ = '='; break;
56        case '\\': *o++ = '\\'; break;
57        default: *o++ = tmp; break;
58      }
59    } else {
60      *o++ = *i++;
61    }
62  }
63}
64
65static int read_node_tags(char **tags, char **k, char **v) {
66  if (!**tags) return 0;
67  char *i = strchr(*tags, ';');
68  if (!i) i = *tags + strlen(*tags);
69  char *j = strchr(*tags, '=');
70  *k = *tags;
71  if (j && j < i) {
72    *v = j + 1;
73  } else {
74    *v = i;
75  }
76  *tags = *i ? i + 1 : i;
77  *i = '\0';
78  if (j) *j = '\0';
79
80  unescape(*k);
81  unescape(*v);
82
83  return 1;
84}
85
86struct data {
87  MYSQL *mysql;
88  size_t version_size;
89  uint16_t *version;
90};
91
92static void proc_nodes(struct data *d, const char *tbl, FILE *out, FILE *out_tags, int hist) {
93  MYSQL_RES *res;
94  MYSQL_ROW row;
95  char query[256];
96
97  snprintf(query, sizeof(query),  "SELECT id, latitude, longitude, "
98      "user_id, visible, tags, timestamp, tile FROM %s", tbl);
99  if (mysql_query(d->mysql, query))
100    exit_mysql_err(d->mysql);
101
102  res = mysql_use_result(d->mysql);
103  if (!res) exit_mysql_err(d->mysql);
104
105  while ((row = mysql_fetch_row(res))) {
106    unsigned long id = strtoul(row[0], NULL, 10);
107    uint32_t version;
108
109    if (id >= d->version_size) {
110      fprintf(stderr, "preallocated nodes size exceeded");
111      abort();
112    }
113
114    if (hist) {
115      version = ++(d->version[id]);
116
117      fprintf(out, "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%u\"\n",
118        row[0], row[1], row[2], row[3], row[4], row[6], row[7], version);
119    } else {
120      /*fprintf(out, "\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"\n",
121        row[0], row[1], row[2], row[3], row[4], row[6], row[7]);*/
122    }
123
124    char *tags_it = row[5], *k, *v;
125    while (read_node_tags(&tags_it, &k, &v)) {
126      if (hist) {
127        fprintf(out_tags, "\"%s\",\"%u\",", row[0], version);
128      } else {
129        fprintf(out_tags, "\"%s\",", row[0]);
130      }
131
132      write_csv_col(out_tags, k, ',');
133      write_csv_col(out_tags, v, '\n');
134    }
135  }
136  if (mysql_errno(d->mysql)) exit_mysql_err(d->mysql);
137
138  mysql_free_result(res);
139}
140
141static size_t select_size(MYSQL *mysql, const char *q) {
142  MYSQL_RES *res;
143  MYSQL_ROW row;
144  size_t ret;
145
146  if (mysql_query(mysql, q))
147    exit_mysql_err(mysql);
148
149  res = mysql_store_result(mysql);
150  if (!res) exit_mysql_err(mysql);
151
152  row = mysql_fetch_row(res);
153  if (!row) exit_mysql_err(mysql);
154
155  if (row[0]) {
156    ret = strtoul(row[0], NULL, 10);
157  } else {
158    ret = 0;
159  }
160
161  mysql_free_result(res);
162
163  return ret;
164}
165
166static MYSQL *connect_to_mysql(char **argv) {
167  MYSQL *mysql = mysql_init(NULL);
168  if (!mysql) exit_mysql_err(mysql);
169
170  if (!mysql_real_connect(mysql, argv[1], argv[2], argv[3], argv[4],
171      argv[5][0] ? atoi(argv[5]) : 0, argv[6][0] ? argv[6] : NULL, 0))
172    exit_mysql_err(mysql);
173
174  if (mysql_set_character_set(mysql, "utf8"))
175    exit_mysql_err(mysql);
176
177  return mysql;
178}
179
180static void open_file(FILE **f, char *fn) {
181  *f = fopen(fn, "w+");
182  if (!*f) {
183    perror("fopen");
184    exit(EXIT_FAILURE);
185  }
186}
187
188int main(int argc, char **argv) {
189  size_t prefix_len;
190  FILE *current_nodes, *current_node_tags, *nodes, *node_tags;
191  char *tempfn;
192  struct data data, *d = &data;
193
194  if (argc != 8) {
195    printf("Usage: 017_populate_node_tags_and_remove_helper host user passwd database port socket prefix\n");
196    exit(EXIT_FAILURE);
197  }
198
199  d->mysql = connect_to_mysql(argv);
200
201  d->version_size = 1 + select_size(d->mysql, "SELECT max(id) FROM current_nodes");
202  d->version = (uint16_t *) malloc(sizeof(uint16_t) * d->version_size);
203  if (!d->version) {
204    perror("malloc");
205    abort();
206    exit(EXIT_FAILURE);
207  }
208  memset(d->version, 0, sizeof(uint16_t) * d->version_size);
209
210  prefix_len = strlen(argv[7]);
211  tempfn = (char *) malloc(prefix_len + 32);
212  strcpy(tempfn, argv[7]);
213
214  strcpy(tempfn + prefix_len, "current_nodes");
215  open_file(&current_nodes, tempfn);
216
217  strcpy(tempfn + prefix_len, "current_node_tags");
218  open_file(&current_node_tags, tempfn);
219
220  strcpy(tempfn + prefix_len, "nodes");
221  open_file(&nodes, tempfn);
222
223  strcpy(tempfn + prefix_len, "node_tags");
224  open_file(&node_tags, tempfn);
225
226  free(tempfn);
227
228  proc_nodes(d, "nodes", nodes, node_tags, 1);
229  proc_nodes(d, "current_nodes", current_nodes, current_node_tags, 0);
230
231  free(d->version);
232
233  mysql_close(d->mysql);
234
235  fclose(current_nodes);
236  fclose(current_node_tags);
237  fclose(nodes);
238  fclose(node_tags);
239
240  exit(EXIT_SUCCESS);
241}
Note: See TracBrowser for help on using the repository browser.