1-- This config example file is released into the Public Domain. 2 3-- This configuration for the flex output tries to be compatible with the 4-- original pgsql C transform output. There might be some corner cases but 5-- it should do exactly the same in almost all cases. 6 7-- The output projection used (3857, web mercator is the default). Set this 8-- to 4326 if you were using the -l|--latlong option or to the EPSG 9-- code you were using on the -E|-proj option. 10local srid = 3857 11 12-- Set this to true if you were using option -K|--keep-coastlines. 13local keep_coastlines = false 14 15-- Set this to the table name prefix (what used to be option -p|--prefix). 16local prefix = 'planet_osm' 17 18-- Set this to true if multipolygons should be written as multipolygons into 19-- db (what used to be option -G|--multi-geometry). 20local multi_geometry = false 21 22-- Set this to true if you want an hstore column (what used to be option 23-- -k|--hstore). Can not be true if "hstore_all" is true. 24local hstore = false 25 26-- Set this to true if you want all tags in an hstore column (what used to 27-- be option -j|--hstore-all). Can not be true if "hstore" is true. 28local hstore_all = false 29 30-- Only keep objects that have a value in one of the non-hstore columns 31-- (normal action with --hstore is to keep all objects). Equivalent to 32-- what used to be set through option --hstore-match-only. 33local hstore_match_only = false 34 35-- Set this to add an additional hstore (key/value) column containing all tags 36-- that start with the specified string, eg "name:". Will produce an extra 37-- hstore column that contains all "name:xx" tags. Equivalent to what used to 38-- be set through option -z|--hstore-column. Unlike the -z option which can 39-- be specified multiple time, this does only support a single additional 40-- hstore column. 41local hstore_column = nil 42 43-- There is some very old specialized handling of route relations in osm2pgsql, 44-- which you probably don't need. This is disabled here, but you can enable 45-- it by setting this to true. If you don't understand this, leave it alone. 46local enable_legacy_route_processing = false 47 48-- --------------------------------------------------------------------------- 49 50if hstore and hstore_all then 51 error("hstore and hstore_all can't be both true") 52end 53 54-- Used for splitting up long linestrings 55if srid == 4326 then 56 max_length = 1 57else 58 max_length = 100000 59end 60 61-- Ways with any of the following keys will be treated as polygon 62local polygon_keys = { 63 'aeroway', 64 'amenity', 65 'building', 66 'harbour', 67 'historic', 68 'landuse', 69 'leisure', 70 'man_made', 71 'military', 72 'natural', 73 'office', 74 'place', 75 'power', 76 'public_transport', 77 'shop', 78 'sport', 79 'tourism', 80 'water', 81 'waterway', 82 'wetland', 83 'abandoned:aeroway', 84 'abandoned:amenity', 85 'abandoned:building', 86 'abandoned:landuse', 87 'abandoned:power', 88 'area:highway' 89} 90 91-- Objects without any of the following keys will be deleted 92local generic_keys = { 93 'access', 94 'addr:housename', 95 'addr:housenumber', 96 'addr:interpolation', 97 'admin_level', 98 'aerialway', 99 'aeroway', 100 'amenity', 101 'area', 102 'barrier', 103 'bicycle', 104 'boundary', 105 'brand', 106 'bridge', 107 'building', 108 'capital', 109 'construction', 110 'covered', 111 'culvert', 112 'cutting', 113 'denomination', 114 'disused', 115 'ele', 116 'embankment', 117 'foot', 118 'generation:source', 119 'harbour', 120 'highway', 121 'historic', 122 'hours', 123 'intermittent', 124 'junction', 125 'landuse', 126 'layer', 127 'leisure', 128 'lock', 129 'man_made', 130 'military', 131 'motorcar', 132 'name', 133 'natural', 134 'office', 135 'oneway', 136 'operator', 137 'place', 138 'population', 139 'power', 140 'power_source', 141 'public_transport', 142 'railway', 143 'ref', 144 'religion', 145 'route', 146 'service', 147 'shop', 148 'sport', 149 'surface', 150 'toll', 151 'tourism', 152 'tower:type', 153 'tracktype', 154 'tunnel', 155 'water', 156 'waterway', 157 'wetland', 158 'width', 159 'wood', 160 'abandoned:aeroway', 161 'abandoned:amenity', 162 'abandoned:building', 163 'abandoned:landuse', 164 'abandoned:power', 165 'area:highway' 166} 167 168-- The following keys will be deleted 169local delete_keys = { 170 'attribution', 171 'comment', 172 'created_by', 173 'fixme', 174 'note', 175 'note:*', 176 'odbl', 177 'odbl:note', 178 'source', 179 'source:*', 180 'source_ref', 181 'way', 182 'way_area', 183 'z_order', 184} 185 186local point_columns = { 187 'access', 188 'addr:housename', 189 'addr:housenumber', 190 'addr:interpolation', 191 'admin_level', 192 'aerialway', 193 'aeroway', 194 'amenity', 195 'area', 196 'barrier', 197 'bicycle', 198 'brand', 199 'bridge', 200 'boundary', 201 'building', 202 'capital', 203 'construction', 204 'covered', 205 'culvert', 206 'cutting', 207 'denomination', 208 'disused', 209 'ele', 210 'embankment', 211 'foot', 212 'generator:source', 213 'harbour', 214 'highway', 215 'historic', 216 'horse', 217 'intermittent', 218 'junction', 219 'landuse', 220 'layer', 221 'leisure', 222 'lock', 223 'man_made', 224 'military', 225 'motorcar', 226 'name', 227 'natural', 228 'office', 229 'oneway', 230 'operator', 231 'place', 232 'population', 233 'power', 234 'power_source', 235 'public_transport', 236 'railway', 237 'ref', 238 'religion', 239 'route', 240 'service', 241 'shop', 242 'sport', 243 'surface', 244 'toll', 245 'tourism', 246 'tower:type', 247 'tunnel', 248 'water', 249 'waterway', 250 'wetland', 251 'width', 252 'wood', 253} 254 255local non_point_columns = { 256 'access', 257 'addr:housename', 258 'addr:housenumber', 259 'addr:interpolation', 260 'admin_level', 261 'aerialway', 262 'aeroway', 263 'amenity', 264 'area', 265 'barrier', 266 'bicycle', 267 'brand', 268 'bridge', 269 'boundary', 270 'building', 271 'construction', 272 'covered', 273 'culvert', 274 'cutting', 275 'denomination', 276 'disused', 277 'embankment', 278 'foot', 279 'generator:source', 280 'harbour', 281 'highway', 282 'historic', 283 'horse', 284 'intermittent', 285 'junction', 286 'landuse', 287 'layer', 288 'leisure', 289 'lock', 290 'man_made', 291 'military', 292 'motorcar', 293 'name', 294 'natural', 295 'office', 296 'oneway', 297 'operator', 298 'place', 299 'population', 300 'power', 301 'power_source', 302 'public_transport', 303 'railway', 304 'ref', 305 'religion', 306 'route', 307 'service', 308 'shop', 309 'sport', 310 'surface', 311 'toll', 312 'tourism', 313 'tower:type', 314 'tracktype', 315 'tunnel', 316 'water', 317 'waterway', 318 'wetland', 319 'width', 320 'wood', 321} 322 323function gen_columns(text_columns, with_hstore, area, geometry_type) 324 columns = {} 325 326 local add_column = function (name, type) 327 columns[#columns + 1] = { column = name, type = type } 328 end 329 330 for _, c in ipairs(text_columns) do 331 add_column(c, 'text') 332 end 333 334 add_column('z_order', 'int') 335 336 if area ~= nil then 337 if area then 338 add_column('way_area', 'area') 339 else 340 add_column('way_area', 'real') 341 end 342 end 343 344 if hstore_column then 345 add_column(hstore_column, 'hstore') 346 end 347 348 if with_hstore then 349 add_column('tags', 'hstore') 350 end 351 352 add_column('way', geometry_type) 353 columns[#columns].projection = srid 354 355 return columns 356end 357 358local tables = {} 359 360tables.point = osm2pgsql.define_table{ 361 name = prefix .. '_point', 362 ids = { type = 'node', id_column = 'osm_id' }, 363 columns = gen_columns(point_columns, hstore or hstore_all, nil, 'point') 364} 365 366tables.line = osm2pgsql.define_table{ 367 name = prefix .. '_line', 368 ids = { type = 'way', id_column = 'osm_id' }, 369 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring') 370} 371 372tables.polygon = osm2pgsql.define_table{ 373 name = prefix .. '_polygon', 374 ids = { type = 'area', id_column = 'osm_id' }, 375 columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'geometry') 376} 377 378tables.roads = osm2pgsql.define_table{ 379 name = prefix .. '_roads', 380 ids = { type = 'way', id_column = 'osm_id' }, 381 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring') 382} 383 384local z_order_lookup = { 385 proposed = {1, false}, 386 construction = {2, false}, 387 steps = {10, false}, 388 cycleway = {10, false}, 389 bridleway = {10, false}, 390 footway = {10, false}, 391 path = {10, false}, 392 track = {11, false}, 393 service = {15, false}, 394 395 tertiary_link = {24, false}, 396 secondary_link = {25, true}, 397 primary_link = {27, true}, 398 trunk_link = {28, true}, 399 motorway_link = {29, true}, 400 401 raceway = {30, false}, 402 pedestrian = {31, false}, 403 living_street = {32, false}, 404 road = {33, false}, 405 unclassified = {33, false}, 406 residential = {33, false}, 407 tertiary = {34, false}, 408 secondary = {36, true}, 409 primary = {37, true}, 410 trunk = {38, true}, 411 motorway = {39, true} 412} 413 414function as_bool(value) 415 return value == 'yes' or value == 'true' or value == '1' 416end 417 418function get_z_order(tags) 419 local z_order = 100 * math.floor(tonumber(tags.layer or '0') or 0) 420 local roads = false 421 422 local highway = tags['highway'] 423 if highway then 424 local r = z_order_lookup[highway] or {0, false} 425 z_order = z_order + r[1] 426 roads = r[2] 427 end 428 429 if tags.railway then 430 z_order = z_order + 35 431 roads = true 432 end 433 434 if tags.boundary and tags.boundary == 'administrative' then 435 roads = true 436 end 437 438 if as_bool(tags.bridge) then 439 z_order = z_order + 100 440 end 441 442 if as_bool(tags.tunnel) then 443 z_order = z_order - 100 444 end 445 446 return z_order, roads 447end 448 449function make_check_in_list_func(list) 450 local h = {} 451 for _, k in ipairs(list) do 452 h[k] = true 453 end 454 return function(tags) 455 for k, _ in pairs(tags) do 456 if h[k] then 457 return true 458 end 459 end 460 return false 461 end 462end 463 464local is_polygon = make_check_in_list_func(polygon_keys) 465local clean_tags = osm2pgsql.make_clean_tags_func(delete_keys) 466 467function make_column_hash(columns) 468 local h = {} 469 470 for _, k in ipairs(columns) do 471 h[k] = true 472 end 473 474 return h 475end 476 477function make_get_output(columns, hstore_all) 478 local h = make_column_hash(columns) 479 if hstore_all then 480 return function(tags) 481 local output = {} 482 local hstore_entries = {} 483 484 for k, _ in pairs(tags) do 485 if h[k] then 486 output[k] = tags[k] 487 end 488 hstore_entries[k] = tags[k] 489 end 490 491 return output, hstore_entries 492 end 493 else 494 return function(tags) 495 local output = {} 496 local hstore_entries = {} 497 498 for k, _ in pairs(tags) do 499 if h[k] then 500 output[k] = tags[k] 501 else 502 hstore_entries[k] = tags[k] 503 end 504 end 505 506 return output, hstore_entries 507 end 508 end 509end 510 511local has_generic_tag = make_check_in_list_func(generic_keys) 512 513local get_point_output = make_get_output(point_columns, hstore_all) 514local get_non_point_output = make_get_output(non_point_columns, hstore_all) 515 516function get_hstore_column(tags) 517 local len = #hstore_column 518 local h = {} 519 for k, v in pairs(tags) do 520 if k:sub(1, len) == hstore_column then 521 h[k:sub(len + 1)] = v 522 end 523 end 524 525 if next(h) then 526 return h 527 end 528 return nil 529end 530 531function osm2pgsql.process_node(object) 532 if clean_tags(object.tags) then 533 return 534 end 535 536 local output 537 local output_hstore = {} 538 if hstore or hstore_all then 539 output, output_hstore = get_point_output(object.tags) 540 if not next(output) and not next(output_hstore) then 541 return 542 end 543 if hstore_match_only and not has_generic_tag(object.tags) then 544 return 545 end 546 else 547 output = object.tags 548 if not has_generic_tag(object.tags) then 549 return 550 end 551 end 552 553 output.tags = output_hstore 554 555 if hstore_column then 556 output[hstore_column] = get_hstore_column(object.tags) 557 end 558 559 tables.point:add_row(output) 560end 561 562function osm2pgsql.process_way(object) 563 if clean_tags(object.tags) then 564 return 565 end 566 567 local add_area = false 568 if object.tags.natural == 'coastline' then 569 add_area = true 570 if not keep_coastlines then 571 object.tags.natural = nil 572 end 573 end 574 575 local output 576 local output_hstore = {} 577 if hstore or hstore_all then 578 output, output_hstore = get_non_point_output(object.tags) 579 if not next(output) and not next(output_hstore) then 580 return 581 end 582 if hstore_match_only and not has_generic_tag(object.tags) then 583 return 584 end 585 if add_area and hstore_all then 586 output_hstore.area = 'yes' 587 end 588 else 589 output = object.tags 590 if not has_generic_tag(object.tags) then 591 return 592 end 593 end 594 595 local polygon 596 local area_tag = object.tags.area 597 if area_tag == 'yes' or area_tag == '1' or area_tag == 'true' then 598 polygon = true 599 elseif area_tag == 'no' or area_tag == '0' or area_tag == 'false' then 600 polygon = false 601 else 602 polygon = is_polygon(object.tags) 603 end 604 605 if add_area then 606 output.area = 'yes' 607 polygon = true 608 end 609 610 local z_order, roads = get_z_order(object.tags) 611 output.z_order = z_order 612 613 output.tags = output_hstore 614 615 if hstore_column then 616 output[hstore_column] = get_hstore_column(object.tags) 617 end 618 619 if polygon and object.is_closed then 620 output.way = { create = 'area' } 621 tables.polygon:add_row(output) 622 else 623 output.way = { create = 'line', split_at = max_length } 624 tables.line:add_row(output) 625 if roads then 626 tables.roads:add_row(output) 627 end 628 end 629end 630 631function osm2pgsql.process_relation(object) 632 if clean_tags(object.tags) then 633 return 634 end 635 636 local type = object.tags.type 637 if (type ~= 'route') and (type ~= 'multipolygon') and (type ~= 'boundary') then 638 return 639 end 640 object.tags.type = nil 641 642 local output 643 local output_hstore = {} 644 if hstore or hstore_all then 645 output, output_hstore = get_non_point_output(object.tags) 646 if not next(output) and not next(output_hstore) then 647 return 648 end 649 if hstore_match_only and not has_generic_tag(object.tags) then 650 return 651 end 652 else 653 output = object.tags 654 if not has_generic_tag(object.tags) then 655 return 656 end 657 end 658 659 if not next(output) and not next(output_hstore) then 660 return 661 end 662 663 if enable_legacy_route_processing and (hstore or hstore_all) and type == 'route' then 664 if not object.tags.route_name then 665 output_hstore.route_name = object.tags.name 666 end 667 668 local state = object.tags.state 669 if state ~= 'alternate' and state ~= 'connection' then 670 state = 'yes' 671 end 672 673 local network = object.tags.network 674 if network == 'lcn' then 675 output_hstore.lcn = output_hstore.lcn or state 676 output_hstore.lcn_ref = output_hstore.lcn_ref or object.tags.ref 677 elseif network == 'rcn' then 678 output_hstore.rcn = output_hstore.rcn or state 679 output_hstore.rcn_ref = output_hstore.rcn_ref or object.tags.ref 680 elseif network == 'ncn' then 681 output_hstore.ncn = output_hstore.ncn or state 682 output_hstore.ncn_ref = output_hstore.ncn_ref or object.tags.ref 683 elseif network == 'lwn' then 684 output_hstore.lwn = output_hstore.lwn or state 685 output_hstore.lwn_ref = output_hstore.lwn_ref or object.tags.ref 686 elseif network == 'rwn' then 687 output_hstore.rwn = output_hstore.rwn or state 688 output_hstore.rwn_ref = output_hstore.rwn_ref or object.tags.ref 689 elseif network == 'nwn' then 690 output_hstore.nwn = output_hstore.nwn or state 691 output_hstore.nwn_ref = output_hstore.nwn_ref or object.tags.ref 692 end 693 694 local pc = object.tags.preferred_color 695 if pc == '0' or pc == '1' or pc == '2' or pc == '3' or pc == '4' then 696 output_hstore.route_pref_color = pc 697 else 698 output_hstore.route_pref_color = '0' 699 end 700 end 701 702 local make_boundary = false 703 local make_polygon = false 704 if type == 'boundary' then 705 make_boundary = true 706 elseif type == 'multipolygon' and object.tags.boundary then 707 make_boundary = true 708 elseif type == 'multipolygon' then 709 make_polygon = true 710 end 711 712 local z_order, roads = get_z_order(object.tags) 713 output.z_order = z_order 714 715 output.tags = output_hstore 716 717 if hstore_column then 718 output[hstore_column] = get_hstore_column(object.tags) 719 end 720 721 if not make_polygon then 722 output.way = { create = 'line', split_at = max_length } 723 tables.line:add_row(output) 724 if roads then 725 tables.roads:add_row(output) 726 end 727 end 728 729 if make_boundary or make_polygon then 730 output.way = { create = 'area' } 731 if not multi_geometry then 732 output.way.split_at = 'multi' 733 end 734 tables.polygon:add_row(output) 735 end 736end 737 738