Skip to content

Commit 0a42b24

Browse files
committed
feat: add region and subregion columns to country_mapping datasources (IN-1188)
Signed-off-by: Gašper Grom <gasper.grom@gmail.com>
1 parent dff19ed commit 0a42b24

6 files changed

Lines changed: 1821 additions & 2 deletions

File tree

services/libs/tinybird/datasources/country_mapping_ds.datasource

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ SCHEMA >
22
`country` String,
33
`flag` String,
44
`country_code` String,
5-
`timezone_offset` Int16
5+
`timezone_offset` Int16,
6+
`region` String,
7+
`subregion` String
68

79
ENGINE MergeTree
810
ENGINE_SORTING_KEY flag, country_code, timezone_offset
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
SCHEMA >
22
`country` String,
33
`country_code` String,
4-
`timezone_offset` Int16
4+
`timezone_offset` Int16,
5+
`region` String,
6+
`subregion` String
57

68
ENGINE MergeTree
79
ENGINE_SORTING_KEY country, timezone_offset

services/libs/tinybird/datasources/fixtures/country_mapping_ds.ndjson

Lines changed: 242 additions & 0 deletions
Large diffs are not rendered by default.

services/libs/tinybird/datasources/fixtures/country_mapping_no_flags_ds.ndjson

Lines changed: 242 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
#!/usr/bin/env node
2+
// Copyright (c) 2026 The Linux Foundation and each contributor.
3+
// SPDX-License-Identifier: MIT
4+
//
5+
// Reads mledoze_countries_snapshot.json, a checked-in snapshot of countries.json
6+
// pinned at https://github.com/mledoze/countries/blob/09b28e3d03e6ca3fbbac996d716a50d929781e8c/countries.json
7+
// so re-running this script later doesn't depend on network access or pick up upstream drift.
8+
9+
const fs = require('fs');
10+
const path = require('path');
11+
12+
const PIPE_PATH = path.join(__dirname, '../pipes/country_mapping.pipe');
13+
const FIXTURES_DIR = path.join(__dirname, '../datasources/fixtures');
14+
const MLEDOZE_SNAPSHOT_PATH = path.join(__dirname, 'mledoze_countries_snapshot.json');
15+
16+
const UNKNOWN = 'Unknown';
17+
18+
// Extracts the ('Country', 'flag', 'CODE', offset) tuples from the arrayJoin([...]) literal
19+
// in country_mapping.pipe.
20+
function parsePipeCountries(pipeContent) {
21+
const tupleRegex = /\(\s*'((?:[^'\\]|\\.|'')*)'\s*,\s*'((?:[^'\\]|\\.|'')*)'\s*,\s*'([A-Z]{2})'\s*,\s*(-?\d+)\s*\)/g;
22+
const countries = [];
23+
let match;
24+
while ((match = tupleRegex.exec(pipeContent)) !== null) {
25+
const unescape = (s) => s.replace(/''/g, "'");
26+
countries.push({
27+
country: unescape(match[1]),
28+
flag: unescape(match[2]),
29+
country_code: match[3],
30+
timezone_offset: parseInt(match[4], 10),
31+
});
32+
}
33+
return countries;
34+
}
35+
36+
function main() {
37+
const pipeContent = fs.readFileSync(PIPE_PATH, 'utf8');
38+
const countries = parsePipeCountries(pipeContent);
39+
console.error(`Parsed ${countries.length} countries from country_mapping.pipe`);
40+
41+
const mledoze = JSON.parse(fs.readFileSync(MLEDOZE_SNAPSHOT_PATH, 'utf8'));
42+
43+
const byCca2 = new Map();
44+
for (const entry of mledoze) {
45+
if (entry.cca2) byCca2.set(entry.cca2, entry);
46+
}
47+
48+
const rows = countries.map(({ country, flag, country_code, timezone_offset }) => {
49+
const match = byCca2.get(country_code);
50+
let region = UNKNOWN;
51+
let subregion = UNKNOWN;
52+
if (match) {
53+
region = match.region || UNKNOWN;
54+
subregion = match.subregion || UNKNOWN;
55+
} else {
56+
console.error(`WARNING: no mledoze match for country_code=${country_code} (${country}) — defaulting region/subregion to "${UNKNOWN}"`);
57+
}
58+
return { country, flag, country_code, timezone_offset, region, subregion };
59+
});
60+
61+
fs.mkdirSync(FIXTURES_DIR, { recursive: true });
62+
63+
const withFlags = rows.map((row) => JSON.stringify(row));
64+
fs.writeFileSync(path.join(FIXTURES_DIR, 'country_mapping_ds.ndjson'), withFlags.join('\n') + '\n');
65+
66+
const noFlags = rows.map(({ country, country_code, timezone_offset, region, subregion }) =>
67+
JSON.stringify({ country, country_code, timezone_offset, region, subregion }),
68+
);
69+
fs.writeFileSync(path.join(FIXTURES_DIR, 'country_mapping_no_flags_ds.ndjson'), noFlags.join('\n') + '\n');
70+
71+
console.error(`Wrote ${rows.length} rows to country_mapping_ds.ndjson and country_mapping_no_flags_ds.ndjson`);
72+
}
73+
74+
try {
75+
main();
76+
} catch (err) {
77+
console.error(err);
78+
process.exit(1);
79+
}

0 commit comments

Comments
 (0)