15 * <tag k=".." v=".." />
28 # define stopcondition (start = ++end) < (range + max)
29 # define nextline start = end + 1
31 # define nextline free(start); start = NULL; tmp = getline(&start, &tmplen, stdin); if (tmp == -1) { goto exit; }
32 # define stopcondition 1
35 #define file_delete_nodes "delete_nodes.csv"
36 #define file_delete_ways "delete_ways.csv"
37 #define file_delete_relations "delete_relations.csv"
39 #define file_modify_nodes "modify_nodes.csv"
40 #define file_modify_ways "modify_ways.csv"
41 #define file_modify_relations "modify_relations.csv"
43 #define file_nodes "nodes.csv"
46 #define file_nodes_uint "nodes_uint.csv"
47 #define file_nodes_gis "nodes_gis.csv"
50 #define file_node_tags "node_tags.csv"
51 #define file_ways "ways.csv"
52 #define file_way_tags "way_tags.csv"
53 #define file_way_nds "way_nds.csv"
54 #define file_relations "relations.csv"
55 #define file_relation_tags "relation_tags.csv"
56 #define file_relation_member_node "relation_member_node.csv"
57 #define file_relation_member_relation "relation_member_relation.csv"
58 #define file_relation_member_way "relation_member_way.csv"
60 unsigned int coordtouint(char *input
) {
61 double maxbit
= (double) 4294967296.0 / (double) 360.0;
62 double proper
= strtod(input
, NULL
) * maxbit
;
63 return (unsigned int) proper
;
66 char * escape_string(char *instr
)
68 unsigned int i
, j
=0, need
= 0;
69 unsigned int len
= strlen(instr
);
73 if (instr
[i
]=='\\' || instr
[i
]=='\'') need
++;
76 outstr
= malloc(len
+ 1);
78 for (i
=0;i
<=strlen(instr
);i
++) {
79 if (instr
[i
]=='\\' || instr
[i
]=='\'')
87 static void parser(char *range
, unsigned long int max
) {
89 static void parser() {
91 typedef enum { NONE
= 0, CREATE
= 1, MODIFY
= 2, DELETE
= 3 } ywk_state_t
;
92 typedef enum { OSM
= 0, NODE
= 1, WAY
= 2, RELATION
= 3, TAG
= 4, ND
= 5, MEMBER
= 6 } osm_state_t
;
93 typedef enum { UNKNOWN
= 0, ID
, LAT
, LON
, USER
, UID
, TIMESTAMP
, KEY
, VALUE
, TYPE
, REF
, ROLE
} key_state_t
;
94 char *attr_id
= NULL
, *attr_lat
= NULL
, *attr_lon
= NULL
, *attr_user
= NULL
, *attr_uid
= NULL
, *attr_timestamp
= NULL
, *attr_key
= NULL
, *attr_value
= NULL
,
95 *attr_type
= NULL
, *attr_ref
= NULL
, *attr_role
= NULL
;
97 unsigned int attr_lat_uint
= 0;
98 unsigned int attr_lon_uint
= 0;
101 unsigned long int count_nodes
= 0, count_node_tags
= 0,
102 count_ways
= 0, count_way_tags
= 0, count_way_nds
= 0,
103 count_relations
= 0, count_relation_tags
= 0, count_members_node
= 0, count_members_relation
= 0, count_members_way
= 0;
105 unsigned long int sequence
= 0;
107 ywk_state_t ywk
= CREATE
;
108 osm_state_t current_tag
= OSM
;
109 osm_state_t parent_tag
= OSM
;
111 char *start
= NULL
, *end
, *nodename
, *nodename_end
;
120 end
= strchrnul((const char*) start
, '\n');
122 if (strncmp(start
, "<?xml", 5) != 0)
126 end
= strchrnul((const char*) start
, '\n');
128 if (strncmp(start
, "<osm", 4) != 0)
131 if (strncmp(&start
[4], "Change", 6) == 0)
146 *fd_members_relation
,
150 fd_nodes
= fopen(file_nodes
, "w");
151 if (fd_nodes
== NULL
) { perror("Open:"); exit(-1); }
153 fd_nodes_uint
= fopen(file_nodes_uint
, "w");
154 if (fd_nodes_uint
== NULL
) { perror("Open:"); exit(-1); }
155 fd_nodes_gis
= fopen(file_nodes_gis
, "w");
156 if (fd_nodes_gis
== NULL
) { perror("Open:"); exit(-1); }
158 fd_node_tags
= fopen(file_node_tags
, "w");
159 if (fd_node_tags
== NULL
) { perror("Open:"); exit(-1); }
160 fd_ways
= fopen(file_ways
, "w");
161 if (fd_ways
== NULL
) { perror("Open:"); exit(-1); }
162 fd_way_tags
= fopen(file_way_tags
, "w");
163 if (fd_way_tags
== NULL
) { perror("Open:"); exit(-1); }
164 fd_way_nds
= fopen(file_way_nds
, "w");
165 if (fd_way_nds
== NULL
) { perror("Open:"); exit(-1); }
166 fd_relations
= fopen(file_relations
, "w");
167 if (fd_relations
== NULL
) { perror("Open:"); exit(-1); }
168 fd_relation_tags
= fopen(file_relation_tags
, "w");
169 if (fd_relation_tags
== NULL
) { perror("Open:"); exit(-1); }
170 fd_members_node
= fopen(file_relation_member_node
, "w");
171 if (fd_members_node
== NULL
) { perror("Open:"); exit(-1); }
172 fd_members_relation
= fopen(file_relation_member_relation
, "w");
173 if (fd_members_relation
== NULL
) { perror("Open:"); exit(-1); }
174 fd_members_way
= fopen(file_relation_member_way
, "w");
175 if (fd_members_way
== NULL
) { perror("Open:"); exit(-1); }
177 fd_node_tags
= fd_ways
= fd_way_tags
= fd_way_nds
= fd_relations
= fd_relation_tags
= fd_members_node
= fd_members_relation
= fd_members_way
= fd_nodes
= stdout
;
178 fputs("START TRANSACTION;\n", fd_nodes
);
184 end
= strchrnul((const char*) start
, '\n');
186 nodename
= strchrnul(start
, '<') + 1;
187 nodename_end
= strchrnul(nodename
, ' ');
189 if (nodename
[0] == '/') {
193 free(attr_timestamp
);
197 attr_id
= attr_lat
= attr_lon
= attr_user
= attr_uid
= attr_timestamp
= NULL
;
205 switch (nodename_end
- nodename
) {
210 switch (nodename
[0]) {
221 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
233 switch (nodename
[2]) {
250 current_tag
= MEMBER
;
253 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
258 current_tag
= RELATION
;
261 fprintf(stderr
, "--> %c%c", nodename
[0], nodename
[1]);
265 char *key
, *key_end
, *value_end
;
266 key
= nodename_end
+ 1;
270 key_state_t current_key
= UNKNOWN
;
271 key_end
= strchrnul(key
, '=');
273 if (key_end
== NULL
|| key_end
>= end
)
276 switch (key_end
- key
) {
286 current_key
= UNKNOWN
;
308 current_key
= UNKNOWN
;
309 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
325 current_key
= UNKNOWN
;
326 fprintf(stderr
, "--> %c%c\n", key
[0], key
[1]);
331 current_key
= TIMESTAMP
;
334 char *thingie
= strndup(key
, (key_end
- key
));
335 current_key
= UNKNOWN
;
337 fprintf(stderr
, "UNKNOWN ATTR %s-> %c%c\n", thingie
, key
[0], key
[1]);
344 value_end
= strchr(value_end
, '"');
349 switch (current_key
) {
351 if (attr_id
) free(attr_id
);
352 attr_id
= strndup(value
, (value_end
- value
));
356 if (attr_lat
) free(attr_lat
);
357 attr_lat
= strndup(value
, (value_end
- value
));
358 attr_lat_uint
= coordtouint(attr_lat
);
362 if (attr_lon
) free(attr_lon
);
363 attr_lon
= strndup(value
, (value_end
- value
));
364 attr_lon_uint
= coordtouint(attr_lon
);
368 if (attr_timestamp
) free(attr_timestamp
);
369 // attr_timestamp = strndup(value, (value_end - value));
370 attr_timestamp
= strndup(value
, (value_end
- (value
+ 1))); /* another stupid fix */
371 // attr_timestamp[10] = ' '; /* Stupid timestamp fix */
376 if (attr_user
) free(attr_user
);
377 attr_user
= strndup(value
, (value_end
- value
));
378 tmp
= escape_string(attr_user
);
385 if (attr_uid
) free(attr_uid
);
386 attr_uid
= strndup(value
, (value_end
- value
));
392 if (attr_key
) free(attr_key
);
393 attr_key
= strndup(value
, (value_end
- value
));
394 tmp
= escape_string(attr_key
);
402 if (attr_value
) free(attr_value
);
403 attr_value
= strndup(value
, (value_end
- value
));
404 tmp
= escape_string(attr_value
);
411 if (attr_type
) free(attr_type
);
412 attr_type
= strndup(value
, (value_end
- value
));
416 if (attr_ref
) free(attr_ref
);
417 attr_ref
= strndup(value
, (value_end
- value
));
422 if (attr_role
) free(attr_role
);
423 attr_role
= strndup(value
, (value_end
- value
));
424 tmp
= escape_string(attr_role
);
431 fprintf(stderr
, "--> %c%c\n", value
[0], value
[1]);
437 if (ywk
== DELETE
|| ywk
== MODIFY
) {
438 switch (current_tag
) {
440 fprintf(fd_nodes
, "DELETE FROM node_tags WHERE node = %s;\n", attr_id
);
441 fprintf(fd_nodes
, "DELETE FROM nodes_legacy WHERE id = %s;\n", attr_id
);
444 fprintf(fd_nodes
, "DELETE FROM way_tags WHERE way = %s;\n", attr_id
);
445 fprintf(fd_nodes
, "DELETE FROM way_nds WHERE way = %s;\n", attr_id
);
446 fprintf(fd_nodes
, "DELETE FROM ways WHERE id = %s;\n", attr_id
);
449 fprintf(fd_nodes
, "DELETE FROM relation_tags WHERE relation = %s;\n", attr_id
);
450 fprintf(fd_nodes
, "DELETE FROM relation_members_node WHERE relation = %s;\n", attr_id
);
451 fprintf(fd_nodes
, "DELETE FROM relation_members_way WHERE relation = %s;\n", attr_id
);
452 fprintf(fd_nodes
, "DELETE FROM relation_members_relation WHERE relation = %s;\n", attr_id
);
453 fprintf(fd_nodes
, "DELETE FROM relations WHERE id = %s;\n", attr_id
);
460 fputs("INSERT INTO ", fd_nodes
);
461 switch (current_tag
) {
463 fputs("nodes_legacy", fd_nodes
);
466 fputs("ways", fd_nodes
);
469 fputs("relations", fd_nodes
);
472 fputs("way_nds", fd_nodes
);
475 fputs("members_", fd_nodes
);
476 fputs(attr_type
, fd_nodes
);
479 switch (parent_tag
) {
481 fputs("node_tags", fd_nodes
);
484 fputs("way_tags", fd_nodes
);
487 fputs("relation_tags", fd_nodes
);
492 fputs(" VALUES (", fd_nodes
);
495 switch (current_tag
) {
497 fprintf(fd_nodes
, "%s, %s, %s, %s, '%s'%s\n", attr_id
, attr_lat
, attr_lon
, (attr_uid
!= NULL
? attr_uid
: "0"), attr_timestamp
, (ywk
==NONE
?"":");"));
499 fprintf(fd_nodes_uint
, "%s, %d, %d, %s, '%s'%s\n", attr_id
, attr_lat_uint
, attr_lon_uint
, (attr_uid
!= NULL
? attr_uid
: "0"), attr_timestamp
, (ywk
==NONE
?"":");"));
500 fprintf(fd_nodes_gis
, "%s, 'POINT( %s %s )', '%s', '%s'%s\n", attr_id
, attr_lon
, attr_lat
, (attr_uid
!= NULL
? attr_uid
: "0"), attr_timestamp
, (ywk
==NONE
?"":");"));
505 switch (parent_tag
) {
507 fprintf(fd_node_tags
, "%s, '%s', '%s'%s\n", attr_id
, attr_key
, attr_value
, (ywk
==NONE
?"":");"));
511 fprintf(fd_way_tags
, "%s, '%s', '%s'%s\n", attr_id
, attr_key
, attr_value
, (ywk
==NONE
?"":");"));
515 fprintf(fd_relation_tags
, "%s, '%s', '%s'%s\n", attr_id
, attr_key
, attr_value
, (ywk
==NONE
?"":");"));
516 count_relation_tags
++;
524 fprintf(fd_ways
, "%s, %s, '%s'%s\n", attr_id
, (attr_uid
!= NULL
? attr_uid
: "0"), attr_timestamp
, (ywk
==NONE
?"":");"));
526 // fprintf(fd_way_tags, "%s, '%s', '%s'%s\n", attr_id, "type", "way", (ywk==NONE?"":");"));
530 fprintf(fd_relations
, "%s, %s, '%s'%s\n", attr_id
, (attr_uid
!= NULL
? attr_uid
: "0"), attr_timestamp
, (ywk
==NONE
?"":");"));
534 if (strcmp(attr_type
, "node") == 0) {
535 fprintf(fd_members_node
, "%s, %lu, %s, '%s'%s\n", attr_id
, sequence
, attr_ref
, attr_role
, (ywk
==NONE
?"":");"));
536 count_members_node
++;
537 } else if (strcmp(attr_type
, "way") == 0) {
538 fprintf(fd_members_way
, "%s, %lu, %s, '%s'%s\n", attr_id
, sequence
, attr_ref
, attr_role
, (ywk
==NONE
?"":");"));
540 } else if (strcmp(attr_type
, "relation") == 0) {
541 fprintf(fd_members_relation
, "%s, %lu, %s, '%s'%s\n", attr_id
, sequence
, attr_ref
, attr_role
, (ywk
==NONE
?"":");"));
542 count_members_relation
++;
547 fprintf(fd_way_nds
, "%s, %lu, %s%s\n", attr_id
, sequence
, attr_ref
, (ywk
==NONE
?"":");"));
558 if (end
[-2] == '/') {
559 switch (current_tag
) {
572 free(attr_timestamp
);
576 attr_id
= attr_user
= attr_uid
= attr_timestamp
= NULL
;
601 } else if (current_tag
== NODE
|| current_tag
== WAY
|| current_tag
== RELATION
) {
602 parent_tag
= current_tag
;
607 } while (stopcondition
);
613 free(attr_timestamp
);
622 fclose(fd_nodes_uint
);
623 fclose(fd_nodes_gis
);
625 fclose(fd_node_tags
);
629 fclose(fd_relations
);
630 fclose(fd_relation_tags
);
631 fclose(fd_members_node
);
632 fclose(fd_members_relation
);
633 fclose(fd_members_way
);
637 char *current
= get_current_dir_name();
639 puts("START TRANSACTION;");
641 puts("CREATE TABLE nodes_legacy (id integer, long double, lat double, uid integer, timestamp timestamptz);");
643 puts("CREATE TABLE nodes_legacy_uint (id integer, long integer, lat integer, uid integer, timestamp timestamptz);");
644 puts("CREATE TABLE nodes_legacy_gis (id integer, poi point, uid integer, timestamp timestamptz);");
646 puts("CREATE TABLE node_tags (node integer, k varchar(255), v varchar(1024));");
647 puts("CREATE TABLE ways (id integer,uid integer, timestamp timestamptz);");
648 puts("CREATE TABLE way_tags (way integer, k varchar(255), v varchar(1024));");
649 puts("CREATE TABLE way_nds (way integer, idx integer, to_node integer);");
650 puts("CREATE TABLE relations(id integer, uid integer, timestamp timestamptz);");
651 puts("CREATE TABLE relation_members_node (relation integer, idx integer, to_node integer, role varchar(255));");
652 puts("CREATE TABLE relation_members_relation (relation integer, idx integer, to_relation integer, role varchar(255));");
653 puts("CREATE TABLE relation_members_way (relation integer, idx integer, to_way integer, role varchar(255));");
654 puts("CREATE TABLE relation_tags (relation integer, k varchar(255), v varchar(1024));");
656 printf("COPY %lu RECORDS INTO nodes_legacy from '%s/" file_nodes
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
658 printf("COPY %lu RECORDS INTO nodes_legacy_uint from '%s/" file_nodes_uint
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
659 printf("COPY %lu RECORDS INTO nodes_legacy_gis from '%s/" file_nodes_gis
"' USING DELIMITERS ',', '\\n', '''';\n", count_nodes
, current
);
661 printf("COPY %lu RECORDS INTO node_tags from '%s/" file_node_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_node_tags
, current
);
662 printf("COPY %lu RECORDS INTO ways from '%s/" file_ways
"' USING DELIMITERS ',', '\\n', '''';\n", count_ways
, current
);
663 printf("COPY %lu RECORDS INTO way_tags from '%s/" file_way_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_tags
, current
);
664 printf("COPY %lu RECORDS INTO way_nds from '%s/" file_way_nds
"' USING DELIMITERS ',', '\\n', '''';\n", count_way_nds
, current
);
665 printf("COPY %lu RECORDS INTO relations from '%s/" file_relations
"' USING DELIMITERS ',', '\\n', '''';\n", count_relations
, current
);
666 printf("COPY %lu RECORDS INTO relation_tags from '%s/" file_relation_tags
"' USING DELIMITERS ',', '\\n', '''';\n", count_relation_tags
, current
);
667 printf("COPY %lu RECORDS INTO relation_members_node from '%s/" file_relation_member_node
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_node
, current
);
668 printf("COPY %lu RECORDS INTO relation_members_relation from '%s/" file_relation_member_relation
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_relation
, current
);
669 printf("COPY %lu RECORDS INTO relation_members_way from '%s/" file_relation_member_way
"' USING DELIMITERS ',', '\\n', '''';\n", count_members_way
, current
);
675 puts("START TRANSACTION;");
677 puts("CREATE SEQUENCE s_nodes AS INTEGER;");
678 puts("ALTER SEQUENCE s_nodes RESTART WITH (SELECT MAX(id) FROM nodes_legacy);");
679 puts("ALTER TABLE nodes_legacy ALTER COLUMN id SET NOT NULL;");
680 puts("ALTER TABLE nodes_legacy ALTER COLUMN id SET DEFAULT NEXT VALUE FOR \"sys\".\"s_nodes\";");
681 puts("ALTER TABLE nodes_legacy ADD CONSTRAINT pk_nodes_id PRIMARY KEY (id);");
683 puts("CREATE SEQUENCE s_ways AS INTEGER;");
684 puts("ALTER SEQUENCE s_ways RESTART WITH (SELECT MAX(id) FROM ways);");
685 puts("ALTER TABLE ways ALTER COLUMN id SET NOT NULL;");
686 puts("ALTER TABLE ways ALTER COLUMN id SET DEFAULT NEXT VALUE FOR \"sys\".\"s_ways\";");
687 puts("ALTER TABLE ways ADD CONSTRAINT pk_ways_id PRIMARY KEY (id);");
689 puts("CREATE SEQUENCE s_relations AS INTEGER;");
690 puts("ALTER SEQUENCE s_relations RESTART WITH (SELECT MAX(id) FROM relations);");
691 puts("ALTER TABLE relations ALTER COLUMN id SET NOT NULL;");
692 puts("ALTER TABLE relations ALTER COLUMN id SET DEFAULT NEXT VALUE FOR \"sys\".\"s_relations\";");
693 puts("ALTER TABLE relations ADD CONSTRAINT pk_relations_id PRIMARY KEY (id);");
695 puts("ALTER TABLE relation_members_node ADD CONSTRAINT pk_relation_members_node PRIMARY KEY (relation, idx);");
696 puts("ALTER TABLE relation_members_way ADD CONSTRAINT pk_relation_members_way PRIMARY KEY (relation,idx);");
697 puts("ALTER TABLE relation_members_relation ADD CONSTRAINT pk_relation_members_relation PRIMARY KEY (relation,idx);");
702 puts("START TRANSACTION;");
704 puts("ALTER TABLE node_tags ADD CONSTRAINT fk_node_tags_node FOREIGN KEY (node) REFERENCES nodes_legacy (id);");
705 puts("ALTER TABLE node_tags ADD CONSTRAINT pk_node_tags UNIQUE (node, k, v);");
707 puts("ALTER TABLE way_tags ADD CONSTRAINT fk_way_tags_way FOREIGN KEY (way) REFERENCES ways (id);");
708 puts("ALTER TABLE way_tags ADD CONSTRAINT pk_way_tags UNIQUE (way, k, v);");
710 puts("ALTER TABLE way_nds ADD CONSTRAINT pk_way_nds PRIMARY KEY (way, idx);");
711 puts("ALTER TABLE way_nds ADD CONSTRAINT fk_way_nds_way FOREIGN KEY (way) REFERENCES ways (id);");
712 puts("ALTER TABLE way_nds ADD CONSTRAINT fk_way_nds_node FOREIGN KEY (to_node) REFERENCES nodes_legacy (id);");
714 puts("ALTER TABLE relation_tags ADD CONSTRAINT fk_relation_tags FOREIGN KEY (relation) REFERENCES relations (id);");
715 puts("ALTER TABLE relation_tags ADD CONSTRAINT pk_relation_tags UNIQUE (relation, k, v);");
717 puts("ALTER TABLE relation_members_node ADD CONSTRAINT fk_relation_members_node FOREIGN KEY (relation) REFERENCES relations (id);");
718 puts("ALTER TABLE relation_members_node ADD CONSTRAINT fk_relation_members_tonode FOREIGN KEY (to_node) REFERENCES nodes_legacy (id);");
720 puts("ALTER TABLE relation_members_way ADD CONSTRAINT fk_relation_members_way FOREIGN KEY (relation) REFERENCES relations (id);");
721 puts("ALTER TABLE relation_members_way ADD CONSTRAINT fk_relation_members_toway FOREIGN KEY (to_way) REFERENCES ways (id);");
723 puts("ALTER TABLE relation_members_relation ADD CONSTRAINT fk_relation_members_relation FOREIGN KEY (relation) REFERENCES relations (id);");
724 puts("ALTER TABLE relation_members_relation ADD CONSTRAINT fk_relation_members_torelation FOREIGN KEY (to_relation) REFERENCES relations (id);");
732 int main(int argc
, char *argv
[]) {
740 fprintf(stderr
, "Analysing %s...\n", argv
[1]);
742 fd
= open(argv
[1], O_RDONLY
);
747 if (fstat (fd
, &statbuf
) == -1) { perror("fstat:"); exit(-1); }
749 if (statbuf
.st_size
> 0) {
751 range
= mmap(NULL
, statbuf
.st_size
, PROT_READ
, MAP_SHARED
, fd
, (off_t
) 0);
752 if (range
== MAP_FAILED
) { perror("Mmap:"); puts("(did you compile PAE in the kernel?)"); exit(-1); }
753 parser(range
, statbuf
.st_size
/ sizeof(char));
754 munmap(range
, statbuf
.st_size
);