# CommonDataModel is where the CSVs are the source of truth and the DDL is the output

> The OHDSI CommonDataModel repository is the R package and the SQL DDL set behind the OMOP Common Data Model, the observational data model used across the OHDSI community. Its most consequential rule is a negative one: never edit the DDL directly, because the CSV files are the ground truth that the DDL, the documentation and the data quality dashboard are all generated from.

**OHDSI/CommonDataModel** — Definition and DDLs for the OMOP Common Data Model (CDM)

- Repository: https://github.com/OHDSI/CommonDataModel
- Website: https://ohdsi.github.io/CommonDataModel
- Stars: 1,097 · Forks: 515
- Language: HTML
- License: not declared
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/ohdsi-commondatamodel

## A schema, a package and a documentation pipeline

The CommonDataModel repository holds the definition and the DDLs for the OMOP Common Data Model, and the repository description says it in one line. What follows from that is the shape of the project. There is no application, no service and no data. There is a model, the SQL that creates it, the documentation that describes it, and the tooling that keeps those three in agreement.

The repository is an R package. The top level has DESCRIPTION and NAMESPACE, an R/ directory of the package's functions, man/ for the generated help pages, tests/ for the test suite, inst/ for the installed artefacts, docs/ and site/ for the documentation, extras/ for additional material, and the RStudio project file CommonDataModel.Rproj. There is also CRAN-SUBMISSION and cran-comments.md, which mark this as a package published to CRAN rather than a private script collection.

The audience is the OHDSI community and the people who work with observational health data: the analysts who need a table of conditions, drug exposures and measurements in a layout that lets a study be reproduced by someone else, and the engineers who build the pipelines that fill those tables.

The most important structural fact is stated as a prohibition in the contribution guide. Changes to the model structure should be made in the representative CSV files by adding, subtracting or renaming fields or tables, and the guide says in capitals: do not make any changes in the DDL itself. The structure is set up in such a way that the CSV files are the ground truth, and if changes are made in the DDL instead of the CSV files then the DDL will be out of sync with the documentation and the DQD.

So the DDL is a build artefact, and the schema lives in two CSV files.

## The DDLs are downloadable, and R is optional

The first section of the README is aimed at people who do not want to run R at all, and it is worth reading first because it changes who the project is for.

If you are looking for the SQL DDLs and do not wish to generate them through R, they can be accessed directly in the repository, under inst/ddl/5.5 for the current version. The latest release also contains the SQL scripts as zip files, and the bug fix section makes the same point in a different way: if you only want the latest version of the CDM and do not care about the R package, visit the tags and download the latest, which will include the DDLs for all currently supported versions of the CDM for all supported SQL dialects.

That is the practical answer for most adopters. A data engineer setting up a database does not need an R toolchain, they need the SQL, and the project publishes it in both a browsable form and a packaged one.

The R package exists for the case where you want to generate the scripts yourself, or to instantiate the tables directly. Its documented dependencies are RStudio, along with DatabaseConnector and SqlRender, both from the same organisation, and the package can be installed from GitHub with devtools:

install devtools with install.packages("devtools") and then devtools::install_github("OHDSI/CommonDataModel").

The two functions worth knowing are the discovery ones, CommonDataModel::listSupportedDialects() and CommonDataModel::listSupportedVersions(), which tell you what the package can actually do on your database.

The dialect list is a hard constraint, because the DDL is written per dialect and the package will not generate one that it does not know how to write.

## buildRelease writes files, executeDdl creates tables

The README demonstrates the two ways the package can be used, and they differ in where the work happens.

The first is buildRelease, which generates the text files in the dialect you choose and puts the output files in the folder you specify:

```R
CommonDataModel::buildRelease(
  cdmVersions = "5.5",
  targetDialects = "postgresql",
  outputfolder = "/pathToOutput"
)
```

This is the path for an end user who wants the scripts without cloning or downloading the source, and the result is a set of SQL files on disk that you then run with your own tooling.

The second is executeDdl, which connects to your SQL client directly, assuming your dbms is one of the supported dialects, and instantiates the tables through R. The connection details are created with DatabaseConnector:

```R
cd <- DatabaseConnector::createConnectionDetails(
  dbms = "postgresql",
  server = "localhost/ohdsi",
  user = "postgres",
  password = "postgres",
  pathToDriver = "/pathToDriver"
)
```

and then the schema is created in a named schema:

```R
CommonDataModel::executeDdl(
  connectionDetails = cd,
  cdmVersion = "5.5",
  cdmDatabaseSchema = "ohdsi_demo"
)
```

The difference in approach is the difference between generating a script and running one. buildRelease is script generation and leaves the execution to you, which is what you want if the SQL is going into a migration pipeline or a review process. executeDdl connects and acts, which is faster to try and gives less control over how the DDL reaches the database. The README also notes that if you have an empty schema ready to go, the package will connect and instantiate the tables for you, so the target has to exist first.

## One CSV, three consumers: DDL, documentation and quality checks

The contribution guide explains what the CSV files actually are, and this is the heart of the project.

Step 1.1 says that for changes to the model structure you rename the table level and field level inst/csv files from the current released version to the new version, for example renaming OMOP_CDMv5.3_Field_Level.csv and OMOP_CDMv5.3_Table_Level.csv to the v5.4 equivalents. And then it says why that matters: these files serve multiple functions, they are the basis for the CDM DDL, the CDM documentation, and the Data Quality Dashboard.

