├── .Rbuildignore
├── .covrignore
├── .gitattributes
├── .github
├── .gitignore
├── CODEOWNERS
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── ISSUE_TEMPLATE
│ └── issue_template.md
├── SUPPORT.md
├── move.yml
├── odbc
│ ├── odbc.ini
│ └── odbcinst.ini
└── workflows
│ ├── R-CMD-check.yaml
│ ├── mssql.yaml
│ ├── pkgdown.yaml
│ ├── postgres.yaml
│ ├── pr-commands.yaml
│ └── test-coverage.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── LICENSE.md
├── NAMESPACE
├── NEWS.md
├── R
├── backend-.R
├── backend-access.R
├── backend-hana.R
├── backend-hive.R
├── backend-impala.R
├── backend-mssql.R
├── backend-mysql.R
├── backend-odbc.R
├── backend-oracle.R
├── backend-postgres-old.R
├── backend-postgres.R
├── backend-redshift.R
├── backend-snowflake.R
├── backend-spark-sql.R
├── backend-sqlite.R
├── backend-teradata.R
├── build-sql.R
├── data-cache.R
├── data-lahman.R
├── data-nycflights13.R
├── db-escape.R
├── db-io.R
├── db-sql.R
├── db.R
├── dbplyr.R
├── escape.R
├── explain.R
├── ident.R
├── import-standalone-obj-type.R
├── import-standalone-s3-register.R
├── import-standalone-types-check.R
├── join-by-compat.R
├── join-cols-compat.R
├── lazy-join-query.R
├── lazy-ops.R
├── lazy-query.R
├── lazy-select-query.R
├── lazy-set-op-query.R
├── memdb.R
├── optimise-utils.R
├── pillar.R
├── progress.R
├── query-join.R
├── query-select.R
├── query-semi-join.R
├── query-set-op.R
├── query.R
├── reexport.R
├── remote.R
├── rows.R
├── schema.R
├── simulate.R
├── sql-build.R
├── sql-clause.R
├── sql-expr.R
├── sql.R
├── src-sql.R
├── src_dbi.R
├── table-name.R
├── tbl-lazy.R
├── tbl-sql.R
├── test-frame.R
├── testthat.R
├── tidyeval-across.R
├── tidyeval.R
├── translate-sql-conditional.R
├── translate-sql-cut.R
├── translate-sql-helpers.R
├── translate-sql-paste.R
├── translate-sql-quantile.R
├── translate-sql-string.R
├── translate-sql-window.R
├── translate-sql.R
├── utils-check.R
├── utils-format.R
├── utils.R
├── verb-arrange.R
├── verb-compute.R
├── verb-copy-to.R
├── verb-count.R
├── verb-distinct.R
├── verb-do-query.R
├── verb-do.R
├── verb-expand.R
├── verb-fill.R
├── verb-filter.R
├── verb-group_by.R
├── verb-head.R
├── verb-joins.R
├── verb-mutate.R
├── verb-pivot-longer.R
├── verb-pivot-wider.R
├── verb-pull.R
├── verb-select.R
├── verb-set-ops.R
├── verb-slice.R
├── verb-summarise.R
├── verb-uncount.R
├── verb-window.R
└── zzz.R
├── README.Rmd
├── README.md
├── _pkgdown.yml
├── codecov.yml
├── cran-comments.md
├── dbplyr.Rproj
├── inst
└── db
│ └── .gitignore
├── man
├── arrange.tbl_lazy.Rd
├── backend-access.Rd
├── backend-hana.Rd
├── backend-hive.Rd
├── backend-impala.Rd
├── backend-mssql.Rd
├── backend-mysql.Rd
├── backend-odbc.Rd
├── backend-oracle.Rd
├── backend-postgres.Rd
├── backend-redshift.Rd
├── backend-snowflake.Rd
├── backend-spark-sql.Rd
├── backend-sqlite.Rd
├── backend-teradata.Rd
├── build_sql.Rd
├── collapse.tbl_sql.Rd
├── complete.tbl_lazy.Rd
├── copy_inline.Rd
├── copy_to.src_sql.Rd
├── count.tbl_lazy.Rd
├── db-io.Rd
├── db-misc.Rd
├── db-quote.Rd
├── db-sql.Rd
├── dbplyr-package.Rd
├── dbplyr-slice.Rd
├── dbplyr_uncount.Rd
├── distinct.tbl_lazy.Rd
├── do.tbl_sql.Rd
├── escape.Rd
├── expand.tbl_lazy.Rd
├── figures
│ ├── lifecycle-archived.svg
│ ├── lifecycle-defunct.svg
│ ├── lifecycle-deprecated.svg
│ ├── lifecycle-experimental.svg
│ ├── lifecycle-maturing.svg
│ ├── lifecycle-questioning.svg
│ ├── lifecycle-soft-deprecated.svg
│ ├── lifecycle-stable.svg
│ ├── lifecycle-superseded.svg
│ └── logo.png
├── fill.tbl_lazy.Rd
├── filter.tbl_lazy.Rd
├── get_returned_rows.Rd
├── group_by.tbl_lazy.Rd
├── head.tbl_lazy.Rd
├── ident.Rd
├── ident_q.Rd
├── in_schema.Rd
├── intersect.tbl_lazy.Rd
├── is_table_path.Rd
├── join.tbl_sql.Rd
├── lahman.Rd
├── lazy_ops.Rd
├── memdb_frame.Rd
├── mutate.tbl_lazy.Rd
├── named_commas.Rd
├── nycflights13.Rd
├── partial_eval.Rd
├── pivot_longer.tbl_lazy.Rd
├── pivot_wider.tbl_lazy.Rd
├── pull.tbl_sql.Rd
├── reexports.Rd
├── remote_name.Rd
├── replace_na.tbl_lazy.Rd
├── rows-db.Rd
├── select.tbl_lazy.Rd
├── simulate_dbi.Rd
├── sql.Rd
├── sql_build.Rd
├── sql_expr.Rd
├── sql_options.Rd
├── sql_query_insert.Rd
├── sql_quote.Rd
├── sql_variant.Rd
├── src_dbi.Rd
├── src_sql.Rd
├── summarise.tbl_lazy.Rd
├── tbl.src_dbi.Rd
├── tbl_lazy.Rd
├── tbl_sql.Rd
├── testing.Rd
├── translate_sql.Rd
├── win_over.Rd
└── window_order.Rd
├── pkgdown
└── favicon
│ ├── apple-touch-icon-120x120.png
│ ├── apple-touch-icon-152x152.png
│ ├── apple-touch-icon-180x180.png
│ ├── apple-touch-icon-60x60.png
│ ├── apple-touch-icon-76x76.png
│ ├── apple-touch-icon.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ └── favicon.ico
├── revdep
├── .gitignore
├── README.md
├── check.R
├── cran.md
├── email.yml
├── failures.md
└── problems.md
├── tests
├── testthat.R
└── testthat
│ ├── .gitignore
│ ├── _snaps
│ ├── backend-.md
│ ├── backend-access.md
│ ├── backend-hana.md
│ ├── backend-hive.md
│ ├── backend-impala.md
│ ├── backend-mssql.md
│ ├── backend-mysql.md
│ ├── backend-oracle.md
│ ├── backend-postgres.md
│ ├── backend-redshift.md
│ ├── backend-snowflake.md
│ ├── backend-spark-sql.md
│ ├── backend-sqlite.md
│ ├── backend-teradata.md
│ ├── build-sql.md
│ ├── db-io.md
│ ├── db-sql.md
│ ├── escape.md
│ ├── ident.md
│ ├── lazy-join-query.md
│ ├── lazy-select-query.md
│ ├── pillar.md
│ ├── query-join.md
│ ├── query-select.md
│ ├── query-semi-join.md
│ ├── query-set-op.md
│ ├── rows.md
│ ├── schema.md
│ ├── sql-build.md
│ ├── sql.md
│ ├── table-name.md
│ ├── tbl-lazy.md
│ ├── tbl-sql.md
│ ├── tidyeval-across.md
│ ├── tidyeval.md
│ ├── translate-sql-conditional.md
│ ├── translate-sql-cut.md
│ ├── translate-sql-helpers.md
│ ├── translate-sql-quantile.md
│ ├── translate-sql-string.md
│ ├── translate-sql-window.md
│ ├── translate-sql.md
│ ├── verb-arrange.md
│ ├── verb-compute.md
│ ├── verb-copy-to.md
│ ├── verb-count.md
│ ├── verb-distinct.md
│ ├── verb-do.md
│ ├── verb-expand.md
│ ├── verb-fill.md
│ ├── verb-filter.md
│ ├── verb-group_by.md
│ ├── verb-joins.md
│ ├── verb-mutate.md
│ ├── verb-pivot-longer.md
│ ├── verb-pivot-wider.md
│ ├── verb-pull.md
│ ├── verb-select.md
│ ├── verb-set-ops.md
│ ├── verb-slice.md
│ ├── verb-summarise.md
│ ├── verb-uncount.md
│ └── verb-window.md
│ ├── helper-src.R
│ ├── test-backend-.R
│ ├── test-backend-access.R
│ ├── test-backend-hana.R
│ ├── test-backend-hive.R
│ ├── test-backend-impala.R
│ ├── test-backend-mssql.R
│ ├── test-backend-mysql.R
│ ├── test-backend-odbc.R
│ ├── test-backend-oracle.R
│ ├── test-backend-postgres-old.R
│ ├── test-backend-postgres.R
│ ├── test-backend-redshift.R
│ ├── test-backend-snowflake.R
│ ├── test-backend-spark-sql.R
│ ├── test-backend-sqlite.R
│ ├── test-backend-teradata.R
│ ├── test-build-sql.R
│ ├── test-db-escape.R
│ ├── test-db-io.R
│ ├── test-db-sql.R
│ ├── test-escape.R
│ ├── test-ident.R
│ ├── test-lazy-join-query.R
│ ├── test-lazy-select-query.R
│ ├── test-pillar.R
│ ├── test-query-join.R
│ ├── test-query-select.R
│ ├── test-query-semi-join.R
│ ├── test-query-set-op.R
│ ├── test-remote.R
│ ├── test-rows.R
│ ├── test-schema.R
│ ├── test-sql-build.R
│ ├── test-sql-expr.R
│ ├── test-sql.R
│ ├── test-src_dbi.R
│ ├── test-table-name.R
│ ├── test-tbl-lazy.R
│ ├── test-tbl-sql.R
│ ├── test-tidyeval-across.R
│ ├── test-tidyeval.R
│ ├── test-translate-sql-conditional.R
│ ├── test-translate-sql-cut.R
│ ├── test-translate-sql-helpers.R
│ ├── test-translate-sql-paste.R
│ ├── test-translate-sql-quantile.R
│ ├── test-translate-sql-string.R
│ ├── test-translate-sql-window.R
│ ├── test-translate-sql.R
│ ├── test-utils.R
│ ├── test-verb-arrange.R
│ ├── test-verb-compute.R
│ ├── test-verb-copy-to.R
│ ├── test-verb-count.R
│ ├── test-verb-distinct.R
│ ├── test-verb-do.R
│ ├── test-verb-expand.R
│ ├── test-verb-fill.R
│ ├── test-verb-filter.R
│ ├── test-verb-group_by.R
│ ├── test-verb-head.R
│ ├── test-verb-joins.R
│ ├── test-verb-mutate.R
│ ├── test-verb-pivot-longer.R
│ ├── test-verb-pivot-wider.R
│ ├── test-verb-pull.R
│ ├── test-verb-select.R
│ ├── test-verb-set-ops.R
│ ├── test-verb-slice.R
│ ├── test-verb-summarise.R
│ ├── test-verb-uncount.R
│ └── test-verb-window.R
└── vignettes
├── .gitignore
├── backend-2.Rmd
├── dbplyr.Rmd
├── new-backend.Rmd
├── reprex.Rmd
├── setup
├── _mssql.Rmd
├── _mysql.Rmd
├── _postgres.Rmd
└── _sap-hana.Rmd
├── sql.Rmd
├── translation-function.Rmd
├── translation-verb.Rmd
├── windows.graffle
└── windows.png
/.Rbuildignore:
--------------------------------------------------------------------------------
1 | ^CRAN-RELEASE$
2 | ^pkgdown$
3 | ^\.covrignore$
4 | ^.*\.Rproj$
5 | ^\.Rproj\.user$
6 | ^\.travis\.yml$
7 | ^inst/db$
8 | ^LICENSE\.md$
9 | ^README\.Rmd$
10 | ^codecov\.yml$
11 | ^_pkgdown\.yml$
12 | ^docs$
13 | ^cran-comments\.md$
14 | ^revdep$
15 | ^\.httr-oauth$
16 | ^\.github$
17 | ^CRAN-SUBMISSION$
18 |
--------------------------------------------------------------------------------
/.covrignore:
--------------------------------------------------------------------------------
1 | R/deprec-*.R
2 | R/compat-*.R
3 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | /NEWS.md merge=union
2 |
--------------------------------------------------------------------------------
/.github/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | # CODEOWNERS for dbplyr
2 | # https://www.tidyverse.org/development/understudies
3 | .github/CODEOWNERS @hadley @edgararuiz
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/issue_template.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report or feature request
3 | about: Describe a bug you've seen or make a case for a new feature
4 | ---
5 |
6 | Please briefly describe your problem and what output you expect. If you have a question, please don't use this form. Instead, ask on or .
7 |
8 | Please include a minimal reproducible example (AKA a reprex). If you've never heard of a [reprex](http://reprex.tidyverse.org/) before, start by reading . You can use the examples in [Reprexes for dbplyr](https://dbplyr.tidyverse.org/articles/reprex.html) as a starting point for your reprex.
9 |
10 | Brief description of the problem
11 |
12 | ```r
13 | # insert reprex here
14 | ```
15 |
--------------------------------------------------------------------------------
/.github/move.yml:
--------------------------------------------------------------------------------
1 | # Configuration for move-issues bot - https://github.com/dessant/move-issues
2 |
3 | # Delete the command comment when it contains no other content
4 | deleteCommand: true
5 |
6 | # Close the source issue after moving
7 | closeSourceIssue: true
8 |
9 | # Lock the source issue after moving
10 | lockSourceIssue: false
11 |
12 | # Mention issue and comment authors
13 | mentionAuthors: true
14 |
15 | # Preserve mentions in the issue content
16 | keepContentMentions: true
17 |
18 | # Set custom aliases for targets
19 | # aliases:
20 | # r: repo
21 | # or: owner/repo
22 |
--------------------------------------------------------------------------------
/.github/odbc/odbc.ini:
--------------------------------------------------------------------------------
1 | [ODBC Data Sources]
2 |
3 | [MicrosoftSQLServer]
4 | Driver = ODBC Driver 17 for SQL Server
5 | Server = localhost
6 | Port = 1433
7 | Database = test
8 |
--------------------------------------------------------------------------------
/.github/odbc/odbcinst.ini:
--------------------------------------------------------------------------------
1 | [ODBC Drivers]
2 |
3 | [ODBC Driver 17 for SQL Server]
4 | Description=Microsoft ODBC Driver 17 for SQL Server
5 | Driver=/usr/lib/libmsodbcsql-17.so
6 | UsageCount=1
7 |
--------------------------------------------------------------------------------
/.github/workflows/mssql.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - main
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | name: mssql
10 |
11 | jobs:
12 | mssql:
13 | runs-on: ubuntu-latest
14 |
15 | services:
16 | sqlserver:
17 | image: mcr.microsoft.com/mssql/server:2017-latest-ubuntu
18 | ports:
19 | - 1433:1433
20 | env:
21 | ACCEPT_EULA: Y
22 | SA_PASSWORD: Password12
23 |
24 | env:
25 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
26 | GITHUB_MSSQL: true
27 | ODBCSYSINI: ${{ github.workspace }}/.github/odbc
28 |
29 | steps:
30 | - uses: actions/checkout@v3
31 |
32 | - uses: r-lib/actions/setup-r@v2
33 |
34 | - uses: r-lib/actions/setup-pandoc@v2
35 |
36 | - uses: r-lib/actions/setup-r@v2
37 | with:
38 | use-public-rspm: true
39 |
40 | - uses: r-lib/actions/setup-r-dependencies@v2
41 | with:
42 | extra-packages: any::rcmdcheck
43 | needs: check
44 |
45 | - name: Install SQL Server driver
46 | run: |
47 | curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -
48 | curl https://packages.microsoft.com/config/ubuntu/20.04/prod.list > /etc/apt/sources.list.d/mssql-release.list
49 | apt-get update
50 | ACCEPT_EULA=Y apt-get install -y msodbcsql17
51 | sqlcmd -U SA -P 'Password12' -Q 'CREATE DATABASE test;'
52 | dpkg -L msodbcsql17
53 | shell: sudo bash {0}
54 |
55 | - name: Check drivers
56 | run: odbc::odbcListDrivers()
57 | shell: Rscript {0}
58 |
59 | - uses: r-lib/actions/check-r-package@v2
60 | with:
61 | upload-snapshots: true
62 |
--------------------------------------------------------------------------------
/.github/workflows/pkgdown.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 | release:
9 | types: [published]
10 | workflow_dispatch:
11 |
12 | name: pkgdown
13 |
14 | jobs:
15 | pkgdown:
16 | runs-on: ubuntu-latest
17 | # Only restrict concurrency for non-PR jobs
18 | concurrency:
19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}
20 | env:
21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
22 | permissions:
23 | contents: write
24 | steps:
25 | - uses: actions/checkout@v3
26 |
27 | - uses: r-lib/actions/setup-pandoc@v2
28 |
29 | - uses: r-lib/actions/setup-r@v2
30 | with:
31 | use-public-rspm: true
32 |
33 | - uses: r-lib/actions/setup-r-dependencies@v2
34 | with:
35 | extra-packages: any::pkgdown, local::.
36 | needs: website
37 |
38 | - name: Build site
39 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)
40 | shell: Rscript {0}
41 |
42 | - name: Deploy to GitHub pages 🚀
43 | if: github.event_name != 'pull_request'
44 | uses: JamesIves/github-pages-deploy-action@v4.4.1
45 | with:
46 | clean: false
47 | branch: gh-pages
48 | folder: docs
49 |
--------------------------------------------------------------------------------
/.github/workflows/postgres.yaml:
--------------------------------------------------------------------------------
1 | on:
2 | push:
3 | branches:
4 | - main
5 | pull_request:
6 | branches:
7 | - main
8 |
9 | name: postgres
10 |
11 | jobs:
12 | postgres:
13 | runs-on: ubuntu-latest
14 |
15 | services:
16 | postgres:
17 | image: postgres
18 | ports:
19 | - 5432:5432
20 | env:
21 | POSTGRES_USER: postgres
22 | POSTGRES_PASSWORD: password
23 | POSTGRES_DB: test
24 | options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
25 |
26 | env:
27 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true
28 | GITHUB_POSTGRES: true
29 |
30 | steps:
31 | - uses: actions/checkout@v3
32 |
33 | - uses: r-lib/actions/setup-r@v2
34 |
35 | - uses: r-lib/actions/setup-pandoc@v2
36 |
37 | - uses: r-lib/actions/setup-r@v2
38 | with:
39 | use-public-rspm: true
40 |
41 | - uses: r-lib/actions/setup-r-dependencies@v2
42 | with:
43 | extra-packages: any::rcmdcheck
44 | needs: check
45 |
46 | - uses: r-lib/actions/check-r-package@v2
47 | with:
48 | upload-snapshots: true
49 |
--------------------------------------------------------------------------------
/.github/workflows/test-coverage.yaml:
--------------------------------------------------------------------------------
1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples
2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help
3 | on:
4 | push:
5 | branches: [main, master]
6 | pull_request:
7 | branches: [main, master]
8 |
9 | name: test-coverage.yaml
10 |
11 | permissions: read-all
12 |
13 | jobs:
14 | test-coverage:
15 | runs-on: ubuntu-latest
16 | env:
17 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}
18 |
19 | steps:
20 | - uses: actions/checkout@v4
21 |
22 | - uses: r-lib/actions/setup-r@v2
23 | with:
24 | use-public-rspm: true
25 |
26 | - uses: r-lib/actions/setup-r-dependencies@v2
27 | with:
28 | extra-packages: any::covr, any::xml2
29 | needs: coverage
30 |
31 | - name: Test coverage
32 | run: |
33 | cov <- covr::package_coverage(
34 | quiet = FALSE,
35 | clean = FALSE,
36 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package")
37 | )
38 | print(cov)
39 | covr::to_cobertura(cov)
40 | shell: Rscript {0}
41 |
42 | - uses: codecov/codecov-action@v5
43 | with:
44 | # Fail if error if not on PR, or if on PR and token is given
45 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }}
46 | files: ./cobertura.xml
47 | plugins: noop
48 | disable_search: true
49 | token: ${{ secrets.CODECOV_TOKEN }}
50 |
51 | - name: Show testthat output
52 | if: always()
53 | run: |
54 | ## --------------------------------------------------------------------
55 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true
56 | shell: bash
57 |
58 | - name: Upload test results
59 | if: failure()
60 | uses: actions/upload-artifact@v4
61 | with:
62 | name: coverage-test-failures
63 | path: ${{ runner.temp }}/package
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /src/*.o
2 | /src/*.o-*
3 | /src/*.d
4 | /src/*.so
5 | *.dll
6 | .RData
7 | .Rproj.user
8 | .Rhistory
9 | inst/doc
10 | .httr-oauth
11 | vignettes/*.R
12 | .DS_Store
13 | /.idea
14 | /clion-test.R
15 | /BROWSE
16 | /GPATH
17 | /GRTAGS
18 | /GTAGS
19 | /TAGS
20 | /.dir-locals.el
21 | revdep/checks
22 | revdep/library
23 | docs
24 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | YEAR: 2023
2 | COPYRIGHT HOLDER: dbplyr authors
3 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | # MIT License
2 |
3 | Copyright (c) 2023 dbplyr authors
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/R/backend-impala.R:
--------------------------------------------------------------------------------
1 | #' Backend: Impala
2 | #'
3 | #' @description
4 | #' See `vignette("translation-function")` and `vignette("translation-verb")` for
5 | #' details of overall translation technology. Key differences for this backend
6 | #' are a scattering of custom translations provided by users, mostly focussed
7 | #' on bitwise operations.
8 | #'
9 | #' Use `simulate_impala()` with `lazy_frame()` to see simulated SQL without
10 | #' converting to live access database.
11 | #'
12 | #' @name backend-impala
13 | #' @aliases NULL
14 | #' @examples
15 | #' library(dplyr, warn.conflicts = FALSE)
16 | #'
17 | #' lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_impala())
18 | #' lf %>% transmute(X = bitwNot(bitwOr(b, c)))
19 | NULL
20 |
21 | #' @export
22 | #' @rdname backend-impala
23 | simulate_impala <- function() simulate_dbi("Impala")
24 |
25 | #' @export
26 | dbplyr_edition.Impala <- function(con) {
27 | 2L
28 | }
29 |
30 | #' @export
31 | sql_translation.Impala <- function(con) {
32 | sql_variant(
33 | scalar = sql_translator(.parent = base_odbc_scalar,
34 | bitwNot = sql_prefix("BITNOT", 1),
35 | bitwAnd = sql_prefix("BITAND", 2),
36 | bitwOr = sql_prefix("BITOR", 2),
37 | bitwXor = sql_prefix("BITXOR", 2),
38 | bitwShiftL = sql_prefix("SHIFTLEFT", 2),
39 | bitwShiftR = sql_prefix("SHIFTRIGHT", 2),
40 |
41 | as.Date = sql_cast("VARCHAR(10)"),
42 | ceiling = sql_prefix("CEIL")
43 | ) ,
44 | base_odbc_agg,
45 | base_odbc_win
46 | )
47 | }
48 |
49 | #' @export
50 | sql_table_analyze.Impala <- function(con, table, ...) {
51 | # Using COMPUTE STATS instead of ANALYZE as recommended in this article
52 | # https://www.cloudera.com/documentation/enterprise/5-9-x/topics/impala_compute_stats.html
53 | glue_sql2(con, "COMPUTE STATS {.tbl table}")
54 | }
55 |
--------------------------------------------------------------------------------
/R/data-cache.R:
--------------------------------------------------------------------------------
1 | cache <- function() {
2 | if (!is_attached("dbplyr_cache")) {
3 | get("attach")(new_environment(), name = "dbplyr_cache", pos = length(search()) - 1)
4 | }
5 | search_env("dbplyr_cache")
6 | }
7 |
8 | cache_computation <- function(name, computation) {
9 | cache <- cache()
10 |
11 | if (env_has(cache, name)) {
12 | env_get(cache, name)
13 | } else {
14 | res <- force(computation)
15 | env_poke(cache, name, res)
16 | res
17 | }
18 | }
19 |
20 | # nocov start
21 | load_srcs <- function(f, src_names, quiet = NULL) {
22 | if (is.null(quiet)) {
23 | quiet <- !identical(Sys.getenv("NOT_CRAN"), "true")
24 | }
25 |
26 | srcs <- lapply(src_names, function(x) {
27 | out <- NULL
28 | try(out <- f(x), silent = TRUE)
29 | if (is.null(out) && !quiet) {
30 | message("Could not instantiate ", x, " src")
31 | }
32 | out
33 | })
34 |
35 | purrr::compact(setNames(srcs, src_names))
36 | }
37 |
38 |
39 | db_location <- function(path = NULL, filename) {
40 | if (!is.null(path)) {
41 | # Check that path is a directory and is writeable
42 | if (!file.exists(path) || !file.info(path)$isdir) {
43 | cli_abort("{.path {path}} is not a directory")
44 | }
45 | if (!is_writeable(path)) cli_abort("Can not write to {.path {path}}")
46 | return(file.path(path, filename))
47 | }
48 |
49 | pkg <- file.path(system.file("db", package = "dplyr"))
50 | if (is_writeable(pkg)) return(file.path(pkg, filename))
51 |
52 | tmp <- tempdir()
53 | if (is_writeable(tmp)) return(file.path(tmp, filename))
54 |
55 | cli_abort("Could not find writeable location to cache db")
56 | }
57 |
58 | is_writeable <- function(x) {
59 | unname(file.access(x, 2) == 0)
60 | }
61 | # nocov end
62 |
--------------------------------------------------------------------------------
/R/db-escape.R:
--------------------------------------------------------------------------------
1 | #' SQL escaping/quoting generics
2 | #'
3 | #' These generics translate individual values into SQL. The core
4 | #' generics are [DBI::dbQuoteIdentifier()] and [DBI::dbQuoteString]
5 | #' for quoting identifiers and strings, but dbplyr needs additional
6 | #' tools for inserting logical, date, date-time, and raw values into
7 | #' queries.
8 | #'
9 | #' @keywords internal
10 | #' @family generic
11 | #' @name db-quote
12 | #' @aliases NULL
13 | #' @examples
14 | #' con <- simulate_dbi()
15 | #' sql_escape_logical(con, c(TRUE, FALSE, NA))
16 | #' sql_escape_date(con, Sys.Date())
17 | #' sql_escape_date(con, Sys.time())
18 | #' sql_escape_raw(con, charToRaw("hi"))
19 | NULL
20 |
21 | #' @rdname db-quote
22 | #' @export
23 | sql_escape_logical <- function(con, x) {
24 | UseMethod("sql_escape_logical")
25 | }
26 | #' @export
27 | sql_escape_logical.DBIConnection <- function(con, x) {
28 | y <- as.character(x)
29 | y[is.na(x)] <- "NULL"
30 | y
31 | }
32 |
33 | #' @export
34 | #' @rdname db-quote
35 | sql_escape_date <- function(con, x) {
36 | UseMethod("sql_escape_date")
37 | }
38 | #' @export
39 | sql_escape_date.DBIConnection <- function(con, x) {
40 | sql_escape_string(con, as.character(x))
41 | }
42 |
43 | #' @export
44 | #' @rdname db-quote
45 | sql_escape_datetime <- function(con, x) {
46 | UseMethod("sql_escape_datetime")
47 | }
48 | #' @export
49 | sql_escape_datetime.DBIConnection <- function(con, x) {
50 | x <- strftime(x, "%Y-%m-%dT%H:%M:%OSZ", tz = "UTC")
51 | sql_escape_string(con, x)
52 | }
53 |
54 | #' @export
55 | #' @rdname db-quote
56 | sql_escape_raw <- function(con, x) {
57 | UseMethod("sql_escape_raw")
58 | }
59 | #' @export
60 | sql_escape_raw.DBIConnection <- function(con, x) {
61 | # Unlike the other escape functions, this is not vectorised because
62 | # raw "vectors" are scalars in this content
63 |
64 | if (is.null(x)) {
65 | "NULL"
66 | } else {
67 | # SQL-99 standard for BLOB literals
68 | # https://crate.io/docs/sql-99/en/latest/chapters/05.html#blob-literal-s
69 | paste0(c("X'", format(x), "'"), collapse = "")
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/R/dbplyr.R:
--------------------------------------------------------------------------------
1 | #' @importFrom stats setNames update
2 | #' @importFrom utils head tail
3 | #' @importFrom glue glue
4 | #' @importFrom cli cli_abort
5 | #' @importFrom dplyr n join_by
6 | #' @import rlang
7 | #' @import DBI
8 | #' @importFrom tibble tibble as_tibble
9 | #' @importFrom magrittr %>%
10 | #' @importFrom lifecycle deprecated
11 | #' @keywords internal
12 | "_PACKAGE"
13 |
--------------------------------------------------------------------------------
/R/explain.R:
--------------------------------------------------------------------------------
1 | #' @importFrom dplyr show_query
2 | #' @export
3 | show_query.tbl_lazy <- function(x, ..., cte = FALSE, sql_options = NULL) {
4 | withr::local_options(list(dbplyr_use_colour = TRUE))
5 | sql <- remote_query(x, cte = cte, sql_options = sql_options)
6 | cat_line("")
7 | cat_line(sql)
8 | invisible(x)
9 | }
10 |
11 | #' @importFrom dplyr explain
12 | #' @export
13 | explain.tbl_sql <- function(x, ...) {
14 | force(x)
15 | show_query(x)
16 | cat_line()
17 | cat_line("")
18 | cat_line(remote_query_plan(x, ...))
19 |
20 | invisible(x)
21 | }
22 |
--------------------------------------------------------------------------------
/R/ident.R:
--------------------------------------------------------------------------------
1 | #' Flag a character vector as SQL identifiers
2 | #'
3 | #' @description
4 | #' `ident()` takes strings and turns them as database identifiers (e.g. table
5 | #' or column names) quoting them using the identifer rules for your database.
6 | #' `ident_q()` does the same, but assumes the names have already been
7 | #' quoted, preventing them from being quoted again.
8 | #'
9 | #' These are generally for internal use only; if you need to supply an
10 | #' table name that is qualified with schema or catalog, or has already been
11 | #' quoted for some other reason, use `I()`.
12 | #'
13 | #' @param ... A character vector, or name-value pairs.
14 | #' @param x An object.
15 | #' @keywords internal
16 | #' @export
17 | #' @examples
18 | #' # SQL92 quotes strings with '
19 | #' escape_ansi("x")
20 | #'
21 | #' # And identifiers with "
22 | #' ident("x")
23 | #' escape_ansi(ident("x"))
24 | #'
25 | #' # You can supply multiple inputs
26 | #' ident(a = "x", b = "y")
27 | #' ident_q(a = "x", b = "y")
28 | ident <- function(...) {
29 | x <- c_character(...)
30 | structure(x, class = c("ident", "character"))
31 | }
32 |
33 | #' @export
34 | print.ident <- function(x, ...) cat(format(x, ...), sep = "\n")
35 | #' @export
36 | format.ident <- function(x, ...) {
37 | if (length(x) == 0) {
38 | paste0(" [empty]")
39 | } else {
40 | paste0(" ", x)
41 | }
42 | }
43 |
44 | #' @rdname ident
45 | #' @export
46 | is.ident <- function(x) inherits(x, "ident")
47 |
48 |
--------------------------------------------------------------------------------
/R/lazy-query.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | #' @rdname sql_build
3 | lazy_query <- function(query_type,
4 | x,
5 | ...,
6 | group_vars = op_grps(x),
7 | order_vars = op_sort(x),
8 | frame = op_frame(x)) {
9 | stopifnot(is.null(group_vars) || (is.character(group_vars) && is.null(names(group_vars))))
10 | stopifnot(is_lazy_sql_part(order_vars), is.null(names(order_vars)))
11 | check_frame(frame)
12 |
13 | structure(
14 | list(
15 | x = x,
16 | ...,
17 | group_vars = group_vars,
18 | order_vars = order_vars,
19 | frame = frame
20 | ),
21 | class = c(paste0("lazy_", query_type, "_query"), "lazy_query")
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/R/memdb.R:
--------------------------------------------------------------------------------
1 | #' Create a database table in temporary in-memory database.
2 | #'
3 | #' `memdb_frame()` works like [tibble::tibble()], but instead of creating a new
4 | #' data frame in R, it creates a table in [src_memdb()].
5 | #'
6 | #' @inheritParams tibble::tibble
7 | #' @param name,.name Name of table in database: defaults to a random name that's
8 | #' unlikely to conflict with an existing table.
9 | #' @param df Data frame to copy
10 | #' @export
11 | #' @examples
12 | #' library(dplyr)
13 | #' df <- memdb_frame(x = runif(100), y = runif(100))
14 | #' df %>% arrange(x)
15 | #' df %>% arrange(x) %>% show_query()
16 | #'
17 | #' mtcars_db <- tbl_memdb(mtcars)
18 | #' mtcars_db %>% group_by(cyl) %>% summarise(n = n()) %>% show_query()
19 | memdb_frame <- function(..., .name = unique_table_name()) {
20 | x <- copy_to(src_memdb(), tibble(...), name = .name)
21 | x
22 | }
23 |
24 | #' @rdname memdb_frame
25 | #' @export
26 | tbl_memdb <- function(df, name = deparse(substitute(df))) {
27 | copy_to(src_memdb(), df, name = name) # nocov
28 | }
29 |
30 | #' @rdname memdb_frame
31 | #' @export
32 | src_memdb <- function() {
33 | cache_computation("src_memdb", {
34 | src_dbi(DBI::dbConnect(RSQLite::SQLite(), ":memory:", create = TRUE))
35 | })
36 | }
37 |
--------------------------------------------------------------------------------
/R/optimise-utils.R:
--------------------------------------------------------------------------------
1 | uses_mutated_vars <- function(dots, select) {
2 | if (is_null(select)) {
3 | return(TRUE)
4 | }
5 |
6 | vars <- set_names(select$expr, select$name)
7 | mutated_vars <- names(purrr::discard(vars, is_symbol))
8 |
9 | if (is_empty(mutated_vars)) {
10 | return(FALSE)
11 | }
12 |
13 | any(purrr::map_lgl(dots, expr_uses_var, mutated_vars))
14 | }
15 |
16 | expr_uses_var <- function(x, vars) {
17 | if (is.sql(x)) return(TRUE)
18 | if (is_call(x, "sql")) return(TRUE)
19 | if (is_quosure(x)) return(expr_uses_var(quo_get_expr(x), vars))
20 | if (is_symbol(x)) {
21 | return(is_symbol(x, vars))
22 | }
23 |
24 | any(purrr::map_lgl(as.list(x[-1]), expr_uses_var, vars))
25 | }
26 |
27 | any_expr_uses_sql <- function(dots) {
28 | purrr::some(dots, expr_uses_sql)
29 | }
30 |
31 | expr_uses_sql <- function(x) {
32 | if (is.sql(x)) return(TRUE)
33 | if (is_call(x, "sql")) return(TRUE)
34 | if (is_quosure(x)) return(expr_uses_sql(quo_get_expr(x)))
35 |
36 | if (!is_call(x)) return(FALSE)
37 |
38 | any(purrr::map_lgl(as.list(x[-1]), expr_uses_sql))
39 | }
40 |
--------------------------------------------------------------------------------
/R/pillar.R:
--------------------------------------------------------------------------------
1 | #' @importFrom pillar tbl_format_header style_subtle align
2 | #' @export
3 | tbl_format_header.tbl_sql <- function(x, setup, ...) {
4 | named_header <- tbl_sum(x)
5 |
6 | # The setup object may know the total number of rows
7 | named_header["Source"] <- tbl_desc(x, rows_total = setup$rows_total)
8 |
9 | # Adapted from pillar
10 | header <- paste0(
11 | align(paste0(names(named_header), ":")),
12 | " ",
13 | named_header
14 | )
15 |
16 | style_subtle(paste0("# ", header))
17 | }
18 |
--------------------------------------------------------------------------------
/R/query-semi-join.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | #' @rdname sql_build
3 | semi_join_query <- function(x,
4 | y,
5 | vars,
6 | anti = FALSE,
7 | by = NULL,
8 | where = NULL,
9 | na_matches = FALSE) {
10 | structure(
11 | list(
12 | x = x,
13 | y = y,
14 | vars = vars,
15 | anti = anti,
16 | by = by,
17 | where = where,
18 | na_matches = na_matches
19 | ),
20 | class = c("semi_join_query", "query")
21 | )
22 | }
23 |
24 | #' @export
25 | print.semi_join_query <- function(x, ...) {
26 | cat_line("")
27 |
28 | cat_line("By:")
29 | cat_line(indent(paste0(x$by$x, "-", x$by$y)))
30 |
31 | if (length(x$where)) {
32 | cat_line("Where:")
33 | where <- purrr::map_chr(x$where, as_label)
34 | cat_line(indent(paste0(where)))
35 | }
36 |
37 | cat_line("X:")
38 | cat_line(indent_print(x$x))
39 |
40 | cat_line("Y:")
41 | cat_line(indent_print(x$y))
42 | }
43 |
44 | #' @export
45 | sql_render.semi_join_query <- function(query,
46 | con = NULL,
47 | ...,
48 | sql_options = NULL,
49 | subquery = FALSE,
50 | lvl = 0) {
51 | from_x <- sql_render(query$x, con, ..., subquery = TRUE, lvl = lvl + 1)
52 | from_y <- sql_render(query$y, con, ..., subquery = TRUE, lvl = lvl + 1)
53 |
54 | dbplyr_query_semi_join(
55 | con,
56 | from_x,
57 | from_y,
58 | vars = query$vars,
59 | anti = query$anti,
60 | by = query$by,
61 | where = query$where,
62 | lvl = lvl
63 | )
64 | }
65 |
66 | #' @export
67 | flatten_query.semi_join_query <- flatten_query_2_tables
68 |
--------------------------------------------------------------------------------
/R/query.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | sql_optimise.query <- function(x, con = NULL, ...) {
3 | # Default to no optimisation
4 | x
5 | }
6 |
--------------------------------------------------------------------------------
/R/reexport.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | magrittr::`%>%`
3 |
--------------------------------------------------------------------------------
/R/simulate.R:
--------------------------------------------------------------------------------
1 | #' Simulate database connections
2 | #'
3 | #' These functions generate S3 objects that have been designed to simulate
4 | #' the action of a database connection, without actually having the database
5 | #' available. Obviously, this simulation can only be incomplete, but most
6 | #' importantly it allows us to simulate SQL generation for any database without
7 | #' actually connecting to it.
8 | #'
9 | #' Simulated SQL always quotes identifies with `` `x` ``, and strings with
10 | #' `'x'`.
11 | #'
12 | #' @keywords internal
13 | #' @export
14 | simulate_dbi <- function(class = character(), ...) {
15 | structure(
16 | list(),
17 | ...,
18 | class = c(class, "TestConnection", "DBIConnection")
19 | )
20 | }
21 |
22 | #' @export
23 | dbplyr_edition.TestConnection <- function(con) 2L
24 |
25 |
26 | sql_escape_ident <- function(con, x) {
27 | UseMethod("sql_escape_ident")
28 | }
29 | #' @export
30 | sql_escape_ident.default <- function(con, x) {
31 | dbQuoteIdentifier(con, x)
32 | }
33 | #' @export
34 | sql_escape_ident.TestConnection <- function(con, x) {
35 | if (methods::is(x, "SQL")) {
36 | x
37 | } else {
38 | sql_quote(x, "`")
39 | }
40 | }
41 |
42 | sql_escape_string <- function(con, x) {
43 | UseMethod("sql_escape_string")
44 | }
45 | #' @export
46 | sql_escape_string.default <- function(con, x) {
47 | dbQuoteString(con, x)
48 | }
49 | #' @export
50 | sql_escape_string.TestConnection <- function(con, x) {
51 | sql_quote(x, "'")
52 | }
53 |
--------------------------------------------------------------------------------
/R/sql.R:
--------------------------------------------------------------------------------
1 | #' SQL escaping.
2 | #'
3 | #' These functions are critical when writing functions that translate R
4 | #' functions to sql functions. Typically a conversion function should escape
5 | #' all its inputs and return an sql object.
6 | #'
7 | #' @param ... Character vectors that will be combined into a single SQL
8 | #' expression.
9 | #' @export
10 | sql <- function(...) {
11 | x <- c_character(...)
12 | structure(x, class = c("sql", "character"))
13 | }
14 |
15 | # See setOldClass definition in zzz.R
16 |
17 | # c() is also called outside of the dbplyr context so must supply default
18 | # connection - this seems like a design mistake, and probably an indication
19 | # that within dbplyr c() should be replaced with a more specific function
20 | #' @export
21 | c.sql <- function(..., drop_null = FALSE, con = simulate_dbi()) {
22 | input <- list(...)
23 |
24 | if (drop_null) input <- purrr::compact(input) # nocov
25 |
26 | out <- unlist(lapply(input, escape, collapse = NULL, con = con))
27 | sql(out)
28 | }
29 |
30 | #' @export
31 | c.ident <- c.sql
32 |
33 | #' @export
34 | unique.sql <- function(x, ...) {
35 | sql(NextMethod()) # nocov
36 | }
37 |
38 | #' @rdname sql
39 | #' @export
40 | is.sql <- function(x) inherits(x, "sql")
41 |
42 | #' @export
43 | print.sql <- function(x, ...) cat(format(x, ...), sep = "\n")
44 | #' @export
45 | format.sql <- function(x, ...) {
46 | if (length(x) == 0) {
47 | paste0(" [empty]")
48 | } else {
49 | paste0(" ", x, ifelse(names2(x) == "", "", paste0(" AS ", names2(x))))
50 | }
51 | }
52 |
53 | #' @rdname sql
54 | #' @export
55 | #' @param x Object to coerce
56 | #' @param con Needed when `x` is directly supplied from the user so that
57 | #' schema specifications can be quoted using the correct identifiers.
58 | as.sql <- function(x, con) UseMethod("as.sql")
59 |
60 | #' @export
61 | as.sql.ident <- function(x, con) x
62 | #' @export
63 | as.sql.sql <- function(x, con) x
64 | #' @export
65 | as.sql.character <- function(x, con) ident(x)
66 |
--------------------------------------------------------------------------------
/R/src-sql.R:
--------------------------------------------------------------------------------
1 | # nocov start
2 |
3 | #' Create a "sql src" object
4 | #'
5 | #' Deprecated: please use directly use a `DBIConnection` object instead.
6 | #'
7 | #' @keywords internal
8 | #' @export
9 | #' @param subclass name of subclass. "src_sql" is an abstract base class, so you
10 | #' must supply this value. `src_` is automatically prepended to the
11 | #' class name
12 | #' @param con the connection object
13 | #' @param ... fields used by object
14 | src_sql <- function(subclass, con, ...) {
15 | lifecycle::deprecate_stop(
16 | when = "1.4.0",
17 | what = "src_sql()",
18 | always = TRUE
19 | )
20 | }
21 |
22 |
23 | #' @importFrom dplyr same_src
24 | #' @export
25 | same_src.src_sql <- function(x, y) {
26 | if (!inherits(y, "src_sql")) return(FALSE)
27 | identical(x$con, y$con)
28 | }
29 |
30 | #' @importFrom dplyr src_tbls
31 | #' @export
32 | src_tbls.src_sql <- function(x, ...) {
33 | dbListTables(x$con)
34 | }
35 |
36 | #' @export
37 | format.src_sql <- function(x, ...) {
38 | paste0(
39 | "src: ", dbplyr_connection_describe(x$con), "\n",
40 | wrap("tbls: ", paste0(sort(src_tbls(x)), collapse = ", "))
41 | )
42 | }
43 | # nocov end
44 |
--------------------------------------------------------------------------------
/R/testthat.R:
--------------------------------------------------------------------------------
1 |
2 | compare_tbl <- function(x, y, label = NULL, expected.label = NULL) {
3 | testthat::expect_equal(
4 | arrange(collect(x), dplyr::across(everything())),
5 | arrange(collect(y), dplyr::across(everything())),
6 | label = label,
7 | expected.label = expected.label
8 | )
9 | }
10 |
11 | expect_equal_tbls <- function(results, ref = NULL, ...) {
12 | check_list(results)
13 |
14 | if (!is_named(results)) {
15 | result_name <- expr_name(substitute(results)) # nocov
16 | names(results) <- paste0(result_name, "_", seq_along(results)) # nocov
17 | }
18 |
19 | # If ref is NULL, use the first result
20 | if (is.null(ref)) {
21 | if (length(results) < 2) {
22 | testthat::skip("Need at least two srcs to compare")
23 | }
24 |
25 | ref <- results[[1]]
26 | ref_name <- names(results)[[1]]
27 |
28 | rest <- results[-1]
29 | } else {
30 | rest <- results
31 | ref_name <- "`ref`"
32 | }
33 |
34 | for (i in seq_along(rest)) {
35 | compare_tbl(
36 | rest[[i]], ref,
37 | label = names(rest)[[i]],
38 | expected.label = ref_name
39 | )
40 | }
41 |
42 | invisible(TRUE)
43 | }
44 |
--------------------------------------------------------------------------------
/R/translate-sql-paste.R:
--------------------------------------------------------------------------------
1 | #' @export
2 | #' @rdname sql_variant
3 | sql_paste <- function(default_sep, f = "CONCAT_WS") {
4 |
5 | function(..., sep = default_sep, collapse = NULL){
6 | check_collapse(collapse)
7 | sql_call2(f, sep, ...)
8 | }
9 | }
10 |
11 | #' @export
12 | #' @rdname sql_variant
13 | sql_paste_infix <- function(default_sep, op, cast) {
14 | force(default_sep)
15 | op <- as.symbol(paste0("%", op, "%"))
16 | force(cast)
17 |
18 | function(..., sep = default_sep, collapse = NULL){
19 | check_collapse(collapse)
20 |
21 | args <- list(...)
22 | if (length(args) == 1) {
23 | return(cast(args[[1]]))
24 | }
25 |
26 | if (sep == "") {
27 | infix <- function(x, y) sql_call2(op, x, y)
28 | } else {
29 | infix <- function(x, y) sql_call2(op, sql_call2(op, x, sep), y)
30 | }
31 |
32 | purrr::reduce(args, infix)
33 | }
34 | }
35 |
36 | check_collapse <- function(collapse) {
37 | if (is.null(collapse))
38 | return()
39 |
40 | cli_abort(c(
41 | "{.arg collapse} not supported in DB translation of {.fun paste}.",
42 | i = "Please use {.fun str_flatten} instead."
43 | ))
44 | }
45 |
--------------------------------------------------------------------------------
/R/translate-sql-quantile.R:
--------------------------------------------------------------------------------
1 | sql_quantile <- function(f,
2 | style = c("infix", "ordered"),
3 | window = FALSE) {
4 | force(f)
5 | style <- match.arg(style)
6 | force(window)
7 |
8 | function(x, probs, na.rm = FALSE) {
9 | check_probs(probs)
10 | check_na_rm(na.rm)
11 |
12 | sql <- switch(style,
13 | infix = sql_call2(f, x, probs),
14 | ordered = glue_sql2(
15 | sql_current_con(),
16 | sql_call2(f, probs), " WITHIN GROUP (ORDER BY {x})"
17 | )
18 | )
19 |
20 | if (window) {
21 | sql <- win_over(sql,
22 | partition = win_current_group(),
23 | frame = win_current_frame()
24 | )
25 | }
26 | sql
27 | }
28 | }
29 |
30 | sql_median <- function(f,
31 | style = c("infix", "ordered"),
32 | window = FALSE) {
33 | quantile <- sql_quantile(f, style = style, window = window)
34 | function(x, na.rm = FALSE) {
35 | quantile(x, 0.5, na.rm = na.rm)
36 | }
37 | }
38 |
39 | check_probs <- function(probs, call = caller_env()) {
40 | # TODO min, max? Inf? NA?
41 | check_number_decimal(probs, call = call)
42 |
43 | if (length(probs) > 1) {
44 | cli_abort("SQL translation only supports single value for {.arg probs}.")
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/R/utils-format.R:
--------------------------------------------------------------------------------
1 | # nocov start
2 | wrap <- function(..., indent = 0) {
3 | x <- paste0(..., collapse = "")
4 | wrapped <- strwrap(
5 | x,
6 | indent = indent,
7 | exdent = indent + 2,
8 | width = getOption("width")
9 | )
10 |
11 | paste0(wrapped, collapse = "\n")
12 | }
13 | # nocov end
14 |
15 | indent <- function(x) {
16 | x <- paste0(x, collapse = "\n")
17 | paste0(" ", gsub("\n", "\n ", x))
18 | }
19 |
20 | indent_print <- function(x) {
21 | indent(utils::capture.output(print(x)))
22 | }
23 |
24 | style_kw <- function(x) {
25 | if (!dbplyr_use_colour()) {
26 | return(x)
27 | }
28 |
29 | highlight <- dbplyr_highlight()
30 | if (is_false(highlight)) {
31 | return(x)
32 | }
33 |
34 | highlight(x)
35 | }
36 |
37 | # function for the thousand separator,
38 | # returns "," unless it's used for the decimal point, in which case returns "."
39 | 'big_mark' <- function(x, ...) {
40 | mark <- if (identical(getOption("OutDec"), ",")) "." else ","
41 | formatC(x, big.mark = mark, ...)
42 | }
43 |
44 | dbplyr_use_colour <- function() {
45 | getOption("dbplyr_use_colour", FALSE)
46 | }
47 |
48 | dbplyr_highlight <- function() {
49 | highlight <- getOption("dbplyr_highlight", cli::combine_ansi_styles("blue"))
50 |
51 | if (is_true(highlight)) {
52 | highlight <- cli::combine_ansi_styles("blue")
53 | }
54 |
55 | if (is_false(highlight)) {
56 | return(FALSE)
57 | }
58 |
59 | if (!inherits(highlight, "cli_ansi_style")) {
60 | msg <- "{.envvar dbplyr_highlight} must be `NULL`, `FALSE` or a {.cls cli_ansi_style}."
61 | cli::cli_abort(msg)
62 | }
63 |
64 | highlight
65 | }
66 |
--------------------------------------------------------------------------------
/R/verb-do-query.R:
--------------------------------------------------------------------------------
1 | #' @importFrom R6 R6Class
2 | NULL
3 |
4 | Query <- R6::R6Class("Query",
5 | private = list(
6 | .vars = NULL
7 | ),
8 | public = list(
9 | con = NULL,
10 | sql = NULL,
11 |
12 | initialize = function(con, sql, vars) {
13 | self$con <- con
14 | self$sql <- sql
15 | private$.vars <- vars
16 | },
17 |
18 | # nocov start
19 | print = function(...) {
20 | cat_line(" ", self$sql)
21 | print(self$con)
22 | },
23 |
24 | fetch = function(n = -1L) {
25 | res <- dbSendQuery(self$con, self$sql)
26 | on.exit(dbClearResult(res))
27 |
28 | out <- dbFetch(res, n)
29 | res_warn_incomplete(res)
30 | out
31 | },
32 | # nocov end
33 |
34 | fetch_paged = function(chunk_size = 1e4, callback) {
35 | qry <- dbSendQuery(self$con, self$sql)
36 | on.exit(dbClearResult(qry))
37 |
38 | while (!dbHasCompleted(qry)) {
39 | chunk <- dbFetch(qry, chunk_size)
40 | callback(chunk)
41 | }
42 |
43 | invisible(TRUE)
44 | },
45 |
46 | # nocov start
47 | vars = function() {
48 | private$.vars
49 | },
50 |
51 | ncol = function() {
52 | length(self$vars())
53 | }
54 | # nocov end
55 | )
56 | )
57 |
--------------------------------------------------------------------------------
/R/verb-head.R:
--------------------------------------------------------------------------------
1 | #' Subset the first rows
2 | #'
3 | #' @description
4 | #' This is a method for the [head()] generic. It is usually translated to the
5 | #' `LIMIT` clause of the SQL query. Because `LIMIT` is not an official part of
6 | #' the SQL specification, some database use other clauses like `TOP` or
7 | #' `FETCH ROWS`.
8 | #'
9 | #' Note that databases don't really have a sense of row order, so what "first"
10 | #' means is subject to interpretation. Most databases will respect ordering
11 | #' performed with `arrange()`, but it's not guaranteed. `tail()` is not
12 | #' supported at all because the situation is even murkier for the "last" rows.
13 | #'
14 | #' @param x A lazy data frame backed by a database query.
15 | #' @param n Number of rows to return
16 | #' @param ... Not used.
17 | #' @inherit arrange.tbl_lazy return
18 | #' @export
19 | #' @examples
20 | #' library(dplyr, warn.conflicts = FALSE)
21 | #'
22 | #' db <- memdb_frame(x = 1:100)
23 | #' db %>% head() %>% show_query()
24 | #'
25 | #' # Pretend we have data in a SQL server database
26 | #' db2 <- lazy_frame(x = 1:100, con = simulate_mssql())
27 | #' db2 %>% head() %>% show_query()
28 | head.tbl_lazy <- function(x, n = 6L, ...) {
29 | if (!is.numeric(n) || length(n) != 1L || n < 0) {
30 | cli_abort("{.arg n} must be a non-negative integer")
31 | }
32 | n <- trunc(n)
33 |
34 | x$lazy_query <- add_head(x, n)
35 | x
36 | }
37 |
38 | add_head <- function(x, n) {
39 | lazy_query <- x$lazy_query
40 | if (!is_lazy_select_query(lazy_query)) {
41 | lazy_query <- lazy_select_query(
42 | x = lazy_query,
43 | limit = n
44 | )
45 |
46 | return(lazy_query)
47 | }
48 |
49 | lazy_query$limit <- min(lazy_query$limit, n)
50 | lazy_query
51 | }
52 |
53 | #' @export
54 | tail.tbl_lazy <- function(x, n = 6L, ...) {
55 | stop_unsupported_function("tail")
56 | }
57 |
--------------------------------------------------------------------------------
/R/verb-pull.R:
--------------------------------------------------------------------------------
1 | #' Extract a single column
2 | #'
3 | #' This is a method for the dplyr [pull()] generic. It evaluates the query
4 | #' retrieving just the specified column.
5 | #'
6 | #' @inheritParams arrange.tbl_lazy
7 | #' @inheritParams dplyr::pull
8 | #' @return A vector of data.
9 | #' @importFrom dplyr pull
10 | #' @export
11 | #' @examples
12 | #' library(dplyr, warn.conflicts = FALSE)
13 | #'
14 | #' db <- memdb_frame(x = 1:5, y = 5:1)
15 | #' db %>%
16 | #' mutate(z = x + y * 2) %>%
17 | #' pull()
18 | pull.tbl_sql <- function(.data, var = -1, name = NULL, ...) {
19 | vars <- tbl_vars(.data)
20 | var <- tidyselect::vars_pull(vars, !!enquo(var), error_arg = "var")
21 | name_quo <- enquo(name)
22 | if (!quo_is_null(name_quo)) {
23 | name <- tidyselect::vars_pull(vars, !!name_quo, error_arg = "name")
24 | }
25 |
26 | .data <- ungroup(.data)
27 | .data <- select(.data, all_of(c(var, name)))
28 |
29 | .data <- collect(.data)
30 | out <- .data[[var]]
31 | if (!is.null(name)) {
32 | out <- set_names(out, nm = .data[[name]])
33 | }
34 |
35 | out
36 | }
37 |
--------------------------------------------------------------------------------
/R/zzz.R:
--------------------------------------------------------------------------------
1 | # nocov start
2 | .onLoad <- function(...) {
3 | # lazy S3method() directive for this case only works in 4.3 and later
4 | s3_register("dplyr::filter", "tbl_lazy")
5 |
6 | methods::setOldClass(c("ident_q", "ident", "character"), ident_q())
7 | methods::setOldClass(c("ident", "character"), ident())
8 | methods::setOldClass(c("sql", "character"), sql())
9 |
10 | base_scalar$`%>%` <- magrittr::`%>%`
11 | }
12 |
13 | # Silence R CMD check note:
14 | # ** checking whether the namespace can be loaded with stated dependencies ... NOTE
15 | # Warning in .undefineMethod("initialize", Class, classWhere) :
16 | # no generic function 'initialize' found
17 | #
18 | # I'm not sure why this is necessary, but I suspect it's due to the use of
19 | # setOldClass onLoad
20 | #' @importFrom methods initialize
21 | NULL
22 |
23 | # nocov end
24 |
--------------------------------------------------------------------------------
/codecov.yml:
--------------------------------------------------------------------------------
1 | comment: false
2 |
3 | coverage:
4 | status:
5 | project:
6 | default:
7 | target: auto
8 | threshold: 1%
9 | informational: true
10 | patch:
11 | default:
12 | target: auto
13 | threshold: 1%
14 | informational: true
15 |
--------------------------------------------------------------------------------
/cran-comments.md:
--------------------------------------------------------------------------------
1 | ## R CMD check results
2 |
3 | 0 errors | 0 warnings | 1 notes
4 |
5 | Just the usual maintainer email address change.
6 |
7 | ## revdepcheck results
8 |
9 | We checked 101 reverse dependencies (92 from CRAN + 9 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.
10 |
11 | * We saw 8 new problems:
12 |
13 | Andromeda: fix submitted at https://github.com/OHDSI/Andromeda/pull/63
14 |
15 | CMDConnector: fix submitted at https://github.com/darwin-eu/CDMConnector/pull/16
16 |
17 | CohortSurvival/DrugUtilisation/IncidencePrevalence/PatientProfiles:
18 | Failure due CDMConnector
19 |
20 | SCDB: fix submitted at https://github.com/ssi-dk/SCDB/pull/114
21 |
22 | diseasystore: due to SCDB
23 |
24 | * We failed to check 0 packages
25 |
26 | The authors of failing packages have been contacted, and most have been supplied with patches. Detailed summarised at https://github.com/tidyverse/dbplyr/issues/1469
27 |
--------------------------------------------------------------------------------
/dbplyr.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 |
15 | AutoAppendNewline: Yes
16 | StripTrailingWhitespace: Yes
17 |
18 | BuildType: Package
19 | PackageUseDevtools: Yes
20 | PackageInstallArgs: --no-multiarch --with-keep.source --install-tests
21 | PackageRoxygenize: rd,collate,namespace
22 |
--------------------------------------------------------------------------------
/inst/db/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite
2 |
--------------------------------------------------------------------------------
/man/arrange.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-arrange.R
3 | \name{arrange.tbl_lazy}
4 | \alias{arrange.tbl_lazy}
5 | \title{Arrange rows by column values}
6 | \usage{
7 | \method{arrange}{tbl_lazy}(.data, ..., .by_group = FALSE)
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
13 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
14 | order.}
15 |
16 | \item{.by_group}{If \code{TRUE}, will sort first by grouping variable. Applies to
17 | grouped data frames only.}
18 | }
19 | \value{
20 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
21 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
22 | and return data to R.
23 | }
24 | \description{
25 | This is an method for the dplyr \code{\link[=arrange]{arrange()}} generic. It generates
26 | the \verb{ORDER BY} clause of the SQL query. It also affects the
27 | \code{\link[=window_order]{window_order()}} of windowed expressions in \code{\link[=mutate.tbl_lazy]{mutate.tbl_lazy()}}.
28 |
29 | Note that \verb{ORDER BY} clauses can not generally appear in subqueries, which
30 | means that you should \code{arrange()} as late as possible in your pipelines.
31 | }
32 | \section{Missing values}{
33 |
34 | Unlike R, most databases sorts \code{NA} (\code{NULL}s) at the front. You can
35 | can override this behaviour by explicitly sorting on \code{is.na(x)}.
36 | }
37 |
38 | \examples{
39 | library(dplyr, warn.conflicts = FALSE)
40 |
41 | db <- memdb_frame(a = c(3, 4, 1, 2), b = c(5, 1, 2, NA))
42 | db \%>\% arrange(a) \%>\% show_query()
43 |
44 | # Note that NAs are sorted first
45 | db \%>\% arrange(b)
46 | # override by sorting on is.na() first
47 | db \%>\% arrange(is.na(b), b)
48 | }
49 |
--------------------------------------------------------------------------------
/man/backend-access.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-access.R
3 | \name{backend-access}
4 | \alias{simulate_access}
5 | \title{Backend: MS Access}
6 | \usage{
7 | simulate_access()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item \code{SELECT} uses \code{TOP}, not \code{LIMIT}
15 | \item Non-standard types and mathematical functions
16 | \item String concatenation uses \code{&}
17 | \item No \code{ANALYZE} equivalent
18 | \item \code{TRUE} and \code{FALSE} converted to 1 and 0
19 | }
20 |
21 | Use \code{simulate_access()} with \code{lazy_frame()} to see simulated SQL without
22 | converting to live access database.
23 | }
24 | \examples{
25 | library(dplyr, warn.conflicts = FALSE)
26 | lf <- lazy_frame(x = 1, y = 2, z = "a", con = simulate_access())
27 |
28 | lf \%>\% head()
29 | lf \%>\% mutate(y = as.numeric(y), z = sqrt(x^2 + 10))
30 | lf \%>\% mutate(a = paste0(z, " times"))
31 | }
32 |
--------------------------------------------------------------------------------
/man/backend-hana.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-hana.R
3 | \name{backend-hana}
4 | \alias{simulate_hana}
5 | \title{Backend: SAP HANA}
6 | \usage{
7 | simulate_hana()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item Temporary tables get \verb{#} prefix and use \verb{LOCAL TEMPORARY COLUMN}.
15 | \item No table analysis performed in \code{\link[=copy_to]{copy_to()}}.
16 | \item \code{paste()} uses \code{||}
17 | \item Note that you can't create new boolean columns from logical expressions;
18 | you need to wrap with explicit \code{ifelse}: \code{ifelse(x > y, TRUE, FALSE)}.
19 | }
20 |
21 | Use \code{simulate_hana()} with \code{lazy_frame()} to see simulated SQL without
22 | converting to live access database.
23 | }
24 | \examples{
25 | library(dplyr, warn.conflicts = FALSE)
26 |
27 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_hana())
28 | lf \%>\% transmute(x = paste0(d, " times"))
29 | }
30 |
--------------------------------------------------------------------------------
/man/backend-hive.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-hive.R
3 | \name{backend-hive}
4 | \alias{simulate_hive}
5 | \title{Backend: Hive}
6 | \usage{
7 | simulate_hive()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are a scattering of custom translations provided by users.
13 |
14 | Use \code{simulate_hive()} with \code{lazy_frame()} to see simulated SQL without
15 | converting to live access database.
16 | }
17 | \examples{
18 | library(dplyr, warn.conflicts = FALSE)
19 |
20 | lf <- lazy_frame(a = TRUE, b = 1, d = 2, c = "z", con = simulate_hive())
21 | lf \%>\% transmute(x = cot(b))
22 | lf \%>\% transmute(x = bitwShiftL(c, 1L))
23 | lf \%>\% transmute(x = str_replace_all(c, "a", "b"))
24 |
25 | lf \%>\% summarise(x = median(d, na.rm = TRUE))
26 | lf \%>\% summarise(x = var(c, na.rm = TRUE))
27 | }
28 |
--------------------------------------------------------------------------------
/man/backend-impala.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-impala.R
3 | \name{backend-impala}
4 | \alias{simulate_impala}
5 | \title{Backend: Impala}
6 | \usage{
7 | simulate_impala()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are a scattering of custom translations provided by users, mostly focussed
13 | on bitwise operations.
14 |
15 | Use \code{simulate_impala()} with \code{lazy_frame()} to see simulated SQL without
16 | converting to live access database.
17 | }
18 | \examples{
19 | library(dplyr, warn.conflicts = FALSE)
20 |
21 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_impala())
22 | lf \%>\% transmute(X = bitwNot(bitwOr(b, c)))
23 | }
24 |
--------------------------------------------------------------------------------
/man/backend-mysql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-mysql.R
3 | \name{backend-mysql}
4 | \alias{simulate_mysql}
5 | \alias{simulate_mariadb}
6 | \title{Backend: MySQL/MariaDB}
7 | \usage{
8 | simulate_mysql()
9 |
10 | simulate_mariadb()
11 | }
12 | \description{
13 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
14 | details of overall translation technology. Key differences for this backend
15 | are:
16 | \itemize{
17 | \item \code{paste()} uses \code{CONCAT_WS()}
18 | \item String translations for \code{str_detect()}, \code{str_locate()}, and
19 | \code{str_replace_all()}
20 | \item Clear error message for unsupported full joins
21 | }
22 |
23 | Use \code{simulate_mysql()} with \code{lazy_frame()} to see simulated SQL without
24 | converting to live access database.
25 | }
26 | \examples{
27 | library(dplyr, warn.conflicts = FALSE)
28 |
29 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_mysql())
30 | lf \%>\% transmute(x = paste0(d, " times"))
31 | }
32 |
--------------------------------------------------------------------------------
/man/backend-odbc.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-odbc.R
3 | \name{backend-odbc}
4 | \alias{simulate_odbc}
5 | \title{Backend: ODBC}
6 | \usage{
7 | simulate_odbc()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are minor translations for common data types.
13 |
14 | Use \code{simulate_odbc()} with \code{lazy_frame()} to see simulated SQL without
15 | converting to live access database.
16 | }
17 | \examples{
18 | library(dplyr, warn.conflicts = FALSE)
19 |
20 | lf <- lazy_frame(a = TRUE, b = 1, d = 2, c = "z", con = simulate_odbc())
21 | lf \%>\% transmute(x = as.numeric(b))
22 | lf \%>\% transmute(x = as.integer(b))
23 | lf \%>\% transmute(x = as.character(b))
24 | }
25 |
--------------------------------------------------------------------------------
/man/backend-oracle.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-oracle.R
3 | \name{backend-oracle}
4 | \alias{simulate_oracle}
5 | \title{Backend: Oracle}
6 | \usage{
7 | simulate_oracle()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item Use \verb{FETCH FIRST} instead of \code{LIMIT}
15 | \item Custom types
16 | \item \code{paste()} uses \code{||}
17 | \item Custom subquery generation (no \code{AS})
18 | \item \code{setdiff()} uses \code{MINUS} instead of \code{EXCEPT}
19 | }
20 |
21 | Note that versions of Oracle prior to 23c have limited supported for
22 | \code{TRUE} and \code{FALSE} and you may need to use \code{1} and \code{0} instead.
23 | See \url{https://oracle-base.com/articles/23/boolean-data-type-23} for
24 | more details.
25 |
26 | Use \code{simulate_oracle()} with \code{lazy_frame()} to see simulated SQL without
27 | converting to live access database.
28 | }
29 | \examples{
30 | library(dplyr, warn.conflicts = FALSE)
31 |
32 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_oracle())
33 | lf \%>\% transmute(x = paste0(c, " times"))
34 | lf \%>\% setdiff(lf)
35 | }
36 |
--------------------------------------------------------------------------------
/man/backend-postgres.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-postgres.R
3 | \name{backend-postgres}
4 | \alias{simulate_postgres}
5 | \title{Backend: PostgreSQL}
6 | \usage{
7 | simulate_postgres()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item Many stringr functions
15 | \item lubridate date-time extraction functions
16 | \item More standard statistical summaries
17 | }
18 |
19 | Use \code{simulate_postgres()} with \code{lazy_frame()} to see simulated SQL without
20 | converting to live access database.
21 | }
22 | \examples{
23 | library(dplyr, warn.conflicts = FALSE)
24 |
25 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_postgres())
26 | lf \%>\% summarise(x = sd(b, na.rm = TRUE))
27 | lf \%>\% summarise(y = cor(b, c), z = cov(b, c))
28 | }
29 |
--------------------------------------------------------------------------------
/man/backend-redshift.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-redshift.R
3 | \name{backend-redshift}
4 | \alias{simulate_redshift}
5 | \title{Backend: Redshift}
6 | \usage{
7 | simulate_redshift()
8 | }
9 | \description{
10 | Base translations come from \link[=simulate_postgres]{PostgreSQL backend}. There
11 | are generally few differences, apart from string manipulation.
12 |
13 | Use \code{simulate_redshift()} with \code{lazy_frame()} to see simulated SQL without
14 | converting to live access database.
15 | }
16 | \examples{
17 | library(dplyr, warn.conflicts = FALSE)
18 |
19 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_redshift())
20 | lf \%>\% transmute(x = paste(c, " times"))
21 | lf \%>\% transmute(x = substr(c, 2, 3))
22 | lf \%>\% transmute(x = str_replace_all(c, "a", "z"))
23 | }
24 |
--------------------------------------------------------------------------------
/man/backend-snowflake.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-snowflake.R
3 | \name{backend-snowflake}
4 | \alias{simulate_snowflake}
5 | \title{Backend: Snowflake}
6 | \usage{
7 | simulate_snowflake()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology.
12 |
13 | Use \code{simulate_snowflake()} with \code{lazy_frame()} to see simulated SQL without
14 | converting to live access database.
15 | }
16 | \examples{
17 | library(dplyr, warn.conflicts = FALSE)
18 |
19 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_snowflake())
20 | lf \%>\% transmute(x = paste0(d, " times"))
21 | }
22 |
--------------------------------------------------------------------------------
/man/backend-spark-sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-spark-sql.R
3 | \name{backend-spark-sql}
4 | \alias{simulate_spark_sql}
5 | \title{Backend: Databricks Spark SQL}
6 | \usage{
7 | simulate_spark_sql()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are better translation of statistical aggregate functions
13 | (e.g. \code{var()}, \code{median()}) and use of temporary views instead of temporary
14 | tables when copying data.
15 |
16 | Use \code{simulate_spark_sql()} with \code{lazy_frame()} to see simulated SQL without
17 | converting to live access database.
18 | }
19 | \examples{
20 | library(dplyr, warn.conflicts = FALSE)
21 |
22 | lf <- lazy_frame(a = TRUE, b = 1, d = 2, c = "z", con = simulate_spark_sql())
23 |
24 | lf \%>\% summarise(x = median(d, na.rm = TRUE))
25 | lf \%>\% summarise(x = var(c, na.rm = TRUE), .by = d)
26 |
27 | lf \%>\% mutate(x = first(c))
28 | lf \%>\% mutate(x = first(c), .by = d)
29 | }
30 |
--------------------------------------------------------------------------------
/man/backend-sqlite.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-sqlite.R
3 | \name{backend-sqlite}
4 | \alias{simulate_sqlite}
5 | \title{Backend: SQLite}
6 | \usage{
7 | simulate_sqlite()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item Uses non-standard \code{LOG()} function
15 | \item Date-time extraction functions from lubridate
16 | \item Custom median translation
17 | \item Right and full joins are simulated using left joins
18 | }
19 |
20 | Use \code{simulate_sqlite()} with \code{lazy_frame()} to see simulated SQL without
21 | converting to live access database.
22 | }
23 | \examples{
24 | library(dplyr, warn.conflicts = FALSE)
25 |
26 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_sqlite())
27 | lf \%>\% transmute(x = paste(c, " times"))
28 | lf \%>\% transmute(x = log(b), y = log(b, base = 2))
29 | }
30 |
--------------------------------------------------------------------------------
/man/backend-teradata.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/backend-teradata.R
3 | \name{backend-teradata}
4 | \alias{simulate_teradata}
5 | \title{Backend: Teradata}
6 | \usage{
7 | simulate_teradata()
8 | }
9 | \description{
10 | See \code{vignette("translation-function")} and \code{vignette("translation-verb")} for
11 | details of overall translation technology. Key differences for this backend
12 | are:
13 | \itemize{
14 | \item Uses \code{TOP} instead of \code{LIMIT}
15 | \item Selection of user supplied translations
16 | }
17 |
18 | Use \code{simulate_teradata()} with \code{lazy_frame()} to see simulated SQL without
19 | converting to live access database.
20 | }
21 | \examples{
22 | library(dplyr, warn.conflicts = FALSE)
23 |
24 | lf <- lazy_frame(a = TRUE, b = 1, c = 2, d = "z", con = simulate_teradata())
25 | lf \%>\% head()
26 | }
27 |
--------------------------------------------------------------------------------
/man/build_sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/build-sql.R
3 | \name{build_sql}
4 | \alias{build_sql}
5 | \title{Build a SQL string.}
6 | \usage{
7 | build_sql(..., .env = parent.frame(), con = sql_current_con())
8 | }
9 | \arguments{
10 | \item{...}{input to convert to SQL. Use \code{\link[=sql]{sql()}} to preserve
11 | user input as is (dangerous), and \code{\link[=ident]{ident()}} to label user
12 | input as sql identifiers (safe)}
13 |
14 | \item{.env}{the environment in which to evaluate the arguments. Should not
15 | be needed in typical use.}
16 |
17 | \item{con}{database connection; used to select correct quoting characters.}
18 | }
19 | \description{
20 | This is a convenience function that should prevent sql injection attacks
21 | (which in the context of dplyr are most likely to be accidental not
22 | deliberate) by automatically escaping all expressions in the input, while
23 | treating bare strings as sql. This is unlikely to prevent any serious
24 | attack, but should make it unlikely that you produce invalid sql.
25 | }
26 | \details{
27 | This function should be used only when generating \code{SELECT} clauses,
28 | other high level queries, or for other syntax that has no R equivalent.
29 | For individual function translations, prefer \code{\link[=sql_expr]{sql_expr()}}.
30 | }
31 | \examples{
32 | con <- simulate_dbi()
33 | build_sql("SELECT * FROM TABLE", con = con)
34 | x <- "TABLE"
35 | build_sql("SELECT * FROM ", x, con = con)
36 | build_sql("SELECT * FROM ", ident(x), con = con)
37 | build_sql("SELECT * FROM ", sql(x), con = con)
38 |
39 | # http://xkcd.com/327/
40 | name <- "Robert'); DROP TABLE Students;--"
41 | build_sql("INSERT INTO Students (Name) VALUES (", name, ")", con = con)
42 | }
43 | \keyword{internal}
44 |
--------------------------------------------------------------------------------
/man/complete.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-expand.R
3 | \name{complete.tbl_lazy}
4 | \alias{complete.tbl_lazy}
5 | \title{Complete a SQL table with missing combinations of data}
6 | \usage{
7 | \method{complete}{tbl_lazy}(data, ..., fill = list())
8 | }
9 | \arguments{
10 | \item{data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{Specification of columns to expand. See \link[tidyr:expand]{tidyr::expand} for
13 | more details.}
14 |
15 | \item{fill}{A named list that for each variable supplies a single value to
16 | use instead of NA for missing combinations.}
17 | }
18 | \value{
19 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
20 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
21 | and return data to R.
22 | }
23 | \description{
24 | Turns implicit missing values into explicit missing values. This is a method
25 | for the \code{\link[tidyr:complete]{tidyr::complete()}} generic.
26 | }
27 | \examples{
28 | \dontshow{if (rlang::is_installed("tidyr", version = "1.0.0")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
29 | df <- memdb_frame(
30 | group = c(1:2, 1),
31 | item_id = c(1:2, 2),
32 | item_name = c("a", "b", "b"),
33 | value1 = 1:3,
34 | value2 = 4:6
35 | )
36 |
37 | df \%>\% tidyr::complete(group, nesting(item_id, item_name))
38 |
39 | # You can also choose to fill in missing values
40 | df \%>\% tidyr::complete(group, nesting(item_id, item_name), fill = list(value1 = 0))
41 | \dontshow{\}) # examplesIf}
42 | }
43 |
--------------------------------------------------------------------------------
/man/copy_inline.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-copy-to.R
3 | \name{copy_inline}
4 | \alias{copy_inline}
5 | \title{Use a local data frame in a dbplyr query}
6 | \usage{
7 | copy_inline(con, df, types = NULL)
8 | }
9 | \arguments{
10 | \item{con}{A database connection.}
11 |
12 | \item{df}{A local data frame. The data is written directly in the SQL query
13 | so it should be small.}
14 |
15 | \item{types}{A named character vector of SQL data types to use for the columns.
16 | The data types are backend specific. For example for Postgres this could
17 | be \code{c(id = "bigint", created_at = "timestamp", values = "integer[]")}.
18 | If \code{NULL}, the default, the types are determined from \code{df}.}
19 | }
20 | \value{
21 | A \code{tbl_lazy}.
22 | }
23 | \description{
24 | This is an alternative to \code{\link[=copy_to]{copy_to()}} that does not need write access and
25 | is faster for small data.
26 | }
27 | \details{
28 | It writes the data directly in the SQL query via the \code{VALUES} clause.
29 | }
30 | \examples{
31 | df <- data.frame(x = 1:3, y = c("a", "b", "c"))
32 | con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
33 |
34 | copy_inline(con, df)
35 |
36 | copy_inline(con, df) \%>\% dplyr::show_query()
37 | }
38 | \seealso{
39 | \code{\link[=copy_to]{copy_to()}} to copy the data into a new database table.
40 | }
41 |
--------------------------------------------------------------------------------
/man/db-misc.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/db.R
3 | \name{db-misc}
4 | \alias{db_connection_describe}
5 | \alias{sql_join_suffix}
6 | \alias{db_sql_render}
7 | \alias{db_col_types}
8 | \alias{dbplyr_edition}
9 | \title{Miscellaneous database generics}
10 | \usage{
11 | db_connection_describe(con, ...)
12 |
13 | sql_join_suffix(con, suffix, ...)
14 |
15 | db_sql_render(con, sql, ..., cte = FALSE, sql_options = NULL)
16 |
17 | db_col_types(con, table, call)
18 |
19 | dbplyr_edition(con)
20 | }
21 | \description{
22 | \itemize{
23 | \item \code{db_connection_describe()} provides a short string describing the
24 | database connection, helping users tell which database a table comes
25 | from. It should be a single line, and ideally less than 60 characters wide.
26 | }
27 | }
28 | \details{
29 | \itemize{
30 | \item \code{dbplyr_edition()} declares which version of the dbplyr API you want.
31 | See below for more details.
32 | \item \code{db_col_types()} returns the column types of a table.
33 | }
34 | }
35 | \section{dbplyr 2.0.0}{
36 |
37 | dbplyr 2.0.0 renamed a number of generics so that they could be cleanly moved
38 | from dplyr to dbplyr. If you have an existing backend, you'll need to rename
39 | the following methods.
40 | \itemize{
41 | \item \code{dplyr::db_desc()} -> \code{dbplyr::db_connection_describe()} (also note that
42 | the argument named changed from \code{x} to \code{con}).
43 | }
44 | }
45 |
46 | \seealso{
47 | Other generic:
48 | \code{\link{db-sql}},
49 | \code{\link{db_copy_to}()},
50 | \code{\link{sql_escape_logical}()}
51 | }
52 | \concept{generic}
53 | \keyword{internal}
54 |
--------------------------------------------------------------------------------
/man/db-quote.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/db-escape.R
3 | \name{db-quote}
4 | \alias{sql_escape_logical}
5 | \alias{sql_escape_date}
6 | \alias{sql_escape_datetime}
7 | \alias{sql_escape_raw}
8 | \title{SQL escaping/quoting generics}
9 | \usage{
10 | sql_escape_logical(con, x)
11 |
12 | sql_escape_date(con, x)
13 |
14 | sql_escape_datetime(con, x)
15 |
16 | sql_escape_raw(con, x)
17 | }
18 | \description{
19 | These generics translate individual values into SQL. The core
20 | generics are \code{\link[DBI:dbQuoteIdentifier]{DBI::dbQuoteIdentifier()}} and \link[DBI:dbQuoteString]{DBI::dbQuoteString}
21 | for quoting identifiers and strings, but dbplyr needs additional
22 | tools for inserting logical, date, date-time, and raw values into
23 | queries.
24 | }
25 | \examples{
26 | con <- simulate_dbi()
27 | sql_escape_logical(con, c(TRUE, FALSE, NA))
28 | sql_escape_date(con, Sys.Date())
29 | sql_escape_date(con, Sys.time())
30 | sql_escape_raw(con, charToRaw("hi"))
31 | }
32 | \seealso{
33 | Other generic:
34 | \code{\link{db-sql}},
35 | \code{\link{db_connection_describe}()},
36 | \code{\link{db_copy_to}()}
37 | }
38 | \concept{generic}
39 | \keyword{internal}
40 |
--------------------------------------------------------------------------------
/man/dbplyr-package.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/dbplyr.R
3 | \docType{package}
4 | \name{dbplyr-package}
5 | \alias{dbplyr}
6 | \alias{dbplyr-package}
7 | \title{dbplyr: A 'dplyr' Back End for Databases}
8 | \description{
9 | \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}
10 |
11 | A 'dplyr' back end for databases that allows you to work with remote database tables as if they are in-memory data frames. Basic features works with any database that has a 'DBI' back end; more advanced features require 'SQL' translation to be provided by the package author.
12 | }
13 | \seealso{
14 | Useful links:
15 | \itemize{
16 | \item \url{https://dbplyr.tidyverse.org/}
17 | \item \url{https://github.com/tidyverse/dbplyr}
18 | \item Report bugs at \url{https://github.com/tidyverse/dbplyr/issues}
19 | }
20 |
21 | }
22 | \author{
23 | \strong{Maintainer}: Hadley Wickham \email{hadley@posit.co}
24 |
25 | Authors:
26 | \itemize{
27 | \item Maximilian Girlich
28 | \item Edgar Ruiz
29 | }
30 |
31 | Other contributors:
32 | \itemize{
33 | \item Posit Software, PBC [copyright holder, funder]
34 | }
35 |
36 | }
37 | \keyword{internal}
38 |
--------------------------------------------------------------------------------
/man/dbplyr_uncount.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-uncount.R
3 | \name{dbplyr_uncount}
4 | \alias{dbplyr_uncount}
5 | \title{"Uncount" a database table}
6 | \usage{
7 | dbplyr_uncount(data, weights, .remove = TRUE, .id = NULL)
8 | }
9 | \arguments{
10 | \item{data}{A lazy data frame backed by a database query.}
11 |
12 | \item{weights}{A vector of weights. Evaluated in the context of \code{data};
13 | supports quasiquotation.}
14 |
15 | \item{.remove}{If \code{TRUE}, and \code{weights} is the name of a column in \code{data},
16 | then this column is removed.}
17 |
18 | \item{.id}{Supply a string to create a new variable which gives a unique
19 | identifier for each created row.}
20 | }
21 | \description{
22 | This is a method for the tidyr \code{uncount()} generic. It uses a temporary
23 | table, so your database user needs permissions to create one.
24 | }
25 | \examples{
26 | df <- memdb_frame(x = c("a", "b"), n = c(1, 2))
27 | dbplyr_uncount(df, n)
28 | dbplyr_uncount(df, n, .id = "id")
29 |
30 | # You can also use constants
31 | dbplyr_uncount(df, 2)
32 |
33 | # Or expressions
34 | dbplyr_uncount(df, 2 / n)
35 | }
36 |
--------------------------------------------------------------------------------
/man/distinct.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-distinct.R
3 | \name{distinct.tbl_lazy}
4 | \alias{distinct.tbl_lazy}
5 | \title{Subset distinct/unique rows}
6 | \usage{
7 | \method{distinct}{tbl_lazy}(.data, ..., .keep_all = FALSE)
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
13 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
14 | order.}
15 |
16 | \item{.keep_all}{If \code{TRUE}, keep all variables in \code{.data}.
17 | If a combination of \code{...} is not distinct, this keeps the
18 | first row of values.}
19 | }
20 | \value{
21 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
22 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
23 | and return data to R.
24 | }
25 | \description{
26 | This is a method for the dplyr \code{\link[=distinct]{distinct()}} generic. It adds the
27 | \code{DISTINCT} clause to the SQL query.
28 | }
29 | \examples{
30 | library(dplyr, warn.conflicts = FALSE)
31 |
32 | db <- memdb_frame(x = c(1, 1, 2, 2), y = c(1, 2, 1, 1))
33 | db \%>\% distinct() \%>\% show_query()
34 | db \%>\% distinct(x) \%>\% show_query()
35 | }
36 |
--------------------------------------------------------------------------------
/man/do.tbl_sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-do.R
3 | \name{do.tbl_sql}
4 | \alias{do.tbl_sql}
5 | \title{Perform arbitrary computation on remote backend}
6 | \usage{
7 | \method{do}{tbl_sql}(.data, ..., .chunk_size = 10000L)
8 | }
9 | \arguments{
10 | \item{.data}{a tbl}
11 |
12 | \item{...}{Expressions to apply to each group. If named, results will be
13 | stored in a new column. If unnamed, must return a data frame. You can
14 | use \code{.} to refer to the current group. You can not mix named and
15 | unnamed arguments.}
16 |
17 | \item{.chunk_size}{The size of each chunk to pull into R. If this number is
18 | too big, the process will be slow because R has to allocate and free a lot
19 | of memory. If it's too small, it will be slow, because of the overhead of
20 | talking to the database.}
21 | }
22 | \description{
23 | Perform arbitrary computation on remote backend
24 | }
25 |
--------------------------------------------------------------------------------
/man/escape.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/escape.R
3 | \name{escape}
4 | \alias{escape}
5 | \alias{escape_ansi}
6 | \alias{sql_vector}
7 | \title{Escape/quote a string.}
8 | \usage{
9 | escape(x, parens = NA, collapse = " ", con = NULL)
10 |
11 | escape_ansi(x, parens = NA, collapse = "")
12 |
13 | sql_vector(x, parens = NA, collapse = " ", con = NULL)
14 | }
15 | \arguments{
16 | \item{x}{An object to escape. Existing sql vectors will be left as is,
17 | character vectors are escaped with single quotes, numeric vectors have
18 | trailing \code{.0} added if they're whole numbers, identifiers are
19 | escaped with double quotes.}
20 |
21 | \item{parens, collapse}{Controls behaviour when multiple values are supplied.
22 | \code{parens} should be a logical flag, or if \code{NA}, will wrap in
23 | parens if length > 1.
24 |
25 | Default behaviour: lists are always wrapped in parens and separated by
26 | commas, identifiers are separated by commas and never wrapped,
27 | atomic vectors are separated by spaces and wrapped in parens if needed.}
28 |
29 | \item{con}{Database connection.}
30 | }
31 | \description{
32 | \code{escape()} requires you to provide a database connection to control the
33 | details of escaping. \code{escape_ansi()} uses the SQL 92 ANSI standard.
34 | }
35 | \examples{
36 | # Doubles vs. integers
37 | escape_ansi(1:5)
38 | escape_ansi(c(1, 5.4))
39 |
40 | # String vs known sql vs. sql identifier
41 | escape_ansi("X")
42 | escape_ansi(sql("X"))
43 | escape_ansi(ident("X"))
44 |
45 | # Escaping is idempotent
46 | escape_ansi("X")
47 | escape_ansi(escape_ansi("X"))
48 | escape_ansi(escape_ansi(escape_ansi("X")))
49 | }
50 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-archived.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-defunct.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-deprecated.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-experimental.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-maturing.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-questioning.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-soft-deprecated.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-stable.svg:
--------------------------------------------------------------------------------
1 |
30 |
--------------------------------------------------------------------------------
/man/figures/lifecycle-superseded.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/man/figures/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/man/figures/logo.png
--------------------------------------------------------------------------------
/man/fill.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-fill.R
3 | \name{fill.tbl_lazy}
4 | \alias{fill.tbl_lazy}
5 | \title{Fill in missing values with previous or next value}
6 | \usage{
7 | \method{fill}{tbl_lazy}(.data, ..., .direction = c("down", "up", "updown", "downup"))
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{Columns to fill.}
13 |
14 | \item{.direction}{Direction in which to fill missing values. Currently
15 | either "down" (the default) or "up". Note that "up" does not work when
16 | \code{.data} is sorted by non-numeric columns. As a workaround revert the order
17 | yourself beforehand; for example replace \code{arrange(x, desc(y))} by
18 | \code{arrange(desc(x), y)}.}
19 | }
20 | \description{
21 | Fill in missing values with previous or next value
22 | }
23 | \examples{
24 | \dontshow{if (rlang::is_installed("tidyr", version = "1.0.0")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
25 | squirrels <- tibble::tribble(
26 | ~group, ~name, ~role, ~n_squirrels, ~ n_squirrels2,
27 | 1, "Sam", "Observer", NA, 1,
28 | 1, "Mara", "Scorekeeper", 8, NA,
29 | 1, "Jesse", "Observer", NA, NA,
30 | 1, "Tom", "Observer", NA, 4,
31 | 2, "Mike", "Observer", NA, NA,
32 | 2, "Rachael", "Observer", NA, 6,
33 | 2, "Sydekea", "Scorekeeper", 14, NA,
34 | 2, "Gabriela", "Observer", NA, NA,
35 | 3, "Derrick", "Observer", NA, NA,
36 | 3, "Kara", "Scorekeeper", 9, 10,
37 | 3, "Emily", "Observer", NA, NA,
38 | 3, "Danielle", "Observer", NA, NA
39 | )
40 | squirrels$id <- 1:12
41 |
42 | tbl_memdb(squirrels) \%>\%
43 | window_order(id) \%>\%
44 | tidyr::fill(
45 | n_squirrels,
46 | n_squirrels2,
47 | )
48 | \dontshow{\}) # examplesIf}
49 | }
50 |
--------------------------------------------------------------------------------
/man/filter.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-filter.R
3 | \name{filter.tbl_lazy}
4 | \alias{filter.tbl_lazy}
5 | \title{Subset rows using column values}
6 | \usage{
7 | \method{filter}{tbl_lazy}(.data, ..., .by = NULL, .preserve = FALSE)
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
13 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
14 | order.}
15 |
16 | \item{.by}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
17 |
18 | <\code{\link[dplyr:dplyr_tidy_select]{tidy-select}}> Optionally, a selection of columns to
19 | group by for just this operation, functioning as an alternative to \code{\link[dplyr:group_by]{group_by()}}. For
20 | details and examples, see \link[dplyr:dplyr_by]{?dplyr_by}.}
21 |
22 | \item{.preserve}{Not supported by this method.}
23 | }
24 | \value{
25 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
26 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
27 | and return data to R.
28 | }
29 | \description{
30 | This is a method for the dplyr \code{\link[=filter]{filter()}} generic. It generates the
31 | \code{WHERE} clause of the SQL query.
32 | }
33 | \examples{
34 | library(dplyr, warn.conflicts = FALSE)
35 |
36 | db <- memdb_frame(x = c(2, NA, 5, NA, 10), y = 1:5)
37 | db \%>\% filter(x < 5) \%>\% show_query()
38 | db \%>\% filter(is.na(x)) \%>\% show_query()
39 | }
40 |
--------------------------------------------------------------------------------
/man/get_returned_rows.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/rows.R
3 | \name{get_returned_rows}
4 | \alias{get_returned_rows}
5 | \alias{has_returned_rows}
6 | \title{Extract and check the \code{RETURNING} rows}
7 | \usage{
8 | get_returned_rows(x)
9 |
10 | has_returned_rows(x)
11 | }
12 | \arguments{
13 | \item{x}{A lazy tbl.}
14 | }
15 | \value{
16 | For \code{get_returned_rows()}, a tibble.
17 |
18 | For \code{has_returned_rows()}, a scalar logical.
19 | }
20 | \description{
21 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}}
22 |
23 | \code{get_returned_rows()} extracts the \code{RETURNING} rows produced by
24 | \code{\link[=rows_insert]{rows_insert()}}, \code{\link[=rows_append]{rows_append()}}, \code{\link[=rows_update]{rows_update()}}, \code{\link[=rows_upsert]{rows_upsert()}},
25 | or \code{\link[=rows_delete]{rows_delete()}} if these are called with the \code{returning} argument.
26 | An error is raised if this information is not available.
27 |
28 | \code{has_returned_rows()} checks if \code{x} has stored RETURNING rows produced by
29 | \code{\link[=rows_insert]{rows_insert()}}, \code{\link[=rows_append]{rows_append()}}, \code{\link[=rows_update]{rows_update()}}, \code{\link[=rows_upsert]{rows_upsert()}},
30 | or \code{\link[=rows_delete]{rows_delete()}}.
31 | }
32 | \examples{
33 | library(dplyr)
34 |
35 | con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
36 | DBI::dbExecute(con, "CREATE TABLE Info (
37 | id INTEGER PRIMARY KEY AUTOINCREMENT,
38 | number INTEGER
39 | )")
40 | info <- tbl(con, "Info")
41 |
42 | rows1 <- copy_inline(con, data.frame(number = c(1, 5)))
43 | rows_insert(info, rows1, conflict = "ignore", in_place = TRUE)
44 | info
45 |
46 | # If the table has an auto incrementing primary key, you can use
47 | # the returning argument + `get_returned_rows()` its value
48 | rows2 <- copy_inline(con, data.frame(number = c(13, 27)))
49 | info <- rows_insert(
50 | info,
51 | rows2,
52 | conflict = "ignore",
53 | in_place = TRUE,
54 | returning = id
55 | )
56 | info
57 | get_returned_rows(info)
58 | }
59 |
--------------------------------------------------------------------------------
/man/group_by.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-group_by.R
3 | \name{group_by.tbl_lazy}
4 | \alias{group_by.tbl_lazy}
5 | \title{Group by one or more variables}
6 | \usage{
7 | \method{group_by}{tbl_lazy}(.data, ..., .add = FALSE, add = deprecated(), .drop = TRUE)
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
13 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
14 | order.}
15 |
16 | \item{.add}{When \code{FALSE}, the default, \code{group_by()} will
17 | override existing groups. To add to the existing groups, use
18 | \code{.add = TRUE}.
19 |
20 | This argument was previously called \code{add}, but that prevented
21 | creating a new grouping variable called \code{add}, and conflicts with
22 | our naming conventions.}
23 |
24 | \item{add}{Deprecated. Please use \code{.add} instead.}
25 |
26 | \item{.drop}{Not supported by this method.}
27 | }
28 | \description{
29 | This is a method for the dplyr \code{\link[=group_by]{group_by()}} generic. It is translated to
30 | the \verb{GROUP BY} clause of the SQL query when used with
31 | \code{\link[=summarise.tbl_lazy]{summarise()}} and to the \verb{PARTITION BY} clause of
32 | window functions when used with \code{\link[=mutate.tbl_lazy]{mutate()}}.
33 | }
34 | \examples{
35 | library(dplyr, warn.conflicts = FALSE)
36 |
37 | db <- memdb_frame(g = c(1, 1, 1, 2, 2), x = c(4, 3, 6, 9, 2))
38 | db \%>\%
39 | group_by(g) \%>\%
40 | summarise(n()) \%>\%
41 | show_query()
42 |
43 | db \%>\%
44 | group_by(g) \%>\%
45 | mutate(x2 = x / sum(x, na.rm = TRUE)) \%>\%
46 | show_query()
47 | }
48 |
--------------------------------------------------------------------------------
/man/head.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-head.R
3 | \name{head.tbl_lazy}
4 | \alias{head.tbl_lazy}
5 | \title{Subset the first rows}
6 | \usage{
7 | \method{head}{tbl_lazy}(x, n = 6L, ...)
8 | }
9 | \arguments{
10 | \item{x}{A lazy data frame backed by a database query.}
11 |
12 | \item{n}{Number of rows to return}
13 |
14 | \item{...}{Not used.}
15 | }
16 | \value{
17 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
18 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
19 | and return data to R.
20 | }
21 | \description{
22 | This is a method for the \code{\link[=head]{head()}} generic. It is usually translated to the
23 | \code{LIMIT} clause of the SQL query. Because \code{LIMIT} is not an official part of
24 | the SQL specification, some database use other clauses like \code{TOP} or
25 | \verb{FETCH ROWS}.
26 |
27 | Note that databases don't really have a sense of row order, so what "first"
28 | means is subject to interpretation. Most databases will respect ordering
29 | performed with \code{arrange()}, but it's not guaranteed. \code{tail()} is not
30 | supported at all because the situation is even murkier for the "last" rows.
31 | }
32 | \examples{
33 | library(dplyr, warn.conflicts = FALSE)
34 |
35 | db <- memdb_frame(x = 1:100)
36 | db \%>\% head() \%>\% show_query()
37 |
38 | # Pretend we have data in a SQL server database
39 | db2 <- lazy_frame(x = 1:100, con = simulate_mssql())
40 | db2 \%>\% head() \%>\% show_query()
41 | }
42 |
--------------------------------------------------------------------------------
/man/ident.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/ident.R
3 | \name{ident}
4 | \alias{ident}
5 | \alias{is.ident}
6 | \title{Flag a character vector as SQL identifiers}
7 | \usage{
8 | ident(...)
9 |
10 | is.ident(x)
11 | }
12 | \arguments{
13 | \item{...}{A character vector, or name-value pairs.}
14 |
15 | \item{x}{An object.}
16 | }
17 | \description{
18 | \code{ident()} takes strings and turns them as database identifiers (e.g. table
19 | or column names) quoting them using the identifer rules for your database.
20 | \code{ident_q()} does the same, but assumes the names have already been
21 | quoted, preventing them from being quoted again.
22 |
23 | These are generally for internal use only; if you need to supply an
24 | table name that is qualified with schema or catalog, or has already been
25 | quoted for some other reason, use \code{I()}.
26 | }
27 | \examples{
28 | # SQL92 quotes strings with '
29 | escape_ansi("x")
30 |
31 | # And identifiers with "
32 | ident("x")
33 | escape_ansi(ident("x"))
34 |
35 | # You can supply multiple inputs
36 | ident(a = "x", b = "y")
37 | ident_q(a = "x", b = "y")
38 | }
39 | \keyword{internal}
40 |
--------------------------------------------------------------------------------
/man/ident_q.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/schema.R
3 | \name{ident_q}
4 | \alias{ident_q}
5 | \title{Declare a identifier as being pre-quoted.}
6 | \usage{
7 | ident_q(...)
8 | }
9 | \description{
10 | No longer needed; please use \code{\link[=sql]{sql()}} instead.
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/man/in_schema.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/schema.R
3 | \name{in_schema}
4 | \alias{in_schema}
5 | \alias{in_catalog}
6 | \title{Refer to a table in another schema/catalog}
7 | \usage{
8 | in_schema(schema, table)
9 |
10 | in_catalog(catalog, schema, table)
11 | }
12 | \arguments{
13 | \item{catalog, schema, table}{Names of catalog, schema, and table.
14 | These will be automatically quoted; use \code{\link[=sql]{sql()}} to pass a raw name
15 | that won't get quoted.}
16 | }
17 | \description{
18 | \code{in_schema()} and \code{in_catalog()} can be used to refer to tables outside of
19 | the current catalog/schema. However, we now recommend using \code{I()} as it's
20 | typically less typing.
21 | }
22 | \examples{
23 | # Previously:
24 | in_schema("my_schema", "my_table")
25 | in_catalog("my_catalog", "my_schema", "my_table")
26 | in_schema(sql("my_schema"), sql("my_table"))
27 |
28 | # Now
29 | I("my_schema.my_table")
30 | I("my_catalog.my_schema.my_table")
31 | I("my_schema.my_table")
32 |
33 | # Example using schemas with SQLite
34 | con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
35 |
36 | # Add auxiliary schema
37 | tmp <- tempfile()
38 | DBI::dbExecute(con, paste0("ATTACH '", tmp, "' AS aux"))
39 |
40 | library(dplyr, warn.conflicts = FALSE)
41 | copy_to(con, iris, "df", temporary = FALSE)
42 | copy_to(con, mtcars, I("aux.df"), temporary = FALSE)
43 |
44 | con \%>\% tbl("df")
45 | con \%>\% tbl(I("aux.df"))
46 | }
47 | \keyword{internal}
48 |
--------------------------------------------------------------------------------
/man/intersect.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-set-ops.R
3 | \name{intersect.tbl_lazy}
4 | \alias{intersect.tbl_lazy}
5 | \alias{union.tbl_lazy}
6 | \alias{union_all.tbl_lazy}
7 | \alias{setdiff.tbl_lazy}
8 | \title{SQL set operations}
9 | \usage{
10 | \method{intersect}{tbl_lazy}(x, y, copy = FALSE, ..., all = FALSE)
11 |
12 | \method{union}{tbl_lazy}(x, y, copy = FALSE, ..., all = FALSE)
13 |
14 | \method{union_all}{tbl_lazy}(x, y, copy = FALSE, ...)
15 |
16 | \method{setdiff}{tbl_lazy}(x, y, copy = FALSE, ..., all = FALSE)
17 | }
18 | \arguments{
19 | \item{x, y}{A pair of lazy data frames backed by database queries.}
20 |
21 | \item{copy}{If \code{x} and \code{y} are not from the same data source,
22 | and \code{copy} is \code{TRUE}, then \code{y} will be copied into a
23 | temporary table in same database as \code{x}. \verb{*_join()} will automatically
24 | run \code{ANALYZE} on the created table in the hope that this will make
25 | you queries as efficient as possible by giving more data to the query
26 | planner.
27 |
28 | This allows you to join tables across srcs, but it's potentially expensive
29 | operation so you must opt into it.}
30 |
31 | \item{...}{Not currently used; provided for future extensions.}
32 |
33 | \item{all}{If \code{TRUE}, includes all matches in output, not just unique rows.}
34 | }
35 | \description{
36 | These are methods for the dplyr generics \code{dplyr::intersect()},
37 | \code{dplyr::union()}, and \code{dplyr::setdiff()}. They are translated to
38 | \code{INTERSECT}, \code{UNION}, and \code{EXCEPT} respectively.
39 | }
40 |
--------------------------------------------------------------------------------
/man/is_table_path.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/table-name.R
3 | \name{is_table_path}
4 | \alias{is_table_path}
5 | \alias{table_path_name}
6 | \alias{table_path_components}
7 | \alias{check_table_path}
8 | \alias{as_table_path}
9 | \title{Table paths}
10 | \usage{
11 | is_table_path(x)
12 |
13 | table_path_name(x, con)
14 |
15 | table_path_components(x, con)
16 |
17 | check_table_path(x, error_arg = caller_arg(x), error_call = caller_env())
18 |
19 | as_table_path(x, con, error_arg = caller_arg(x), error_call = caller_env())
20 | }
21 | \description{
22 | dbplyr standardises all the ways of referring to a table (i.e. a single
23 | string, a string wrapped in \code{I()}, a \code{\link[DBI:Id]{DBI::Id()}} and the results of
24 | \code{\link[=in_schema]{in_schema()}} and \code{\link[=in_catalog]{in_catalog()}}) into a table "path" of the form
25 | \code{table}, \code{schema.table}, or \code{catalog.schema.path}. A table path is
26 | always suitable for inlining into a query, so user input is quoted unless
27 | it is wrapped in \code{I()}.
28 |
29 | This is primarily for internal usage, but you may need to work with it if
30 | you're implementing a backend, and you need to compute with the table path,
31 | not just pass it on unchanged to some other dbplyr function.
32 | \itemize{
33 | \item \code{is_table_path()} returns \code{TRUE} if the object is a \code{table_path}.
34 | \item \code{as_table_path()} coerces known table identifiers to a \code{table_path}.
35 | \item \code{check_table_path()} throws an error if the object is not a \code{table_path}.
36 | \item \code{table_path_name()} returns the last component of the table path (i.e.
37 | the name of the table).
38 | \item \code{table_path_components()} returns a list containing the components of each
39 | table path.
40 | }
41 |
42 | A \code{table_path} object can technically be a vector of table paths, but
43 | you will never see this in table paths constructed from user inputs.
44 | }
45 | \keyword{internal}
46 |
--------------------------------------------------------------------------------
/man/lahman.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data-lahman.R
3 | \name{lahman}
4 | \alias{lahman}
5 | \alias{lahman_sqlite}
6 | \alias{lahman_postgres}
7 | \alias{lahman_mysql}
8 | \alias{copy_lahman}
9 | \alias{has_lahman}
10 | \alias{lahman_srcs}
11 | \title{Cache and retrieve an \code{src_sqlite} of the Lahman baseball database.}
12 | \usage{
13 | lahman_sqlite(path = NULL)
14 |
15 | lahman_postgres(dbname = "lahman", host = "localhost", ...)
16 |
17 | lahman_mysql(dbname = "lahman", ...)
18 |
19 | copy_lahman(con, ...)
20 |
21 | has_lahman(type, ...)
22 |
23 | lahman_srcs(..., quiet = NULL)
24 | }
25 | \arguments{
26 | \item{...}{Other arguments passed to \code{src} on first
27 | load. For MySQL and PostgreSQL, the defaults assume you have a local
28 | server with \code{lahman} database already created.
29 | For \code{lahman_srcs()}, character vector of names giving srcs to generate.}
30 |
31 | \item{type}{src type.}
32 |
33 | \item{quiet}{if \code{TRUE}, suppress messages about databases failing to
34 | connect.}
35 | }
36 | \description{
37 | This creates an interesting database using data from the Lahman baseball
38 | data source, provided by \href{http://seanlahman.com}{Sean Lahman}, and
39 | made easily available in R through the \pkg{Lahman} package by
40 | Michael Friendly, Dennis Murphy and Martin Monkman. See the documentation
41 | for that package for documentation of the individual tables.
42 | }
43 | \examples{
44 | # Connect to a local sqlite database, if already created
45 | \donttest{
46 | library(dplyr)
47 |
48 | if (has_lahman("sqlite")) {
49 | lahman_sqlite()
50 | batting <- tbl(lahman_sqlite(), "Batting")
51 | batting
52 | }
53 |
54 | # Connect to a local postgres database with lahman database, if available
55 | if (has_lahman("postgres")) {
56 | lahman_postgres()
57 | batting <- tbl(lahman_postgres(), "Batting")
58 | }
59 | }
60 | }
61 | \keyword{internal}
62 |
--------------------------------------------------------------------------------
/man/lazy_ops.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/lazy-ops.R
3 | \name{lazy_ops}
4 | \alias{lazy_ops}
5 | \alias{lazy_base_query}
6 | \alias{op_grps}
7 | \alias{op_vars}
8 | \alias{op_sort}
9 | \alias{op_frame}
10 | \title{Lazy operations}
11 | \usage{
12 | lazy_base_query(x, vars, class = character(), ...)
13 |
14 | op_grps(op)
15 |
16 | op_vars(op)
17 |
18 | op_sort(op)
19 |
20 | op_frame(op)
21 | }
22 | \description{
23 | This set of S3 classes describe the action of dplyr verbs. These are
24 | currently used for SQL sources to separate the description of operations
25 | in R from their computation in SQL. This API is very new so is likely
26 | to evolve in the future.
27 | }
28 | \details{
29 | \code{op_vars()} and \code{op_grps()} compute the variables and groups from
30 | a sequence of lazy operations. \code{op_sort()} and \code{op_frame()} tracks the
31 | order and frame for use in window functions.
32 | }
33 | \keyword{internal}
34 |
--------------------------------------------------------------------------------
/man/memdb_frame.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/memdb.R
3 | \name{memdb_frame}
4 | \alias{memdb_frame}
5 | \alias{tbl_memdb}
6 | \alias{src_memdb}
7 | \title{Create a database table in temporary in-memory database.}
8 | \usage{
9 | memdb_frame(..., .name = unique_table_name())
10 |
11 | tbl_memdb(df, name = deparse(substitute(df)))
12 |
13 | src_memdb()
14 | }
15 | \arguments{
16 | \item{...}{<\code{\link[rlang:dyn-dots]{dynamic-dots}}>
17 | A set of name-value pairs. These arguments are
18 | processed with \code{\link[rlang:defusing-advanced]{rlang::quos()}} and support unquote via \code{\link{!!}} and
19 | unquote-splice via \code{\link{!!!}}. Use \verb{:=} to create columns that start with a dot.
20 |
21 | Arguments are evaluated sequentially.
22 | You can refer to previously created elements directly or using the \link{.data}
23 | pronoun.
24 | To refer explicitly to objects in the calling environment, use \code{\link{!!}} or
25 | \link{.env}, e.g. \code{!!.data} or \code{.env$.data} for the special case of an object
26 | named \code{.data}.}
27 |
28 | \item{df}{Data frame to copy}
29 |
30 | \item{name, .name}{Name of table in database: defaults to a random name that's
31 | unlikely to conflict with an existing table.}
32 | }
33 | \description{
34 | \code{memdb_frame()} works like \code{\link[tibble:tibble]{tibble::tibble()}}, but instead of creating a new
35 | data frame in R, it creates a table in \code{\link[=src_memdb]{src_memdb()}}.
36 | }
37 | \examples{
38 | library(dplyr)
39 | df <- memdb_frame(x = runif(100), y = runif(100))
40 | df \%>\% arrange(x)
41 | df \%>\% arrange(x) \%>\% show_query()
42 |
43 | mtcars_db <- tbl_memdb(mtcars)
44 | mtcars_db \%>\% group_by(cyl) \%>\% summarise(n = n()) \%>\% show_query()
45 | }
46 |
--------------------------------------------------------------------------------
/man/named_commas.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/utils.R
3 | \name{named_commas}
4 | \alias{named_commas}
5 | \title{Provides comma-separated string out of the parameters}
6 | \usage{
7 | named_commas(x)
8 | }
9 | \description{
10 | Provides comma-separated string out of the parameters
11 | }
12 | \keyword{internal}
13 |
--------------------------------------------------------------------------------
/man/nycflights13.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/data-nycflights13.R
3 | \name{nycflights13}
4 | \alias{nycflights13}
5 | \alias{nycflights13_sqlite}
6 | \alias{nycflights13_postgres}
7 | \alias{has_nycflights13}
8 | \alias{copy_nycflights13}
9 | \title{Database versions of the nycflights13 data}
10 | \usage{
11 | nycflights13_sqlite(path = NULL)
12 |
13 | nycflights13_postgres(dbname = "nycflights13", ...)
14 |
15 | has_nycflights13(type = c("sqlite", "postgres"), ...)
16 |
17 | copy_nycflights13(con, ...)
18 | }
19 | \arguments{
20 | \item{path}{location of SQLite database file}
21 |
22 | \item{dbname, ...}{Arguments passed on to \code{\link[=src_postgres]{src_postgres()}}}
23 | }
24 | \description{
25 | These functions cache the data from the \code{nycflights13} database in
26 | a local database, for use in examples and vignettes. Indexes are created
27 | to making joining tables on natural keys efficient.
28 | }
29 | \keyword{internal}
30 |
--------------------------------------------------------------------------------
/man/pull.tbl_sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-pull.R
3 | \name{pull.tbl_sql}
4 | \alias{pull.tbl_sql}
5 | \title{Extract a single column}
6 | \usage{
7 | \method{pull}{tbl_sql}(.data, var = -1, name = NULL, ...)
8 | }
9 | \arguments{
10 | \item{.data}{A lazy data frame backed by a database query.}
11 |
12 | \item{var}{A variable specified as:
13 | \itemize{
14 | \item a literal variable name
15 | \item a positive integer, giving the position counting from the left
16 | \item a negative integer, giving the position counting from the right.
17 | }
18 |
19 | The default returns the last column (on the assumption that's the
20 | column you've created most recently).
21 |
22 | This argument is taken by expression and supports
23 | \link[rlang:topic-inject]{quasiquotation} (you can unquote column
24 | names and column locations).}
25 |
26 | \item{name}{An optional parameter that specifies the column to be used
27 | as names for a named vector. Specified in a similar manner as \code{var}.}
28 |
29 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
30 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
31 | order.}
32 | }
33 | \value{
34 | A vector of data.
35 | }
36 | \description{
37 | This is a method for the dplyr \code{\link[=pull]{pull()}} generic. It evaluates the query
38 | retrieving just the specified column.
39 | }
40 | \examples{
41 | library(dplyr, warn.conflicts = FALSE)
42 |
43 | db <- memdb_frame(x = 1:5, y = 5:1)
44 | db \%>\%
45 | mutate(z = x + y * 2) \%>\%
46 | pull()
47 | }
48 |
--------------------------------------------------------------------------------
/man/reexports.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/reexport.R
3 | \docType{import}
4 | \name{reexports}
5 | \alias{reexports}
6 | \alias{\%>\%}
7 | \title{Objects exported from other packages}
8 | \keyword{internal}
9 | \description{
10 | These objects are imported from other packages. Follow the links
11 | below to see their documentation.
12 |
13 | \describe{
14 | \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}}
15 | }}
16 |
17 |
--------------------------------------------------------------------------------
/man/replace_na.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-expand.R
3 | \name{replace_na.tbl_lazy}
4 | \alias{replace_na.tbl_lazy}
5 | \title{Replace NAs with specified values}
6 | \usage{
7 | \method{replace_na}{tbl_lazy}(data, replace = list(), ...)
8 | }
9 | \arguments{
10 | \item{data}{A pair of lazy data frame backed by database queries.}
11 |
12 | \item{replace}{A named list of values, with one value for each column that
13 | has NA values to be replaced.}
14 |
15 | \item{...}{Unused; included for compatibility with generic.}
16 | }
17 | \value{
18 | Another \code{tbl_lazy}. Use \code{\link[=show_query]{show_query()}} to see the generated
19 | query, and use \code{\link[=collect.tbl_sql]{collect()}} to execute the query
20 | and return data to R.
21 | }
22 | \description{
23 | This is a method for the \code{\link[tidyr:replace_na]{tidyr::replace_na()}} generic.
24 | }
25 | \examples{
26 | \dontshow{if (rlang::is_installed("tidyr", version = "1.0.0")) (if (getRversion() >= "3.4") withAutoprint else force)(\{ # examplesIf}
27 | df <- memdb_frame(x = c(1, 2, NA), y = c("a", NA, "b"))
28 | df \%>\% tidyr::replace_na(list(x = 0, y = "unknown"))
29 | \dontshow{\}) # examplesIf}
30 | }
31 |
--------------------------------------------------------------------------------
/man/select.tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-select.R
3 | \name{select.tbl_lazy}
4 | \alias{select.tbl_lazy}
5 | \alias{rename.tbl_lazy}
6 | \alias{rename_with.tbl_lazy}
7 | \alias{relocate.tbl_lazy}
8 | \title{Subset, rename, and reorder columns using their names}
9 | \usage{
10 | \method{select}{tbl_lazy}(.data, ...)
11 |
12 | \method{rename}{tbl_lazy}(.data, ...)
13 |
14 | \method{rename_with}{tbl_lazy}(.data, .fn, .cols = everything(), ...)
15 |
16 | \method{relocate}{tbl_lazy}(.data, ..., .before = NULL, .after = NULL)
17 | }
18 | \arguments{
19 | \item{.data}{A lazy data frame backed by a database query.}
20 |
21 | \item{...}{<\code{\link[rlang:args_data_masking]{data-masking}}> Variables, or
22 | functions of variables. Use \code{\link[dplyr:desc]{desc()}} to sort a variable in descending
23 | order.}
24 |
25 | \item{.fn}{A function used to transform the selected \code{.cols}. Should
26 | return a character vector the same length as the input.}
27 |
28 | \item{.cols}{<\code{\link[dplyr:dplyr_tidy_select]{tidy-select}}> Columns to rename;
29 | defaults to all columns.}
30 |
31 | \item{.before, .after}{<\code{\link[dplyr:dplyr_tidy_select]{tidy-select}}> Destination of
32 | columns selected by \code{...}. Supplying neither will move columns to the
33 | left-hand side; specifying both is an error.}
34 | }
35 | \description{
36 | These are methods for the dplyr \code{\link[=select]{select()}}, \code{\link[=rename]{rename()}}, and \code{\link[=relocate]{relocate()}}
37 | generics. They generate the \code{SELECT} clause of the SQL query.
38 |
39 | These functions do not support predicate functions, i.e. you can
40 | not use \code{where(is.numeric)} to select all numeric variables.
41 | }
42 | \examples{
43 | library(dplyr, warn.conflicts = FALSE)
44 |
45 | db <- memdb_frame(x = 1, y = 2, z = 3)
46 | db \%>\% select(-y) \%>\% show_query()
47 | db \%>\% relocate(z) \%>\% show_query()
48 | db \%>\% rename(first = x, last = z) \%>\% show_query()
49 | }
50 |
--------------------------------------------------------------------------------
/man/simulate_dbi.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/simulate.R
3 | \name{simulate_dbi}
4 | \alias{simulate_dbi}
5 | \title{Simulate database connections}
6 | \usage{
7 | simulate_dbi(class = character(), ...)
8 | }
9 | \description{
10 | These functions generate S3 objects that have been designed to simulate
11 | the action of a database connection, without actually having the database
12 | available. Obviously, this simulation can only be incomplete, but most
13 | importantly it allows us to simulate SQL generation for any database without
14 | actually connecting to it.
15 | }
16 | \details{
17 | Simulated SQL always quotes identifies with \code{`x`}, and strings with
18 | \code{'x'}.
19 | }
20 | \keyword{internal}
21 |
--------------------------------------------------------------------------------
/man/sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sql.R
3 | \name{sql}
4 | \alias{sql}
5 | \alias{is.sql}
6 | \alias{as.sql}
7 | \title{SQL escaping.}
8 | \usage{
9 | sql(...)
10 |
11 | is.sql(x)
12 |
13 | as.sql(x, con)
14 | }
15 | \arguments{
16 | \item{...}{Character vectors that will be combined into a single SQL
17 | expression.}
18 |
19 | \item{x}{Object to coerce}
20 |
21 | \item{con}{Needed when \code{x} is directly supplied from the user so that
22 | schema specifications can be quoted using the correct identifiers.}
23 | }
24 | \description{
25 | These functions are critical when writing functions that translate R
26 | functions to sql functions. Typically a conversion function should escape
27 | all its inputs and return an sql object.
28 | }
29 |
--------------------------------------------------------------------------------
/man/sql_expr.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/sql-expr.R
3 | \name{sql_expr}
4 | \alias{sql_expr}
5 | \alias{sql_call2}
6 | \title{Generate SQL from R expressions}
7 | \usage{
8 | sql_expr(x, con = sql_current_con())
9 |
10 | sql_call2(.fn, ..., con = sql_current_con())
11 | }
12 | \arguments{
13 | \item{x}{A quasiquoted expression}
14 |
15 | \item{con}{Connection to use for escaping. Will be set automatically when
16 | called from a function translation.}
17 |
18 | \item{.fn}{Function name (as string, call, or symbol)}
19 |
20 | \item{...}{Arguments to function}
21 | }
22 | \description{
23 | Low-level building block for generating SQL from R expressions.
24 | Strings are escaped; names become bare SQL identifiers. User infix
25 | functions have \verb{\%} stripped.
26 | }
27 | \details{
28 | Using \code{sql_expr()} in package will require use of \code{\link[=globalVariables]{globalVariables()}}
29 | to avoid \verb{R CMD check} NOTES. This is a small amount of additional pain,
30 | which I think is worthwhile because it leads to more readable translation
31 | code.
32 | }
33 | \examples{
34 | con <- simulate_dbi() # not necessary when writing translations
35 |
36 | sql_expr(f(x + 1), con = con)
37 | sql_expr(f("x", "y"), con = con)
38 | sql_expr(f(x, y), con = con)
39 |
40 | x <- ident("x")
41 | sql_expr(f(!!x, y), con = con)
42 |
43 | sql_expr(cast("x" \%as\% DECIMAL), con = con)
44 | sql_expr(round(x) \%::\% numeric, con = con)
45 |
46 | sql_call2("+", quote(x), 1, con = con)
47 | sql_call2("+", "x", 1, con = con)
48 | }
49 | \keyword{internal}
50 |
--------------------------------------------------------------------------------
/man/sql_options.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/db.R
3 | \name{sql_options}
4 | \alias{sql_options}
5 | \title{Options for generating SQL}
6 | \usage{
7 | sql_options(cte = FALSE, use_star = TRUE, qualify_all_columns = FALSE)
8 | }
9 | \arguments{
10 | \item{cte}{If \code{FALSE}, the default, subqueries are used. If \code{TRUE} common
11 | table expressions are used.}
12 |
13 | \item{use_star}{If \code{TRUE}, the default, \code{*} is used to select all columns of
14 | a table. If \code{FALSE} all columns are explicitly selected.}
15 |
16 | \item{qualify_all_columns}{If \code{FALSE}, the default, columns are only
17 | qualified with the table they come from if the same column name appears in
18 | multiple tables.}
19 | }
20 | \value{
21 | A object.
22 | }
23 | \description{
24 | Options for generating SQL
25 | }
26 | \examples{
27 | library(dplyr, warn.conflicts = FALSE)
28 | lf1 <- lazy_frame(key = 1, a = 1, b = 2)
29 | lf2 <- lazy_frame(key = 1, a = 1, c = 3)
30 |
31 | result <- left_join(lf1, lf2, by = "key") \%>\%
32 | filter(c >= 3)
33 |
34 | show_query(result)
35 | sql_options <- sql_options(cte = TRUE, qualify_all_columns = TRUE)
36 | show_query(result, sql_options = sql_options)
37 | }
38 |
--------------------------------------------------------------------------------
/man/sql_quote.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/escape.R
3 | \name{sql_quote}
4 | \alias{sql_quote}
5 | \title{Helper function for quoting sql elements.}
6 | \usage{
7 | sql_quote(x, quote)
8 | }
9 | \arguments{
10 | \item{x}{Character vector to escape.}
11 |
12 | \item{quote}{Single quoting character.}
13 | }
14 | \description{
15 | If the quote character is present in the string, it will be doubled.
16 | \code{NA}s will be replaced with NULL.
17 | }
18 | \examples{
19 | sql_quote("abc", "'")
20 | sql_quote("I've had a good day", "'")
21 | sql_quote(c("abc", NA), "'")
22 | }
23 | \keyword{internal}
24 |
--------------------------------------------------------------------------------
/man/src_dbi.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/src_dbi.R
3 | \name{src_dbi}
4 | \alias{src_dbi}
5 | \title{Database src}
6 | \usage{
7 | src_dbi(con, auto_disconnect = FALSE)
8 | }
9 | \arguments{
10 | \item{con}{An object that inherits from \link[DBI:DBIConnection-class]{DBI::DBIConnection},
11 | typically generated by \link[DBI:dbConnect]{DBI::dbConnect}}
12 |
13 | \item{auto_disconnect}{Should the connection be automatically closed when
14 | the src is deleted? Set to \code{TRUE} if you initialize the connection
15 | the call to \code{src_dbi()}. Pass \code{NA} to auto-disconnect but print a message
16 | when this happens.}
17 | }
18 | \value{
19 | An S3 object with class \code{src_dbi}, \code{src_sql}, \code{src}.
20 | }
21 | \description{
22 | \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#superseded}{\figure{lifecycle-superseded.svg}{options: alt='[Superseded]'}}}{\strong{[Superseded]}}
23 |
24 | Since can generate a \code{tbl()} directly from a DBI connection we no longer
25 | recommend using \code{src_dbi()}.
26 | }
27 | \keyword{internal}
28 |
--------------------------------------------------------------------------------
/man/src_sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/src-sql.R
3 | \name{src_sql}
4 | \alias{src_sql}
5 | \title{Create a "sql src" object}
6 | \usage{
7 | src_sql(subclass, con, ...)
8 | }
9 | \arguments{
10 | \item{subclass}{name of subclass. "src_sql" is an abstract base class, so you
11 | must supply this value. \code{src_} is automatically prepended to the
12 | class name}
13 |
14 | \item{con}{the connection object}
15 |
16 | \item{...}{fields used by object}
17 | }
18 | \description{
19 | Deprecated: please use directly use a \code{DBIConnection} object instead.
20 | }
21 | \keyword{internal}
22 |
--------------------------------------------------------------------------------
/man/tbl_lazy.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tbl-lazy.R
3 | \name{tbl_lazy}
4 | \alias{tbl_lazy}
5 | \alias{lazy_frame}
6 | \title{Create a local lazy tibble}
7 | \usage{
8 | tbl_lazy(df, con = NULL, ..., name = "df")
9 |
10 | lazy_frame(..., con = NULL, .name = "df")
11 | }
12 | \description{
13 | These functions are useful for testing SQL generation without having to
14 | have an active database connection. See \code{\link[=simulate_dbi]{simulate_dbi()}} for a list
15 | available database simulations.
16 | }
17 | \examples{
18 | library(dplyr)
19 | df <- data.frame(x = 1, y = 2)
20 |
21 | df_sqlite <- tbl_lazy(df, con = simulate_sqlite())
22 | df_sqlite \%>\% summarise(x = sd(x, na.rm = TRUE)) \%>\% show_query()
23 | }
24 | \keyword{internal}
25 |
--------------------------------------------------------------------------------
/man/tbl_sql.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/tbl-sql.R
3 | \name{tbl_sql}
4 | \alias{tbl_sql}
5 | \title{Create an SQL tbl (abstract)}
6 | \usage{
7 | tbl_sql(subclass, src, from, ..., vars = NULL, check_from = deprecated())
8 | }
9 | \arguments{
10 | \item{subclass}{name of subclass}
11 |
12 | \item{...}{needed for agreement with generic. Not otherwise used.}
13 |
14 | \item{vars}{Provide column names as a character vector
15 | to avoid retrieving them from the database.
16 | Mainly useful for better performance when creating
17 | multiple \code{tbl} objects.}
18 |
19 | \item{check_from}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}}}
20 | }
21 | \description{
22 | Generally, you should no longer need to provide a custom \code{tbl()}
23 | method.
24 | The default \code{tbl.DBIConnect} method should work in most cases.
25 | }
26 | \keyword{internal}
27 |
--------------------------------------------------------------------------------
/man/testing.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/test-frame.R
3 | \name{testing}
4 | \alias{testing}
5 | \alias{test_register_src}
6 | \alias{test_register_con}
7 | \alias{src_test}
8 | \alias{test_load}
9 | \alias{test_frame}
10 | \title{Infrastructure for testing dplyr}
11 | \usage{
12 | test_register_src(name, src)
13 |
14 | test_register_con(name, ...)
15 |
16 | src_test(name)
17 |
18 | test_load(
19 | df,
20 | name = unique_table_name(),
21 | srcs = test_srcs$get(),
22 | ignore = character()
23 | )
24 |
25 | test_frame(..., srcs = test_srcs$get(), ignore = character())
26 | }
27 | \description{
28 | Register testing sources, then use \code{test_load()} to load an existing
29 | data frame into each source. To create a new table in each source,
30 | use \code{test_frame()}.
31 | }
32 | \examples{
33 | \dontrun{
34 | test_register_src("sqlite", {
35 | DBI::dbConnect(RSQLite::SQLite(), ":memory:", create = TRUE)
36 | })
37 |
38 | test_frame(x = 1:3, y = 3:1)
39 | test_load(mtcars)
40 | }
41 | }
42 | \keyword{internal}
43 |
--------------------------------------------------------------------------------
/man/win_over.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/translate-sql-window.R, R/backend-teradata.R
3 | \name{win_over}
4 | \alias{win_over}
5 | \alias{win_rank}
6 | \alias{win_aggregate}
7 | \alias{win_aggregate_2}
8 | \alias{win_recycled}
9 | \alias{win_cumulative}
10 | \alias{win_absent}
11 | \alias{win_current_group}
12 | \alias{win_current_order}
13 | \alias{win_current_frame}
14 | \alias{win_rank_tdata}
15 | \title{Generate SQL expression for window functions}
16 | \usage{
17 | win_over(
18 | expr,
19 | partition = NULL,
20 | order = NULL,
21 | frame = NULL,
22 | con = sql_current_con()
23 | )
24 |
25 | win_rank(f, empty_order = FALSE)
26 |
27 | win_aggregate(f)
28 |
29 | win_aggregate_2(f)
30 |
31 | win_cumulative(f)
32 |
33 | win_absent(f)
34 |
35 | win_current_group()
36 |
37 | win_current_order()
38 |
39 | win_current_frame()
40 |
41 | win_rank_tdata(f)
42 | }
43 | \arguments{
44 | \item{expr}{The window expression}
45 |
46 | \item{partition}{Variables to partition over}
47 |
48 | \item{order}{Variables to order by}
49 |
50 | \item{frame}{A numeric vector of length two defining the frame.}
51 |
52 | \item{f}{The name of an sql function as a string}
53 |
54 | \item{empty_order}{A logical value indicating whether to order by NULL if \code{order} is not specified}
55 | }
56 | \description{
57 | \code{win_over()} makes it easy to generate the window function specification.
58 | \code{win_absent()}, \code{win_rank()}, \code{win_aggregate()}, and \code{win_cumulative()}
59 | provide helpers for constructing common types of window functions.
60 | \code{win_current_group()} and \code{win_current_order()} allow you to access
61 | the grouping and order context set up by \code{\link[=group_by]{group_by()}} and \code{\link[=arrange]{arrange()}}.
62 | }
63 | \examples{
64 | con <- simulate_dbi()
65 |
66 | win_over(sql("avg(x)"), con = con)
67 | win_over(sql("avg(x)"), "y", con = con)
68 | win_over(sql("avg(x)"), order = "y", con = con)
69 | win_over(sql("avg(x)"), order = c("x", "y"), con = con)
70 | win_over(sql("avg(x)"), frame = c(-Inf, 0), order = "y", con = con)
71 | }
72 | \keyword{internal}
73 |
--------------------------------------------------------------------------------
/man/window_order.Rd:
--------------------------------------------------------------------------------
1 | % Generated by roxygen2: do not edit by hand
2 | % Please edit documentation in R/verb-window.R
3 | \name{window_order}
4 | \alias{window_order}
5 | \alias{window_frame}
6 | \title{Override window order and frame}
7 | \usage{
8 | window_order(.data, ...)
9 |
10 | window_frame(.data, from = -Inf, to = Inf)
11 | }
12 | \arguments{
13 | \item{.data}{A lazy data frame backed by a database query.}
14 |
15 | \item{...}{Variables to order by}
16 |
17 | \item{from, to}{Bounds of the frame.}
18 | }
19 | \description{
20 | These allow you to override the \verb{PARTITION BY} and \verb{ORDER BY} clauses
21 | of window functions generated by grouped mutates.
22 | }
23 | \examples{
24 | library(dplyr, warn.conflicts = FALSE)
25 |
26 | db <- memdb_frame(g = rep(1:2, each = 5), y = runif(10), z = 1:10)
27 | db \%>\%
28 | window_order(y) \%>\%
29 | mutate(z = cumsum(y)) \%>\%
30 | show_query()
31 |
32 | db \%>\%
33 | group_by(g) \%>\%
34 | window_frame(-3, 0) \%>\%
35 | window_order(z) \%>\%
36 | mutate(z = sum(y)) \%>\%
37 | show_query()
38 | }
39 |
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon-76x76.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon-76x76.png
--------------------------------------------------------------------------------
/pkgdown/favicon/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/apple-touch-icon.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/favicon-16x16.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/favicon-32x32.png
--------------------------------------------------------------------------------
/pkgdown/favicon/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/pkgdown/favicon/favicon.ico
--------------------------------------------------------------------------------
/revdep/.gitignore:
--------------------------------------------------------------------------------
1 | checks
2 | library
3 | checks.noindex
4 | library.noindex
5 | data.sqlite
6 | *.html
7 | cloud.noindex
8 |
--------------------------------------------------------------------------------
/revdep/README.md:
--------------------------------------------------------------------------------
1 | # Revdeps
2 |
3 | ## Failed to check (11)
4 |
5 | |package |version |error |warning |note |
6 | |:------------------|:-------|:-----|:-------|:----|
7 | |BiocFileCache |? | | | |
8 | |BiocOncoTK |? | | | |
9 | |CompoundDb |? | | | |
10 | |CuratedAtlasQueryR |? | | | |
11 | |GEOmetadb |? | | | |
12 | |grasp2db |? | | | |
13 | |msPurity |? | | | |
14 | |NoRCE |? | | | |
15 | |Organism.dplyr |? | | | |
16 | |SQLDataFrame |? | | | |
17 | |synaptome.db |? | | | |
18 |
19 | ## New problems (8)
20 |
21 | |package |version |error |warning |note |
22 | |:-------------------|:-------|:--------|:-------|:----|
23 | |[Andromeda](problems.md#andromeda)|0.6.5 |__+3__ |-1 | |
24 | |[CDMConnector](problems.md#cdmconnector)|1.3.0 |__+2__ | |1 |
25 | |[CohortSurvival](problems.md#cohortsurvival)|0.3.0 |__+2__ | | |
26 | |[diseasystore](problems.md#diseasystore)|0.1.1 |__+1__ | | |
27 | |[DrugUtilisation](problems.md#drugutilisation)|0.5.2 |__+2__ | | |
28 | |[IncidencePrevalence](problems.md#incidenceprevalence)|0.7.1 |__+2__ | | |
29 | |[PatientProfiles](problems.md#patientprofiles)|0.6.2 |1 __+1__ | | |
30 | |[SCDB](problems.md#scdb)|0.3 |__+3__ | | |
31 |
32 |
--------------------------------------------------------------------------------
/revdep/check.R:
--------------------------------------------------------------------------------
1 | library("devtools")
2 |
3 | install.packages("RPostgreSQL", lib = getOption("devtools.revdep.libpath"))
4 | install.packages("bit64", lib = getOption("devtools.revdep.libpath"))
5 | install.packages("rJava", lib = getOption("devtools.revdep.libpath"))
6 |
7 | revdep_check()
8 | revdep_check_save_summary()
9 | revdep_check_print_problems()
10 |
--------------------------------------------------------------------------------
/revdep/cran.md:
--------------------------------------------------------------------------------
1 | ## revdepcheck results
2 |
3 | We checked 112 reverse dependencies (101 from CRAN + 11 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package.
4 |
5 | * We saw 8 new problems
6 | * We failed to check 0 packages
7 |
8 | Issues with CRAN packages are summarised below.
9 |
10 | ### New problems
11 | (This reports the first line of each new failure)
12 |
13 | * Andromeda
14 | checking examples ... ERROR
15 | checking tests ... ERROR
16 | checking re-building of vignette outputs ... ERROR
17 |
18 | * CDMConnector
19 | checking tests ... ERROR
20 | checking re-building of vignette outputs ... ERROR
21 |
22 | * CohortSurvival
23 | checking tests ... ERROR
24 | checking re-building of vignette outputs ... ERROR
25 |
26 | * diseasystore
27 | checking tests ... ERROR
28 |
29 | * DrugUtilisation
30 | checking tests ... ERROR
31 | checking re-building of vignette outputs ... ERROR
32 |
33 | * IncidencePrevalence
34 | checking tests ... ERROR
35 | checking re-building of vignette outputs ... ERROR
36 |
37 | * PatientProfiles
38 | checking re-building of vignette outputs ... ERROR
39 |
40 | * SCDB
41 | checking examples ... ERROR
42 | checking tests ... ERROR
43 | checking re-building of vignette outputs ... ERROR
44 |
45 |
--------------------------------------------------------------------------------
/revdep/email.yml:
--------------------------------------------------------------------------------
1 | release_date: April 22
2 | rel_release_date: 1 week
3 | my_news_url: https://github.com/tidyverse/dbplyr/blob/master/NEWS.md#dbplyr-development-version
4 | release_version: 1.4.0
5 | release_details: >
6 | This is a major release with a bunch of improvements to SQL generation,
7 | so I'd really appreciate your help checking that I haven't broken
8 | any existing translations.
9 |
--------------------------------------------------------------------------------
/tests/testthat.R:
--------------------------------------------------------------------------------
1 | library(testthat)
2 | library(dbplyr)
3 |
4 | test_check("dbplyr")
5 |
--------------------------------------------------------------------------------
/tests/testthat/.gitignore:
--------------------------------------------------------------------------------
1 | *.sqlite3
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-access.md:
--------------------------------------------------------------------------------
1 | # custom scalar translated correctly
2 |
3 | Code
4 | test_translate_sql(paste(x, collapse = "-"))
5 | Condition
6 | Error in `check_collapse()`:
7 | ! `collapse` not supported in DB translation of `paste()`.
8 | i Please use `str_flatten()` instead.
9 |
10 | # queries translate correctly
11 |
12 | Code
13 | mf %>% head()
14 | Output
15 |
16 | SELECT TOP 6 `df`.*
17 | FROM `df`
18 |
19 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-hana.md:
--------------------------------------------------------------------------------
1 | # custom string translations
2 |
3 | Code
4 | test_translate_sql(paste0("a", "b"))
5 | Output
6 | 'a' || 'b'
7 |
8 | ---
9 |
10 | Code
11 | test_translate_sql(paste("a", "b"))
12 | Output
13 | 'a' || ' ' || 'b'
14 |
15 | ---
16 |
17 | Code
18 | test_translate_sql(substr(x, 2, 4))
19 | Output
20 | SUBSTRING(`x`, 2, 3)
21 |
22 | ---
23 |
24 | Code
25 | test_translate_sql(substring(x, 2, 4))
26 | Output
27 | SUBSTRING(`x`, 2, 3)
28 |
29 | ---
30 |
31 | Code
32 | test_translate_sql(str_sub(x, 2, -2))
33 | Output
34 | SUBSTRING(`x`, 2, LENGTH(`x`) - 2)
35 |
36 | # copy_inline uses UNION ALL
37 |
38 | Code
39 | copy_inline(con, y %>% slice(0)) %>% remote_query()
40 | Output
41 | SELECT CAST(NULL AS INTEGER) AS `id`, CAST(NULL AS VARCHAR) AS `arr`
42 | FROM `DUMMY`
43 | WHERE (0 = 1)
44 | Code
45 | copy_inline(con, y) %>% remote_query()
46 | Output
47 | SELECT CAST(`id` AS INTEGER) AS `id`, CAST(`arr` AS VARCHAR) AS `arr`
48 | FROM (
49 | SELECT NULL AS `id`, NULL AS `arr`
50 | FROM `DUMMY`
51 | WHERE (0 = 1)
52 |
53 | UNION ALL
54 |
55 | SELECT 1, '{1,2,3}' FROM DUMMY
56 | ) AS `values_table`
57 | Code
58 | copy_inline(con, y %>% slice(0), types = types) %>% remote_query()
59 | Output
60 | SELECT CAST(NULL AS bigint) AS `id`, CAST(NULL AS integer[]) AS `arr`
61 | FROM `DUMMY`
62 | WHERE (0 = 1)
63 | Code
64 | copy_inline(con, y, types = types) %>% remote_query()
65 | Output
66 | SELECT CAST(`id` AS bigint) AS `id`, CAST(`arr` AS integer[]) AS `arr`
67 | FROM (
68 | SELECT NULL AS `id`, NULL AS `arr`
69 | FROM `DUMMY`
70 | WHERE (0 = 1)
71 |
72 | UNION ALL
73 |
74 | SELECT 1, '{1,2,3}' FROM DUMMY
75 | ) AS `values_table`
76 |
77 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-hive.md:
--------------------------------------------------------------------------------
1 | # generates custom sql
2 |
3 | Code
4 | sql_table_analyze(con, in_schema("schema", "tbl"))
5 | Output
6 | ANALYZE TABLE `schema`.`tbl` COMPUTE STATISTICS
7 |
8 | ---
9 |
10 | Code
11 | union_all(lf, lf)
12 | Output
13 |
14 | SELECT *
15 | FROM `df`
16 |
17 | UNION ALL
18 |
19 | SELECT *
20 | FROM `df`
21 |
22 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-impala.md:
--------------------------------------------------------------------------------
1 | # generates custom sql
2 |
3 | Code
4 | sql_table_analyze(con, in_schema("schema", "tbl"))
5 | Output
6 | COMPUTE STATS `schema`.`tbl`
7 |
8 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-snowflake.md:
--------------------------------------------------------------------------------
1 | # pasting translated correctly
2 |
3 | Code
4 | test_translate_sql(paste0(x, collapse = ""))
5 | Condition
6 | Error in `check_collapse()`:
7 | ! `collapse` not supported in DB translation of `paste()`.
8 | i Please use `str_flatten()` instead.
9 |
10 | # pmin() and pmax() respect na.rm
11 |
12 | Code
13 | test_translate_sql(pmin(x, y, z, na.rm = TRUE))
14 | Output
15 | COALESCE(IFF(COALESCE(IFF(`x` <= `y`, `x`, `y`), `x`, `y`) <= `z`, COALESCE(IFF(`x` <= `y`, `x`, `y`), `x`, `y`), `z`), COALESCE(IFF(`x` <= `y`, `x`, `y`), `x`, `y`), `z`)
16 |
17 | ---
18 |
19 | Code
20 | test_translate_sql(pmax(x, y, z, na.rm = TRUE))
21 | Output
22 | COALESCE(IFF(COALESCE(IFF(`x` >= `y`, `x`, `y`), `x`, `y`) >= `z`, COALESCE(IFF(`x` >= `y`, `x`, `y`), `x`, `y`), `z`), COALESCE(IFF(`x` >= `y`, `x`, `y`), `x`, `y`), `z`)
23 |
24 | # row_number() with and without group_by() and arrange(): unordered defaults to Ordering by NULL (per empty_order)
25 |
26 | Code
27 | mf %>% mutate(rown = row_number())
28 | Output
29 |
30 | SELECT `df`.*, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS `rown`
31 | FROM `df`
32 |
33 | ---
34 |
35 | Code
36 | mf %>% group_by(y) %>% mutate(rown = row_number())
37 | Output
38 |
39 | SELECT
40 | `df`.*,
41 | ROW_NUMBER() OVER (PARTITION BY `y` ORDER BY (SELECT NULL)) AS `rown`
42 | FROM `df`
43 |
44 | ---
45 |
46 | Code
47 | mf %>% arrange(y) %>% mutate(rown = row_number())
48 | Output
49 |
50 | SELECT `df`.*, ROW_NUMBER() OVER (ORDER BY `y`) AS `rown`
51 | FROM `df`
52 | ORDER BY `y`
53 |
54 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-spark-sql.md:
--------------------------------------------------------------------------------
1 | # custom clock functions translated correctly
2 |
3 | Code
4 | test_translate_sql(date_count_between(date_column_1, date_column_2, "year"))
5 | Condition
6 | Error in `date_count_between()`:
7 | ! `precision = "year"` isn't supported on database backends.
8 | i It must be "day" instead.
9 |
10 | ---
11 |
12 | Code
13 | test_translate_sql(date_count_between(date_column_1, date_column_2, "day", n = 5))
14 | Condition
15 | Error in `date_count_between()`:
16 | ! `n = 5` isn't supported on database backends.
17 | i It must be 1 instead.
18 |
19 | # difftime is translated correctly
20 |
21 | Code
22 | test_translate_sql(difftime(start_date, end_date, units = "auto"))
23 | Condition
24 | Error in `difftime()`:
25 | ! `units = "auto"` isn't supported on database backends.
26 | i It must be "days" instead.
27 |
28 | ---
29 |
30 | Code
31 | test_translate_sql(difftime(start_date, end_date, tz = "UTC", units = "days"))
32 | Condition
33 | Error in `difftime()`:
34 | ! Argument `tz` isn't supported on database backends.
35 |
36 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-sqlite.md:
--------------------------------------------------------------------------------
1 | # custom SQL translation
2 |
3 | Code
4 | left_join(lf, lf, by = "x", na_matches = "na")
5 | Output
6 |
7 | SELECT `df_LHS`.`x` AS `x`
8 | FROM `df` AS `df_LHS`
9 | LEFT JOIN `df` AS `df_RHS`
10 | ON (`df_LHS`.`x` IS `df_RHS`.`x`)
11 |
12 | ---
13 |
14 | Code
15 | test_translate_sql(runif(n()))
16 | Output
17 | (0.5 + RANDOM() / 18446744073709551616.0)
18 |
19 | # case_when translates correctly to ELSE when TRUE ~ is used
20 |
21 | Code
22 | test_translate_sql(case_when(x == 1L ~ "yes", x == 0L ~ "no", TRUE ~
23 | "undefined"), con = simulate_sqlite())
24 | Output
25 | CASE WHEN (`x` = 1) THEN 'yes' WHEN (`x` = 0) THEN 'no' ELSE 'undefined' END
26 |
27 | # can explain a query
28 |
29 | Code
30 | db %>% filter(x > 2) %>% explain()
31 | Output
32 |
33 | SELECT `test`.*
34 | FROM `test`
35 | WHERE (`x` > 2.0)
36 |
37 |
38 | id parent notused detail
39 | 1 2 0 35 SEARCH test USING COVERING INDEX test_x (x>?)
40 |
41 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/backend-teradata.md:
--------------------------------------------------------------------------------
1 | # generates custom sql
2 |
3 | Code
4 | sql_table_analyze(con, in_schema("schema", "tbl"))
5 | Output
6 | COLLECT STATISTICS `schema`.`tbl`
7 |
8 | # head translated to TOP
9 |
10 | Code
11 | mf %>% head() %>% sql_render()
12 | Output
13 | SELECT TOP 6 `df`.*
14 | FROM `df`
15 |
16 | # lead, lag work
17 |
18 | Code
19 | mf %>% group_by(y) %>% mutate(val2 = lead(x, order_by = x)) %>% sql_render()
20 | Output
21 | SELECT `df`.*, LEAD(`x`, 1, NULL) OVER (PARTITION BY `y` ORDER BY `x`) AS `val2`
22 | FROM `df`
23 |
24 | ---
25 |
26 | Code
27 | mf %>% group_by(y) %>% mutate(val2 = lag(x, order_by = x)) %>% sql_render()
28 | Output
29 | SELECT `df`.*, LAG(`x`, 1, NULL) OVER (PARTITION BY `y` ORDER BY `x`) AS `val2`
30 | FROM `df`
31 |
32 | # weighted.mean
33 |
34 | Code
35 | mf %>% summarise(wt_mean = weighted.mean(x, y))
36 | Output
37 |
38 | SELECT SUM((`x` * `y`)) / SUM(`y`) OVER () AS `wt_mean`
39 | FROM `df`
40 |
41 | # row_number() with and without group_by() and arrange(): unordered defaults to Ordering by NULL (per empty_order)
42 |
43 | Code
44 | mf %>% mutate(rown = row_number())
45 | Output
46 |
47 | SELECT `df`.*, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS `rown`
48 | FROM `df`
49 |
50 | ---
51 |
52 | Code
53 | mf %>% group_by(y) %>% mutate(rown = row_number())
54 | Output
55 |
56 | SELECT
57 | `df`.*,
58 | ROW_NUMBER() OVER (PARTITION BY `y` ORDER BY (SELECT NULL)) AS `rown`
59 | FROM `df`
60 |
61 | ---
62 |
63 | Code
64 | mf %>% arrange(y) %>% mutate(rown = row_number())
65 | Output
66 |
67 | SELECT `df`.*, ROW_NUMBER() OVER (ORDER BY `y`) AS `rown`
68 | FROM `df`
69 | ORDER BY `y`
70 |
71 | # head after distinct() produces subquery
72 |
73 | Code
74 | lf %>% distinct() %>% head()
75 | Output
76 |
77 | SELECT TOP 6 `q01`.*
78 | FROM (
79 | SELECT DISTINCT `df`.*
80 | FROM `df`
81 | ) AS `q01`
82 |
83 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/build-sql.md:
--------------------------------------------------------------------------------
1 | # build_sql() requires connection
2 |
3 | Code
4 | build_sql("SELECT * FROM ", x)
5 | Condition
6 | Error in `build_sql()`:
7 | ! `con` must not be NULL.
8 |
9 | # glue_sql() checks size
10 |
11 | Code
12 | glue_sql2("{.col x}", .con = con)
13 | Condition
14 | Error in `.transformer()`:
15 | ! `value` must have size 1, not 2.
16 | Code
17 | glue_sql2("{.col character()}", .con = con)
18 | Condition
19 | Error in `.transformer()`:
20 | ! `value` must have size 1, not 0.
21 |
22 | # glue_sql() can collapse
23 |
24 | Code
25 | glue_sql2("{.tbl x*}", .con = con)
26 | Condition
27 | Error in `glue_check_collapse()`:
28 | ! Collapsing is only allowed for "col" and "val", not for "tbl".
29 | Code
30 | glue_sql2("{.name x*}", .con = con)
31 | Condition
32 | Error in `glue_check_collapse()`:
33 | ! Collapsing is only allowed for "col" and "val", not for "name".
34 | Code
35 | glue_sql2("{.from x*}", .con = con)
36 | Condition
37 | Error in `glue_check_collapse()`:
38 | ! Collapsing is only allowed for "col" and "val", not for "from".
39 |
40 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/db-io.md:
--------------------------------------------------------------------------------
1 | # db_copy_to() wraps DBI errors
2 |
3 | Code
4 | (expect_error(db_copy_to(con = con, table = "tmp2", values = data.frame(x = c(1,
5 | 1)), unique_indexes = list("x"))))
6 | Output
7 |
8 | Error in `db_copy_to()`:
9 | ! Can't copy data to table `tmp2`.
10 | Caused by error in `db_create_index.DBIConnection()`:
11 | ! Can't create index on table `tmp2`.
12 | i Using SQL: CREATE UNIQUE INDEX `tmp2_x` ON `tmp2` (`x`)
13 | Caused by error:
14 | ! dummy DBI error
15 |
16 | # db_copy_to() can overwrite a table
17 |
18 | Code
19 | (expect_error(db_copy_to(con = con, table = "tmp", values = data.frame(x = c(1,
20 | 1)))))
21 | Output
22 |
23 | Error in `db_copy_to()`:
24 | ! Can't copy data to table `tmp`.
25 | Caused by error in `dplyr::db_write_table()`:
26 | ! Can't write table table `tmp`.
27 | Caused by error:
28 | ! dummy DBI error
29 |
30 | # db_save_query() can overwrite a table
31 |
32 | Code
33 | (expect_error(db_save_query(con = con, sql = "SELECT 2 FROM tmp", name = "tmp"))
34 | )
35 | Output
36 |
37 | Error in `db_save_query()`:
38 | ! Can't save query to table `tmp`.
39 | i Using SQL: CREATE TEMPORARY TABLE `tmp` AS `SELECT 2 FROM tmp`
40 | Caused by error:
41 | ! dummy DBI error
42 |
43 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/db-sql.md:
--------------------------------------------------------------------------------
1 | # 2nd edition uses sql methods
2 |
3 | Code
4 | expect_error(dbplyr_analyze(con), "db_method")
5 | Condition
6 | Warning:
7 | uses an old dbplyr interface
8 | i Please install a newer version of the package or contact the maintainer
9 | This warning is displayed once every 8 hours.
10 |
11 | # handles DBI error
12 |
13 | Code
14 | (expect_error(db_analyze(con, "tbl")))
15 | Output
16 |
17 | Error in `db_analyze()`:
18 | ! Can't analyze table tbl.
19 | i Using SQL: ANALYZE `tbl`
20 | Caused by error:
21 | ! dummy DBI error
22 | Code
23 | (expect_error(db_create_index(con, "tbl", "col")))
24 | Output
25 |
26 | Error in `db_create_index()`:
27 | ! Can't create index on table tbl.
28 | i Using SQL: CREATE INDEX `tbl_col` ON `tbl` (`col`)
29 | Caused by error:
30 | ! dummy DBI error
31 | Code
32 | (expect_error(db_explain(con, "invalid sql")))
33 | Output
34 |
35 | Error in `db_explain()`:
36 | ! Can't explain query.
37 | i Using SQL: EXPLAIN QUERY PLAN invalid sql
38 | Caused by error:
39 | ! dummy DBI error
40 | Code
41 | (expect_error(db_query_fields(con, "does not exist")))
42 | Output
43 |
44 | Error in `db_query_fields()`:
45 | ! Can't query fields.
46 | i Using SQL: SELECT * FROM `does not exist` AS `q01` WHERE (0 = 1)
47 | Caused by error:
48 | ! dummy DBI error
49 | Code
50 | (expect_error(db_save_query(con, "invalid sql", "tbl")))
51 | Output
52 |
53 | Error in `db_save_query()`:
54 | ! Can't save query to table `tbl`.
55 | i Using SQL: CREATE TEMPORARY TABLE `tbl` AS `invalid sql`
56 | Caused by error:
57 | ! dummy DBI error
58 |
59 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/escape.md:
--------------------------------------------------------------------------------
1 | # con must not be NULL
2 |
3 | Code
4 | escape("a")
5 | Condition
6 | Error in `escape()`:
7 | ! `con` must not be NULL.
8 |
9 | ---
10 |
11 | Code
12 | sql_vector("a")
13 | Condition
14 | Error in `sql_vector()`:
15 | ! `con` must not be NULL.
16 |
17 | # other objects get informative error
18 |
19 | Code
20 | lf %>% filter(x == input)
21 | Condition
22 | Error:
23 | ! Cannot translate shiny inputs to SQL.
24 | i Do you want to force evaluation in R with (e.g.) `!!input$x` or `local(input$x)`?
25 | Code
26 | lf %>% filter(x == x())
27 | Condition
28 | Error:
29 | ! Cannot translate a shiny reactive to SQL.
30 | i Do you want to force evaluation in R with (e.g.) `!!foo()` or `local(foo())`?
31 | Code
32 | lf %>% filter(x == df)
33 | Condition
34 | Error:
35 | ! Cannot translate a data.frame to SQL.
36 | i Do you want to force evaluation in R with (e.g.) `!!df$x` or `local(df$x)`?
37 | Code
38 | lf %>% filter(x == mean)
39 | Condition
40 | Error:
41 | ! Cannot translate a function to SQL.
42 | i Do you want to force evaluation in R with (e.g.) `!!x` or `local(x)`?
43 |
44 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/ident.md:
--------------------------------------------------------------------------------
1 | # can format ident
2 |
3 | Code
4 | ident()
5 | Output
6 | [empty]
7 |
8 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/lazy-join-query.md:
--------------------------------------------------------------------------------
1 | # lazy_semi_join_query() checks arguments
2 |
3 | Code
4 | (my_lazy_semi_join_query(x = lazy_frame(x = 1)))
5 | Condition
6 | Error in `my_lazy_semi_join_query()`:
7 | ! `x` must be a lazy query, not a object.
8 | Code
9 | (my_lazy_semi_join_query(y = lazy_frame(x = 1)))
10 | Condition
11 | Error in `my_lazy_semi_join_query()`:
12 | ! `y` must be a lazy query, not a object.
13 |
14 | ---
15 |
16 | Code
17 | (my_lazy_semi_join_query(by = lmod(by0, x = 1)))
18 | Condition
19 | Error in `my_lazy_semi_join_query()`:
20 | ! `by$x` must be a character vector, not the number 1.
21 |
22 | ---
23 |
24 | Code
25 | (my_lazy_semi_join_query(anti = NA))
26 | Condition
27 | Error in `my_lazy_semi_join_query()`:
28 | ! `anti` must be `TRUE` or `FALSE`, not `NA`.
29 |
30 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/lazy-select-query.md:
--------------------------------------------------------------------------------
1 | # can print lazy_select_query
2 |
3 | Code
4 | lazy_select_query(x = lf$lazy_query, select = quos(x_mean = mean(x), y2 = y),
5 | where = quos(y > 1, x == y - 2), group_by = quos("x"))
6 | Output
7 |
8 | From:
9 | `df`
10 | Select: x_mean = mean(x), y2 = y
11 | Where: y > 1, x == y - 2
12 | Group by: "x"
13 |
14 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/pillar.md:
--------------------------------------------------------------------------------
1 | # custom header
2 |
3 | Code
4 | # Number of rows is shown
5 | x <- memdb_frame(a = 1:3) %>% filter(a > 0)
6 | setup <- pillar::tbl_format_setup(x)
7 | tbl_format_header(x, setup)[[1]]
8 | Output
9 | [1] "# Source: SQL [3 x 1]"
10 | Code
11 | # Number of rows still can't be shown if above 20
12 | x <- memdb_frame(a = 1:21) %>% filter(a > 0)
13 | setup <- pillar::tbl_format_setup(x)
14 | tbl_format_header(x, setup)[[1]]
15 | Output
16 | [1] "# Source: SQL [?? x 1]"
17 |
18 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/query-select.md:
--------------------------------------------------------------------------------
1 | # select_query() print method output is as expected
2 |
3 | Code
4 | mf
5 | Output
6 |
7 | From:
8 | `df`
9 | Select: `df`.*
10 | Where: `x` > 1
11 | Order by: `x`
12 | Limit: 10
13 |
14 | # queries generated by select() don't alias unnecessarily
15 |
16 | Code
17 | lf_render
18 | Output
19 | SELECT `x`
20 | FROM `df`
21 |
22 | ---
23 |
24 | Code
25 | lazy_frame(x = 1, y = 1) %>% select()
26 | Condition
27 | Error in `sql_clause_select()`:
28 | ! Query contains no columns
29 |
30 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/query-semi-join.md:
--------------------------------------------------------------------------------
1 | # print method doesn't change unexpectedly
2 |
3 | Code
4 | sql_build(semi_join(lf1, lf2 %>% filter(z == 2)))
5 | Message
6 | Joining with `by = join_by(x)`
7 | Output
8 |
9 | By:
10 | x-x
11 | Where:
12 | "`df_RHS`.`z` = 2.0"
13 | X:
14 | `df`
15 | Y:
16 | `df`
17 |
18 | # generated sql doesn't change unexpectedly
19 |
20 | Code
21 | semi_join(lf, lf)
22 | Message
23 | Joining with `by = join_by(x, y)`
24 | Output
25 |
26 | SELECT `df_LHS`.*
27 | FROM `df` AS `df_LHS`
28 | WHERE EXISTS (
29 | SELECT 1 FROM `df` AS `df_RHS`
30 | WHERE (`df_LHS`.`x` = `df_RHS`.`x`) AND (`df_LHS`.`y` = `df_RHS`.`y`)
31 | )
32 |
33 | ---
34 |
35 | Code
36 | anti_join(lf, lf)
37 | Message
38 | Joining with `by = join_by(x, y)`
39 | Output
40 |
41 | SELECT `df_LHS`.*
42 | FROM `df` AS `df_LHS`
43 | WHERE NOT EXISTS (
44 | SELECT 1 FROM `df` AS `df_RHS`
45 | WHERE (`df_LHS`.`x` = `df_RHS`.`x`) AND (`df_LHS`.`y` = `df_RHS`.`y`)
46 | )
47 |
48 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/query-set-op.md:
--------------------------------------------------------------------------------
1 | # print method doesn't change unexpectedly
2 |
3 | Code
4 | sql_build(union(lf1, lf2) %>% union_all(lf3))
5 | Output
6 |
7 | From:
8 | `lf1`
9 | Select: `lf1`.*, NULL
10 |
11 | UNION
12 |
13 |
14 | From:
15 | `lf2`
16 | Select: `x`, NULL, `z`
17 |
18 | UNION ALL
19 |
20 |
21 | From:
22 | `lf3`
23 | Select: `x`, NULL, `z`
24 |
25 | # generated sql doesn't change unexpectedly
26 |
27 | Code
28 | union(lf, lf)
29 | Output
30 |
31 | SELECT *
32 | FROM `df`
33 |
34 | UNION
35 |
36 | SELECT *
37 | FROM `df`
38 |
39 | ---
40 |
41 | Code
42 | setdiff(lf, lf)
43 | Output
44 |
45 | (
46 | SELECT *
47 | FROM `df`
48 | )
49 | EXCEPT
50 | (
51 | SELECT *
52 | FROM `df`
53 | )
54 |
55 | ---
56 |
57 | Code
58 | intersect(lf, lf)
59 | Output
60 |
61 | (
62 | SELECT *
63 | FROM `df`
64 | )
65 | INTERSECT
66 | (
67 | SELECT *
68 | FROM `df`
69 | )
70 |
71 | ---
72 |
73 | Code
74 | union(lf, lf, all = TRUE)
75 | Output
76 |
77 | SELECT *
78 | FROM `df`
79 |
80 | UNION ALL
81 |
82 | SELECT *
83 | FROM `df`
84 |
85 | ---
86 |
87 | Code
88 | setdiff(lf, lf, all = TRUE)
89 | Output
90 |
91 | (
92 | SELECT *
93 | FROM `df`
94 | )
95 | EXCEPT ALL
96 | (
97 | SELECT *
98 | FROM `df`
99 | )
100 |
101 | ---
102 |
103 | Code
104 | intersect(lf, lf, all = TRUE)
105 | Output
106 |
107 | (
108 | SELECT *
109 | FROM `df`
110 | )
111 | INTERSECT ALL
112 | (
113 | SELECT *
114 | FROM `df`
115 | )
116 |
117 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/schema.md:
--------------------------------------------------------------------------------
1 | # can construct and print
2 |
3 | Code
4 | in_schema("schema", "table")
5 | Output
6 | `schema`.`table`
7 |
8 | ---
9 |
10 | Code
11 | in_catalog("catalog", "schema", "table")
12 | Output
13 | `catalog`.`schema`.`table`
14 |
15 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/sql-build.md:
--------------------------------------------------------------------------------
1 | # rendering table wraps in SELECT *
2 |
3 | Code
4 | out %>% sql_render()
5 | Output
6 | SELECT *
7 | FROM `test-sql-build`
8 |
9 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/sql.md:
--------------------------------------------------------------------------------
1 | # can format sql
2 |
3 | Code
4 | sql()
5 | Output
6 | [empty]
7 |
8 | ---
9 |
10 | Code
11 | sql(a = "x", "y")
12 | Output
13 | x AS a
14 | y
15 |
16 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/table-name.md:
--------------------------------------------------------------------------------
1 | # table_path possess key methods
2 |
3 | Code
4 | name <- table_path(c("x", "y", "z"))
5 | name
6 | Output
7 | x, y, z
8 |
9 | # can check for table name
10 |
11 | Code
12 | foo(1)
13 | Condition
14 | Error in `foo()`:
15 | ! `y` must be a , not a string.
16 | i This is an internal error that was detected in the dbplyr package.
17 | Please report it at with a reprex () and the full backtrace.
18 |
19 | # as_table_path validates its inputs
20 |
21 | Code
22 | as_table_path("x")
23 | Condition
24 | Error in `as_table_path()`:
25 | ! `con` is absent but must be supplied.
26 | Code
27 | as_table_path(c("x", "y"), con)
28 | Condition
29 | Error:
30 | ! `c("x", "y")` must be a single string, not a character vector.
31 | Code
32 | as_table_path(1, con)
33 | Condition
34 | Error in `as_table_path()`:
35 | ! `1` uses unknown specification for table name
36 | Code
37 | as_table_path(I(1), con)
38 | Condition
39 | Error:
40 | ! `I(1)` must be a single string, not the number 1.
41 |
42 | # as_table_path warns when using sql
43 |
44 | Code
45 | as_table_path(sql("x"), con)
46 | Condition
47 | Warning:
48 | `sql("x")` uses SQL where a table identifier is expected.
49 | i If you want to use a literal (unquoted) identifier use `I()` instead.
50 | Output
51 | x
52 |
53 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/tbl-lazy.md:
--------------------------------------------------------------------------------
1 | # argument src is deprecated
2 |
3 | Code
4 | tbl_lazy(mtcars, src = simulate_sqlite())
5 | Condition
6 | Error in `tbl_lazy()`:
7 | ! `...` must be empty.
8 | x Problematic argument:
9 | * src = simulate_sqlite()
10 |
11 | # cannot convert tbl_lazy to data.frame
12 |
13 | Code
14 | as.data.frame(tbl_lazy(mtcars, con = simulate_sqlite()))
15 | Condition
16 | Error in `as.data.frame()`:
17 | ! Can not coerce to
18 |
19 | # has print method
20 |
21 | Code
22 | tbl_lazy(mtcars)
23 | Output
24 |
25 | SELECT *
26 | FROM `df`
27 |
28 | # names() inform that they aren't meant to be used
29 |
30 | Code
31 | names(lazy_frame(x = 1))
32 | Message
33 | ! The `names()` method of is for internal use only.
34 | i Did you mean `colnames()`?
35 | Output
36 | [1] "lazy_query" "src"
37 |
38 | # $ aborts when not used with src or lazy_query
39 |
40 | The `$` method of is for internal use only.
41 | i Use `dplyr::pull()` to get the values in a column.
42 |
43 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/tbl-sql.md:
--------------------------------------------------------------------------------
1 | # sql tbl can be printed
2 |
3 | Code
4 | mf2
5 | Output
6 | # Source: SQL [?? x 2]
7 | # Database: sqlite ?.?.? [:memory:]
8 | x y
9 |
10 | 1 1 3
11 | 2 2 2
12 | 3 3 1
13 |
14 | # useful error if missing I()
15 |
16 | Code
17 | tbl(src_memdb(), "foo.bar")
18 | Condition
19 | Error in `tbl_sql()`:
20 | ! Failed to find table `foo.bar`.
21 | i Did you mean `from = I("foo.bar")`?
22 | Caused by error in `db_query_fields.DBIConnection()`:
23 | ! Can't query fields.
24 | i Using SQL: SELECT * FROM `foo.bar` AS `q05` WHERE (0 = 1)
25 | Caused by error:
26 | ! no such table: foo.bar
27 |
28 | # check_from is deprecated
29 |
30 | Code
31 | out <- tbl(con, "x", check_from = FALSE)
32 | Condition
33 | Warning:
34 | The `check_from` argument of `tbl_sql()` is deprecated as of dbplyr 2.5.0.
35 |
36 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/tidyeval.md:
--------------------------------------------------------------------------------
1 | # old arguments are defunct
2 |
3 | Code
4 | partial_eval(quote(x), vars = c("x", "y"))
5 | Condition
6 | Error:
7 | ! The `vars` argument of `partial_eval()` was deprecated in dbplyr 2.1.2 and is now defunct.
8 | Code
9 | partial_eval(quote(x), data = c("x", "y"))
10 | Condition
11 | Error:
12 | ! The `data` argument of `partial_eval()` must be a lazy frame as of dbplyr 2.1.2.
13 |
14 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/translate-sql-cut.md:
--------------------------------------------------------------------------------
1 | # works with labels a character vector
2 |
3 | Code
4 | (expect_error(test_translate_sql(cut(x, 1:3, labels = c("a", "b", "c")))))
5 | Output
6 |
7 | Error in `cut()`:
8 | ! Can't recycle `labels` (size 3) to size 2.
9 |
10 | # cut checks arguments
11 |
12 | Code
13 | (expect_error(test_translate_sql(cut(x, 1))))
14 | Output
15 |
16 | Error in `cut()`:
17 | ! `breaks` must have at least two values.
18 | Code
19 | (expect_error(test_translate_sql(cut(x, c(1, 1)))))
20 | Output
21 |
22 | Error in `cut()`:
23 | ! `breaks` are not unique.
24 | Code
25 | (expect_error(test_translate_sql(cut(x, c(1, 2, NA)))))
26 | Output
27 |
28 | Error in `cut()`:
29 | ! `breaks` values must not be missing.
30 |
31 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/translate-sql-helpers.md:
--------------------------------------------------------------------------------
1 | # warns informatively with unsupported function
2 |
3 | Code
4 | sql_not_supported("cor")()
5 | Condition
6 | Error:
7 | ! `cor()` is not available in this SQL variant.
8 |
9 | # duplicates throw an error
10 |
11 | Code
12 | sql_translator(round = function(x) x, round = function(y) y)
13 | Condition
14 | Error in `sql_translator()`:
15 | ! Duplicate names in `sql_translator()`
16 | * round
17 |
18 | # output of print method for sql_variant is correct
19 |
20 | Code
21 | sql_variant(sim_trans, sim_trans, sim_trans)
22 | Output
23 |
24 | scalar: +
25 | aggregate: +
26 | window: +
27 |
28 | # win_rank() is accepted by the sql_translator
29 |
30 | Code
31 | sql_variant(sql_translator(test = win_rank("test")))
32 | Output
33 |
34 | scalar: test
35 |
36 | # sql_prefix checks arguments
37 |
38 | Code
39 | sin_db(sin(1, 2))
40 | Condition
41 | Error in `sin()`:
42 | ! 2 arguments passed to 'sin' which requires 1
43 |
44 | ---
45 |
46 | Code
47 | sin_db(sin(a = 1))
48 | Condition
49 | Error in `sin()`:
50 | ! supplied argument name 'a' does not match 'x'
51 |
52 | # runif is translated
53 |
54 | Code
55 | test_translate_sql(runif(2))
56 | Condition
57 | Error in `sql_runif()`:
58 | ! Only `n = n()` is supported.
59 |
60 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/translate-sql-quantile.md:
--------------------------------------------------------------------------------
1 | # quantile and median don't change without warning
2 |
3 | Code
4 | test_translate_sql(quantile(x, 0.75, na.rm = TRUE), window = FALSE)
5 | Output
6 | PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY `x`)
7 |
8 | ---
9 |
10 | Code
11 | test_translate_sql(quantile(x, 0.75, na.rm = TRUE), vars_group = "g")
12 | Output
13 | PERCENTILE_CONT(0.75) WITHIN GROUP (ORDER BY `x`) OVER (PARTITION BY `g`)
14 |
15 | ---
16 |
17 | Code
18 | test_translate_sql(median(x, na.rm = TRUE), window = FALSE)
19 | Output
20 | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY `x`)
21 |
22 | ---
23 |
24 | Code
25 | test_translate_sql(median(x, na.rm = TRUE), vars_group = "g")
26 | Output
27 | PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY `x`) OVER (PARTITION BY `g`)
28 |
29 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/translate-sql-string.md:
--------------------------------------------------------------------------------
1 | # sql_substr works as expected
2 |
3 | Code
4 | substr("test")
5 | Condition
6 | Error in `substr()`:
7 | ! `start` must be a whole number, not absent.
8 |
9 | ---
10 |
11 | Code
12 | substr("test", 0)
13 | Condition
14 | Error in `substr()`:
15 | ! `stop` must be a whole number, not absent.
16 |
17 | ---
18 |
19 | Code
20 | substr("test", "x", 1)
21 | Condition
22 | Error in `substr()`:
23 | ! `start` must be a whole number, not the string "x".
24 |
25 | ---
26 |
27 | Code
28 | substr("test", 1, "x")
29 | Condition
30 | Error in `substr()`:
31 | ! `stop` must be a whole number, not the string "x".
32 |
33 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/translate-sql.md:
--------------------------------------------------------------------------------
1 | # dplyr.strict_sql = TRUE prevents auto conversion
2 |
3 | Code
4 | test_translate_sql(blah(x))
5 | Condition
6 | Error in `blah()`:
7 | ! Don't know how to translate `blah()`
8 | Code
9 | test_translate_sql(x %blah% y)
10 | Condition
11 | Error in `x %blah% y`:
12 | ! Don't know how to translate `%blah%`
13 |
14 | # namespace calls are translated
15 |
16 | Code
17 | test_translate_sql(NOSUCHPACKAGE::foo())
18 | Condition
19 | Error:
20 | ! There is no package called NOSUCHPACKAGE
21 | Code
22 | test_translate_sql(dbplyr::NOSUCHFUNCTION())
23 | Condition
24 | Error:
25 | ! "NOSUCHFUNCTION" is not an exported object from dbplyr
26 | Code
27 | test_translate_sql(base::abbreviate(x))
28 | Condition
29 | Error in `base::abbreviate()`:
30 | ! No known SQL translation
31 |
32 | ---
33 |
34 | Code
35 | lz %>% mutate(x = NOSUCHPACKAGE::foo())
36 | Condition
37 | Error:
38 | ! There is no package called NOSUCHPACKAGE
39 | Code
40 | lz %>% mutate(x = dbplyr::NOSUCHFUNCTION())
41 | Condition
42 | Error:
43 | ! "NOSUCHFUNCTION" is not an exported object from dbplyr
44 | Code
45 | lz %>% mutate(x = base::abbreviate(x))
46 | Condition
47 | Error in `base::abbreviate()`:
48 | ! No known SQL translation
49 |
50 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-compute.md:
--------------------------------------------------------------------------------
1 | # index fails if columns are missing
2 |
3 | Code
4 | (expect_error(compute(mf, indexes = list(c("y", "x", "z"), "a"))))
5 | Output
6 |
7 | Error in `compute()`:
8 | ! All columns specified through `indexes` must exist in `x`.
9 | i The following columns are missing from `indexes`: y, z, and a.
10 | Code
11 | (expect_error(compute(mf, unique_indexes = list(c("y", "x", "z"), "a"))))
12 | Output
13 |
14 | Error in `compute()`:
15 | ! All columns specified through `unique_indexes` must exist in `x`.
16 | i The following columns are missing from `unique_indexes`: y, z, and a.
17 |
18 | # compute can handle schema
19 |
20 | Code
21 | df %>% compute(name = in_schema("main", "db1"), temporary = FALSE)
22 | Condition
23 | Error in `db_compute()`:
24 | ! Can't copy query to table `main`.`db1`.
25 | Caused by error in `db_save_query.DBIConnection()`:
26 | ! Can't save query to table `main`.`db1`.
27 | i Using SQL: CREATE TABLE `main`.`db1` AS SELECT * FROM `dbplyr_{tmp}`
28 | Caused by error:
29 | ! dummy DBI error
30 |
31 | # collect() handles DBI error
32 |
33 | Code
34 | (expect_error(mf %>% mutate(a = sql("invalid sql")) %>% collect()))
35 | Output
36 |
37 | Error in `collect()`:
38 | ! Failed to collect lazy table.
39 | Caused by error:
40 | ! dummy DBI error
41 |
42 | # compute(temporary = FALSE) without a name is deprecated
43 |
44 | The `name` argument of `compute()` must be provided when `temporary = FALSE` as of dbplyr 2.3.3.
45 |
46 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-count.md:
--------------------------------------------------------------------------------
1 | # generates expected SQL for common situations
2 |
3 | Code
4 | db %>% count(g)
5 | Output
6 |
7 | SELECT `g`, COUNT(*) AS `n`
8 | FROM `df`
9 | GROUP BY `g`
10 |
11 | ---
12 |
13 | Code
14 | db %>% count(g, wt = x)
15 | Output
16 |
17 | SELECT `g`, SUM(`x`) AS `n`
18 | FROM `df`
19 | GROUP BY `g`
20 |
21 | ---
22 |
23 | Code
24 | db %>% count(g, sort = TRUE)
25 | Output
26 |
27 | SELECT `g`, COUNT(*) AS `n`
28 | FROM `df`
29 | GROUP BY `g`
30 | ORDER BY `n` DESC
31 |
32 | ---
33 |
34 | Code
35 | db %>% add_count(g, sort = TRUE)
36 | Output
37 |
38 | SELECT `df`.*, COUNT(*) OVER (PARTITION BY `g`) AS `n`
39 | FROM `df`
40 | ORDER BY `n` DESC
41 |
42 | ---
43 |
44 | Code
45 | db %>% group_by(g) %>% add_count()
46 | Output
47 |
48 | SELECT `df`.*, COUNT(*) OVER (PARTITION BY `g`) AS `n`
49 | FROM `df`
50 |
51 | # .drop is not supported
52 |
53 | Code
54 | lazy_frame(g = 1) %>% add_count(.drop = TRUE)
55 | Condition
56 | Error in `add_count()`:
57 | ! Argument `.drop` isn't supported on database backends.
58 |
59 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-distinct.md:
--------------------------------------------------------------------------------
1 | # distinct() produces optimized SQL
2 |
3 | Code
4 | (out <- lf %>% head(2) %>% distinct(x, y))
5 | Output
6 |
7 | SELECT DISTINCT `q01`.*
8 | FROM (
9 | SELECT `df`.*
10 | FROM `df`
11 | LIMIT 2
12 | ) AS `q01`
13 |
14 | # distinct respects window_order when .keep_all is TRUE
15 |
16 | Code
17 | lf %>% window_order(desc(y)) %>% distinct(x, .keep_all = TRUE)
18 | Output
19 |
20 | SELECT `x`, `y`
21 | FROM (
22 | SELECT
23 | `df`.*,
24 | ROW_NUMBER() OVER (PARTITION BY `x` ORDER BY `y` DESC) AS `col01`
25 | FROM `df`
26 | ) AS `q01`
27 | WHERE (`col01` = 1)
28 |
29 | # distinct uses dummy window order when .keep_all is TRUE and no order is used
30 |
31 | Code
32 | lf %>% distinct(x, .keep_all = TRUE)
33 | Output
34 |
35 | SELECT `x`, `y`
36 | FROM (
37 | SELECT `df`.*, ROW_NUMBER() OVER (PARTITION BY `x` ORDER BY `x`) AS `col01`
38 | FROM `df`
39 | ) AS `q01`
40 | WHERE (`col01` = 1)
41 |
42 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-do.md:
--------------------------------------------------------------------------------
1 | # unnamed results must be data frames
2 |
3 | Code
4 | mf %>% do(nrow(.))
5 | Condition
6 | Error in `label_output_dataframe()`:
7 | ! Results must be data frames
8 | Problems at positions 1 and 2
9 |
10 | # named argument become list columns
11 |
12 | Code
13 | mf %>% do(nrow = nrow(.), ncol(.))
14 | Condition
15 | Error in `named_args()`:
16 | ! Arguments to `do()` must either be all named or all unnamed
17 |
18 | ---
19 |
20 | Code
21 | mf %>% do(nrow(.), ncol(.))
22 | Condition
23 | Error in `named_args()`:
24 | ! Can only supply single unnamed argument to `do()`
25 |
26 | ---
27 |
28 | Code
29 | mf %>% do(.f = nrow)
30 | Condition
31 | Error in `named_args()`:
32 | ! `do()` syntax changed in dplyr 0.2. Please see documentation for details
33 |
34 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-group_by.md:
--------------------------------------------------------------------------------
1 | # errors about add argument
2 |
3 | Code
4 | gf <- mf %>% group_by(x) %>% group_by(y, add = TRUE)
5 | Condition
6 | Error:
7 | ! The `add` argument of `group_by()` was deprecated in dplyr 1.0.0 and is now defunct.
8 | i Please use the `.add` argument instead.
9 |
10 | # errors for .drop = FALSE
11 |
12 | Code
13 | lazy_frame(x = 1:3, y = 1:3) %>% group_by(y, .drop = FALSE)
14 | Condition
15 | Error in `group_by()`:
16 | ! `.drop = FALSE` isn't supported on database backends.
17 | i It must be TRUE instead.
18 |
19 | # informative errors for missing variables
20 |
21 | Code
22 | (expect_error(lazy_frame(x = 1:3) %>% group_by(y)))
23 | Output
24 |
25 | Error in `group_by()`:
26 | i In argument: `y`
27 | Caused by error:
28 | ! Object `y` not found.
29 |
30 | # group_by() produces nice error messages
31 |
32 | Code
33 | lf %>% group_by(z = non_existent + 1)
34 | Condition
35 | Error in `group_by()`:
36 | i In argument: `z = non_existent + 1`
37 | Caused by error:
38 | ! Object `non_existent` not found.
39 | Code
40 | lf %>% group_by(across(non_existent))
41 | Condition
42 | Error in `group_by()`:
43 | i In argument: `across(non_existent)`
44 | Caused by error in `across()`:
45 | ! Can't select columns that don't exist.
46 | x Column `non_existent` doesn't exist.
47 |
48 | # ungroup() produces nice error messages
49 |
50 | Code
51 | lazy_frame(x = 1) %>% ungroup(non_existent)
52 | Condition
53 | Error in `ungroup()`:
54 | ! Can't select columns that don't exist.
55 | x Column `non_existent` doesn't exist.
56 |
57 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-pull.md:
--------------------------------------------------------------------------------
1 | # ungroup() produces nice error messages
2 |
3 | Code
4 | memdb_frame(x = 1) %>% pull(non_existent)
5 | Condition
6 | Error in `pull()`:
7 | Caused by error:
8 | ! object 'non_existent' not found
9 | Code
10 | memdb_frame(x = 1) %>% pull("non_existent")
11 | Condition
12 | Error in `pull()`:
13 | ! Can't extract columns that don't exist.
14 | x Column `non_existent` doesn't exist.
15 | Code
16 | memdb_frame(x = 1) %>% pull(1000)
17 | Condition
18 | Error in `pull()`:
19 | ! Can't extract columns past the end.
20 | i Location 1000 doesn't exist.
21 | i There is only 1 column.
22 | Code
23 | memdb_frame(x = 1) %>% pull(x, "name_non_existent")
24 | Condition
25 | Error in `pull()`:
26 | ! Can't extract columns that don't exist.
27 | x Column `name_non_existent` doesn't exist.
28 |
29 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-set-ops.md:
--------------------------------------------------------------------------------
1 | # can combine multiple union in one query
2 |
3 | Code
4 | lf1 %>% union_all(lf2) %>% union(lf3)
5 | Output
6 |
7 | SELECT `lf1`.*, NULL AS `z`
8 | FROM `lf1`
9 |
10 | UNION ALL
11 |
12 | SELECT `q01`.*, NULL AS `z`
13 | FROM (
14 | SELECT NULL AS `x`, `lf2`.*
15 | FROM `lf2`
16 | ) AS `q01`
17 |
18 | UNION
19 |
20 | SELECT NULL AS `x`, NULL AS `y`, `lf3`.*
21 | FROM `lf3`
22 |
23 | ---
24 |
25 | Code
26 | lf1 %>% union_all(lf2) %>% union(lf3) %>% left_join(lf1, by = "x") %>%
27 | show_query(sql_options = sql_options(cte = TRUE))
28 | Output
29 |
30 | WITH `q01` AS (
31 | SELECT `lf1`.*, NULL AS `z`
32 | FROM `lf1`
33 | ),
34 | `q02` AS (
35 | SELECT NULL AS `x`, `lf2`.*
36 | FROM `lf2`
37 | ),
38 | `q03` AS (
39 | SELECT `q01`.*, NULL AS `z`
40 | FROM `q02` AS `q01`
41 | ),
42 | `q04` AS (
43 | SELECT NULL AS `x`, NULL AS `y`, `lf3`.*
44 | FROM `lf3`
45 | ),
46 | `q05` AS (
47 | SELECT *
48 | FROM `q01`
49 |
50 | UNION ALL
51 |
52 | SELECT *
53 | FROM `q03`
54 |
55 | UNION
56 |
57 | SELECT *
58 | FROM `q04`
59 | )
60 | SELECT `LHS`.`x` AS `x`, `LHS`.`y` AS `y.x`, `z`, `lf1`.`y` AS `y.y`
61 | FROM `q05` AS `LHS`
62 | LEFT JOIN `lf1`
63 | ON (`LHS`.`x` = `lf1`.`x`)
64 |
65 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-uncount.md:
--------------------------------------------------------------------------------
1 | # symbols weights are dropped in output
2 |
3 | Code
4 | dbplyr_uncount(df, w) %>% show_query()
5 | Output
6 |
7 | SELECT `x`
8 | FROM `test`
9 | INNER JOIN (
10 | SELECT CAST(`..dbplyr_row_id` AS INTEGER) AS `..dbplyr_row_id`
11 | FROM (
12 | SELECT NULL AS `..dbplyr_row_id`
13 | WHERE (0 = 1)
14 |
15 | UNION ALL
16 |
17 | VALUES (1)
18 | ) AS `values_table`
19 | ) AS `RHS`
20 | ON (`RHS`.`..dbplyr_row_id` <= `test`.`w`)
21 |
22 | ---
23 |
24 | Code
25 | df %>% mutate(w = w + 1) %>% dbplyr_uncount(w) %>% show_query()
26 | Output
27 |
28 | SELECT `x`
29 | FROM (
30 | SELECT `x`, `w` + 1.0 AS `w`
31 | FROM `test`
32 | ) AS `LHS`
33 | INNER JOIN (
34 | SELECT CAST(`..dbplyr_row_id` AS INTEGER) AS `..dbplyr_row_id`
35 | FROM (
36 | SELECT NULL AS `..dbplyr_row_id`
37 | WHERE (0 = 1)
38 |
39 | UNION ALL
40 |
41 | VALUES (1), (2)
42 | ) AS `values_table`
43 | ) AS `RHS`
44 | ON (`RHS`.`..dbplyr_row_id` <= `LHS`.`w`)
45 |
46 |
--------------------------------------------------------------------------------
/tests/testthat/_snaps/verb-window.md:
--------------------------------------------------------------------------------
1 | # window_order errors for data frame
2 |
3 | Code
4 | (expect_error(window_order(data.frame(x = 1))))
5 | Output
6 |
7 | Error in `window_order()`:
8 | ! `.data` must be a , not a data frame.
9 | i Did you mean to use `arrange()` instead?
10 | Code
11 | (expect_error(window_order("a")))
12 | Output
13 |
14 | Error in `window_order()`:
15 | ! `.data` must be a , not a string.
16 |
17 | # window_order only accepts variables
18 |
19 | Code
20 | (expect_error(window_order(lf, x + y)))
21 | Output
22 |
23 | Error in `window_order()`:
24 | ! Each element of `...` must be a single column name or a column wrapped in `desc()`.
25 | x Element 1 is `x + y`.
26 |
27 | # window order works afer renaming variable
28 |
29 | Code
30 | lazy_frame(x = 1, y = 1) %>% window_order(y) %>% rename(y2 = y) %>% mutate(
31 | x_cum = cumsum(x))
32 | Output
33 |
34 | SELECT
35 | `q01`.*,
36 | SUM(`x`) OVER (ORDER BY `y2` ROWS UNBOUNDED PRECEDING) AS `x_cum`
37 | FROM (
38 | SELECT `x`, `y` AS `y2`
39 | FROM `df`
40 | ) AS `q01`
41 | Code
42 | lazy_frame(x = 1, y = 1) %>% rename(y2 = y) %>% window_order(y2) %>% mutate(
43 | x_cum = cumsum(x))
44 | Output
45 |
46 | SELECT
47 | `q01`.*,
48 | SUM(`x`) OVER (ORDER BY `y2` ROWS UNBOUNDED PRECEDING) AS `x_cum`
49 | FROM (
50 | SELECT `x`, `y` AS `y2`
51 | FROM `df`
52 | ) AS `q01`
53 |
54 | # window_frame errors for data frame
55 |
56 | Code
57 | (expect_error(window_frame(data.frame(x = 1))))
58 | Output
59 |
60 | Error in `window_frame()`:
61 | ! `.data` must be a , not a .
62 |
63 |
--------------------------------------------------------------------------------
/tests/testthat/helper-src.R:
--------------------------------------------------------------------------------
1 | on_gha <- function() identical(Sys.getenv("GITHUB_ACTIONS"), "true")
2 | on_cran <- function() !identical(Sys.getenv("NOT_CRAN"), "true")
3 |
4 | if (test_srcs$length() == 0) {
5 |
6 | test_register_con("sqlite", RSQLite::SQLite(), ":memory:")
7 |
8 | if (identical(Sys.getenv("GITHUB_POSTGRES"), "true")) {
9 | test_register_con("postgres", RPostgres::Postgres(),
10 | dbname = "test",
11 | user = "postgres",
12 | password = "password",
13 | host = "127.0.0.1"
14 | )
15 | } else if (identical(Sys.getenv("GITHUB_MSSQL"), "true")) {
16 | test_register_con("mssql", odbc::odbc(),
17 | driver = "ODBC Driver 17 for SQL Server",
18 | database = "test",
19 | uid = "SA",
20 | pwd = "Password12",
21 | server = "localhost",
22 | port = 1433
23 | )
24 | } else if (on_gha() || on_cran()) {
25 | # Only test with sqlite
26 | } else {
27 | test_register_con("MariaDB", RMariaDB::MariaDB(),
28 | dbname = "test",
29 | host = "localhost",
30 | username = Sys.getenv("USER")
31 | )
32 | test_register_con("postgres", RPostgres::Postgres(),
33 | dbname = "test",
34 | host = "localhost",
35 | user = ""
36 | )
37 | }
38 | }
39 |
40 | local_sqlite_con_with_aux <- function(envir = parent.frame()) {
41 | tmp <- tempfile()
42 |
43 | con <- withr::local_db_connection(
44 | DBI::dbConnect(RSQLite::SQLite(), ":memory:"),
45 | .local_envir = envir
46 | )
47 | DBI::dbExecute(con, paste0("ATTACH '", tmp, "' AS aux"))
48 |
49 | con
50 | }
51 |
52 | snap_transform_dbi <- function(x) {
53 | x <- gsub("dbplyr_[a-zA-Z0-9]+", "dbplyr_{tmp}", x)
54 |
55 | # use the last line matching this in case of multiple chained errors
56 | caused_by <- which(x == "Caused by error:")
57 | if (length(caused_by) == 0) {
58 | return(x)
59 | }
60 |
61 | dbi_line_id <- max(caused_by)
62 |
63 | n <- length(x)
64 | x <- x[-seq2(dbi_line_id + 1, n)]
65 | c(x, "! dummy DBI error")
66 | }
67 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-hana.R:
--------------------------------------------------------------------------------
1 | test_that("custom string translations", {
2 | local_con(simulate_hana())
3 |
4 | expect_snapshot(test_translate_sql(paste0("a", "b")))
5 | expect_snapshot(test_translate_sql(paste("a", "b")))
6 |
7 | expect_snapshot(test_translate_sql(substr(x, 2, 4)))
8 | expect_snapshot(test_translate_sql(substring(x, 2, 4)))
9 | expect_snapshot(test_translate_sql(str_sub(x, 2, -2)))
10 | })
11 |
12 | test_that("copy_inline uses UNION ALL", {
13 | con <- simulate_hana()
14 | y <- tibble::tibble(id = 1L, arr = "{1,2,3}")
15 |
16 | types <- c(id = "bigint", arr = "integer[]")
17 | expect_snapshot({
18 | copy_inline(con, y %>% slice(0)) %>% remote_query()
19 | copy_inline(con, y) %>% remote_query()
20 |
21 | # with `types`
22 | copy_inline(con, y %>% slice(0), types = types) %>% remote_query()
23 | copy_inline(con, y, types = types) %>% remote_query()
24 | })
25 | })
26 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-hive.R:
--------------------------------------------------------------------------------
1 | test_that("custom scalar & string functions translated correctly", {
2 | local_con(simulate_hive())
3 |
4 | expect_equal(test_translate_sql(bitwShiftL(x, 2L)), sql("SHIFTLEFT(`x`, 2)"))
5 | expect_equal(test_translate_sql(bitwShiftR(x, 2L)), sql("SHIFTRIGHT(`x`, 2)"))
6 | expect_equal(test_translate_sql(cot(x)), sql("1.0 / TAN(`x`)"))
7 | expect_equal(test_translate_sql(str_replace_all(x, "old", "new")), sql("REGEXP_REPLACE(`x`, 'old', 'new')"))
8 | expect_equal(test_translate_sql(median(x, na.rm = TRUE)), sql("PERCENTILE(`x`, 0.5) OVER ()"))
9 | })
10 |
11 | test_that("generates custom sql", {
12 | con <- simulate_hive()
13 | expect_snapshot(sql_table_analyze(con, in_schema("schema", "tbl")))
14 |
15 | expect_equal(
16 | translate_sql(last(x, na_rm = TRUE), vars_order = "a", con = con),
17 | sql("LAST_VALUE(`x`, TRUE) OVER (ORDER BY `a` ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)")
18 | )
19 |
20 | lf <- lazy_frame(tibble(x = 1), con = con)
21 | expect_snapshot(union_all(lf, lf))
22 | })
23 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-impala.R:
--------------------------------------------------------------------------------
1 | test_that("custom scalar functions translated correctly", {
2 | local_con(simulate_impala())
3 |
4 | expect_equal(test_translate_sql(as.Date(x)), sql("CAST(`x` AS VARCHAR(10))"))
5 | expect_equal(test_translate_sql(ceiling(x)), sql("CEIL(`x`)"))
6 | })
7 |
8 | test_that("custom bitwise operations translated correctly", {
9 | local_con(simulate_impala())
10 |
11 | expect_equal(test_translate_sql(bitwNot(x)), sql("BITNOT(`x`)"))
12 | expect_equal(test_translate_sql(bitwAnd(x, 128L)), sql("BITAND(`x`, 128)"))
13 | expect_equal(test_translate_sql(bitwOr(x, 128L)), sql("BITOR(`x`, 128)"))
14 | expect_equal(test_translate_sql(bitwXor(x, 128L)), sql("BITXOR(`x`, 128)"))
15 | expect_equal(test_translate_sql(bitwShiftL(x, 2L)), sql("SHIFTLEFT(`x`, 2)"))
16 | expect_equal(test_translate_sql(bitwShiftR(x, 2L)), sql("SHIFTRIGHT(`x`, 2)"))
17 | })
18 |
19 | test_that("generates custom sql", {
20 | con <- simulate_impala()
21 |
22 | expect_snapshot(sql_table_analyze(con, in_schema("schema", "tbl")))
23 | })
24 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-odbc.R:
--------------------------------------------------------------------------------
1 | test_that("custom scalar translated correctly", {
2 | local_con(simulate_odbc())
3 |
4 | expect_equal(test_translate_sql(as.numeric(x)), sql("CAST(`x` AS DOUBLE)"))
5 | expect_equal(test_translate_sql(as.double(x)), sql("CAST(`x` AS DOUBLE)"))
6 | expect_equal(test_translate_sql(as.integer(x)), sql("CAST(`x` AS INT)"))
7 | expect_equal(test_translate_sql(as.character(x)), sql("CAST(`x` AS STRING)"))
8 | })
9 |
10 | test_that("custom aggregators translated correctly", {
11 | local_con(simulate_odbc())
12 |
13 | expect_equal(
14 | test_translate_sql(sd(x, na.rm = TRUE), window = FALSE),
15 | sql("STDDEV_SAMP(`x`)")
16 | )
17 | })
18 |
19 | test_that("custom window functions translated correctly", {
20 | local_con(simulate_odbc())
21 |
22 | expect_equal(
23 | test_translate_sql(sd(x, na.rm = TRUE)),
24 | sql("STDDEV_SAMP(`x`) OVER ()")
25 | )
26 | })
27 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-postgres-old.R:
--------------------------------------------------------------------------------
1 | test_that("RPostgreSQL backend", {
2 | skip_if_not(identical(Sys.getenv("GITHUB_POSTGRES"), "true"))
3 |
4 | src <- withr::local_db_connection(
5 | DBI::dbConnect(
6 | RPostgreSQL::PostgreSQL(),
7 | dbname = "test",
8 | user = "postgres",
9 | password = "password",
10 | host = "127.0.0.1"
11 | )
12 | )
13 |
14 | suppressWarnings(
15 | copy_to(src, mtcars, "mtcars", overwrite = TRUE, temporary = FALSE)
16 | )
17 | withr::defer(DBI::dbRemoveTable(src, "mtcars"))
18 |
19 | expect_identical(colnames(tbl(src, "mtcars")), colnames(mtcars))
20 |
21 | src_cyl <- tbl(src, "mtcars") %>% select(cyl) %>% collect()
22 | expect_identical(src_cyl$cyl, mtcars$cyl)
23 | })
24 |
--------------------------------------------------------------------------------
/tests/testthat/test-backend-spark-sql.R:
--------------------------------------------------------------------------------
1 | test_that("custom clock functions translated correctly", {
2 | local_con(simulate_spark_sql())
3 | expect_equal(test_translate_sql(add_years(x, 1)), sql("ADD_MONTHS(`x`, 1.0 * 12.0)"))
4 | expect_equal(test_translate_sql(add_days(x, 1)), sql("DATE_ADD(`x`, 1.0)"))
5 | expect_error(
6 | test_translate_sql(add_days(x, 1, "dots", "must", "be empty")),
7 | class = "rlib_error_dots_nonempty"
8 | )
9 | expect_equal(test_translate_sql(date_build(2020, 1, 1)), sql("MAKE_DATE(2020.0, 1.0, 1.0)"))
10 | expect_equal(test_translate_sql(date_build(year_column, 1L, 1L)), sql("MAKE_DATE(`year_column`, 1, 1)"))
11 | expect_equal(test_translate_sql(get_year(date_column)), sql("DATE_PART('YEAR', `date_column`)"))
12 | expect_equal(test_translate_sql(get_month(date_column)), sql("DATE_PART('MONTH', `date_column`)"))
13 | expect_equal(test_translate_sql(get_day(date_column)), sql("DATE_PART('DAY', `date_column`)"))
14 | expect_equal(test_translate_sql(date_count_between(date_column_1, date_column_2, "day")),
15 | sql("DATEDIFF(`date_column_2`, `date_column_1`)"))
16 | expect_snapshot(
17 | error = TRUE,
18 | test_translate_sql(date_count_between(date_column_1, date_column_2, "year"))
19 | )
20 | expect_snapshot(
21 | error = TRUE,
22 | test_translate_sql(date_count_between(date_column_1, date_column_2, "day", n = 5))
23 | )
24 | })
25 |
26 | test_that("difftime is translated correctly", {
27 | local_con(simulate_spark_sql())
28 | expect_equal(test_translate_sql(difftime(start_date, end_date, units = "days")), sql("DATEDIFF(`end_date`, `start_date`)"))
29 | expect_equal(test_translate_sql(difftime(start_date, end_date)), sql("DATEDIFF(`end_date`, `start_date`)"))
30 |
31 | expect_snapshot(
32 | error = TRUE,
33 | test_translate_sql(difftime(start_date, end_date, units = "auto"))
34 | )
35 | expect_snapshot(
36 | error = TRUE,
37 | test_translate_sql(difftime(start_date, end_date, tz = "UTC", units = "days"))
38 | )
39 | })
40 |
--------------------------------------------------------------------------------
/tests/testthat/test-db-escape.R:
--------------------------------------------------------------------------------
1 | test_that("can translate raw to blob spec", {
2 | con <- simulate_dbi()
3 |
4 | expect_equal(sql_escape_raw(con, NULL), "NULL")
5 | expect_equal(sql_escape_raw(con, charToRaw("abc")), "X'616263'")
6 | })
7 |
--------------------------------------------------------------------------------
/tests/testthat/test-db-io.R:
--------------------------------------------------------------------------------
1 | test_that("db_copy_to() wraps DBI errors", {
2 | con <- local_sqlite_connection()
3 | local_db_table(con, data.frame(x = 1), "tmp")
4 |
5 | # error when creating unique index
6 | expect_snapshot(
7 | (expect_error(
8 | db_copy_to(
9 | con = con,
10 | table = "tmp2",
11 | values = data.frame(x = c(1, 1)),
12 | unique_indexes = list("x")
13 | )
14 | )),
15 | transform = snap_transform_dbi
16 | )
17 | })
18 |
19 | test_that("db_copy_to() can overwrite a table", {
20 | con <- local_sqlite_connection()
21 | local_db_table(con, data.frame(x = 1), "tmp")
22 |
23 | # doesn't overwrite by default
24 | expect_snapshot(
25 | (expect_error(
26 | db_copy_to(
27 | con = con,
28 | table = "tmp",
29 | values = data.frame(x = c(1, 1))
30 | )
31 | )),
32 | transform = snap_transform_dbi
33 | )
34 |
35 | db_copy_to(
36 | con = con,
37 | table = "tmp",
38 | values = data.frame(x = c(1, 1)),
39 | overwrite = TRUE
40 | )
41 | expect_equal(DBI::dbReadTable(con, "tmp"), data.frame(x = c(1, 1)))
42 | })
43 |
44 | test_that("db_save_query() can overwrite a table", {
45 | con <- local_sqlite_connection()
46 | local_db_table(con, data.frame(x = 1), "tmp")
47 |
48 | # doesn't overwrite by default
49 | expect_snapshot(
50 | (expect_error(
51 | db_save_query(
52 | con = con,
53 | sql = "SELECT 2 FROM tmp",
54 | name = "tmp"
55 | )
56 | )),
57 | transform = snap_transform_dbi
58 | )
59 |
60 | db_save_query(
61 | con = con,
62 | sql = sql("SELECT 2 AS x"),
63 | name = "tmp",
64 | overwrite = TRUE
65 | )
66 | expect_equal(DBI::dbReadTable(con, "tmp"), data.frame(x = 2L))
67 | })
68 |
--------------------------------------------------------------------------------
/tests/testthat/test-db-sql.R:
--------------------------------------------------------------------------------
1 | test_that("2nd edition uses sql methods", {
2 | reset_warning_verbosity("Test-edition")
3 | local_methods(
4 | db_analyze.Test = function(con, ...) abort("db_method")
5 | )
6 |
7 | con <- structure(list(), class = c("Test", "DBIConnection"))
8 | expect_snapshot(expect_error(dbplyr_analyze(con), "db_method"))
9 |
10 | local_methods(
11 | dbplyr_edition.Test = function(con) 2,
12 | sql_table_analyze.Test = function(con, ...) abort("sql_method")
13 | )
14 | expect_error(dbplyr_analyze(con), "sql_method")
15 | })
16 |
17 | test_that("sql_query_rows() works", {
18 | expect_equal(
19 | sql_query_rows(simulate_dbi(), ident("abc")),
20 | sql("SELECT COUNT(*) FROM `abc` AS `master`")
21 | )
22 | })
23 |
24 | test_that("handles DBI error", {
25 | unique_subquery_name_reset()
26 | con <- local_sqlite_connection()
27 |
28 | expect_snapshot({
29 | (expect_error(db_analyze(con, "tbl")))
30 | (expect_error(db_create_index(con, "tbl", "col")))
31 |
32 | (expect_error(db_explain(con, "invalid sql")))
33 | (expect_error(db_query_fields(con, "does not exist")))
34 | (expect_error(db_save_query(con, "invalid sql", "tbl")))
35 | },
36 | transform = snap_transform_dbi
37 | )
38 | })
39 |
--------------------------------------------------------------------------------
/tests/testthat/test-ident.R:
--------------------------------------------------------------------------------
1 | test_that("zero length inputs return correct clases", {
2 | expect_s3_class(ident(), "ident")
3 | })
4 |
5 | test_that("ident quotes", {
6 | con <- simulate_dbi()
7 | x1 <- ident("x")
8 |
9 | expect_equal(escape(x1, con = con), sql('`x`'))
10 | expect_equal(as.sql(x1), x1)
11 | })
12 |
13 | test_that("can format ident", {
14 | expect_snapshot(ident())
15 | })
16 |
--------------------------------------------------------------------------------
/tests/testthat/test-lazy-join-query.R:
--------------------------------------------------------------------------------
1 | test_that("lazy_semi_join_query() checks arguments", {
2 | by0 <- list(x = "x", y = "x", x_as = ident("LHS"), y_as = ident("RHS"), na_matches = "never")
3 | lmod <- purrr::list_modify
4 |
5 | my_lazy_semi_join_query <- function(x = lazy_frame(x = 1, y = 2)$lazy_query,
6 | y = lazy_frame(x = 1, z = 2)$lazy_query,
7 | anti = FALSE,
8 | by = by0) {
9 | lazy_semi_join_query(
10 | x = x,
11 | y = y,
12 | vars = tibble(name = "x", var = "x"),
13 | anti = anti,
14 | by = by
15 | )
16 | }
17 |
18 | expect_snapshot(error = TRUE, {
19 | (my_lazy_semi_join_query(x = lazy_frame(x = 1)))
20 | (my_lazy_semi_join_query(y = lazy_frame(x = 1)))
21 | })
22 |
23 | expect_snapshot(error = TRUE, {
24 | (my_lazy_semi_join_query(by = lmod(by0, x = 1)))
25 | })
26 |
27 | expect_snapshot(error = TRUE, {
28 | (my_lazy_semi_join_query(anti = NA))
29 | })
30 | })
31 |
--------------------------------------------------------------------------------
/tests/testthat/test-lazy-select-query.R:
--------------------------------------------------------------------------------
1 | test_that("can print lazy_select_query", {
2 | lf <- lazy_frame(x = 1, y = 2)
3 |
4 | expect_snapshot(
5 | lazy_select_query(
6 | x = lf$lazy_query,
7 | select = quos(
8 | x_mean = mean(x),
9 | y2 = y
10 | ),
11 | where = quos(y > 1, x == y - 2),
12 | group_by = quos("x")
13 | )
14 | )
15 | })
16 |
--------------------------------------------------------------------------------
/tests/testthat/test-pillar.R:
--------------------------------------------------------------------------------
1 | test_that("custom header", {
2 | expect_snapshot({
3 | "Number of rows is shown"
4 | x <- memdb_frame(a = 1:3) %>% filter(a > 0)
5 | setup <- pillar::tbl_format_setup(x)
6 | tbl_format_header(x, setup)[[1]]
7 |
8 | "Number of rows still can't be shown if above 20"
9 | x <- memdb_frame(a = 1:21) %>% filter(a > 0)
10 | setup <- pillar::tbl_format_setup(x)
11 | tbl_format_header(x, setup)[[1]]
12 | })
13 | })
14 |
--------------------------------------------------------------------------------
/tests/testthat/test-query-semi-join.R:
--------------------------------------------------------------------------------
1 | test_that("print method doesn't change unexpectedly", {
2 | lf1 <- lazy_frame(x = 1, y = 2)
3 | lf2 <- lazy_frame(x = 1, z = 2)
4 | expect_snapshot(
5 | sql_build(semi_join(lf1, lf2 %>% filter(z == 2)))
6 | )
7 | })
8 |
9 | test_that("generated sql doesn't change unexpectedly", {
10 | lf <- lazy_frame(x = 1, y = 2)
11 | expect_snapshot(semi_join(lf, lf))
12 | expect_snapshot(anti_join(lf, lf))
13 | })
14 |
--------------------------------------------------------------------------------
/tests/testthat/test-query-set-op.R:
--------------------------------------------------------------------------------
1 | test_that("print method doesn't change unexpectedly", {
2 | lf1 <- lazy_frame(x = 1, y = 2, .name = "lf1")
3 | lf2 <- lazy_frame(x = 1, z = 2, .name = "lf2")
4 | lf3 <- lazy_frame(x = 1, z = 2, .name = "lf3")
5 | expect_snapshot(sql_build(union(lf1, lf2) %>% union_all(lf3)))
6 | })
7 |
8 | test_that("generated sql doesn't change unexpectedly", {
9 | lf <- lazy_frame(x = 1, y = 2)
10 | expect_snapshot(union(lf, lf))
11 | expect_snapshot(setdiff(lf, lf))
12 | expect_snapshot(intersect(lf, lf))
13 |
14 | expect_snapshot(union(lf, lf, all = TRUE))
15 | expect_snapshot(setdiff(lf, lf, all = TRUE))
16 | expect_snapshot(intersect(lf, lf, all = TRUE))
17 | })
18 |
--------------------------------------------------------------------------------
/tests/testthat/test-schema.R:
--------------------------------------------------------------------------------
1 | test_that("can construct and print", {
2 | expect_snapshot(in_schema("schema", "table"))
3 | expect_snapshot(in_catalog("catalog", "schema", "table"))
4 | })
5 |
6 | test_that("escaped as needed", {
7 | con <- simulate_dbi()
8 | expect_equal(as.sql(in_schema("s", "t"), con), ident_q("`s`.`t`"))
9 | expect_equal(as.sql(in_schema(sql("s"), sql("t")), con), ident_q("s.t"))
10 | expect_equal(as.sql(in_catalog("c", "s", "t"), con), ident_q("`c`.`s`.`t`"))
11 | expect_equal(as.sql(in_catalog(sql("c"), sql("s"), sql("t")), con), ident_q("c.s.t"))
12 | })
13 |
14 | test_that("can copy and collect with schema or Id", {
15 | con <- local_sqlite_con_with_aux()
16 | df <- tibble(x = 1:10)
17 |
18 | db <- copy_to(con, df, in_schema("aux", "db1"), temporary = FALSE)
19 | expect_equal(collect(db), df)
20 | expect_equal(collect(filter(db, x < 2)), df[1, ])
21 |
22 | db <- copy_to(con, df, Id(schema = "aux", table = "db2"), temporary = FALSE)
23 | expect_equal(collect(db), df)
24 | expect_equal(collect(filter(db, x < 2)), df[1, ])
25 | })
26 |
27 | test_that("quoted identifier correctly escaped", {
28 | con <- simulate_dbi()
29 | x2 <- ident_q('"x"')
30 | expect_equal(as.sql(x2), x2)
31 | expect_equal(escape(x2, con = con), sql('"x"'))
32 |
33 | expect_equal(sql_vector(ident_q(), collapse = NULL, con = con), sql())
34 | expect_equal(sql_vector(ident_q(), parens = FALSE, collapse = "", con = con), sql(""))
35 | expect_equal(sql_vector(ident_q(), parens = TRUE, collapse = "", con = con), sql("()"))
36 | })
37 |
--------------------------------------------------------------------------------
/tests/testthat/test-sql-build.R:
--------------------------------------------------------------------------------
1 | test_that("rendering table wraps in SELECT *", {
2 | out <- copy_to_test("sqlite", tibble(x = 1), name = "test-sql-build")
3 | expect_snapshot(out %>% sql_render())
4 | expect_equal(out %>% collect(), tibble(x = 1))
5 | })
6 |
--------------------------------------------------------------------------------
/tests/testthat/test-sql-expr.R:
--------------------------------------------------------------------------------
1 | test_that("NULL becomes SQL NULL", {
2 | con <- simulate_dbi()
3 | expect_equal(sql_expr(NULL), sql("NULL"))
4 | })
5 |
6 | test_that("atomic vectors are escaped", {
7 | con <- simulate_dbi()
8 |
9 | expect_equal(sql_expr(2, con = con), sql("2.0"))
10 | expect_equal(sql_expr("x", con = con), sql("'x'"))
11 | })
12 |
13 | test_that("user infix functions have % stripped", {
14 | con <- simulate_dbi()
15 |
16 | expect_equal(sql_expr(x %like% y, con = con), sql("x LIKE y"))
17 | })
18 |
19 | test_that("string function names are not quoted", {
20 | con <- simulate_dbi()
21 |
22 | f <- "foo"
23 | expect_equal(sql_expr((!!f)(), con = con), sql("FOO()"))
24 | })
25 |
26 | test_that("correct number of parens", {
27 | con <- simulate_dbi()
28 |
29 | expect_equal(sql_expr((1L), con = con), sql("(1)"))
30 | })
31 |
--------------------------------------------------------------------------------
/tests/testthat/test-sql.R:
--------------------------------------------------------------------------------
1 | test_that("can concatenate sql vector without supplying connection", {
2 | expect_equal(c(sql("x")), sql("x"))
3 | expect_equal(c(sql("x"), "x"), sql("x", "'x'"))
4 | expect_equal(c(ident("x")), sql("`x`"))
5 | })
6 |
7 | test_that("can format sql", {
8 | expect_snapshot(sql())
9 | expect_snapshot(sql(a = "x", "y"))
10 | })
11 |
--------------------------------------------------------------------------------
/tests/testthat/test-src_dbi.R:
--------------------------------------------------------------------------------
1 | test_that("tbl and src classes include connection class", {
2 |
3 | mf <- memdb_frame(x = 1, y = 2)
4 | expect_true(inherits(mf, "tbl_SQLiteConnection"))
5 | expect_true(inherits(mf$src, "src_SQLiteConnection"))
6 | })
7 |
8 | test_that("generates S3 class based on S4 class name", {
9 | con <- DBI::dbConnect(RSQLite::SQLite(), ":memory:")
10 | expect_equal(
11 | connection_s3_class(con),
12 | c("src_SQLiteConnection", "src_dbi", "src_sql", "src")
13 | )
14 |
15 | on.exit(removeClass("Foo2"))
16 | on.exit(removeClass("Foo1"))
17 |
18 | Foo1 <- setClass("Foo1", contains = "DBIConnection")
19 | Foo2 <- setClass("Foo2", contains = "Foo1")
20 | expect_equal(
21 | connection_s3_class(Foo2()),
22 | c("src_Foo2", "src_Foo1", "src_dbi", "src_sql", "src")
23 | )
24 | })
25 |
--------------------------------------------------------------------------------
/tests/testthat/test-tbl-lazy.R:
--------------------------------------------------------------------------------
1 | test_that("adds src class", {
2 | tb <- tbl_lazy(mtcars, con = simulate_sqlite())
3 | expect_s3_class(tb, "tbl_SQLiteConnection")
4 | })
5 |
6 | test_that("argument src is deprecated", {
7 | expect_snapshot(error = TRUE, tbl_lazy(mtcars, src = simulate_sqlite()))
8 | })
9 |
10 | test_that("cannot convert tbl_lazy to data.frame", {
11 | expect_snapshot(
12 | error = TRUE,
13 | as.data.frame(tbl_lazy(mtcars, con = simulate_sqlite()))
14 | )
15 | })
16 |
17 | test_that("dim() works for tbl_lazy", {
18 | expect_equal(dim(tbl_lazy(mtcars)), c(NA, 11))
19 | })
20 |
21 | test_that("has print method", {
22 | expect_snapshot(tbl_lazy(mtcars))
23 | })
24 |
25 | test_that("support colwise variants", {
26 | mf <- memdb_frame(x = 1:5, y = factor(letters[1:5]))
27 | exp <- mf %>% collect() %>% mutate(y = as.character(y))
28 |
29 | expect_message(
30 | mf1 <- dplyr::mutate_if(mf, is.factor, as.character),
31 | "on the first 100 rows"
32 | )
33 | compare_tbl(mf1, exp)
34 |
35 | mf2 <- dplyr::mutate_at(mf, "y", as.character)
36 | compare_tbl(mf2, exp)
37 | })
38 |
39 | test_that("base source of tbl_lazy is always 'df'", {
40 | out <- lazy_frame(x = 1, y = 5) %>% sql_build()
41 | expect_equal(out, base_query(table_path("`df`")))
42 | })
43 |
44 | test_that("names() inform that they aren't meant to be used", {
45 | expect_snapshot(names(lazy_frame(x = 1)))
46 | })
47 |
48 | test_that("$ aborts when not used with src or lazy_query", {
49 | lf <- lazy_frame(x = 1)
50 | expect_no_error(lf$src)
51 | expect_no_error(lf$lazy_query)
52 | expect_snapshot_error(lf$x)
53 | })
54 |
--------------------------------------------------------------------------------
/tests/testthat/test-translate-sql-paste.R:
--------------------------------------------------------------------------------
1 | test_that("basic prefix operation", {
2 | local_con(simulate_dbi())
3 |
4 | paste <- sql_paste("")
5 | x <- ident("x")
6 | y <- ident("y")
7 |
8 | expect_equal(paste(x), sql("CONCAT_WS('', `x`)"))
9 | expect_equal(paste(x, y), sql("CONCAT_WS('', `x`, `y`)"))
10 | expect_equal(paste(x, y, sep = " "), sql("CONCAT_WS(' ', `x`, `y`)"))
11 | })
12 |
13 | test_that("basic infix operation", {
14 | local_con(simulate_dbi())
15 |
16 | paste <- sql_paste_infix("", "&&", function(x) sql_expr(cast((!!x) %as% text)))
17 | x <- ident("x")
18 | y <- ident("y")
19 |
20 | expect_equal(paste(x), sql("CAST(`x` AS text)"))
21 | expect_equal(paste(x, y), sql("`x` && `y`"))
22 | expect_equal(paste(x, y, sep = " "), sql("`x` && ' ' && `y`"))
23 | })
24 |
--------------------------------------------------------------------------------
/tests/testthat/test-translate-sql-quantile.R:
--------------------------------------------------------------------------------
1 | test_that("quantile and median don't change without warning", {
2 | local_con(simulate_dbi())
3 | expect_snapshot(test_translate_sql(quantile(x, 0.75, na.rm = TRUE), window = FALSE))
4 | expect_snapshot(test_translate_sql(quantile(x, 0.75, na.rm = TRUE), vars_group = "g"))
5 | expect_snapshot(test_translate_sql(median(x, na.rm = TRUE), window = FALSE))
6 | expect_snapshot(test_translate_sql(median(x, na.rm = TRUE), vars_group = "g"))
7 | })
8 |
9 | test_that("checks for invalid probs", {
10 | expect_error(check_probs("a"), "number")
11 | expect_error(check_probs(1:3), "vector")
12 | })
13 |
--------------------------------------------------------------------------------
/tests/testthat/test-utils.R:
--------------------------------------------------------------------------------
1 | test_that("Successful and not-successful commands are identified", {
2 | expect_true(succeeds("success"))
3 | expect_false(succeeds(x - 1, quiet = TRUE))
4 | })
5 |
6 | test_that("Returns error if no characters are passed", {
7 | expect_error(c_character(1, 2))
8 | })
9 |
--------------------------------------------------------------------------------
/tests/testthat/test-verb-do.R:
--------------------------------------------------------------------------------
1 | test_that("ungrouped data collected first", {
2 | out <- memdb_frame(x = 1:2) %>% do(head(.))
3 | expect_equal(out, tibble(x = 1:2))
4 | })
5 |
6 | test_that("named argument become list columns", {
7 | mf <- memdb_frame(
8 | g = rep(1:3, 1:3),
9 | x = 1:6
10 | ) %>% group_by(g)
11 |
12 | out <- mf %>% do(nrow = nrow(.), ncol = ncol(.))
13 | expect_equal(out$nrow, list(1, 2, 3))
14 | expect_equal(out$ncol, list(2, 2, 2))
15 | })
16 |
17 | test_that("unnamed results bound together by row", {
18 | mf <- memdb_frame(
19 | g = c(1, 1, 2, 2),
20 | x = c(3, 9, 4, 9)
21 | ) %>% group_by(g)
22 |
23 | first <- mf %>% do(head(., 1)) %>% ungroup()
24 | compare_tbl(first, tibble(g = c(1, 2), x = c(3, 4)))
25 | })
26 |
27 | test_that("unnamed results must be data frames", {
28 | mf <- memdb_frame(
29 | g = c(1, 1, 2, 2),
30 | x = c(3, 9, 4, 9)
31 | ) %>% group_by(g)
32 |
33 | expect_snapshot(error = TRUE, mf %>% do(nrow(.)))
34 | })
35 |
36 | test_that("Results respect select", {
37 | mf <- memdb_frame(
38 | g = c(1, 1, 2, 2),
39 | x = c(3, 9, 4, 9),
40 | y = 1:4,
41 | z = 4:1
42 | ) %>% group_by(g)
43 |
44 | expect_message(out <- mf %>% select(x) %>% do(ncol = ncol(.)))
45 | expect_equal(out$g, c(1, 2))
46 | expect_equal(out$ncol, list(2L, 2L))
47 | })
48 |
49 | test_that("results independent of chunk_size", {
50 | mf <- memdb_frame(
51 | g = rep(1:3, 1:3),
52 | x = 1:6
53 | ) %>% group_by(g)
54 |
55 | nrows <- function(group, n) {
56 | unlist(do(group, nrow = nrow(.), .chunk_size = n)$nrow)
57 | }
58 |
59 | expect_equal(nrows(mf, 1), c(1, 2, 3))
60 | expect_equal(nrows(mf, 2), c(1, 2, 3))
61 | expect_equal(nrows(mf, 10), c(1, 2, 3))
62 | })
63 |
64 | test_that("named argument become list columns", {
65 | mf <- memdb_frame(
66 | g = rep(1:3, 1:3),
67 | x = 1:6
68 | ) %>% group_by(g)
69 |
70 | # mix named and unnamed
71 | expect_snapshot(error = TRUE, mf %>% do(nrow = nrow(.), ncol(.)))
72 |
73 | # multiple unnamed
74 | expect_snapshot(error = TRUE, mf %>% do(nrow(.), ncol(.)))
75 |
76 | # old syntax
77 | expect_snapshot(error = TRUE, mf %>% do(.f = nrow))
78 | })
79 |
--------------------------------------------------------------------------------
/tests/testthat/test-verb-head.R:
--------------------------------------------------------------------------------
1 | test_that("head limits rows", {
2 | db <- head(memdb_frame(x = 1:100), 10)
3 |
4 | expect_equal(sql_build(db)$limit, 10)
5 | expect_equal(nrow(collect(db)), 10)
6 | })
7 |
8 | test_that("two heads are equivalent to one", {
9 | out <- lazy_frame(x = 1:10) %>% head(3) %>% head(5)
10 | expect_equal(out$lazy_query$limit, 3)
11 | })
12 |
13 | test_that("non-integer automatically truncated", {
14 | out <- lazy_frame(x = 1:10) %>% head(3.5)
15 | expect_equal(out$lazy_query$limit, 3)
16 | })
17 |
18 | test_that("can get 0 rows", {
19 | db <- memdb_frame(x = 1)
20 | out <- collect(head(db, 0))
21 | expect_equal(out, tibble(x = double()))
22 | })
23 |
24 | test_that("n must be valid", {
25 | db <- memdb_frame(x = 1)
26 |
27 | expect_error(head(db, "x"), "non-negative integer")
28 | expect_error(head(db, 1:2), "non-negative integer")
29 | expect_error(head(db, -1), "non-negative integer")
30 | expect_error(head(db, Inf), NA)
31 | })
32 |
33 | test_that("tail not supported", {
34 | lf <- lazy_frame(x = 1)
35 | expect_error(tail(lf), "not supported")
36 | })
37 |
--------------------------------------------------------------------------------
/tests/testthat/test-verb-pull.R:
--------------------------------------------------------------------------------
1 | test_that("default extracts last var from data frame", {
2 | df <- memdb_frame(x = 1:3, z = 4:6)
3 | expect_equal(pull(df), 4:6)
4 | })
5 |
6 | test_that("can extract by name, or positive/negative position", {
7 | x <- 1:3
8 | df <- memdb_frame(x = x, y = 4:6)
9 |
10 | expect_equal(pull(df, x), x)
11 | expect_equal(pull(df, 1L), x)
12 | expect_equal(pull(df, 1), x)
13 | expect_equal(pull(df, -2), x)
14 | expect_equal(pull(df, -2L), x)
15 | })
16 |
17 | test_that("extracts correct column from grouped tbl", {
18 | mf <- memdb_frame(id = "a", value = 42)
19 | gf <- mf %>% group_by(id)
20 |
21 | expect_equal(pull(mf, value), 42)
22 | })
23 |
24 | test_that("doesn't unnecessarily select", {
25 | mf <- memdb_frame(x = c(3, 1, 2))
26 | # no warning about select after arrange
27 | expect_warning(out <- mf %>% arrange(x) %>% pull(), NA)
28 | expect_equal(out, 1:3)
29 | })
30 |
31 | test_that("can extract named vectors", {
32 | x <- 1:3
33 | y <- letters[x]
34 | df <- memdb_frame(x = x, y = y)
35 | xn <- set_names(x, y)
36 |
37 | expect_equal(pull(df, x), x)
38 | expect_equal(pull(df, x, y), xn)
39 | expect_equal(pull(df, 1, 2), xn)
40 | expect_equal(names(pull(df, x, y)), y)
41 | })
42 |
43 |
44 | test_that("ungroup() produces nice error messages", {
45 | expect_snapshot(error = TRUE, {
46 | memdb_frame(x = 1) %>% pull(non_existent)
47 | memdb_frame(x = 1) %>% pull("non_existent")
48 | memdb_frame(x = 1) %>% pull(1000)
49 |
50 | memdb_frame(x = 1) %>% pull(x, "name_non_existent")
51 | })
52 | })
53 |
54 |
--------------------------------------------------------------------------------
/tests/testthat/test-verb-window.R:
--------------------------------------------------------------------------------
1 | test_that("window_order errors for data frame", {
2 | expect_snapshot({
3 | (expect_error(window_order(data.frame(x = 1))))
4 | (expect_error(window_order("a")))
5 | })
6 | })
7 |
8 | test_that("window_order only accepts variables", {
9 | lf <- lazy_frame(x = 1, y = 1)
10 | expect_equal(window_order(lf, x, y) %>% op_sort(), unname(exprs(x, y)))
11 | expect_equal(window_order(lf, x, desc(y)) %>% op_sort(), unname(exprs(x, desc(y))))
12 |
13 | expect_snapshot({
14 | (expect_error(window_order(lf, x + y)))
15 | })
16 | })
17 |
18 | test_that("window order works afer renaming variable", {
19 | expect_snapshot({
20 | lazy_frame(x = 1, y = 1) %>%
21 | window_order(y) %>%
22 | rename(y2 = y) %>%
23 | mutate(x_cum = cumsum(x))
24 |
25 | lazy_frame(x = 1, y = 1) %>%
26 | rename(y2 = y) %>%
27 | window_order(y2) %>%
28 | mutate(x_cum = cumsum(x))
29 | })
30 | })
31 |
32 | test_that("window_frame errors for data frame", {
33 | expect_snapshot({
34 | (expect_error(window_frame(data.frame(x = 1))))
35 | })
36 | })
37 |
--------------------------------------------------------------------------------
/vignettes/.gitignore:
--------------------------------------------------------------------------------
1 | *.html
2 | *.R
3 | figure
4 | *.md
5 | rsconnect
6 |
--------------------------------------------------------------------------------
/vignettes/setup/_mssql.Rmd:
--------------------------------------------------------------------------------
1 | # MySQL
2 |
3 | ## Install drivers
4 |
5 | ```
6 | brew tap microsoft/mssql-release https://github.com/Microsoft/homebrew-mssql-release
7 | brew update
8 | brew install msodbcsql17 mssql-tools
9 | ```
10 |
11 | Check available:
12 |
13 | ```{r}
14 | odbc::odbcListDrivers()
15 | edit_file("/usr/local/etc/odbcinst.ini")
16 | Sys.setenv("GITHUB_MSSQL" = "true")
17 | ```
18 |
19 | ## Start
20 |
21 | ```
22 | docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=Password12' -t -i -p 1433:1433 microsoft/mssql-server-linux
23 |
24 | sqlcmd -U SA -P 'Password12' -Q 'CREATE DATABASE test;'
25 | ```
26 |
27 | ## Connect
28 |
29 | ```{r, eval = FALSE}
30 | con <- DBI::dbConnect(odbc::odbc(),
31 | driver = "ODBC Driver 17 for SQL Server",
32 | database = "test",
33 | uid = "SA",
34 | pwd = "Password12",
35 | server = "localhost",
36 | port = 1433
37 | )
38 | ```
39 |
--------------------------------------------------------------------------------
/vignettes/setup/_mysql.Rmd:
--------------------------------------------------------------------------------
1 | # MariaDB
2 |
3 | ## Install
4 |
5 | ```
6 | brew install mariadb
7 | mysql_install_db --verbose --user=hadley --basedir=/usr/local \
8 | --datadir=/User/hadley/db/mariadb --tmpdir=/tmp
9 |
10 | mysqld --datadir='/Users/hadley/db/mysql'
11 |
12 | mysql -u root -e "CREATE DATABASE lahman;"
13 | mysql -u root -e "CREATE DATABASE nycflights13;"
14 | mysql -u root -e "CREATE DATABASE test;"
15 | ```
16 |
17 | ## Start
18 |
19 | ```
20 | mysqld --datadir='/Users/hadley/db/mysql'
21 | ```
22 |
23 | ## Connect
24 |
25 | ```{r, eval = FALSE}
26 | install.packages("RMariaDB")
27 |
28 | con <- dbConnect(RMariaDB::MariaDB(), dbname = "lahman", username = "root", password = "")
29 | dbListTables(con)
30 | ```
31 |
32 | # Shut down
33 |
34 | ```
35 | mysqladmin shutdown -u root -p
36 | ```
37 |
--------------------------------------------------------------------------------
/vignettes/setup/_postgres.Rmd:
--------------------------------------------------------------------------------
1 | # PostgreSQL
2 |
3 | ## Install
4 |
5 | First install PostgreSQL, create a data directory, and create a default database.
6 |
7 | ```
8 | brew install postgresql
9 | export PGDATA=~/db/postgres # set this globally somewhere
10 | initdb
11 | createdb test
12 |
13 | psql -c "CREATE USER postgres WITH PASSWORD 'password';"
14 | psql -c "ALTER USER postgres WITH SUPERUSER;"
15 | ```
16 |
17 | ## Start
18 |
19 | ```
20 | pg_ctl start
21 | ```
22 |
23 | ## Connect
24 |
25 | ```{r, eval = FALSE}
26 | library(DBI)
27 | con <- dbConnect(RPostgres::Postgres(), dbname = "hadley")
28 | dbListTables(con)
29 |
30 | con <- dbConnect(
31 | RPostgres::Postgres(),
32 | dbname = "test",
33 | user = "postgres",
34 | password = "passowrd"
35 | )
36 | ```
37 |
--------------------------------------------------------------------------------
/vignettes/setup/_sap-hana.Rmd:
--------------------------------------------------------------------------------
1 | # SAP HANA
2 |
3 | ## Sign up for free cloud trial
4 |
5 | *
6 | * Go to
7 | * Click trial, then "dev" space.
8 | * Then follow
9 | * Allow access from all IP addresses.
10 | * Need to restart service every day; it's automatically stopped each night.
11 | * Need to create `test` database using database explorer
12 |
13 | ## Install drivers
14 |
15 | * Download SAP HANA installer from
16 | * Uncheck virtual machine; check "clients (mac)"
17 | * Untar download
18 | * Untar `hdb_client_mac.tgz`
19 | * `./hdb_inst`
20 |
21 | Configure odbc.init: `edit_file("/usr/local/etc/odbcinst.ini")`
22 |
23 | ```
24 | [SAP HANA]
25 | Description=SAP HANA
26 | Driver=/Applications/sap/hdbclient/libodbcHDB.dylib
27 | ```
28 |
29 | Check:
30 |
31 | ```{r}
32 | odbc::odbcListDrivers()
33 | ```
34 |
35 | ## Connect
36 |
37 | ```{r, eval = FALSE}
38 | con <- DBI::dbConnect(odbc::odbc(),
39 | driver = "SAP HANA",
40 | uid = "DBADMIN",
41 | pwd = "Password12",
42 | servernode = "a9441502-7166-4a5a-b5d8-23abe3b5009c.hana.trial-us10.hanacloud.ondemand.com:443",
43 | encrypt="true",
44 | sslValidateCertificate = "false"
45 | )
46 | class(con)
47 | #> [1] "HDB"
48 | ```
49 |
--------------------------------------------------------------------------------
/vignettes/windows.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/vignettes/windows.graffle
--------------------------------------------------------------------------------
/vignettes/windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tidyverse/dbplyr/99a70f554dba41945f6d36dd8a01b6151537076f/vignettes/windows.png
--------------------------------------------------------------------------------