├── .Rbuildignore ├── .classpath ├── .github ├── pull_request_template.md └── workflows │ ├── R_CMD_check_Hades.yaml │ ├── R_CMD_check_main_weekly.yaml │ └── reverse_dependency.yml ├── .gitignore ├── .project ├── .settings ├── org.eclipse.cdt.codan.core.prefs ├── org.eclipse.cdt.managedbuilder.core.prefs └── org.eclipse.jdt.core.prefs ├── CRAN-SUBMISSION ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── HelperFunctions.R ├── RenderSql.R ├── ShinyApps.R ├── SparkSql.R └── SqlRender.R ├── README.md ├── SqlRender.Rproj ├── _pkgdown.yml ├── compare_versions ├── cran-comments.md ├── deploy.sh ├── docs ├── 404.html ├── articles │ ├── UsingSqlRender.html │ ├── UsingSqlRender_files │ │ ├── accessible-code-block-0.0.1 │ │ │ └── empty-anchor.js │ │ ├── anchor-sections-1.0 │ │ │ ├── anchor-sections.css │ │ │ └── anchor-sections.js │ │ ├── header-attrs-2.10 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.11 │ │ │ └── header-attrs.js │ │ ├── header-attrs-2.4 │ │ │ └── header-attrs.js │ │ └── header-attrs-2.5 │ │ │ └── header-attrs.js │ └── index.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── jquery.sticky-kit.min.js ├── link.svg ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── pull_request_template.html ├── reference │ ├── Rplot001.png │ ├── SqlRender-package.html │ ├── SqlRender.html │ ├── camelCaseToSnakeCase.html │ ├── camelCaseToSnakeCaseNames.html │ ├── camelCaseToTitleCase.html │ ├── createRWrapperForSql.html │ ├── getTempTablePrefix.html │ ├── index.html │ ├── launchSqlRenderDeveloper.html │ ├── listSupportedDialects.html │ ├── loadRenderTranslateSql.html │ ├── readSql.html │ ├── render.html │ ├── renderSql.html │ ├── renderSqlFile.html │ ├── snakeCaseToCamelCase.html │ ├── snakeCaseToCamelCaseNames.html │ ├── sparkHandleInsert.html │ ├── splitSql.html │ ├── supportsJava8.html │ ├── translate.html │ ├── translateSingleStatement.html │ ├── translateSql.html │ ├── translateSqlFile.html │ └── writeSql.html └── sitemap.xml ├── extras ├── PackageMaintenance.R └── SqlRender.pdf ├── inst ├── csv │ ├── jarChecksum.txt │ ├── replacementPatterns.csv │ └── supportedDialects.csv ├── doc │ └── UsingSqlRender.pdf ├── java │ └── SqlRender.jar ├── shinyApps │ └── SqlDeveloper │ │ ├── SqlDeveloper.Rproj │ │ ├── server.R │ │ ├── ui.R │ │ └── widgets.R └── sql │ ├── oracle │ └── test.sql │ ├── sql_server │ └── test.sql │ └── test2.sql ├── java ├── SqlRender.jardesc └── org │ └── ohdsi │ └── sql │ ├── BigQuerySparkTranslate.java │ ├── JarChecksum.java │ ├── MainClass.java │ ├── SqlRender.java │ ├── SqlSplit.java │ ├── SqlTranslate.java │ ├── StringUtils.java │ └── TestSqlRender.java ├── license_header_stub.txt ├── man ├── SqlRender-package.Rd ├── camelCaseToSnakeCase.Rd ├── camelCaseToSnakeCaseNames.Rd ├── camelCaseToTitleCase.Rd ├── createRWrapperForSql.Rd ├── getTempTablePrefix.Rd ├── launchSqlRenderDeveloper.Rd ├── listSupportedDialects.Rd ├── loadRenderTranslateSql.Rd ├── readSql.Rd ├── render.Rd ├── renderSql.Rd ├── renderSqlFile.Rd ├── snakeCaseToCamelCase.Rd ├── snakeCaseToCamelCaseNames.Rd ├── sparkHandleInsert.Rd ├── splitSql.Rd ├── supportsJava8.Rd ├── translate.Rd ├── translateSingleStatement.Rd ├── translateSql.Rd ├── translateSqlFile.Rd └── writeSql.Rd ├── pom.xml ├── tests ├── testthat.R └── testthat │ ├── setup.R │ ├── test-helperFunctions.R │ ├── test-renderSql.R │ ├── test-replacement-patterns-file-format.R │ ├── test-splitSql.R │ ├── test-translate-bigquery.R │ ├── test-translate-duckdb.R │ ├── test-translate-hive.R │ ├── test-translate-impala.R │ ├── test-translate-iris.R │ ├── test-translate-netezza.R │ ├── test-translate-oracle.R │ ├── test-translate-pdw.R │ ├── test-translate-postgresql.R │ ├── test-translate-redshift.R │ ├── test-translate-snowflake.R │ ├── test-translate-spark.R │ ├── test-translate-sql_server.R │ ├── test-translate-sqlite-extended.R │ ├── test-translate-sqlite.R │ ├── test-translate-synapse.R │ └── test-translateSql.R └── vignettes ├── .gitignore └── UsingSqlRender.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | extras 2 | license_header_stub.txt 3 | pom.xml 4 | ^.*\.Rproj$ 5 | ^\.Rproj\.user$ 6 | .travis.yml 7 | .classpath 8 | .project 9 | ^cran-comments.md$ 10 | build.xml 11 | deploy.sh 12 | extras/ 13 | pom.xml 14 | bin/ 15 | .idea/ 16 | SqlRender.iml 17 | license_header_stub.txt 18 | target/ 19 | docs 20 | compare_versions 21 | _pkgdown.yml 22 | ^CRAN-RELEASE$ 23 | .github 24 | ^CRAN-SUBMISSION$ 25 | revdep 26 | -------------------------------------------------------------------------------- /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | Before you do a pull request, you should always **file an issue** and make sure the package maintainer agrees that it’s a problem, and is happy with your basic proposal for fixing it. We don’t want you to spend a bunch of time on something that we don’t think is a good idea. 2 | 3 | Additional requirements for pull requests: 4 | 5 | - Adhere to the [Developer Guidelines](https://ohdsi.github.io/MethodsLibrary/developerGuidelines.html) as well as the [OHDSI Code Style](https://ohdsi.github.io/MethodsLibrary/codeStyle.html). 6 | 7 | - If possible, add unit tests for new functionality you add. 8 | 9 | - Restrict your pull request to solving the issue at hand. Do not try to 'improve' parts of the code that are not related to the issue. If you feel other parts of the code need better organization, create a separate issue for that. 10 | 11 | - Make sure you pass R check without errors and warnings before submitting. 12 | 13 | - Always target the `develop` branch, and make sure you are up-to-date with the develop branch. 14 | 15 | -------------------------------------------------------------------------------- /.github/workflows/R_CMD_check_Hades.yaml: -------------------------------------------------------------------------------- 1 | # For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. 2 | # https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions 3 | on: 4 | push: 5 | branches: 6 | - '**' 7 | pull_request: 8 | branches: 9 | - '**' 10 | 11 | name: R-CMD-check 12 | 13 | jobs: 14 | R-CMD-check: 15 | runs-on: ${{ matrix.config.os }} 16 | 17 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 18 | 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | config: 23 | - {os: windows-latest, r: 'release', rtools: '', rspm: "https://cloud.r-project.org"} 24 | - {os: macOS-latest, r: 'release', rtools: '', rspm: "https://cloud.r-project.org"} 25 | - {os: ubuntu-22.04, r: 'release', rspm: "https://packagemanager.posit.co/cran/__linux__/jammy/latest"} 26 | env: 27 | GITHUB_PAT: ${{ secrets.GH_TOKEN }} 28 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 29 | RSPM: ${{ matrix.config.rspm }} 30 | CDM5_ORACLE_CDM_SCHEMA: ${{ secrets.CDM5_ORACLE_CDM_SCHEMA }} 31 | CDM5_ORACLE_OHDSI_SCHEMA: ${{ secrets.CDM5_ORACLE_OHDSI_SCHEMA }} 32 | CDM5_ORACLE_PASSWORD: ${{ secrets.CDM5_ORACLE_PASSWORD }} 33 | CDM5_ORACLE_SERVER: ${{ secrets.CDM5_ORACLE_SERVER }} 34 | CDM5_ORACLE_USER: ${{ secrets.CDM5_ORACLE_USER }} 35 | CDM5_POSTGRESQL_CDM_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_CDM_SCHEMA }} 36 | CDM5_POSTGRESQL_OHDSI_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_OHDSI_SCHEMA }} 37 | CDM5_POSTGRESQL_PASSWORD: ${{ secrets.CDM5_POSTGRESQL_PASSWORD }} 38 | CDM5_POSTGRESQL_SERVER: ${{ secrets.CDM5_POSTGRESQL_SERVER }} 39 | CDM5_POSTGRESQL_USER: ${{ secrets.CDM5_POSTGRESQL_USER }} 40 | CDM5_SQL_SERVER_CDM_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_CDM_SCHEMA }} 41 | CDM5_SQL_SERVER_OHDSI_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_OHDSI_SCHEMA }} 42 | CDM5_SQL_SERVER_PASSWORD: ${{ secrets.CDM5_SQL_SERVER_PASSWORD }} 43 | CDM5_SQL_SERVER_SERVER: ${{ secrets.CDM5_SQL_SERVER_SERVER }} 44 | CDM5_SQL_SERVER_USER: ${{ secrets.CDM5_SQL_SERVER_USER }} 45 | CDM5_REDSHIFT_CDM_SCHEMA: ${{ secrets.CDM5_REDSHIFT_CDM_SCHEMA }} 46 | CDM5_REDSHIFT_OHDSI_SCHEMA: ${{ secrets.CDM5_REDSHIFT_OHDSI_SCHEMA }} 47 | CDM5_REDSHIFT_PASSWORD: ${{ secrets.CDM5_REDSHIFT_PASSWORD }} 48 | CDM5_REDSHIFT_SERVER: ${{ secrets.CDM5_REDSHIFT_SERVER }} 49 | CDM5_REDSHIFT_USER: ${{ secrets.CDM5_REDSHIFT_USER }} 50 | CDM5_SPARK_USER: ${{ secrets.CDM5_SPARK_USER }} 51 | CDM5_SPARK_PASSWORD: ${{ secrets.CDM5_SPARK_PASSWORD }} 52 | CDM5_SPARK_CONNECTION_STRING: ${{ secrets.CDM5_SPARK_CONNECTION_STRING }} 53 | 54 | steps: 55 | - uses: actions/checkout@v3 56 | 57 | - uses: r-lib/actions/setup-r@v2 58 | with: 59 | r-version: ${{ matrix.config.r }} 60 | 61 | - uses: r-lib/actions/setup-tinytex@v2 62 | 63 | - uses: r-lib/actions/setup-pandoc@v2 64 | 65 | - name: Install system requirements 66 | if: runner.os == 'Linux' 67 | run: | 68 | sudo apt-get install -y libssh-dev 69 | Rscript -e 'install.packages("remotes")' 70 | while read -r cmd 71 | do 72 | eval sudo $cmd 73 | done < <(Rscript -e 'writeLines(remotes::system_requirements("ubuntu", "22.04"))') 74 | 75 | - uses: r-lib/actions/setup-r-dependencies@v2 76 | with: 77 | extra-packages: any::rcmdcheck 78 | needs: check 79 | 80 | - uses: r-lib/actions/check-r-package@v2 81 | with: 82 | args: 'c("--no-manual", "--as-cran")' 83 | error-on: '"warning"' 84 | check-dir: '"check"' 85 | 86 | - name: Upload source package 87 | if: success() && runner.os == 'macOS' && github.event_name != 'pull_request' && github.ref == 'refs/heads/main' 88 | uses: actions/upload-artifact@v4 89 | with: 90 | name: package_tarball 91 | path: check/*.tar.gz 92 | 93 | - name: Install covr 94 | if: runner.os == 'Linux' 95 | run: | 96 | remotes::install_cran("covr") 97 | remotes::install_cran("xml2") 98 | shell: Rscript {0} 99 | 100 | - name: Test coverage 101 | if: runner.os == 'Linux' 102 | run: | 103 | cov <- covr::package_coverage( 104 | quiet = FALSE, 105 | clean = FALSE, 106 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package") 107 | ) 108 | covr::to_cobertura(cov) 109 | shell: Rscript {0} 110 | 111 | - uses: codecov/codecov-action@v4 112 | if: runner.os == 'Linux' 113 | with: 114 | file: ./cobertura.xml 115 | plugin: noop 116 | disable_search: true 117 | token: ${{ secrets.CODECOV_TOKEN }} 118 | 119 | Release: 120 | needs: R-CMD-Check 121 | 122 | runs-on: macOS-latest 123 | 124 | env: 125 | GH_TOKEN: ${{ secrets.GH_TOKEN }} 126 | 127 | if: ${{ github.event_name != 'pull_request' && github.ref == 'refs/heads/main' }} 128 | 129 | steps: 130 | 131 | - uses: actions/checkout@v3 132 | with: 133 | fetch-depth: 0 134 | 135 | - name: Check if version has increased 136 | run: | 137 | echo "new_version="$(perl compare_versions --tag) >> $GITHUB_ENV 138 | 139 | - name: Display new version number 140 | if: ${{ env.new_version != '' }} 141 | run: | 142 | echo "${{ env.new_version }}" 143 | 144 | - name: Create release 145 | if: ${{ env.new_version != '' }} 146 | uses: actions/create-release@v1 147 | env: 148 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} 149 | with: 150 | tag_name: ${{ env.new_version }} 151 | release_name: Release ${{ env.new_version }} 152 | body: | 153 | See NEWS.md for release notes. 154 | draft: false 155 | prerelease: false 156 | 157 | - uses: r-lib/actions/setup-r@v2 158 | if: ${{ env.new_version != '' }} 159 | 160 | - name: Install drat 161 | if: ${{ env.new_version != '' }} 162 | run: | 163 | install.packages('drat') 164 | shell: Rscript {0} 165 | 166 | - name: Remove any tarballs that already exists 167 | if: ${{ env.new_version != '' }} 168 | run: | 169 | rm -f *.tar.gz 170 | 171 | - name: Download package tarball 172 | if: ${{ env.new_version != '' }} 173 | uses: actions/download-artifact@v4.1.7 174 | with: 175 | name: package_tarball 176 | 177 | - name: Push to drat 178 | if: ${{ env.new_version != '' }} 179 | run: | 180 | bash deploy.sh 181 | 182 | - name: Push to BroadSea 183 | if: ${{ env.new_version != '' }} 184 | run: | 185 | curl --data "build=true" -X POST https://registry.hub.docker.com/u/ohdsi/broadsea-methodslibrary/trigger/f0b51cec-4027-4781-9383-4b38b42dd4f5/ 186 | 187 | -------------------------------------------------------------------------------- /.github/workflows/R_CMD_check_main_weekly.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | schedule: 3 | - cron: '0 12 * * 0' # every Sunday at noon UTC 4 | 5 | name: 'R check' 6 | 7 | jobs: 8 | R-CMD-check-main: 9 | runs-on: ${{ matrix.config.os }} 10 | 11 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 12 | 13 | strategy: 14 | fail-fast: false 15 | matrix: 16 | config: 17 | - {os: macOS-latest, r: 'release'} 18 | 19 | env: 20 | GITHUB_PAT: ${{ secrets.GH_TOKEN }} 21 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 22 | RSPM: ${{ matrix.config.rspm }} 23 | CDM5_ORACLE_CDM_SCHEMA: ${{ secrets.CDM5_ORACLE_CDM_SCHEMA }} 24 | CDM5_ORACLE_OHDSI_SCHEMA: ${{ secrets.CDM5_ORACLE_OHDSI_SCHEMA }} 25 | CDM5_ORACLE_PASSWORD: ${{ secrets.CDM5_ORACLE_PASSWORD }} 26 | CDM5_ORACLE_SERVER: ${{ secrets.CDM5_ORACLE_SERVER }} 27 | CDM5_ORACLE_USER: ${{ secrets.CDM5_ORACLE_USER }} 28 | CDM5_POSTGRESQL_CDM_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_CDM_SCHEMA }} 29 | CDM5_POSTGRESQL_OHDSI_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_OHDSI_SCHEMA }} 30 | CDM5_POSTGRESQL_PASSWORD: ${{ secrets.CDM5_POSTGRESQL_PASSWORD }} 31 | CDM5_POSTGRESQL_SERVER: ${{ secrets.CDM5_POSTGRESQL_SERVER }} 32 | CDM5_POSTGRESQL_USER: ${{ secrets.CDM5_POSTGRESQL_USER }} 33 | CDM5_SQL_SERVER_CDM_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_CDM_SCHEMA }} 34 | CDM5_SQL_SERVER_OHDSI_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_OHDSI_SCHEMA }} 35 | CDM5_SQL_SERVER_PASSWORD: ${{ secrets.CDM5_SQL_SERVER_PASSWORD }} 36 | CDM5_SQL_SERVER_SERVER: ${{ secrets.CDM5_SQL_SERVER_SERVER }} 37 | CDM5_SQL_SERVER_USER: ${{ secrets.CDM5_SQL_SERVER_USER }} 38 | CDM5_REDSHIFT_CDM_SCHEMA: ${{ secrets.CDM5_REDSHIFT_CDM_SCHEMA }} 39 | CDM5_REDSHIFT_OHDSI_SCHEMA: ${{ secrets.CDM5_REDSHIFT_OHDSI_SCHEMA }} 40 | CDM5_REDSHIFT_PASSWORD: ${{ secrets.CDM5_REDSHIFT_PASSWORD }} 41 | CDM5_REDSHIFT_SERVER: ${{ secrets.CDM5_REDSHIFT_SERVER }} 42 | CDM5_REDSHIFT_USER: ${{ secrets.CDM5_REDSHIFT_USER }} 43 | CDM5_SPARK_USER: ${{ secrets.CDM5_SPARK_USER }} 44 | CDM5_SPARK_PASSWORD: ${{ secrets.CDM5_SPARK_PASSWORD }} 45 | CDM5_SPARK_CONNECTION_STRING: ${{ secrets.CDM5_SPARK_CONNECTION_STRING }} 46 | 47 | steps: 48 | - uses: actions/checkout@v3 49 | 50 | - uses: r-lib/actions/setup-r@v2 51 | with: 52 | r-version: ${{ matrix.config.r }} 53 | 54 | - uses: r-lib/actions/setup-tinytex@v2 55 | 56 | - uses: r-lib/actions/setup-pandoc@v2 57 | 58 | - uses: r-lib/actions/setup-r-dependencies@v2 59 | with: 60 | extra-packages: any::rcmdcheck 61 | needs: check 62 | 63 | - uses: r-lib/actions/check-r-package@v2 64 | with: 65 | args: 'c("--no-manual", "--as-cran")' 66 | error-on: '"warning"' 67 | check-dir: '"check"' 68 | -------------------------------------------------------------------------------- /.github/workflows/reverse_dependency.yml: -------------------------------------------------------------------------------- 1 | on: workflow_dispatch 2 | 3 | name: Reverse-deps-check 4 | 5 | jobs: 6 | Reverse-deps-check: 7 | runs-on: ${{ matrix.config.os }} 8 | 9 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 10 | 11 | strategy: 12 | fail-fast: false 13 | matrix: 14 | config: 15 | - {os: macOS-latest, r: 'release'} 16 | 17 | env: 18 | GITHUB_PAT: ${{ secrets.GH_TOKEN }} 19 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 20 | RSPM: ${{ matrix.config.rspm }} 21 | CDM5_ORACLE_CDM_SCHEMA: ${{ secrets.CDM5_ORACLE_CDM_SCHEMA }} 22 | CDM5_ORACLE_OHDSI_SCHEMA: ${{ secrets.CDM5_ORACLE_OHDSI_SCHEMA }} 23 | CDM5_ORACLE_PASSWORD: ${{ secrets.CDM5_ORACLE_PASSWORD }} 24 | CDM5_ORACLE_SERVER: ${{ secrets.CDM5_ORACLE_SERVER }} 25 | CDM5_ORACLE_USER: ${{ secrets.CDM5_ORACLE_USER }} 26 | CDM5_POSTGRESQL_CDM_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_CDM_SCHEMA }} 27 | CDM5_POSTGRESQL_OHDSI_SCHEMA: ${{ secrets.CDM5_POSTGRESQL_OHDSI_SCHEMA }} 28 | CDM5_POSTGRESQL_PASSWORD: ${{ secrets.CDM5_POSTGRESQL_PASSWORD }} 29 | CDM5_POSTGRESQL_SERVER: ${{ secrets.CDM5_POSTGRESQL_SERVER }} 30 | CDM5_POSTGRESQL_USER: ${{ secrets.CDM5_POSTGRESQL_USER }} 31 | CDM5_SQL_SERVER_CDM_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_CDM_SCHEMA }} 32 | CDM5_SQL_SERVER_OHDSI_SCHEMA: ${{ secrets.CDM5_SQL_SERVER_OHDSI_SCHEMA }} 33 | CDM5_SQL_SERVER_PASSWORD: ${{ secrets.CDM5_SQL_SERVER_PASSWORD }} 34 | CDM5_SQL_SERVER_SERVER: ${{ secrets.CDM5_SQL_SERVER_SERVER }} 35 | CDM5_SQL_SERVER_USER: ${{ secrets.CDM5_SQL_SERVER_USER }} 36 | 37 | steps: 38 | - uses: actions/checkout@v2 39 | 40 | - uses: r-lib/actions/setup-r@v2 41 | with: 42 | r-version: ${{ matrix.config.r }} 43 | 44 | - uses: r-lib/actions/setup-tinytex@v2 45 | 46 | - uses: r-lib/actions/setup-pandoc@v2 47 | 48 | - name: Install system requirements 49 | if: runner.os == 'Linux' 50 | run: | 51 | sudo apt-get install -y make 52 | sudo apt-get install -y default-jdk 53 | sudo apt-get install -y libcurl4-openssl-dev 54 | sudo apt-get install -y libssl-dev 55 | 56 | 57 | - uses: r-lib/actions/setup-r-dependencies@v2 58 | with: 59 | extra-packages: | 60 | any::rcmdcheck 61 | any::remotes 62 | needs: check 63 | 64 | - name: Install main package develop version 65 | run: | 66 | remotes::install_local(build_opts = c("--no-resave-data", "--no-manual", "--no-build-vignettes", "--no-multiarch")) 67 | shell: Rscript {0} 68 | 69 | - name: Get reverse dependencies script 70 | run: | 71 | utils::download.file("https://raw.githubusercontent.com/OHDSI/.github/main/ReverseDependencyCheckFunctions.R", "ReverseDependencyCheckFunctions.R", method = "curl") 72 | shell: Rscript {0} 73 | 74 | - name: Install reverse dependencies 75 | run: | 76 | source("ReverseDependencyCheckFunctions.R") 77 | saveRDS(prepareForReverseDependencyCheck(), ".github/reverseDependencies.rds") 78 | shell: Rscript {0} 79 | 80 | - name: Check reverse dependencies 81 | run: | 82 | source("ReverseDependencyCheckFunctions.R") 83 | reverseDependencies <- readRDS(".github/reverseDependencies.rds") 84 | if (nrow(reverseDependencies) > 0) 85 | for (i in 1:nrow(reverseDependencies)) 86 | checkPackage(package = reverseDependencies$name[i], inCran = reverseDependencies$inCran[i]) 87 | shell: Rscript {0} 88 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | src/*.o 5 | src/*.so 6 | src/*.dll 7 | /Debug 8 | standalone/build/* 9 | /build 10 | /bin 11 | /target 12 | .idea 13 | *.iml 14 | errorReportSql.txt 15 | .DS_Store 16 | revdep/ 17 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SqlRender 4 | 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.jdt.core.javanature 16 | 17 | 18 | -------------------------------------------------------------------------------- /.settings/org.eclipse.cdt.managedbuilder.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/CPATH/delimiter=; 3 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/CPATH/operation=remove 4 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/CPLUS_INCLUDE_PATH/delimiter=; 5 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/CPLUS_INCLUDE_PATH/operation=remove 6 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/C_INCLUDE_PATH/delimiter=; 7 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/C_INCLUDE_PATH/operation=remove 8 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/append=true 9 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/appendContributed=true 10 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/CPATH/delimiter=; 11 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/CPATH/operation=remove 12 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/CPLUS_INCLUDE_PATH/delimiter=; 13 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/CPLUS_INCLUDE_PATH/operation=remove 14 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/C_INCLUDE_PATH/delimiter=; 15 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/C_INCLUDE_PATH/operation=remove 16 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/append=true 17 | environment/buildEnvironmentInclude/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/appendContributed=true 18 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/LIBRARY_PATH/delimiter=; 19 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/LIBRARY_PATH/operation=remove 20 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/append=true 21 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.350870109/appendContributed=true 22 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/LIBRARY_PATH/delimiter=; 23 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/LIBRARY_PATH/operation=remove 24 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/append=true 25 | environment/buildEnvironmentLibrary/cdt.managedbuild.config.gnu.mingw.exe.debug.398158269/appendContributed=true 26 | -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate 4 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 5 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 6 | org.eclipse.jdt.core.compiler.compliance=1.8 7 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 8 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 9 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 10 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 11 | org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled 12 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 13 | org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning 14 | org.eclipse.jdt.core.compiler.release=disabled 15 | org.eclipse.jdt.core.compiler.source=1.8 16 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 1.19.4 2 | Date: 2025-09-26 15:14:09 UTC 3 | SHA: 2b45ac2586957d70c68082581fa913d6f6cd582a 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: SqlRender 2 | Type: Package 3 | Title: Rendering Parameterized SQL and Translation to Dialects 4 | Version: 1.19.4 5 | Date: 2025-09-26 6 | Authors@R: c( 7 | person("Martijn", "Schuemie", , "schuemie@ohdsi.org", role = c("aut", "cre")), 8 | person("Marc", "Suchard", role = c("aut")) 9 | ) 10 | Maintainer: Martijn Schuemie 11 | Description: A rendering tool for parameterized SQL that also translates into 12 | different SQL dialects. These dialects include 'Microsoft SQL Server', 'Oracle', 13 | 'PostgreSql', 'Amazon RedShift', 'Apache Impala', 'IBM Netezza', 'Google BigQuery', 'Microsoft PDW', 'Snowflake', 14 | 'Azure Synapse Analytics Dedicated', 'Apache Spark', 'SQLite', and 'InterSystems IRIS'. 15 | SystemRequirements: Java (>= 8) 16 | License: Apache License 2.0 17 | VignetteBuilder: knitr 18 | URL: https://ohdsi.github.io/SqlRender/, https://github.com/OHDSI/SqlRender 19 | BugReports: https://github.com/OHDSI/SqlRender/issues 20 | Imports: 21 | rJava, 22 | rlang, 23 | checkmate 24 | Suggests: 25 | testthat, 26 | knitr, 27 | rmarkdown, 28 | shiny, 29 | shinydashboard 30 | RoxygenNote: 7.3.3 31 | Encoding: UTF-8 32 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(camelCaseToSnakeCase) 4 | export(camelCaseToSnakeCaseNames) 5 | export(camelCaseToTitleCase) 6 | export(createRWrapperForSql) 7 | export(getTempTablePrefix) 8 | export(launchSqlRenderDeveloper) 9 | export(listSupportedDialects) 10 | export(loadRenderTranslateSql) 11 | export(readSql) 12 | export(render) 13 | export(renderSql) 14 | export(renderSqlFile) 15 | export(snakeCaseToCamelCase) 16 | export(snakeCaseToCamelCaseNames) 17 | export(sparkHandleInsert) 18 | export(splitSql) 19 | export(supportsJava8) 20 | export(translate) 21 | export(translateSingleStatement) 22 | export(translateSql) 23 | export(translateSqlFile) 24 | export(writeSql) 25 | import(rJava) 26 | importFrom(rlang,abort) 27 | importFrom(rlang,inform) 28 | importFrom(rlang,warn) 29 | importFrom(utils,install.packages) 30 | importFrom(utils,menu) 31 | importFrom(utils,read.csv) 32 | -------------------------------------------------------------------------------- /R/ShinyApps.R: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Observational Health Data Sciences and Informatics 2 | # 3 | # This file is part of SqlRender 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #' Launch the SqlRender Developer Shiny app 18 | #' 19 | #' @param launch.browser Should the app be launched in your default browser, or in a Shiny window. 20 | #' Note: copying to clipboard will not work in a Shiny window. 21 | #' 22 | #' @details 23 | #' Launches a Shiny app that allows the user to develop SQL and see how it translates to the supported 24 | #' dialects. 25 | #' 26 | #' @export 27 | launchSqlRenderDeveloper <- function(launch.browser = TRUE) { 28 | errorMessages <- checkmate::makeAssertCollection() 29 | checkmate::assertLogical(launch.browser, len = 1, add = errorMessages) 30 | checkmate::reportAssertions(collection = errorMessages) 31 | 32 | ensure_installed("shinydashboard") 33 | appDir <- system.file("shinyApps", "SqlDeveloper", package = "SqlRender") 34 | shiny::runApp(appDir, display.mode = "normal", launch.browser = launch.browser) 35 | } 36 | 37 | is_installed <- function(pkg, version = 0) { 38 | installed_version <- tryCatch(utils::packageVersion(pkg), error = function(e) NA) 39 | !is.na(installed_version) && installed_version >= version 40 | } 41 | 42 | ensure_installed <- function(pkg) { 43 | if (!is_installed(pkg)) { 44 | msg <- paste0(sQuote(pkg), " must be installed for this functionality.") 45 | if (interactive()) { 46 | inform(paste(msg, "Would you like to install it?", sep = "\n")) 47 | if (menu(c("Yes", "No")) == 1) { 48 | install.packages(pkg) 49 | } else { 50 | stop(msg, call. = FALSE) 51 | } 52 | } else { 53 | stop(msg, call. = FALSE) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /R/SparkSql.R: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Observational Health Data Sciences and Informatics 2 | # 3 | # This file is part of SqlRender 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #' @title 18 | #' Handles Spark Inserts 19 | #' 20 | #' @description 21 | #' This function is for Spark connections only, 22 | #' it handles insert commands, as Spark cannot handle inserts with aliased or subset columns. 23 | #' 24 | #' @param sql The SQL to be translated. 25 | #' @param connection The connection to the database server. 26 | #' 27 | #' @return 28 | #' A sql string with INSERT command modified to contain the full column list, padded with NULLS as needed. 29 | #' 30 | #' @export 31 | sparkHandleInsert <- function(sql, connection) { 32 | errorMessages <- checkmate::makeAssertCollection() 33 | checkmate::assertCharacter(sql, len = 1, add = errorMessages) 34 | checkmate::reportAssertions(collection = errorMessages) 35 | 36 | sql <- rJava::J("org.ohdsi.sql.BigQuerySparkTranslate")$sparkHandleInsert(as.character(sql), connection@jConnection) 37 | return(sql) 38 | } 39 | -------------------------------------------------------------------------------- /R/SqlRender.R: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Observational Health Data Sciences and Informatics 2 | # 3 | # This file is part of SqlRender 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | #' @keywords internal 18 | "_PACKAGE" 19 | 20 | #' @importFrom utils install.packages menu read.csv 21 | #' @importFrom rlang abort warn inform 22 | NULL 23 | 24 | .onLoad <- function(libname, pkgname) { 25 | rJava::.jpackage(pkgname, lib.loc = libname) 26 | 27 | # Verify checksum of JAR: 28 | storedChecksum <- scan( 29 | file = system.file("csv", "jarChecksum.txt", package = "SqlRender"), 30 | what = character(), quiet = TRUE 31 | ) 32 | computedChecksum <- tryCatch(rJava::J("org.ohdsi.sql.JarChecksum", "computeJarChecksum"), 33 | error = function(e) { 34 | warning("Problem connecting to Java. This is normal when runing roxygen.") 35 | return("") 36 | } 37 | ) 38 | if (computedChecksum != "" && (storedChecksum != computedChecksum)) { 39 | warning("Java library version does not match R package version! Please try reinstalling the SqlRender package. 40 | Make sure to close all instances of R, and open only one instance before reinstalling. Also make sure your 41 | R workspace is not reloaded on startup. Delete your .Rdata file if necessary") 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SqlRender 2 | ========= 3 | 4 | [![Build Status](https://github.com/OHDSI/SqlRender/workflows/R-CMD-check/badge.svg)](https://github.com/OHDSI/SqlRender/actions?query=workflow%3AR-CMD-check) 5 | [![codecov.io](https://codecov.io/github/OHDSI/SqlRender/coverage.svg?branch=main)](https://app.codecov.io/github/OHDSI/SqlRender) 6 | [![CRAN_Status_Badge](https://www.r-pkg.org/badges/version/SqlRender)](https://cran.r-project.org/package=SqlRender) 7 | [![CRAN_Status_Badge](https://cranlogs.r-pkg.org/badges/SqlRender)](https://cran.r-project.org/package=SqlRender) 8 | 9 | SqlRender is part of [HADES](https://ohdsi.github.io/Hades/). 10 | 11 | Introduction 12 | ============ 13 | This is an R package for rendering parameterized SQL, and translating it to different SQL dialects. SqlRender can also be used as a stand-alone Java library and a command-line executable. 14 | 15 | Features 16 | ======== 17 | - Supports a simple markup syntax for making SQL parameterized, and renders parameterized SQL (containing the markup syntax) to executable SQL 18 | - The syntax supports defining default parameter values 19 | - The syntax supports if-then-else structures 20 | - Has functions for translating SQL from one dialect (Microsoft SQL Server) to other dialects (Oracle, PostgreSQL, Amazon RedShift, Impala, IBM Netezza, Google BigQuery, Microsoft PDW, Snowflake, Azure Synapse, Apache Spark, SQLite, and InterSystems IRIS) 21 | - Can be used as R package, Java library, or as stand-alone executable through a command-line interface 22 | 23 | Examples 24 | ======== 25 | This example shows the use of parameters, as well as SqlRender's {if} ? {then} : {else} syntax: 26 | 27 | ```r 28 | sql <- render("SELECT * FROM @a; {@b != ''}?{USE @b;}", a = "my_table", b = "my_schema") 29 | ``` 30 | 31 | will produce the variable `sql` containing this value: 32 | 33 | ``` 34 | "SELECT * FROM my_table; USE my_schema;" 35 | ``` 36 | 37 | subsequently running this code 38 | 39 | ```r 40 | sql <- translate(sql, "oracle") 41 | ``` 42 | 43 | will produce the variable `sql` containing this value: 44 | 45 | ``` 46 | "SELECT * FROM my_table; ALTER SESSION SET current_schema = my_schema;" 47 | ``` 48 | 49 | ## SqlDeveloper 50 | 51 | The SqlDeveloper Shiny app is included in the SqlRender R package, and allows viewing the rendering and translation on the fly as you develop your SQL. The SqlDeveloper app is also available online [here](https://data.ohdsi.org/SqlDeveloper/). 52 | 53 | Technology 54 | ========== 55 | The SqlRender package is an R package wrapped around a Java library. The rJava package is used as interface. 56 | 57 | The Java library is available as a JAR file. 58 | 59 | System Requirements 60 | =================== 61 | Running the package requires R with the package rJava installed. Also requires Java 1.6 or higher. 62 | It is highly recommended for best performance to use a version of R that is at least version 4 or higher otherwise, unexpected bugs or errors may occur. 63 | 64 | Installation 65 | ============= 66 | ## R package 67 | 68 | In R, to install the latest stable version, install from CRAN: 69 | 70 | ```r 71 | install.packages("SqlRender") 72 | ``` 73 | 74 | To install the latest development version, install from GitHub: 75 | 76 | ```r 77 | install.packages("remotes") 78 | remotes::install_github("ohdsi/SqlRender", ref = "develop") 79 | ``` 80 | 81 | Once installed, you can try out SqlRender in a Shiny app that comes with the package: 82 | 83 | ```r 84 | library(SqlRender) 85 | launchSqlRenderDeveloper() 86 | ``` 87 | 88 | ## Java library 89 | You can fetch the JAR file in the inst/java folder of this repository, or use Maven: 90 | 91 | 1. First add the SqlRender repository so that maven can find and download the SqlRender artifact automatically: 92 | ```xml 93 | 94 | ohdsi 95 | repo.ohdsi.org 96 | https://repo.ohdsi.org/nexus/content/repositories/releases 97 | 98 | 99 | ohdsi.snapshots 100 | repo.ohdsi.org-snapshots 101 | https://repo.ohdsi.org/nexus/content/repositories/snapshots 102 | 103 | false 104 | 105 | 106 | true 107 | 108 | 109 | ``` 110 | 2: Include the SqlRender dependency in your pom.xml 111 | ```xml 112 | 113 | org.ohdsi.sql 114 | SqlRender 115 | 1.9.2-SNAPSHOT 116 | 117 | ``` 118 | 119 | ## Command-line executable 120 | You can fetch the JAR file in the inst/java folder of this repository, or use Maven as described above. Run this from the command line to get a list of options: 121 | ``` 122 | java -jar SqlRender.jar ? 123 | ``` 124 | 125 | User Documentation 126 | ================== 127 | Documentation can be found on the [package website](https://ohdsi.github.io/SqlRender/). 128 | 129 | PDF versions of the documentation are also available: 130 | * Vignette: [Using SqlRender](https://github.com/OHDSI/SqlRender/raw/main/inst/doc/UsingSqlRender.pdf) 131 | * Package manual: [SqlRender manual](https://github.com/OHDSI/SqlRender/raw/main/extras/SqlRender.pdf) 132 | 133 | Support 134 | ======= 135 | * Developer questions/comments/feedback: OHDSI Forum 136 | * We use the GitHub issue tracker for all bugs/issues/enhancements 137 | 138 | Contributing 139 | ============ 140 | Read [here](https://ohdsi.github.io/Hades/contribute.html) how you can contribute to this package. 141 | 142 | License 143 | ======= 144 | SqlRender is licensed under Apache License 2.0 145 | 146 | Development 147 | =========== 148 | SqlRender is being developed in R Studio. 149 | 150 | ### Development status 151 | 152 | Stable. The code is actively being used in several projects. 153 | 154 | Acknowledgements 155 | ================ 156 | - This project is supported in part through the National Science Foundation grant IIS 1251151. 157 | 158 | -------------------------------------------------------------------------------- /SqlRender.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | ProjectId: d9ea87f8-f71c-443d-a3ec-5bd0e2204c1d 3 | 4 | RestoreWorkspace: No 5 | SaveWorkspace: No 6 | AlwaysSaveHistory: No 7 | 8 | EnableCodeIndexing: Yes 9 | UseSpacesForTab: Yes 10 | NumSpacesForTab: 2 11 | Encoding: UTF-8 12 | 13 | RnwWeave: knitr 14 | LaTeX: pdfLaTeX 15 | 16 | BuildType: Package 17 | PackageInstallArgs: --with-keep.source 18 | PackageCheckArgs: --as-cran 19 | PackageRoxygenize: rd,collate,namespace 20 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | template: 2 | params: 3 | bootswatch: cosmo 4 | 5 | home: 6 | links: 7 | - text: Ask a question 8 | href: http://forums.ohdsi.org 9 | 10 | navbar: 11 | structure: 12 | left: 13 | - home 14 | - reference 15 | - articles 16 | - SqlDeveloper 17 | - news 18 | right: [hades, github] 19 | components: 20 | SqlDeveloper: 21 | text: SqlDeveloper 22 | href: https://results.ohdsi.org/app/01_SqlDeveloper 23 | hades: 24 | text: hadesLogo 25 | href: https://ohdsi.github.io/Hades 26 | -------------------------------------------------------------------------------- /compare_versions: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | open(R_VERSION, "grep 'Version' DESCRIPTION |"); 4 | $version = ; 5 | close(R_VERSION); 6 | 7 | $version =~ /(\d+)\.(\d+)\.(\d+)/; 8 | $r_major = $1; 9 | $r_minor = $2; 10 | $r_mod = $3; 11 | 12 | open(GIT_VERSION, "git describe --tags |"); 13 | $git = ; 14 | close(GIT_VERSION); 15 | 16 | $git =~ /v(\d+)\.(\d+)\.(\d+)/; 17 | $git_major = $1; 18 | $git_minor = $2; 19 | $git_mod = $3; 20 | 21 | if ($r_major > $git_major || $r_minor > $git_minor || $r_mod > $git_mod) { 22 | $new_version = "v$r_major.$r_minor.$r_mod"; 23 | } else { 24 | $new_version = ""; 25 | } 26 | 27 | print($new_version); 28 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | There is 1 bugfix (see NEWS.md). 2 | 3 | --- 4 | 5 | ## Test environments 6 | * Ubuntu 20.04, R 4.5.1 7 | * Microsoft Windows Server 2022, R 4.5.1 8 | * MacOS, R 4.5.1 9 | * MacOS, R 4.4.1 10 | 11 | ## R CMD check results 12 | 13 | There were no ERRORs or WARNINGs. 14 | 15 | ## Downstream dependencies 16 | 17 | - Achilles, allofus, CohortAlgebra, CommonDataModel, FeatureExtraction, CohortAlgebra, DatabaseConnector, DrugExposureDiagnostics, TreatmentPatterns, CDMConnector, and DrugExposureDiagnostics depend on SqlRender, and have been tested with this new version. No problems were found. 18 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -o errexit -o nounset 3 | addToDrat(){ 4 | PKG_REPO=$PWD 5 | 6 | ## Build package tar ball 7 | export PKG_TARBALL=$(ls *.tar.gz) 8 | 9 | cd ..; mkdir drat; cd drat 10 | 11 | ## Set up Repo parameters 12 | git init 13 | git config user.name "Martijn Schuemie" 14 | git config user.email "schuemie@ohdsi.org" 15 | git config --global push.default simple 16 | 17 | ## Get drat repo 18 | git remote add upstream "https://$GH_TOKEN@github.com/OHDSI/drat.git" 19 | git fetch upstream 2>err.txt 20 | git checkout gh-pages 21 | 22 | ## Link to local R packages 23 | echo 'R_LIBS=~/Rlib' > .Renviron 24 | 25 | Rscript -e "drat::insertPackage('$PKG_REPO/$PKG_TARBALL', \ 26 | repodir = '.', \ 27 | commit='GitHub Actions release: $PKG_TARBALL run $GITHUB_RUN_ID')" 28 | git push 29 | 30 | } 31 | addToDrat 32 | -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • SqlRender 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 |
24 |
79 | 80 | 81 | 82 | 83 |
84 |
85 | 88 | 89 | Content not found. Please use links in the navbar. 90 | 91 |
92 | 93 | 97 | 98 |
99 | 100 | 101 | 102 |
106 | 107 |
108 |

109 |

Site built with pkgdown 2.1.3.

110 |
111 | 112 |
113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/accessible-code-block-0.0.1/empty-anchor.js: -------------------------------------------------------------------------------- 1 | // Hide empty tag within highlighted CodeBlock for screen reader accessibility (see https://github.com/jgm/pandoc/issues/6352#issuecomment-626106786) --> 2 | // v0.0.1 3 | // Written by JooYoung Seo (jooyoung@psu.edu) and Atsushi Yasumoto on June 1st, 2020. 4 | 5 | document.addEventListener('DOMContentLoaded', function() { 6 | const codeList = document.getElementsByClassName("sourceCode"); 7 | for (var i = 0; i < codeList.length; i++) { 8 | var linkList = codeList[i].getElementsByTagName('a'); 9 | for (var j = 0; j < linkList.length; j++) { 10 | if (linkList[j].innerHTML === "") { 11 | linkList[j].setAttribute('aria-hidden', 'true'); 12 | } 13 | } 14 | } 15 | }); 16 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/anchor-sections-1.0/anchor-sections.css: -------------------------------------------------------------------------------- 1 | /* Styles for section anchors */ 2 | a.anchor-section {margin-left: 10px; visibility: hidden; color: inherit;} 3 | a.anchor-section::before {content: '#';} 4 | .hasAnchor:hover a.anchor-section {visibility: visible;} 5 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/anchor-sections-1.0/anchor-sections.js: -------------------------------------------------------------------------------- 1 | // Anchor sections v1.0 written by Atsushi Yasumoto on Oct 3rd, 2020. 2 | document.addEventListener('DOMContentLoaded', function() { 3 | // Do nothing if AnchorJS is used 4 | if (typeof window.anchors === 'object' && anchors.hasOwnProperty('hasAnchorJSLink')) { 5 | return; 6 | } 7 | 8 | const h = document.querySelectorAll('h1, h2, h3, h4, h5, h6'); 9 | 10 | // Do nothing if sections are already anchored 11 | if (Array.from(h).some(x => x.classList.contains('hasAnchor'))) { 12 | return null; 13 | } 14 | 15 | // Use section id when pandoc runs with --section-divs 16 | const section_id = function(x) { 17 | return ((x.classList.contains('section') || (x.tagName === 'SECTION')) 18 | ? x.id : ''); 19 | }; 20 | 21 | // Add anchors 22 | h.forEach(function(x) { 23 | const id = x.id || section_id(x.parentElement); 24 | if (id === '') { 25 | return null; 26 | } 27 | let anchor = document.createElement('a'); 28 | anchor.href = '#' + id; 29 | anchor.classList = ['anchor-section']; 30 | x.classList.add('hasAnchor'); 31 | x.appendChild(anchor); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/header-attrs-2.10/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/header-attrs-2.11/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/header-attrs-2.4/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/UsingSqlRender_files/header-attrs-2.5/header-attrs.js: -------------------------------------------------------------------------------- 1 | // Pandoc 2.9 adds attributes on both header and div. We remove the former (to 2 | // be compatible with the behavior of Pandoc < 2.8). 3 | document.addEventListener('DOMContentLoaded', function(e) { 4 | var hs = document.querySelectorAll("div.section[class*='level'] > :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | Articles • SqlRender 6 | 7 | 8 |
9 |
56 | 57 | 58 | 59 |
60 |
61 | 64 | 65 |
66 |

All vignettes

67 |

68 | 69 |
Using SqlRender
70 |
71 |
72 |
73 |
74 | 75 | 76 |
79 | 80 |
81 |

Site built with pkgdown 2.1.3.

82 |
83 | 84 |
85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | Authors and Citation • SqlRender 6 | 7 | 8 |
9 |
56 | 57 | 58 | 59 |
60 |
61 |
62 | 65 | 66 | 67 |
  • 68 |

    Martijn Schuemie. Author, maintainer. 69 |

    70 |
  • 71 |
  • 72 |

    Marc Suchard. Author. 73 |

    74 |
  • 75 |
76 |
77 |
78 |

Citation

79 | Source: DESCRIPTION 80 |
81 |
82 | 83 | 84 |

Schuemie M, Suchard M (2025). 85 | SqlRender: Rendering Parameterized SQL and Translation to Dialects. 86 | R package version 1.19.4, https://github.com/OHDSI/SqlRender, https://ohdsi.github.io/SqlRender/. 87 |

88 |
@Manual{,
 89 |   title = {SqlRender: Rendering Parameterized SQL and Translation to Dialects},
 90 |   author = {Martijn Schuemie and Marc Suchard},
 91 |   year = {2025},
 92 |   note = {R package version 1.19.4, https://github.com/OHDSI/SqlRender},
 93 |   url = {https://ohdsi.github.io/SqlRender/},
 94 | }
95 | 96 |
97 | 98 |
99 | 100 | 101 | 102 |
105 | 106 |
107 |

Site built with pkgdown 2.1.3.

108 |
109 | 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/jquery.sticky-kit.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | Sticky-kit v1.1.2 | WTFPL | Leaf Corcoran 2015 | http://leafo.net 3 | */ 4 | (function(){var b,f;b=this.jQuery||window.jQuery;f=b(window);b.fn.stick_in_parent=function(d){var A,w,J,n,B,K,p,q,k,E,t;null==d&&(d={});t=d.sticky_class;B=d.inner_scrolling;E=d.recalc_every;k=d.parent;q=d.offset_top;p=d.spacer;w=d.bottoming;null==q&&(q=0);null==k&&(k=void 0);null==B&&(B=!0);null==t&&(t="is_stuck");A=b(document);null==w&&(w=!0);J=function(a,d,n,C,F,u,r,G){var v,H,m,D,I,c,g,x,y,z,h,l;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);I=A.height();g=a.parent();null!=k&&(g=g.closest(k)); 5 | if(!g.length)throw"failed to find stick parent";v=m=!1;(h=null!=p?p&&a.closest(p):b("
    "))&&h.css("position",a.css("position"));x=function(){var c,f,e;if(!G&&(I=A.height(),c=parseInt(g.css("border-top-width"),10),f=parseInt(g.css("padding-top"),10),d=parseInt(g.css("padding-bottom"),10),n=g.offset().top+c+f,C=g.height(),m&&(v=m=!1,null==p&&(a.insertAfter(h),h.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(t),e=!0),F=a.offset().top-(parseInt(a.css("margin-top"),10)||0)-q, 6 | u=a.outerHeight(!0),r=a.css("float"),h&&h.css({width:a.outerWidth(!0),height:u,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),e))return l()};x();if(u!==C)return D=void 0,c=q,z=E,l=function(){var b,l,e,k;if(!G&&(e=!1,null!=z&&(--z,0>=z&&(z=E,x(),e=!0)),e||A.height()===I||x(),e=f.scrollTop(),null!=D&&(l=e-D),D=e,m?(w&&(k=e+u+c>C+n,v&&!k&&(v=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),eb&&!v&&(c-=l,c=Math.max(b-u,c),c=Math.min(q,c),m&&a.css({top:c+"px"})))):e>F&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(t),null==p&&(a.after(h),"left"!==r&&"right"!==r||h.append(a)),a.trigger("sticky_kit:stick")),m&&w&&(null==k&&(k=e+u+c>C+n),!v&&k)))return v=!0,"static"===g.css("position")&&g.css({position:"relative"}), 8 | a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")},y=function(){x();return l()},H=function(){G=!0;f.off("touchmove",l);f.off("scroll",l);f.off("resize",y);b(document.body).off("sticky_kit:recalc",y);a.off("sticky_kit:detach",H);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});g.position("position","");if(m)return null==p&&("left"!==r&&"right"!==r||a.insertAfter(h),h.remove()),a.removeClass(t)},f.on("touchmove",l),f.on("scroll",l),f.on("resize", 9 | y),b(document.body).on("sticky_kit:recalc",y),a.on("sticky_kit:detach",H),setTimeout(l,0)}};n=0;for(K=this.length;n 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $("div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: '3.2' 2 | pkgdown: 2.1.3 3 | pkgdown_sha: ~ 4 | articles: 5 | UsingSqlRender: UsingSqlRender.html 6 | last_built: 2025-09-26T13:47Z 7 | -------------------------------------------------------------------------------- /docs/pull_request_template.html: -------------------------------------------------------------------------------- 1 | 2 | NA • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 64 | 65 | 66 |

    Before you do a pull request, you should always file an issue and make sure the package maintainer agrees that it’s a problem, and is happy with your basic proposal for fixing it. We don’t want you to spend a bunch of time on something that we don’t think is a good idea.

    67 |

    Additional requirements for pull requests:

    68 |
    • Adhere to the Developer Guidelines as well as the OHDSI Code Style.

    • 69 |
    • If possible, add unit tests for new functionality you add.

    • 70 |
    • Restrict your pull request to solving the issue at hand. Do not try to ‘improve’ parts of the code that are not related to the issue. If you feel other parts of the code need better organization, create a separate issue for that.

    • 71 |
    • Make sure you pass R check without errors and warnings before submitting.

    • 72 |
    • Always target the develop branch, and make sure you are up-to-date with the develop branch.

    • 73 |
    74 | 75 | 78 | 79 |
    80 | 81 | 82 | 83 |
    86 | 87 |
    88 |

    Site built with pkgdown 2.0.7.

    89 |
    90 | 91 |
    92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHDSI/SqlRender/97eb3b441bb98fa51676c54eca20b296fdcfbf21/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/SqlRender.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | SqlRender — SqlRender • SqlRender 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 54 | 55 | 56 | 57 | 58 | 59 |
    60 |
    61 | 115 | 116 | 117 | 118 |
    119 | 120 |
    121 |
    122 | 127 | 128 |
    129 |

    SqlRender

    130 |
    131 | 132 | 133 | 134 | 135 |
    136 | 142 |
    143 | 144 | 145 |
    146 | 149 | 150 |
    151 |

    Site built with pkgdown 1.4.1.

    152 |
    153 | 154 |
    155 |
    156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /docs/reference/camelCaseToSnakeCase.html: -------------------------------------------------------------------------------- 1 | 2 | Convert a camel case string to snake case — camelCaseToSnakeCase • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 66 | 67 |
    68 |

    Convert a camel case string to snake case

    69 |
    70 | 71 |
    72 |
    camelCaseToSnakeCase(string)
    73 |
    74 | 75 |
    76 |

    Arguments

    77 | 78 | 79 |
    string
    80 |

    The string to be converted

    81 | 82 |
    83 |
    84 |

    Value

    85 |

    A string

    86 |
    87 | 88 |
    89 |

    Examples

    90 |
    camelCaseToSnakeCase("exposureConceptId1")
     91 | #> [1] "exposure_concept_id_1"
     92 | 
     93 | 
    94 |
    95 |
    96 | 99 |
    100 | 101 | 102 |
    105 | 106 |
    107 |

    Site built with pkgdown 2.1.3.

    108 |
    109 | 110 |
    111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/reference/camelCaseToTitleCase.html: -------------------------------------------------------------------------------- 1 | 2 | Convert a camel case string to title case — camelCaseToTitleCase • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 66 | 67 |
    68 |

    Convert a camel case string to title case

    69 |
    70 | 71 |
    72 |
    camelCaseToTitleCase(string)
    73 |
    74 | 75 |
    76 |

    Arguments

    77 | 78 | 79 |
    string
    80 |

    The string to be converted

    81 | 82 |
    83 |
    84 |

    Value

    85 |

    A string

    86 |
    87 | 88 |
    89 |

    Examples

    90 |
    camelCaseToTitleCase("exposureConceptId1")
     91 | #> [1] "Exposure Concept Id 1"
     92 | 
     93 | 
    94 |
    95 |
    96 | 99 |
    100 | 101 | 102 |
    105 | 106 |
    107 |

    Site built with pkgdown 2.1.3.

    108 |
    109 | 110 |
    111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/reference/getTempTablePrefix.html: -------------------------------------------------------------------------------- 1 | 2 | Get the prefix used for emulated temp tables for DBMSs that do not support temp tables (e.g. Oracle, BigQuery). — getTempTablePrefix • SqlRender 7 | 8 | 9 |
    10 |
    57 | 58 | 59 | 60 |
    61 |
    62 | 67 | 68 |
    69 |

    Get the prefix used for emulated temp tables for DBMSs that do not support temp tables (e.g. Oracle, 70 | BigQuery).

    71 |
    72 | 73 |
    74 |
    getTempTablePrefix()
    75 |
    76 | 77 |
    78 |

    Value

    79 |

    The prefix string.

    80 |
    81 | 82 |
    83 |

    Examples

    84 |
    getTempTablePrefix()
     85 | #> [1] "l3470uc6"
     86 | 
    87 |
    88 |
    89 | 92 |
    93 | 94 | 95 |
    98 | 99 |
    100 |

    Site built with pkgdown 2.1.3.

    101 |
    102 | 103 |
    104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /docs/reference/launchSqlRenderDeveloper.html: -------------------------------------------------------------------------------- 1 | 2 | Launch the SqlRender Developer Shiny app — launchSqlRenderDeveloper • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 66 | 67 |
    68 |

    Launch the SqlRender Developer Shiny app

    69 |
    70 | 71 |
    72 |
    launchSqlRenderDeveloper(launch.browser = TRUE)
    73 |
    74 | 75 |
    76 |

    Arguments

    77 | 78 | 79 |
    launch.browser
    80 |

    Should the app be launched in your default browser, or in a Shiny window. 81 | Note: copying to clipboard will not work in a Shiny window.

    82 | 83 |
    84 |
    85 |

    Details

    86 |

    Launches a Shiny app that allows the user to develop SQL and see how it translates to the supported 87 | dialects.

    88 |
    89 | 90 |
    91 | 94 |
    95 | 96 | 97 |
    100 | 101 |
    102 |

    Site built with pkgdown 2.1.3.

    103 |
    104 | 105 |
    106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /docs/reference/snakeCaseToCamelCase.html: -------------------------------------------------------------------------------- 1 | 2 | Convert a snake case string to camel case — snakeCaseToCamelCase • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 66 | 67 |
    68 |

    Convert a snake case string to camel case

    69 |
    70 | 71 |
    72 |
    snakeCaseToCamelCase(string)
    73 |
    74 | 75 |
    76 |

    Arguments

    77 | 78 | 79 |
    string
    80 |

    The string to be converted

    81 | 82 |
    83 |
    84 |

    Value

    85 |

    A string

    86 |
    87 | 88 |
    89 |

    Examples

    90 |
    snakeCaseToCamelCase("exposure_concept_id_1")
     91 | #> [1] "exposureConceptId1"
     92 | 
     93 | 
    94 |
    95 |
    96 | 99 |
    100 | 101 | 102 |
    105 | 106 |
    107 |

    Site built with pkgdown 2.1.3.

    108 |
    109 | 110 |
    111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/reference/sparkHandleInsert.html: -------------------------------------------------------------------------------- 1 | 2 | Handles Spark Inserts — sparkHandleInsert • SqlRender 7 | 8 | 9 |
    10 |
    57 | 58 | 59 | 60 |
    61 |
    62 | 67 | 68 |
    69 |

    This function is for Spark connections only, 70 | it handles insert commands, as Spark cannot handle inserts with aliased or subset columns.

    71 |
    72 | 73 |
    74 |
    sparkHandleInsert(sql, connection)
    75 |
    76 | 77 |
    78 |

    Arguments

    79 | 80 | 81 |
    sql
    82 |

    The SQL to be translated.

    83 | 84 | 85 |
    connection
    86 |

    The connection to the database server.

    87 | 88 |
    89 |
    90 |

    Value

    91 |

    A sql string with INSERT command modified to contain the full column list, padded with NULLS as needed.

    92 |
    93 | 94 |
    95 | 98 |
    99 | 100 | 101 |
    104 | 105 |
    106 |

    Site built with pkgdown 2.1.3.

    107 |
    108 | 109 |
    110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /docs/reference/supportsJava8.html: -------------------------------------------------------------------------------- 1 | 2 | Determine if Java virtual machine supports Java — supportsJava8 • SqlRender 6 | 7 | 8 |
    9 |
    56 | 57 | 58 | 59 |
    60 |
    61 | 66 | 67 |
    68 |

    Tests Java virtual machine (JVM) java.version system property to check if version >= 8.

    69 |
    70 | 71 |
    72 |
    supportsJava8()
    73 |
    74 | 75 |
    76 |

    Value

    77 |

    Returns TRUE if JVM supports Java >= 8.

    78 |
    79 | 80 |
    81 |

    Examples

    82 |
    supportsJava8()
     83 | #> [1] TRUE
     84 | 
    85 |
    86 |
    87 | 90 |
    91 | 92 | 93 |
    96 | 97 |
    98 |

    Site built with pkgdown 2.1.3.

    99 |
    100 | 101 |
    102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | /404.html 3 | /articles/UsingSqlRender.html 4 | /articles/index.html 5 | /authors.html 6 | /index.html 7 | /news/index.html 8 | /pull_request_template.html 9 | /reference/SqlRender-package.html 10 | /reference/camelCaseToSnakeCase.html 11 | /reference/camelCaseToSnakeCaseNames.html 12 | /reference/camelCaseToTitleCase.html 13 | /reference/createRWrapperForSql.html 14 | /reference/getTempTablePrefix.html 15 | /reference/index.html 16 | /reference/launchSqlRenderDeveloper.html 17 | /reference/listSupportedDialects.html 18 | /reference/loadRenderTranslateSql.html 19 | /reference/readSql.html 20 | /reference/render.html 21 | /reference/renderSql.html 22 | /reference/renderSqlFile.html 23 | /reference/snakeCaseToCamelCase.html 24 | /reference/snakeCaseToCamelCaseNames.html 25 | /reference/sparkHandleInsert.html 26 | /reference/splitSql.html 27 | /reference/supportsJava8.html 28 | /reference/translate.html 29 | /reference/translateSingleStatement.html 30 | /reference/translateSql.html 31 | /reference/translateSqlFile.html 32 | /reference/writeSql.html 33 | 34 | 35 | -------------------------------------------------------------------------------- /extras/PackageMaintenance.R: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Observational Health Data Sciences and Informatics 2 | # 3 | # This file is part of SqlRender 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Format and check code -------------------------------------------------------- 18 | styler::style_pkg() 19 | OhdsiRTools::checkUsagePackage("SqlRender") 20 | OhdsiRTools::updateCopyrightYearFolder() 21 | devtools::spell_check() 22 | 23 | # Create manual and vignettes -------------------------------------------------- 24 | unlink("extras/SqlRender.pdf") 25 | system("R CMD Rd2pdf ./ --output=extras/SqlRender.pdf") 26 | 27 | dir.create("inst/doc") 28 | rmarkdown::render("vignettes/UsingSqlRender.Rmd", 29 | output_file = "../inst/doc/UsingSqlRender.pdf", 30 | rmarkdown::pdf_document(latex_engine = "pdflatex", 31 | toc = TRUE, 32 | number_sections = TRUE)) 33 | 34 | pkgdown::build_site() 35 | OhdsiRTools::fixHadesLogo() 36 | 37 | # Store JAR checksum ----------------------------------------------------------- 38 | checksum <- rJava::J("org.ohdsi.sql.JarChecksum", "computeJarChecksum") 39 | write(checksum, file.path("inst", "csv", "jarChecksum.txt")) 40 | 41 | # Release package -------------------------------------------------------------- 42 | # Check if DESCRIPTION version matches POM version: 43 | descriptionVersion <- stringr::str_extract(readLines("DESCRIPTION")[grepl("^Version:", readLines("DESCRIPTION"))], "(?<=Version: ).*$") 44 | pomVersion <- stringr::str_extract(readLines("pom.xml")[grepl("SNAPSHOT", readLines("pom.xml"))], "(?<=).*(?=-SNAPSHOT)") 45 | if (descriptionVersion != pomVersion) stop("DESCRIPTION version does not match POM version") 46 | 47 | revdepcheck::revdep_check(num_workers = 4) 48 | 49 | devtools::check_win_devel() 50 | 51 | rhub::rc_submit(platforms = "atlas") 52 | 53 | devtools::release() 54 | -------------------------------------------------------------------------------- /extras/SqlRender.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHDSI/SqlRender/97eb3b441bb98fa51676c54eca20b296fdcfbf21/extras/SqlRender.pdf -------------------------------------------------------------------------------- /inst/csv/jarChecksum.txt: -------------------------------------------------------------------------------- 1 | dc152542636e6f48d689a17b71cce31ce2d77160b76ce599b76f1e06a7e4d211 2 | -------------------------------------------------------------------------------- /inst/csv/supportedDialects.csv: -------------------------------------------------------------------------------- 1 | dialect,description 2 | sql server,Microsoft SQL Server 3 | oracle,Oracle 4 | postgresql,PostgreSQL 5 | pdw,Microsoft Parallel Data Warehouse 6 | impala,Apache Impala 7 | netezza,IBM Netezza 8 | bigquery,Google BigQuery 9 | spark,Apache Spark 10 | sqlite,SQLite 11 | redshift,Amazon RedShift 12 | hive,Apache Hive 13 | sqlite extended,SQLite Extended Syntax 14 | duckdb,DuckDB 15 | snowflake,Snowflake 16 | synapse,Azure Synapse Analytics Dedicated 17 | iris,InterSystems IRIS 18 | -------------------------------------------------------------------------------- /inst/doc/UsingSqlRender.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHDSI/SqlRender/97eb3b441bb98fa51676c54eca20b296fdcfbf21/inst/doc/UsingSqlRender.pdf -------------------------------------------------------------------------------- /inst/java/SqlRender.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/OHDSI/SqlRender/97eb3b441bb98fa51676c54eca20b296fdcfbf21/inst/java/SqlRender.jar -------------------------------------------------------------------------------- /inst/shinyApps/SqlDeveloper/SqlDeveloper.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | -------------------------------------------------------------------------------- /inst/shinyApps/SqlDeveloper/server.R: -------------------------------------------------------------------------------- 1 | library(shiny) 2 | library(SqlRender) 3 | 4 | shinyServer(function(input, output, session) { 5 | 6 | # cache <- reactiveValues(target = '', clicks = 0, parameters = NULL) 7 | 8 | parameters <- reactive({ 9 | params <- regmatches(input$source, gregexpr("@[a-zA-Z0-9_]+", input$source))[[1]] 10 | params <- unique(params) 11 | params <- params[order(params)] 12 | params <- substr(params, 2, nchar(params)) 13 | return(params) 14 | }) 15 | 16 | output$target <- renderText({ 17 | parameterValues <- list() 18 | for (param in parameters()) { 19 | value <- input[[param]] 20 | if (!is.null(value)) { 21 | parameterValues[[param]] <- value 22 | } 23 | } 24 | sql <- do.call("render", append(input$source, parameterValues)) 25 | warningString <- c() 26 | handleWarning <- function(e) { 27 | output$warnings <- e$message 28 | } 29 | tempEmulationSchema <- input$tempEmulationSchema 30 | if (tempEmulationSchema == "") 31 | tempEmulationSchema <- NULL 32 | sql <- withCallingHandlers(suppressWarnings(translate(sql, 33 | targetDialect = tolower(input$dialect), 34 | tempEmulationSchema = tempEmulationSchema)), warning = handleWarning) 35 | if (!is.null(warningString)) 36 | output$warnings <- warningString 37 | return(sql) 38 | }) 39 | 40 | output$parameterInputs <- renderUI({ 41 | params <- parameters() 42 | sourceSql <- input$source 43 | 44 | createRow <- function(param, sourceSql) { 45 | # Get current values if already exists: 46 | value <- isolate(input[[param]]) 47 | 48 | if (is.null(value)) { 49 | # Get default values: 50 | value <- regmatches(sourceSql, 51 | regexpr(paste0("\\{\\s*DEFAULT\\s*@", param, "\\s=[^}]+}"), sourceSql)) 52 | if (length(value) == 1) { 53 | value <- sub(paste0("\\{\\s*DEFAULT\\s*@", param, "\\s=\\s*"), "", sub("\\}$", "", value)) 54 | } else { 55 | value <- "" 56 | } 57 | } 58 | textInput(param, param, value = value) 59 | } 60 | lapply(params, createRow, sourceSql = sourceSql) 61 | }) 62 | 63 | observeEvent(input$open, { 64 | sql <- SqlRender::readSql(input$open$datapath) 65 | updateTextAreaInput(session, "source", value = sql) 66 | }) 67 | 68 | output$save <- downloadHandler(filename = function() { 69 | paste("query-", Sys.Date(), ".sql", sep = "") 70 | }, content = function(con) { 71 | SqlRender::writeSql(sql = input$source, targetFile = con) 72 | }) 73 | }) 74 | 75 | -------------------------------------------------------------------------------- /inst/shinyApps/SqlDeveloper/ui.R: -------------------------------------------------------------------------------- 1 | library(shiny) 2 | library(shinydashboard) 3 | source("widgets.R") 4 | 5 | dashboardPage( 6 | dashboardHeader(title = "SqlRender Developer"), 7 | dashboardSidebar( 8 | sidebarMenu( 9 | menuItemFileInput("open", "Open file", icon = shiny::icon("folder-open")), 10 | menuItemDownloadLink("save", "Save", icon = shiny::icon("save")), 11 | menuItem("Open new tab", href = "", icon = shiny::icon("plus-square")), 12 | menuItemCopyTextAreaToClipboard("source", "Copy source to clipboard"), 13 | menuItemCopyDivToClipboard("target", "Copy target to clipboard") 14 | ) 15 | ), 16 | dashboardBody( 17 | fluidRow( 18 | column(width = 9, 19 | box( 20 | title = "Source: OHDSI SQL", width = NULL, status = "primary", 21 | textAreaInput("source", NULL, width = "100%", height = "300px") 22 | ), 23 | box( 24 | title = "Target: Rendered translation", width = NULL, 25 | # tags$table(width = "100%", 26 | # tags$tr( 27 | # tags$td(align = "left", actionButton("renderTranslate", "Render and translate")), 28 | # tags$td(align = "right", checkboxInput("continuous", "Auto render and translate")))), 29 | pre(textOutput("target")) 30 | ) 31 | ), 32 | column(width = 3, 33 | box(background = "light-blue", 34 | h4("Target dialect"), width = NULL, 35 | selectInput("dialect", NULL, choices = c("BigQuery", "Impala", "Netezza", "Oracle", "PDW", "PostgreSQL", "RedShift", "SQL Server", "SQLite", "Hive", "Spark", "Snowflake", "Synapse", "InterSystems IRIS" = "iris"), selected = "SQL Server"), 36 | h4("Temp emulation schema"), 37 | textInput("tempEmulationSchema", NULL), 38 | h4("Parameters"), 39 | uiOutput("parameterInputs"), 40 | textOutput("warnings") 41 | ) 42 | ) 43 | ) 44 | ) 45 | ) 46 | -------------------------------------------------------------------------------- /inst/shinyApps/SqlDeveloper/widgets.R: -------------------------------------------------------------------------------- 1 | menuItemFileInput <- function(inputId, text, icon = shiny::icon("file-text-o")) { 2 | script <- "document.getElementById('%id%').click(); return false;" 3 | script <- gsub("%id%", inputId, script) 4 | list(div(fileInput(inputId, ""), style = "display: none;"), 5 | tags$li(class = "treeview", a(href = "#", onclick = script, icon, text))) 6 | } 7 | 8 | menuItemDownloadLink <- function(inputId, label, icon = shiny::icon("floppy-o")) { 9 | tags$li(class = "treeview", 10 | tags$a(id = inputId, 11 | class = "shiny-download-link", 12 | href = "", 13 | target = "_blank", 14 | download = NA, 15 | icon, 16 | label)) 17 | } 18 | 19 | menuItemCopyTextAreaToClipboard <- function(textAreaId, label, icon = shiny::icon("clipboard")) { 20 | script <- " 21 | element = $('