Step 1.2 fills in the mechanics. If a new table is added, a line goes into the Table_Level.csv with the table name and description and the table is listed as part of the CDM schema, and the remaining columns are quality checks that can be run, with details in the Data Quality Dashboard documentation. Changes to CDM fields go into the Field_Level.csv, and the columns are meant to mimic how a DDL is structured, which is how it will eventually be generated. A yes in the isRequired field indicates a NOT NULL constraint, and the datatype field should be filled in exactly how it would look in the DDL. Additions and changes should also be reflected in the userGuidance and etlConventions fields, which are the basis for the documentation.

So a single row in a CSV produces a column in a table, a paragraph of documentation, and a set of automated checks. That is a much better arrangement than three separate artefacts that drift, and it explains why the guide is so insistent about the DDL never being edited by hand.

The Data Quality Dashboard is the part of this that a consumer benefits from even without contributing, since the same files drive the checks that validate a loaded database.

## New versions and bug fixes take different paths

The process has two branches of work, and the guide is explicit about which is which.

For a change to the model structure, you request a new branch in the CommonDataModel repository for the new version of the CDM, then fork the repository and clone the newly made branch. For squashing bugs, you fork the repository and clone the master branch. The difference matters, because a bug fix should not land on a branch that is about to become a new version, and a structural change should not land on master.

The scope of a bug fix is also constrained. Bug fixes are made much the same way using the CSV files, but they should be limited to typos, primary and foreign key relationships, and formatting, with datetime versus datetime2 given as the example of the kind of formatting difference that counts. Anything more belongs in a new version.

The reason is that the model is versioned in public. A new table or a renamed field changes what every consumer of that version sees, so it needs a version, a working group decision and a migration path, while a typo does not.

One more detail is worth knowing, and it is a limitation of the model rather than of the process. ETL conventions are not currently tracked by CDM version unless they are conventions specific to new fields, with CONDITION_STATUS given as the example, added in v5.3, which specifies the way primary condition designations should be captured. The guide says general ETL convention changes are not tracked by CDM version except where specific to new fields. That does not mean older fields have no conventions; consult the current field guidance and document local ETL decisions.

## Two version lines in one repository

The release history is worth reading carefully, because there are two numbering schemes in play.

The recent releases are v1.1.0, labelled as the CDM v5.5 CRAN release, dated 2026-10-09, then v5.5.0, labelled as CDM v5.5, from 2026-08-25, and v5.4.3 from 2026-08-04.

So the R package on CRAN is at version 1.1.0 and corresponds to the CDM v5.5, while the repository also carries tags named after the CDM versions themselves, v5.5.0 and v5.4.3. The CRAN version and the model version are different counters, and the release note in the tag name is what ties them together.

That matters for anyone scripting around this. The answer to the question of which version you have depends on which artefact you are holding, the R package version or the DDL release, and the README is the place that distinguishes them, since the guidance for a user who does not care about the R package is to go to the tags and download the latest.

The governance around new versions is also described. New CDM versions and updates are decided by the CDM working group, with details of how to join the meetings on the project homepage, and the changes are tracked as issues in the GitHub repository. Once the working group decides which changes make up a version, all the corresponding issues should be tagged with a version number such as v5.5 and added to a project board.

The repository is not archived, the last push was on 2026-10-09, and the licence is not one of the standard identifiers that GitHub can classify, so the terms are not recorded in the repository metadata. The docs/ directory holds the rendered documentation and site/ the site content, and the NEWS.md is the changelog for the R package.

## Conclusion

CommonDataModel suits an analyst or engineer running observational health data studies who needs the same schema as the rest of the OHDSI community, and who can run the DDL in a supported SQL dialect. It does not suit a team that wants a database with data in it, since the model is a schema and a set of conventions, not an ETL pipeline, although pre-generated DDL can be used without R. Verify first which CDM version and which SQL dialect you need against the supported lists, and if you intend to contribute, work through the CSV files rather than the generated SQL, because a change made in the DDL alone leaves the documentation and the data quality dashboard out of step with the model.

## FAQ

### Where can I get the OMOP CDM SQL DDL scripts without using R?

They are browsable directly in the repository under inst/ddl/5.5 for the current version, and the latest release contains the DDLs for all currently supported CDM versions and all supported SQL dialects as zip files.

### How do I generate the CDM DDL from R?

Install the package from GitHub with devtools::install_github("OHDSI/CommonDataModel"), then call CommonDataModel::buildRelease with the cdmVersions, targetDialects and outputfolder arguments, as in the README example that targets postgresql for CDM 5.5.

### What is the difference between buildRelease and executeDdl?

buildRelease generates the DDL text files into a folder you specify, leaving execution to you, while executeDdl connects to your database through DatabaseConnector and instantiates the tables directly in a schema you name.

### Why should I not edit the DDL directly?

The guide states that the CSV files are the ground truth, because they are the basis for the CDM DDL, the CDM documentation and the Data Quality Dashboard. A change made only in the DDL leaves the documentation and the dashboard out of sync with the model.

### How are changes to the model made?

Changes to the model structure are made in the representative CSV files by adding, subtracting or renaming fields or tables, and they go into a new branch for the new CDM version, with the working group deciding which changes make up a version. Bug fixes, limited to typos, key relationships and formatting, are made in the CSV files for the version being fixed on master.

## Sources

- [Issues](https://github.com/OHDSI/CommonDataModel/issues)
- [OHDSI/CommonDataModel on GitHub](https://github.com/OHDSI/CommonDataModel)
- [Project website](https://ohdsi.github.io/CommonDataModel)
- [README](https://github.com/OHDSI/CommonDataModel/blob/main/README.md)
- [Releases](https://github.com/OHDSI/CommonDataModel/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ohdsi-commondatamodel
