diff --git a/.Rbuildignore b/.Rbuildignore index 91114bf..51cbb5f 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -1,2 +1,4 @@ ^.*\.Rproj$ ^\.Rproj\.user$ +^LICENSE\.md$ +.github/* diff --git a/.github/workflows/R_CMD_check.yaml b/.github/workflows/R_CMD_check.yaml new file mode 100644 index 0000000..c458ae0 --- /dev/null +++ b/.github/workflows/R_CMD_check.yaml @@ -0,0 +1,117 @@ +# For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. +# https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions +on: + push: + branches: + - '**' + pull_request: + branches: + - '**' + +name: R-CMD-check + +jobs: + R-CMD-check: + runs-on: ${{ matrix.config.os }} + + name: ${{ matrix.config.os }} (${{ matrix.config.r }}) + + strategy: + # Test create and drop tables in a database so they cannot be executed in parallel + max-parallel: 1 + fail-fast: false + matrix: + config: + - {os: macOS-latest, r: 'release'} + - {os: ubuntu-20.04, r: 'release', rspm: "https://packagemanager.rstudio.com/cran/__linux__/focal/latest"} + - {os: windows-latest, r: 'release'} # Does not appear to have Java 32-bit, hence the --no-multiarch + + env: + R_REMOTES_NO_ERRORS_FROM_WARNINGS: true + RSPM: ${{ matrix.config.rspm }} + CDMDDLBASE_POSTGRESQL_USER: ${{ secrets.CDMDDLBASE_POSTGRESQL_USER }} + CDMDDLBASE_POSTGRESQL_PASSWORD: ${{ secrets.CDMDDLBASE_POSTGRESQL_PASSWORD }} + CDMDDLBASE_POSTGRESQL_SERVER: ${{ secrets.CDMDDLBASE_POSTGRESQL_SERVER }} + CDMDDLBASE_POSTGRESQL_SCHEMA: ${{ secrets.CDMDDLBASE_POSTGRESQL_SCHEMA }} + + steps: + - uses: actions/checkout@v2 + + - uses: r-lib/actions/setup-r@v1 + with: + r-version: ${{ matrix.config.r }} + + - uses: r-lib/actions/setup-tinytex@v1 + + - uses: r-lib/actions/setup-pandoc@v1 + + - name: Query dependencies + run: | + install.packages('remotes') + saveRDS(remotes::dev_package_deps(dependencies = TRUE), ".github/depends.Rds", version = 2) + writeLines(sprintf("R-%i.%i", getRversion()$major, getRversion()$minor), ".github/R-version") + shell: Rscript {0} + + - name: Cache R packages + if: runner.os != 'Windows' + uses: actions/cache@v2 + with: + path: ${{ env.R_LIBS_USER }} + key: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1-${{ hashFiles('.github/depends.Rds') }} + restore-keys: ${{ runner.os }}-${{ hashFiles('.github/R-version') }}-1- + + - name: Install system dependencies + if: runner.os == 'Linux' + run: | + while read -r cmd + do + eval sudo $cmd + done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "20.04"))') + + - name: Install libssh + if: runner.os == 'Linux' + run: | + sudo apt-get install libssh-dev + + - name: Install dependencies + run: | + remotes::install_deps(dependencies = TRUE, INSTALL_opts=c("--no-multiarch")) + remotes::install_cran("rcmdcheck") + shell: Rscript {0} + + - name: Install covr + if: runner.os == 'macOS' + run: | + remotes::install_cran("covr") + shell: Rscript {0} + + - name: Remove check folder if exists + if: runner.os == 'macOS' + run: unlink("check", recursive = TRUE) + shell: Rscript {0} + + - name: Check + env: + _R_CHECK_CRAN_INCOMING_REMOTE_: false + run: rcmdcheck::rcmdcheck(args = c("--no-manual", "--as-cran", "--no-multiarch"), error_on = "warning", check_dir = "check") + shell: Rscript {0} + + - name: Upload check results + if: failure() + uses: actions/upload-artifact@v2 + with: + name: ${{ runner.os }}-r${{ matrix.config.r }}-results + path: check + + - name: Upload source package + if: success() && runner.os == 'macOS' && github.event_name != 'pull_request' && github.ref == 'refs/heads/master' + uses: actions/upload-artifact@v2 + with: + name: package_tarball + path: check/*.tar.gz + + - name: Test coverage + if: runner.os == 'macOS' + run: covr::codecov() + shell: Rscript {0} + diff --git a/CdmDdlBase.Rproj b/CommonDataModel.Rproj similarity index 100% rename from CdmDdlBase.Rproj rename to CommonDataModel.Rproj diff --git a/DESCRIPTION b/DESCRIPTION index 290b438..9e8b93e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,4 +1,4 @@ -Package: CdmDdlBase +Package: CommonDataModel Type: Package Title: OMOP CDM DDL and Documentation Generator Version: 0.1.0 @@ -14,6 +14,15 @@ Imports: rmarkdown, stringr, readxl, - dplyr + DatabaseConnector, + DBI, + dplyr, + readr +Suggests: + knitr, + testthat (>= 3.0.0), + RSQLite, + withr NeedsCompilation: no RoxygenNote: 7.1.1 +Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index e843930..4946218 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -4,9 +4,10 @@ export(createDdl) export(createForeignKeys) export(createPrimaryKeys) export(downloadCurrentDdl) +export(executeDdl) export(listSupportedVersions) export(parseWiki) -export(writeDDL) +export(writeDdl) export(writeForeignKeys) export(writeIndex) export(writePrimaryKeys) diff --git a/R/createDdl.R b/R/createDdl.R index 3ccf0d6..74464e6 100644 --- a/R/createDdl.R +++ b/R/createDdl.R @@ -1,4 +1,3 @@ - # Copyright 2019 Observational Health Data Sciences and Informatics # # This file is part of CdmDdlBase @@ -15,21 +14,30 @@ # See the License for the specific language governing permissions and # limitations under the License. -#' Create a DDL script from a two csv files that detail the OMOP CDM Specifications. These files also form the basis of the CDM documentation and the Data Quality +#' Create the OHDSI-SQL Common Data Model DDL code +#' +#' The createDdl, createForeignKeys, and createPrimaryKeys functions each return a character string +#' containing their respective DDL SQL code in OHDSQL dialect for a specific CDM version. +#' The SQL they generate needs to be rendered and translated before it can be executed. +#' +#' The DDL SQL code is created from a two csv files that detail the OMOP CDM Specifications. +#' These files also form the basis of the CDM documentation and the Data Quality #' Dashboard. #' -#' @param cdmVersionNum The version of the CDM you are creating, e.g. 5.3.1 -#' -#' @param cdmTableCsvLoc The location of the csv file with the high-level CDM table information. This is defaulted to "inst/csv/OMOP_CDMv5.3.1_Table_Level.csv". -#' If a new version of this file was committed to the CDM repository the package automatically will grab it and place it in "inst/csv/". -#' @param cdmFieldCsvLoc The location of the csv file with the CDM field information. This is defaulted to "inst/csv/OMOP_CDMv5.3.1_Field_Level.csv". -#' If a new version of this file was committed to the CDM repository the package automatically will grab it and place it in "inst/csv/". -#' @param outputFile The name of the output ddl sql file. This is defaulted to a location in the inst/sql/sql server folder and named with today's date and the CDM version. +#' @param cdmVersion The version of the CDM you are creating, e.g. 5.3, 5.4 +#' @return A character string containing the OHDSQL DDL #' @export +#' @examples +#' ddl <- createDdl("5.4") +#' pk <- createPrimaryKeys("5.4") +#' fk <- createForeignKeys("5.4") +createDdl <- function(cdmVersion){ -createDdl <- function(cdmVersion = cdmVersion){ - cdmTableCsvLoc = paste0("inst/csv/OMOP_CDMv", cdmVersion, "_Table_Level.csv") - cdmFieldCsvLoc = paste0("inst/csv/OMOP_CDMv", cdmVersion, "_Field_Level.csv") + # argument checks + stopifnot(is.character(cdmVersion), length(cdmVersion) == 1, cdmVersion %in% listSupportedVersions()) + + cdmTableCsvLoc <- system.file(file.path("csv", paste0("OMOP_CDMv", cdmVersion, "_Table_Level.csv")), package = "CommonDataModel", mustWork = TRUE) + cdmFieldCsvLoc <- system.file(file.path("csv", paste0("OMOP_CDMv", cdmVersion, "_Field_Level.csv")), package = "CommonDataModel", mustWork = TRUE) tableSpecs <- read.csv(cdmTableCsvLoc, stringsAsFactors = FALSE) cdmSpecs <- read.csv(cdmFieldCsvLoc, stringsAsFactors = FALSE) @@ -37,7 +45,7 @@ createDdl <- function(cdmVersion = cdmVersion){ tableList <- tableSpecs$cdmTableName sql_result <- c() - sql_result <- c(paste0("--@targetdialect CDM DDL Specification for OMOP Common Data Model ", cdmVersion)) + sql_result <- c(paste0("--@targetDialect CDM DDL Specification for OMOP Common Data Model ", cdmVersion)) for (tableName in tableList){ fields <- subset(cdmSpecs, cdmTableName == tableName) fieldNames <- fields$cdmFieldName @@ -81,3 +89,52 @@ createDdl <- function(cdmVersion = cdmVersion){ } return(paste0(sql_result, collapse = "")) } + + +#' @describeIn createDdl createPrimaryKeys Returns a string containing the OHDSQL for creation of primary keys in the OMOP CDM. +#' @export +createPrimaryKeys <- function(cdmVersion){ + + # argument checks + stopifnot(is.character(cdmVersion), length(cdmVersion) == 1, cdmVersion %in% listSupportedVersions()) + + cdmFieldCsvLoc <- system.file(file.path("csv", paste0("OMOP_CDMv", cdmVersion, "_Field_Level.csv")), package = "CommonDataModel", mustWork = TRUE) + cdmSpecs <- read.csv(cdmFieldCsvLoc, stringsAsFactors = FALSE) + + primaryKeys <- subset(cdmSpecs, isPrimaryKey == "Yes") + pkFields <- primaryKeys$cdmFieldName + + sql_result <- c(paste0("--@targetDialect CDM Primary Key Constraints for OMOP Common Data Model ", cdmVersion, "\n")) + for (pkField in pkFields){ + + subquery <- subset(primaryKeys, cdmFieldName==pkField) + + sql_result <- c(sql_result, paste0("\nALTER TABLE @cdmDatabaseSchema.", subquery$cdmTableName, " ADD CONSTRAINT xpk_", subquery$cdmTableName, " PRIMARY KEY NONCLUSTERED (", subquery$cdmFieldName , ");\n")) + + } + return(paste0(sql_result, collapse = "")) +} + +#' @describeIn createDdl createForeignKeys Returns a string containing the OHDSQL for creation of foreign keys in the OMOP CDM. +#' @export +createForeignKeys <- function(cdmVersion){ + + # argument checks + stopifnot(is.character(cdmVersion), length(cdmVersion) == 1, cdmVersion %in% listSupportedVersions()) + + cdmFieldCsvLoc <- system.file(file.path("csv", paste0("OMOP_CDMv", cdmVersion, "_Field_Level.csv")), package = "CommonDataModel", mustWork = TRUE) + cdmSpecs <- read.csv(cdmFieldCsvLoc, stringsAsFactors = FALSE) + + foreignKeys <- subset(cdmSpecs, isForeignKey == "Yes") + foreignKeys$key <- paste0(foreignKeys$cdmTableName, "_", foreignKeys$cdmFieldName) + + sql_result <- c(paste0("--@targetDialect CDM Foreign Key Constraints for OMOP Common Data Model ", cdmVersion, "\n")) + for (foreignKey in foreignKeys$key){ + + subquery <- subset(foreignKeys, foreignKeys$key==foreignKey) + + sql_result <- c(sql_result, paste0("\nALTER TABLE @cdmDatabaseSchema.", subquery$cdmTableName, " ADD CONSTRAINT fpk_", subquery$cdmTableName, "_", subquery$cdmFieldName, " FOREIGN KEY (", subquery$cdmFieldName , ") REFERENCES @cdmDatabaseSchema.", subquery$fkTableName, " (", subquery$fkFieldName, ");\n")) + + } + return(paste0(sql_result, collapse = "")) +} diff --git a/R/createForeignKeys.R b/R/createForeignKeys.R deleted file mode 100644 index 0317ed4..0000000 --- a/R/createForeignKeys.R +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2019 Observational Health Data Sciences and Informatics -# -# This file is part of CdmDdlBase -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#' Create a foreign key sql script from two csv files that detail the OMOP CDM Specifications. - -#' @param cdmVersionNum The version of the CDM you are creating, e.g. 5.3.1 -#' @export - -createForeignKeys <- function(cdmVersion = cdmVersion){ - cdmFieldCsvLoc <- paste0("inst/csv/OMOP_CDMv", cdmVersion, "_Field_Level.csv") - cdmSpecs <- read.csv(cdmFieldCsvLoc, stringsAsFactors = FALSE) - - foreignKeys <- subset(cdmSpecs, isForeignKey == "Yes") - foreignKeys$key <- paste0(foreignKeys$cdmTableName, "_", foreignKeys$cdmFieldName) - - sql_result <- c(paste0("--@targetdialect CDM Foreign Key Constraints for OMOP Common Data Model ", cdmVersion, "\n")) - for (foreignKey in foreignKeys$key){ - - subquery <- subset(foreignKeys, foreignKeys$key==foreignKey) - - sql_result <- c(sql_result, paste0("\nALTER TABLE @cdmDatabaseSchema.", subquery$cdmTableName, " ADD CONSTRAINT fpk_", subquery$cdmTableName, "_", subquery$cdmFieldName, " FOREIGN KEY (", subquery$cdmFieldName , ") REFERENCES @cdmDatabaseSchema.", subquery$fkTableName, " (", subquery$fkFieldName, ");\n")) - - } - return(paste0(sql_result, collapse = "")) -} diff --git a/R/createPrimaryKeys.R b/R/createPrimaryKeys.R deleted file mode 100644 index 6897ecf..0000000 --- a/R/createPrimaryKeys.R +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2019 Observational Health Data Sciences and Informatics -# -# This file is part of CdmDdlBase -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#' Create a primary key sql script from two csv files that detail the OMOP CDM Specifications. - -#' @param cdmVersionNum The version of the CDM you are creating, e.g. 5.3 -#' @export - -createPrimaryKeys <- function(cdmVersion = cdmVersion){ - cdmFieldCsvLoc <- paste0("inst/csv/OMOP_CDMv", cdmVersion, "_Field_Level.csv") - cdmSpecs <- read.csv(cdmFieldCsvLoc, stringsAsFactors = FALSE) - - primaryKeys <- subset(cdmSpecs, isPrimaryKey == "Yes") - pkFields <- primaryKeys$cdmFieldName - - sql_result <- c(paste0("--@targetdialect CDM Primary Key Constraints for OMOP Common Data Model ", cdmVersion, "\n")) - for (pkField in pkFields){ - - subquery <- subset(primaryKeys, cdmFieldName==pkField) - - sql_result <- c(sql_result, paste0("\nALTER TABLE @cdmDatabaseSchema.", subquery$cdmTableName, " ADD CONSTRAINT xpk_", subquery$cdmTableName, " PRIMARY KEY NONCLUSTERED (", subquery$cdmFieldName , ");\n")) - - } - return(paste0(sql_result, collapse = "")) -} diff --git a/R/downloadCurrentDdl.R b/R/downloadCurrentDdl.R index 2831e7b..8bd9de3 100644 --- a/R/downloadCurrentDdl.R +++ b/R/downloadCurrentDdl.R @@ -11,7 +11,8 @@ #' #' @examples #' \dontrun{ -#' downloadCurrentDdl("OHDSI/CommonDataModel", pathToCsv="Sql%20Server/OMOP%20CDM%20sql%20server%20ddl.txt") +#' downloadCurrentDdl("OHDSI/CommonDataModel", +#' pathToCsv="Sql%20Server/OMOP%20CDM%20sql%20server%20ddl.txt") #' } #' #' @export diff --git a/R/executeDdl.R b/R/executeDdl.R new file mode 100644 index 0000000..ed5e010 --- /dev/null +++ b/R/executeDdl.R @@ -0,0 +1,86 @@ +# Copyright 2019 Observational Health Data Sciences and Informatics +# +# This file is part of CdmDdlBase +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +#' Generate and execute the DDL on a database +#' +#' This function will generate the DDL for a specific dbms and CDM version and +#' then execute the DDL on a database. +#' +#' @param connectionDetails An object of class connectionDetails as created by the DatabaseConnector::createConnectionDetails function. +#' @param cdmVersion The version of the CDM you are creating, e.g. 5.3, 5.4 +#' @param cdmDatabaseSchema The schema of the CDM instance where the DDL will be run. For example, this would be "ohdsi.dbo" when testing on sql server. +#' @param executeDdl Should the DDL be executed? TRUE or FALSE +#' @param executePrimaryKey Should the primary keys be added? TRUE or FALSE +#' @param executeForeignKey Should the foreign keys be added? TRUE or FALSE +#' @param ... Other arguments passed on to DatabaseConnector::executeSql. (This allows the user to set the path to errorReportFile.) +#' @export +#' +#' @examples +#' \dontrun{ +#' executeDdl(connectionDetails = connectionDetails, +#' cdmVersion = "5.4", +#' cdmDatabaseSchema = "myCdm") +#'} +executeDdl <- function(connectionDetails, + cdmVersion, + cdmDatabaseSchema, + executeDdl = TRUE, + executePrimaryKey = TRUE, + executeForeignKey = TRUE, + ...) { + + outputpath <- tempdir(check = TRUE) + + + if(executeDdl) { + filename <- writeDdl(targetDialect = connectionDetails$dbms, + cdmVersion = cdmVersion, + cdmDatabaseSchema = cdmDatabaseSchema, + outputpath = outputpath) + + sql <- readr::read_file(file.path(outputpath, filename)) + } else { + sql <- "" + } + + if(executePrimaryKey) { + filename <- writePrimaryKeys(targetDialect = connectionDetails$dbms, + cdmVersion = cdmVersion, + cdmDatabaseSchema = cdmDatabaseSchema, + outputpath = outputpath) + + sql <- paste(sql, readr::read_file(file.path(outputpath, filename)), sep = "\n") + } + + if(executeForeignKey) { + filename <- writeForeignKeys(targetDialect = connectionDetails$dbms, + cdmVersion = cdmVersion, + cdmDatabaseSchema = cdmDatabaseSchema, + outputpath = outputpath) + + sql <- paste(sql, readr::read_file(file.path(outputpath, filename)), sep = "\n") + } + + con <- DatabaseConnector::connect(connectionDetails = connectionDetails) + + DatabaseConnector::executeSql(con, sql = sql, ...) + + DatabaseConnector::disconnect(con) +} + + + + diff --git a/R/writeDDL.R b/R/writeDDL.R index 153096d..6b89082 100644 --- a/R/writeDDL.R +++ b/R/writeDDL.R @@ -16,22 +16,108 @@ #' Write DDL script #' -#' @param targetdialect The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server" -#' @param cdmVersion The version of the CDM for which you are creating the DDL. e.g. 5.3.1 +#' Write the DDL to a SQL file. The SQL will be rendered (parameters replaced) and translated to the target SQL +#' dialect. By default the @cdmDatabaseSchema parameter is kept in the SQL file and needs to be replaced before +#' execution. +#' +#' @param targetDialect The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server" +#' @param cdmVersion The version of the CDM you are creating, e.g. 5.3, 5.4 +#' @param outputpath The directory or folder where the SQL file should be saved. #' @param cdmDatabaseSchema The schema of the CDM instance where the DDL will be run. For example, this would be "ohdsi.dbo" when testing on sql server. #' Defaults to "@cdmDatabaseSchema" #' #' @export -writeDDL <- function(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") { - outputpath <- file.path("ddl", cdmVersion, targetdialect) - dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) +writeDdl <- function(targetDialect, cdmVersion, outputpath, cdmDatabaseSchema = "@cdmDatabaseSchema") { + + # argument checks + stopifnot(targetDialect %in% c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) + stopifnot(cdmVersion %in% listSupportedVersions()) + stopifnot(is.character(cdmDatabaseSchema)) + + if(missing(outputpath)) { + outputpath <- file.path("ddl", cdmVersion, gsub(" ", "_", targetDialect)) + } + + if(!dir.exists(outputpath)) dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) sql <- createDdl(cdmVersion) - sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetdialect = targetdialect) - sql <- SqlRender::translate(sql, targetDialect = targetdialect) + sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetDialect = targetDialect) + sql <- SqlRender::translate(sql, targetDialect = targetDialect) - filename <- paste("OMOPCDM", targetdialect, cdmVersion, "ddl.sql", sep = "_") - SqlRender::writeSql(sql = sql, - targetFile = file.path(outputpath, filename) - ) + filename <- paste("OMOPCDM", gsub(" ", "_", targetDialect), cdmVersion, "ddl.sql", sep = "_") + SqlRender::writeSql(sql = sql, targetFile = file.path(outputpath, filename)) + invisible(filename) +} + +#' @describeIn writeDdl writePrimaryKeys Write the SQL code that creates the primary keys to a file. +#' @export +writePrimaryKeys <- function(targetDialect, cdmVersion, outputpath, cdmDatabaseSchema = "@cdmDatabaseSchema") { + + # argument checks + stopifnot(targetDialect %in% c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) + stopifnot(cdmVersion %in% listSupportedVersions()) + stopifnot(is.character(cdmDatabaseSchema)) + + if(missing(outputpath)) { + outputpath <- file.path("ddl", cdmVersion, gsub(" ", "_", targetDialect)) + } + + if(!dir.exists(outputpath)) dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) + + sql <- createPrimaryKeys(cdmVersion) + sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetDialect = targetDialect) + sql <- SqlRender::translate(sql, targetDialect = targetDialect) + + filename <- paste("OMOPCDM", gsub(" ", "_", targetDialect), cdmVersion, "primary", "keys.sql", sep = "_") + SqlRender::writeSql(sql = sql, targetFile = file.path(outputpath, filename)) + invisible(filename) +} + +#' @describeIn writeDdl writeForeignKeys Write the SQL code that creates the foreign keys to a file. +#' @export +writeForeignKeys <- function(targetDialect, cdmVersion, outputpath, cdmDatabaseSchema = "@cdmDatabaseSchema") { + + # argument checks + stopifnot(targetDialect %in% c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) + stopifnot(cdmVersion %in% listSupportedVersions()) + stopifnot(is.character(cdmDatabaseSchema)) + + if(missing(outputpath)) { + outputpath <- file.path("ddl", cdmVersion, gsub(" ", "_", targetDialect)) + } + + if(!dir.exists(outputpath)) dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) + + sql <- createForeignKeys(cdmVersion) + sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetDialect = targetDialect) + sql <- SqlRender::translate(sql, targetDialect = targetDialect) + + filename <- paste("OMOPCDM", gsub(" ", "_", targetDialect), cdmVersion, "constraints.sql", sep = "_") + SqlRender::writeSql(sql = sql, targetFile = file.path(outputpath, filename)) + invisible(filename) +} + +#' @describeIn writeDdl writeIndex Write the rendered and translated sql that creates recommended indexes to a file. +#' @export +writeIndex <- function(targetDialect, cdmVersion, outputpath, cdmDatabaseSchema = "@cdmDatabaseSchema") { + + # argument checks + stopifnot(targetDialect %in% c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) + stopifnot(cdmVersion %in% listSupportedVersions()) + stopifnot(is.character(cdmDatabaseSchema)) + + if(missing(outputpath)) { + outputpath <- file.path("ddl", cdmVersion, gsub(" ", "_", targetDialect)) + } + + if(!dir.exists(outputpath)) dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) + + sqlFilename <- paste0("OMOP_CDM_indices_v", cdmVersion, ".sql") + sql <- readr::read_file(system.file(file.path("sql", "sql_server", sqlFilename), package = "CommonDataModel")) + sql <- SqlRender::render(sql, targetDialect = targetDialect, cdmDatabaseSchema = cdmDatabaseSchema) + sql <- SqlRender::translate(sql, targetDialect = targetDialect) + + filename <- paste("OMOPCDM", gsub(" ", "_", targetDialect), cdmVersion, "indices.sql", sep = "_") + SqlRender::writeSql(sql = sql, targetFile = file.path(outputpath, filename)) + invisible(filename) } diff --git a/R/writeForeignKeys.R b/R/writeForeignKeys.R deleted file mode 100644 index 92e6bc0..0000000 --- a/R/writeForeignKeys.R +++ /dev/null @@ -1,36 +0,0 @@ -# Copyright 2017 Observational Health Data Sciences and Informatics -# -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#' Write constraint script -#' -#' @param targetdialect The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server" -#' @param cdmVersion The version of the CDM that you are creating the primary keys for -#' @param cdmDatabaseSchema The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema" -#' -#' @export - -writeForeignKeys <- function(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") { - outputpath <- file.path("ddl", cdmVersion, targetdialect) - dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) - - sql <- createForeignKeys(cdmVersion) - sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetdialect = targetdialect) - sql <- SqlRender::translate(sql, targetDialect = targetdialect) - - filename <- paste("OMOPCDM", targetdialect, cdmVersion, "constraints.sql", sep = "_") - SqlRender::writeSql(sql = sql, - targetFile = file.path(outputpath, filename) - ) -} diff --git a/R/writeIndex.R b/R/writeIndex.R deleted file mode 100644 index 5f53200..0000000 --- a/R/writeIndex.R +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright 2017 Observational Health Data Sciences and Informatics -# -# This file is part of DDLGeneratr -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#' Write Index script -#' -#' @param targetdialect The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server" -#' @param cdmVersion The version of the CDM that you are creating the indices for. e.g. 5.3.1 -#' @param cdmDatabaseSchema The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema" -#' -#' @export -writeIndex <- function(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") { - outputpath <- file.path("ddl", cdmVersion, targetdialect) - dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) - - sqlFilename <- paste0("OMOP CDM indices v", cdmVersion, ".sql") - sql <- SqlRender::loadRenderTranslateSql(sqlFilename = sqlFilename, - packageName = "CdmDdlBase", - dbms = targetdialect, - targetdialect = targetdialect, - cdmDatabaseSchema = cdmDatabaseSchema) - - filename <- paste("OMOPCDM", targetdialect, cdmVersion, "indices.sql", sep = "_") - SqlRender::writeSql(sql = sql, - targetFile = file.path(outputpath, filename)) -} diff --git a/R/writePrimaryKeys.R b/R/writePrimaryKeys.R deleted file mode 100644 index d867d33..0000000 --- a/R/writePrimaryKeys.R +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright 2017 Observational Health Data Sciences and Informatics -# -# This file is part of DDLGeneratr -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -#' Write primary key script -#' -#' @param targetdialect The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server" -#' @param cdmVersion The version of the CDM that you are creating the primary keys for -#' @param cdmDatabaseSchema The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema" -#' -#' @export - -writePrimaryKeys <- function(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") { - outputpath <- file.path("ddl", cdmVersion, targetdialect) - dir.create(outputpath, showWarnings = FALSE, recursive = TRUE) - - sql <- createPrimaryKeys(cdmVersion) - sql <- SqlRender::render(sql = sql, cdmDatabaseSchema = cdmDatabaseSchema, targetdialect = targetdialect) - sql <- SqlRender::translate(sql, targetDialect = targetdialect) - - filename <- paste("OMOPCDM", targetdialect, cdmVersion, "primary", "keys.sql", sep = "_") - SqlRender::writeSql(sql = sql, - targetFile = file.path(outputpath, filename) - ) -} diff --git a/ddl/5.3/sql server/OMOPCDM_sql server_5.3_constraints.sql b/ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_constraints.sql similarity index 100% rename from ddl/5.3/sql server/OMOPCDM_sql server_5.3_constraints.sql rename to ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_constraints.sql diff --git a/ddl/5.3/sql server/OMOPCDM_sql server_5.3_ddl.sql b/ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_ddl.sql similarity index 100% rename from ddl/5.3/sql server/OMOPCDM_sql server_5.3_ddl.sql rename to ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_ddl.sql diff --git a/ddl/5.3/sql server/OMOPCDM_sql server_5.3_indices.sql b/ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_indices.sql similarity index 100% rename from ddl/5.3/sql server/OMOPCDM_sql server_5.3_indices.sql rename to ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_indices.sql diff --git a/ddl/5.3/sql server/OMOPCDM_sql server_5.3_primary_keys.sql b/ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_primary_keys.sql similarity index 100% rename from ddl/5.3/sql server/OMOPCDM_sql server_5.3_primary_keys.sql rename to ddl/5.3/sql_server/OMOPCDM_sql_server_5.3_primary_keys.sql diff --git a/ddl/5.4/sql server/OMOPCDM_sql server_5.4_constraints.sql b/ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_constraints.sql similarity index 100% rename from ddl/5.4/sql server/OMOPCDM_sql server_5.4_constraints.sql rename to ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_constraints.sql diff --git a/ddl/5.4/sql server/OMOPCDM_sql server_5.4_ddl.sql b/ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_ddl.sql similarity index 100% rename from ddl/5.4/sql server/OMOPCDM_sql server_5.4_ddl.sql rename to ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_ddl.sql diff --git a/ddl/5.4/sql server/OMOPCDM_sql server_5.4_indices.sql b/ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_indices.sql similarity index 100% rename from ddl/5.4/sql server/OMOPCDM_sql server_5.4_indices.sql rename to ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_indices.sql diff --git a/ddl/5.4/sql server/OMOPCDM_sql server_5.4_primary_keys.sql b/ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_primary_keys.sql similarity index 100% rename from ddl/5.4/sql server/OMOPCDM_sql server_5.4_primary_keys.sql rename to ddl/5.4/sql_server/OMOPCDM_sql_server_5.4_primary_keys.sql diff --git a/errorReport.txt b/errorReport.txt deleted file mode 100644 index 85222f6..0000000 --- a/errorReport.txt +++ /dev/null @@ -1,26 +0,0 @@ -DBMS: -sql server - -Error: -com.microsoft.sqlserver.jdbc.SQLServerException: 'fpk_NOTE_person_id' is not a constraint. - -SQL: -ALTER TABLE ohdsi.dbo.NOTE DROP CONSTRAINT fpk_NOTE_person_id - -R version: -R version 3.4.2 (2017-09-28) - -Platform: -x86_64-w64-mingw32 - -Attached base packages: -- stats -- graphics -- grDevices -- utils -- datasets -- methods -- base - -Other attached packages: -- CdmDdlBase (0.1.0) \ No newline at end of file diff --git a/extras/codeToRun.R b/extras/codeToRun.R index fcc10a0..f93dcc3 100644 --- a/extras/codeToRun.R +++ b/extras/codeToRun.R @@ -7,17 +7,17 @@ cdmVersion <- "5.3" supportedVersions <- listSupportedVersions() for (cdmVersion in supportedVersions) { - for (targetdialect in c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) { - writeDDL(targetdialect = targetdialect, + for (targetDialect in c("oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server")) { + writeDdl(targetDialect = targetDialect, cdmVersion = cdmVersion) - writePrimaryKeys(targetdialect = targetdialect, + writePrimaryKeys(targetDialect = targetDialect, cdmVersion = cdmVersion) - writeForeignKeys(targetdialect = targetdialect, + writeForeignKeys(targetDialect = targetDialect, cdmVersion = cdmVersion) - writeIndex(targetdialect = targetdialect, + writeIndex(targetDialect = targetDialect, cdmVersion = cdmVersion) } } diff --git a/inst/csv/OMOP_CDMv5.3_Field_Level.csv b/inst/csv/OMOP_CDMv5.3_Field_Level.csv index 6b7418c..80e0e9f 100644 --- a/inst/csv/OMOP_CDMv5.3_Field_Level.csv +++ b/inst/csv/OMOP_CDMv5.3_Field_Level.csv @@ -514,20 +514,4 @@ ATTRIBUTE_DEFINITION,attribute_name,Yes,varchar(255),,,No,No,,,,, ATTRIBUTE_DEFINITION,attribute_description,No,varchar(MAX),,,No,No,,,,, ATTRIBUTE_DEFINITION,attribute_type_concept_id,Yes,integer,,,No,Yes,CONCEPT,CONCEPT_ID,,, ATTRIBUTE_DEFINITION,attribute_syntax,No,varchar(MAX),,,No,No,,,,, -======= -1-Jan-1970.",,No,No,,,,, -DRUG_STRENGTH,valid_end_date,Yes,date,The date when then Concept became invalid.,,No,No,,,,, -DRUG_STRENGTH,invalid_reason,No,varchar(1),"Reason the concept was invalidated. Possible values are D (deleted), U (replaced with an update) or NULL when valid_end_date has the default value.",,No,No,,,,, -COHORT_DEFINITION,cohort_definition_id,Yes,integer,"This is the identifier given to the cohort, usually by the ATLAS application",,No,No,,,,, -COHORT_DEFINITION,cohort_definition_name,Yes,varchar(255),A short description of the cohort,,No,No,,,,, -COHORT_DEFINITION,cohort_definition_description,No,varchar(MAX),A complete description of the cohort.,,No,No,,,,, -COHORT_DEFINITION,definition_type_concept_id,Yes,integer,Type defining what kind of Cohort Definition the record represents and how the syntax may be executed.,,No,Yes,CONCEPT,CONCEPT_ID,,, -COHORT_DEFINITION,cohort_definition_syntax,No,varchar(MAX),Syntax or code to operationalize the Cohort Definition.,,No,No,,,,, -COHORT_DEFINITION,subject_concept_id,Yes,integer,"This field contains a Concept that represents the domain of the subjects that are members of the cohort (e.g., Person, Provider, Visit).",,No,Yes,CONCEPT,CONCEPT_ID,,, -COHORT_DEFINITION,cohort_initiation_date,No,date,A date to indicate when the Cohort was initiated in the COHORT table.,,No,No,,,,, -ATTRIBUTE_DEFINITION,attribute_definition_id,Yes,integer,,,No,No,,,,, -ATTRIBUTE_DEFINITION,attribute_name,Yes,varchar(255),,,No,No,,,,, -ATTRIBUTE_DEFINITION,attribute_description,No,varchar(MAX),,,No,No,,,,, -ATTRIBUTE_DEFINITION,attribute_type_concept_id,Yes,integer,,,No,Yes,CONCEPT,CONCEPT_ID,,, -ATTRIBUTE_DEFINITION,attribute_syntax,No,varchar(MAX),,,No,No,,,,, ->>>>>>> v5.4:inst/csv/OMOP_CDMv5.3.1_Field_Level.csv + diff --git a/inst/sql/sql_server/OMOP CDM indices v5.3.sql b/inst/sql/sql_server/OMOP_CDM_indices_v5.3.sql similarity index 99% rename from inst/sql/sql_server/OMOP CDM indices v5.3.sql rename to inst/sql/sql_server/OMOP_CDM_indices_v5.3.sql index 9e96c2b..c4a50b5 100644 --- a/inst/sql/sql_server/OMOP CDM indices v5.3.sql +++ b/inst/sql/sql_server/OMOP_CDM_indices_v5.3.sql @@ -1,4 +1,4 @@ -/*@targetdialect OMOP CDM Indices +/*@targetDialect OMOP CDM Indices There are no unique indices created because it is assumed that the primary key constraints have been run prior to implementing indices. diff --git a/inst/sql/sql_server/OMOP CDM indices v5.4.sql b/inst/sql/sql_server/OMOP_CDM_indices_v5.4.sql similarity index 99% rename from inst/sql/sql_server/OMOP CDM indices v5.4.sql rename to inst/sql/sql_server/OMOP_CDM_indices_v5.4.sql index 9e96c2b..c4a50b5 100644 --- a/inst/sql/sql_server/OMOP CDM indices v5.4.sql +++ b/inst/sql/sql_server/OMOP_CDM_indices_v5.4.sql @@ -1,4 +1,4 @@ -/*@targetdialect OMOP CDM Indices +/*@targetDialect OMOP CDM Indices There are no unique indices created because it is assumed that the primary key constraints have been run prior to implementing indices. diff --git a/inst/sql/sql_server/OMOP CDM indices v6.0.sql b/inst/sql/sql_server/OMOP_CDM_indices_v6.0.sql similarity index 99% rename from inst/sql/sql_server/OMOP CDM indices v6.0.sql rename to inst/sql/sql_server/OMOP_CDM_indices_v6.0.sql index ac1aabb..520320c 100644 --- a/inst/sql/sql_server/OMOP CDM indices v6.0.sql +++ b/inst/sql/sql_server/OMOP_CDM_indices_v6.0.sql @@ -1,4 +1,4 @@ -/*@targetdialect OMOP CDM Indices*/ +/*@targetDialect OMOP CDM Indices*/ /************************ diff --git a/man/createDdl.Rd b/man/createDdl.Rd index 748b83e..c30bec1 100644 --- a/man/createDdl.Rd +++ b/man/createDdl.Rd @@ -1,24 +1,42 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/createDdl.R +% Please edit documentation in R/createdDdl.R \name{createDdl} \alias{createDdl} -\title{Create a DDL script from a two csv files that detail the OMOP CDM Specifications. These files also form the basis of the CDM documentation and the Data Quality -Dashboard.} +\alias{createPrimaryKeys} +\alias{createForeignKeys} +\title{Create the OHDSI-SQL Common Data Model DDL code} \usage{ -createDdl(cdmVersion = cdmVersion) +createDdl(cdmVersion) + +createPrimaryKeys(cdmVersion) + +createForeignKeys(cdmVersion) } \arguments{ -\item{cdmVersionNum}{The version of the CDM you are creating, e.g. 5.3.1} - -\item{cdmTableCsvLoc}{The location of the csv file with the high-level CDM table information. This is defaulted to "inst/csv/OMOP_CDMv5.3.1_Table_Level.csv". -If a new version of this file was committed to the CDM repository the package automatically will grab it and place it in "inst/csv/".} - -\item{cdmFieldCsvLoc}{The location of the csv file with the CDM field information. This is defaulted to "inst/csv/OMOP_CDMv5.3.1_Field_Level.csv". -If a new version of this file was committed to the CDM repository the package automatically will grab it and place it in "inst/csv/".} - -\item{outputFile}{The name of the output ddl sql file. This is defaulted to a location in the inst/sql/sql server folder and named with today's date and the CDM version.} +\item{cdmVersion}{The version of the CDM you are creating, e.g. 5.3, 5.4} +} +\value{ +A character string containing the OHDSQL DDL } \description{ -Create a DDL script from a two csv files that detail the OMOP CDM Specifications. These files also form the basis of the CDM documentation and the Data Quality +The createDdl, createForeignKeys, and createPrimaryKeys functions each return a character string +containing their respective DDL SQL code in OHDSQL dialect for a specific CDM version. +The SQL they generate needs to be rendered and translated before it can be executed. +} +\details{ +The DDL SQL code is created from a two csv files that detail the OMOP CDM Specifications. +These files also form the basis of the CDM documentation and the Data Quality Dashboard. } +\section{Functions}{ +\itemize{ +\item \code{createPrimaryKeys}: createPrimaryKeys asdfladsfj + +\item \code{createForeignKeys}: createForeignKeys asdfladsf +}} + +\examples{ +ddl <- createDdl("5.4") +pk <- createPrimaryKeys("5.4") +fk <- createForeignKeys("5.4") +} diff --git a/man/createForeignKeys.Rd b/man/createForeignKeys.Rd deleted file mode 100644 index e5d54c3..0000000 --- a/man/createForeignKeys.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/createForeignKeys.R -\name{createForeignKeys} -\alias{createForeignKeys} -\title{Create a foreign key sql script from two csv files that detail the OMOP CDM Specifications.} -\usage{ -createForeignKeys(cdmVersion = cdmVersion) -} -\arguments{ -\item{cdmVersionNum}{The version of the CDM you are creating, e.g. 5.3.1} -} -\description{ -Create a foreign key sql script from two csv files that detail the OMOP CDM Specifications. -} diff --git a/man/createPrimaryKeys.Rd b/man/createPrimaryKeys.Rd deleted file mode 100644 index 53e5236..0000000 --- a/man/createPrimaryKeys.Rd +++ /dev/null @@ -1,14 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/createPrimaryKeys.R -\name{createPrimaryKeys} -\alias{createPrimaryKeys} -\title{Create a primary key sql script from two csv files that detail the OMOP CDM Specifications.} -\usage{ -createPrimaryKeys(cdmVersion = cdmVersion) -} -\arguments{ -\item{cdmVersionNum}{The version of the CDM you are creating, e.g. 5.3} -} -\description{ -Create a primary key sql script from two csv files that detail the OMOP CDM Specifications. -} diff --git a/man/downloadCurrentDdl.Rd b/man/downloadCurrentDdl.Rd index 8b806b3..867c863 100644 --- a/man/downloadCurrentDdl.Rd +++ b/man/downloadCurrentDdl.Rd @@ -27,7 +27,8 @@ The default location is } \examples{ \dontrun{ -downloadCurrentDdl("OHDSI/CommonDataModel", pathToCsv="Sql\%20Server/OMOP\%20CDM\%20sql\%20server\%20ddl.txt") +downloadCurrentDdl("OHDSI/CommonDataModel", + pathToCsv="Sql\%20Server/OMOP\%20CDM\%20sql\%20server\%20ddl.txt") } } diff --git a/man/executeDdl.Rd b/man/executeDdl.Rd new file mode 100644 index 0000000..6a49797 --- /dev/null +++ b/man/executeDdl.Rd @@ -0,0 +1,42 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/executeDdl.R +\name{executeDdl} +\alias{executeDdl} +\title{Generate and execute the DDL on a database} +\usage{ +executeDdl( + connectionDetails, + cdmVersion, + cdmDatabaseSchema, + executeDdl = TRUE, + executePrimaryKey = TRUE, + executeForeignKey = TRUE, + ... +) +} +\arguments{ +\item{connectionDetails}{An object of class connectionDetails as created by the DatabaseConnector::createConnectionDetails function.} + +\item{cdmVersion}{The version of the CDM you are creating, e.g. 5.3, 5.4} + +\item{cdmDatabaseSchema}{The schema of the CDM instance where the DDL will be run. For example, this would be "ohdsi.dbo" when testing on sql server.} + +\item{executeDdl}{Should the DDL be executed? TRUE or FALSE} + +\item{executePrimaryKey}{Should the primary keys be added? TRUE or FALSE} + +\item{executeForeignKey}{Should the foreign keys be added? TRUE or FALSE} + +\item{...}{Other arguments passed on to DatabaseConnector::executeSql. (This allows the user to set the path to errorReportFile.)} +} +\description{ +This function will generate the DDL for a specific dbms and CDM version and +then execute the DDL on a database. +} +\examples{ +\dontrun{ +executeDdl(connectionDetails = connectionDetails, + cdmVersion = "5.4", + cdmDatabaseSchema = "myCdm") +} +} diff --git a/man/writeDDL.Rd b/man/writeDDL.Rd index d541d50..c245499 100644 --- a/man/writeDDL.Rd +++ b/man/writeDDL.Rd @@ -1,19 +1,61 @@ % Generated by roxygen2: do not edit by hand -% Please edit documentation in R/writeDDL.R -\name{writeDDL} -\alias{writeDDL} +% Please edit documentation in R/writeDdl.R +\name{writeDdl} +\alias{writeDdl} +\alias{writePrimaryKeys} +\alias{writeForeignKeys} +\alias{writeIndex} \title{Write DDL script} \usage{ -writeDDL(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") +writeDdl( + targetDialect, + cdmVersion, + outputpath, + cdmDatabaseSchema = "@cdmDatabaseSchema" +) + +writePrimaryKeys( + targetDialect, + cdmVersion, + outputpath, + cdmDatabaseSchema = "@cdmDatabaseSchema" +) + +writeForeignKeys( + targetDialect, + cdmVersion, + outputpath, + cdmDatabaseSchema = "@cdmDatabaseSchema" +) + +writeIndex( + targetDialect, + cdmVersion, + outputpath, + cdmDatabaseSchema = "@cdmDatabaseSchema" +) } \arguments{ -\item{targetdialect}{The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server"} +\item{targetDialect}{The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server"} -\item{cdmVersion}{The version of the CDM for which you are creating the DDL. e.g. 5.3.1} +\item{cdmVersion}{The version of the CDM you are creating, e.g. 5.3, 5.4} + +\item{outputpath}{The directory or folder where the SQL file should be saved.} \item{cdmDatabaseSchema}{The schema of the CDM instance where the DDL will be run. For example, this would be "ohdsi.dbo" when testing on sql server. Defaults to "@cdmDatabaseSchema"} } \description{ -Write DDL script +Write the DDL to a SQL file. The SQL will be rendered (parameters replaced) and translated to the target SQL +dialect. By default the @cdmDatabaseSchema parameter is kept in the SQL file and needs to be replaced before +execution. } +\section{Functions}{ +\itemize{ +\item \code{writePrimaryKeys}: writePrimaryKeys Write the SQL code that creates the primary keys to a file. + +\item \code{writeForeignKeys}: writeForeignKeys Write the SQL code that creates the foreign keys to a file. + +\item \code{writeIndex}: writeIndex Write the rendered and translated sql that creates recommended indexes to a file. +}} + diff --git a/man/writeForeignKeys.Rd b/man/writeForeignKeys.Rd deleted file mode 100644 index fe4d855..0000000 --- a/man/writeForeignKeys.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/writeForeignKeys.R -\name{writeForeignKeys} -\alias{writeForeignKeys} -\title{Write constraint script} -\usage{ -writeForeignKeys( - targetdialect, - cdmVersion, - cdmDatabaseSchema = "@cdmDatabaseSchema" -) -} -\arguments{ -\item{targetdialect}{The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server"} - -\item{cdmVersion}{The version of the CDM that you are creating the primary keys for} - -\item{cdmDatabaseSchema}{The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema"} -} -\description{ -Write constraint script -} diff --git a/man/writeIndex.Rd b/man/writeIndex.Rd deleted file mode 100644 index 5042f3c..0000000 --- a/man/writeIndex.Rd +++ /dev/null @@ -1,18 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/writeIndex.R -\name{writeIndex} -\alias{writeIndex} -\title{Write Index script} -\usage{ -writeIndex(targetdialect, cdmVersion, cdmDatabaseSchema = "@cdmDatabaseSchema") -} -\arguments{ -\item{targetdialect}{The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server"} - -\item{cdmVersion}{The version of the CDM that you are creating the indices for. e.g. 5.3.1} - -\item{cdmDatabaseSchema}{The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema"} -} -\description{ -Write Index script -} diff --git a/man/writePrimaryKeys.Rd b/man/writePrimaryKeys.Rd deleted file mode 100644 index ad1e2ff..0000000 --- a/man/writePrimaryKeys.Rd +++ /dev/null @@ -1,22 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/writePrimaryKeys.R -\name{writePrimaryKeys} -\alias{writePrimaryKeys} -\title{Write primary key script} -\usage{ -writePrimaryKeys( - targetdialect, - cdmVersion, - cdmDatabaseSchema = "@cdmDatabaseSchema" -) -} -\arguments{ -\item{targetdialect}{The dialect of the target database. Choices are "oracle", "postgresql", "pdw", "redshift", "impala", "netezza", "bigquery", "sql server"} - -\item{cdmVersion}{The version of the CDM that you are creating the primary keys for} - -\item{cdmDatabaseSchema}{The name of the schema where the cdm sits. Defaults to "@cdmDatabaseSchema"} -} -\description{ -Write primary key script -} diff --git a/tests/setup.R b/tests/setup.R new file mode 100644 index 0000000..d4a2841 --- /dev/null +++ b/tests/setup.R @@ -0,0 +1,21 @@ +# Download the JDBC drivers used in the tests + +# oldJarFolder <- Sys.getenv("DATABASECONNECTOR_JAR_FOLDER") + +driverPath <- file.path(Sys.getenv("HOME"), "drivers") +if(!dir.exists(driverPath)) dir.create(driverPath) +Sys.setenv("DATABASECONNECTOR_JAR_FOLDER" = driverPath) +DatabaseConnector::downloadJdbcDrivers("postgresql", pathToDriver = driverPath) + +print(Sys.getenv("DATABASECONNECTOR_JAR_FOLDER")) +print(list.files(driverPath)) +# if(Sys.getenv("DATABASECONNECTOR_JAR_FOLDER") == "") { + # driverPath <- file.path(Sys.getenv("HOME"), "drivers") +# } +# downloadJdbcDrivers("sql server") +# downloadJdbcDrivers("oracle") + +# withr::defer({ +# unlink(Sys.getenv("DATABASECONNECTOR_JAR_FOLDER"), recursive = TRUE, force = TRUE) +# Sys.setenv("DATABASECONNECTOR_JAR_FOLDER" = oldJarFolder) +# }, testthat::teardown_env()) diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..eaa35d8 --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,4 @@ +library(testthat) +library(CommonDataModel) + +test_check("CommonDataModel") diff --git a/tests/testthat/test-createDdl.R b/tests/testthat/test-createDdl.R new file mode 100644 index 0000000..19dd82f --- /dev/null +++ b/tests/testthat/test-createDdl.R @@ -0,0 +1,38 @@ +test_that("createDdl works", { + # for(cdmVersion in listSupportedVersions()) { # 5.3 ddl csv control file is currently messed up. + cdmVersion <- "5.4" + sql <- createDdl(cdmVersion) + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + # } + + expect_error(createDdl(5.4)) + expect_error(createDdl("blah")) + +}) + +test_that("createPrimaryKeys works", { + # for(cdmVersion in listSupportedVersions()) { + cdmVersion <- "5.4" + sql <- createPrimaryKeys(cdmVersion) + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + # } + + expect_error(createPrimaryKeys(5.4)) + expect_error(createPrimaryKeys("blah")) +}) + +test_that("createForeignKeys works", { + # for(cdmVersion in listSupportedVersions()) { + cdmVersion <- "5.4" + sql <- createForeignKeys(cdmVersion) + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + # } + + expect_error(createForeignKeys(5.4)) + expect_error(createForeignKeys("blah")) +}) + + diff --git a/tests/testthat/test-executeDdl.R b/tests/testthat/test-executeDdl.R new file mode 100644 index 0000000..4710f7b --- /dev/null +++ b/tests/testthat/test-executeDdl.R @@ -0,0 +1,84 @@ +library(DatabaseConnector) + +connectionDetails <- createConnectionDetails( + dbms = "postgresql", + user = Sys.getenv("CDMDDLBASE_POSTGRESQL_USER"), + password = Sys.getenv("CDMDDLBASE_POSTGRESQL_PASSWORD"), + server = Sys.getenv("CDMDDLBASE_POSTGRESQL_SERVER"), + pathToDriver = file.path(Sys.getenv("HOME"), "drivers") +) + +# Helper functions used in tests +.listTablesInSchema <- function(connectionDetails, schema) { + con <- DatabaseConnector::connect(connectionDetails) + tables <- DBI::dbListObjects(con, prefix = "cdmddlbase") + DatabaseConnector::disconnect(con) + tables <- subset(tables, is_prefix == FALSE) + tables <- subset(tables, grepl("table", table))$table + tables <- vapply(tables, function(.) .@name, FUN.VALUE = character(1)) + return(tables) +} + +.dropAllTablesFromSchema <- function(connectionDetails, schema) { + tables <- .listTablesInSchema(connectionDetails, schema) + + con <- DatabaseConnector::connect(connectionDetails) + for(table in tables) { + DBI::dbRemoveTable(con, name = DBI::SQL(paste(schema, table, sep = "."))) + } + DatabaseConnector::disconnect(con) +} + +.removeConstraintsPostgresql <- function(connectionDetails, schema) { + # the order of removal of constraints matters! + con <- DatabaseConnector::connect(connectionDetails) + constraints <- DBI::dbGetQuery(con, + "SELECT con.conname, rel.relname as relname + FROM pg_catalog.pg_constraint con + INNER JOIN pg_catalog.pg_class rel + ON rel.oid = con.conrelid + INNER JOIN pg_catalog.pg_namespace nsp + ON nsp.oid = connamespace + WHERE nsp.nspname = 'cdmddlbase';") + + + constraints <- dplyr::mutate(constraints, sql = paste0("alter table ", schema, ".", relname, " drop constraint if exists ", conname, ";\n" )) + + sql <- paste(rev(constraints$sql), collapse = "") + executeSql(con, sql) + + disconnect(con) + +} + +test_that("Database can be connected to", { + expect_error(con <- connect(connectionDetails), NA) + disconnect(con) +}) + +test_that("Execute DDL on Postgres", { + # make sure the schema is cleared out + cdmDatabaseSchema <- Sys.getenv("CDMDDLBASE_POSTGRESQL_SCHEMA") + cdmVersion <- "5.4" + # .removeConstraintsPostgresql(connectionDetails, cdmDatabaseSchema) + .dropAllTablesFromSchema(connectionDetails, cdmDatabaseSchema) + cat(paste("Connecting to schema", cdmDatabaseSchema, "\n")) + executeDdl(connectionDetails, + cdmVersion = cdmVersion, + cdmDatabaseSchema = cdmDatabaseSchema, + executeDdl = TRUE, + executePrimaryKey = FALSE, + executeForeignKey = FALSE) + + tables <- .listTablesInSchema(connectionDetails, schema = cdmDatabaseSchema) + + cdmTableCsvLoc <- system.file(file.path("csv", paste0("OMOP_CDMv", cdmVersion, "_Table_Level.csv")), package = "CommonDataModel", mustWork = TRUE) + tableSpecs <- read.csv(cdmTableCsvLoc, stringsAsFactors = FALSE)$cdmTableName + + # check that the tables in the database match the tables in the specification + expect_equal(sort(tables), sort(tableSpecs)) + + # clear schema + # .removeConstraintsPostgresql(connectionDetails, cdmDatabaseSchema) + .dropAllTablesFromSchema(connectionDetails, cdmDatabaseSchema) +}) diff --git a/tests/testthat/test-writeDdl.R b/tests/testthat/test-writeDdl.R new file mode 100644 index 0000000..1c95f2b --- /dev/null +++ b/tests/testthat/test-writeDdl.R @@ -0,0 +1,51 @@ +test_that("writeDdl works", { + + outputpath <- tempdir(TRUE) + filename <- writeDdl(targetDialect = "postgresql", cdmVersion = "5.4", outputpath = outputpath) + + expect_true(file.exists(file.path(outputpath, filename))) + sql <- readr::read_file(file.path(outputpath, filename)) + + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + +}) + +test_that("writePrimaryKeys works", { + + outputpath <- tempdir(TRUE) + filename <- writePrimaryKeys(targetDialect = "postgresql", cdmVersion = "5.4", outputpath = outputpath) + + expect_true(file.exists(file.path(outputpath, filename))) + sql <- readr::read_file(file.path(outputpath, filename)) + + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + +}) + +test_that("writeForeignKeys works", { + + outputpath <- tempdir(TRUE) + filename <- writeForeignKeys(targetDialect = "postgresql", cdmVersion = "5.4", outputpath = outputpath) + + expect_true(file.exists(file.path(outputpath, filename))) + sql <- readr::read_file(file.path(outputpath, filename)) + + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + +}) + +test_that("writeIndex works", { + + outputpath <- tempdir(TRUE) + filename <- writeIndex(targetDialect = "postgresql", cdmVersion = "5.4", outputpath = outputpath) + + expect_true(file.exists(file.path(outputpath, filename))) + sql <- readr::read_file(file.path(outputpath, filename)) + + expect_type(sql, "character") + expect_gt(nchar(sql), 10) + +})