cpp2sqlite is a C++ tool that generates SQLite databases containing Swiss Healthcare Public Domain Drug Information. It aggregates data from multiple Swiss health authority sources (Swissmedic, BAG, Refdata, etc.) into SQLite databases used by AmiKo and other applications.
cd scripts && source steps_public1.source && ./download.sh
source steps_public2.source && ./download.sh
cd ../build && cmake .. && make -j9Note: BOOST_BIND_GLOBAL_PLACEHOLDERS is defined in CMakeLists.txt to suppress Boost bind placeholder deprecation warnings (the project doesn't use boost::bind directly, but Boost headers trigger the warning internally).
cpp2sqlite- Main tool, generates amiko_db SQLite databasespharma- Generates pharma.csvsai- Processes SAI (Refdata structured article information)zurrose- Processes Zur Rose data
All support --fhir flag to use BAG FHIR ndjson instead of BAG XML.
- Source:
src/bagFHIR.cpp/src/bagFHIR.hpp - Input:
downloads/fhir-sl-{de,fr,it}.ndjsonfrom https://epl.bag.admin.ch/static/fhir/foph-sl-export-latest-{de,fr,it}.ndjson (per-language NDJSON) - Each line is a FHIR Bundle with entries: MedicinalProductDefinition, RegulatedAuthorization, PackagedProductDefinition, Ingredient, ClinicalUseDefinition
- Prices (EFP/PP) and reimbursement data are in RegulatedAuthorization extensions under
reimbursementSL>productPrice - Legal status codes map to categories: A (756005022001), B (756005022003), C (756005022005), D (756005022007, 756005022008), E (756005022009)
- When
--fhiris active, all price lookups (including from Refdata and Swissmedic) must useBAGFHIR::getPricesAndFlags()instead ofBAG::getPricesAndFlags(), sinceBAG::parseXML()is not called and its prepList is empty
- Mandatory on SL prescriptions and invoices from 2026-07-01 (BAG Rundschreiben 2026-02-19); insurers may reject non-compliant invoices from 2027-01-01
- Source:
src/bagFHIR.cppcollectBundleIndC()— bundle-scoped pass over each NDJSON line (one Bundle per line) XXXXXcomes from oneRegulatedAuthorization.extension[reimbursementSL].extension[FOPHDossierNumber].valueIdentifier.value;.NNis the trailing all-digit segment of eachClinicalUseDefinition.id(e.g.CYRAMZA.01); onlytype == "indication"CUDs are picked up. The actual feed shipstypeas a plain string andindicationas a single object — both shapes are handled.- Limitations text comes from
indication.diseaseSymptomProcedure.concept.text, with fallbackindication.extension[url == "limitationText"].valueString - Stored on
BAG::Preparation.indicationCodes(and copied onto everyPack) asIndicationCode {code, cudId, text} BAGFHIR::getIndCByRegnr(regnr, &codes, &text)returns the joined columns the schema expects: comma-joined codes + newline-joinedcode: textlines, deduped by code, in bundle order. Mirrors rust2xml ≥ 3.1.12 (INDIKATIONSCODE/INDIKATIONSCODE_TEXTXML elements). The function walks the entireprepListand merges IndicationCodes from every prep that shares the queried Swissmedic regnr, deduped by code — required because the same 5-digit Swissmedic regnr typically spans multiple FHIR bundles (only one of which carries the type=indication ClinicalUseDefinitions). An earlier early-return on the first matching prep with empty indicationCodes silently dropped IndC for ~80% of regnrs.- Schema/binding:
Sql::useIndCis set fromflagFHIRinopenDB(). When true, theamikodbschema gains two trailing TEXT columns (indikationscode,indikationscode_text) andinsertRowbinds positions 19/20. Non-FHIR builds emit the legacy 19-column schema, so apps reading by column index keep working. - iOS consumer:
generikacc/Generika/IndCSection.swift(issue zdavatz/generikacc#102) — guarded byAmikoDBManager isIndcColumnAvailableso older DB snapshots don't break the app
src/- C++ source filessrc/c2s/- cpp2sqlite specific sourcessrc/pha/- pharma specific sourcessrc/sai/- SAI specific sourcessrc/zur/- zurrose specific sourcesscripts/- Build and download scriptsinput/- Input data files (not in git)downloads/- Downloaded source files (not in git)output/- Generated databases and reports (not in git)