geolite

osm_node, osm_way, osm_relation

the three element tables of the osm_data database, one folder each: the entity and its decoder, the storage row, the jsonb payload and the repository — ddl, index, bulk insert and, for ways and relations, the candidate queries the admin-level stages read.

a decoder takes the wire form from osm_pbf_file::message — the block’s string table and, for nodes, its block_scale (granularity and offsets) — and a tag_policy, and returns entities. the dependency runs one way: the file’s osm_data pass calls the element decoders; no element folder knows the pass exists.

the payload — payload and the row

a row is (id, osm_pbf_chunk_id, payload), and payload is sqlite’s jsonb binary written by hand. database::jsonb is the generic codec — headers, size classes, objects and arrays, a scratch pool — and each folder’s payload::encode is the shape: lat, lon and tags for a node, refs and tags for a way, tags and members (type as n/w/r, id, role) for a relation. the codec knows no entity, and the paths every reader uses ($.tags.…, $.refs, $.members) are fixed by the writer in the same folder. the row is encoded in the decoder threads (osm_node_row::encode and its siblings), not at insert time: the single writer thread only binds blobs, which is what keeps the pipeline parallel. the three inserts share database::insert_in_chunks, one multi-row statement per ten thousand rows, sized under sqlite’s variable limit.

the filters — osm_way::filter and repository

way_filter is the meaning — which ways a level wants (include_place_neighbourhood, exclude_building, …); admin_level::rules selects with it and a preset may override it. the sql of each variant lives in the way’s repository alone, built from osm_tag::select over typed keys and values, so the vocabulary and its translation are separate and the translation has one owner.

the candidate queries and the expression index

osm_relation::repository answers which relations of a level are still to index and osm_way::repository which ways; both anti-join main.admin_levels. the relation queries filter on the admin_level tag through the expression index osm_relations_search_by_admin_level and keep that expression as a bare literal, for the reason given under osm_tag: wrapping it makes sqlite drop the index and scan every relation of the file.