Skip to content

feat(country): retire the translated name columns of t_country (#1939) - #1980

Merged
tristan0x merged 3 commits into
developfrom
feat/retire-unused-name-columns-of-t-country-use-native
Nov 7, 2026
Merged

tristan0x merged 3 commits into
developfrom
feat/retire-unused-name-columns-of-t-country-use-native

Conversation

@tristan0x

@tristan0x tristan0x commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

🤔 What

  • Drop the 9 translated name columns of t_country (en_name, fr_name, es_name, de_name, bg_name, it_name, ca_name, nl_name, rs_name). native_name stays.
  • v_data_quality_compute_entrance exposes co.native_name as country_name instead of co.fr_name.
  • New migration sql/9_37_2026_11_06_drop_country_translations.sql. It runs as one transaction and:
    1. drops and recreates the view, with its 4 indexes,
    2. refreshes the view,
    3. gives the view back to gc_owner,
    4. restores the view's grants,
    5. drops the 9 columns.
  • Removed the fields from:
    • TCountry
    • managedCountries in toOrganization and in the swagger
    • the organization export GROUP BY
    • sql/0_tables.sql, sql/91_materialized_views.sql and the countries seed
    • test/fixtures/tcountry.json
  • GET /api/v1/convert (and /api/convert) now returns iso2, sorts by native country name and documents its fields. The issue missed this reader (see Why).

Closes #1939

🤷‍♂️ Why

native_name is the only country name the API and the front end use. The front end localizes country names from the ISO code with Intl.DisplayNames. The 9 other columns had no real reader left, apart from fr_name in the data-quality view.

One reader was missing from the issue. ConvertService runs SELECT * over t_crs ⟕ t_country and sorted on Fr_name. With the columns dropped, /api/v1/convert returned a 500. The front end reads that response too. CRSMenu labels each projection group with getLocalizedCountryName(p.iso2 || p.country_code, locale, p.en_name). Neither iso2 nor country_code exists in the response today, so the label is always the en_name fallback. Without en_name, every projection would have landed under "World". The query now returns co.iso AS iso2, so the front end localizes the label from the ISO code with no front-end change needed.

Behavior changes

  • Data quality (/api/v1/entrances/with-quality/...): country_name is now the native name (España, not Espagne), and so is the sort=country_name order. The front end does not read country_name. Documented in the swagger.
  • Organizations: managedCountries[] only carries id and nativeName. enName … rsName are gone from the public response. No front-end consumer is known; external API consumers should be checked before merging.
  • Convert: the response gains iso2, keeps native_name, and loses the translated *_name fields. Fr_name was already always World, because Postgres returns the column as fr_name. It is kept and documented as such.

🔍 How

  • Ownership in the migration. A refresh runs with the privileges of the view's owner. On a fresh local volume, the tables only move to gc_owner in zz_ownership_and_grants.sql. If the migration handed the view to gc_owner unconditionally, 99_refresh_views.sql would fail with permission denied for table t_entrance. The migration therefore gives the view to gc_owner only when gc_owner already owns t_entrance (production). On a fresh volume, zz_ownership_and_grants.sql transfers it with everything else.
  • Grants. Dropping the view drops its grants. The default privileges only cover objects created by gc_owner or grottoce, so the migration grants SELECT, INSERT, UPDATE, DELETE to gc_app and SELECT to gc_readonly again. That is exactly the ACL the view had before.
  • Order. Everything runs in one transaction because search_outbox_enqueue_data_quality reads the view by name and would fail while it is missing.
  • Fixture fix. The j_country_crs test fixture used column names (id_country, id_crs) instead of the model's attributes, so its rows loaded with no country. It now uses country / crs, which the new convert test needs.

⚠️ Production does not run migrations on deploy. Apply sql/9_37_2026_11_06_drop_country_translations.sql by hand, after the deploy:

  1. Deploy this PR.
  2. Wait until no API process running the previous code is left. That code still reads the dropped columns: TCountry declares them, ConvertService sorts on fr_name, and the organization export groups by them.
  3. Apply the migration. The view's country_name switches to the native name as soon as it runs.

Once the migration has run, rolling back to the previous code requires restoring the columns and their data first. The migration header documents this order too.

🧪 Testing

  • New tests:
    • toOrganization exposes managed countries with id and nativeName only.
    • /api/v1/convert returns iso2 / native_name for a projection with a country, null for a world-wide one, and no en_name / fr_name.
  • npm run lint: clean.
  • npm run test: 5492 passing, 5 failing. The 5 failures also fail on develop and are unrelated:
    • Document get-snapshots
    • 4 order-dependent Changes relevance-swap tests in shard 3, which pass in isolation
  • Fresh volume: initialised a throwaway grottocenter-dbserver container from this branch's sql/.
    • Init completes.
    • t_country has the 6 expected columns.
    • The view, its 4 indexes and its owner are in place.
    • Re-running the migration is idempotent.
  • Production-like schema: initialised a container from develop's sql/, then applied the migration by hand.
    • The columns are dropped.
    • The view is recreated with its 4 indexes, owned by gc_owner, with the same ACL as before (gc_app=arwd, gc_readonly=r).
    • REFRESH ... CONCURRENTLY and search_outbox_enqueue_data_quality() succeed.
  • API on that migrated database, connected as gc_app:
    • GET /api/v1/convert returns 200 with iso2.
    • GET /api/v1/entrances/with-quality/countries/FR?sort=country_name returns 200 with native names.
    • GET /api/v1/organizations/1 returns managedCountries: [{ id, nativeName }].
    • The organization export query from api/dbSync/entities/organization.js runs.

📸 Previews

No UI change. In the projection menu of the front end, groups are now labelled from iso2 through Intl.DisplayNames instead of the en_name fallback.

- Select co.iso AS iso2 in the projection query: the front end localizes the
  group label of a projection from iso2 and falls back to en_name, which no
  longer exists once t_country loses its translated names.
- Sort by native country name instead of the French one.
- Fix the j_country_crs fixture, which used column names instead of the model
  attributes and so loaded rows with no country.
- Document iso2 and native_name in the swagger, and that Fr_name is always World.
- Drop en_name, fr_name, es_name, de_name, bg_name, it_name, ca_name, nl_name
  and rs_name from t_country: native_name is the only name the API and the
  front end read, and the front end localizes country names from the ISO code.
- Expose native_name instead of fr_name as country_name in
  v_data_quality_compute_entrance, the last reader of fr_name: the
  data-quality endpoints now return and sort on the native name (España
  instead of Espagne).
- Add migration 9_37, one transaction: recreate the view with its four
  indexes, refresh it, give it back to gc_owner when gc_owner owns the tables,
  restore its grants, then drop the columns.
- Remove the fields from TCountry, from managedCountries in toOrganization
  and the swagger, from the organization export GROUP BY, from 0_tables.sql,
  the countries seed and the fixtures.
@tristan0x tristan0x self-assigned this Nov 6, 2026
@tristan0x
tristan0x requested review from ClemRz and Paul-AUB November 6, 2026 15:41

@Paul-AUB Paul-AUB left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changes requested for deployment safety.

Given the size of the diff, analysis prioritized the migration, business logic and public API changes. All 250 country seed rows were also checked mechanically: their six retained values are unchanged.

Runtime validation is incomplete: the focused converter test command could not start because Mocha is not installed, and no PostgreSQL container is running. The chained lint command therefore did not run. Database initialization and migration checks reported in the PR were not independently reproduced.

- State in migration 9_37 that the API code which no longer reads the
  translated country names must be deployed, with no older process left,
  before the migration runs: the current code declares the columns in
  TCountry, sorts on fr_name in ConvertService and groups by them in the
  organization export, so it fails on the migrated schema.
- Note that rolling the code back after the migration requires restoring the
  columns and their data first.

@Paul-AUB Paul-AUB left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previously requested deployment-order correction is addressed in the migration header and PR description. No further blocking findings identified.

Given the diff size, analysis prioritized migration ownership/grants/indexes, runtime readers and public API changes. Independently checked that all 250 country seed rows preserve their six retained values, the recreated view matches the canonical definition, and the organization converter emits only the intended country fields.

Validation: changed JavaScript passes ESLint when linted with LF-normalized input; the Windows checkout's CRLF endings cause formatting-only errors in a direct lint run. PostgreSQL/Docker and the local API are unavailable here, so the migration and route checks reported in the PR were not independently reproduced. GitHub's build-test check passes.

@tristan0x
tristan0x merged commit d1ec437 into develop Nov 7, 2026
5 checks passed
@tristan0x
tristan0x deleted the feat/retire-unused-name-columns-of-t-country-use-native branch November 7, 2026 01:14

This branch was successfully deployed

1 active deployment
build — 6c309fde Deployed Nov 6, 2026 by tristan0x via build-test #4180
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Retire unused name columns of t_country, use native_name in the data quality view

2 participants