From 673784f4c4193d6fe898f6e37b799c1ed32f266b Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 17 Feb 2023 12:07:33 -0800 Subject: [PATCH 001/184] chore: Add changelog template for 0.5.2 (#1868) --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 294c08c83ebf..b20024a7ea67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # PRQL Changelog +## 0.5.2 โ€” [unreleased] + +**Features**: + +**Fixes**: + +**Documentation**: + +**Web**: + +**Integrations**: + +**Internal changes**: + +**New Contributors**: + ## 0.5.1 โ€” 2022-02-17 0.5.1 contains a few fixes, and another change to how bindings handle default From 716525a20cb6052a5932cf6eea517a924d060092 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 17 Feb 2023 12:31:50 -0800 Subject: [PATCH 002/184] ci: Ensure python caching is OS-specific in GHA (#1869) --- .github/actions/build-prql-python/action.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/build-prql-python/action.yaml b/.github/actions/build-prql-python/action.yaml index 95c2429151e9..eecee5d390c8 100644 --- a/.github/actions/build-prql-python/action.yaml +++ b/.github/actions/build-prql-python/action.yaml @@ -9,6 +9,7 @@ runs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} + key: ${{ runner.os }}-python - uses: messense/maturin-action@v1 if: runner.os == 'Linux' with: From 9b21e945282130fea5619d994ff1568b4ea46f0d Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 17 Feb 2023 14:32:37 -0800 Subject: [PATCH 003/184] ci: `--no-confirm` in CI's release (#1870) --- .github/workflows/release.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index c0e6e6cc0fba..d7d944410b54 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -72,7 +72,7 @@ jobs: - uses: richb-hanover/cargo@v1.1.0 with: command: release - args: publish -x + args: publish --no-confirm -x env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} From 52518f2598dc66cd476871c56248cad60689f753 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 17 Feb 2023 21:44:39 -0800 Subject: [PATCH 004/184] ci: Another pass of GHA actions (#1871) Including concurrency & caching --- .github/actions/build-prql-python/action.yaml | 2 +- .github/workflows/test-all.yaml | 2 +- .github/workflows/test-elixir.yaml | 2 +- .github/workflows/test-java.yaml | 2 +- .github/workflows/test-js.yaml | 5 ++--- .github/workflows/test-rust.yaml | 2 +- .github/workflows/test-taskfile.yaml | 4 ++-- 7 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/actions/build-prql-python/action.yaml b/.github/actions/build-prql-python/action.yaml index eecee5d390c8..4fd788076a98 100644 --- a/.github/actions/build-prql-python/action.yaml +++ b/.github/actions/build-prql-python/action.yaml @@ -9,7 +9,7 @@ runs: - uses: Swatinem/rust-cache@v2 with: save-if: ${{ github.ref == 'refs/heads/main' }} - key: ${{ runner.os }}-python + key: python - uses: messense/maturin-action@v1 if: runner.os == 'Linux' with: diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 43de52522bb9..3646199f3c43 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -18,7 +18,7 @@ on: concurrency: # See notes in `pull-request.yaml` - group: ${{ github.workflow }}-${{ github.ref }}-test-all + group: ${{ github.workflow }}-${{ github.ref }}-all cancel-in-progress: true jobs: diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index e8fb34941c5f..5c091d8e3543 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -11,7 +11,7 @@ on: workflow_call: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-elixir cancel-in-progress: true defaults: diff --git a/.github/workflows/test-java.yaml b/.github/workflows/test-java.yaml index b3940b283861..7eac03959c0c 100644 --- a/.github/workflows/test-java.yaml +++ b/.github/workflows/test-java.yaml @@ -11,7 +11,7 @@ on: workflow_call: concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-test-java + group: ${{ github.workflow }}-${{ github.ref }}-java cancel-in-progress: true jobs: diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index 4dd0344226c4..bb25f46cc634 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -11,16 +11,15 @@ on: workflow_call: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-js cancel-in-progress: true jobs: test: - # This is copy & pasted into test-all.yaml runs-on: ${{ matrix.os }} strategy: matrix: - os: [ubuntu-latest] + os: [ubuntu-latest, macos-latest, windows-latest] steps: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index db2271459078..c983bc6dab46 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -18,7 +18,7 @@ jobs: - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 with: - key: ${{ inputs.os }}-${{ inputs.target_option }} + key: ${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - uses: jetli/wasm-bindgen-action@v0.2.0 if: inputs.target_option == '--target=wasm32-unknown-unknown' diff --git a/.github/workflows/test-taskfile.yaml b/.github/workflows/test-taskfile.yaml index 15dcec83ccb3..cb6ab15be302 100644 --- a/.github/workflows/test-taskfile.yaml +++ b/.github/workflows/test-taskfile.yaml @@ -1,5 +1,5 @@ # Workflow to check that the workflows in Taskfile pass. -name: taskfile +name: test-taskfile on: push: @@ -12,7 +12,7 @@ on: - .github/workflows/test-taskfile.yaml concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }}-taskfile cancel-in-progress: true jobs: From fe404cc6807cb4dfaf4a098be2d1495e361f555a Mon Sep 17 00:00:00 2001 From: Matthias Q <35303817+matthias-Q@users.noreply.github.com> Date: Sat, 18 Feb 2023 14:40:28 +0100 Subject: [PATCH 005/184] fix: playground link in readme badge (#1873) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f7b835a6efa8..cd843393f16a 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Website](https://img.shields.io/badge/INTRO-WEB-blue?style=for-the-badge)](https://prql-lang.org) -[![Playground](https://img.shields.io/badge/INTRO-PLAYGROUND-blue?style=for-the-badge)](https://prql-lang.org/book) +[![Playground](https://img.shields.io/badge/INTRO-PLAYGROUND-blue?style=for-the-badge)](https://prql-lang.org/playground) [![Language Docs](https://img.shields.io/badge/DOCS-BOOK-blue?style=for-the-badge)](https://prql-lang.org/book) [![Discord](https://img.shields.io/discord/936728116712316989?label=discord%20chat&style=for-the-badge)](https://discord.gg/eQcfaCmsNc) From 27f2c59369ffa63b5bed481db5b3b76b828e434e Mon Sep 17 00:00:00 2001 From: Matthias Q <35303817+matthias-Q@users.noreply.github.com> Date: Sun, 19 Feb 2023 00:28:54 +0100 Subject: [PATCH 006/184] docs: add information on treesitter grammar for prql (#1884) * add information on treesitter grammar for prql * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- book/src/internals/syntax-highlighting.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/book/src/internals/syntax-highlighting.md b/book/src/internals/syntax-highlighting.md index ec1cc7d16695..2a2c3d8b0ca7 100644 --- a/book/src/internals/syntax-highlighting.md +++ b/book/src/internals/syntax-highlighting.md @@ -26,6 +26,11 @@ an index. the Monaco editor, which we use for the Playground. The grammar is at [`playground/src/workbench/prql-syntax.js`](https://github.com/PRQL/prql/blob/main/playground/src/workbench/prql-syntax.js). +- [Tree-Sitter](https://tree-sitter.github.io/tree-sitter) โ€” used by the neovim + and helix. The grammar can be found at + [https://github.com/matthias-Q/tree-sitter-prql](https://github.com/matthias-Q/tree-sitter-prql). + This is in a very early stage. + While the [pest](https://pest.rs/) grammar at [`prql-compiler/src/parser/prql.pest`](https://github.com/PRQL/prql/blob/main/prql-compiler/src/parser/prql.pest) isn't used for syntax highlighting, it's the arbiter of truth given it currently From 4d3a4a2c321e07b4e82ac6530791bd58bb62798c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 16:17:03 -0800 Subject: [PATCH 007/184] build: Fix replacing versions in npm's lockfiles (#1886) Also simplifying the search & replace strings a bit --- prql-js/Cargo.toml | 17 +- prql-js/package-lock.json | 710 +------------------------------------- 2 files changed, 15 insertions(+), 712 deletions(-) diff --git a/prql-js/Cargo.toml b/prql-js/Cargo.toml index 2a3755f5fa25..ef5a64a6610a 100644 --- a/prql-js/Cargo.toml +++ b/prql-js/Cargo.toml @@ -44,12 +44,19 @@ tag-prefix = "" [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "package.json" -replace = ' "version": "{{version}}"' -search = ' "version": "(\d+\.\d+\.\d+)"' +replace = '$1"{{version}}"' +search = '( "version": )"(\d+\.\d+\.\d+)"' + +[[package.metadata.release.pre-release-replacements]] +exactly = 2 +file = "package-lock.json" +replace = ''' +$1 +$2"{{version}}"''' +search = '(\s+"prql-js",)\n(\s+"version": )"[\d\.]+"' [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "../playground/package-lock.json" -replace = ''' "../prql-js": { - "version": "{{version}}"''' -search = ' "../prql-js": \{\n "version": "[\d\.]+"' +replace = '''$1"{{version}}"''' +search = '( "../prql-js": \{\n "version": )"[\d\.]+"' diff --git a/prql-js/package-lock.json b/prql-js/package-lock.json index db2e089642e7..1ddd2b067761 100644 --- a/prql-js/package-lock.json +++ b/prql-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "prql-js", - "version": "0.4.2", - "lockfileVersion": 2, + "version": "0.5.1", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prql-js", - "version": "0.4.2", + "version": "0.5.1", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", @@ -997,709 +997,5 @@ "url": "https://github.com/sponsors/sindresorhus" } } - }, - "dependencies": { - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true - }, - "chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", - "pathval": "^1.1.1", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", - "dev": true - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true - }, - "deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", - "dev": true - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true - }, - "is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "requires": { - "argparse": "^2.0.1" - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "requires": { - "p-locate": "^5.0.0" - } - }, - "log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - } - }, - "loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", - "dev": true, - "requires": { - "get-func-name": "^2.0.0" - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dev": true, - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "dev": true - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "requires": { - "p-limit": "^3.0.2" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "requires": { - "picomatch": "^2.2.1" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "dev": true, - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", - "dev": true - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - } - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true - } } } From 123e5499fa752c3ebd4a462977cf38d663c2026e Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Sun, 19 Feb 2023 10:48:26 +0900 Subject: [PATCH 008/184] docs: update prqlc and prql-compiler's description in the website index page (#1877) --- website/content/_index.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/website/content/_index.md b/website/content/_index.md index c6729e872c06..035f4eaedfe2 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -380,12 +380,13 @@ tools_section: `pip install pyprql` - - link: "https://github.com/PRQL/prql" - label: "prql-compiler" + - link: https://crates.io/crates/prqlc + label: "prqlc" text: | - Reference compiler implementation. Has a CLI utility that can transpile, format and annotate PRQL queries. + A CLI for PRQL compiler, written in Rust. - `brew install prql/PRQL/prql-compiler` + `cargo install prqlc` + `brew install prql/PRQL/prqlc` integrations_section: enable: true @@ -430,12 +431,10 @@ bindings_section: label: "prqlr" text: "R bindings for prql-compiler." - - link: https://crates.io/crates/prqlc - label: "prqlc" + - link: "https://crates.io/crates/prql-compiler" + label: "prql-compiler" text: | - A CLI for PRQL compiler, written in Rust. - - `cargo install prqlc` + Reference compiler implementation, written in Rust. Transpile, format and annotate PRQL queries. comments_section: enable: true From d843658b3fe483acc44256dc96d4eb2634445e40 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:48:55 -0800 Subject: [PATCH 009/184] build(js): Fix wasm-pack's use of `.gitignore` (#1887) Closes https://github.com/PRQL/prql/issues/1875. Not sure why this used to work and doesn't work, but the `.gitignore`s were causing no files to be added to the package. Now we hackily remove them. This event adds weight to https://github.com/PRQL/prql/issues/1836 --- prql-js/README.md | 2 +- prql-js/package.json | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/prql-js/README.md b/prql-js/README.md index ba0606c2664a..500e55ee8d90 100644 --- a/prql-js/README.md +++ b/prql-js/README.md @@ -173,4 +173,4 @@ npm test [^1]: Though we would be very open to other approaches, given wasm-pack does not seem maintained, and we're eliding many of its features to build for three - targets. + targets. See for more details. diff --git a/prql-js/package.json b/prql-js/package.json index e3f7b8c0fc09..96ddb45d6bd9 100644 --- a/prql-js/package.json +++ b/prql-js/package.json @@ -18,9 +18,9 @@ }, "scripts": { "build": "npm run build:node && npm run build:bundler && npm run build:web", - "build:bundler": "wasm-pack build --target bundler --release --out-dir dist/bundler", - "build:node": "wasm-pack build --target nodejs --release --out-dir dist/node", - "build:web": "wasm-pack build --target no-modules --release --out-dir dist/web", + "build:bundler": "wasm-pack build --target bundler --release --out-dir dist/bundler && rm dist/bundler/.gitignore", + "build:node": "wasm-pack build --target nodejs --release --out-dir dist/node && rm dist/node/.gitignore", + "build:web": "wasm-pack build --target no-modules --release --out-dir dist/web && rm dist/web/.gitignore", "test": "wasm-pack test --firefox && mocha tests" }, "types": "dist/node/prql_js.d.ts", From 25e972fbe4ac3c2330ea87200b47711c350e0218 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:51:02 -0800 Subject: [PATCH 010/184] docs: Add release notes for 0.5.2 (#1888) --- CHANGELOG.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b20024a7ea67..fe771ef8a11b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,20 +1,10 @@ # PRQL Changelog -## 0.5.2 โ€” [unreleased] +## 0.5.2 โ€” 2022-02-18 -**Features**: - -**Fixes**: - -**Documentation**: - -**Web**: - -**Integrations**: +0.5.2 fixes an issue with `prql-js`'s build. -**Internal changes**: - -**New Contributors**: +This release has 7 commits from 2 contributors. ## 0.5.1 โ€” 2022-02-17 From 08c05069249612191c75bf6370c697287c37a26d Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 18:11:47 -0800 Subject: [PATCH 011/184] chore: Bump versions to 0.5.2 (#1889) --- Cargo.lock | 20 +++++++++---------- Cargo.toml | 2 +- playground/package-lock.json | 2 +- prql-compiler/prql-compiler-macros/Cargo.toml | 2 +- prql-compiler/prqlc/Cargo.toml | 2 +- prql-elixir/native/prql/Cargo.toml | 2 +- prql-js/package-lock.json | 4 ++-- prql-js/package.json | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc1e658fc3ff..fbf59f6863f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -627,7 +627,7 @@ dependencies = [ [[package]] name = "compile-files" -version = "0.5.1" +version = "0.5.2" dependencies = [ "prql-compiler", ] @@ -1626,7 +1626,7 @@ dependencies = [ [[package]] name = "mdbook-prql" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "clap 4.1.1", @@ -2120,7 +2120,7 @@ dependencies = [ [[package]] name = "prql" -version = "0.5.1" +version = "0.5.2" dependencies = [ "prql-compiler", "rustler", @@ -2128,7 +2128,7 @@ dependencies = [ [[package]] name = "prql-compiler" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "ariadne", @@ -2161,7 +2161,7 @@ dependencies = [ [[package]] name = "prql-compiler-macros" -version = "0.5.1" +version = "0.5.2" dependencies = [ "prql-compiler", "syn", @@ -2169,7 +2169,7 @@ dependencies = [ [[package]] name = "prql-java" -version = "0.5.1" +version = "0.5.2" dependencies = [ "jni", "prql-compiler", @@ -2177,7 +2177,7 @@ dependencies = [ [[package]] name = "prql-js" -version = "0.5.1" +version = "0.5.2" dependencies = [ "console_error_panic_hook", "prql-compiler", @@ -2187,7 +2187,7 @@ dependencies = [ [[package]] name = "prql-lib" -version = "0.5.1" +version = "0.5.2" dependencies = [ "libc", "prql-compiler", @@ -2196,7 +2196,7 @@ dependencies = [ [[package]] name = "prql-python" -version = "0.5.1" +version = "0.5.2" dependencies = [ "insta", "prql-compiler", @@ -2206,7 +2206,7 @@ dependencies = [ [[package]] name = "prqlc" -version = "0.5.1" +version = "0.5.2" dependencies = [ "anyhow", "ariadne", diff --git a/Cargo.toml b/Cargo.toml index b51460ce07fc..5507308038bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ edition = "2021" license = "Apache-2.0" repository = "https://github.com/PRQL/prql" rust-version = "1.65.0" -version = "0.5.1" +version = "0.5.2" [profile.release.package.prql-js] # Tell `rustc` to optimize for small code size. diff --git a/playground/package-lock.json b/playground/package-lock.json index a6a833ef6c20..a7e16715fc2f 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -28,7 +28,7 @@ } }, "../prql-js": { - "version": "0.5.1", + "version": "0.5.2", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/prql-compiler/prql-compiler-macros/Cargo.toml b/prql-compiler/prql-compiler-macros/Cargo.toml index ee28586b7d37..460ff18a7d27 100644 --- a/prql-compiler/prql-compiler-macros/Cargo.toml +++ b/prql-compiler/prql-compiler-macros/Cargo.toml @@ -14,7 +14,7 @@ proc_macro = true test = false [dependencies] -prql-compiler = {path = "..", default-features = false, version = "0.5.1" } +prql-compiler = {path = "..", default-features = false, version = "0.5.2" } syn = "1.0" [package.metadata.release] diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 7a70d90ae406..322148aae867 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6.1" env_logger = {version = "0.9.1", features = ["termcolor"]} itertools = "0.10.3" notify = "^5.1.0" -prql-compiler = {path = '..', version = "0.5.1" } +prql-compiler = {path = '..', version = "0.5.2" } serde_json = "1.0.81" serde_yaml = "0.9.1" walkdir = "^2.3.2" diff --git a/prql-elixir/native/prql/Cargo.toml b/prql-elixir/native/prql/Cargo.toml index cffb57f7634f..51fdb36cc87c 100644 --- a/prql-elixir/native/prql/Cargo.toml +++ b/prql-elixir/native/prql/Cargo.toml @@ -16,6 +16,6 @@ name = "prql" path = "src/lib.rs" [dependencies] -prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.1" } +prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.2" } [target.'cfg(not(any(target_family="wasm")))'.dependencies] rustler = "0.27.0" diff --git a/prql-js/package-lock.json b/prql-js/package-lock.json index 1ddd2b067761..82d80abcb852 100644 --- a/prql-js/package-lock.json +++ b/prql-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "prql-js", - "version": "0.5.1", + "version": "0.5.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prql-js", - "version": "0.5.1", + "version": "0.5.2", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/prql-js/package.json b/prql-js/package.json index 96ddb45d6bd9..06e58721e5ed 100644 --- a/prql-js/package.json +++ b/prql-js/package.json @@ -24,5 +24,5 @@ "test": "wasm-pack test --firefox && mocha tests" }, "types": "dist/node/prql_js.d.ts", - "version": "0.5.1" + "version": "0.5.2" } From cc67f9c38f74ee5ecf2a99a1525d77007ac53090 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 18:13:57 -0800 Subject: [PATCH 012/184] ci: Fix `pull_request_target` concurrency (#1890) --- .github/workflows/pull-request-target.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-target.yaml b/.github/workflows/pull-request-target.yaml index ff60c7b89406..0793964f36d0 100644 --- a/.github/workflows/pull-request-target.yaml +++ b/.github/workflows/pull-request-target.yaml @@ -5,7 +5,8 @@ on: types: [opened, edited, synchronize, labeled, closed] concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + # Generally we use `github.ref`, but in pull_request_target, that's always `main`. + group: ${{ github.workflow }}-${{ github.event.pull_request.number }} cancel-in-progress: true jobs: @@ -20,8 +21,10 @@ jobs: requireScope: false backport: + # Backport to `web` branch on `pr-backport-web` + name: Backport to `web` branch runs-on: ubuntu-latest - # Confirm that it's merged and has a label to ensure nothing is merged without oversight + # Confirm that it's merged and has a label to ensure nothing is backported without oversight if: | github.event.pull_request.merged && ( From ee670481811a0b5142b8d32ef83864e2c0376987 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 18:22:57 -0800 Subject: [PATCH 013/184] chore: Add new contributor to changelog (#1891) * chore: Add new contributor to changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe771ef8a11b..bec0b920bb4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,15 @@ ## 0.5.2 โ€” 2022-02-18 -0.5.2 fixes an issue with `prql-js`'s build. +0.5.2 is a tiny release to fixes an issue with `prql-js`'s build in yesterday's +0.5.1 release. This release has 7 commits from 2 contributors. +**New Contributors**: + +- @matthias-Q, with #1873 + ## 0.5.1 โ€” 2022-02-17 0.5.1 contains a few fixes, and another change to how bindings handle default From 396b912d92960007a9f5635849ffd3b55a51af9f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 18 Feb 2023 18:37:50 -0800 Subject: [PATCH 014/184] chore: Add changelog template for 0.5.3 (#1892) --- CHANGELOG.md | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bec0b920bb4d..9f7a48567a3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,25 @@ # PRQL Changelog +## 0.5.3 โ€” [unreleased] + +**Features**: + +**Fixes**: + +**Documentation**: + +**Web**: + +**Integrations**: + +**Internal changes**: + +**New Contributors**: + ## 0.5.2 โ€” 2022-02-18 -0.5.2 is a tiny release to fixes an issue with `prql-js`'s build in yesterday's -0.5.1 release. +0.5.2 is a tiny release to fix an build issue in yesterday's `prql-js` 0.5.1 +release. This release has 7 commits from 2 contributors. From c79c5f1e2b54c021538da2954352e9c3207fca4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Sun, 19 Feb 2023 11:17:49 +0100 Subject: [PATCH 015/184] feat!: loop (#1642) --- CHANGELOG.md | 2 + book/README.md | 2 +- book/book.toml | 2 +- book/src/SUMMARY.md | 4 +- book/src/integrations/jupyter.md | 2 +- book/src/integrations/rill.md | 2 +- book/src/internals/name-resolving.md | 2 +- .../README.md} | 2 +- .../standard-library/from-text.md | 63 ++ .../standard-library/loop.md | 50 ++ book/src/syntax.md | 2 +- book/src/transforms/from_text.md | 61 -- .../README-0.prql} | 0 .../standard-library/from-text-0.prql} | 0 .../standard-library/from-text-1.prql} | 0 .../standard-library/from-text-2.prql} | 0 .../standard-library/loop-0.prql | 7 + .../snapshot__@examples__cte-0.prql.snap | 22 +- ...snapshot__@examples__employees-0.prql.snap | 21 +- ...snapshot__@examples__employees-1.prql.snap | 27 +- ...snapshot__@examples__employees-2.prql.snap | 23 +- ...snapshot__@examples__employees-3.prql.snap | 11 +- .../snapshot__@examples__misc-0.prql.snap | 15 +- ...snapshot__@examples__variables-0.prql.snap | 3 +- ...snapshot__@examples__variables-1.prql.snap | 9 +- .../snapshot__@introduction-0.prql.snap | 5 +- ...__@language-features__distinct-2.prql.snap | 3 +- ..._@language-features__s-strings-3.prql.snap | 13 +- ...res__standard-library__README-0.prql.snap} | 3 +- ...__standard-library__from-text-0.prql.snap} | 6 +- ...__standard-library__from-text-1.prql.snap} | 2 +- ...__standard-library__from-text-2.prql.snap} | 2 +- ...atures__standard-library__loop-0.prql.snap | 34 + .../snapshot__@queries__pipelines-2.prql.snap | 9 +- .../snapshot__@queries__variables-0.prql.snap | 4 +- .../snapshots/snapshot__@syntax-5.prql.snap | 3 +- .../snapshot__@transforms__group-2.prql.snap | 3 +- .../snapshot__@transforms__sort-3.prql.snap | 17 +- .../snapshot__@transforms__sort-5.prql.snap | 7 +- .../snapshot__@transforms__window-4.prql.snap | 3 +- ...res__standard-library__README-0.prql.snap} | 2 +- ...__standard-library__from-text-0.prql.snap} | 2 +- ...__standard-library__from-text-1.prql.snap} | 2 +- ...__standard-library__from-text-2.prql.snap} | 2 +- ...atures__standard-library__loop-0.prql.snap | 13 + prql-compiler/src/ast/pl/expr.rs | 1 + prql-compiler/src/ast/pl/fold.rs | 1 + prql-compiler/src/ast/pl/types.rs | 8 +- prql-compiler/src/ast/rq/fold.rs | 1 + prql-compiler/src/ast/rq/transform.rs | 1 + prql-compiler/src/semantic/lowering.rs | 33 +- prql-compiler/src/semantic/std.prql | 1 + prql-compiler/src/semantic/transforms.rs | 8 + .../prql_compiler__test__prql_to_sql_2.snap | 3 +- prql-compiler/src/sql/anchor.rs | 87 ++- prql-compiler/src/sql/context.rs | 61 +- prql-compiler/src/sql/gen_expr.rs | 75 +- prql-compiler/src/sql/gen_query.rs | 687 ++++++++++-------- prql-compiler/src/sql/mod.rs | 35 + prql-compiler/src/sql/preprocess.rs | 68 +- ...query__test__variable_after_aggregate.snap | 3 +- prql-compiler/src/test.rs | 291 +++++--- .../tests/integration/queries/loop.prql | 7 + .../integration__tests__test@loop.prql.snap | 12 + 64 files changed, 1107 insertions(+), 743 deletions(-) rename book/src/language-features/{standard-library.md => standard-library/README.md} (98%) create mode 100644 book/src/language-features/standard-library/from-text.md create mode 100644 book/src/language-features/standard-library/loop.md rename book/tests/prql/language-features/{standard-library-0.prql => standard-library/README-0.prql} (100%) rename book/tests/prql/{transforms/from_text-0.prql => language-features/standard-library/from-text-0.prql} (100%) rename book/tests/prql/{transforms/from_text-1.prql => language-features/standard-library/from-text-1.prql} (100%) rename book/tests/prql/{transforms/from_text-2.prql => language-features/standard-library/from-text-2.prql} (100%) create mode 100644 book/tests/prql/language-features/standard-library/loop-0.prql rename book/tests/snapshots/{snapshot__@language-features__standard-library-0.prql.snap => snapshot__@language-features__standard-library__README-0.prql.snap} (84%) rename book/tests/snapshots/{snapshot__@transforms__from_text-0.prql.snap => snapshot__@language-features__standard-library__from-text-0.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@transforms__from_text-1.prql.snap => snapshot__@language-features__standard-library__from-text-1.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@transforms__from_text-2.prql.snap => snapshot__@language-features__standard-library__from-text-2.prql.snap} (91%) create mode 100644 book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap => snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap} (76%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap => snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap} (69%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap => snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap} (76%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap => snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap} (82%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap create mode 100644 prql-compiler/tests/integration/queries/loop.prql create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f7a48567a3e..4a3c85b96daf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ **Features**: +- `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) + **Fixes**: **Documentation**: diff --git a/book/README.md b/book/README.md index ec088b512dcb..57b803d93865 100644 --- a/book/README.md +++ b/book/README.md @@ -1,4 +1,4 @@ -# PRQL Language Book +# PRQL language book These docs serve as a language book, for users of the language. They should be friendly & accessible, at a minimum to those who understand basic SQL. diff --git a/book/book.toml b/book/book.toml index f503dc2bb7a9..8c10a1e4b368 100644 --- a/book/book.toml +++ b/book/book.toml @@ -2,7 +2,7 @@ description = "Modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement" language = "en" multilingual = false -title = "PRQL Language Book" +title = "PRQL language book" [output.html] additional-css = ["comparison-table.css", "mdbook-admonish.css"] diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 153e70bdb090..cc27566b74a2 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -36,7 +36,9 @@ - [Ranges](./language-features/ranges.md) - [Regex](./language-features/regex.md) - - [Stdlib](./language-features/standard-library.md) + - [Standard library](./language-features/standard-library/README.md) + - [From text](./language-features/standard-library/from-text.md) + - [Loop](./language-features/standard-library/loop.md) - [Strings](./language-features/strings.md) - [S-strings](./language-features/s-strings.md) - [F-strings](./language-features/f-strings.md) diff --git a/book/src/integrations/jupyter.md b/book/src/integrations/jupyter.md index 176a47ac11ad..7b0bdd3c063d 100644 --- a/book/src/integrations/jupyter.md +++ b/book/src/integrations/jupyter.md @@ -24,7 +24,7 @@ could to go! We bundle in `IPython` and `pandas`, though you'll need to install pip install pyprql ``` -### Set Up +### Set up Open up either an `IPython` terminal or `Jupyter` notebook. First, we need to load the extension and connect to a database. diff --git a/book/src/integrations/rill.md b/book/src/integrations/rill.md index 950e0b5fb50d..0e2f4729e32e 100644 --- a/book/src/integrations/rill.md +++ b/book/src/integrations/rill.md @@ -1,5 +1,5 @@ # Rill PRQL has had some work to integrate with Rill. See the -[Rill Issues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more +[Rill ssues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more details. diff --git a/book/src/internals/name-resolving.md b/book/src/internals/name-resolving.md index 74b590e93a14..78a153358959 100644 --- a/book/src/internals/name-resolving.md +++ b/book/src/internals/name-resolving.md @@ -50,7 +50,7 @@ three things can happen: ## Translating to SQL -When translating into a SQL statement which references only one table, there is +When translating into an SQL statement which references only one table, there is no need to reference column names with table prefix. ```prql diff --git a/book/src/language-features/standard-library.md b/book/src/language-features/standard-library/README.md similarity index 98% rename from book/src/language-features/standard-library.md rename to book/src/language-features/standard-library/README.md index 220565d5cf3d..1ccbbc5d92f8 100644 --- a/book/src/language-features/standard-library.md +++ b/book/src/language-features/standard-library/README.md @@ -1,4 +1,4 @@ -# Standard Library +# Standard library The standard library currently contains commonly used functions that are used in SQL. It's not yet as broad as we'd like, and we're very open to expanding it. diff --git a/book/src/language-features/standard-library/from-text.md b/book/src/language-features/standard-library/from-text.md new file mode 100644 index 000000000000..29229f6db0ef --- /dev/null +++ b/book/src/language-features/standard-library/from-text.md @@ -0,0 +1,63 @@ +# From text + +It's often useful to make a small table inline, for example when exploring how a +database will evaluate an expression, or to have a small lookup table inline. +This can be quite verbose in SQL. + +PRQL uses `from_text` for this. + +It accepts a few formats: + +- `format:csv` parses CSV (default), +- `format:json` parses either: + - an array of objects each of which represents a row, or + - an object with fields `columns` & `data`, where `columns` take an array of + column names and `data` takes an array of arrays. + +```prql +from_text """ +a,b,c +1,2,3 +4,5,6 +""" +derive [ + d = b + c, + answer = 20 * 2 + 2, +] +``` + +An example of adding a small lookup table: + +```prql +let temp_format_lookup = from_text format:csv """ +country_code,format +uk,C +us,F +lr,F +de,C +""" + +from temperatures +join temp_format_lookup [==country_code] +``` + +And JSON: + +```prql +let x = from_text format:json """{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}""" + +let y = from_text format:json """ + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +""" + +from x | join y [==a] +``` diff --git a/book/src/language-features/standard-library/loop.md b/book/src/language-features/standard-library/loop.md new file mode 100644 index 000000000000..97f462a8b5cc --- /dev/null +++ b/book/src/language-features/standard-library/loop.md @@ -0,0 +1,50 @@ +# Loop + +> _experimental_ + +```prql_no_test +loop {step_function} {initial_relation} +``` + +Iteratively applies `step` function to `initial` relation until the `step` +returns an empty table. Returns a relation that contains rows of initial +relation and all intermediate relations. + +This behavior could be expressed with following pseudo-code: + +``` +def loop(step, initial): + result = [] + current = initial + while current is not empty: + result = append(result, current) + current = step(current) + + return result +``` + +## Examples + +```prql +from_text format:json '[{"n": 1 }]' +loop ( + filter n<4 + select n = n+1 +) + +# returns [1, 2, 3, 4] +``` + +```admonish +Behavior of WITH RECURSIVE may depend on database configuration (MySQL). +prql-compiler assumes behavior described by +[Postgres documentation](https://www.postgresql.org/docs/15/queries-with.html#QUERIES-WITH-RECURSIVE) +and will not produce correct results for +[alternative configurations of MySQL](https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive). +``` + +```admonish +Currently, `loop` may produce references to the recursive CTE in sub-queries, +which is not supported by some database engines (SQLite). For now, we suggest you keep step +functions simple enough to fit into a single SELECT statement. +``` diff --git a/book/src/syntax.md b/book/src/syntax.md index 3c0afc5dd5b7..b23537228f4c 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -166,7 +166,7 @@ sort (-distance) sort [-distance] ``` -## Inner Transforms +## Inner transforms Parentheses are also used for transforms (such as `group` and `window`) that pass their result to an "inner transform". The example below applies the diff --git a/book/src/transforms/from_text.md b/book/src/transforms/from_text.md index 0a9b51160ca7..a05d2a4b011d 100644 --- a/book/src/transforms/from_text.md +++ b/book/src/transforms/from_text.md @@ -1,62 +1 @@ # From Text - -It's often useful to make a small table inline, for example when exploring how a -database will evaluate an expression, or to have a small lookup table inline. -This can be quite verbose in SQL. - -PRQL uses `from_text` for this. - -It accepts a few formats: - -- `format:csv`; also the default, for CSV. -- `format:json` for either: - - A list of dicts, - - or a schema of `columns` & `data>`. - -```prql -from_text """ -a,b,c -1,2,3 -4,5,6 -""" -derive [ - d = b + c, - answer = 20 * 2 + 2, -] -``` - -An example of adding a small lookup table: - -```prql -let temp_format_lookup = from_text format:csv """ -country_code,format -uk,C -us,F -lr,F -de,C -""" - -from temperatures -join temp_format_lookup [==country_code] -``` - -And JSON: - -```prql -let x = from_text format:json """{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}""" - -let y = from_text format:json """ - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -""" - -from x | join y [==a] -``` diff --git a/book/tests/prql/language-features/standard-library-0.prql b/book/tests/prql/language-features/standard-library/README-0.prql similarity index 100% rename from book/tests/prql/language-features/standard-library-0.prql rename to book/tests/prql/language-features/standard-library/README-0.prql diff --git a/book/tests/prql/transforms/from_text-0.prql b/book/tests/prql/language-features/standard-library/from-text-0.prql similarity index 100% rename from book/tests/prql/transforms/from_text-0.prql rename to book/tests/prql/language-features/standard-library/from-text-0.prql diff --git a/book/tests/prql/transforms/from_text-1.prql b/book/tests/prql/language-features/standard-library/from-text-1.prql similarity index 100% rename from book/tests/prql/transforms/from_text-1.prql rename to book/tests/prql/language-features/standard-library/from-text-1.prql diff --git a/book/tests/prql/transforms/from_text-2.prql b/book/tests/prql/language-features/standard-library/from-text-2.prql similarity index 100% rename from book/tests/prql/transforms/from_text-2.prql rename to book/tests/prql/language-features/standard-library/from-text-2.prql diff --git a/book/tests/prql/language-features/standard-library/loop-0.prql b/book/tests/prql/language-features/standard-library/loop-0.prql new file mode 100644 index 000000000000..5dccfdba14ae --- /dev/null +++ b/book/tests/prql/language-features/standard-library/loop-0.prql @@ -0,0 +1,7 @@ +from_text format:json '[{"n": 1 }]' +loop ( + filter n<4 + select n = n+1 +) + +# returns [1, 2, 3, 4] diff --git a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap index 5e55e6c27d2b..36a99fd31e3f 100644 --- a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap @@ -1,18 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "table newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\ntable average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" +expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" input_file: book/tests/prql/examples/cte-0.prql --- -WITH average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country -), -newest_employees AS ( +WITH newest_employees AS ( SELECT * FROM @@ -21,6 +12,14 @@ newest_employees AS ( tenure LIMIT 50 +), average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country ) SELECT newest_employees.name, @@ -29,3 +28,4 @@ SELECT FROM newest_employees JOIN average_salaries ON newest_employees.country = average_salaries.country + diff --git a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap index 2ed2d4eba75e..47650f37675d 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" input_file: book/tests/prql/examples/employees-0.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT AVG(salary) AS _expr_0, emp_no @@ -12,23 +12,24 @@ WITH table_1 AS ( GROUP BY emp_no ), -table_2 AS ( +table_1 AS ( SELECT t.title, - AVG(table_1._expr_0) AS avg_salary, + AVG(table_2._expr_0) AS avg_salary, dept_emp.dept_no FROM - table_1 - JOIN titles AS t ON table_1.emp_no = t.emp_no - LEFT JOIN dept_emp ON table_1.emp_no = dept_emp.emp_no + table_3 AS table_2 + JOIN titles AS t ON table_2.emp_no = t.emp_no + LEFT JOIN dept_emp ON table_2.emp_no = dept_emp.emp_no GROUP BY dept_emp.dept_no, t.title ) SELECT departments.dept_name, - table_2.title, - table_2.avg_salary + table_0.title, + table_0.avg_salary FROM - table_2 - JOIN departments ON table_2.dept_no = departments.dept_no + table_1 AS table_0 + JOIN departments ON table_0.dept_no = departments.dept_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap index 434d377e6067..88f00f10486c 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-1.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,24 +15,25 @@ WITH table_1 AS ( e.emp_no, e.gender ), -table_2 AS ( +table_1 AS ( SELECT - table_1.gender, - AVG(table_1._expr_0) AS salary_avg, - STDDEV(table_1._expr_0) AS salary_sd, + table_2.gender, + AVG(table_2._expr_0) AS salary_avg, + STDDEV(table_2._expr_0) AS salary_sd, de.dept_no FROM - table_1 - LEFT JOIN dept_emp AS de ON table_1.emp_no = de.emp_no + table_3 AS table_2 + LEFT JOIN dept_emp AS de ON table_2.emp_no = de.emp_no GROUP BY de.dept_no, - table_1.gender + table_2.gender ) SELECT departments.dept_name, - table_2.gender, - table_2.salary_avg, - table_2.salary_sd + table_0.gender, + table_0.salary_avg, + table_0.salary_sd FROM - table_2 - JOIN departments ON table_2.dept_no = departments.dept_no + table_1 AS table_0 + JOIN departments ON table_0.dept_no = departments.dept_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap index 6918730104c0..612ece4db0c6 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-2.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,25 +15,26 @@ WITH table_1 AS ( e.emp_no, e.gender ), -table_2 AS ( +table_1 AS ( SELECT - AVG(table_1._expr_0) AS salary_avg, - STDDEV(table_1._expr_0) AS salary_sd, + AVG(table_2._expr_0) AS salary_avg, + STDDEV(table_2._expr_0) AS salary_sd, dm.emp_no FROM - table_1 - JOIN dept_emp AS de ON table_1.emp_no = de.emp_no + table_3 AS table_2 + JOIN dept_emp AS de ON table_2.emp_no = de.emp_no JOIN dept_manager AS dm ON dm.dept_no = de.dept_no AND (de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date) GROUP BY dm.emp_no, - table_1.gender + table_2.gender ) SELECT managers.first_name || ' ' || managers.last_name AS mng_name, managers.gender, - table_2.salary_avg, - table_2.salary_sd + table_0.salary_avg, + table_0.salary_sd FROM - table_2 - JOIN employees AS managers ON table_2.emp_no = managers.emp_no + table_1 AS table_0 + JOIN employees AS managers ON table_0.emp_no = managers.emp_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap index fa439fbf23c0..68c457076ef7 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap @@ -17,11 +17,12 @@ WITH table_1 AS ( de.dept_no ) SELECT - table_1.dept_no, - table_1.salary, + table_0.dept_no, + table_0.salary, employees.gender, titles.title FROM - table_1 - JOIN employees ON table_1.emp_no = employees.emp_no - JOIN titles ON table_1.emp_no = titles.emp_no + table_1 AS table_0 + JOIN employees ON table_0.emp_no = employees.emp_no + JOIN titles ON table_0.emp_no = titles.emp_no + diff --git a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap index b12126c24dd3..676b3103af9c 100644 --- a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap @@ -1,15 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\ntable parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" +expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" input_file: book/tests/prql/examples/misc-0.prql --- -WITH parts AS ( - SELECT - * - FROM - seq_1_to_5 -), -table_1 AS ( +WITH table_1 AS ( SELECT related_id FROM @@ -33,8 +27,9 @@ SELECT -1 ) AS stub FROM - table_1 - JOIN accounts AS a ON a.id = table_1.related_id + table_1 AS table_0 + JOIN accounts AS a ON a.id = table_0.related_id JOIN email_addr_bean_rel AS er ON er.bean_id = a.id AND er.primary_address = '1' JOIN email_addresses AS ea ON ea.id = er.email_address_id + diff --git a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap index 9f7411a758ba..69e10cb2c16d 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap @@ -26,7 +26,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -38,3 +38,4 @@ ORDER BY sum_gross_cost LIMIT 20 + diff --git a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap index ea3da8460bb5..77b68ee0c7d1 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap @@ -13,12 +13,13 @@ WITH table_1 AS ( emp_no ) SELECT - AVG(table_1._expr_0) / 1000 AS salary_k, - AVG(table_1._expr_0) / 1000 * 1000 AS salary + AVG(table_0._expr_0) / 1000 AS salary_k, + AVG(table_0._expr_0) / 1000 * 1000 AS salary FROM - table_1 - JOIN titles ON table_1.emp_no = titles.emp_no + table_1 AS table_0 + JOIN titles ON table_0.emp_no = titles.emp_no GROUP BY titles.title LIMIT 10 + diff --git a/book/tests/snapshots/snapshot__@introduction-0.prql.snap b/book/tests/snapshots/snapshot__@introduction-0.prql.snap index 741163b2be4d..2cfecfb1a71d 100644 --- a/book/tests/snapshots/snapshot__@introduction-0.prql.snap +++ b/book/tests/snapshots/snapshot__@introduction-0.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" +expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" input_file: book/tests/prql/introduction-0.prql --- WITH table_1 AS ( @@ -22,7 +22,7 @@ SELECT CONCAT(title, '_', country) AS id, LEFT(country, 2) AS country_code FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -35,3 +35,4 @@ ORDER BY country DESC LIMIT 20 + diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap index 2d9d6d5178f5..693c04dcf449 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap @@ -17,6 +17,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 1 + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap index 3f5c880fd181..3d97e867fc17 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" input_file: book/tests/prql/language-features/s-strings-3.prql --- -WITH table_2 AS ( +WITH table_0 AS ( SELECT DISTINCT ON first_name, id, @@ -13,15 +13,16 @@ WITH table_2 AS ( ORDER BY age ASC ), -table_3 AS ( +table_1 AS ( SELECT * FROM salaries ) SELECT - table_0.*, - table_1.* + table_2.*, + table_3.* FROM - table_2 AS table_0 - JOIN table_3 AS table_1 ON table_0.id = table_1.id + table_0 AS table_2 + JOIN table_1 AS table_3 ON table_2.id = table_3.id + diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap index 31e030d55e0b..b3a371283e07 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" -input_file: book/tests/prql/language-features/standard-library-0.prql +input_file: book/tests/prql/language-features/standard-library/README-0.prql --- SELECT *, @@ -10,3 +10,4 @@ SELECT NOW() AS time FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap index 59de499b2072..904a45d549da 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" -input_file: book/tests/prql/transforms/from_text-0.prql +input_file: book/tests/prql/language-features/standard-library/from-text-0.prql --- -WITH table_1 AS ( +WITH table_0 AS ( SELECT '1' AS a, '2' AS b, @@ -22,5 +22,5 @@ SELECT b + c AS d, 42 AS answer FROM - table_1 AS table_0 + table_0 AS table_1 diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap index 9ae070f052eb..670e58dfc204 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" -input_file: book/tests/prql/transforms/from_text-1.prql +input_file: book/tests/prql/language-features/standard-library/from-text-1.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap similarity index 91% rename from book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap index 085bbccf68f8..becf706977bb 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" -input_file: book/tests/prql/transforms/from_text-2.prql +input_file: book/tests/prql/language-features/standard-library/from-text-2.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap new file mode 100644 index 000000000000..5515357a6c0c --- /dev/null +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap @@ -0,0 +1,34 @@ +--- +source: book/tests/snapshot.rs +expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" +input_file: book/tests/prql/language-features/standard-library/loop-0.prql +--- +WITH table_0 AS ( + SELECT + 1 AS n +), +table_4 AS ( + WITH RECURSIVE loop AS ( + SELECT + n + FROM + table_0 AS table_1 + UNION + ALL + SELECT + n + 1 + FROM + loop AS table_2 + WHERE + n < 4 + ) + SELECT + * + FROM + loop +) +SELECT + n +FROM + table_4 AS table_3 + diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap index 48c578cb780a..8a7e0fd99bc5 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap @@ -16,9 +16,10 @@ WITH table_1 AS ( 10 ) SELECT - table_1.name, - table_1.gross_salary, + table_0.name, + table_0.gross_salary, d.name FROM - table_1 - JOIN department AS d ON table_1.dept_no = d.dept_no + table_1 AS table_0 + JOIN department AS d ON table_0.dept_no = d.dept_no + diff --git a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap index e37a88722453..ca97469b4749 100644 --- a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" input_file: book/tests/prql/queries/variables-0.prql --- -WITH table_0 AS ( +WITH table_1 AS ( SELECT salary FROM @@ -16,7 +16,7 @@ WITH table_0 AS ( SELECT SUM(salary) AS total_salary FROM - table_0 + table_1 AS table_0 ) SELECT total_salary diff --git a/book/tests/snapshots/snapshot__@syntax-5.prql.snap b/book/tests/snapshots/snapshot__@syntax-5.prql.snap index 374cbd663cf3..9095768d6603 100644 --- a/book/tests/snapshots/snapshot__@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-5.prql.snap @@ -14,7 +14,8 @@ SELECT circumference, color FROM - table_1 + table_1 AS table_0 WHERE circumference > 10 AND color <> 'red' + diff --git a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap index a11503ab56c8..03289443cc04 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap @@ -17,6 +17,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 1 + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap index 7b6e784e1da0..fb7acd653ec6 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap @@ -3,16 +3,11 @@ source: book/tests/snapshot.rs expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" input_file: book/tests/prql/transforms/sort-3.prql --- -WITH table_1 AS ( - SELECT - *, - substr(first_name, 2, 5) AS _expr_0 - FROM - employees - ORDER BY - _expr_0 -) SELECT - * + *, + substr(first_name, 2, 5) AS _expr_0 FROM - table_1 + employees +ORDER BY + _expr_0 + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap index de8d52ca5f42..b969c19b2a4d 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap @@ -12,8 +12,9 @@ WITH table_1 AS ( tenure ) SELECT - table_1.*, + table_0.*, locations.* FROM - table_1 - JOIN locations ON table_1.employee_id = locations.employee_id + table_1 AS table_0 + JOIN locations ON table_0.employee_id = locations.employee_id + diff --git a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap index 13bb14a01bc7..0dcf1866c987 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap @@ -13,6 +13,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE salary < _expr_0 + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap index 691cabab4a62..7103d173bb5b 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library-0.prql +input_file: book/tests/prql/language-features/standard-library/README-0.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap similarity index 69% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap index d86f2e1e86bb..f5eae06d50c6 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-0.prql +input_file: book/tests/prql/language-features/standard-library/from-text-0.prql --- from_text " a,b,c diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap index 740349748e00..8dcf2f21faac 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-1.prql +input_file: book/tests/prql/language-features/standard-library/from-text-1.prql --- let temp_format_lookup = ( from_text format:csv " diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap index a0aaabe15cb7..13b437d66562 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-2.prql +input_file: book/tests/prql/language-features/standard-library/from-text-2.prql --- let x = ( from_text format:json '{ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap new file mode 100644 index 000000000000..b039f259620b --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/standard-library/loop-0.prql +--- +from_text format:json '[{"n": 1 }]' +loop ( + filter n < 4 + select n = n + 1 +) + + + diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index ea3dc6f0a7b7..a3b0b7b9132c 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -310,6 +310,7 @@ pub enum TransformKind { pipeline: Box, }, Append(Box), + Loop(Box), } #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index 3af403b8525d..b82f9178a296 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -273,6 +273,7 @@ pub fn fold_transform_kind( range: fold_range(fold, range)?, pipeline: Box::new(fold.fold_expr(*pipeline)?), }, + Loop(pipeline) => Loop(Box::new(fold.fold_expr(*pipeline)?)), }) } diff --git a/prql-compiler/src/ast/pl/types.rs b/prql-compiler/src/ast/pl/types.rs index 3d4c428d5d75..cb1463940c7b 100644 --- a/prql-compiler/src/ast/pl/types.rs +++ b/prql-compiler/src/ast/pl/types.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use super::Frame; -#[derive(Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] pub enum Ty { Empty, Literal(TyLit), @@ -162,9 +162,3 @@ impl Display for Ty { } } } - -impl Debug for Ty { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - Display::fmt(self, f) - } -} diff --git a/prql-compiler/src/ast/rq/fold.rs b/prql-compiler/src/ast/rq/fold.rs index d84d6385ba37..1c799e35dfe0 100644 --- a/prql-compiler/src/ast/rq/fold.rs +++ b/prql-compiler/src/ast/rq/fold.rs @@ -187,6 +187,7 @@ pub fn fold_transform( filter: fold.fold_expr(filter)?, }, Append(bottom) => Append(fold.fold_table_ref(bottom)?), + Loop(transforms) => Loop(fold_transforms(fold, transforms)?), }; Ok(transform) } diff --git a/prql-compiler/src/ast/rq/transform.rs b/prql-compiler/src/ast/rq/transform.rs index 7a946e1d2c13..875bc3d922b6 100644 --- a/prql-compiler/src/ast/rq/transform.rs +++ b/prql-compiler/src/ast/rq/transform.rs @@ -25,6 +25,7 @@ pub enum Transform { filter: Expr, }, Append(TableRef), + Loop(Vec), } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index bb595dd20da0..25383b9dd744 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -269,7 +269,7 @@ impl Lowerer { let ty = expr.ty.clone(); let prev_pipeline = self.pipeline.drain(..).collect_vec(); - self.lower_pipeline(expr)?; + self.lower_pipeline(expr, None)?; let mut transforms = self.pipeline.drain(..).collect_vec(); let columns = self.push_select(ty, &mut transforms)?; @@ -284,10 +284,22 @@ impl Lowerer { } // Result is stored in self.pipeline - fn lower_pipeline(&mut self, ast: pl::Expr) -> Result<()> { + fn lower_pipeline(&mut self, ast: pl::Expr, closure_param: Option) -> Result<()> { let transform_call = match ast.kind { pl::ExprKind::TransformCall(transform) => transform, + pl::ExprKind::Closure(closure) => { + let param = closure.params.first(); + let param = param.and_then(|p| p.name.parse::().ok()); + return self.lower_pipeline(*closure.body, param); + } _ => { + if let Some(target) = ast.target_id { + if Some(target) == closure_param { + // ast is a closure param, so we can skip pushing From + return Ok(()); + } + } + let table_ref = self.lower_table_ref(ast)?; self.pipeline.push(Transform::From(table_ref)); return Ok(()); @@ -295,7 +307,7 @@ impl Lowerer { }; // lower input table - self.lower_pipeline(*transform_call.input)?; + self.lower_pipeline(*transform_call.input, closure_param)?; // ... and continues with transforms created in this function @@ -362,8 +374,16 @@ impl Lowerer { pl::TransformKind::Append(bottom) => { let bottom = self.lower_table_ref(*bottom)?; - let transform = Transform::Append(bottom); - self.pipeline.push(transform); + self.pipeline.push(Transform::Append(bottom)); + } + pl::TransformKind::Loop(pipeline) => { + let relation = self.lower_relation(*pipeline)?; + let mut pipeline = relation.kind.into_pipeline().unwrap(); + + // last select is not needed here + pipeline.pop(); + + self.pipeline.push(Transform::Loop(pipeline)); } pl::TransformKind::Group { .. } | pl::TransformKind::Window { .. } => unreachable!( "transform `{}` cannot be lowered.", @@ -680,9 +700,10 @@ impl Lowerer { let name = match name { Some(v) => RelationColumn::Single(Some(v.clone())), None => return Err(Error::new_simple( - "This table contains unnamed columns, that need to be referenced by name", + "This table contains unnamed columns that need to be referenced by name", ) .with_span(self.context.span_map.get(&id).cloned()) + .with_help("The name may have been overridden later in the pipeline.") .into()), }; log::trace!("lookup cid of name={name:?} in input {input_columns:?}"); diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index f906e2dc7b23..586a9dcaf94f 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -48,6 +48,7 @@ func remove `default_db.bottom`
top
-> ( filter (all (map _is_null b.*)) select t.* ) +func loop
pipeline top
-> null # List functions func all list -> null diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs index b517b2a81c33..15c73cbbe44f 100644 --- a/prql-compiler/src/semantic/transforms.rs +++ b/prql-compiler/src/semantic/transforms.rs @@ -192,6 +192,13 @@ pub fn cast_transform(resolver: &mut Resolver, closure: Closure) -> Result { + let [pipeline, tbl] = unpack::<2>(closure); + + let pipeline = fold_by_simulating_eval(resolver, pipeline, tbl.ty.clone().unwrap())?; + + (TransformKind::Loop(Box::new(pipeline)), tbl) + } "std.in" => { // yes, this is not a transform, but this is the most appropriate place for it @@ -582,6 +589,7 @@ impl TransformCall { let bottom = ty_frame_or_default(bottom)?; append(top, bottom)? } + Loop(_) => ty_frame_or_default(&self.input)?, Sort { .. } | Filter { .. } | Take { .. } => ty_frame_or_default(&self.input)?, }) } diff --git a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap index bbc44298cbb5..23a1cc2ad749 100644 --- a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap +++ b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap @@ -25,7 +25,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -37,3 +37,4 @@ ORDER BY sum_gross_cost LIMIT 20 + diff --git a/prql-compiler/src/sql/anchor.rs b/prql-compiler/src/sql/anchor.rs index 6740cd2cc391..4c0e0ece9b76 100644 --- a/prql-compiler/src/sql/anchor.rs +++ b/prql-compiler/src/sql/anchor.rs @@ -3,28 +3,28 @@ use itertools::Itertools; use std::collections::{HashMap, HashSet}; use crate::ast::rq::{ - self, fold_transform, CId, Compute, Expr, Relation, RelationColumn, RelationKind, RqFold, - TableDecl, TableRef, Transform, + self, fold_transform, CId, Compute, Expr, RelationColumn, RqFold, TableRef, Transform, }; +use crate::sql::context::SqlTableDecl; +use crate::sql::preprocess::{SqlRelation, SqlRelationKind}; use super::{ context::{AnchorContext, ColumnDecl}, preprocess::{SqlFold, SqlTransform}, }; -type RemainingPipeline = (Vec, Vec); - /// Splits pipeline into two parts, such that the second part contains /// maximum number of transforms while "fitting" into a SELECT query. pub(super) fn split_off_back( - ctx: &mut AnchorContext, - output: Vec, mut pipeline: Vec, -) -> (Option, Vec) { + ctx: &mut AnchorContext, +) -> (Option>, Vec) { if pipeline.is_empty() { return (None, Vec::new()); } + let output = AnchorContext::determine_select_columns(&pipeline); + log::debug!("traversing pipeline to obtain columns: {output:?}"); let mut following_transforms: HashSet = HashSet::new(); @@ -137,8 +137,9 @@ pub(super) fn split_off_back( None } else { // drop inputs that were satisfied in current pipeline + pipeline.push(SqlTransform::Super(Transform::Select(missing))); - Some((pipeline, missing)) + Some(pipeline) }; curr_pipeline_rev.reverse(); @@ -166,20 +167,23 @@ fn can_materialize(compute: &Compute, inputs_required: &[Requirement]) -> bool { } /// Applies adjustments to second part of a pipeline when it's split: -/// - prepend pipeline with From -/// - redefine columns materialized in preceding pipeline +/// - append Select to proceeding pipeline +/// - prepend From to atomic pipeline +/// - redefine columns materialized in atomic pipeline /// - redirect all references to original columns to the new ones pub(super) fn anchor_split( ctx: &mut AnchorContext, - first_table_name: &str, - cols_at_split: &[CId], - second_pipeline: Vec, + preceding: Vec, + atomic: Vec, ) -> Vec { let new_tid = ctx.tid.gen(); + let preceding_select = &preceding.last().unwrap().as_super().unwrap(); + let cols_at_split = preceding_select.as_select().unwrap(); + log::debug!("split pipeline, first pipeline output: {cols_at_split:?}"); - // define columns of the new CTE + // redefine columns of the atomic pipeline let mut cid_redirects = HashMap::::new(); let mut new_columns = Vec::new(); for old_cid in cols_at_split { @@ -204,32 +208,31 @@ pub(super) fn anchor_split( // define a new table ctx.table_decls.insert( new_tid, - TableDecl { + SqlTableDecl { id: new_tid, - name: Some(first_table_name.to_string()), - // here we should put the pipeline, but because how this function is called, - // we need to return the pipeline directly, so we just insert dummy expr instead - relation: Relation { - kind: RelationKind::SString(vec![]), - columns: vec![], - }, + name: None, + relation: Some(SqlRelation { + columns: cols_at_split + .iter() + .map(|_| RelationColumn::Single(None)) + .collect_vec(), + kind: SqlRelationKind::PreprocessedPipeline(preceding), + }), }, ); // define instance of that table - let table_ref = TableRef { + let table_ref = ctx.create_table_instance(TableRef { source: new_tid, - name: Some(first_table_name.to_string()), + name: None, columns: new_columns, - }; - ctx.create_table_instance(table_ref.clone()); + }); // adjust second part: prepend from and rewrite expressions to use new columns - let mut second = second_pipeline; + let mut second = atomic; second.insert(0, SqlTransform::Super(Transform::From(table_ref))); - let mut redirector = CidRedirector { ctx, cid_redirects }; - redirector.fold_sql_transforms(second).unwrap() + CidRedirector::redirect(second, cid_redirects, ctx) } /// Determines whether a pipeline must be split at a transform to @@ -248,6 +251,7 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) // - take (no limit) // - distinct // - append/except/intersect (no limit) + // - loop (max 1x) // // Select is not affected by the order. use SqlTransform::*; @@ -306,6 +310,7 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) "Distinct", ], ), + SqlTransform::Loop(_) => !following.is_empty(), _ => false, }; @@ -387,12 +392,13 @@ pub(super) fn get_requirements( cids } - Super(Append(_)) => unreachable!(), - Super(Select(_) | From(_) | Aggregate { .. }) + Super(Aggregate { .. } | Append(_) | Transform::Loop(_)) => unreachable!(), + Super(Select(_) | From(_)) | Distinct | Union { .. } | Except { .. } - | Intersect { .. } => return Vec::new(), + | Intersect { .. } + | SqlTransform::Loop(_) => return Vec::new(), }; // general case: determine complexity @@ -502,9 +508,20 @@ impl RqFold for CidCollector { } } -struct CidRedirector<'a> { - ctx: &'a mut AnchorContext, - cid_redirects: HashMap, +pub(super) struct CidRedirector<'a> { + pub ctx: &'a mut AnchorContext, + pub cid_redirects: HashMap, +} + +impl<'a> CidRedirector<'a> { + pub fn redirect( + pipeline: Vec, + cid_redirects: HashMap, + ctx: &mut AnchorContext, + ) -> Vec { + let mut redirector = CidRedirector { ctx, cid_redirects }; + redirector.fold_sql_transforms(pipeline).unwrap() + } } impl<'a> RqFold for CidRedirector<'a> { diff --git a/prql-compiler/src/sql/context.rs b/prql-compiler/src/sql/context.rs index 4fa41ea51e71..b9b38e1ae2bf 100644 --- a/prql-compiler/src/sql/context.rs +++ b/prql-compiler/src/sql/context.rs @@ -10,19 +10,19 @@ use itertools::Itertools; use crate::ast::pl::TableExternRef; use crate::ast::rq::{ - fold_table, CId, Compute, Query, RelationColumn, RelationKind, RqFold, TId, TableDecl, - TableRef, Transform, + fold_table, CId, Compute, Query, Relation, RelationColumn, RelationKind, RqFold, TId, + TableDecl, TableRef, Transform, }; use crate::utils::{IdGenerator, NameGenerator}; -use super::preprocess::SqlTransform; +use super::preprocess::{SqlRelation, SqlTransform}; #[derive(Default)] pub struct AnchorContext { pub(super) column_decls: HashMap, pub(super) column_names: HashMap, - pub(super) table_decls: HashMap, + pub(super) table_decls: HashMap, pub(super) table_instances: HashMap, @@ -33,6 +33,20 @@ pub struct AnchorContext { pub(super) tid: IdGenerator, pub(super) tiid: IdGenerator, } + +#[derive(Debug, Clone)] +pub(super) struct SqlTableDecl { + #[allow(dead_code)] + pub id: TId, + + pub name: Option, + + /// Relation that still needs to be defined (usually as CTE) so it can be referenced by name. + /// None means that it has already been defined, or was not needed to be defined in the + /// first place. + pub relation: Option, +} + /// Table instance id #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TIId(usize); @@ -51,7 +65,7 @@ pub enum ColumnDecl { } impl AnchorContext { - pub fn of(query: Query) -> (Self, Query) { + pub fn of(query: Query) -> (Self, Relation) { let (cid, tid, query) = IdGenerator::load(query); let context = AnchorContext { @@ -78,7 +92,7 @@ impl AnchorContext { self.column_decls.insert(id, decl); } - pub fn create_table_instance(&mut self, mut table_ref: TableRef) { + pub fn create_table_instance(&mut self, mut table_ref: TableRef) -> TableRef { let tiid = self.tiid.gen(); for (col, cid) in &table_ref.columns { @@ -90,7 +104,8 @@ impl AnchorContext { table_ref.name = Some(self.table_name.gen()) } - self.table_instances.insert(tiid, table_ref); + self.table_instances.insert(tiid, table_ref.clone()); + table_ref } pub(crate) fn ensure_column_name(&mut self, cid: CId) -> Option<&String> { @@ -193,29 +208,45 @@ struct QueryLoader { } impl QueryLoader { - fn load(context: AnchorContext, query: Query) -> (AnchorContext, Query) { + fn load(context: AnchorContext, query: Query) -> (AnchorContext, Relation) { let mut loader = QueryLoader { context }; - let query = loader.fold_query(query).unwrap(); - (loader.context, query) + + for t in query.tables { + loader.load_table(t).unwrap(); + } + let relation = loader.fold_relation(query.relation).unwrap(); + (loader.context, relation) } -} -impl RqFold for QueryLoader { - fn fold_table(&mut self, table: TableDecl) -> Result { + fn load_table(&mut self, table: TableDecl) -> Result<()> { let mut decl = fold_table(self, table)?; + // assume name of the LocalTable that the relation is referencing if let RelationKind::ExternRef(TableExternRef::LocalTable(table)) = &decl.relation.kind { decl.name = Some(table.clone()); } + // generate name (if not present) if decl.name.is_none() && decl.relation.kind.as_extern_ref().is_none() { decl.name = Some(self.context.table_name.gen()); } - self.context.table_decls.insert(decl.id, decl.clone()); - Ok(decl) + let sql_decl = SqlTableDecl { + id: decl.id, + name: decl.name, + relation: if matches!(decl.relation.kind, RelationKind::ExternRef(_)) { + None + } else { + Some(decl.relation.into()) + }, + }; + + self.context.table_decls.insert(decl.id, sql_decl); + Ok(()) } +} +impl RqFold for QueryLoader { fn fold_compute(&mut self, compute: Compute) -> Result { self.context.register_compute(compute.clone()); Ok(compute) diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 44fd67901dbe..7806cf9b70a4 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -6,8 +6,7 @@ use lazy_static::lazy_static; use regex::Regex; use sqlparser::ast::{ self as sql_ast, BinaryOperator, DateTimeField, Function, FunctionArg, FunctionArgExpr, Ident, - Join, JoinConstraint, JoinOperator, ObjectName, OrderByExpr, SelectItem, TableAlias, - TableFactor, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, + ObjectName, OrderByExpr, SelectItem, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, }; use sqlparser::keywords::{ Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX, RESERVED_FOR_COLUMN_ALIAS, RESERVED_FOR_TABLE_ALIAS, @@ -15,8 +14,7 @@ use sqlparser::keywords::{ use std::collections::HashSet; use crate::ast::pl::{ - BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, SortDirection, TableExternRef, - WindowFrame, WindowKind, + BinOp, ColumnSort, InterpolateItem, Literal, Range, SortDirection, WindowFrame, WindowKind, }; use crate::ast::rq::*; use crate::error::{Error, Span}; @@ -187,7 +185,7 @@ pub(super) fn translate_literal(l: Literal, ctx: &Context) -> Result Result { - if ctx.pre_projection { + if ctx.query.pre_projection { log::debug!("translating {cid:?} pre projection"); let decl = ctx.anchor.column_decls.get(&cid).expect("bad RQ ids"); @@ -231,7 +229,7 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result { let name = ctx.anchor.column_names.get(&cid).cloned(); - name.expect("a name of this column to be set before generating SQL") + name.expect("name of this column has not been to be set before generating SQL") } }; @@ -244,38 +242,6 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result TableFactor { - let decl = ctx.anchor.table_decls.get(&table_ref.source).unwrap(); - - let name = match &decl.relation.kind { - // special case for anchor - RelationKind::ExternRef(TableExternRef::Anchor(anchor_id)) => { - sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]) - } - - // base case - _ => { - let decl_name = decl.name.clone().unwrap(); - - sql_ast::ObjectName(translate_ident(Some(decl_name), None, ctx)) - } - }; - - TableFactor::Table { - name, - alias: if decl.name == table_ref.name { - None - } else { - table_ref.name.map(|ident| TableAlias { - name: translate_ident_part(ident, ctx), - columns: vec![], - }) - }, - args: None, - with_hints: vec![], - } -} - pub(super) fn translate_sstring( items: Vec>, ctx: &mut Context, @@ -623,23 +589,6 @@ pub(super) fn translate_column_sort( }) } -pub(super) fn translate_join( - (side, with, filter): (JoinSide, TableRef, Expr), - ctx: &mut Context, -) -> Result { - let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); - - Ok(Join { - relation: table_factor_of_tid(with, ctx), - join_operator: match side { - JoinSide::Inner => JoinOperator::Inner(constraint), - JoinSide::Left => JoinOperator::LeftOuter(constraint), - JoinSide::Right => JoinOperator::RightOuter(constraint), - JoinSide::Full => JoinOperator::FullOuter(constraint), - }, - }) -} - /// Translate a PRQL Ident to a Vec of SQL Idents. // We return a vec of SQL Idents because sqlparser sometimes uses // [ObjectName](sql_ast::ObjectName) and sometimes uses @@ -651,7 +600,7 @@ pub(super) fn translate_ident( ctx: &Context, ) -> Vec { let mut parts = Vec::with_capacity(4); - if !ctx.omit_ident_prefix || column.is_none() { + if !ctx.query.omit_ident_prefix || column.is_none() { if let Some(table) = table_name { #[allow(clippy::if_same_then_else)] if ctx.dialect.big_query_quoting() { @@ -957,22 +906,12 @@ mod test { { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_with_concat_function = Context { - dialect: Box::new(GenericDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + context_with_concat_function = Context::new(Box::new(GenericDialect {}), anchor); } { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_without_concat_function = Context { - dialect: Box::new(SQLiteDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + context_without_concat_function = Context::new(Box::new(SQLiteDialect {}), anchor); } fn str_lit(s: &str) -> InterpolateItem { diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index a109eb8b0aa1..fba04d0be692 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -6,21 +6,23 @@ use std::collections::HashSet; use std::str::FromStr; use anyhow::{anyhow, Result}; -use enum_as_inner::EnumAsInner; use itertools::Itertools; use sqlparser::ast::{ - self as sql_ast, Ident, Select, SelectItem, SetExpr, TableAlias, TableFactor, TableWithJoins, + self as sql_ast, Ident, Join, JoinConstraint, JoinOperator, Select, SelectItem, SetExpr, + TableAlias, TableFactor, TableWithJoins, }; -use crate::ast::pl::{BinOp, Literal, RelationLiteral}; -use crate::ast::rq::{CId, Expr, ExprKind, Query, Relation, RelationKind, TableDecl, Transform}; +use crate::ast::pl::{BinOp, JoinSide, Literal, RelationLiteral}; +use crate::ast::rq::{CId, Expr, ExprKind, Query, RelationKind, TableRef, Transform}; +use crate::sql::anchor::anchor_split; +use crate::sql::preprocess::SqlRelationKind; use crate::utils::{BreakUp, IntoOnly, Pluck}; use crate::Target; use super::context::AnchorContext; use super::gen_expr::*; use super::gen_projection::*; -use super::preprocess::{self, SqlTransform}; +use super::preprocess::{self, SqlRelation, SqlTransform}; use super::{anchor, Context, Dialect}; pub fn translate_query(query: Query, dialect: Option) -> Result { @@ -36,77 +38,17 @@ pub fn translate_query(query: Query, dialect: Option) -> Result { - // preprocess - let pipeline = Ok(pipeline) - .map(preprocess::normalize) - .map(preprocess::push_down_selects) - .map(preprocess::prune_inputs) - .map(preprocess::wrap) - .and_then(|p| preprocess::distinct(p, &mut context)) - .map(preprocess::union) - .and_then(|p| preprocess::except(p, &context)) - .and_then(|p| preprocess::intersect(p, &context)) - .map(preprocess::reorder)?; - - // load names of output columns - context.anchor.load_names(&pipeline, table.relation.columns); - - // split to atomics - let ats = split_into_atomics(name, pipeline, &mut context.anchor); - - // ensure names for all columns that need it - ensure_names(&ats, &mut context.anchor); - - atomics.extend(ats); - } - RelationKind::Literal(_) | RelationKind::SString(_) => atomics.push(AtomicQuery { - name, - relation: SqlRelation::Super(table.relation.kind), - }), - RelationKind::ExternRef(_) => { - // ref does not need it's own CTE - } - } - } - - // take last table - let main_query = atomics.remove(atomics.len() - 1); - let ctes = atomics; - - // convert each of the CTEs - let ctes: Vec<_> = ctes - .into_iter() - .map(|t| table_to_sql_cte(t, &mut context)) - .try_collect()?; + let mut ctx = Context::new(dialect, anchor); - // convert main query - let mut main_query = sql_query_of_relation(main_query.relation, &mut context)?; + // compile main relation that will recursively compile CTEs + let mut main_query = sql_query_of_sql_relation(main_relation.into(), &mut ctx)?; // attach CTEs - if !ctes.is_empty() { + if !ctx.ctes.is_empty() { main_query.with = Some(sql_ast::With { - cte_tables: ctes, + cte_tables: ctx.ctes.drain(..).collect_vec(), recursive: false, }); } @@ -114,99 +56,188 @@ pub fn translate_query(query: Query, dialect: Option) -> Result Result { + use RelationKind::*; -#[derive(Debug, EnumAsInner)] -enum SqlRelation { - Super(RelationKind), - Pipeline(Vec), -} + // preprocess & split into atomics + match sql_relation.kind { + // base case + SqlRelationKind::Super(Pipeline(pipeline)) => { + // preprocess + let pipeline = Ok(pipeline) + .map(preprocess::normalize) + .map(preprocess::prune_inputs) + .map(preprocess::wrap) + .and_then(|p| preprocess::distinct(p, ctx)) + .map(preprocess::union) + .and_then(|p| preprocess::except(p, ctx)) + .and_then(|p| preprocess::intersect(p, ctx)) + .map(preprocess::reorder)?; + + // load names of output columns + ctx.anchor.load_names(&pipeline, sql_relation.columns); + + sql_query_of_pipeline(pipeline, ctx) + } -fn into_tables( - main_pipeline: Relation, - tables: Vec, - context: &mut Context, -) -> Result> { - let main = TableDecl { - id: context.anchor.tid.gen(), - name: None, - relation: main_pipeline, - }; - Ok([tables, vec![main]].concat()) + // no need to preprocess, has been done already + SqlRelationKind::PreprocessedPipeline(pipeline) => sql_query_of_pipeline(pipeline, ctx), + + // special case: literals + SqlRelationKind::Super(Literal(lit)) => sql_of_sample_data(lit, ctx), + + // special case: s-strings + SqlRelationKind::Super(SString(items)) => translate_query_sstring(items, ctx), + + // ref cannot be converted directly into query and does not need it's own CTE + SqlRelationKind::Super(ExternRef(_)) => unreachable!(), + } } -fn table_to_sql_cte(table: AtomicQuery, context: &mut Context) -> Result { - let alias = sql_ast::TableAlias { - name: translate_ident_part(table.name, context), - columns: vec![], +fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result { + let table_ref_alias = (table_ref.name.clone()) + .map(|ident| translate_ident_part(ident, ctx)) + .map(simple_table_alias); + + let decl = ctx.anchor.table_decls.get_mut(&table_ref.source).unwrap(); + + // prepare names + let table_name = match &decl.name { + None => { + decl.name = Some(ctx.anchor.table_name.gen()); + decl.name.clone().unwrap() + } + Some(n) => n.clone(), }; - Ok(sql_ast::Cte { - alias, - query: Box::new(sql_query_of_relation(table.relation, context)?), - from: None, - }) -} -fn sql_query_of_relation(relation: SqlRelation, context: &mut Context) -> Result { - use RelationKind::*; + // ensure that the table is declared + if let Some(sql_relation) = decl.relation.take() { + // if we cannot use CTEs + if ctx.query.forbid_ctes { + // restore relation for other references + decl.relation = Some(sql_relation.clone()); + + // return a sub-query + let query = sql_query_of_sql_relation(sql_relation, ctx)?; + return Ok(TableFactor::Derived { + lateral: false, + subquery: Box::new(query), + alias: table_ref_alias, + }); + } + + let query = sql_query_of_sql_relation(sql_relation, ctx)?; + let alias = sql_ast::TableAlias { + name: translate_ident_part(table_name.clone(), ctx), + columns: vec![], + }; - match relation { - SqlRelation::Super(ExternRef(_)) | SqlRelation::Super(Pipeline(_)) => unreachable!(), - SqlRelation::Pipeline(pipeline) => sql_query_of_pipeline(pipeline, context), - SqlRelation::Super(Literal(lit)) => Ok(sql_of_sample_data(lit, context)?), - SqlRelation::Super(SString(items)) => translate_query_sstring(items, context), + ctx.ctes.push(sql_ast::Cte { + alias, + query: Box::new(query), + from: None, + }) } + + // let name = match &decl.relation { + // // special case for anchor + // // TODO + // // Some(SqlRelationKind::Super(RelationKind::ExternRef(TableExternRef::Anchor( + // // anchor_id, + // // )))) => sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]), + + // // base case + // _ => { + + // } + // }; + + let name = sql_ast::ObjectName(translate_ident(Some(table_name.clone()), None, ctx)); + + Ok(TableFactor::Table { + name, + alias: if Some(table_name) == table_ref.name { + None + } else { + table_ref_alias + }, + args: None, + with_hints: vec![], + }) +} + +fn translate_join( + (side, with, filter): (JoinSide, TableRef, Expr), + ctx: &mut Context, +) -> Result { + let relation = table_factor_of_table_ref(with, ctx)?; + + let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); + + Ok(Join { + relation, + join_operator: match side { + JoinSide::Inner => JoinOperator::Inner(constraint), + JoinSide::Left => JoinOperator::LeftOuter(constraint), + JoinSide::Right => JoinOperator::RightOuter(constraint), + JoinSide::Full => JoinOperator::FullOuter(constraint), + }, + }) } fn sql_query_of_pipeline( - pipeline: Vec, - context: &mut Context, + mut pipeline: Vec, + ctx: &mut Context, ) -> Result { use SqlTransform::*; + // special case: loop + if pipeline.iter().any(|t| matches!(t, Loop(_))) { + pipeline = sql_of_loop(pipeline, ctx)?; + } + + // extract an atomic pipeline from back of the pipeline and stash preceding part into context + let pipeline = extract_atomic(pipeline, &mut ctx.anchor); + + // ensure names for all columns that need it + ensure_names(&pipeline, &mut ctx.anchor); + let (select, set_ops) = pipeline.break_up(|t| matches!(t, Union { .. } | Except { .. } | Intersect { .. })); - let select = sql_select_query_of_pipeline(select, context)?; + let select = sql_select_query_of_pipeline(select, ctx)?; - sql_set_ops_of_pipeline(select, set_ops, context) + sql_set_ops_of_pipeline(select, set_ops, ctx) } fn sql_select_query_of_pipeline( mut pipeline: Vec, - context: &mut Context, + ctx: &mut Context, ) -> Result { let table_count = count_tables(&pipeline); log::debug!("atomic query contains {table_count} tables"); - context.omit_ident_prefix = table_count == 1; - - context.pre_projection = true; - - let projection = pipeline - .pluck(|t| t.into_super_and(|t| t.into_select())) - .into_only() - .unwrap(); - let projection = translate_wildcards(&context.anchor, projection); - let projection = translate_select_items(projection.0, projection.1, context)?; + ctx.push_query(); + ctx.query.omit_ident_prefix = table_count == 1; + ctx.query.pre_projection = true; - let mut from = pipeline + let mut from: Vec<_> = pipeline .pluck(|t| t.into_super_and(|t| t.into_from())) .into_iter() - .map(|source| TableWithJoins { - relation: table_factor_of_tid(source, context), - joins: vec![], + .map(|source| -> Result { + Ok(TableWithJoins { + relation: table_factor_of_table_ref(source, ctx)?, + joins: vec![], + }) }) - .collect::>(); + .try_collect()?; let joins = pipeline .pluck(|t| t.into_super_and(|t| t.into_join())) .into_iter() - .map(|j| translate_join(j, context)) + .map(|j| translate_join(j, ctx)) .collect::>>()?; if !joins.is_empty() { if let Some(from) = from.last_mut() { @@ -216,6 +247,13 @@ fn sql_select_query_of_pipeline( } } + let projection = pipeline + .pluck(|t| t.into_super_and(|t| t.into_select())) + .into_only() + .unwrap(); + let projection = translate_wildcards(&ctx.anchor, projection); + let projection = translate_select_items(projection.0, projection.1, ctx)?; + let sorts = pipeline.pluck(|t| t.into_super_and(|t| t.into_sort())); let takes = pipeline.pluck(|t| t.into_super_and(|t| t.into_take())); let distinct = pipeline.iter().any(|t| matches!(t, SqlTransform::Distinct)); @@ -231,11 +269,11 @@ fn sql_select_query_of_pipeline( // WHERE and HAVING let where_ = filter_of_conditions( before_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - context, + ctx, )?; let having = filter_of_conditions( after_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - context, + ctx, )?; // GROUP BY @@ -244,9 +282,9 @@ fn sql_select_query_of_pipeline( .into_iter() .next(); let group_by: Vec = aggregate.map(|(part, _)| part).unwrap_or_default(); - let group_by = try_into_exprs(group_by, context, None)?; + let group_by = try_into_exprs(group_by, ctx, None)?; - context.pre_projection = false; + ctx.query.pre_projection = false; let ranges = takes.into_iter().map(|x| x.range).collect(); let take = range_of_ranges(ranges)?; @@ -257,7 +295,7 @@ fn sql_select_query_of_pipeline( None } else { Some(sqlparser::ast::Offset { - value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), context)?, + value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), ctx)?, rows: sqlparser::ast::OffsetRows::None, }) }; @@ -268,17 +306,20 @@ fn sql_select_query_of_pipeline( .map(|sorts| { sorts .iter() - .map(|s| translate_column_sort(s, context)) + .map(|s| translate_column_sort(s, ctx)) .try_collect() }) .transpose()? .unwrap_or_default(); - let (top, limit) = if context.dialect.use_top() { - (limit.map(|l| top_of_i64(l, context)), None) + let (top, limit) = if ctx.dialect.use_top() { + (limit.map(|l| top_of_i64(l, ctx)), None) } else { (None, limit.map(expr_of_i64)) }; + + ctx.pop_query(); + Ok(sql_ast::Query { order_by, limit, @@ -322,36 +363,7 @@ fn sql_set_ops_of_pipeline( }; // prepare top - let top_is_simple = top.with.is_none() - && top.order_by.is_empty() - && top.limit.is_none() - && top.offset.is_none() - && top.fetch.is_none() - && top.locks.is_empty(); - - let left = if top_is_simple { - top.body - } else { - // top is not simple, so we need to wrap it into - // `SELECT * FROM top` - Box::new(SetExpr::Select(Box::new(Select { - projection: vec![SelectItem::Wildcard( - sql_ast::WildcardAdditionalOptions::default(), - )], - from: vec![TableWithJoins { - relation: TableFactor::Derived { - lateral: false, - subquery: Box::new(top), - alias: Some(TableAlias { - name: Ident::new(context.anchor.table_name.gen()), - columns: Vec::new(), - }), - }, - joins: vec![], - }], - ..default_select() - }))) - }; + let left = query_to_set_expr(top, context); top = default_query(SetExpr::SetOperation { left, @@ -360,7 +372,7 @@ fn sql_set_ops_of_pipeline( sql_ast::WildcardAdditionalOptions::default(), )], from: vec![TableWithJoins { - relation: table_factor_of_tid(bottom, context), + relation: table_factor_of_table_ref(bottom, context)?, joins: vec![], }], ..default_select() @@ -381,6 +393,99 @@ fn sql_set_ops_of_pipeline( Ok(top) } +fn sql_of_loop(pipeline: Vec, ctx: &mut Context) -> Result> { + // split the pipeline + let (mut initial, mut following) = pipeline.break_up(|t| matches!(t, SqlTransform::Loop(_))); + let loop_ = following.remove(0); + let step = loop_.into_loop().unwrap(); + + // RECURSIVE can only follow WITH directly, which means that if we want to use it for + // an arbitrary query, we have to defined a *nested* WITH RECURSIVE and not use + // the top-level list of CTEs. + + // determine columns of the initial table + let recursive_columns = AnchorContext::determine_select_columns(&initial); + + // do the same thing we do when splitting a pipeline + // (defining new columns, redirecting cids) + let recursive_columns = SqlTransform::Super(Transform::Select(recursive_columns)); + initial.push(recursive_columns.clone()); + let step = anchor_split(&mut ctx.anchor, initial, step); + let from = step.first().unwrap().as_super().unwrap().as_from().unwrap(); + + let initial = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); + initial.name = Some("loop".to_string()); + let initial_relation = initial.relation.take().unwrap(); + + let initial = initial_relation.kind.into_preprocessed_pipeline().unwrap(); + + // compile initial + let initial = query_to_set_expr(sql_query_of_pipeline(initial, ctx)?, ctx); + + // compile step (without producing CTEs) + ctx.push_query(); + ctx.query.forbid_ctes = true; + + let step = query_to_set_expr(sql_query_of_pipeline(step, ctx)?, ctx); + + ctx.pop_query(); + + // build CTE and it's SELECT + let cte = sql_ast::Cte { + alias: simple_table_alias(Ident::new("loop")), + query: Box::new(default_query(SetExpr::SetOperation { + op: sql_ast::SetOperator::Union, + set_quantifier: sql_ast::SetQuantifier::All, + left: initial, + right: step, + })), + from: None, + }; + let query = Box::new(sql_ast::Query { + with: Some(sql_ast::With { + recursive: true, + cte_tables: vec![cte], + }), + ..default_query(sql_ast::SetExpr::Select(Box::new(sql_ast::Select { + projection: vec![SelectItem::Wildcard( + sql_ast::WildcardAdditionalOptions::default(), + )], + from: vec![TableWithJoins { + relation: TableFactor::Table { + name: sql_ast::ObjectName(vec![Ident::new("loop")]), + alias: None, + args: None, + with_hints: Vec::new(), + }, + joins: vec![], + }], + ..default_select() + }))) + }); + + // create a split between the loop SELECT statement and the following pipeline + let mut following = anchor_split(&mut ctx.anchor, vec![recursive_columns], following); + + let from = following.first_mut().unwrap(); + let from = from.as_super().unwrap().as_from().unwrap(); + + // this will be table decl that references the whole loop expression + let loop_decl = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); + + let loop_name = ctx.anchor.table_name.gen(); + loop_decl.name = Some(loop_name.clone()); + loop_decl.relation = None; + + // push the whole thing into WITH of the main query + ctx.ctes.push(sql_ast::Cte { + alias: simple_table_alias(Ident::new(loop_name)), + query, + from: None, + }); + + Ok(following) +} + fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result { // TODO: this could be made to use VALUES instead of SELECT UNION ALL SELECT // I'm not sure about compatibility though. @@ -416,121 +521,65 @@ fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result, - ctx: &mut AnchorContext, -) -> Vec { - let outputs_cid = AnchorContext::determine_select_columns(&pipeline); - - let mut required_cols = outputs_cid.clone(); - - // split pipeline, back to front - let mut parts_rev = Vec::new(); - loop { - let (preceding, split) = anchor::split_off_back(ctx, required_cols, pipeline); - - if let Some((preceding, cols_at_split)) = preceding { - log::debug!( - "pipeline split after {}", - preceding.last().unwrap().as_str() - ); - parts_rev.push((split, cols_at_split.clone())); - - pipeline = preceding; - required_cols = cols_at_split; - } else { - parts_rev.push((split, Vec::new())); - break; - } - } - parts_rev.reverse(); - let mut parts = parts_rev; +/// Extract last part of pipeline that is able to "fit" into a single SELECT statement. +/// Remaining proceeding pipeline is declared as a table and stored in AnchorContext. +fn extract_atomic(pipeline: Vec, ctx: &mut AnchorContext) -> Vec { + let (preceding, atomic) = anchor::split_off_back(pipeline, ctx); - // sometimes, additional columns will be added into select, which have to - // be filtered out here, using additional CTE - if let Some((pipeline, _)) = parts.last() { - let select_cols = pipeline - .first() - .unwrap() - .as_super() - .unwrap() - .as_select() - .unwrap(); - - if select_cols.iter().any(|c| !outputs_cid.contains(c)) { - parts.push(( - vec![SqlTransform::Super(Transform::Select(outputs_cid))], - select_cols.clone(), - )); - } - } + if let Some(preceding) = preceding { + log::debug!( + "pipeline split after {}", + preceding.last().unwrap().as_str() + ); - // add names to pipelines, anchor, front to back - let mut atomics = Vec::with_capacity(parts.len()); - let last = parts.pop().unwrap(); - - let last_pipeline = if parts.is_empty() { - last.0 + anchor::anchor_split(ctx, preceding, atomic) } else { - // this code chunk is bloated but I cannot find a more concise alternative - let first = parts.remove(0); - - let first_name = ctx.table_name.gen(); - atomics.push(AtomicQuery { - name: first_name.clone(), - relation: SqlRelation::Pipeline(first.0), - }); - - let mut prev_name = first_name; - for (pipeline, cols_before) in parts.into_iter() { - let name = ctx.table_name.gen(); - let pipeline = anchor::anchor_split(ctx, &prev_name, &cols_before, pipeline); - - atomics.push(AtomicQuery { - name: name.clone(), - relation: SqlRelation::Pipeline(pipeline), - }); - - prev_name = name; - } - - anchor::anchor_split(ctx, &prev_name, &last.1, last.0) - }; - atomics.push(AtomicQuery { - name, - relation: SqlRelation::Pipeline(last_pipeline), - }); + atomic + } - atomics + // TODO + // sometimes, additional columns will be added into select, which have to + // be filtered out here, using additional CTE + // if let Some((pipeline, _)) = parts.last() { + // let select_cols = pipeline + // .first() + // .unwrap() + // .as_super() + // .unwrap() + // .as_select() + // .unwrap(); + + // if select_cols.iter().any(|c| !outputs_cid.contains(c)) { + // parts.push(( + // vec![SqlTransform::Super(Transform::Select(outputs_cid))], + // select_cols.clone(), + // )); + // } + // } } -fn ensure_names(atomics: &[AtomicQuery], ctx: &mut AnchorContext) { - // ensure column names for columns that need it - for a in atomics { - let empty = HashSet::new(); - for t in a.relation.as_pipeline().unwrap() { - match t { - SqlTransform::Super(Transform::Sort(_)) => { - for r in anchor::get_requirements(t, &empty) { - ctx.ensure_column_name(r.col); - } +fn ensure_names(transforms: &[SqlTransform], ctx: &mut AnchorContext) { + let empty = HashSet::new(); + for t in transforms { + match t { + SqlTransform::Super(Transform::Sort(_)) => { + for r in anchor::get_requirements(t, &empty) { + ctx.ensure_column_name(r.col); } - SqlTransform::Super(Transform::Select(cids)) => { - for cid in cids { - let _decl = &ctx.column_decls[cid]; - //let name = match decl { - // ColumnDecl::RelationColumn(_, _, _) => todo!(), - // ColumnDecl::Compute(_) => ctx.column_names[..], - //}; - } + } + SqlTransform::Super(Transform::Select(cids)) => { + for cid in cids { + let _decl = &ctx.column_decls[cid]; + //let name = match decl { + // ColumnDecl::RelationColumn(_, _, _) => todo!(), + // ColumnDecl::Compute(_) => ctx.column_names[..], + //}; } - _ => (), } + _ => (), } } } - fn filter_of_conditions(exprs: Vec, context: &mut Context) -> Result> { Ok(if let Some(cond) = all(exprs) { Some(translate_expr_kind(cond.kind, context)?) @@ -584,6 +633,45 @@ fn default_select() -> Select { } } +fn simple_table_alias(name: Ident) -> TableAlias { + TableAlias { + name, + columns: Vec::new(), + } +} + +fn query_to_set_expr(query: sql_ast::Query, context: &mut Context) -> Box { + let is_simple = query.with.is_none() + && query.order_by.is_empty() + && query.limit.is_none() + && query.offset.is_none() + && query.fetch.is_none() + && query.locks.is_empty(); + + if is_simple { + return query.body; + } + + // query is not simple, so we need to wrap it into + // `SELECT * FROM (query)` + Box::new(SetExpr::Select(Box::new(Select { + projection: vec![SelectItem::Wildcard( + sql_ast::WildcardAdditionalOptions::default(), + )], + from: vec![TableWithJoins { + relation: TableFactor::Derived { + lateral: false, + subquery: Box::new(query), + alias: Some(simple_table_alias(Ident::new( + context.anchor.table_name.gen(), + ))), + }, + joins: vec![], + }], + ..default_select() + }))) +} + fn count_tables(transforms: &[SqlTransform]) -> usize { let mut count = 0; for transform in transforms { @@ -603,19 +691,36 @@ mod test { fn parse_and_resolve(prql: &str) -> Result<(Vec, Context)> { let query = resolve(parse(prql)?)?; - let (anchor, query) = AnchorContext::of(query); - let context = Context { - dialect: Box::new(GenericDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + let (anchor, main_relation) = AnchorContext::of(query); + let context = Context::new(Box::new(GenericDialect {}), anchor); - let pipeline = query.relation.kind.into_pipeline().unwrap(); + let pipeline = main_relation.kind.into_pipeline().unwrap(); Ok((preprocess::reorder(preprocess::wrap(pipeline)), context)) } + fn count_atomics(prql: &str) -> usize { + let (mut pipeline, mut context) = parse_and_resolve(prql).unwrap(); + context.anchor.table_decls.clear(); + + let mut atomics = 0; + loop { + let _ = extract_atomic(pipeline, &mut context.anchor); + atomics += 1; + + if let Some((_, decl)) = context.anchor.table_decls.drain().next() { + if let Some(relation) = decl.relation { + if let SqlRelationKind::PreprocessedPipeline(p) = relation.kind { + pipeline = p; + continue; + } + } + } + break; + } + atomics + } + #[test] fn test_ctes_of_pipeline() { // One aggregate, take at the end @@ -627,9 +732,7 @@ mod test { take 20 "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 1); + assert_eq!(count_atomics(prql), 1); // One aggregate, but take at the top let prql: &str = r###" @@ -640,9 +743,7 @@ mod test { sort sal "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 2); + assert_eq!(count_atomics(prql), 2); // A take, then two aggregates let prql: &str = r###" @@ -654,9 +755,7 @@ mod test { sort sal2 "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 3); + assert_eq!(count_atomics(prql), 3); // A take, then a select let prql: &str = r###" @@ -665,9 +764,7 @@ mod test { select first_name "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 1); + assert_eq!(count_atomics(prql), 1); } #[test] @@ -719,7 +816,7 @@ mod test { *, RANK() OVER () AS rank FROM - table_1 + table_1 AS table_0 WHERE country = 'USA' "###); @@ -744,7 +841,7 @@ mod test { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 3 "###); diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index 0be592ecf4b3..31f422c9ab6b 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -63,6 +63,18 @@ struct Context { pub dialect: Box, pub anchor: AnchorContext, + // stuff regarding current query + query: QueryOpts, + + // stuff regarding parent queries + query_stack: Vec, + + pub ctes: Vec, +} + +#[derive(Default, Clone)] +struct QueryOpts { + /// When true, column references will not include table names prefixes. pub omit_ident_prefix: bool, /// True iff codegen should generate expressions before SELECT's projection is applied. @@ -70,6 +82,29 @@ struct Context { /// - WHERE needs `pre_projection=true`, but /// - ORDER BY needs `pre_projection=false`. pub pre_projection: bool, + + /// When true, queries will contain nested sub-queries instead of WITH CTEs. + pub forbid_ctes: bool, +} + +impl Context { + fn new(dialect: Box, anchor: AnchorContext) -> Self { + Context { + dialect, + anchor, + query: QueryOpts::default(), + query_stack: Vec::new(), + ctes: Vec::new(), + } + } + + fn push_query(&mut self) { + self.query_stack.push(self.query.clone()); + } + + fn pop_query(&mut self) { + self.query = self.query_stack.pop().unwrap(); + } } #[cfg(test)] diff --git a/prql-compiler/src/sql/preprocess.rs b/prql-compiler/src/sql/preprocess.rs index 7c04c4cbf7cb..035f6858dd30 100644 --- a/prql-compiler/src/sql/preprocess.rs +++ b/prql-compiler/src/sql/preprocess.rs @@ -10,7 +10,8 @@ use crate::ast::pl::{ BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, WindowFrame, WindowKind, }; use crate::ast::rq::{ - self, new_binop, CId, Compute, Expr, ExprKind, RqFold, TableRef, Transform, Window, + self, new_binop, CId, Compute, Expr, ExprKind, Relation, RelationColumn, RelationKind, RqFold, + TableRef, Transform, Window, }; use crate::error::Error; use crate::sql::context::AnchorContext; @@ -18,31 +19,45 @@ use crate::sql::context::AnchorContext; use super::anchor::{infer_complexity, CidCollector, Complexity}; use super::Context; -#[derive(Debug, EnumAsInner, strum::AsRefStr)] +#[derive(Debug, Clone, EnumAsInner)] +pub(super) enum SqlRelationKind { + Super(RelationKind), + PreprocessedPipeline(Vec), +} + +#[derive(Debug, Clone)] +pub(super) struct SqlRelation { + pub kind: SqlRelationKind, + pub columns: Vec, +} + +#[derive(Debug, Clone, EnumAsInner, strum::AsRefStr)] pub(super) enum SqlTransform { Super(Transform), Distinct, Except { bottom: TableRef, distinct: bool }, Intersect { bottom: TableRef, distinct: bool }, Union { bottom: TableRef, distinct: bool }, + Loop(Vec), } -/// Pushes all [Transform::Select]s to the back of the pipeline. -pub(super) fn push_down_selects(pipeline: Vec) -> Vec { - let mut select = None; - let mut res = Vec::with_capacity(pipeline.len()); - for t in pipeline { - if let Transform::Select(_) = t { - select = Some(t); - } else { - res.push(t); - } - } - if let Some(select) = select { - res.push(select); - } - res -} +// This function was disabled because it changes semantics of the pipeline in some cases. +// /// Pushes all [Transform::Select]s to the back of the pipeline. +// pub(super) fn push_down_selects(pipeline: Vec) -> Vec { +// let mut select = None; +// let mut res = Vec::with_capacity(pipeline.len()); +// for t in pipeline { +// if let Transform::Select(_) = t { +// select = Some(t); +// } else { +// res.push(t); +// } +// } +// if let Some(select) = select { +// res.push(select); +// } +// res +// } /// Removes unused relation inputs pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { @@ -76,7 +91,12 @@ pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { } pub(super) fn wrap(pipe: Vec) -> Vec { - pipe.into_iter().map(SqlTransform::Super).collect() + pipe.into_iter() + .map(|t| match t { + Transform::Loop(pipeline) => SqlTransform::Loop(wrap(pipeline)), + _ => SqlTransform::Super(t), + }) + .collect() } /// Creates [SqlTransform::Distinct] from [Transform::Take] @@ -557,6 +577,15 @@ impl SqlTransform { } } +impl From for SqlRelation { + fn from(rel: Relation) -> Self { + SqlRelation { + kind: SqlRelationKind::Super(rel.kind), + columns: rel.columns, + } + } +} + pub(super) trait SqlFold: RqFold { fn fold_sql_transforms(&mut self, transforms: Vec) -> Result> { transforms @@ -581,6 +610,7 @@ pub(super) trait SqlFold: RqFold { bottom: self.fold_table_ref(bottom)?, distinct, }, + SqlTransform::Loop(pipeline) => SqlTransform::Loop(self.fold_sql_transforms(pipeline)?), }) } } diff --git a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap index 5b7e140a157a..1164db5605aa 100644 --- a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap +++ b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap @@ -16,6 +16,7 @@ SELECT title, AVG(_expr_0) AS avg_salary FROM - table_1 + table_1 AS table_0 GROUP BY title + diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index d1a4f1f2dd5b..d5991e8a9eb5 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -205,7 +205,7 @@ fn test_append() { take 10 ) "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT *, name, @@ -227,13 +227,13 @@ fn test_append() { employees LIMIT 3 - ) AS table_3 + ) AS table_2 UNION ALL SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "###); assert_display_snapshot!(compile(r###" @@ -310,7 +310,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -325,7 +325,7 @@ fn test_remove() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -337,7 +337,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -348,9 +348,9 @@ fn test_remove() { album.title FROM album - LEFT JOIN table_1 AS table_0 ON album.artist_id = table_0.artist_id + LEFT JOIN table_0 AS table_1 ON album.artist_id = table_1.artist_id WHERE - table_0.artist_id IS NULL + table_1.artist_id IS NULL "### ); @@ -382,11 +382,11 @@ fn test_remove() { album ) SELECT - table_1.artist_id, - table_1.title + table_0.artist_id, + table_0.title FROM - table_1 - LEFT JOIN bottom AS b ON table_1.artist_id = b.* + table_1 AS table_0 + LEFT JOIN bottom AS b ON table_0.artist_id = b.* WHERE b.* IS NULL "### @@ -443,7 +443,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -458,7 +458,7 @@ fn test_intersect() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -474,22 +474,28 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM artist + ), + table_3 AS ( + SELECT + artist_id + FROM + album + INTERSECT + DISTINCT + SELECT + * + FROM + table_0 AS table_1 ) SELECT - artist_id + DISTINCT artist_id FROM - album - INTERSECT - DISTINCT - SELECT - * - FROM - table_1 AS table_0 + table_3 AS table_2 "### ); @@ -504,22 +510,28 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM artist + ), + table_3 AS ( + SELECT + artist_id + FROM + album + INTERSECT + ALL + SELECT + * + FROM + table_0 AS table_1 ) SELECT - artist_id - FROM - album - INTERSECT - DISTINCT - SELECT - * + DISTINCT artist_id FROM - table_1 AS table_0 + table_3 AS table_2 "### ); @@ -534,7 +546,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -549,7 +561,7 @@ fn test_intersect() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -574,28 +586,28 @@ fn test_rn_ids_are_unique() { take 3 ) "###).unwrap()), @r###" - WITH table_1 AS ( + WITH table_3 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_0 + ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_1 FROM y_orig ), - table_2 AS ( + table_1 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_1 + ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_0 FROM - table_1 + table_3 AS table_2 WHERE - _expr_0 <= 2 + _expr_1 <= 2 ) SELECT * FROM - table_2 + table_1 AS table_0 WHERE - _expr_1 <= 3 + _expr_0 <= 3 "###); } @@ -690,19 +702,13 @@ fn test_sorts() { select [renamed = somefield] "### ).unwrap()), @r###" - WITH table_1 AS ( - SELECT - 'something' AS renamed, - 'something' AS _expr_0 - FROM - x - ORDER BY - _expr_0 - ) SELECT - renamed + 'something' AS renamed, + 'something' AS _expr_0 FROM - table_1 + x + ORDER BY + _expr_0 "###); } @@ -877,7 +883,7 @@ fn test_window_functions_02() { order_day ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS num_books_last_week FROM - table_1 + table_1 AS table_0 ORDER BY order_day "###); @@ -1261,7 +1267,7 @@ fn test_take() { SELECT * FROM - table_1 + table_1 AS table_0 ORDER BY name LIMIT @@ -1340,7 +1346,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE rn > 2 "###); @@ -1397,7 +1403,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 3 "###); @@ -1420,7 +1426,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 BETWEEN 2 AND 3 "###); @@ -1443,7 +1449,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 = 4 "###); @@ -1832,16 +1838,7 @@ fn test_prql_to_sql_table() { let sql = compile(query).unwrap(); assert_display_snapshot!(sql, @r###" - WITH average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country - ), - newest_employees AS ( + WITH newest_employees AS ( SELECT * FROM @@ -1850,6 +1847,14 @@ fn test_prql_to_sql_table() { tenure LIMIT 50 + ), average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country ) SELECT newest_employees.name, @@ -1883,7 +1888,7 @@ fn test_nonatomic() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_1 AS ( + WITH table_3 AS ( SELECT title, country, @@ -1892,13 +1897,13 @@ fn test_nonatomic() { employees LIMIT 20 - ), table_2 AS ( + ), table_1 AS ( SELECT title, country, AVG(salary) AS _expr_0 FROM - table_1 + table_3 AS table_2 WHERE country = 'USA' GROUP BY @@ -1910,7 +1915,7 @@ fn test_nonatomic() { country, AVG(_expr_0) AS sum_gross_cost FROM - table_2 + table_1 AS table_0 GROUP BY title, country @@ -1963,7 +1968,7 @@ fn test_nonatomic_table() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT country FROM @@ -1975,7 +1980,7 @@ fn test_nonatomic_table() { country, count(*) FROM - table_0 + table_1 AS table_0 GROUP BY country ) @@ -2012,12 +2017,12 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_1.emp_no, - table_1.name, + table_0.emp_no, + table_0.name, s.salary FROM - table_1 - JOIN salaries AS s ON table_1.emp_no = s.emp_no + table_1 AS table_0 + JOIN salaries AS s ON table_0.emp_no = s.emp_no "###); let prql = r###" @@ -2037,11 +2042,11 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_1.*, + table_0.*, salaries.salary FROM - table_1 - JOIN salaries ON table_1.emp_no = salaries.emp_no + table_1 AS table_0 + JOIN salaries ON table_0.emp_no = salaries.emp_no "###); } @@ -2321,12 +2326,6 @@ fn test_toposort() { * FROM somesource - ), - a AS ( - SELECT - * - FROM - b ) SELECT * @@ -2346,7 +2345,7 @@ fn test_inline_tables() { join s = (from salaries | select [emp_id, salary]) [==emp_id] "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT emp_id, salary @@ -2359,11 +2358,11 @@ fn test_inline_tables() { employees.surname, employees.type, employees.amount, - table_0.emp_id, - table_0.salary + table_1.emp_id, + table_1.salary FROM employees - JOIN table_1 AS table_0 ON employees.emp_id = table_0.emp_id + JOIN table_0 AS table_1 ON employees.emp_id = table_1.emp_id "### ); } @@ -2448,7 +2447,7 @@ fn test_table_s_string() { s"SELECT DISTINCT ON first_name, age FROM employees ORDER BY age ASC" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT DISTINCT ON first_name, age @@ -2459,7 +2458,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -2470,7 +2469,7 @@ fn test_table_s_string() { join s = s"SELECT * FROM salaries" [==id] "###).unwrap(), @r###" - WITH table_2 AS ( + WITH table_0 AS ( SELECT DISTINCT ON first_name, id, @@ -2480,18 +2479,18 @@ fn test_table_s_string() { ORDER BY age ASC ), - table_3 AS ( + table_1 AS ( SELECT * FROM salaries ) SELECT - table_0.*, - table_1.* + table_2.*, + table_3.* FROM - table_2 AS table_0 - JOIN table_3 AS table_1 ON table_0.id = table_1.id + table_0 AS table_2 + JOIN table_1 AS table_3 ON table_2.id = table_3.id "### ); @@ -2500,7 +2499,7 @@ fn test_table_s_string() { filter country == "USA" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2509,7 +2508,7 @@ fn test_table_s_string() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 WHERE country = 'USA' "### @@ -2520,7 +2519,7 @@ fn test_table_s_string() { filter e.country == "USA" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2529,7 +2528,7 @@ fn test_table_s_string() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 WHERE country = 'USA' "### @@ -2542,7 +2541,7 @@ fn test_table_s_string() { weeks_between @2022-06-03 (current_week + 4) "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT generate_series( DATE '2022-06-03', @@ -2552,7 +2551,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -2560,7 +2559,7 @@ fn test_table_s_string() { s"SELECT * FROM {default_db.x}" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2568,7 +2567,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); } @@ -2668,13 +2667,13 @@ fn test_group_all() { 10 ) SELECT - table_1.*, + table_0.*, SUM(salaries.salary) AS sal FROM - table_1 - JOIN salaries ON table_1.emp_no = salaries.emp_no + table_1 AS table_0 + JOIN salaries ON table_0.emp_no = salaries.emp_no GROUP BY - table_1.* + table_0.* "### ); @@ -2705,7 +2704,7 @@ fn test_output_column_deduplication() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE r = 1 "### @@ -2779,7 +2778,7 @@ fn test_switch() { category, COUNT(*) FROM - table_1 + table_1 AS table_0 GROUP BY category "### @@ -3135,7 +3134,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT '1' AS a, '2' AS b, @@ -3151,7 +3150,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -3162,7 +3161,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT 1 AS a, 'x' AS b, @@ -3178,7 +3177,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -3193,7 +3192,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT 1 AS a, 'x' AS b, @@ -3209,7 +3208,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); } @@ -3226,3 +3225,55 @@ fn test_header_target_error() { from a "#).unwrap_err(),@r###"target `"sql.foo"` not found"###) } + +#[test] +fn test_loop() { + assert_display_snapshot!(compile(r#" + from_text format:json '[{"n": 1 }]' + select n = n - 2 + loop ( + select n = n+1 + filter n<5 + ) + select n = n * 2 + take 4 + "#).unwrap(), + @r###" + WITH table_0 AS ( + SELECT + 1 AS n + ), + table_6 AS ( + WITH RECURSIVE loop AS ( + SELECT + n - 2 AS _expr_0 + FROM + table_0 AS table_1 + UNION + ALL + SELECT + _expr_1 + FROM + ( + SELECT + _expr_0 + 1 AS _expr_1 + FROM + loop AS table_2 + ) AS table_3 + WHERE + _expr_1 < 5 + ) + SELECT + * + FROM + loop + ) + SELECT + _expr_0 * 2 AS n + FROM + table_6 AS table_5 + LIMIT + 4 + "### + ); +} diff --git a/prql-compiler/tests/integration/queries/loop.prql b/prql-compiler/tests/integration/queries/loop.prql new file mode 100644 index 000000000000..e83d02e37057 --- /dev/null +++ b/prql-compiler/tests/integration/queries/loop.prql @@ -0,0 +1,7 @@ +from_text format:json '[{"n": 1 }]' +select n = n - 2 +loop ( + filter n<4 + select n = n+1 +) +select n = n * 2 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap new file mode 100644 index 000000000000..482dc9933c4d --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap @@ -0,0 +1,12 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/loop.prql +--- +n +-2 +0 +2 +4 +6 +8 From b68a944aa09233636be832afb73cee9b933d0bde Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 19 Feb 2023 13:01:32 +0100 Subject: [PATCH 016/184] feat: Generate C header file for prql-lib (#1879) --- prql-lib/README.md | 8 ++++++++ prql-lib/cbindgen.toml | 1 + prql-lib/libprql_lib.h | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 prql-lib/cbindgen.toml create mode 100644 prql-lib/libprql_lib.h diff --git a/prql-lib/README.md b/prql-lib/README.md index 9c17b3da2b21..ba49ff9fffa5 100644 --- a/prql-lib/README.md +++ b/prql-lib/README.md @@ -82,3 +82,11 @@ func ToJSON(prql string) (string, error) { return "", errors.New(C.GoString(cstr)) } ``` + +## C header file + +The C header file `libprql_lib.h` was generated using +[cbindgen](https://github.com/eqrion/cbindgen). To generate a new one run: + + cargo install --force cbindgen + cbindgen --crate prql-lib --output libprql_lib.h diff --git a/prql-lib/cbindgen.toml b/prql-lib/cbindgen.toml new file mode 100644 index 000000000000..08094f28fc2c --- /dev/null +++ b/prql-lib/cbindgen.toml @@ -0,0 +1 @@ +language = "C" diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h new file mode 100644 index 000000000000..8a1ed325e4f0 --- /dev/null +++ b/prql-lib/libprql_lib.h @@ -0,0 +1,18 @@ +#include +#include +#include +#include + +/** + * # Safety + * + * This function is inherently unsafe because it is using C ABI. + */ +int to_sql(const char *query, char *out); + +/** + * # Safety + * + * This function is inherently unsafe because it using C ABI. + */ +int to_json(const char *query, char *out); From d8b7e63f2edeab7dc4598d6736354030b841ecc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Sun, 19 Feb 2023 13:15:42 +0100 Subject: [PATCH 017/184] fix: website tests (#1894) --- website/content/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/_index.md b/website/content/_index.md index 035f4eaedfe2..c40e3396934f 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -246,7 +246,7 @@ showcase_section: SELECT * FROM - table_1 + table_1 as table_0 WHERE _expr_0 <= 1 From 9bd27f19d91ba326918a7ec157eec2aec083994c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Sun, 19 Feb 2023 21:27:49 +0100 Subject: [PATCH 018/184] feat(prqlc)!: preprocess Jinja templates (#1722) --- Cargo.lock | 15 ++- prql-compiler/prqlc/Cargo.toml | 5 +- prql-compiler/prqlc/src/jinja.rs | 177 +++++++++++++++++++++++++++++ prql-compiler/prqlc/src/main.rs | 2 + prql-compiler/prqlc/src/watch.rs | 10 +- prql-compiler/src/parser/mod.rs | 41 +------ prql-compiler/src/parser/prql.pest | 5 +- prql-compiler/src/sql/gen_expr.rs | 5 +- prql-compiler/src/sql/mod.rs | 5 +- prql-compiler/src/test.rs | 13 --- website/content/_index.md | 2 +- 11 files changed, 215 insertions(+), 65 deletions(-) create mode 100644 prql-compiler/prqlc/src/jinja.rs diff --git a/Cargo.lock b/Cargo.lock index fbf59f6863f1..f94ad387bfbf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1669,6 +1669,14 @@ dependencies = [ "autocfg", ] +[[package]] +name = "minijinja" +version = "0.30.2" +source = "git+https://github.com/aljazerzen/minijinja#af5a4fd89e5ee5455d673a23098dcbc3d8444229" +dependencies = [ + "serde", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -2217,8 +2225,11 @@ dependencies = [ "env_logger 0.9.3", "insta", "itertools", + "minijinja", "notify", "prql-compiler", + "regex", + "serde", "serde_json", "serde_yaml", "walkdir", @@ -2397,9 +2408,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" +checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" dependencies = [ "aho-corasick", "memchr", diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 322148aae867..621fdc071a43 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -18,9 +18,12 @@ color-eyre = "0.6.1" env_logger = {version = "0.9.1", features = ["termcolor"]} itertools = "0.10.3" notify = "^5.1.0" -prql-compiler = {path = '..', version = "0.5.2" } +minijinja = {git = "https://github.com/aljazerzen/minijinja"} +prql-compiler = {path = '..', version = "0.5.2"} +regex = {version = "1.7.1", features = ["std", "unicode"]} serde_json = "1.0.81" serde_yaml = "0.9.1" +serde = "^1" walkdir = "^2.3.2" [target.'cfg(not(target_family="wasm"))'.dev-dependencies] diff --git a/prql-compiler/prqlc/src/jinja.rs b/prql-compiler/prqlc/src/jinja.rs new file mode 100644 index 000000000000..ac8835747a37 --- /dev/null +++ b/prql-compiler/prqlc/src/jinja.rs @@ -0,0 +1,177 @@ +//! Handling of Jinja templates +//! +//! dbt is using the following pipeline: `Jinja+SQL -> SQL -> execution`. +//! +//! To prevent messing up the templates, we have create the following pipeline: +//! ``` +//! Jinja+PRQL -> Jinja+SQL -> SQL -> execution +//! ``` +//! +//! But because prql-compiler does not (and should not) know how to handle Jinja, +//! we have to extract the interpolations, replace them something that is valid PRQL, +//! compile the query and inject interpolations back in. +//! +//! Unfortunately, this requires parsing Jinja. +//! +//! use crate::compiler::tokens::{Span, Token}; + +use std::collections::HashMap; + +use anyhow::Result; +use minijinja::compiler::tokens::{Span, Token}; +use regex::Regex; + +const ANCHOR_PREFIX: &str = "_jinja_"; + +#[derive(Debug)] +pub enum JinjaBlock<'a> { + Data(&'a str), + Interpolation(Vec<(Token<'a>, Span)>), +} + +#[derive(Default)] +pub struct JinjaContext<'a> { + anchor_map: HashMap, + header: Vec<&'a str>, +} + +/// Parse source as Jinja template, extract all interpolations +/// and replace them with anchors. +pub fn pre_process(source: &str) -> Result<(String, JinjaContext)> { + let mut blocks = Vec::new(); + let mut current_block = Vec::new(); + + for res in minijinja::compiler::lexer::tokenize(source, false) { + let (token, span) = res?; + + if let Token::TemplateData(data) = token { + if !current_block.is_empty() { + blocks.push(JinjaBlock::Interpolation(current_block)); + current_block = Vec::new(); + } + blocks.push(JinjaBlock::Data(data)) + } else { + current_block.push((token, span)); + } + } + if !current_block.is_empty() { + blocks.push(JinjaBlock::Interpolation(current_block)); + } + + let mut anchored_source = String::new(); + let mut next_anchor_id = 0; + let mut context = JinjaContext::default(); + for block in blocks { + match block { + JinjaBlock::Data(data) => anchored_source += data, + JinjaBlock::Interpolation(block) => { + let (tokens, spans): (Vec<_>, _) = block.into_iter().unzip(); + + let source_span = find_span(source, spans); + + if let Some(Token::Ident("config" | "set")) = tokens.get(1) { + context.header.push(source_span); + } else { + let id = format!("{ANCHOR_PREFIX}{next_anchor_id}"); + next_anchor_id += 1; + + anchored_source += &id; + + context.anchor_map.insert(id, source_span); + } + } + } + } + + Ok((anchored_source, context)) +} + +fn find_span(source: &str, spans: Vec) -> &str { + let start = spans.first().unwrap(); + let end = spans.last().unwrap(); + + let mut start_index = 0; + let mut end_index = source.len(); + + let mut line = 1; + let mut col = 0; + for (index, char) in source.chars().enumerate() { + if char == '\n' { + line += 1; + col = 0; + continue; + } else { + col += 1; + } + + if line == start.start_line && col == start.start_col { + start_index = index; + } + if line == end.end_line && col == end.end_col { + end_index = index + 1; + } + } + &source[start_index..end_index] +} + +/// Replace anchors with their values. +pub fn post_process(source: &str, context: JinjaContext) -> String { + let mut res = String::new(); + + for stmt in context.header { + res += stmt; + res += "\n"; + } + + let re = Regex::new(&format!(r"{ANCHOR_PREFIX}\d+")).unwrap(); + + let mut last_index = 0; + for cap in re.captures_iter(source) { + let cap = cap.get(0).unwrap(); + let index = cap.start(); + let anchor_id = cap.as_str(); + + res += &source[last_index..index]; + res += context.anchor_map.get(anchor_id).unwrap_or(&anchor_id); + + last_index = index + anchor_id.len(); + } + res += &source[last_index..]; + + res +} + +#[cfg(test)] +mod test { + use super::Span; + + #[test] + fn test_find_span() { + let text = r#"line 1 col 13 + line 2 col 21 + some text line 3 col 31 more text + "#; + + assert_eq!( + super::find_span( + text, + vec![ + Span { + start_line: 2, + start_col: 9, + end_line: 12123123, + end_col: 2930293, + }, + Span { + start_line: 7893648, + start_col: 79678, + end_line: 3, + end_col: 31, + } + ] + ), + r#"line 2 col 21 + some text line 3 col 31"# + ); + } +} diff --git a/prql-compiler/prqlc/src/main.rs b/prql-compiler/prqlc/src/main.rs index 98ed661a72d6..0a3e3d6edc14 100644 --- a/prql-compiler/prqlc/src/main.rs +++ b/prql-compiler/prqlc/src/main.rs @@ -7,6 +7,8 @@ #[cfg(not(target_family = "wasm"))] mod cli; #[cfg(not(target_family = "wasm"))] +mod jinja; +#[cfg(not(target_family = "wasm"))] mod watch; #[cfg(not(target_family = "wasm"))] diff --git a/prql-compiler/prqlc/src/watch.rs b/prql-compiler/prqlc/src/watch.rs index a6bd2c4d0a2b..6c0f70121372 100644 --- a/prql-compiler/prqlc/src/watch.rs +++ b/prql-compiler/prqlc/src/watch.rs @@ -8,6 +8,8 @@ use notify::{Config, RecommendedWatcher, RecursiveMode, Watcher}; use prql_compiler::downcast; use walkdir::WalkDir; +use crate::jinja; + #[derive(Parser)] pub struct WatchCommand { /// Directory or file to watch for changes @@ -33,7 +35,7 @@ pub fn run(command: &mut WatchCommand) -> Result<()> { // watch and compile println!("Watching path \"{}\"", path.display()); - watch_and_compile(path, &opt).unwrap(); + watch_and_compile(path, &opt)?; Ok(()) } @@ -108,6 +110,9 @@ fn compile_path(path: &Path, opt: &prql_compiler::Options) -> Result<()> { return Ok(()); } + // pre-process Jinja + let (prql_string, jinja_context) = jinja::pre_process(&prql_string)?; + // compile println!("Compiling {}", prql_path.display()); let sql_string = match prql_compiler::compile(&prql_string, opt.clone()) { @@ -119,6 +124,9 @@ fn compile_path(path: &Path, opt: &prql_compiler::Options) -> Result<()> { } }; + // post-process Jinja + let sql_string = jinja::post_process(&sql_string, jinja_context); + // write fs::write(sql_path, sql_string)?; diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 12aad8385407..4483911c5604 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -233,10 +233,6 @@ fn expr_of_parse_pair(pair: Pair) -> Result { named_args: named, }) } - Rule::jinja => { - let inner = pair.as_str(); - ExprKind::Ident(Ident::from_name(inner)) - } Rule::ident => { // Pest has already parsed, so Chumsky should never fail let ident = ::chumsky::Parser::parse(&chumsky::ident(), pair.as_str()).unwrap(); @@ -850,39 +846,14 @@ Canada } #[test] - fn test_parse_jinja() -> Result<()> { - assert_yaml_snapshot!(stmts_of_string(r#" + fn test_parse_jinja() { + stmts_of_string( + r#" from {{ ref('stg_orders') }} aggregate (sum order_id) - "#)?, @r###" - --- - - Main: - Pipeline: - exprs: - - FuncCall: - name: - Ident: - - from - args: - - Ident: - - "{{ ref('stg_orders') }}" - named_args: {} - - FuncCall: - name: - Ident: - - aggregate - args: - - FuncCall: - name: - Ident: - - sum - args: - - Ident: - - order_id - named_args: {} - named_args: {} - "###); - Ok(()) + "#, + ) + .unwrap_err(); } #[test] diff --git a/prql-compiler/src/parser/prql.pest b/prql-compiler/src/parser/prql.pest index 50cf6707ce68..b30651838c25 100644 --- a/prql-compiler/src/parser/prql.pest +++ b/prql-compiler/src/parser/prql.pest @@ -57,7 +57,7 @@ expr_compare = { expr_add ~ (operator_compare ~ expr_add)? } expr_add = { expr_mul ~ (operator_add ~ expr_add)? } expr_mul = { term ~ (operator_mul ~ expr_mul)? } -term = _{ ( switch | s_string | f_string | range | literal | ident | nested_pipeline | expr_unary | list | jinja ) } +term = _{ ( switch | s_string | f_string | range | literal | ident | nested_pipeline | expr_unary | list ) } expr_unary = { ( operator_unary ~ ( nested_pipeline | ident | list )) } literal = _{ value_and_unit | number | boolean | null | string | timestamp | date | time | "(" ~ literal ~ ")" } // `assign | pipeline` based on discussion in #648 @@ -146,8 +146,5 @@ timestamp_inner = ${ date_inner ~ "T" ~ time_inner } // not supported) end_expr = _{ WHITESPACE | "," | ")" | "]" | EOI | NEWLINE | ".." } -// We pass text between `{{` and `}}` through, so dbt can use Jinja. -jinja = { ("{{" ~ (!"}}" ~ ANY)* ~ "}}") } - switch = { "switch" ~ "[" ~ (NEWLINE* ~ switch_case ~ ("," ~ NEWLINE* ~ switch_case )* ~ ","?)? ~ NEWLINE* ~ "]" } switch_case = { expr_call ~ "->" ~ expr_call } diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 7806cf9b70a4..271b4a6a1833 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -664,9 +664,6 @@ fn is_keyword(ident: &str) -> bool { } pub(super) fn translate_ident_part(ident: String, ctx: &Context) -> sql_ast::Ident { - // We'll remove this when we get the new dbt plugin working (so no need to - // integrate into the regex) - let is_jinja = ident.starts_with("{{") && ident.ends_with("}}"); lazy_static! { // One of: // - `*` @@ -679,7 +676,7 @@ pub(super) fn translate_ident_part(ident: String, ctx: &Context) -> sql_ast::Ide let is_bare = VALID_BARE_IDENT.is_match(&ident); - if is_jinja || is_bare && !is_keyword(&ident) { + if is_bare && !is_keyword(&ident) { sql_ast::Ident::new(ident) } else { sql_ast::Ident::with_quote(ctx.dialect.ident_quote(), ident) diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index 31f422c9ab6b..c49140711390 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -32,10 +32,7 @@ pub fn compile(query: Query, options: Options) -> Result { sqlformat::FormatOptions::default(), ); - // The sql formatter turns `{{` into `{ {`, and while that's reasonable SQL, - // we want to allow jinja expressions through. So we (somewhat hackily) replace - // any `{ {` with `{{`. - formatted.replace("{ {", "{{").replace("} }", "}}") + "\n" + formatted + "\n" } else { sql }; diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index d5991e8a9eb5..16c1d560cf5a 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -1455,19 +1455,6 @@ fn test_distinct() { "###); } -#[test] -fn test_dbt_query() { - assert_display_snapshot!((compile(r###" - from {{ ref('stg_orders') }} - aggregate (min order_id) - "###).unwrap()), @r###" - SELECT - MIN(order_id) - FROM - {{ ref('stg_orders') }} - "###); -} - #[test] fn test_join() { assert_display_snapshot!((compile(r###" diff --git a/website/content/_index.md b/website/content/_index.md index c40e3396934f..349317aaf594 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -246,7 +246,7 @@ showcase_section: SELECT * FROM - table_1 as table_0 + table_1 AS table_0 WHERE _expr_0 <= 1 From b430f03e05171c898ece420674d63511d17f2d69 Mon Sep 17 00:00:00 2001 From: Rich Brown Date: Sun, 19 Feb 2023 16:04:57 -0500 Subject: [PATCH 019/184] docs: Fix "LSP server" (#1896) Fix "LSP server" --- website/content/roadmap.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/roadmap.md b/website/content/roadmap.md index 7a9cb1b107c6..46c5deb259e4 100644 --- a/website/content/roadmap.md +++ b/website/content/roadmap.md @@ -78,7 +78,7 @@ This requires development across multiple dimensions โ€” writing an [LSP server](https://langserver.org/), better support for typing in the compiler, and possibly database cohesion. -While PRQL compiler will never depend on a database to compile queries, LPS +While PRQL compiler will never depend on a database to compile queries, an LSP server could greatly help with generating type definitions from the information schema of a database. From 2560ca59c90faa64eae0b4188e43cd6a2fb64d91 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 19 Feb 2023 23:31:10 +0100 Subject: [PATCH 020/184] docs: Added C header file (#1898) Added C header file --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a3c85b96daf..d42f9d8eee82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ **Integrations**: +- [prql-lib] Added C header file (@vanillajonathan, #1879) + **Internal changes**: **New Contributors**: From d2ee50239c121875c8e55754a932f9ffef895831 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 16:26:53 -0800 Subject: [PATCH 021/184] revert: "feat!: loop" (#1899) Revert "feat!: loop (#1642)" This reverts commit c79c5f1e2b54c021538da2954352e9c3207fca4c. --- CHANGELOG.md | 2 - book/README.md | 2 +- book/book.toml | 2 +- book/src/SUMMARY.md | 4 +- book/src/integrations/jupyter.md | 2 +- book/src/integrations/rill.md | 2 +- book/src/internals/name-resolving.md | 2 +- .../README.md => standard-library.md} | 2 +- .../standard-library/from-text.md | 63 -- .../standard-library/loop.md | 50 -- book/src/syntax.md | 2 +- book/src/transforms/from_text.md | 61 ++ .../README-0.prql => standard-library-0.prql} | 0 .../standard-library/loop-0.prql | 7 - .../from_text-0.prql} | 0 .../from_text-1.prql} | 0 .../from_text-2.prql} | 0 .../snapshot__@examples__cte-0.prql.snap | 22 +- ...snapshot__@examples__employees-0.prql.snap | 21 +- ...snapshot__@examples__employees-1.prql.snap | 27 +- ...snapshot__@examples__employees-2.prql.snap | 23 +- ...snapshot__@examples__employees-3.prql.snap | 11 +- .../snapshot__@examples__misc-0.prql.snap | 15 +- ...snapshot__@examples__variables-0.prql.snap | 3 +- ...snapshot__@examples__variables-1.prql.snap | 9 +- .../snapshot__@introduction-0.prql.snap | 5 +- ...__@language-features__distinct-2.prql.snap | 3 +- ..._@language-features__s-strings-3.prql.snap | 13 +- ...ge-features__standard-library-0.prql.snap} | 3 +- ...atures__standard-library__loop-0.prql.snap | 34 - .../snapshot__@queries__pipelines-2.prql.snap | 9 +- .../snapshot__@queries__variables-0.prql.snap | 4 +- .../snapshots/snapshot__@syntax-5.prql.snap | 3 +- ...pshot__@transforms__from_text-0.prql.snap} | 6 +- ...pshot__@transforms__from_text-1.prql.snap} | 2 +- ...pshot__@transforms__from_text-2.prql.snap} | 2 +- .../snapshot__@transforms__group-2.prql.snap | 3 +- .../snapshot__@transforms__sort-3.prql.snap | 17 +- .../snapshot__@transforms__sort-5.prql.snap | 7 +- .../snapshot__@transforms__window-4.prql.snap | 3 +- ...ge-features__standard-library-0.prql.snap} | 2 +- ...atures__standard-library__loop-0.prql.snap | 13 - ...ce_prql@transforms__from_text-0.prql.snap} | 2 +- ...ce_prql@transforms__from_text-1.prql.snap} | 2 +- ...ce_prql@transforms__from_text-2.prql.snap} | 2 +- prql-compiler/src/ast/pl/expr.rs | 1 - prql-compiler/src/ast/pl/fold.rs | 1 - prql-compiler/src/ast/pl/types.rs | 8 +- prql-compiler/src/ast/rq/fold.rs | 1 - prql-compiler/src/ast/rq/transform.rs | 1 - prql-compiler/src/semantic/lowering.rs | 33 +- prql-compiler/src/semantic/std.prql | 1 - prql-compiler/src/semantic/transforms.rs | 8 - .../prql_compiler__test__prql_to_sql_2.snap | 3 +- prql-compiler/src/sql/anchor.rs | 87 +-- prql-compiler/src/sql/context.rs | 61 +- prql-compiler/src/sql/gen_expr.rs | 75 +- prql-compiler/src/sql/gen_query.rs | 687 ++++++++---------- prql-compiler/src/sql/mod.rs | 35 - prql-compiler/src/sql/preprocess.rs | 68 +- ...query__test__variable_after_aggregate.snap | 3 +- prql-compiler/src/test.rs | 291 +++----- .../tests/integration/queries/loop.prql | 7 - .../integration__tests__test@loop.prql.snap | 12 - 64 files changed, 743 insertions(+), 1107 deletions(-) rename book/src/language-features/{standard-library/README.md => standard-library.md} (98%) delete mode 100644 book/src/language-features/standard-library/from-text.md delete mode 100644 book/src/language-features/standard-library/loop.md rename book/tests/prql/language-features/{standard-library/README-0.prql => standard-library-0.prql} (100%) delete mode 100644 book/tests/prql/language-features/standard-library/loop-0.prql rename book/tests/prql/{language-features/standard-library/from-text-0.prql => transforms/from_text-0.prql} (100%) rename book/tests/prql/{language-features/standard-library/from-text-1.prql => transforms/from_text-1.prql} (100%) rename book/tests/prql/{language-features/standard-library/from-text-2.prql => transforms/from_text-2.prql} (100%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__README-0.prql.snap => snapshot__@language-features__standard-library-0.prql.snap} (84%) delete mode 100644 book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-0.prql.snap => snapshot__@transforms__from_text-0.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-1.prql.snap => snapshot__@transforms__from_text-1.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-2.prql.snap => snapshot__@transforms__from_text-2.prql.snap} (91%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap => snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap} (76%) delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap => snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap} (69%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap => snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap} (76%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap => snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap} (82%) delete mode 100644 prql-compiler/tests/integration/queries/loop.prql delete mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index d42f9d8eee82..fa1d666d8796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,6 @@ **Features**: -- `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) - **Fixes**: **Documentation**: diff --git a/book/README.md b/book/README.md index 57b803d93865..ec088b512dcb 100644 --- a/book/README.md +++ b/book/README.md @@ -1,4 +1,4 @@ -# PRQL language book +# PRQL Language Book These docs serve as a language book, for users of the language. They should be friendly & accessible, at a minimum to those who understand basic SQL. diff --git a/book/book.toml b/book/book.toml index 8c10a1e4b368..f503dc2bb7a9 100644 --- a/book/book.toml +++ b/book/book.toml @@ -2,7 +2,7 @@ description = "Modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement" language = "en" multilingual = false -title = "PRQL language book" +title = "PRQL Language Book" [output.html] additional-css = ["comparison-table.css", "mdbook-admonish.css"] diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index cc27566b74a2..153e70bdb090 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -36,9 +36,7 @@ - [Ranges](./language-features/ranges.md) - [Regex](./language-features/regex.md) - - [Standard library](./language-features/standard-library/README.md) - - [From text](./language-features/standard-library/from-text.md) - - [Loop](./language-features/standard-library/loop.md) + - [Stdlib](./language-features/standard-library.md) - [Strings](./language-features/strings.md) - [S-strings](./language-features/s-strings.md) - [F-strings](./language-features/f-strings.md) diff --git a/book/src/integrations/jupyter.md b/book/src/integrations/jupyter.md index 7b0bdd3c063d..176a47ac11ad 100644 --- a/book/src/integrations/jupyter.md +++ b/book/src/integrations/jupyter.md @@ -24,7 +24,7 @@ could to go! We bundle in `IPython` and `pandas`, though you'll need to install pip install pyprql ``` -### Set up +### Set Up Open up either an `IPython` terminal or `Jupyter` notebook. First, we need to load the extension and connect to a database. diff --git a/book/src/integrations/rill.md b/book/src/integrations/rill.md index 0e2f4729e32e..950e0b5fb50d 100644 --- a/book/src/integrations/rill.md +++ b/book/src/integrations/rill.md @@ -1,5 +1,5 @@ # Rill PRQL has had some work to integrate with Rill. See the -[Rill ssues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more +[Rill Issues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more details. diff --git a/book/src/internals/name-resolving.md b/book/src/internals/name-resolving.md index 78a153358959..74b590e93a14 100644 --- a/book/src/internals/name-resolving.md +++ b/book/src/internals/name-resolving.md @@ -50,7 +50,7 @@ three things can happen: ## Translating to SQL -When translating into an SQL statement which references only one table, there is +When translating into a SQL statement which references only one table, there is no need to reference column names with table prefix. ```prql diff --git a/book/src/language-features/standard-library/README.md b/book/src/language-features/standard-library.md similarity index 98% rename from book/src/language-features/standard-library/README.md rename to book/src/language-features/standard-library.md index 1ccbbc5d92f8..220565d5cf3d 100644 --- a/book/src/language-features/standard-library/README.md +++ b/book/src/language-features/standard-library.md @@ -1,4 +1,4 @@ -# Standard library +# Standard Library The standard library currently contains commonly used functions that are used in SQL. It's not yet as broad as we'd like, and we're very open to expanding it. diff --git a/book/src/language-features/standard-library/from-text.md b/book/src/language-features/standard-library/from-text.md deleted file mode 100644 index 29229f6db0ef..000000000000 --- a/book/src/language-features/standard-library/from-text.md +++ /dev/null @@ -1,63 +0,0 @@ -# From text - -It's often useful to make a small table inline, for example when exploring how a -database will evaluate an expression, or to have a small lookup table inline. -This can be quite verbose in SQL. - -PRQL uses `from_text` for this. - -It accepts a few formats: - -- `format:csv` parses CSV (default), -- `format:json` parses either: - - an array of objects each of which represents a row, or - - an object with fields `columns` & `data`, where `columns` take an array of - column names and `data` takes an array of arrays. - -```prql -from_text """ -a,b,c -1,2,3 -4,5,6 -""" -derive [ - d = b + c, - answer = 20 * 2 + 2, -] -``` - -An example of adding a small lookup table: - -```prql -let temp_format_lookup = from_text format:csv """ -country_code,format -uk,C -us,F -lr,F -de,C -""" - -from temperatures -join temp_format_lookup [==country_code] -``` - -And JSON: - -```prql -let x = from_text format:json """{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}""" - -let y = from_text format:json """ - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -""" - -from x | join y [==a] -``` diff --git a/book/src/language-features/standard-library/loop.md b/book/src/language-features/standard-library/loop.md deleted file mode 100644 index 97f462a8b5cc..000000000000 --- a/book/src/language-features/standard-library/loop.md +++ /dev/null @@ -1,50 +0,0 @@ -# Loop - -> _experimental_ - -```prql_no_test -loop {step_function} {initial_relation} -``` - -Iteratively applies `step` function to `initial` relation until the `step` -returns an empty table. Returns a relation that contains rows of initial -relation and all intermediate relations. - -This behavior could be expressed with following pseudo-code: - -``` -def loop(step, initial): - result = [] - current = initial - while current is not empty: - result = append(result, current) - current = step(current) - - return result -``` - -## Examples - -```prql -from_text format:json '[{"n": 1 }]' -loop ( - filter n<4 - select n = n+1 -) - -# returns [1, 2, 3, 4] -``` - -```admonish -Behavior of WITH RECURSIVE may depend on database configuration (MySQL). -prql-compiler assumes behavior described by -[Postgres documentation](https://www.postgresql.org/docs/15/queries-with.html#QUERIES-WITH-RECURSIVE) -and will not produce correct results for -[alternative configurations of MySQL](https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive). -``` - -```admonish -Currently, `loop` may produce references to the recursive CTE in sub-queries, -which is not supported by some database engines (SQLite). For now, we suggest you keep step -functions simple enough to fit into a single SELECT statement. -``` diff --git a/book/src/syntax.md b/book/src/syntax.md index b23537228f4c..3c0afc5dd5b7 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -166,7 +166,7 @@ sort (-distance) sort [-distance] ``` -## Inner transforms +## Inner Transforms Parentheses are also used for transforms (such as `group` and `window`) that pass their result to an "inner transform". The example below applies the diff --git a/book/src/transforms/from_text.md b/book/src/transforms/from_text.md index a05d2a4b011d..0a9b51160ca7 100644 --- a/book/src/transforms/from_text.md +++ b/book/src/transforms/from_text.md @@ -1 +1,62 @@ # From Text + +It's often useful to make a small table inline, for example when exploring how a +database will evaluate an expression, or to have a small lookup table inline. +This can be quite verbose in SQL. + +PRQL uses `from_text` for this. + +It accepts a few formats: + +- `format:csv`; also the default, for CSV. +- `format:json` for either: + - A list of dicts, + - or a schema of `columns` & `data>`. + +```prql +from_text """ +a,b,c +1,2,3 +4,5,6 +""" +derive [ + d = b + c, + answer = 20 * 2 + 2, +] +``` + +An example of adding a small lookup table: + +```prql +let temp_format_lookup = from_text format:csv """ +country_code,format +uk,C +us,F +lr,F +de,C +""" + +from temperatures +join temp_format_lookup [==country_code] +``` + +And JSON: + +```prql +let x = from_text format:json """{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}""" + +let y = from_text format:json """ + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +""" + +from x | join y [==a] +``` diff --git a/book/tests/prql/language-features/standard-library/README-0.prql b/book/tests/prql/language-features/standard-library-0.prql similarity index 100% rename from book/tests/prql/language-features/standard-library/README-0.prql rename to book/tests/prql/language-features/standard-library-0.prql diff --git a/book/tests/prql/language-features/standard-library/loop-0.prql b/book/tests/prql/language-features/standard-library/loop-0.prql deleted file mode 100644 index 5dccfdba14ae..000000000000 --- a/book/tests/prql/language-features/standard-library/loop-0.prql +++ /dev/null @@ -1,7 +0,0 @@ -from_text format:json '[{"n": 1 }]' -loop ( - filter n<4 - select n = n+1 -) - -# returns [1, 2, 3, 4] diff --git a/book/tests/prql/language-features/standard-library/from-text-0.prql b/book/tests/prql/transforms/from_text-0.prql similarity index 100% rename from book/tests/prql/language-features/standard-library/from-text-0.prql rename to book/tests/prql/transforms/from_text-0.prql diff --git a/book/tests/prql/language-features/standard-library/from-text-1.prql b/book/tests/prql/transforms/from_text-1.prql similarity index 100% rename from book/tests/prql/language-features/standard-library/from-text-1.prql rename to book/tests/prql/transforms/from_text-1.prql diff --git a/book/tests/prql/language-features/standard-library/from-text-2.prql b/book/tests/prql/transforms/from_text-2.prql similarity index 100% rename from book/tests/prql/language-features/standard-library/from-text-2.prql rename to book/tests/prql/transforms/from_text-2.prql diff --git a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap index 36a99fd31e3f..5e55e6c27d2b 100644 --- a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap @@ -1,9 +1,18 @@ --- source: book/tests/snapshot.rs -expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" +expression: "table newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\ntable average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" input_file: book/tests/prql/examples/cte-0.prql --- -WITH newest_employees AS ( +WITH average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country +), +newest_employees AS ( SELECT * FROM @@ -12,14 +21,6 @@ WITH newest_employees AS ( tenure LIMIT 50 -), average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country ) SELECT newest_employees.name, @@ -28,4 +29,3 @@ SELECT FROM newest_employees JOIN average_salaries ON newest_employees.country = average_salaries.country - diff --git a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap index 47650f37675d..2ed2d4eba75e 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" input_file: book/tests/prql/examples/employees-0.prql --- -WITH table_3 AS ( +WITH table_1 AS ( SELECT AVG(salary) AS _expr_0, emp_no @@ -12,24 +12,23 @@ WITH table_3 AS ( GROUP BY emp_no ), -table_1 AS ( +table_2 AS ( SELECT t.title, - AVG(table_2._expr_0) AS avg_salary, + AVG(table_1._expr_0) AS avg_salary, dept_emp.dept_no FROM - table_3 AS table_2 - JOIN titles AS t ON table_2.emp_no = t.emp_no - LEFT JOIN dept_emp ON table_2.emp_no = dept_emp.emp_no + table_1 + JOIN titles AS t ON table_1.emp_no = t.emp_no + LEFT JOIN dept_emp ON table_1.emp_no = dept_emp.emp_no GROUP BY dept_emp.dept_no, t.title ) SELECT departments.dept_name, - table_0.title, - table_0.avg_salary + table_2.title, + table_2.avg_salary FROM - table_1 AS table_0 - JOIN departments ON table_0.dept_no = departments.dept_no - + table_2 + JOIN departments ON table_2.dept_no = departments.dept_no diff --git a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap index 88f00f10486c..434d377e6067 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-1.prql --- -WITH table_3 AS ( +WITH table_1 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,25 +15,24 @@ WITH table_3 AS ( e.emp_no, e.gender ), -table_1 AS ( +table_2 AS ( SELECT - table_2.gender, - AVG(table_2._expr_0) AS salary_avg, - STDDEV(table_2._expr_0) AS salary_sd, + table_1.gender, + AVG(table_1._expr_0) AS salary_avg, + STDDEV(table_1._expr_0) AS salary_sd, de.dept_no FROM - table_3 AS table_2 - LEFT JOIN dept_emp AS de ON table_2.emp_no = de.emp_no + table_1 + LEFT JOIN dept_emp AS de ON table_1.emp_no = de.emp_no GROUP BY de.dept_no, - table_2.gender + table_1.gender ) SELECT departments.dept_name, - table_0.gender, - table_0.salary_avg, - table_0.salary_sd + table_2.gender, + table_2.salary_avg, + table_2.salary_sd FROM - table_1 AS table_0 - JOIN departments ON table_0.dept_no = departments.dept_no - + table_2 + JOIN departments ON table_2.dept_no = departments.dept_no diff --git a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap index 612ece4db0c6..6918730104c0 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-2.prql --- -WITH table_3 AS ( +WITH table_1 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,26 +15,25 @@ WITH table_3 AS ( e.emp_no, e.gender ), -table_1 AS ( +table_2 AS ( SELECT - AVG(table_2._expr_0) AS salary_avg, - STDDEV(table_2._expr_0) AS salary_sd, + AVG(table_1._expr_0) AS salary_avg, + STDDEV(table_1._expr_0) AS salary_sd, dm.emp_no FROM - table_3 AS table_2 - JOIN dept_emp AS de ON table_2.emp_no = de.emp_no + table_1 + JOIN dept_emp AS de ON table_1.emp_no = de.emp_no JOIN dept_manager AS dm ON dm.dept_no = de.dept_no AND (de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date) GROUP BY dm.emp_no, - table_2.gender + table_1.gender ) SELECT managers.first_name || ' ' || managers.last_name AS mng_name, managers.gender, - table_0.salary_avg, - table_0.salary_sd + table_2.salary_avg, + table_2.salary_sd FROM - table_1 AS table_0 - JOIN employees AS managers ON table_0.emp_no = managers.emp_no - + table_2 + JOIN employees AS managers ON table_2.emp_no = managers.emp_no diff --git a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap index 68c457076ef7..fa439fbf23c0 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap @@ -17,12 +17,11 @@ WITH table_1 AS ( de.dept_no ) SELECT - table_0.dept_no, - table_0.salary, + table_1.dept_no, + table_1.salary, employees.gender, titles.title FROM - table_1 AS table_0 - JOIN employees ON table_0.emp_no = employees.emp_no - JOIN titles ON table_0.emp_no = titles.emp_no - + table_1 + JOIN employees ON table_1.emp_no = employees.emp_no + JOIN titles ON table_1.emp_no = titles.emp_no diff --git a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap index 676b3103af9c..b12126c24dd3 100644 --- a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap @@ -1,9 +1,15 @@ --- source: book/tests/snapshot.rs -expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" +expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\ntable parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" input_file: book/tests/prql/examples/misc-0.prql --- -WITH table_1 AS ( +WITH parts AS ( + SELECT + * + FROM + seq_1_to_5 +), +table_1 AS ( SELECT related_id FROM @@ -27,9 +33,8 @@ SELECT -1 ) AS stub FROM - table_1 AS table_0 - JOIN accounts AS a ON a.id = table_0.related_id + table_1 + JOIN accounts AS a ON a.id = table_1.related_id JOIN email_addr_bean_rel AS er ON er.bean_id = a.id AND er.primary_address = '1' JOIN email_addresses AS ea ON ea.id = er.email_address_id - diff --git a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap index 69e10cb2c16d..9f7411a758ba 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap @@ -26,7 +26,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 AS table_0 + table_1 WHERE _expr_0 > 0 GROUP BY @@ -38,4 +38,3 @@ ORDER BY sum_gross_cost LIMIT 20 - diff --git a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap index 77b68ee0c7d1..ea3da8460bb5 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap @@ -13,13 +13,12 @@ WITH table_1 AS ( emp_no ) SELECT - AVG(table_0._expr_0) / 1000 AS salary_k, - AVG(table_0._expr_0) / 1000 * 1000 AS salary + AVG(table_1._expr_0) / 1000 AS salary_k, + AVG(table_1._expr_0) / 1000 * 1000 AS salary FROM - table_1 AS table_0 - JOIN titles ON table_0.emp_no = titles.emp_no + table_1 + JOIN titles ON table_1.emp_no = titles.emp_no GROUP BY titles.title LIMIT 10 - diff --git a/book/tests/snapshots/snapshot__@introduction-0.prql.snap b/book/tests/snapshots/snapshot__@introduction-0.prql.snap index 2cfecfb1a71d..741163b2be4d 100644 --- a/book/tests/snapshots/snapshot__@introduction-0.prql.snap +++ b/book/tests/snapshots/snapshot__@introduction-0.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" +expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" input_file: book/tests/prql/introduction-0.prql --- WITH table_1 AS ( @@ -22,7 +22,7 @@ SELECT CONCAT(title, '_', country) AS id, LEFT(country, 2) AS country_code FROM - table_1 AS table_0 + table_1 WHERE _expr_0 > 0 GROUP BY @@ -35,4 +35,3 @@ ORDER BY country DESC LIMIT 20 - diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap index 693c04dcf449..2d9d6d5178f5 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap @@ -17,7 +17,6 @@ WITH table_1 AS ( SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 <= 1 - diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap index 3d97e867fc17..3f5c880fd181 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" input_file: book/tests/prql/language-features/s-strings-3.prql --- -WITH table_0 AS ( +WITH table_2 AS ( SELECT DISTINCT ON first_name, id, @@ -13,16 +13,15 @@ WITH table_0 AS ( ORDER BY age ASC ), -table_1 AS ( +table_3 AS ( SELECT * FROM salaries ) SELECT - table_2.*, - table_3.* + table_0.*, + table_1.* FROM - table_0 AS table_2 - JOIN table_1 AS table_3 ON table_2.id = table_3.id - + table_2 AS table_0 + JOIN table_3 AS table_1 ON table_0.id = table_1.id diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap index b3a371283e07..31e030d55e0b 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" -input_file: book/tests/prql/language-features/standard-library/README-0.prql +input_file: book/tests/prql/language-features/standard-library-0.prql --- SELECT *, @@ -10,4 +10,3 @@ SELECT NOW() AS time FROM employees - diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap deleted file mode 100644 index 5515357a6c0c..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap +++ /dev/null @@ -1,34 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" -input_file: book/tests/prql/language-features/standard-library/loop-0.prql ---- -WITH table_0 AS ( - SELECT - 1 AS n -), -table_4 AS ( - WITH RECURSIVE loop AS ( - SELECT - n - FROM - table_0 AS table_1 - UNION - ALL - SELECT - n + 1 - FROM - loop AS table_2 - WHERE - n < 4 - ) - SELECT - * - FROM - loop -) -SELECT - n -FROM - table_4 AS table_3 - diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap index 8a7e0fd99bc5..48c578cb780a 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap @@ -16,10 +16,9 @@ WITH table_1 AS ( 10 ) SELECT - table_0.name, - table_0.gross_salary, + table_1.name, + table_1.gross_salary, d.name FROM - table_1 AS table_0 - JOIN department AS d ON table_0.dept_no = d.dept_no - + table_1 + JOIN department AS d ON table_1.dept_no = d.dept_no diff --git a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap index ca97469b4749..e37a88722453 100644 --- a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" input_file: book/tests/prql/queries/variables-0.prql --- -WITH table_1 AS ( +WITH table_0 AS ( SELECT salary FROM @@ -16,7 +16,7 @@ WITH table_1 AS ( SELECT SUM(salary) AS total_salary FROM - table_1 AS table_0 + table_0 ) SELECT total_salary diff --git a/book/tests/snapshots/snapshot__@syntax-5.prql.snap b/book/tests/snapshots/snapshot__@syntax-5.prql.snap index 9095768d6603..374cbd663cf3 100644 --- a/book/tests/snapshots/snapshot__@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-5.prql.snap @@ -14,8 +14,7 @@ SELECT circumference, color FROM - table_1 AS table_0 + table_1 WHERE circumference > 10 AND color <> 'red' - diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap b/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap rename to book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap index 904a45d549da..59de499b2072 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-0.prql +input_file: book/tests/prql/transforms/from_text-0.prql --- -WITH table_0 AS ( +WITH table_1 AS ( SELECT '1' AS a, '2' AS b, @@ -22,5 +22,5 @@ SELECT b + c AS d, 42 AS answer FROM - table_0 AS table_1 + table_1 AS table_0 diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap b/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap rename to book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap index 670e58dfc204..9ae070f052eb 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-1.prql +input_file: book/tests/prql/transforms/from_text-1.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap b/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap similarity index 91% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap rename to book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap index becf706977bb..085bbccf68f8 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-2.prql +input_file: book/tests/prql/transforms/from_text-2.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap index 03289443cc04..a11503ab56c8 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap @@ -17,7 +17,6 @@ WITH table_1 AS ( SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 <= 1 - diff --git a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap index fb7acd653ec6..7b6e784e1da0 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap @@ -3,11 +3,16 @@ source: book/tests/snapshot.rs expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" input_file: book/tests/prql/transforms/sort-3.prql --- +WITH table_1 AS ( + SELECT + *, + substr(first_name, 2, 5) AS _expr_0 + FROM + employees + ORDER BY + _expr_0 +) SELECT - *, - substr(first_name, 2, 5) AS _expr_0 + * FROM - employees -ORDER BY - _expr_0 - + table_1 diff --git a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap index b969c19b2a4d..de8d52ca5f42 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap @@ -12,9 +12,8 @@ WITH table_1 AS ( tenure ) SELECT - table_0.*, + table_1.*, locations.* FROM - table_1 AS table_0 - JOIN locations ON table_0.employee_id = locations.employee_id - + table_1 + JOIN locations ON table_1.employee_id = locations.employee_id diff --git a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap index 0dcf1866c987..13bb14a01bc7 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap @@ -13,7 +13,6 @@ WITH table_1 AS ( SELECT * FROM - table_1 AS table_0 + table_1 WHERE salary < _expr_0 - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap index 7103d173bb5b..691cabab4a62 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__README-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library/README-0.prql +input_file: book/tests/prql/language-features/standard-library-0.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap deleted file mode 100644 index b039f259620b..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__loop-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library/loop-0.prql ---- -from_text format:json '[{"n": 1 }]' -loop ( - filter n < 4 - select n = n + 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap similarity index 69% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap index f5eae06d50c6..d86f2e1e86bb 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library/from-text-0.prql +input_file: book/tests/prql/transforms/from_text-0.prql --- from_text " a,b,c diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap index 8dcf2f21faac..740349748e00 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library/from-text-1.prql +input_file: book/tests/prql/transforms/from_text-1.prql --- let temp_format_lookup = ( from_text format:csv " diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap index 13b437d66562..a0aaabe15cb7 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library__from-text-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library/from-text-2.prql +input_file: book/tests/prql/transforms/from_text-2.prql --- let x = ( from_text format:json '{ diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index a3b0b7b9132c..ea3dc6f0a7b7 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -310,7 +310,6 @@ pub enum TransformKind { pipeline: Box, }, Append(Box), - Loop(Box), } #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index b82f9178a296..3af403b8525d 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -273,7 +273,6 @@ pub fn fold_transform_kind( range: fold_range(fold, range)?, pipeline: Box::new(fold.fold_expr(*pipeline)?), }, - Loop(pipeline) => Loop(Box::new(fold.fold_expr(*pipeline)?)), }) } diff --git a/prql-compiler/src/ast/pl/types.rs b/prql-compiler/src/ast/pl/types.rs index cb1463940c7b..3d4c428d5d75 100644 --- a/prql-compiler/src/ast/pl/types.rs +++ b/prql-compiler/src/ast/pl/types.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use super::Frame; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] +#[derive(Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] pub enum Ty { Empty, Literal(TyLit), @@ -162,3 +162,9 @@ impl Display for Ty { } } } + +impl Debug for Ty { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + Display::fmt(self, f) + } +} diff --git a/prql-compiler/src/ast/rq/fold.rs b/prql-compiler/src/ast/rq/fold.rs index 1c799e35dfe0..d84d6385ba37 100644 --- a/prql-compiler/src/ast/rq/fold.rs +++ b/prql-compiler/src/ast/rq/fold.rs @@ -187,7 +187,6 @@ pub fn fold_transform( filter: fold.fold_expr(filter)?, }, Append(bottom) => Append(fold.fold_table_ref(bottom)?), - Loop(transforms) => Loop(fold_transforms(fold, transforms)?), }; Ok(transform) } diff --git a/prql-compiler/src/ast/rq/transform.rs b/prql-compiler/src/ast/rq/transform.rs index 875bc3d922b6..7a946e1d2c13 100644 --- a/prql-compiler/src/ast/rq/transform.rs +++ b/prql-compiler/src/ast/rq/transform.rs @@ -25,7 +25,6 @@ pub enum Transform { filter: Expr, }, Append(TableRef), - Loop(Vec), } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index 25383b9dd744..bb595dd20da0 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -269,7 +269,7 @@ impl Lowerer { let ty = expr.ty.clone(); let prev_pipeline = self.pipeline.drain(..).collect_vec(); - self.lower_pipeline(expr, None)?; + self.lower_pipeline(expr)?; let mut transforms = self.pipeline.drain(..).collect_vec(); let columns = self.push_select(ty, &mut transforms)?; @@ -284,22 +284,10 @@ impl Lowerer { } // Result is stored in self.pipeline - fn lower_pipeline(&mut self, ast: pl::Expr, closure_param: Option) -> Result<()> { + fn lower_pipeline(&mut self, ast: pl::Expr) -> Result<()> { let transform_call = match ast.kind { pl::ExprKind::TransformCall(transform) => transform, - pl::ExprKind::Closure(closure) => { - let param = closure.params.first(); - let param = param.and_then(|p| p.name.parse::().ok()); - return self.lower_pipeline(*closure.body, param); - } _ => { - if let Some(target) = ast.target_id { - if Some(target) == closure_param { - // ast is a closure param, so we can skip pushing From - return Ok(()); - } - } - let table_ref = self.lower_table_ref(ast)?; self.pipeline.push(Transform::From(table_ref)); return Ok(()); @@ -307,7 +295,7 @@ impl Lowerer { }; // lower input table - self.lower_pipeline(*transform_call.input, closure_param)?; + self.lower_pipeline(*transform_call.input)?; // ... and continues with transforms created in this function @@ -374,16 +362,8 @@ impl Lowerer { pl::TransformKind::Append(bottom) => { let bottom = self.lower_table_ref(*bottom)?; - self.pipeline.push(Transform::Append(bottom)); - } - pl::TransformKind::Loop(pipeline) => { - let relation = self.lower_relation(*pipeline)?; - let mut pipeline = relation.kind.into_pipeline().unwrap(); - - // last select is not needed here - pipeline.pop(); - - self.pipeline.push(Transform::Loop(pipeline)); + let transform = Transform::Append(bottom); + self.pipeline.push(transform); } pl::TransformKind::Group { .. } | pl::TransformKind::Window { .. } => unreachable!( "transform `{}` cannot be lowered.", @@ -700,10 +680,9 @@ impl Lowerer { let name = match name { Some(v) => RelationColumn::Single(Some(v.clone())), None => return Err(Error::new_simple( - "This table contains unnamed columns that need to be referenced by name", + "This table contains unnamed columns, that need to be referenced by name", ) .with_span(self.context.span_map.get(&id).cloned()) - .with_help("The name may have been overridden later in the pipeline.") .into()), }; log::trace!("lookup cid of name={name:?} in input {input_columns:?}"); diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index 586a9dcaf94f..f906e2dc7b23 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -48,7 +48,6 @@ func remove
`default_db.bottom`
top
-> ( filter (all (map _is_null b.*)) select t.* ) -func loop
pipeline top
-> null # List functions func all list -> null diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs index 15c73cbbe44f..b517b2a81c33 100644 --- a/prql-compiler/src/semantic/transforms.rs +++ b/prql-compiler/src/semantic/transforms.rs @@ -192,13 +192,6 @@ pub fn cast_transform(resolver: &mut Resolver, closure: Closure) -> Result { - let [pipeline, tbl] = unpack::<2>(closure); - - let pipeline = fold_by_simulating_eval(resolver, pipeline, tbl.ty.clone().unwrap())?; - - (TransformKind::Loop(Box::new(pipeline)), tbl) - } "std.in" => { // yes, this is not a transform, but this is the most appropriate place for it @@ -589,7 +582,6 @@ impl TransformCall { let bottom = ty_frame_or_default(bottom)?; append(top, bottom)? } - Loop(_) => ty_frame_or_default(&self.input)?, Sort { .. } | Filter { .. } | Take { .. } => ty_frame_or_default(&self.input)?, }) } diff --git a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap index 23a1cc2ad749..bbc44298cbb5 100644 --- a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap +++ b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap @@ -25,7 +25,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 AS table_0 + table_1 WHERE _expr_0 > 0 GROUP BY @@ -37,4 +37,3 @@ ORDER BY sum_gross_cost LIMIT 20 - diff --git a/prql-compiler/src/sql/anchor.rs b/prql-compiler/src/sql/anchor.rs index 4c0e0ece9b76..6740cd2cc391 100644 --- a/prql-compiler/src/sql/anchor.rs +++ b/prql-compiler/src/sql/anchor.rs @@ -3,28 +3,28 @@ use itertools::Itertools; use std::collections::{HashMap, HashSet}; use crate::ast::rq::{ - self, fold_transform, CId, Compute, Expr, RelationColumn, RqFold, TableRef, Transform, + self, fold_transform, CId, Compute, Expr, Relation, RelationColumn, RelationKind, RqFold, + TableDecl, TableRef, Transform, }; -use crate::sql::context::SqlTableDecl; -use crate::sql::preprocess::{SqlRelation, SqlRelationKind}; use super::{ context::{AnchorContext, ColumnDecl}, preprocess::{SqlFold, SqlTransform}, }; +type RemainingPipeline = (Vec, Vec); + /// Splits pipeline into two parts, such that the second part contains /// maximum number of transforms while "fitting" into a SELECT query. pub(super) fn split_off_back( - mut pipeline: Vec, ctx: &mut AnchorContext, -) -> (Option>, Vec) { + output: Vec, + mut pipeline: Vec, +) -> (Option, Vec) { if pipeline.is_empty() { return (None, Vec::new()); } - let output = AnchorContext::determine_select_columns(&pipeline); - log::debug!("traversing pipeline to obtain columns: {output:?}"); let mut following_transforms: HashSet = HashSet::new(); @@ -137,9 +137,8 @@ pub(super) fn split_off_back( None } else { // drop inputs that were satisfied in current pipeline - pipeline.push(SqlTransform::Super(Transform::Select(missing))); - Some(pipeline) + Some((pipeline, missing)) }; curr_pipeline_rev.reverse(); @@ -167,23 +166,20 @@ fn can_materialize(compute: &Compute, inputs_required: &[Requirement]) -> bool { } /// Applies adjustments to second part of a pipeline when it's split: -/// - append Select to proceeding pipeline -/// - prepend From to atomic pipeline -/// - redefine columns materialized in atomic pipeline +/// - prepend pipeline with From +/// - redefine columns materialized in preceding pipeline /// - redirect all references to original columns to the new ones pub(super) fn anchor_split( ctx: &mut AnchorContext, - preceding: Vec, - atomic: Vec, + first_table_name: &str, + cols_at_split: &[CId], + second_pipeline: Vec, ) -> Vec { let new_tid = ctx.tid.gen(); - let preceding_select = &preceding.last().unwrap().as_super().unwrap(); - let cols_at_split = preceding_select.as_select().unwrap(); - log::debug!("split pipeline, first pipeline output: {cols_at_split:?}"); - // redefine columns of the atomic pipeline + // define columns of the new CTE let mut cid_redirects = HashMap::::new(); let mut new_columns = Vec::new(); for old_cid in cols_at_split { @@ -208,31 +204,32 @@ pub(super) fn anchor_split( // define a new table ctx.table_decls.insert( new_tid, - SqlTableDecl { + TableDecl { id: new_tid, - name: None, - relation: Some(SqlRelation { - columns: cols_at_split - .iter() - .map(|_| RelationColumn::Single(None)) - .collect_vec(), - kind: SqlRelationKind::PreprocessedPipeline(preceding), - }), + name: Some(first_table_name.to_string()), + // here we should put the pipeline, but because how this function is called, + // we need to return the pipeline directly, so we just insert dummy expr instead + relation: Relation { + kind: RelationKind::SString(vec![]), + columns: vec![], + }, }, ); // define instance of that table - let table_ref = ctx.create_table_instance(TableRef { + let table_ref = TableRef { source: new_tid, - name: None, + name: Some(first_table_name.to_string()), columns: new_columns, - }); + }; + ctx.create_table_instance(table_ref.clone()); // adjust second part: prepend from and rewrite expressions to use new columns - let mut second = atomic; + let mut second = second_pipeline; second.insert(0, SqlTransform::Super(Transform::From(table_ref))); - CidRedirector::redirect(second, cid_redirects, ctx) + let mut redirector = CidRedirector { ctx, cid_redirects }; + redirector.fold_sql_transforms(second).unwrap() } /// Determines whether a pipeline must be split at a transform to @@ -251,7 +248,6 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) // - take (no limit) // - distinct // - append/except/intersect (no limit) - // - loop (max 1x) // // Select is not affected by the order. use SqlTransform::*; @@ -310,7 +306,6 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) "Distinct", ], ), - SqlTransform::Loop(_) => !following.is_empty(), _ => false, }; @@ -392,13 +387,12 @@ pub(super) fn get_requirements( cids } - Super(Aggregate { .. } | Append(_) | Transform::Loop(_)) => unreachable!(), - Super(Select(_) | From(_)) + Super(Append(_)) => unreachable!(), + Super(Select(_) | From(_) | Aggregate { .. }) | Distinct | Union { .. } | Except { .. } - | Intersect { .. } - | SqlTransform::Loop(_) => return Vec::new(), + | Intersect { .. } => return Vec::new(), }; // general case: determine complexity @@ -508,20 +502,9 @@ impl RqFold for CidCollector { } } -pub(super) struct CidRedirector<'a> { - pub ctx: &'a mut AnchorContext, - pub cid_redirects: HashMap, -} - -impl<'a> CidRedirector<'a> { - pub fn redirect( - pipeline: Vec, - cid_redirects: HashMap, - ctx: &mut AnchorContext, - ) -> Vec { - let mut redirector = CidRedirector { ctx, cid_redirects }; - redirector.fold_sql_transforms(pipeline).unwrap() - } +struct CidRedirector<'a> { + ctx: &'a mut AnchorContext, + cid_redirects: HashMap, } impl<'a> RqFold for CidRedirector<'a> { diff --git a/prql-compiler/src/sql/context.rs b/prql-compiler/src/sql/context.rs index b9b38e1ae2bf..4fa41ea51e71 100644 --- a/prql-compiler/src/sql/context.rs +++ b/prql-compiler/src/sql/context.rs @@ -10,19 +10,19 @@ use itertools::Itertools; use crate::ast::pl::TableExternRef; use crate::ast::rq::{ - fold_table, CId, Compute, Query, Relation, RelationColumn, RelationKind, RqFold, TId, - TableDecl, TableRef, Transform, + fold_table, CId, Compute, Query, RelationColumn, RelationKind, RqFold, TId, TableDecl, + TableRef, Transform, }; use crate::utils::{IdGenerator, NameGenerator}; -use super::preprocess::{SqlRelation, SqlTransform}; +use super::preprocess::SqlTransform; #[derive(Default)] pub struct AnchorContext { pub(super) column_decls: HashMap, pub(super) column_names: HashMap, - pub(super) table_decls: HashMap, + pub(super) table_decls: HashMap, pub(super) table_instances: HashMap, @@ -33,20 +33,6 @@ pub struct AnchorContext { pub(super) tid: IdGenerator, pub(super) tiid: IdGenerator, } - -#[derive(Debug, Clone)] -pub(super) struct SqlTableDecl { - #[allow(dead_code)] - pub id: TId, - - pub name: Option, - - /// Relation that still needs to be defined (usually as CTE) so it can be referenced by name. - /// None means that it has already been defined, or was not needed to be defined in the - /// first place. - pub relation: Option, -} - /// Table instance id #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TIId(usize); @@ -65,7 +51,7 @@ pub enum ColumnDecl { } impl AnchorContext { - pub fn of(query: Query) -> (Self, Relation) { + pub fn of(query: Query) -> (Self, Query) { let (cid, tid, query) = IdGenerator::load(query); let context = AnchorContext { @@ -92,7 +78,7 @@ impl AnchorContext { self.column_decls.insert(id, decl); } - pub fn create_table_instance(&mut self, mut table_ref: TableRef) -> TableRef { + pub fn create_table_instance(&mut self, mut table_ref: TableRef) { let tiid = self.tiid.gen(); for (col, cid) in &table_ref.columns { @@ -104,8 +90,7 @@ impl AnchorContext { table_ref.name = Some(self.table_name.gen()) } - self.table_instances.insert(tiid, table_ref.clone()); - table_ref + self.table_instances.insert(tiid, table_ref); } pub(crate) fn ensure_column_name(&mut self, cid: CId) -> Option<&String> { @@ -208,45 +193,29 @@ struct QueryLoader { } impl QueryLoader { - fn load(context: AnchorContext, query: Query) -> (AnchorContext, Relation) { + fn load(context: AnchorContext, query: Query) -> (AnchorContext, Query) { let mut loader = QueryLoader { context }; - - for t in query.tables { - loader.load_table(t).unwrap(); - } - let relation = loader.fold_relation(query.relation).unwrap(); - (loader.context, relation) + let query = loader.fold_query(query).unwrap(); + (loader.context, query) } +} - fn load_table(&mut self, table: TableDecl) -> Result<()> { +impl RqFold for QueryLoader { + fn fold_table(&mut self, table: TableDecl) -> Result { let mut decl = fold_table(self, table)?; - // assume name of the LocalTable that the relation is referencing if let RelationKind::ExternRef(TableExternRef::LocalTable(table)) = &decl.relation.kind { decl.name = Some(table.clone()); } - // generate name (if not present) if decl.name.is_none() && decl.relation.kind.as_extern_ref().is_none() { decl.name = Some(self.context.table_name.gen()); } - let sql_decl = SqlTableDecl { - id: decl.id, - name: decl.name, - relation: if matches!(decl.relation.kind, RelationKind::ExternRef(_)) { - None - } else { - Some(decl.relation.into()) - }, - }; - - self.context.table_decls.insert(decl.id, sql_decl); - Ok(()) + self.context.table_decls.insert(decl.id, decl.clone()); + Ok(decl) } -} -impl RqFold for QueryLoader { fn fold_compute(&mut self, compute: Compute) -> Result { self.context.register_compute(compute.clone()); Ok(compute) diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 271b4a6a1833..51d00a1cdd8a 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -6,7 +6,8 @@ use lazy_static::lazy_static; use regex::Regex; use sqlparser::ast::{ self as sql_ast, BinaryOperator, DateTimeField, Function, FunctionArg, FunctionArgExpr, Ident, - ObjectName, OrderByExpr, SelectItem, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, + Join, JoinConstraint, JoinOperator, ObjectName, OrderByExpr, SelectItem, TableAlias, + TableFactor, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, }; use sqlparser::keywords::{ Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX, RESERVED_FOR_COLUMN_ALIAS, RESERVED_FOR_TABLE_ALIAS, @@ -14,7 +15,8 @@ use sqlparser::keywords::{ use std::collections::HashSet; use crate::ast::pl::{ - BinOp, ColumnSort, InterpolateItem, Literal, Range, SortDirection, WindowFrame, WindowKind, + BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, SortDirection, TableExternRef, + WindowFrame, WindowKind, }; use crate::ast::rq::*; use crate::error::{Error, Span}; @@ -185,7 +187,7 @@ pub(super) fn translate_literal(l: Literal, ctx: &Context) -> Result Result { - if ctx.query.pre_projection { + if ctx.pre_projection { log::debug!("translating {cid:?} pre projection"); let decl = ctx.anchor.column_decls.get(&cid).expect("bad RQ ids"); @@ -229,7 +231,7 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result { let name = ctx.anchor.column_names.get(&cid).cloned(); - name.expect("name of this column has not been to be set before generating SQL") + name.expect("a name of this column to be set before generating SQL") } }; @@ -242,6 +244,38 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result TableFactor { + let decl = ctx.anchor.table_decls.get(&table_ref.source).unwrap(); + + let name = match &decl.relation.kind { + // special case for anchor + RelationKind::ExternRef(TableExternRef::Anchor(anchor_id)) => { + sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]) + } + + // base case + _ => { + let decl_name = decl.name.clone().unwrap(); + + sql_ast::ObjectName(translate_ident(Some(decl_name), None, ctx)) + } + }; + + TableFactor::Table { + name, + alias: if decl.name == table_ref.name { + None + } else { + table_ref.name.map(|ident| TableAlias { + name: translate_ident_part(ident, ctx), + columns: vec![], + }) + }, + args: None, + with_hints: vec![], + } +} + pub(super) fn translate_sstring( items: Vec>, ctx: &mut Context, @@ -589,6 +623,23 @@ pub(super) fn translate_column_sort( }) } +pub(super) fn translate_join( + (side, with, filter): (JoinSide, TableRef, Expr), + ctx: &mut Context, +) -> Result { + let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); + + Ok(Join { + relation: table_factor_of_tid(with, ctx), + join_operator: match side { + JoinSide::Inner => JoinOperator::Inner(constraint), + JoinSide::Left => JoinOperator::LeftOuter(constraint), + JoinSide::Right => JoinOperator::RightOuter(constraint), + JoinSide::Full => JoinOperator::FullOuter(constraint), + }, + }) +} + /// Translate a PRQL Ident to a Vec of SQL Idents. // We return a vec of SQL Idents because sqlparser sometimes uses // [ObjectName](sql_ast::ObjectName) and sometimes uses @@ -600,7 +651,7 @@ pub(super) fn translate_ident( ctx: &Context, ) -> Vec { let mut parts = Vec::with_capacity(4); - if !ctx.query.omit_ident_prefix || column.is_none() { + if !ctx.omit_ident_prefix || column.is_none() { if let Some(table) = table_name { #[allow(clippy::if_same_then_else)] if ctx.dialect.big_query_quoting() { @@ -903,12 +954,22 @@ mod test { { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_with_concat_function = Context::new(Box::new(GenericDialect {}), anchor); + context_with_concat_function = Context { + dialect: Box::new(GenericDialect {}), + anchor, + omit_ident_prefix: false, + pre_projection: false, + }; } { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_without_concat_function = Context::new(Box::new(SQLiteDialect {}), anchor); + context_without_concat_function = Context { + dialect: Box::new(SQLiteDialect {}), + anchor, + omit_ident_prefix: false, + pre_projection: false, + }; } fn str_lit(s: &str) -> InterpolateItem { diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index fba04d0be692..a109eb8b0aa1 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -6,23 +6,21 @@ use std::collections::HashSet; use std::str::FromStr; use anyhow::{anyhow, Result}; +use enum_as_inner::EnumAsInner; use itertools::Itertools; use sqlparser::ast::{ - self as sql_ast, Ident, Join, JoinConstraint, JoinOperator, Select, SelectItem, SetExpr, - TableAlias, TableFactor, TableWithJoins, + self as sql_ast, Ident, Select, SelectItem, SetExpr, TableAlias, TableFactor, TableWithJoins, }; -use crate::ast::pl::{BinOp, JoinSide, Literal, RelationLiteral}; -use crate::ast::rq::{CId, Expr, ExprKind, Query, RelationKind, TableRef, Transform}; -use crate::sql::anchor::anchor_split; -use crate::sql::preprocess::SqlRelationKind; +use crate::ast::pl::{BinOp, Literal, RelationLiteral}; +use crate::ast::rq::{CId, Expr, ExprKind, Query, Relation, RelationKind, TableDecl, Transform}; use crate::utils::{BreakUp, IntoOnly, Pluck}; use crate::Target; use super::context::AnchorContext; use super::gen_expr::*; use super::gen_projection::*; -use super::preprocess::{self, SqlRelation, SqlTransform}; +use super::preprocess::{self, SqlTransform}; use super::{anchor, Context, Dialect}; pub fn translate_query(query: Query, dialect: Option) -> Result { @@ -38,17 +36,77 @@ pub fn translate_query(query: Query, dialect: Option) -> Result { + // preprocess + let pipeline = Ok(pipeline) + .map(preprocess::normalize) + .map(preprocess::push_down_selects) + .map(preprocess::prune_inputs) + .map(preprocess::wrap) + .and_then(|p| preprocess::distinct(p, &mut context)) + .map(preprocess::union) + .and_then(|p| preprocess::except(p, &context)) + .and_then(|p| preprocess::intersect(p, &context)) + .map(preprocess::reorder)?; + + // load names of output columns + context.anchor.load_names(&pipeline, table.relation.columns); + + // split to atomics + let ats = split_into_atomics(name, pipeline, &mut context.anchor); + + // ensure names for all columns that need it + ensure_names(&ats, &mut context.anchor); + + atomics.extend(ats); + } + RelationKind::Literal(_) | RelationKind::SString(_) => atomics.push(AtomicQuery { + name, + relation: SqlRelation::Super(table.relation.kind), + }), + RelationKind::ExternRef(_) => { + // ref does not need it's own CTE + } + } + } + + // take last table + let main_query = atomics.remove(atomics.len() - 1); + let ctes = atomics; + + // convert each of the CTEs + let ctes: Vec<_> = ctes + .into_iter() + .map(|t| table_to_sql_cte(t, &mut context)) + .try_collect()?; - // compile main relation that will recursively compile CTEs - let mut main_query = sql_query_of_sql_relation(main_relation.into(), &mut ctx)?; + // convert main query + let mut main_query = sql_query_of_relation(main_query.relation, &mut context)?; // attach CTEs - if !ctx.ctes.is_empty() { + if !ctes.is_empty() { main_query.with = Some(sql_ast::With { - cte_tables: ctx.ctes.drain(..).collect_vec(), + cte_tables: ctes, recursive: false, }); } @@ -56,188 +114,99 @@ pub fn translate_query(query: Query, dialect: Option) -> Result Result { - use RelationKind::*; - - // preprocess & split into atomics - match sql_relation.kind { - // base case - SqlRelationKind::Super(Pipeline(pipeline)) => { - // preprocess - let pipeline = Ok(pipeline) - .map(preprocess::normalize) - .map(preprocess::prune_inputs) - .map(preprocess::wrap) - .and_then(|p| preprocess::distinct(p, ctx)) - .map(preprocess::union) - .and_then(|p| preprocess::except(p, ctx)) - .and_then(|p| preprocess::intersect(p, ctx)) - .map(preprocess::reorder)?; - - // load names of output columns - ctx.anchor.load_names(&pipeline, sql_relation.columns); - - sql_query_of_pipeline(pipeline, ctx) - } - - // no need to preprocess, has been done already - SqlRelationKind::PreprocessedPipeline(pipeline) => sql_query_of_pipeline(pipeline, ctx), - - // special case: literals - SqlRelationKind::Super(Literal(lit)) => sql_of_sample_data(lit, ctx), - - // special case: s-strings - SqlRelationKind::Super(SString(items)) => translate_query_sstring(items, ctx), - - // ref cannot be converted directly into query and does not need it's own CTE - SqlRelationKind::Super(ExternRef(_)) => unreachable!(), - } +/// A query that can be expressed with one SELECT statement +#[derive(Debug)] +pub struct AtomicQuery { + name: String, + relation: SqlRelation, } -fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result { - let table_ref_alias = (table_ref.name.clone()) - .map(|ident| translate_ident_part(ident, ctx)) - .map(simple_table_alias); - - let decl = ctx.anchor.table_decls.get_mut(&table_ref.source).unwrap(); +#[derive(Debug, EnumAsInner)] +enum SqlRelation { + Super(RelationKind), + Pipeline(Vec), +} - // prepare names - let table_name = match &decl.name { - None => { - decl.name = Some(ctx.anchor.table_name.gen()); - decl.name.clone().unwrap() - } - Some(n) => n.clone(), +fn into_tables( + main_pipeline: Relation, + tables: Vec, + context: &mut Context, +) -> Result> { + let main = TableDecl { + id: context.anchor.tid.gen(), + name: None, + relation: main_pipeline, }; + Ok([tables, vec![main]].concat()) +} - // ensure that the table is declared - if let Some(sql_relation) = decl.relation.take() { - // if we cannot use CTEs - if ctx.query.forbid_ctes { - // restore relation for other references - decl.relation = Some(sql_relation.clone()); - - // return a sub-query - let query = sql_query_of_sql_relation(sql_relation, ctx)?; - return Ok(TableFactor::Derived { - lateral: false, - subquery: Box::new(query), - alias: table_ref_alias, - }); - } - - let query = sql_query_of_sql_relation(sql_relation, ctx)?; - let alias = sql_ast::TableAlias { - name: translate_ident_part(table_name.clone(), ctx), - columns: vec![], - }; - - ctx.ctes.push(sql_ast::Cte { - alias, - query: Box::new(query), - from: None, - }) - } - - // let name = match &decl.relation { - // // special case for anchor - // // TODO - // // Some(SqlRelationKind::Super(RelationKind::ExternRef(TableExternRef::Anchor( - // // anchor_id, - // // )))) => sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]), - - // // base case - // _ => { - - // } - // }; - - let name = sql_ast::ObjectName(translate_ident(Some(table_name.clone()), None, ctx)); - - Ok(TableFactor::Table { - name, - alias: if Some(table_name) == table_ref.name { - None - } else { - table_ref_alias - }, - args: None, - with_hints: vec![], +fn table_to_sql_cte(table: AtomicQuery, context: &mut Context) -> Result { + let alias = sql_ast::TableAlias { + name: translate_ident_part(table.name, context), + columns: vec![], + }; + Ok(sql_ast::Cte { + alias, + query: Box::new(sql_query_of_relation(table.relation, context)?), + from: None, }) } -fn translate_join( - (side, with, filter): (JoinSide, TableRef, Expr), - ctx: &mut Context, -) -> Result { - let relation = table_factor_of_table_ref(with, ctx)?; - - let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); - - Ok(Join { - relation, - join_operator: match side { - JoinSide::Inner => JoinOperator::Inner(constraint), - JoinSide::Left => JoinOperator::LeftOuter(constraint), - JoinSide::Right => JoinOperator::RightOuter(constraint), - JoinSide::Full => JoinOperator::FullOuter(constraint), - }, - }) +fn sql_query_of_relation(relation: SqlRelation, context: &mut Context) -> Result { + use RelationKind::*; + + match relation { + SqlRelation::Super(ExternRef(_)) | SqlRelation::Super(Pipeline(_)) => unreachable!(), + SqlRelation::Pipeline(pipeline) => sql_query_of_pipeline(pipeline, context), + SqlRelation::Super(Literal(lit)) => Ok(sql_of_sample_data(lit, context)?), + SqlRelation::Super(SString(items)) => translate_query_sstring(items, context), + } } fn sql_query_of_pipeline( - mut pipeline: Vec, - ctx: &mut Context, + pipeline: Vec, + context: &mut Context, ) -> Result { use SqlTransform::*; - // special case: loop - if pipeline.iter().any(|t| matches!(t, Loop(_))) { - pipeline = sql_of_loop(pipeline, ctx)?; - } - - // extract an atomic pipeline from back of the pipeline and stash preceding part into context - let pipeline = extract_atomic(pipeline, &mut ctx.anchor); - - // ensure names for all columns that need it - ensure_names(&pipeline, &mut ctx.anchor); - let (select, set_ops) = pipeline.break_up(|t| matches!(t, Union { .. } | Except { .. } | Intersect { .. })); - let select = sql_select_query_of_pipeline(select, ctx)?; + let select = sql_select_query_of_pipeline(select, context)?; - sql_set_ops_of_pipeline(select, set_ops, ctx) + sql_set_ops_of_pipeline(select, set_ops, context) } fn sql_select_query_of_pipeline( mut pipeline: Vec, - ctx: &mut Context, + context: &mut Context, ) -> Result { let table_count = count_tables(&pipeline); log::debug!("atomic query contains {table_count} tables"); - ctx.push_query(); - ctx.query.omit_ident_prefix = table_count == 1; - ctx.query.pre_projection = true; + context.omit_ident_prefix = table_count == 1; + + context.pre_projection = true; + + let projection = pipeline + .pluck(|t| t.into_super_and(|t| t.into_select())) + .into_only() + .unwrap(); + let projection = translate_wildcards(&context.anchor, projection); + let projection = translate_select_items(projection.0, projection.1, context)?; - let mut from: Vec<_> = pipeline + let mut from = pipeline .pluck(|t| t.into_super_and(|t| t.into_from())) .into_iter() - .map(|source| -> Result { - Ok(TableWithJoins { - relation: table_factor_of_table_ref(source, ctx)?, - joins: vec![], - }) + .map(|source| TableWithJoins { + relation: table_factor_of_tid(source, context), + joins: vec![], }) - .try_collect()?; + .collect::>(); let joins = pipeline .pluck(|t| t.into_super_and(|t| t.into_join())) .into_iter() - .map(|j| translate_join(j, ctx)) + .map(|j| translate_join(j, context)) .collect::>>()?; if !joins.is_empty() { if let Some(from) = from.last_mut() { @@ -247,13 +216,6 @@ fn sql_select_query_of_pipeline( } } - let projection = pipeline - .pluck(|t| t.into_super_and(|t| t.into_select())) - .into_only() - .unwrap(); - let projection = translate_wildcards(&ctx.anchor, projection); - let projection = translate_select_items(projection.0, projection.1, ctx)?; - let sorts = pipeline.pluck(|t| t.into_super_and(|t| t.into_sort())); let takes = pipeline.pluck(|t| t.into_super_and(|t| t.into_take())); let distinct = pipeline.iter().any(|t| matches!(t, SqlTransform::Distinct)); @@ -269,11 +231,11 @@ fn sql_select_query_of_pipeline( // WHERE and HAVING let where_ = filter_of_conditions( before_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - ctx, + context, )?; let having = filter_of_conditions( after_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - ctx, + context, )?; // GROUP BY @@ -282,9 +244,9 @@ fn sql_select_query_of_pipeline( .into_iter() .next(); let group_by: Vec = aggregate.map(|(part, _)| part).unwrap_or_default(); - let group_by = try_into_exprs(group_by, ctx, None)?; + let group_by = try_into_exprs(group_by, context, None)?; - ctx.query.pre_projection = false; + context.pre_projection = false; let ranges = takes.into_iter().map(|x| x.range).collect(); let take = range_of_ranges(ranges)?; @@ -295,7 +257,7 @@ fn sql_select_query_of_pipeline( None } else { Some(sqlparser::ast::Offset { - value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), ctx)?, + value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), context)?, rows: sqlparser::ast::OffsetRows::None, }) }; @@ -306,20 +268,17 @@ fn sql_select_query_of_pipeline( .map(|sorts| { sorts .iter() - .map(|s| translate_column_sort(s, ctx)) + .map(|s| translate_column_sort(s, context)) .try_collect() }) .transpose()? .unwrap_or_default(); - let (top, limit) = if ctx.dialect.use_top() { - (limit.map(|l| top_of_i64(l, ctx)), None) + let (top, limit) = if context.dialect.use_top() { + (limit.map(|l| top_of_i64(l, context)), None) } else { (None, limit.map(expr_of_i64)) }; - - ctx.pop_query(); - Ok(sql_ast::Query { order_by, limit, @@ -363,7 +322,36 @@ fn sql_set_ops_of_pipeline( }; // prepare top - let left = query_to_set_expr(top, context); + let top_is_simple = top.with.is_none() + && top.order_by.is_empty() + && top.limit.is_none() + && top.offset.is_none() + && top.fetch.is_none() + && top.locks.is_empty(); + + let left = if top_is_simple { + top.body + } else { + // top is not simple, so we need to wrap it into + // `SELECT * FROM top` + Box::new(SetExpr::Select(Box::new(Select { + projection: vec![SelectItem::Wildcard( + sql_ast::WildcardAdditionalOptions::default(), + )], + from: vec![TableWithJoins { + relation: TableFactor::Derived { + lateral: false, + subquery: Box::new(top), + alias: Some(TableAlias { + name: Ident::new(context.anchor.table_name.gen()), + columns: Vec::new(), + }), + }, + joins: vec![], + }], + ..default_select() + }))) + }; top = default_query(SetExpr::SetOperation { left, @@ -372,7 +360,7 @@ fn sql_set_ops_of_pipeline( sql_ast::WildcardAdditionalOptions::default(), )], from: vec![TableWithJoins { - relation: table_factor_of_table_ref(bottom, context)?, + relation: table_factor_of_tid(bottom, context), joins: vec![], }], ..default_select() @@ -393,99 +381,6 @@ fn sql_set_ops_of_pipeline( Ok(top) } -fn sql_of_loop(pipeline: Vec, ctx: &mut Context) -> Result> { - // split the pipeline - let (mut initial, mut following) = pipeline.break_up(|t| matches!(t, SqlTransform::Loop(_))); - let loop_ = following.remove(0); - let step = loop_.into_loop().unwrap(); - - // RECURSIVE can only follow WITH directly, which means that if we want to use it for - // an arbitrary query, we have to defined a *nested* WITH RECURSIVE and not use - // the top-level list of CTEs. - - // determine columns of the initial table - let recursive_columns = AnchorContext::determine_select_columns(&initial); - - // do the same thing we do when splitting a pipeline - // (defining new columns, redirecting cids) - let recursive_columns = SqlTransform::Super(Transform::Select(recursive_columns)); - initial.push(recursive_columns.clone()); - let step = anchor_split(&mut ctx.anchor, initial, step); - let from = step.first().unwrap().as_super().unwrap().as_from().unwrap(); - - let initial = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); - initial.name = Some("loop".to_string()); - let initial_relation = initial.relation.take().unwrap(); - - let initial = initial_relation.kind.into_preprocessed_pipeline().unwrap(); - - // compile initial - let initial = query_to_set_expr(sql_query_of_pipeline(initial, ctx)?, ctx); - - // compile step (without producing CTEs) - ctx.push_query(); - ctx.query.forbid_ctes = true; - - let step = query_to_set_expr(sql_query_of_pipeline(step, ctx)?, ctx); - - ctx.pop_query(); - - // build CTE and it's SELECT - let cte = sql_ast::Cte { - alias: simple_table_alias(Ident::new("loop")), - query: Box::new(default_query(SetExpr::SetOperation { - op: sql_ast::SetOperator::Union, - set_quantifier: sql_ast::SetQuantifier::All, - left: initial, - right: step, - })), - from: None, - }; - let query = Box::new(sql_ast::Query { - with: Some(sql_ast::With { - recursive: true, - cte_tables: vec![cte], - }), - ..default_query(sql_ast::SetExpr::Select(Box::new(sql_ast::Select { - projection: vec![SelectItem::Wildcard( - sql_ast::WildcardAdditionalOptions::default(), - )], - from: vec![TableWithJoins { - relation: TableFactor::Table { - name: sql_ast::ObjectName(vec![Ident::new("loop")]), - alias: None, - args: None, - with_hints: Vec::new(), - }, - joins: vec![], - }], - ..default_select() - }))) - }); - - // create a split between the loop SELECT statement and the following pipeline - let mut following = anchor_split(&mut ctx.anchor, vec![recursive_columns], following); - - let from = following.first_mut().unwrap(); - let from = from.as_super().unwrap().as_from().unwrap(); - - // this will be table decl that references the whole loop expression - let loop_decl = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); - - let loop_name = ctx.anchor.table_name.gen(); - loop_decl.name = Some(loop_name.clone()); - loop_decl.relation = None; - - // push the whole thing into WITH of the main query - ctx.ctes.push(sql_ast::Cte { - alias: simple_table_alias(Ident::new(loop_name)), - query, - from: None, - }); - - Ok(following) -} - fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result { // TODO: this could be made to use VALUES instead of SELECT UNION ALL SELECT // I'm not sure about compatibility though. @@ -521,65 +416,121 @@ fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result, ctx: &mut AnchorContext) -> Vec { - let (preceding, atomic) = anchor::split_off_back(pipeline, ctx); - - if let Some(preceding) = preceding { - log::debug!( - "pipeline split after {}", - preceding.last().unwrap().as_str() - ); - - anchor::anchor_split(ctx, preceding, atomic) - } else { - atomic +fn split_into_atomics( + name: String, + mut pipeline: Vec, + ctx: &mut AnchorContext, +) -> Vec { + let outputs_cid = AnchorContext::determine_select_columns(&pipeline); + + let mut required_cols = outputs_cid.clone(); + + // split pipeline, back to front + let mut parts_rev = Vec::new(); + loop { + let (preceding, split) = anchor::split_off_back(ctx, required_cols, pipeline); + + if let Some((preceding, cols_at_split)) = preceding { + log::debug!( + "pipeline split after {}", + preceding.last().unwrap().as_str() + ); + parts_rev.push((split, cols_at_split.clone())); + + pipeline = preceding; + required_cols = cols_at_split; + } else { + parts_rev.push((split, Vec::new())); + break; + } } + parts_rev.reverse(); + let mut parts = parts_rev; - // TODO // sometimes, additional columns will be added into select, which have to // be filtered out here, using additional CTE - // if let Some((pipeline, _)) = parts.last() { - // let select_cols = pipeline - // .first() - // .unwrap() - // .as_super() - // .unwrap() - // .as_select() - // .unwrap(); - - // if select_cols.iter().any(|c| !outputs_cid.contains(c)) { - // parts.push(( - // vec![SqlTransform::Super(Transform::Select(outputs_cid))], - // select_cols.clone(), - // )); - // } - // } + if let Some((pipeline, _)) = parts.last() { + let select_cols = pipeline + .first() + .unwrap() + .as_super() + .unwrap() + .as_select() + .unwrap(); + + if select_cols.iter().any(|c| !outputs_cid.contains(c)) { + parts.push(( + vec![SqlTransform::Super(Transform::Select(outputs_cid))], + select_cols.clone(), + )); + } + } + + // add names to pipelines, anchor, front to back + let mut atomics = Vec::with_capacity(parts.len()); + let last = parts.pop().unwrap(); + + let last_pipeline = if parts.is_empty() { + last.0 + } else { + // this code chunk is bloated but I cannot find a more concise alternative + let first = parts.remove(0); + + let first_name = ctx.table_name.gen(); + atomics.push(AtomicQuery { + name: first_name.clone(), + relation: SqlRelation::Pipeline(first.0), + }); + + let mut prev_name = first_name; + for (pipeline, cols_before) in parts.into_iter() { + let name = ctx.table_name.gen(); + let pipeline = anchor::anchor_split(ctx, &prev_name, &cols_before, pipeline); + + atomics.push(AtomicQuery { + name: name.clone(), + relation: SqlRelation::Pipeline(pipeline), + }); + + prev_name = name; + } + + anchor::anchor_split(ctx, &prev_name, &last.1, last.0) + }; + atomics.push(AtomicQuery { + name, + relation: SqlRelation::Pipeline(last_pipeline), + }); + + atomics } -fn ensure_names(transforms: &[SqlTransform], ctx: &mut AnchorContext) { - let empty = HashSet::new(); - for t in transforms { - match t { - SqlTransform::Super(Transform::Sort(_)) => { - for r in anchor::get_requirements(t, &empty) { - ctx.ensure_column_name(r.col); +fn ensure_names(atomics: &[AtomicQuery], ctx: &mut AnchorContext) { + // ensure column names for columns that need it + for a in atomics { + let empty = HashSet::new(); + for t in a.relation.as_pipeline().unwrap() { + match t { + SqlTransform::Super(Transform::Sort(_)) => { + for r in anchor::get_requirements(t, &empty) { + ctx.ensure_column_name(r.col); + } } - } - SqlTransform::Super(Transform::Select(cids)) => { - for cid in cids { - let _decl = &ctx.column_decls[cid]; - //let name = match decl { - // ColumnDecl::RelationColumn(_, _, _) => todo!(), - // ColumnDecl::Compute(_) => ctx.column_names[..], - //}; + SqlTransform::Super(Transform::Select(cids)) => { + for cid in cids { + let _decl = &ctx.column_decls[cid]; + //let name = match decl { + // ColumnDecl::RelationColumn(_, _, _) => todo!(), + // ColumnDecl::Compute(_) => ctx.column_names[..], + //}; + } } + _ => (), } - _ => (), } } } + fn filter_of_conditions(exprs: Vec, context: &mut Context) -> Result> { Ok(if let Some(cond) = all(exprs) { Some(translate_expr_kind(cond.kind, context)?) @@ -633,45 +584,6 @@ fn default_select() -> Select { } } -fn simple_table_alias(name: Ident) -> TableAlias { - TableAlias { - name, - columns: Vec::new(), - } -} - -fn query_to_set_expr(query: sql_ast::Query, context: &mut Context) -> Box { - let is_simple = query.with.is_none() - && query.order_by.is_empty() - && query.limit.is_none() - && query.offset.is_none() - && query.fetch.is_none() - && query.locks.is_empty(); - - if is_simple { - return query.body; - } - - // query is not simple, so we need to wrap it into - // `SELECT * FROM (query)` - Box::new(SetExpr::Select(Box::new(Select { - projection: vec![SelectItem::Wildcard( - sql_ast::WildcardAdditionalOptions::default(), - )], - from: vec![TableWithJoins { - relation: TableFactor::Derived { - lateral: false, - subquery: Box::new(query), - alias: Some(simple_table_alias(Ident::new( - context.anchor.table_name.gen(), - ))), - }, - joins: vec![], - }], - ..default_select() - }))) -} - fn count_tables(transforms: &[SqlTransform]) -> usize { let mut count = 0; for transform in transforms { @@ -691,36 +603,19 @@ mod test { fn parse_and_resolve(prql: &str) -> Result<(Vec, Context)> { let query = resolve(parse(prql)?)?; - let (anchor, main_relation) = AnchorContext::of(query); - let context = Context::new(Box::new(GenericDialect {}), anchor); + let (anchor, query) = AnchorContext::of(query); + let context = Context { + dialect: Box::new(GenericDialect {}), + anchor, + omit_ident_prefix: false, + pre_projection: false, + }; - let pipeline = main_relation.kind.into_pipeline().unwrap(); + let pipeline = query.relation.kind.into_pipeline().unwrap(); Ok((preprocess::reorder(preprocess::wrap(pipeline)), context)) } - fn count_atomics(prql: &str) -> usize { - let (mut pipeline, mut context) = parse_and_resolve(prql).unwrap(); - context.anchor.table_decls.clear(); - - let mut atomics = 0; - loop { - let _ = extract_atomic(pipeline, &mut context.anchor); - atomics += 1; - - if let Some((_, decl)) = context.anchor.table_decls.drain().next() { - if let Some(relation) = decl.relation { - if let SqlRelationKind::PreprocessedPipeline(p) = relation.kind { - pipeline = p; - continue; - } - } - } - break; - } - atomics - } - #[test] fn test_ctes_of_pipeline() { // One aggregate, take at the end @@ -732,7 +627,9 @@ mod test { take 20 "###; - assert_eq!(count_atomics(prql), 1); + let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); + let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); + assert_eq!(queries.len(), 1); // One aggregate, but take at the top let prql: &str = r###" @@ -743,7 +640,9 @@ mod test { sort sal "###; - assert_eq!(count_atomics(prql), 2); + let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); + let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); + assert_eq!(queries.len(), 2); // A take, then two aggregates let prql: &str = r###" @@ -755,7 +654,9 @@ mod test { sort sal2 "###; - assert_eq!(count_atomics(prql), 3); + let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); + let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); + assert_eq!(queries.len(), 3); // A take, then a select let prql: &str = r###" @@ -764,7 +665,9 @@ mod test { select first_name "###; - assert_eq!(count_atomics(prql), 1); + let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); + let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); + assert_eq!(queries.len(), 1); } #[test] @@ -816,7 +719,7 @@ mod test { *, RANK() OVER () AS rank FROM - table_1 AS table_0 + table_1 WHERE country = 'USA' "###); @@ -841,7 +744,7 @@ mod test { SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 > 3 "###); diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index c49140711390..c109bc0deab0 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -60,18 +60,6 @@ struct Context { pub dialect: Box, pub anchor: AnchorContext, - // stuff regarding current query - query: QueryOpts, - - // stuff regarding parent queries - query_stack: Vec, - - pub ctes: Vec, -} - -#[derive(Default, Clone)] -struct QueryOpts { - /// When true, column references will not include table names prefixes. pub omit_ident_prefix: bool, /// True iff codegen should generate expressions before SELECT's projection is applied. @@ -79,29 +67,6 @@ struct QueryOpts { /// - WHERE needs `pre_projection=true`, but /// - ORDER BY needs `pre_projection=false`. pub pre_projection: bool, - - /// When true, queries will contain nested sub-queries instead of WITH CTEs. - pub forbid_ctes: bool, -} - -impl Context { - fn new(dialect: Box, anchor: AnchorContext) -> Self { - Context { - dialect, - anchor, - query: QueryOpts::default(), - query_stack: Vec::new(), - ctes: Vec::new(), - } - } - - fn push_query(&mut self) { - self.query_stack.push(self.query.clone()); - } - - fn pop_query(&mut self) { - self.query = self.query_stack.pop().unwrap(); - } } #[cfg(test)] diff --git a/prql-compiler/src/sql/preprocess.rs b/prql-compiler/src/sql/preprocess.rs index 035f6858dd30..7c04c4cbf7cb 100644 --- a/prql-compiler/src/sql/preprocess.rs +++ b/prql-compiler/src/sql/preprocess.rs @@ -10,8 +10,7 @@ use crate::ast::pl::{ BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, WindowFrame, WindowKind, }; use crate::ast::rq::{ - self, new_binop, CId, Compute, Expr, ExprKind, Relation, RelationColumn, RelationKind, RqFold, - TableRef, Transform, Window, + self, new_binop, CId, Compute, Expr, ExprKind, RqFold, TableRef, Transform, Window, }; use crate::error::Error; use crate::sql::context::AnchorContext; @@ -19,45 +18,31 @@ use crate::sql::context::AnchorContext; use super::anchor::{infer_complexity, CidCollector, Complexity}; use super::Context; -#[derive(Debug, Clone, EnumAsInner)] -pub(super) enum SqlRelationKind { - Super(RelationKind), - PreprocessedPipeline(Vec), -} - -#[derive(Debug, Clone)] -pub(super) struct SqlRelation { - pub kind: SqlRelationKind, - pub columns: Vec, -} - -#[derive(Debug, Clone, EnumAsInner, strum::AsRefStr)] +#[derive(Debug, EnumAsInner, strum::AsRefStr)] pub(super) enum SqlTransform { Super(Transform), Distinct, Except { bottom: TableRef, distinct: bool }, Intersect { bottom: TableRef, distinct: bool }, Union { bottom: TableRef, distinct: bool }, - Loop(Vec), } -// This function was disabled because it changes semantics of the pipeline in some cases. -// /// Pushes all [Transform::Select]s to the back of the pipeline. -// pub(super) fn push_down_selects(pipeline: Vec) -> Vec { -// let mut select = None; -// let mut res = Vec::with_capacity(pipeline.len()); -// for t in pipeline { -// if let Transform::Select(_) = t { -// select = Some(t); -// } else { -// res.push(t); -// } -// } -// if let Some(select) = select { -// res.push(select); -// } -// res -// } +/// Pushes all [Transform::Select]s to the back of the pipeline. +pub(super) fn push_down_selects(pipeline: Vec) -> Vec { + let mut select = None; + let mut res = Vec::with_capacity(pipeline.len()); + for t in pipeline { + if let Transform::Select(_) = t { + select = Some(t); + } else { + res.push(t); + } + } + if let Some(select) = select { + res.push(select); + } + res +} /// Removes unused relation inputs pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { @@ -91,12 +76,7 @@ pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { } pub(super) fn wrap(pipe: Vec) -> Vec { - pipe.into_iter() - .map(|t| match t { - Transform::Loop(pipeline) => SqlTransform::Loop(wrap(pipeline)), - _ => SqlTransform::Super(t), - }) - .collect() + pipe.into_iter().map(SqlTransform::Super).collect() } /// Creates [SqlTransform::Distinct] from [Transform::Take] @@ -577,15 +557,6 @@ impl SqlTransform { } } -impl From for SqlRelation { - fn from(rel: Relation) -> Self { - SqlRelation { - kind: SqlRelationKind::Super(rel.kind), - columns: rel.columns, - } - } -} - pub(super) trait SqlFold: RqFold { fn fold_sql_transforms(&mut self, transforms: Vec) -> Result> { transforms @@ -610,7 +581,6 @@ pub(super) trait SqlFold: RqFold { bottom: self.fold_table_ref(bottom)?, distinct, }, - SqlTransform::Loop(pipeline) => SqlTransform::Loop(self.fold_sql_transforms(pipeline)?), }) } } diff --git a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap index 1164db5605aa..5b7e140a157a 100644 --- a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap +++ b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap @@ -16,7 +16,6 @@ SELECT title, AVG(_expr_0) AS avg_salary FROM - table_1 AS table_0 + table_1 GROUP BY title - diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 16c1d560cf5a..e695ed15b6fd 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -205,7 +205,7 @@ fn test_append() { take 10 ) "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT *, name, @@ -227,13 +227,13 @@ fn test_append() { employees LIMIT 3 - ) AS table_2 + ) AS table_3 UNION ALL SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 "###); assert_display_snapshot!(compile(r###" @@ -310,7 +310,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM @@ -325,7 +325,7 @@ fn test_remove() { SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -337,7 +337,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM @@ -348,9 +348,9 @@ fn test_remove() { album.title FROM album - LEFT JOIN table_0 AS table_1 ON album.artist_id = table_1.artist_id + LEFT JOIN table_1 AS table_0 ON album.artist_id = table_0.artist_id WHERE - table_1.artist_id IS NULL + table_0.artist_id IS NULL "### ); @@ -382,11 +382,11 @@ fn test_remove() { album ) SELECT - table_0.artist_id, - table_0.title + table_1.artist_id, + table_1.title FROM - table_1 AS table_0 - LEFT JOIN bottom AS b ON table_0.artist_id = b.* + table_1 + LEFT JOIN bottom AS b ON table_1.artist_id = b.* WHERE b.* IS NULL "### @@ -443,7 +443,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM @@ -458,7 +458,7 @@ fn test_intersect() { SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -474,28 +474,22 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM artist - ), - table_3 AS ( - SELECT - artist_id - FROM - album - INTERSECT - DISTINCT - SELECT - * - FROM - table_0 AS table_1 ) SELECT - DISTINCT artist_id + artist_id FROM - table_3 AS table_2 + album + INTERSECT + DISTINCT + SELECT + * + FROM + table_1 AS table_0 "### ); @@ -510,28 +504,22 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM artist - ), - table_3 AS ( - SELECT - artist_id - FROM - album - INTERSECT - ALL - SELECT - * - FROM - table_0 AS table_1 ) SELECT - DISTINCT artist_id + artist_id + FROM + album + INTERSECT + DISTINCT + SELECT + * FROM - table_3 AS table_2 + table_1 AS table_0 "### ); @@ -546,7 +534,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT artist_id FROM @@ -561,7 +549,7 @@ fn test_intersect() { SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -586,28 +574,28 @@ fn test_rn_ids_are_unique() { take 3 ) "###).unwrap()), @r###" - WITH table_3 AS ( + WITH table_1 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_1 + ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_0 FROM y_orig ), - table_1 AS ( + table_2 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_0 + ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_1 FROM - table_3 AS table_2 + table_1 WHERE - _expr_1 <= 2 + _expr_0 <= 2 ) SELECT * FROM - table_1 AS table_0 + table_2 WHERE - _expr_0 <= 3 + _expr_1 <= 3 "###); } @@ -702,13 +690,19 @@ fn test_sorts() { select [renamed = somefield] "### ).unwrap()), @r###" + WITH table_1 AS ( + SELECT + 'something' AS renamed, + 'something' AS _expr_0 + FROM + x + ORDER BY + _expr_0 + ) SELECT - 'something' AS renamed, - 'something' AS _expr_0 + renamed FROM - x - ORDER BY - _expr_0 + table_1 "###); } @@ -883,7 +877,7 @@ fn test_window_functions_02() { order_day ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS num_books_last_week FROM - table_1 AS table_0 + table_1 ORDER BY order_day "###); @@ -1267,7 +1261,7 @@ fn test_take() { SELECT * FROM - table_1 AS table_0 + table_1 ORDER BY name LIMIT @@ -1346,7 +1340,7 @@ fn test_distinct() { SELECT * FROM - table_1 AS table_0 + table_1 WHERE rn > 2 "###); @@ -1403,7 +1397,7 @@ fn test_distinct() { SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 <= 3 "###); @@ -1426,7 +1420,7 @@ fn test_distinct() { SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 BETWEEN 2 AND 3 "###); @@ -1449,7 +1443,7 @@ fn test_distinct() { SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 = 4 "###); @@ -1825,7 +1819,16 @@ fn test_prql_to_sql_table() { let sql = compile(query).unwrap(); assert_display_snapshot!(sql, @r###" - WITH newest_employees AS ( + WITH average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country + ), + newest_employees AS ( SELECT * FROM @@ -1834,14 +1837,6 @@ fn test_prql_to_sql_table() { tenure LIMIT 50 - ), average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country ) SELECT newest_employees.name, @@ -1875,7 +1870,7 @@ fn test_nonatomic() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_3 AS ( + WITH table_1 AS ( SELECT title, country, @@ -1884,13 +1879,13 @@ fn test_nonatomic() { employees LIMIT 20 - ), table_1 AS ( + ), table_2 AS ( SELECT title, country, AVG(salary) AS _expr_0 FROM - table_3 AS table_2 + table_1 WHERE country = 'USA' GROUP BY @@ -1902,7 +1897,7 @@ fn test_nonatomic() { country, AVG(_expr_0) AS sum_gross_cost FROM - table_1 AS table_0 + table_2 GROUP BY title, country @@ -1955,7 +1950,7 @@ fn test_nonatomic_table() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT country FROM @@ -1967,7 +1962,7 @@ fn test_nonatomic_table() { country, count(*) FROM - table_1 AS table_0 + table_0 GROUP BY country ) @@ -2004,12 +1999,12 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_0.emp_no, - table_0.name, + table_1.emp_no, + table_1.name, s.salary FROM - table_1 AS table_0 - JOIN salaries AS s ON table_0.emp_no = s.emp_no + table_1 + JOIN salaries AS s ON table_1.emp_no = s.emp_no "###); let prql = r###" @@ -2029,11 +2024,11 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_0.*, + table_1.*, salaries.salary FROM - table_1 AS table_0 - JOIN salaries ON table_0.emp_no = salaries.emp_no + table_1 + JOIN salaries ON table_1.emp_no = salaries.emp_no "###); } @@ -2313,6 +2308,12 @@ fn test_toposort() { * FROM somesource + ), + a AS ( + SELECT + * + FROM + b ) SELECT * @@ -2332,7 +2333,7 @@ fn test_inline_tables() { join s = (from salaries | select [emp_id, salary]) [==emp_id] "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT emp_id, salary @@ -2345,11 +2346,11 @@ fn test_inline_tables() { employees.surname, employees.type, employees.amount, - table_1.emp_id, - table_1.salary + table_0.emp_id, + table_0.salary FROM employees - JOIN table_0 AS table_1 ON employees.emp_id = table_1.emp_id + JOIN table_1 AS table_0 ON employees.emp_id = table_0.emp_id "### ); } @@ -2434,7 +2435,7 @@ fn test_table_s_string() { s"SELECT DISTINCT ON first_name, age FROM employees ORDER BY age ASC" "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT DISTINCT ON first_name, age @@ -2445,7 +2446,7 @@ fn test_table_s_string() { ) SELECT FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -2456,7 +2457,7 @@ fn test_table_s_string() { join s = s"SELECT * FROM salaries" [==id] "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_2 AS ( SELECT DISTINCT ON first_name, id, @@ -2466,18 +2467,18 @@ fn test_table_s_string() { ORDER BY age ASC ), - table_1 AS ( + table_3 AS ( SELECT * FROM salaries ) SELECT - table_2.*, - table_3.* + table_0.*, + table_1.* FROM - table_0 AS table_2 - JOIN table_1 AS table_3 ON table_2.id = table_3.id + table_2 AS table_0 + JOIN table_3 AS table_1 ON table_0.id = table_1.id "### ); @@ -2486,7 +2487,7 @@ fn test_table_s_string() { filter country == "USA" "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT * FROM @@ -2495,7 +2496,7 @@ fn test_table_s_string() { SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 WHERE country = 'USA' "### @@ -2506,7 +2507,7 @@ fn test_table_s_string() { filter e.country == "USA" "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT * FROM @@ -2515,7 +2516,7 @@ fn test_table_s_string() { SELECT * FROM - table_0 AS table_1 + table_1 AS table_0 WHERE country = 'USA' "### @@ -2528,7 +2529,7 @@ fn test_table_s_string() { weeks_between @2022-06-03 (current_week + 4) "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT generate_series( DATE '2022-06-03', @@ -2538,7 +2539,7 @@ fn test_table_s_string() { ) SELECT FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -2546,7 +2547,7 @@ fn test_table_s_string() { s"SELECT * FROM {default_db.x}" "###).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT * FROM @@ -2554,7 +2555,7 @@ fn test_table_s_string() { ) SELECT FROM - table_0 AS table_1 + table_1 AS table_0 "### ); } @@ -2654,13 +2655,13 @@ fn test_group_all() { 10 ) SELECT - table_0.*, + table_1.*, SUM(salaries.salary) AS sal FROM - table_1 AS table_0 - JOIN salaries ON table_0.emp_no = salaries.emp_no + table_1 + JOIN salaries ON table_1.emp_no = salaries.emp_no GROUP BY - table_0.* + table_1.* "### ); @@ -2691,7 +2692,7 @@ fn test_output_column_deduplication() { SELECT * FROM - table_1 AS table_0 + table_1 WHERE r = 1 "### @@ -2765,7 +2766,7 @@ fn test_switch() { category, COUNT(*) FROM - table_1 AS table_0 + table_1 GROUP BY category "### @@ -3121,7 +3122,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT '1' AS a, '2' AS b, @@ -3137,7 +3138,7 @@ a,b,c b, c FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -3148,7 +3149,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT 1 AS a, 'x' AS b, @@ -3164,7 +3165,7 @@ a,b,c b, c FROM - table_0 AS table_1 + table_1 AS table_0 "### ); @@ -3179,7 +3180,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT 1 AS a, 'x' AS b, @@ -3195,7 +3196,7 @@ a,b,c b, c FROM - table_0 AS table_1 + table_1 AS table_0 "### ); } @@ -3212,55 +3213,3 @@ fn test_header_target_error() { from a "#).unwrap_err(),@r###"target `"sql.foo"` not found"###) } - -#[test] -fn test_loop() { - assert_display_snapshot!(compile(r#" - from_text format:json '[{"n": 1 }]' - select n = n - 2 - loop ( - select n = n+1 - filter n<5 - ) - select n = n * 2 - take 4 - "#).unwrap(), - @r###" - WITH table_0 AS ( - SELECT - 1 AS n - ), - table_6 AS ( - WITH RECURSIVE loop AS ( - SELECT - n - 2 AS _expr_0 - FROM - table_0 AS table_1 - UNION - ALL - SELECT - _expr_1 - FROM - ( - SELECT - _expr_0 + 1 AS _expr_1 - FROM - loop AS table_2 - ) AS table_3 - WHERE - _expr_1 < 5 - ) - SELECT - * - FROM - loop - ) - SELECT - _expr_0 * 2 AS n - FROM - table_6 AS table_5 - LIMIT - 4 - "### - ); -} diff --git a/prql-compiler/tests/integration/queries/loop.prql b/prql-compiler/tests/integration/queries/loop.prql deleted file mode 100644 index e83d02e37057..000000000000 --- a/prql-compiler/tests/integration/queries/loop.prql +++ /dev/null @@ -1,7 +0,0 @@ -from_text format:json '[{"n": 1 }]' -select n = n - 2 -loop ( - filter n<4 - select n = n+1 -) -select n = n * 2 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap deleted file mode 100644 index 482dc9933c4d..000000000000 --- a/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: prql-compiler/tests/integration/main.rs -expression: sqlite_out -input_file: prql-compiler/tests/integration/queries/loop.prql ---- -n --2 -0 -2 -4 -6 -8 From af416df18799269039f0b4774c941dd82924740b Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 16:53:20 -0800 Subject: [PATCH 022/184] revert: #1894 (#1901) (Possibly fixing would have been easier, sorry if this is creating more work. I do think running all tests is worthwhile with this sort of wide-ranging change...) --- website/content/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/content/_index.md b/website/content/_index.md index 349317aaf594..035f4eaedfe2 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -246,7 +246,7 @@ showcase_section: SELECT * FROM - table_1 AS table_0 + table_1 WHERE _expr_0 <= 1 From abc61ff3fd18e6deff9159b9726071705d3a4f29 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 16:57:54 -0800 Subject: [PATCH 023/184] test: Refactor book snapshot tests (#1900) * tests: Refactor book snapshot tests Modularizes these tests, potentially in preparation for https://github.com/PRQL/prql/issues/1895 --- book/tests/snapshot.rs | 172 ++++++++++-------- ...rql@examples__list-equivalence-0.prql.snap | 10 - ...rql@examples__list-equivalence-1.prql.snap | 10 - ..._reference_prql@examples__misc-0.prql.snap | 26 --- ..._reference_prql@examples__misc-1.prql.snap | 13 -- ...rence_prql@examples__variables-0.prql.snap | 32 ---- ...rence_prql@examples__variables-1.prql.snap | 19 -- ...rql@internals__functional-lang-0.prql.snap | 11 -- ...rql@internals__functional-lang-1.prql.snap | 11 -- ...rql@internals__functional-lang-2.prql.snap | 12 -- ...rql@internals__functional-lang-3.prql.snap | 13 -- ...prql@internals__name-resolving-0.prql.snap | 10 - ...ay_reference_prql@introduction-0.prql.snap | 32 ---- ...ql@language-features__coalesce-0.prql.snap | 10 - ...uage-features__dates-and-times-0.prql.snap | 10 - ...uage-features__dates-and-times-1.prql.snap | 10 - ...uage-features__dates-and-times-2.prql.snap | 10 - ...uage-features__dates-and-times-3.prql.snap | 10 - ...ql@language-features__distinct-0.prql.snap | 13 -- ...ql@language-features__distinct-1.prql.snap | 13 -- ...ql@language-features__distinct-2.prql.snap | 13 -- ...l@language-features__f-strings-0.prql.snap | 10 - ...l@language-features__f-strings-1.prql.snap | 10 - ...e_prql@language-features__null-0.prql.snap | 11 -- ...prql@language-features__ranges-1.prql.snap | 14 -- ...l@language-features__s-strings-0.prql.snap | 10 - ...l@language-features__s-strings-1.prql.snap | 10 - ...age-features__standard-library-0.prql.snap | 20 -- ...rql@language-features__strings-0.prql.snap | 10 - ...rql@language-features__strings-1.prql.snap | 10 - ...rql@language-features__strings-2.prql.snap | 10 - ...rql@language-features__strings-3.prql.snap | 10 - ...rql@language-features__strings-4.prql.snap | 10 - ...prql@language-features__target-0.prql.snap | 15 -- ...prql@language-features__target-1.prql.snap | 15 -- ...prql@language-features__target-2.prql.snap | 13 -- ...erence_prql@queries__pipelines-0.prql.snap | 9 - ...erence_prql@queries__pipelines-1.prql.snap | 10 - ...erence_prql@queries__variables-0.prql.snap | 18 -- ...display_reference_prql@syntax-11.prql.snap | 9 - ...display_reference_prql@syntax-13.prql.snap | 9 - ...display_reference_prql@syntax-14.prql.snap | 10 - ..._display_reference_prql@syntax-3.prql.snap | 10 - ..._display_reference_prql@syntax-4.prql.snap | 10 - ..._display_reference_prql@syntax-6.prql.snap | 40 ---- ..._display_reference_prql@syntax-8.prql.snap | 10 - ...nce_prql@transforms__aggregate-0.prql.snap | 13 -- ...nce_prql@transforms__aggregate-2.prql.snap | 10 - ...erence_prql@transforms__append-0.prql.snap | 10 - ...erence_prql@transforms__append-1.prql.snap | 10 - ...erence_prql@transforms__append-2.prql.snap | 10 - ...erence_prql@transforms__derive-0.prql.snap | 10 - ...erence_prql@transforms__filter-0.prql.snap | 10 - ...erence_prql@transforms__filter-1.prql.snap | 10 - ...erence_prql@transforms__filter-2.prql.snap | 13 -- ...eference_prql@transforms__from-0.prql.snap | 9 - ...eference_prql@transforms__from-1.prql.snap | 10 - ...nce_prql@transforms__from_text-2.prql.snap | 33 ---- ...ference_prql@transforms__group-1.prql.snap | 11 -- ...ference_prql@transforms__group-2.prql.snap | 13 -- ...eference_prql@transforms__join-2.prql.snap | 10 - ...erence_prql@transforms__select-0.prql.snap | 10 - ...erence_prql@transforms__select-2.prql.snap | 10 - ...erence_prql@transforms__select-3.prql.snap | 13 -- ...erence_prql@transforms__select-6.prql.snap | 11 -- ...eference_prql@transforms__sort-0.prql.snap | 10 - ...eference_prql@transforms__sort-1.prql.snap | 10 - ...eference_prql@transforms__sort-2.prql.snap | 14 -- ...eference_prql@transforms__sort-3.prql.snap | 10 - ...eference_prql@transforms__sort-5.prql.snap | 11 -- ...eference_prql@transforms__take-0.prql.snap | 10 - ...eference_prql@transforms__take-1.prql.snap | 14 -- ...erence_prql@transforms__window-2.prql.snap | 11 -- ...erence_prql@transforms__window-3.prql.snap | 13 -- ...erence_prql@transforms__window-4.prql.snap | 10 - ...t__tests__prql__examples__cte-0.prql.snap} | 3 +- ...ts__prql__examples__employees-0.prql.snap} | 3 +- ...ts__prql__examples__employees-1.prql.snap} | 3 +- ...ts__prql__examples__employees-2.prql.snap} | 3 +- ...ts__prql__examples__employees-3.prql.snap} | 3 +- ...ql__examples__list-equivalence-0.prql.snap | 9 + ...ql__examples__list-equivalence-1.prql.snap | 9 + ...l__examples__list-equivalence-2.prql.snap} | 3 +- ...l__examples__list-equivalence-3.prql.snap} | 3 +- ...t__tests__prql__examples__misc-0.prql.snap | 25 +++ ...t__tests__prql__examples__misc-1.prql.snap | 12 ++ ...sts__prql__examples__variables-0.prql.snap | 31 ++++ ...sts__prql__examples__variables-1.prql.snap | 18 ++ ...ql__internals__functional-lang-0.prql.snap | 10 + ...ql__internals__functional-lang-1.prql.snap | 10 + ...ql__internals__functional-lang-2.prql.snap | 11 ++ ...ql__internals__functional-lang-3.prql.snap | 12 ++ ...rql__internals__name-resolving-0.prql.snap | 9 + ...ql__internals__name-resolving-1.prql.snap} | 3 +- ...hot__tests__prql__introduction-0.prql.snap | 31 ++++ ...l__language-features__coalesce-0.prql.snap | 9 + ...uage-features__dates-and-times-0.prql.snap | 9 + ...uage-features__dates-and-times-1.prql.snap | 9 + ...uage-features__dates-and-times-2.prql.snap | 9 + ...uage-features__dates-and-times-3.prql.snap | 9 + ...l__language-features__distinct-0.prql.snap | 12 ++ ...l__language-features__distinct-1.prql.snap | 12 ++ ...l__language-features__distinct-2.prql.snap | 12 ++ ...__language-features__f-strings-0.prql.snap | 9 + ...__language-features__f-strings-1.prql.snap | 9 + ..._prql__language-features__null-0.prql.snap | 10 + ...ql__language-features__ranges-0.prql.snap} | 3 +- ...rql__language-features__ranges-1.prql.snap | 13 ++ ...__language-features__s-strings-0.prql.snap | 9 + ...__language-features__s-strings-1.prql.snap | 9 + ..._language-features__s-strings-2.prql.snap} | 3 +- ..._language-features__s-strings-3.prql.snap} | 3 +- ..._language-features__s-strings-4.prql.snap} | 3 +- ..._language-features__s-strings-5.prql.snap} | 3 +- ..._language-features__s-strings-6.prql.snap} | 3 +- ...age-features__standard-library-0.prql.snap | 19 ++ ...ql__language-features__strings-0.prql.snap | 9 + ...ql__language-features__strings-1.prql.snap | 9 + ...ql__language-features__strings-2.prql.snap | 9 + ...ql__language-features__strings-3.prql.snap | 9 + ...ql__language-features__strings-4.prql.snap | 9 + ...ql__language-features__switch-0.prql.snap} | 3 +- ...ql__language-features__switch-1.prql.snap} | 3 +- ...rql__language-features__target-0.prql.snap | 14 ++ ...rql__language-features__target-1.prql.snap | 14 ++ ...rql__language-features__target-2.prql.snap | 12 ++ ...sts__prql__queries__functions-0.prql.snap} | 3 +- ...sts__prql__queries__functions-1.prql.snap} | 3 +- ...sts__prql__queries__functions-2.prql.snap} | 3 +- ...sts__prql__queries__functions-3.prql.snap} | 3 +- ...sts__prql__queries__functions-4.prql.snap} | 3 +- ...ests__prql__queries__pipelines-0.prql.snap | 8 + ...ests__prql__queries__pipelines-1.prql.snap | 9 + ...sts__prql__queries__pipelines-2.prql.snap} | 3 +- ...ests__prql__queries__variables-0.prql.snap | 17 ++ ...sts__prql__queries__variables-1.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-0.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-1.prql.snap} | 3 +- ...napshot__tests__prql__syntax-10.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-11.prql.snap | 8 + ...napshot__tests__prql__syntax-12.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-13.prql.snap | 8 + ...snapshot__tests__prql__syntax-14.prql.snap | 9 + ...napshot__tests__prql__syntax-15.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-2.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-3.prql.snap | 9 + .../snapshot__tests__prql__syntax-4.prql.snap | 9 + ...snapshot__tests__prql__syntax-5.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-6.prql.snap | 39 ++++ ...snapshot__tests__prql__syntax-7.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-8.prql.snap | 9 + ...snapshot__tests__prql__syntax-9.prql.snap} | 3 +- ...s__prql__transforms__aggregate-0.prql.snap | 12 ++ ...__prql__transforms__aggregate-1.prql.snap} | 3 +- ...s__prql__transforms__aggregate-2.prql.snap | 9 + ...ests__prql__transforms__append-0.prql.snap | 9 + ...ests__prql__transforms__append-1.prql.snap | 9 + ...ests__prql__transforms__append-2.prql.snap | 9 + ...ests__prql__transforms__derive-0.prql.snap | 9 + ...sts__prql__transforms__derive-1.prql.snap} | 3 +- ...ests__prql__transforms__filter-0.prql.snap | 9 + ...ests__prql__transforms__filter-1.prql.snap | 9 + ...ests__prql__transforms__filter-2.prql.snap | 12 ++ ..._tests__prql__transforms__from-0.prql.snap | 8 + ..._tests__prql__transforms__from-1.prql.snap | 9 + ...__prql__transforms__from_text-0.prql.snap} | 3 +- ...__prql__transforms__from_text-1.prql.snap} | 3 +- ...s__prql__transforms__from_text-2.prql.snap | 32 ++++ ...ests__prql__transforms__group-0.prql.snap} | 3 +- ...tests__prql__transforms__group-1.prql.snap | 10 + ...tests__prql__transforms__group-2.prql.snap | 12 ++ ...tests__prql__transforms__join-0.prql.snap} | 3 +- ...tests__prql__transforms__join-1.prql.snap} | 3 +- ..._tests__prql__transforms__join-2.prql.snap | 9 + ...ests__prql__transforms__select-0.prql.snap | 9 + ...sts__prql__transforms__select-1.prql.snap} | 3 +- ...ests__prql__transforms__select-2.prql.snap | 9 + ...ests__prql__transforms__select-3.prql.snap | 12 ++ ...sts__prql__transforms__select-4.prql.snap} | 3 +- ...sts__prql__transforms__select-5.prql.snap} | 3 +- ...ests__prql__transforms__select-6.prql.snap | 10 + ..._tests__prql__transforms__sort-0.prql.snap | 9 + ..._tests__prql__transforms__sort-1.prql.snap | 9 + ..._tests__prql__transforms__sort-2.prql.snap | 13 ++ ..._tests__prql__transforms__sort-3.prql.snap | 9 + ...tests__prql__transforms__sort-4.prql.snap} | 3 +- ..._tests__prql__transforms__sort-5.prql.snap | 10 + ..._tests__prql__transforms__take-0.prql.snap | 9 + ..._tests__prql__transforms__take-1.prql.snap | 13 ++ ...sts__prql__transforms__window-0.prql.snap} | 3 +- ...sts__prql__transforms__window-1.prql.snap} | 3 +- ...ests__prql__transforms__window-2.prql.snap | 10 + ...ests__prql__transforms__window-3.prql.snap | 12 ++ ...ests__prql__transforms__window-4.prql.snap | 9 + 194 files changed, 1010 insertions(+), 1103 deletions(-) delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__cte-0.prql.snap => snapshot__tests__prql__examples__cte-0.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-0.prql.snap => snapshot__tests__prql__examples__employees-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-1.prql.snap => snapshot__tests__prql__examples__employees-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-2.prql.snap => snapshot__tests__prql__examples__employees-2.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-3.prql.snap => snapshot__tests__prql__examples__employees-3.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap => snapshot__tests__prql__examples__list-equivalence-2.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap => snapshot__tests__prql__examples__list-equivalence-3.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap => snapshot__tests__prql__internals__name-resolving-1.prql.snap} (56%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap => snapshot__tests__prql__language-features__ranges-0.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap => snapshot__tests__prql__language-features__s-strings-2.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap => snapshot__tests__prql__language-features__s-strings-3.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap => snapshot__tests__prql__language-features__s-strings-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap => snapshot__tests__prql__language-features__s-strings-5.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap => snapshot__tests__prql__language-features__s-strings-6.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__switch-0.prql.snap => snapshot__tests__prql__language-features__switch-0.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__switch-1.prql.snap => snapshot__tests__prql__language-features__switch-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-0.prql.snap => snapshot__tests__prql__queries__functions-0.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-1.prql.snap => snapshot__tests__prql__queries__functions-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-2.prql.snap => snapshot__tests__prql__queries__functions-2.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-3.prql.snap => snapshot__tests__prql__queries__functions-3.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-4.prql.snap => snapshot__tests__prql__queries__functions-4.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap => snapshot__tests__prql__queries__pipelines-2.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__variables-1.prql.snap => snapshot__tests__prql__queries__variables-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-0.prql.snap => snapshot__tests__prql__syntax-0.prql.snap} (55%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-1.prql.snap => snapshot__tests__prql__syntax-1.prql.snap} (55%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-10.prql.snap => snapshot__tests__prql__syntax-10.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-12.prql.snap => snapshot__tests__prql__syntax-12.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-15.prql.snap => snapshot__tests__prql__syntax-15.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-2.prql.snap => snapshot__tests__prql__syntax-2.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-5.prql.snap => snapshot__tests__prql__syntax-5.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-7.prql.snap => snapshot__tests__prql__syntax-7.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-9.prql.snap => snapshot__tests__prql__syntax-9.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap => snapshot__tests__prql__transforms__aggregate-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__derive-1.prql.snap => snapshot__tests__prql__transforms__derive-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap => snapshot__tests__prql__transforms__from_text-0.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap => snapshot__tests__prql__transforms__from_text-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__group-0.prql.snap => snapshot__tests__prql__transforms__group-0.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__join-0.prql.snap => snapshot__tests__prql__transforms__join-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__join-1.prql.snap => snapshot__tests__prql__transforms__join-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-1.prql.snap => snapshot__tests__prql__transforms__select-1.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-4.prql.snap => snapshot__tests__prql__transforms__select-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-5.prql.snap => snapshot__tests__prql__transforms__select-5.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__sort-4.prql.snap => snapshot__tests__prql__transforms__sort-4.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__window-0.prql.snap => snapshot__tests__prql__transforms__window-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__window-1.prql.snap => snapshot__tests__prql__transforms__window-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index e86b59ae20fc..d26bfe754dec 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -1,6 +1,6 @@ #![cfg(not(target_family = "wasm"))] /// This test: -/// - Extracts PRQL code blocks into the `examples` path. +/// - Extracts PRQL code blocks into files in the `examples` path /// - Converts them to SQL using insta, raising an error if there's a diff. /// - Replaces the PRQL code block with a comparison table. /// @@ -18,69 +18,38 @@ // us. They introduce a bunch of non-rust dependencies, which is not ideal, but // passable. They don't let us customize our formatting (e.g. in a table). // -use anyhow::{bail, Result}; +use anyhow::{bail, Error, Result}; use globset::Glob; -use insta::{assert_display_snapshot, assert_snapshot, glob}; +use insta::{assert_snapshot, glob}; +use itertools::Itertools; use log::warn; use prql_compiler::*; use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; -use std::fs; use std::path::Path; +use std::{collections::HashMap, fs}; use walkdir::WalkDir; #[test] -fn run_examples() -> Result<()> { - // TODO: In CI this could pass by replacing incorrect files. To catch that, - // we could check if there are any diffs after this has run? - +fn test_examples() -> Result<()> { // Note that on windows, markdown is read differently, and so // writing on Windows. ref https://github.com/PRQL/prql/issues/356 #[cfg(not(target_family = "windows"))] - write_reference_prql()?; - run_reference_prql(); - - // TODO: Currently we run this in the same test, since we need the - // `write_reference_prql` function to have been run. If we could iterate - // over the PRQL examples without writing them to disk, we could run this as - // a separate test. (Though then we'd lose the deferred failures feature - // that insta's `glob!` macro provides.) - run_display_reference_prql(); + write_prql_examples()?; + test_prql_examples(); Ok(()) } -/// Extract reference examples from the PRQL docs and write them to the -/// `tests/prql` path, one in each file. -// We could alternatively have used something like -// https://github.com/earldouglas/codedown, but it's not much code, and it -// requires no dependencies. -// -// We allow dead_code because of the window issue described above. (Can we allow -// it only for windows?) -#[allow(dead_code)] -fn write_reference_prql() -> Result<()> { - // Remove old .prql files, since we're going to rewrite them, and we don't want - // old files which wouldn't be rewritten from hanging around. - // We use `trash`, since we don't want to be removing files with test code - // in case there's a bug. - // - // A more elegant approach would be to keep a list of the files and remove - // the ones we don't write. - - let examples_path = Path::new("tests/prql"); - if examples_path.exists() { - trash::delete(Path::new("tests/prql")).unwrap_or_else(|e| { - warn!("Failed to delete old examples: {}", e); - }); - } +const ROOT_EXAMPLES_PATH: &str = "tests/prql"; +/// Collect all the PRQL examples in the book, as a map of . +fn collect_book_examples() -> Result> { let glob = Glob::new("**/*.md")?.compile_matcher(); - - WalkDir::new(Path::new("./src/")) + let examples_in_book: HashMap = WalkDir::new(Path::new("./src/")) .into_iter() .flatten() .filter(|x| glob.is_match(x.path())) - .try_for_each(|dir_entry| { + .flat_map(|dir_entry| { let text = fs::read_to_string(dir_entry.path())?; let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; @@ -102,33 +71,85 @@ fn write_reference_prql() -> Result<()> { _ => {} } } - - // Write each one to a new file. - prql_blocks + let snapshot_prefix = &dir_entry + .path() + .strip_prefix("./src/")? + .to_str() + .unwrap() + .trim_end_matches(".md"); + Ok(prql_blocks .iter() .enumerate() - .try_for_each(|(i, example)| { - let file_relative = &dir_entry - .path() - .strip_prefix("./src/")? - .to_str() - .unwrap() - .trim_end_matches(".md"); - let prql_path = format!("tests/prql/{file_relative}-{i}.prql"); - - fs::create_dir_all(Path::new(&prql_path).parent().unwrap())?; - fs::write(prql_path, example.to_string())?; - - Ok::<(), anyhow::Error>(()) - })?; - Ok(()) + .map(|(i, example)| { + ( + format!("{ROOT_EXAMPLES_PATH}/{snapshot_prefix}-{i}.prql"), + example.to_string(), + ) + }) + .collect::>()) + }) + .flatten() + .collect(); + + Ok(examples_in_book) +} + +/// Extract reference examples from the PRQL docs and write them to the +/// `tests/prql` path, one in each file. +// We could alternatively have used something like +// https://github.com/earldouglas/codedown, but it's not much code, and it +// requires no dependencies. +// +// We allow dead_code because of the window issue described above. (Can we allow +// it only for windows?) +#[allow(dead_code)] +fn write_prql_examples() -> Result<()> { + // If we have to modify any files, raise an error at the end, so it fails in CI. + let mut snapshots_updated = false; + + let examples_path = Path::new(ROOT_EXAMPLES_PATH); + let prql_matcher = Glob::new("**.prql")?.compile_matcher(); + let mut existing_snapshots: HashMap<_, _> = WalkDir::new(examples_path) + .into_iter() + .flatten() + .filter(|x| prql_matcher.is_match(x.path())) + .map(|x| x.path().to_owned()) + .map(|x| Ok::<_, Error>((x.to_string_lossy().to_string(), fs::read_to_string(x)?))) + .try_collect()?; + + // Write any new snapshots, or update any that have changed. = + collect_book_examples()? + .iter() + .try_for_each(|(prql_path, example)| { + if existing_snapshots + .remove(prql_path) + .map(|existing| existing != *example) + .unwrap_or(true) + { + snapshots_updated = true; + fs::create_dir_all(Path::new(prql_path).parent().unwrap())?; + fs::write(prql_path, example)?; + } + + Ok::<(), anyhow::Error>(()) })?; + // If there are any files left in `existing_snapshots`, we remove them, since + // they don't reference anything. + existing_snapshots.iter().for_each(|(path, _)| { + trash::delete(path).unwrap_or_else(|e| { + warn!("Failed to delete unreferenced example: {}", e); + }) + }); + + if snapshots_updated { + bail!("Some book snapshots were not consistent with the queries in the book and have been updated. Subsequent runs should pass."); + } Ok(()) } /// Snapshot the output of each example. -fn run_reference_prql() { +fn test_prql_examples() { glob!("prql/**/*.prql", |path| { let prql = fs::read_to_string(path).unwrap(); @@ -147,20 +168,25 @@ fn run_reference_prql() { } /// Snapshot the display trait output of each example. -// Currently not a separate test, see notes in caller. // // TODO: this involves writing out almost the same PRQL again โ€” instead we could // compare the output of Display to the auto-formatted source. But we need an // autoformatter for that (unless we want to raise on any non-matching input, // which seems very strict) -fn run_display_reference_prql() { - glob!("prql/**/*.prql", |path| { - let prql = fs::read_to_string(path).unwrap(); - - if prql.contains("skip_test") { - return; - } +#[test] +fn test_display() -> Result<(), ErrorMessages> { + use prql_compiler::downcast; + collect_book_examples() + .map_err(downcast)? + .iter() + .try_for_each(|(path, example)| { + assert_snapshot!( + path.to_owned(), + prql_to_pl(example).and_then(pl_to_prql)?, + example + ); + Ok::<(), ErrorMessages>(()) + })?; - assert_display_snapshot!(prql_to_pl(&prql).and_then(pl_to_prql).unwrap()); - }); + Ok(()) } diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap deleted file mode 100644 index 085bada98319..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-0.prql ---- -from employees -select salary - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap deleted file mode 100644 index 6ab6d90cdd10..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-1.prql ---- -from employees -select [salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap deleted file mode 100644 index 930d29f6d477..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/misc-0.prql ---- -let parts = ( - from seq_1_to_5 -) - - - -from pl = prospect_lists_prospects -filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" -join a = accounts [a.id == pl.related_id] -join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] -join ea = email_addresses [ea.id == er.email_address_id] -select ea.email_address -derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" -derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" -select [ - email_address, - stub, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap deleted file mode 100644 index d48e3fe1307a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/misc-1.prql ---- -from club_ratings -filter rating != null -group year ( - derive [rating_norm = rating - ( average rating ) / ( stddev rating )] -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap deleted file mode 100644 index c4e1df527811..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/variables-0.prql ---- -from employees -filter country == "USA" -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average salary, - average gross_salary, - sum salary, - sum gross_salary, - average gross_cost, - sum_gross_cost = sum gross_cost, - ct = count, -] -) -sort sum_gross_cost -filter ct > 200 -take 20 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap deleted file mode 100644 index 1f588bf0d309..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/variables-1.prql ---- -from employees -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join titles [==emp_no] -group [title] ( - aggregate [avg_salary = average emp_salary] -) -select salary_k = avg_salary / 1000 -take 10 -derive salary = salary_k * 1000 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap deleted file mode 100644 index 96d5d50a00e1..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-0.prql ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap deleted file mode 100644 index ae83420f23d3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-1.prql ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap deleted file mode 100644 index f15a84e195b3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-2.prql ---- -filter age > 50 ( - from employees -) -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap deleted file mode 100644 index aa777d923706..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-3.prql ---- -sort name ( - filter age > 50 ( - from employees -) -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap deleted file mode 100644 index a7bd8bc3730a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/name-resolving-0.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap deleted file mode 100644 index bc40a390e21a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/introduction-0.prql ---- -from employees -filter start_date > @2021-01-01 -derive [ - gross_salary = salary + tax ?? 0, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average gross_salary, - sum_gross_cost = sum gross_cost, -] -) -filter sum_gross_cost > 100000 -derive id = f"{title}_{country}" -derive country_code = s"LEFT(country, 2)" -sort [ - sum_gross_cost, - -country, -] -take 1..20 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap deleted file mode 100644 index 16833c5f8cfa..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/coalesce-0.prql ---- -from orders -derive amount ?? 0 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap deleted file mode 100644 index ca08e6d69631..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-0.prql ---- -from employees -derive age_at_year_end = @2022-12-31 - dob - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap deleted file mode 100644 index 07d9b568eac6..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-1.prql ---- -from orders -derive should_have_shipped_today = order_time < @08:30 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap deleted file mode 100644 index 6e0b688f7f7a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-2.prql ---- -from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap deleted file mode 100644 index 5080f647a12c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-3.prql ---- -from projects -derive first_check_in = start + 10days - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap deleted file mode 100644 index 587f75ff1bd2..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-0.prql ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap deleted file mode 100644 index d6bcee7acf86..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-1.prql ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap deleted file mode 100644 index 4f2e5f381a88..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-2.prql ---- -from employees -group department ( - sort age - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap deleted file mode 100644 index 2b8a822ba481..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/f-strings-0.prql ---- -from employees -select full_name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap deleted file mode 100644 index b61f8780aa34..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/f-strings-1.prql ---- -from web -select url = f"http{tls}://www.{domain}.{tld}/{page}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap deleted file mode 100644 index 016809741efe..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/null-0.prql ---- -from employees -filter first_name == null -filter null != last_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap deleted file mode 100644 index 46ce8b767eb3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/ranges-1.prql ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap deleted file mode 100644 index fa9c95fb9f4c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-0.prql ---- -from my_table -select db_version = s"version()" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap deleted file mode 100644 index 7de6990c149c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-1.prql ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap deleted file mode 100644 index 691cabab4a62..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library-0.prql ---- -from employees -derive [ - gross_salary = ( - salary + payroll_tax - as int -), - gross_salary_rounded = ( - gross_salary - round 0 -), - time = s"NOW()", -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap deleted file mode 100644 index 08b198a45ab3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-0.prql ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap deleted file mode 100644 index 014e0927ce0e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-1.prql ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap deleted file mode 100644 index 52b190fec22a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-2.prql ---- -from my_table -select x = '"hello world"' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap deleted file mode 100644 index eddb87ee8834..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-3.prql ---- -from my_table -select x = 'I said "hello world"!' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap deleted file mode 100644 index 5966be260e48..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-4.prql ---- -from my_table -select x = 'I said """hello world"""!' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap deleted file mode 100644 index 8d46fc69595c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-0.prql ---- -prql target:sql.postgres - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap deleted file mode 100644 index 2719c8e16911..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-1.prql ---- -prql target:sql.mssql - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap deleted file mode 100644 index 5bf77265c6a4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-2.prql ---- -prql version:^0.5 - - - -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap deleted file mode 100644 index 7162e861b213..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-0.prql ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap deleted file mode 100644 index f64f5d68dc56..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-1.prql ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap deleted file mode 100644 index fbb8c9dfa00f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/variables-0.prql ---- -let top_50 = ( - from employees - sort salary - take 50 - aggregate [total_salary = sum salary] -) - - - -from top_50 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap deleted file mode 100644 index f719b0acbbd4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-11.prql ---- -from `dir/*.parquet` - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap deleted file mode 100644 index 6316d2280516..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-13.prql ---- -from `music.albums` - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap deleted file mode 100644 index a38f2f750602..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-14.prql ---- -from employees -filter id == $1 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap deleted file mode 100644 index 6820f7c5e628..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-3.prql ---- -from employees -select [first_name] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap deleted file mode 100644 index 6e06fe3ee2e5..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-4.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap deleted file mode 100644 index d6668fe305c7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap +++ /dev/null @@ -1,40 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-6.prql ---- -from employees -derive is_proximate = ( - distance - in 0..20 -) -derive ( - total_distance = sum distance -) -derive ( - min_capped_distance = min distance ?? 5 -) -derive travel_time = distance / 40 -derive ( - distance_rounded_2_dp = round 1 + 1 distance -) -derive [ - is_far = ( - distance - in 100.. -), - is_negative = ( - distance - in -100..0 -), - is_negative = ( - distance - in -100..0 -), - average_distance = average distance, -] -sort -distance -sort [-distance] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap deleted file mode 100644 index 55a51e5d833f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-8.prql ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap deleted file mode 100644 index 89e3271c8316..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-0.prql ---- -from employees -aggregate [ - average salary, - ct = count, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap deleted file mode 100644 index 21468ff11aeb..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-2.prql ---- -from employees -derive [avg_sal = average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap deleted file mode 100644 index 821c0f010d36..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-0.prql ---- -from employees_1 -append employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap deleted file mode 100644 index 2a61ec1251b1..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-1.prql ---- -from employees_1 -remove employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap deleted file mode 100644 index dddeb63b7c9f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-2.prql ---- -from employees_1 -intersect employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap deleted file mode 100644 index e90d9add3db4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/derive-0.prql ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap deleted file mode 100644 index 8a68bf997bd7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-0.prql ---- -from employees -filter age > 25 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap deleted file mode 100644 index 1bc8cf6d4a34..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-1.prql ---- -from employees -filter age > 25 or department != "IT" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap deleted file mode 100644 index ad800e09070f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-2.prql ---- -from employees -filter ( - age - in 25..40 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap deleted file mode 100644 index 0adcf6191d9e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from-0.prql ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap deleted file mode 100644 index b90898f6f93e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from-1.prql ---- -from e = employees -select e.first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap deleted file mode 100644 index a0aaabe15cb7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap +++ /dev/null @@ -1,33 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-2.prql ---- -let x = ( - from_text format:json '{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}' -) - - - -let y = ( - from_text format:json ' - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -' -) - - - -from x -join y [==a] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap deleted file mode 100644 index f916e255f991..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-1.prql ---- -from employees -sort join_date -take 1 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap deleted file mode 100644 index 6b2cb62586b3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-2.prql ---- -from employees -group role ( - sort join_date - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap deleted file mode 100644 index 19b950c9d24b..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-2.prql ---- -from employees -join positions [==emp_no] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap deleted file mode 100644 index 9841ec3d8249..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-0.prql ---- -from employees -select name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap deleted file mode 100644 index 522050c7dd99..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-2.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap deleted file mode 100644 index d6596a9ce634..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-3.prql ---- -from e = employees -select [ - e.first_name, - e.last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap deleted file mode 100644 index 102555240bdb..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-6.prql ---- -from artists -derive nick = name -select not [artists.`*`] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap deleted file mode 100644 index 91b36c10532f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-0.prql ---- -from employees -sort age - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap deleted file mode 100644 index d7f443472fc9..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-1.prql ---- -from employees -sort [-age] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap deleted file mode 100644 index 1df292e0b57f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-2.prql ---- -from employees -sort [ - age, - -tenure, - salary, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap deleted file mode 100644 index 3ef53a4676e9..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-3.prql ---- -from employees -sort [s"substr({first_name}, 2, 5)"] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap deleted file mode 100644 index 52f805544586..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-5.prql ---- -from employees -sort tenure -join locations [==employee_id] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap deleted file mode 100644 index 7f798967b647..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/take-0.prql ---- -from employees -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap deleted file mode 100644 index 4107c86bfd92..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/take-1.prql ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap deleted file mode 100644 index 3015829b90db..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-2.prql ---- -from employees -sort age -derive rnk = rank - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap deleted file mode 100644 index 26a5eb5d9d46..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-3.prql ---- -from employees -group department ( - sort age - derive rnk = rank -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap deleted file mode 100644 index be549656354d..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-4.prql ---- -from employees -filter salary < ( average salary ) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap index b246de058091..83e9f48a0e9e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/cte-0.prql +expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" --- let newest_employees = ( from employees diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap index 692c476512cc..ac80804d08a1 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-0.prql +expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" --- from salaries group [emp_no] ( diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap index 665754bd3fb5..c5d5366f6306 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-1.prql +expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap index 3823173006c7..d957c280a5c6 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-2.prql +expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap index 611769e8f06d..9cc6115f24bd 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-3.prql +expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap new file mode 100644 index 000000000000..8566dfaeb2b2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect salary\n" +--- +from employees +select salary + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap new file mode 100644 index 000000000000..055af64b363a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect [salary]\n" +--- +from employees +select [salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap index 5ba483c522d7..3d298b6f9b55 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-2.prql +expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap index c1c8e138f806..254f07187889 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-3.prql +expression: "from employees\nderive gross_salary = salary + payroll_tax\nderive gross_cost = gross_salary + benefits_cost\n" --- from employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap new file mode 100644 index 000000000000..63b13a31ec56 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap @@ -0,0 +1,25 @@ +--- +source: book/tests/snapshot.rs +expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" +--- +let parts = ( + from seq_1_to_5 +) + + + +from pl = prospect_lists_prospects +filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" +join a = accounts [a.id == pl.related_id] +join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] +join ea = email_addresses [ea.id == er.email_address_id] +select ea.email_address +derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" +derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" +select [ + email_address, + stub, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap new file mode 100644 index 000000000000..50dcca896ea5 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from club_ratings\nfilter rating != null\n# TODO: this is real ugly. `average rating` should not require parenthesis\n# TODO: why cannot we put comments in group's pipeline?\ngroup year (\n derive [rating_norm = rating - (average rating) / (stddev rating)]\n)\n" +--- +from club_ratings +filter rating != null +group year ( + derive [rating_norm = rating - ( average rating ) / ( stddev rating )] +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap new file mode 100644 index 000000000000..4b1f4fce84c1 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap @@ -0,0 +1,31 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter country == \"USA\" # Each line transforms the previous result.\nderive [ # This adds columns / variables.\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost # Variables can use other variables.\n]\nfilter gross_cost > 0\ngroup [title, country] ( # For each group use a nested pipeline\n aggregate [ # Aggregate each group to a single row\n average salary,\n average gross_salary,\n sum salary,\n sum gross_salary,\n average gross_cost,\n sum_gross_cost = sum gross_cost,\n ct = count,\n ]\n)\nsort sum_gross_cost\nfilter ct > 200\ntake 20\n" +--- +from employees +filter country == "USA" +derive [ + gross_salary = salary + payroll_tax, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average salary, + average gross_salary, + sum salary, + sum gross_salary, + average gross_cost, + sum_gross_cost = sum gross_cost, + ct = count, +] +) +sort sum_gross_cost +filter ct > 200 +take 20 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap new file mode 100644 index 000000000000..cfb45e96a801 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap @@ -0,0 +1,18 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup [emp_no] (\n aggregate [\n emp_salary = average salary # average salary resolves to \"AVG(salary)\" (from stdlib)\n ]\n)\njoin titles [==emp_no]\ngroup [title] (\n aggregate [\n avg_salary = average emp_salary\n ]\n)\nselect salary_k = avg_salary / 1000 # avg_salary should resolve to \"AVG(emp_salary)\"\ntake 10 # induces new SELECT\nderive salary = salary_k * 1000 # salary_k should not resolve to \"avg_salary / 1000\"\n" +--- +from employees +group [emp_no] ( + aggregate [emp_salary = average salary] +) +join titles [==emp_no] +group [title] ( + aggregate [avg_salary = average emp_salary] +) +select salary_k = avg_salary / 1000 +take 10 +derive salary = salary_k * 1000 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap new file mode 100644 index 000000000000..1bd2d905e16d --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter age > 50\nsort name\n" +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap new file mode 100644 index 000000000000..da4b761a9e4b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees | filter age > 50 | sort name\n" +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap new file mode 100644 index 000000000000..7da897d0dd14 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "filter age > 50 (from employees) | sort name\n" +--- +filter age > 50 ( + from employees +) +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap new file mode 100644 index 000000000000..045c663815a8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "sort name (filter age > 50 (from employees))\n" +--- +sort name ( + filter age > 50 ( + from employees +) +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap similarity index 56% rename from book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap index 6161fd5892e6..a9d9e5bada6d 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/name-resolving-1.prql +expression: "from employees\nderive [first_name, dept_id]\njoin d=departments [==dept_id]\nselect [first_name, d.title]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap new file mode 100644 index 000000000000..96f55b8ab057 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap @@ -0,0 +1,31 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" +--- +from employees +filter start_date > @2021-01-01 +derive [ + gross_salary = salary + tax ?? 0, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average gross_salary, + sum_gross_cost = sum gross_cost, +] +) +filter sum_gross_cost > 100000 +derive id = f"{title}_{country}" +derive country_code = s"LEFT(country, 2)" +sort [ + sum_gross_cost, + -country, +] +take 1..20 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap new file mode 100644 index 000000000000..24ff749cfbc8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nderive amount ?? 0\n" +--- +from orders +derive amount ?? 0 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap new file mode 100644 index 000000000000..acb71c71fc9a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive age_at_year_end = (@2022-12-31 - dob)\n" +--- +from employees +derive age_at_year_end = @2022-12-31 - dob + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap new file mode 100644 index 000000000000..fd2fe52b3f6c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nderive should_have_shipped_today = (order_time < @08:30)\n" +--- +from orders +derive should_have_shipped_today = order_time < @08:30 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap new file mode 100644 index 000000000000..1507a39b0252 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-0800\n" +--- +from commits +derive first_prql_commit = @2020-01-01T13:19:55-0800 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap new file mode 100644 index 000000000000..70ac66f365a2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from projects\nderive first_check_in = start + 10days\n" +--- +from projects +derive first_check_in = start + 10days + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap new file mode 100644 index 000000000000..7929401e23b6 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect department\ngroup department (\n take 1\n)\n" +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap new file mode 100644 index 000000000000..22ba087f087c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect department\ngroup department (take 1)\n" +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap new file mode 100644 index 000000000000..ceb0035e6601 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "# youngest employee from each department\nfrom employees\ngroup department (\n sort age\n take 1\n)\n" +--- +from employees +group department ( + sort age + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap new file mode 100644 index 000000000000..5f490aa52f00 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect full_name = f\"{first_name} {last_name}\"\n" +--- +from employees +select full_name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap new file mode 100644 index 000000000000..f00e2becbab2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from web\nselect url = f\"http{tls}://www.{domain}.{tld}/{page}\"\n" +--- +from web +select url = f"http{tls}://www.{domain}.{tld}/{page}" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap new file mode 100644 index 000000000000..73594522238f --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter first_name == null\nfilter null != last_name\n" +--- +from employees +filter first_name == null +filter null != last_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap index e20b2b97240c..2d5baa98ae2d 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/ranges-0.prql +expression: "from events\nfilter (date | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" --- from events filter ( diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap new file mode 100644 index 000000000000..b68c1920a669 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nsort [-value, date]\ntake 101..110\n" +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap new file mode 100644 index 000000000000..12abfcc2518c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect db_version = s\"version()\"\n" +--- +from my_table +select db_version = s"version()" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap new file mode 100644 index 000000000000..c57ed2561d58 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\naggregate [average salary]\n" +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap index 8d39feed0f0d..e28b7f46ed0a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-2.prql +expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"\"\"({s.from_date}, {s.to_date})\n OVERLAPS\n ({de.from_date}, {de.to_date})\"\"\"\n]\n" --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap index 85661196009c..2cb93849dda8 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-3.prql +expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" --- from s"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC" join s = s"SELECT * FROM salaries" [==id] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap index d7482d2f4cfb..00c1d5e17349 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-4.prql +expression: "from employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" --- from employees derive [has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){2,}')"] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap index 4313e1e554a7..9bd3b0d3fe16 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-5.prql +expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"{gross_salary} / 365\"\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap index 8ac94b9d968f..3dc30b6885ae 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-6.prql +expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"({gross_salary}) / 365\"\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap new file mode 100644 index 000000000000..011d5f416c47 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap @@ -0,0 +1,19 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" +--- +from employees +derive [ + gross_salary = ( + salary + payroll_tax + as int +), + gross_salary_rounded = ( + gross_salary + round 0 +), + time = s"NOW()", +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap new file mode 100644 index 000000000000..6a1d79036036 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"hello world\"\n" +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap new file mode 100644 index 000000000000..2da7a07937de --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = 'hello world'\n" +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap new file mode 100644 index 000000000000..8d79cd8cedbc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = '\"hello world\"'\n" +--- +from my_table +select x = '"hello world"' + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap new file mode 100644 index 000000000000..a681bc62a036 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\"\"I said \"hello world\"!\"\"\"\n" +--- +from my_table +select x = 'I said "hello world"!' + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap new file mode 100644 index 000000000000..0bae3f836774 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\"\"\"\"I said \"\"\"hello world\"\"\"!\"\"\"\"\"\n" +--- +from my_table +select x = 'I said """hello world"""!' + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap index 85bb6bac32b8..7618b9e71723 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/switch-0.prql +expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap index dd4c64e0b6b0..f9ee3312b92b 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/switch-1.prql +expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap new file mode 100644 index 000000000000..b22539422ae4 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" +--- +prql target:sql.postgres + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap new file mode 100644 index 000000000000..ed7e10fd7388 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: "prql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" +--- +prql target:sql.mssql + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap new file mode 100644 index 000000000000..b05787ed8bae --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "prql version:\"0.5\"\n\nfrom employees\n" +--- +prql version:^0.5 + + + +from employees + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap index bde459b05cf8..e5bb0a64491b 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-0.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap index d8d3e0185fd9..ef971e8402bc 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-1.prql +expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp lower:0 1600 sat_score),\n]\n" --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap index 49560fe48496..2e8f243ea009 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-2.prql +expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp lower:0 1600),\n]\n" --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap index 83e91977fe3f..bc1453813dc9 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-3.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (temp_f | fahrenheit_to_celsius)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap index 8ed62cca5158..3deae6fcab9c 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-4.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap new file mode 100644 index 000000000000..8ef6dce0bb66 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n" +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap new file mode 100644 index 000000000000..b2b18409f03a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive gross_salary = (salary + payroll_tax)\n" +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap index e3ff662251a8..5c74bd2eeb81 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-2.prql +expression: "from e = employees\nderive gross_salary = (salary + payroll_tax)\nsort gross_salary\ntake 10\njoin d = department [==dept_no]\nselect [e.name, gross_salary, d.name]\n" --- from e = employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap new file mode 100644 index 000000000000..3c4edace1010 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap @@ -0,0 +1,17 @@ +--- +source: book/tests/snapshot.rs +expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" +--- +let top_50 = ( + from employees + sort salary + take 50 + aggregate [total_salary = sum salary] +) + + + +from top_50 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap index f7a3cbcd9431..dd72ddc9b4bb 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/variables-1.prql +expression: "let grouping = s\"\"\"\n SELECT SUM(a)\n FROM tbl\n GROUP BY\n GROUPING SETS\n ((b, c, d), (d), (b, d))\n\"\"\"\n\nfrom grouping\n" --- let grouping = s" SELECT SUM(a) diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap index 16788f8c5410..ee78d7a29c00 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-0.prql +expression: "from employees\nfilter department == \"Product\"\nselect [first_name, last_name]\n" --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap index 7d3684118966..ae9d7fcbb81c 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-1.prql +expression: "from employees | filter department == \"Product\" | select [first_name, last_name]\n" --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap index e12239744931..0ef6f6c5ea4e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-10.prql +expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" --- prql target:sql.postgres diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap new file mode 100644 index 000000000000..acd1651bdbb9 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from `dir/*.parquet`\n" +--- +from `dir/*.parquet` + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap index 79ec4c9aa74d..6be462d1cb08 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-12.prql +expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap new file mode 100644 index 000000000000..fc9310bcceea --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from `music.albums`\n" +--- +from `music.albums` + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap new file mode 100644 index 000000000000..429e57d0faf3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter id == $1\n" +--- +from employees +filter id == $1 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap index 34d44267ba17..7aa2caf4c217 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-15.prql +expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" --- from numbers select [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap index 8c5b5825e8c4..a12652162d23 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-2.prql +expression: "from numbers\nderive [x = 1, y = 2]\nderive [\n a = x,\n b = y\n]\nderive [\n c = a,\n d = b,\n]\n" --- from numbers derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap new file mode 100644 index 000000000000..4077d71aaa9b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect [first_name]\n" +--- +from employees +select [first_name] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap index f3ebf960c4bf..027e1a5e000f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-5.prql +expression: "from foo\nselect [\n circumference = diameter * 3.14159,\n color,\n]\nfilter circumference > 10 and color != \"red\"\n" --- from foo select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap new file mode 100644 index 000000000000..b9f326d968cc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap @@ -0,0 +1,39 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" +--- +from employees +derive is_proximate = ( + distance + in 0..20 +) +derive ( + total_distance = sum distance +) +derive ( + min_capped_distance = min distance ?? 5 +) +derive travel_time = distance / 40 +derive ( + distance_rounded_2_dp = round 1 + 1 distance +) +derive [ + is_far = ( + distance + in 100.. +), + is_negative = ( + distance + in -100..0 +), + is_negative = ( + distance + in -100..0 +), + average_distance = average distance, +] +sort -distance +sort [-distance] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap index 29e0c6d26c1e..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-7.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap new file mode 100644 index 000000000000..4f94033b1f86 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap index 9e5a61c3e446..19c4de64822f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-9.prql +expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" --- prql target:sql.mysql diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap new file mode 100644 index 000000000000..1c202ec4ba25 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\naggregate [\n average salary,\n ct = count\n]\n" +--- +from employees +aggregate [ + average salary, + ct = count, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap index bbf253ec6dd5..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-1.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap new file mode 100644 index 000000000000..9b49b51df2a5 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive [avg_sal = average salary]\n" +--- +from employees +derive [avg_sal = average salary] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap new file mode 100644 index 000000000000..cbbd0478001b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nappend employees_2\n" +--- +from employees_1 +append employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap new file mode 100644 index 000000000000..e2b9a1338479 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nremove employees_2\n" +--- +from employees_1 +remove employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap new file mode 100644 index 000000000000..1971d287b890 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nintersect employees_2\n" +--- +from employees_1 +intersect employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap new file mode 100644 index 000000000000..183b59f98112 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive gross_salary = salary + payroll_tax\n" +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap index f2b9dd7bd20d..3d298b6f9b55 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/derive-1.prql +expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap new file mode 100644 index 000000000000..bd5e2c425e25 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter age > 25\n" +--- +from employees +filter age > 25 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap new file mode 100644 index 000000000000..a6cb5b5b569e --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter (age > 25 or department != \"IT\")\n" +--- +from employees +filter age > 25 or department != "IT" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap new file mode 100644 index 000000000000..d3b04cd4de31 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter (age | in 25..40)\n" +--- +from employees +filter ( + age + in 25..40 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap new file mode 100644 index 000000000000..8ef6dce0bb66 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n" +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap new file mode 100644 index 000000000000..ef1312a86941 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from e = employees\nselect e.first_name\n" +--- +from e = employees +select e.first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap index d86f2e1e86bb..6a730d3a1f7e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-0.prql +expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" --- from_text " a,b,c diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap index 740349748e00..6f9f848bbd6e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-1.prql +expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" --- let temp_format_lookup = ( from_text format:csv " diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap new file mode 100644 index 000000000000..da17c3b1fe6f --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap @@ -0,0 +1,32 @@ +--- +source: book/tests/snapshot.rs +expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" +--- +let x = ( + from_text format:json '{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}' +) + + + +let y = ( + from_text format:json ' + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +' +) + + + +from x +join y [==a] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap index 754f23c1d76e..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-0.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap new file mode 100644 index 000000000000..2517396a1418 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort join_date\ntake 1\n" +--- +from employees +sort join_date +take 1 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap new file mode 100644 index 000000000000..11467687bbbb --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup role (\n sort join_date # taken from above\n take 1\n)\n" +--- +from employees +group role ( + sort join_date + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap index 0334411b6614..4d113382409a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-0.prql +expression: "from employees\njoin side:left positions [employees.id==positions.employee_id]\n" --- from employees join side:left positions [employees.id == positions.employee_id] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap index 073e5b79b5ee..b3e13a1d23f8 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-1.prql +expression: "from employees\njoin side:left p=positions [employees.id==p.employee_id]\n" --- from employees join side:left p = positions [employees.id == p.employee_id] diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap new file mode 100644 index 000000000000..ba833fa01b02 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\njoin positions [==emp_no]\n" +--- +from employees +join positions [==emp_no] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap new file mode 100644 index 000000000000..ef3e65965333 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect name = f\"{first_name} {last_name}\"\n" +--- +from employees +select name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap index 1ecfbb0be8f6..57c345371217 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-1.prql +expression: "from employees\nselect [\n name = f\"{first_name} {last_name}\",\n age_eoy = dob - @2022-12-31,\n]\n" --- from employees select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap new file mode 100644 index 000000000000..059b92276754 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from e=employees\nselect [e.first_name, e.last_name]\n" +--- +from e = employees +select [ + e.first_name, + e.last_name, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap index c8837e7a5780..6445588450d2 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-4.prql +expression: "prql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap index ee470cf35cf6..568bc821ba4f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-5.prql +expression: "from tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" --- from tracks select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap new file mode 100644 index 000000000000..19b65db61c48 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from artists\nderive nick = name\nselect ![artists.*]\n" +--- +from artists +derive nick = name +select not [artists.`*`] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap new file mode 100644 index 000000000000..cb41ef4b5ddb --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort age\n" +--- +from employees +sort age + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap new file mode 100644 index 000000000000..12203dcc78d3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [-age]\n" +--- +from employees +sort [-age] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap new file mode 100644 index 000000000000..23c2050900c8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [age, -tenure, +salary]\n" +--- +from employees +sort [ + age, + -tenure, + salary, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap new file mode 100644 index 000000000000..01b0d75eb4e3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" +--- +from employees +sort [s"substr({first_name}, 2, 5)"] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap index 01b5c740c41a..51c71b587af5 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-4.prql +expression: "from employees\nsort tenure\nderive name = f\"{first_name} {last_name}\"\n" --- from employees sort tenure diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap new file mode 100644 index 000000000000..405c461df7e4 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort tenure\njoin locations [==employee_id]\n" +--- +from employees +sort tenure +join locations [==employee_id] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap new file mode 100644 index 000000000000..4c39e0cddcea --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ntake 10\n" +--- +from employees +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap new file mode 100644 index 000000000000..b68c1920a669 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nsort [-value, date]\ntake 101..110\n" +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap index 2366506585b0..08d6e23e2468 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-0.prql +expression: "from employees\ngroup employee_id (\n sort month\n window rolling:12 (\n derive [trail_12_m_comp = sum paycheck]\n )\n)\n" --- from employees group employee_id ( diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap index afffeb8eb185..c0663a94bc4a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-1.prql +expression: "from orders\nsort day\nwindow rows:-3..3 (\n derive [centered_weekly_average = average value]\n)\ngroup [order_month] (\n sort day\n window expanding:true (\n derive [monthly_running_total = sum value]\n )\n)\n" --- from orders sort day diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap new file mode 100644 index 000000000000..dc3037c993b3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort age\nderive rnk = rank\n" +--- +from employees +sort age +derive rnk = rank + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap new file mode 100644 index 000000000000..b71455102a11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup department (\n sort age\n derive rnk = rank\n)\n" +--- +from employees +group department ( + sort age + derive rnk = rank +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap new file mode 100644 index 000000000000..9e104fbe34a9 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter salary < (average salary)\n" +--- +from employees +filter salary < ( average salary ) + + + From 4c3fb3e43806c05728140bb099438719aa91fb6b Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 18:05:26 -0800 Subject: [PATCH 024/184] revert: test: Refactor book snapshot tests (#1903) Revert "test: Refactor book snapshot tests (#1900)" This reverts commit abc61ff3fd18e6deff9159b9726071705d3a4f29. --- book/tests/snapshot.rs | 172 ++++++++---------- ..._reference_prql@examples__cte-0.prql.snap} | 3 +- ...ence_prql@examples__employees-0.prql.snap} | 3 +- ...ence_prql@examples__employees-1.prql.snap} | 3 +- ...ence_prql@examples__employees-2.prql.snap} | 3 +- ...ence_prql@examples__employees-3.prql.snap} | 3 +- ...rql@examples__list-equivalence-0.prql.snap | 10 + ...rql@examples__list-equivalence-1.prql.snap | 10 + ...ql@examples__list-equivalence-2.prql.snap} | 3 +- ...ql@examples__list-equivalence-3.prql.snap} | 3 +- ..._reference_prql@examples__misc-0.prql.snap | 26 +++ ..._reference_prql@examples__misc-1.prql.snap | 13 ++ ...rence_prql@examples__variables-0.prql.snap | 32 ++++ ...rence_prql@examples__variables-1.prql.snap | 19 ++ ...rql@internals__functional-lang-0.prql.snap | 11 ++ ...rql@internals__functional-lang-1.prql.snap | 11 ++ ...rql@internals__functional-lang-2.prql.snap | 12 ++ ...rql@internals__functional-lang-3.prql.snap | 13 ++ ...prql@internals__name-resolving-0.prql.snap | 10 + ...rql@internals__name-resolving-1.prql.snap} | 3 +- ...ay_reference_prql@introduction-0.prql.snap | 32 ++++ ...ql@language-features__coalesce-0.prql.snap | 10 + ...uage-features__dates-and-times-0.prql.snap | 10 + ...uage-features__dates-and-times-1.prql.snap | 10 + ...uage-features__dates-and-times-2.prql.snap | 10 + ...uage-features__dates-and-times-3.prql.snap | 10 + ...ql@language-features__distinct-0.prql.snap | 13 ++ ...ql@language-features__distinct-1.prql.snap | 13 ++ ...ql@language-features__distinct-2.prql.snap | 13 ++ ...l@language-features__f-strings-0.prql.snap | 10 + ...l@language-features__f-strings-1.prql.snap | 10 + ...e_prql@language-features__null-0.prql.snap | 11 ++ ...rql@language-features__ranges-0.prql.snap} | 3 +- ...prql@language-features__ranges-1.prql.snap | 14 ++ ...l@language-features__s-strings-0.prql.snap | 10 + ...l@language-features__s-strings-1.prql.snap | 10 + ...@language-features__s-strings-2.prql.snap} | 3 +- ...@language-features__s-strings-3.prql.snap} | 3 +- ...@language-features__s-strings-4.prql.snap} | 3 +- ...@language-features__s-strings-5.prql.snap} | 3 +- ...@language-features__s-strings-6.prql.snap} | 3 +- ...age-features__standard-library-0.prql.snap | 20 ++ ...rql@language-features__strings-0.prql.snap | 10 + ...rql@language-features__strings-1.prql.snap | 10 + ...rql@language-features__strings-2.prql.snap | 10 + ...rql@language-features__strings-3.prql.snap | 10 + ...rql@language-features__strings-4.prql.snap | 10 + ...rql@language-features__switch-0.prql.snap} | 3 +- ...rql@language-features__switch-1.prql.snap} | 3 +- ...prql@language-features__target-0.prql.snap | 15 ++ ...prql@language-features__target-1.prql.snap | 15 ++ ...prql@language-features__target-2.prql.snap | 13 ++ ...rence_prql@queries__functions-0.prql.snap} | 3 +- ...rence_prql@queries__functions-1.prql.snap} | 3 +- ...rence_prql@queries__functions-2.prql.snap} | 3 +- ...rence_prql@queries__functions-3.prql.snap} | 3 +- ...rence_prql@queries__functions-4.prql.snap} | 3 +- ...erence_prql@queries__pipelines-0.prql.snap | 9 + ...erence_prql@queries__pipelines-1.prql.snap | 10 + ...rence_prql@queries__pipelines-2.prql.snap} | 3 +- ...erence_prql@queries__variables-0.prql.snap | 18 ++ ...rence_prql@queries__variables-1.prql.snap} | 3 +- ...display_reference_prql@syntax-0.prql.snap} | 3 +- ...display_reference_prql@syntax-1.prql.snap} | 3 +- ...isplay_reference_prql@syntax-10.prql.snap} | 3 +- ...display_reference_prql@syntax-11.prql.snap | 9 + ...isplay_reference_prql@syntax-12.prql.snap} | 3 +- ...display_reference_prql@syntax-13.prql.snap | 9 + ...display_reference_prql@syntax-14.prql.snap | 10 + ...isplay_reference_prql@syntax-15.prql.snap} | 3 +- ...display_reference_prql@syntax-2.prql.snap} | 3 +- ..._display_reference_prql@syntax-3.prql.snap | 10 + ..._display_reference_prql@syntax-4.prql.snap | 10 + ...display_reference_prql@syntax-5.prql.snap} | 3 +- ..._display_reference_prql@syntax-6.prql.snap | 40 ++++ ...display_reference_prql@syntax-7.prql.snap} | 3 +- ..._display_reference_prql@syntax-8.prql.snap | 10 + ...display_reference_prql@syntax-9.prql.snap} | 3 +- ...nce_prql@transforms__aggregate-0.prql.snap | 13 ++ ...ce_prql@transforms__aggregate-1.prql.snap} | 3 +- ...nce_prql@transforms__aggregate-2.prql.snap | 10 + ...erence_prql@transforms__append-0.prql.snap | 10 + ...erence_prql@transforms__append-1.prql.snap | 10 + ...erence_prql@transforms__append-2.prql.snap | 10 + ...erence_prql@transforms__derive-0.prql.snap | 10 + ...rence_prql@transforms__derive-1.prql.snap} | 3 +- ...erence_prql@transforms__filter-0.prql.snap | 10 + ...erence_prql@transforms__filter-1.prql.snap | 10 + ...erence_prql@transforms__filter-2.prql.snap | 13 ++ ...eference_prql@transforms__from-0.prql.snap | 9 + ...eference_prql@transforms__from-1.prql.snap | 10 + ...ce_prql@transforms__from_text-0.prql.snap} | 3 +- ...ce_prql@transforms__from_text-1.prql.snap} | 3 +- ...nce_prql@transforms__from_text-2.prql.snap | 33 ++++ ...erence_prql@transforms__group-0.prql.snap} | 3 +- ...ference_prql@transforms__group-1.prql.snap | 11 ++ ...ference_prql@transforms__group-2.prql.snap | 13 ++ ...ference_prql@transforms__join-0.prql.snap} | 3 +- ...ference_prql@transforms__join-1.prql.snap} | 3 +- ...eference_prql@transforms__join-2.prql.snap | 10 + ...erence_prql@transforms__select-0.prql.snap | 10 + ...rence_prql@transforms__select-1.prql.snap} | 3 +- ...erence_prql@transforms__select-2.prql.snap | 10 + ...erence_prql@transforms__select-3.prql.snap | 13 ++ ...rence_prql@transforms__select-4.prql.snap} | 3 +- ...rence_prql@transforms__select-5.prql.snap} | 3 +- ...erence_prql@transforms__select-6.prql.snap | 11 ++ ...eference_prql@transforms__sort-0.prql.snap | 10 + ...eference_prql@transforms__sort-1.prql.snap | 10 + ...eference_prql@transforms__sort-2.prql.snap | 14 ++ ...eference_prql@transforms__sort-3.prql.snap | 10 + ...ference_prql@transforms__sort-4.prql.snap} | 3 +- ...eference_prql@transforms__sort-5.prql.snap | 11 ++ ...eference_prql@transforms__take-0.prql.snap | 10 + ...eference_prql@transforms__take-1.prql.snap | 14 ++ ...rence_prql@transforms__window-0.prql.snap} | 3 +- ...rence_prql@transforms__window-1.prql.snap} | 3 +- ...erence_prql@transforms__window-2.prql.snap | 11 ++ ...erence_prql@transforms__window-3.prql.snap | 13 ++ ...erence_prql@transforms__window-4.prql.snap | 10 + ...ql__examples__list-equivalence-0.prql.snap | 9 - ...ql__examples__list-equivalence-1.prql.snap | 9 - ...t__tests__prql__examples__misc-0.prql.snap | 25 --- ...t__tests__prql__examples__misc-1.prql.snap | 12 -- ...sts__prql__examples__variables-0.prql.snap | 31 ---- ...sts__prql__examples__variables-1.prql.snap | 18 -- ...ql__internals__functional-lang-0.prql.snap | 10 - ...ql__internals__functional-lang-1.prql.snap | 10 - ...ql__internals__functional-lang-2.prql.snap | 11 -- ...ql__internals__functional-lang-3.prql.snap | 12 -- ...rql__internals__name-resolving-0.prql.snap | 9 - ...hot__tests__prql__introduction-0.prql.snap | 31 ---- ...l__language-features__coalesce-0.prql.snap | 9 - ...uage-features__dates-and-times-0.prql.snap | 9 - ...uage-features__dates-and-times-1.prql.snap | 9 - ...uage-features__dates-and-times-2.prql.snap | 9 - ...uage-features__dates-and-times-3.prql.snap | 9 - ...l__language-features__distinct-0.prql.snap | 12 -- ...l__language-features__distinct-1.prql.snap | 12 -- ...l__language-features__distinct-2.prql.snap | 12 -- ...__language-features__f-strings-0.prql.snap | 9 - ...__language-features__f-strings-1.prql.snap | 9 - ..._prql__language-features__null-0.prql.snap | 10 - ...rql__language-features__ranges-1.prql.snap | 13 -- ...__language-features__s-strings-0.prql.snap | 9 - ...__language-features__s-strings-1.prql.snap | 9 - ...age-features__standard-library-0.prql.snap | 19 -- ...ql__language-features__strings-0.prql.snap | 9 - ...ql__language-features__strings-1.prql.snap | 9 - ...ql__language-features__strings-2.prql.snap | 9 - ...ql__language-features__strings-3.prql.snap | 9 - ...ql__language-features__strings-4.prql.snap | 9 - ...rql__language-features__target-0.prql.snap | 14 -- ...rql__language-features__target-1.prql.snap | 14 -- ...rql__language-features__target-2.prql.snap | 12 -- ...ests__prql__queries__pipelines-0.prql.snap | 8 - ...ests__prql__queries__pipelines-1.prql.snap | 9 - ...ests__prql__queries__variables-0.prql.snap | 17 -- ...snapshot__tests__prql__syntax-11.prql.snap | 8 - ...snapshot__tests__prql__syntax-13.prql.snap | 8 - ...snapshot__tests__prql__syntax-14.prql.snap | 9 - .../snapshot__tests__prql__syntax-3.prql.snap | 9 - .../snapshot__tests__prql__syntax-4.prql.snap | 9 - .../snapshot__tests__prql__syntax-6.prql.snap | 39 ---- .../snapshot__tests__prql__syntax-8.prql.snap | 9 - ...s__prql__transforms__aggregate-0.prql.snap | 12 -- ...s__prql__transforms__aggregate-2.prql.snap | 9 - ...ests__prql__transforms__append-0.prql.snap | 9 - ...ests__prql__transforms__append-1.prql.snap | 9 - ...ests__prql__transforms__append-2.prql.snap | 9 - ...ests__prql__transforms__derive-0.prql.snap | 9 - ...ests__prql__transforms__filter-0.prql.snap | 9 - ...ests__prql__transforms__filter-1.prql.snap | 9 - ...ests__prql__transforms__filter-2.prql.snap | 12 -- ..._tests__prql__transforms__from-0.prql.snap | 8 - ..._tests__prql__transforms__from-1.prql.snap | 9 - ...s__prql__transforms__from_text-2.prql.snap | 32 ---- ...tests__prql__transforms__group-1.prql.snap | 10 - ...tests__prql__transforms__group-2.prql.snap | 12 -- ..._tests__prql__transforms__join-2.prql.snap | 9 - ...ests__prql__transforms__select-0.prql.snap | 9 - ...ests__prql__transforms__select-2.prql.snap | 9 - ...ests__prql__transforms__select-3.prql.snap | 12 -- ...ests__prql__transforms__select-6.prql.snap | 10 - ..._tests__prql__transforms__sort-0.prql.snap | 9 - ..._tests__prql__transforms__sort-1.prql.snap | 9 - ..._tests__prql__transforms__sort-2.prql.snap | 13 -- ..._tests__prql__transforms__sort-3.prql.snap | 9 - ..._tests__prql__transforms__sort-5.prql.snap | 10 - ..._tests__prql__transforms__take-0.prql.snap | 9 - ..._tests__prql__transforms__take-1.prql.snap | 13 -- ...ests__prql__transforms__window-2.prql.snap | 10 - ...ests__prql__transforms__window-3.prql.snap | 12 -- ...ests__prql__transforms__window-4.prql.snap | 9 - 194 files changed, 1103 insertions(+), 1010 deletions(-) rename book/tests/snapshots/{snapshot__tests__prql__examples__cte-0.prql.snap => snapshot__run_display_reference_prql@examples__cte-0.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__examples__employees-0.prql.snap => snapshot__run_display_reference_prql@examples__employees-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__tests__prql__examples__employees-1.prql.snap => snapshot__run_display_reference_prql@examples__employees-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__examples__employees-2.prql.snap => snapshot__run_display_reference_prql@examples__employees-2.prql.snap} (50%) rename book/tests/snapshots/{snapshot__tests__prql__examples__employees-3.prql.snap => snapshot__run_display_reference_prql@examples__employees-3.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__examples__list-equivalence-2.prql.snap => snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap} (54%) rename book/tests/snapshots/{snapshot__tests__prql__examples__list-equivalence-3.prql.snap => snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__internals__name-resolving-1.prql.snap => snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap} (56%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__language-features__ranges-0.prql.snap => snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__language-features__s-strings-2.prql.snap => snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__language-features__s-strings-3.prql.snap => snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap} (53%) rename book/tests/snapshots/{snapshot__tests__prql__language-features__s-strings-4.prql.snap => snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__language-features__s-strings-5.prql.snap => snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap} (53%) rename book/tests/snapshots/{snapshot__tests__prql__language-features__s-strings-6.prql.snap => snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__language-features__switch-0.prql.snap => snapshot__run_display_reference_prql@language-features__switch-0.prql.snap} (53%) rename book/tests/snapshots/{snapshot__tests__prql__language-features__switch-1.prql.snap => snapshot__run_display_reference_prql@language-features__switch-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__queries__functions-0.prql.snap => snapshot__run_display_reference_prql@queries__functions-0.prql.snap} (54%) rename book/tests/snapshots/{snapshot__tests__prql__queries__functions-1.prql.snap => snapshot__run_display_reference_prql@queries__functions-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__queries__functions-2.prql.snap => snapshot__run_display_reference_prql@queries__functions-2.prql.snap} (52%) rename book/tests/snapshots/{snapshot__tests__prql__queries__functions-3.prql.snap => snapshot__run_display_reference_prql@queries__functions-3.prql.snap} (54%) rename book/tests/snapshots/{snapshot__tests__prql__queries__functions-4.prql.snap => snapshot__run_display_reference_prql@queries__functions-4.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__queries__pipelines-2.prql.snap => snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__queries__variables-1.prql.snap => snapshot__run_display_reference_prql@queries__variables-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__syntax-0.prql.snap => snapshot__run_display_reference_prql@syntax-0.prql.snap} (55%) rename book/tests/snapshots/{snapshot__tests__prql__syntax-1.prql.snap => snapshot__run_display_reference_prql@syntax-1.prql.snap} (55%) rename book/tests/snapshots/{snapshot__tests__prql__syntax-10.prql.snap => snapshot__run_display_reference_prql@syntax-10.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__syntax-12.prql.snap => snapshot__run_display_reference_prql@syntax-12.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__syntax-15.prql.snap => snapshot__run_display_reference_prql@syntax-15.prql.snap} (50%) rename book/tests/snapshots/{snapshot__tests__prql__syntax-2.prql.snap => snapshot__run_display_reference_prql@syntax-2.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__syntax-5.prql.snap => snapshot__run_display_reference_prql@syntax-5.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__syntax-7.prql.snap => snapshot__run_display_reference_prql@syntax-7.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__syntax-9.prql.snap => snapshot__run_display_reference_prql@syntax-9.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__aggregate-1.prql.snap => snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__derive-1.prql.snap => snapshot__run_display_reference_prql@transforms__derive-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__from_text-0.prql.snap => snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap} (50%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__from_text-1.prql.snap => snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__group-0.prql.snap => snapshot__run_display_reference_prql@transforms__group-0.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__join-0.prql.snap => snapshot__run_display_reference_prql@transforms__join-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__join-1.prql.snap => snapshot__run_display_reference_prql@transforms__join-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__select-1.prql.snap => snapshot__run_display_reference_prql@transforms__select-1.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__select-4.prql.snap => snapshot__run_display_reference_prql@transforms__select-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__select-5.prql.snap => snapshot__run_display_reference_prql@transforms__select-5.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__sort-4.prql.snap => snapshot__run_display_reference_prql@transforms__sort-4.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__transforms__window-0.prql.snap => snapshot__run_display_reference_prql@transforms__window-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__window-1.prql.snap => snapshot__run_display_reference_prql@transforms__window-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index d26bfe754dec..e86b59ae20fc 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -1,6 +1,6 @@ #![cfg(not(target_family = "wasm"))] /// This test: -/// - Extracts PRQL code blocks into files in the `examples` path +/// - Extracts PRQL code blocks into the `examples` path. /// - Converts them to SQL using insta, raising an error if there's a diff. /// - Replaces the PRQL code block with a comparison table. /// @@ -18,38 +18,69 @@ // us. They introduce a bunch of non-rust dependencies, which is not ideal, but // passable. They don't let us customize our formatting (e.g. in a table). // -use anyhow::{bail, Error, Result}; +use anyhow::{bail, Result}; use globset::Glob; -use insta::{assert_snapshot, glob}; -use itertools::Itertools; +use insta::{assert_display_snapshot, assert_snapshot, glob}; use log::warn; use prql_compiler::*; use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; +use std::fs; use std::path::Path; -use std::{collections::HashMap, fs}; use walkdir::WalkDir; #[test] -fn test_examples() -> Result<()> { +fn run_examples() -> Result<()> { + // TODO: In CI this could pass by replacing incorrect files. To catch that, + // we could check if there are any diffs after this has run? + // Note that on windows, markdown is read differently, and so // writing on Windows. ref https://github.com/PRQL/prql/issues/356 #[cfg(not(target_family = "windows"))] - write_prql_examples()?; - test_prql_examples(); + write_reference_prql()?; + run_reference_prql(); + + // TODO: Currently we run this in the same test, since we need the + // `write_reference_prql` function to have been run. If we could iterate + // over the PRQL examples without writing them to disk, we could run this as + // a separate test. (Though then we'd lose the deferred failures feature + // that insta's `glob!` macro provides.) + run_display_reference_prql(); Ok(()) } -const ROOT_EXAMPLES_PATH: &str = "tests/prql"; +/// Extract reference examples from the PRQL docs and write them to the +/// `tests/prql` path, one in each file. +// We could alternatively have used something like +// https://github.com/earldouglas/codedown, but it's not much code, and it +// requires no dependencies. +// +// We allow dead_code because of the window issue described above. (Can we allow +// it only for windows?) +#[allow(dead_code)] +fn write_reference_prql() -> Result<()> { + // Remove old .prql files, since we're going to rewrite them, and we don't want + // old files which wouldn't be rewritten from hanging around. + // We use `trash`, since we don't want to be removing files with test code + // in case there's a bug. + // + // A more elegant approach would be to keep a list of the files and remove + // the ones we don't write. + + let examples_path = Path::new("tests/prql"); + if examples_path.exists() { + trash::delete(Path::new("tests/prql")).unwrap_or_else(|e| { + warn!("Failed to delete old examples: {}", e); + }); + } -/// Collect all the PRQL examples in the book, as a map of . -fn collect_book_examples() -> Result> { let glob = Glob::new("**/*.md")?.compile_matcher(); - let examples_in_book: HashMap = WalkDir::new(Path::new("./src/")) + + WalkDir::new(Path::new("./src/")) .into_iter() .flatten() .filter(|x| glob.is_match(x.path())) - .flat_map(|dir_entry| { + .try_for_each(|dir_entry| { let text = fs::read_to_string(dir_entry.path())?; let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; @@ -71,85 +102,33 @@ fn collect_book_examples() -> Result> { _ => {} } } - let snapshot_prefix = &dir_entry - .path() - .strip_prefix("./src/")? - .to_str() - .unwrap() - .trim_end_matches(".md"); - Ok(prql_blocks + + // Write each one to a new file. + prql_blocks .iter() .enumerate() - .map(|(i, example)| { - ( - format!("{ROOT_EXAMPLES_PATH}/{snapshot_prefix}-{i}.prql"), - example.to_string(), - ) - }) - .collect::>()) - }) - .flatten() - .collect(); - - Ok(examples_in_book) -} - -/// Extract reference examples from the PRQL docs and write them to the -/// `tests/prql` path, one in each file. -// We could alternatively have used something like -// https://github.com/earldouglas/codedown, but it's not much code, and it -// requires no dependencies. -// -// We allow dead_code because of the window issue described above. (Can we allow -// it only for windows?) -#[allow(dead_code)] -fn write_prql_examples() -> Result<()> { - // If we have to modify any files, raise an error at the end, so it fails in CI. - let mut snapshots_updated = false; - - let examples_path = Path::new(ROOT_EXAMPLES_PATH); - let prql_matcher = Glob::new("**.prql")?.compile_matcher(); - let mut existing_snapshots: HashMap<_, _> = WalkDir::new(examples_path) - .into_iter() - .flatten() - .filter(|x| prql_matcher.is_match(x.path())) - .map(|x| x.path().to_owned()) - .map(|x| Ok::<_, Error>((x.to_string_lossy().to_string(), fs::read_to_string(x)?))) - .try_collect()?; - - // Write any new snapshots, or update any that have changed. = - collect_book_examples()? - .iter() - .try_for_each(|(prql_path, example)| { - if existing_snapshots - .remove(prql_path) - .map(|existing| existing != *example) - .unwrap_or(true) - { - snapshots_updated = true; - fs::create_dir_all(Path::new(prql_path).parent().unwrap())?; - fs::write(prql_path, example)?; - } - - Ok::<(), anyhow::Error>(()) + .try_for_each(|(i, example)| { + let file_relative = &dir_entry + .path() + .strip_prefix("./src/")? + .to_str() + .unwrap() + .trim_end_matches(".md"); + let prql_path = format!("tests/prql/{file_relative}-{i}.prql"); + + fs::create_dir_all(Path::new(&prql_path).parent().unwrap())?; + fs::write(prql_path, example.to_string())?; + + Ok::<(), anyhow::Error>(()) + })?; + Ok(()) })?; - // If there are any files left in `existing_snapshots`, we remove them, since - // they don't reference anything. - existing_snapshots.iter().for_each(|(path, _)| { - trash::delete(path).unwrap_or_else(|e| { - warn!("Failed to delete unreferenced example: {}", e); - }) - }); - - if snapshots_updated { - bail!("Some book snapshots were not consistent with the queries in the book and have been updated. Subsequent runs should pass."); - } Ok(()) } /// Snapshot the output of each example. -fn test_prql_examples() { +fn run_reference_prql() { glob!("prql/**/*.prql", |path| { let prql = fs::read_to_string(path).unwrap(); @@ -168,25 +147,20 @@ fn test_prql_examples() { } /// Snapshot the display trait output of each example. +// Currently not a separate test, see notes in caller. // // TODO: this involves writing out almost the same PRQL again โ€” instead we could // compare the output of Display to the auto-formatted source. But we need an // autoformatter for that (unless we want to raise on any non-matching input, // which seems very strict) -#[test] -fn test_display() -> Result<(), ErrorMessages> { - use prql_compiler::downcast; - collect_book_examples() - .map_err(downcast)? - .iter() - .try_for_each(|(path, example)| { - assert_snapshot!( - path.to_owned(), - prql_to_pl(example).and_then(pl_to_prql)?, - example - ); - Ok::<(), ErrorMessages>(()) - })?; +fn run_display_reference_prql() { + glob!("prql/**/*.prql", |path| { + let prql = fs::read_to_string(path).unwrap(); - Ok(()) + if prql.contains("skip_test") { + return; + } + + assert_display_snapshot!(prql_to_pl(&prql).and_then(pl_to_prql).unwrap()); + }); } diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap index 83e9f48a0e9e..b246de058091 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/cte-0.prql --- let newest_employees = ( from employees diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap index ac80804d08a1..692c476512cc 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/employees-0.prql --- from salaries group [emp_no] ( diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap index c5d5366f6306..665754bd3fb5 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/employees-1.prql --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap index d957c280a5c6..3823173006c7 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/employees-2.prql --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap index 9cc6115f24bd..611769e8f06d 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/employees-3.prql --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap new file mode 100644 index 000000000000..085bada98319 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/list-equivalence-0.prql +--- +from employees +select salary + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap new file mode 100644 index 000000000000..6ab6d90cdd10 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/list-equivalence-1.prql +--- +from employees +select [salary] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap index 3d298b6f9b55..5ba483c522d7 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/list-equivalence-2.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap index 254f07187889..c1c8e138f806 100644 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = salary + payroll_tax\nderive gross_cost = gross_salary + benefits_cost\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/list-equivalence-3.prql --- from employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap new file mode 100644 index 000000000000..930d29f6d477 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap @@ -0,0 +1,26 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/misc-0.prql +--- +let parts = ( + from seq_1_to_5 +) + + + +from pl = prospect_lists_prospects +filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" +join a = accounts [a.id == pl.related_id] +join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] +join ea = email_addresses [ea.id == er.email_address_id] +select ea.email_address +derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" +derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" +select [ + email_address, + stub, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap new file mode 100644 index 000000000000..d48e3fe1307a --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/misc-1.prql +--- +from club_ratings +filter rating != null +group year ( + derive [rating_norm = rating - ( average rating ) / ( stddev rating )] +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap new file mode 100644 index 000000000000..c4e1df527811 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap @@ -0,0 +1,32 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/variables-0.prql +--- +from employees +filter country == "USA" +derive [ + gross_salary = salary + payroll_tax, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average salary, + average gross_salary, + sum salary, + sum gross_salary, + average gross_cost, + sum_gross_cost = sum gross_cost, + ct = count, +] +) +sort sum_gross_cost +filter ct > 200 +take 20 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap new file mode 100644 index 000000000000..1f588bf0d309 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap @@ -0,0 +1,19 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/examples/variables-1.prql +--- +from employees +group [emp_no] ( + aggregate [emp_salary = average salary] +) +join titles [==emp_no] +group [title] ( + aggregate [avg_salary = average emp_salary] +) +select salary_k = avg_salary / 1000 +take 10 +derive salary = salary_k * 1000 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap new file mode 100644 index 000000000000..96d5d50a00e1 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/functional-lang-0.prql +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap new file mode 100644 index 000000000000..ae83420f23d3 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/functional-lang-1.prql +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap new file mode 100644 index 000000000000..f15a84e195b3 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/functional-lang-2.prql +--- +filter age > 50 ( + from employees +) +sort name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap new file mode 100644 index 000000000000..aa777d923706 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/functional-lang-3.prql +--- +sort name ( + filter age > 50 ( + from employees +) +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap new file mode 100644 index 000000000000..a7bd8bc3730a --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/name-resolving-0.prql +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap similarity index 56% rename from book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap index a9d9e5bada6d..6161fd5892e6 100644 --- a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [first_name, dept_id]\njoin d=departments [==dept_id]\nselect [first_name, d.title]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/internals/name-resolving-1.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap new file mode 100644 index 000000000000..bc40a390e21a --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap @@ -0,0 +1,32 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/introduction-0.prql +--- +from employees +filter start_date > @2021-01-01 +derive [ + gross_salary = salary + tax ?? 0, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average gross_salary, + sum_gross_cost = sum gross_cost, +] +) +filter sum_gross_cost > 100000 +derive id = f"{title}_{country}" +derive country_code = s"LEFT(country, 2)" +sort [ + sum_gross_cost, + -country, +] +take 1..20 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap new file mode 100644 index 000000000000..16833c5f8cfa --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/coalesce-0.prql +--- +from orders +derive amount ?? 0 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap new file mode 100644 index 000000000000..ca08e6d69631 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/dates-and-times-0.prql +--- +from employees +derive age_at_year_end = @2022-12-31 - dob + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap new file mode 100644 index 000000000000..07d9b568eac6 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/dates-and-times-1.prql +--- +from orders +derive should_have_shipped_today = order_time < @08:30 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap new file mode 100644 index 000000000000..6e0b688f7f7a --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/dates-and-times-2.prql +--- +from commits +derive first_prql_commit = @2020-01-01T13:19:55-0800 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap new file mode 100644 index 000000000000..5080f647a12c --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/dates-and-times-3.prql +--- +from projects +derive first_check_in = start + 10days + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap new file mode 100644 index 000000000000..587f75ff1bd2 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/distinct-0.prql +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap new file mode 100644 index 000000000000..d6bcee7acf86 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/distinct-1.prql +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap new file mode 100644 index 000000000000..4f2e5f381a88 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/distinct-2.prql +--- +from employees +group department ( + sort age + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap new file mode 100644 index 000000000000..2b8a822ba481 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/f-strings-0.prql +--- +from employees +select full_name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap new file mode 100644 index 000000000000..b61f8780aa34 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/f-strings-1.prql +--- +from web +select url = f"http{tls}://www.{domain}.{tld}/{page}" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap new file mode 100644 index 000000000000..016809741efe --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/null-0.prql +--- +from employees +filter first_name == null +filter null != last_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap index 2d5baa98ae2d..e20b2b97240c 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from events\nfilter (date | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/ranges-0.prql --- from events filter ( diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap new file mode 100644 index 000000000000..46ce8b767eb3 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/ranges-1.prql +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap new file mode 100644 index 000000000000..fa9c95fb9f4c --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-0.prql +--- +from my_table +select db_version = s"version()" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap new file mode 100644 index 000000000000..7de6990c149c --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-1.prql +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap index e28b7f46ed0a..8d39feed0f0d 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"\"\"({s.from_date}, {s.to_date})\n OVERLAPS\n ({de.from_date}, {de.to_date})\"\"\"\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-2.prql --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap index 2cb93849dda8..85661196009c 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-3.prql --- from s"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC" join s = s"SELECT * FROM salaries" [==id] diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap index 00c1d5e17349..d7482d2f4cfb 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-4.prql --- from employees derive [has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){2,}')"] diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap index 9bd3b0d3fe16..4313e1e554a7 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"{gross_salary} / 365\"\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-5.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap index 3dc30b6885ae..8ac94b9d968f 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"({gross_salary}) / 365\"\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/s-strings-6.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap new file mode 100644 index 000000000000..691cabab4a62 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap @@ -0,0 +1,20 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/standard-library-0.prql +--- +from employees +derive [ + gross_salary = ( + salary + payroll_tax + as int +), + gross_salary_rounded = ( + gross_salary + round 0 +), + time = s"NOW()", +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap new file mode 100644 index 000000000000..08b198a45ab3 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/strings-0.prql +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap new file mode 100644 index 000000000000..014e0927ce0e --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/strings-1.prql +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap new file mode 100644 index 000000000000..52b190fec22a --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/strings-2.prql +--- +from my_table +select x = '"hello world"' + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap new file mode 100644 index 000000000000..eddb87ee8834 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/strings-3.prql +--- +from my_table +select x = 'I said "hello world"!' + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap new file mode 100644 index 000000000000..5966be260e48 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/strings-4.prql +--- +from my_table +select x = 'I said """hello world"""!' + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap index 7618b9e71723..85bb6bac32b8 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/switch-0.prql --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap index f9ee3312b92b..dd4c64e0b6b0 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/switch-1.prql --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap new file mode 100644 index 000000000000..8d46fc69595c --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap @@ -0,0 +1,15 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/target-0.prql +--- +prql target:sql.postgres + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap new file mode 100644 index 000000000000..2719c8e16911 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap @@ -0,0 +1,15 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/target-1.prql +--- +prql target:sql.mssql + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap new file mode 100644 index 000000000000..5bf77265c6a4 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/language-features/target-2.prql +--- +prql version:^0.5 + + + +from employees + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap index e5bb0a64491b..bde459b05cf8 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/functions-0.prql --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap index ef971e8402bc..d8d3e0185fd9 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp lower:0 1600 sat_score),\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/functions-1.prql --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap index 2e8f243ea009..49560fe48496 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp lower:0 1600),\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/functions-2.prql --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap index bc1453813dc9..83e91977fe3f 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (temp_f | fahrenheit_to_celsius)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/functions-3.prql --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap index 3deae6fcab9c..8ed62cca5158 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/functions-4.prql --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap new file mode 100644 index 000000000000..7162e861b213 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/pipelines-0.prql +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap new file mode 100644 index 000000000000..f64f5d68dc56 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/pipelines-1.prql +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap index 5c74bd2eeb81..e3ff662251a8 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from e = employees\nderive gross_salary = (salary + payroll_tax)\nsort gross_salary\ntake 10\njoin d = department [==dept_no]\nselect [e.name, gross_salary, d.name]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/pipelines-2.prql --- from e = employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap new file mode 100644 index 000000000000..fbb8c9dfa00f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap @@ -0,0 +1,18 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/variables-0.prql +--- +let top_50 = ( + from employees + sort salary + take 50 + aggregate [total_salary = sum salary] +) + + + +from top_50 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap index dd72ddc9b4bb..f7a3cbcd9431 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "let grouping = s\"\"\"\n SELECT SUM(a)\n FROM tbl\n GROUP BY\n GROUPING SETS\n ((b, c, d), (d), (b, d))\n\"\"\"\n\nfrom grouping\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/queries/variables-1.prql --- let grouping = s" SELECT SUM(a) diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap index ee78d7a29c00..16788f8c5410 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter department == \"Product\"\nselect [first_name, last_name]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-0.prql --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap index ae9d7fcbb81c..7d3684118966 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees | filter department == \"Product\" | select [first_name, last_name]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-1.prql --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap index 0ef6f6c5ea4e..e12239744931 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-10.prql --- prql target:sql.postgres diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap new file mode 100644 index 000000000000..f719b0acbbd4 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-11.prql +--- +from `dir/*.parquet` + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap index 6be462d1cb08..79ec4c9aa74d 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-12.prql --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap new file mode 100644 index 000000000000..6316d2280516 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-13.prql +--- +from `music.albums` + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap new file mode 100644 index 000000000000..a38f2f750602 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-14.prql +--- +from employees +filter id == $1 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap index 7aa2caf4c217..34d44267ba17 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-15.prql --- from numbers select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap index a12652162d23..8c5b5825e8c4 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from numbers\nderive [x = 1, y = 2]\nderive [\n a = x,\n b = y\n]\nderive [\n c = a,\n d = b,\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-2.prql --- from numbers derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap new file mode 100644 index 000000000000..6820f7c5e628 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-3.prql +--- +from employees +select [first_name] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap new file mode 100644 index 000000000000..6e06fe3ee2e5 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-4.prql +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap index 027e1a5e000f..f3ebf960c4bf 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from foo\nselect [\n circumference = diameter * 3.14159,\n color,\n]\nfilter circumference > 10 and color != \"red\"\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-5.prql --- from foo select [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap new file mode 100644 index 000000000000..d6668fe305c7 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap @@ -0,0 +1,40 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-6.prql +--- +from employees +derive is_proximate = ( + distance + in 0..20 +) +derive ( + total_distance = sum distance +) +derive ( + min_capped_distance = min distance ?? 5 +) +derive travel_time = distance / 40 +derive ( + distance_rounded_2_dp = round 1 + 1 distance +) +derive [ + is_far = ( + distance + in 100.. +), + is_negative = ( + distance + in -100..0 +), + is_negative = ( + distance + in -100..0 +), + average_distance = average distance, +] +sort -distance +sort [-distance] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap index 81e0a3146955..29e0c6d26c1e 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-7.prql --- from employees group [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap new file mode 100644 index 000000000000..55a51e5d833f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-8.prql +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap index 19c4de64822f..9e5a61c3e446 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/syntax-9.prql --- prql target:sql.mysql diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap new file mode 100644 index 000000000000..89e3271c8316 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/aggregate-0.prql +--- +from employees +aggregate [ + average salary, + ct = count, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap index 81e0a3146955..bbf253ec6dd5 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/aggregate-1.prql --- from employees group [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap new file mode 100644 index 000000000000..21468ff11aeb --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/aggregate-2.prql +--- +from employees +derive [avg_sal = average salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap new file mode 100644 index 000000000000..821c0f010d36 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/append-0.prql +--- +from employees_1 +append employees_2 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap new file mode 100644 index 000000000000..2a61ec1251b1 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/append-1.prql +--- +from employees_1 +remove employees_2 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap new file mode 100644 index 000000000000..dddeb63b7c9f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/append-2.prql +--- +from employees_1 +intersect employees_2 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap new file mode 100644 index 000000000000..e90d9add3db4 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/derive-0.prql +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap index 3d298b6f9b55..f2b9dd7bd20d 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/derive-1.prql --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap new file mode 100644 index 000000000000..8a68bf997bd7 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/filter-0.prql +--- +from employees +filter age > 25 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap new file mode 100644 index 000000000000..1bc8cf6d4a34 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/filter-1.prql +--- +from employees +filter age > 25 or department != "IT" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap new file mode 100644 index 000000000000..ad800e09070f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/filter-2.prql +--- +from employees +filter ( + age + in 25..40 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap new file mode 100644 index 000000000000..0adcf6191d9e --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/from-0.prql +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap new file mode 100644 index 000000000000..b90898f6f93e --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/from-1.prql +--- +from e = employees +select e.first_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap index 6a730d3a1f7e..d86f2e1e86bb 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/from_text-0.prql --- from_text " a,b,c diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap index 6f9f848bbd6e..740349748e00 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/from_text-1.prql --- let temp_format_lookup = ( from_text format:csv " diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap new file mode 100644 index 000000000000..a0aaabe15cb7 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap @@ -0,0 +1,33 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/from_text-2.prql +--- +let x = ( + from_text format:json '{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}' +) + + + +let y = ( + from_text format:json ' + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +' +) + + + +from x +join y [==a] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap index 81e0a3146955..754f23c1d76e 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/group-0.prql --- from employees group [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap new file mode 100644 index 000000000000..f916e255f991 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/group-1.prql +--- +from employees +sort join_date +take 1 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap new file mode 100644 index 000000000000..6b2cb62586b3 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/group-2.prql +--- +from employees +group role ( + sort join_date + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap index 4d113382409a..0334411b6614 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\njoin side:left positions [employees.id==positions.employee_id]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/join-0.prql --- from employees join side:left positions [employees.id == positions.employee_id] diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap index b3e13a1d23f8..073e5b79b5ee 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\njoin side:left p=positions [employees.id==p.employee_id]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/join-1.prql --- from employees join side:left p = positions [employees.id == p.employee_id] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap new file mode 100644 index 000000000000..19b950c9d24b --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/join-2.prql +--- +from employees +join positions [==emp_no] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap new file mode 100644 index 000000000000..9841ec3d8249 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-0.prql +--- +from employees +select name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap index 57c345371217..1ecfbb0be8f6 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nselect [\n name = f\"{first_name} {last_name}\",\n age_eoy = dob - @2022-12-31,\n]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-1.prql --- from employees select [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap new file mode 100644 index 000000000000..522050c7dd99 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-2.prql +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap new file mode 100644 index 000000000000..d6596a9ce634 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-3.prql +--- +from e = employees +select [ + e.first_name, + e.last_name, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap index 6445588450d2..c8837e7a5780 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-4.prql --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap index 568bc821ba4f..ee470cf35cf6 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-5.prql --- from tracks select [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap new file mode 100644 index 000000000000..102555240bdb --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/select-6.prql +--- +from artists +derive nick = name +select not [artists.`*`] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap new file mode 100644 index 000000000000..91b36c10532f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-0.prql +--- +from employees +sort age + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap new file mode 100644 index 000000000000..d7f443472fc9 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-1.prql +--- +from employees +sort [-age] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap new file mode 100644 index 000000000000..1df292e0b57f --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-2.prql +--- +from employees +sort [ + age, + -tenure, + salary, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap new file mode 100644 index 000000000000..3ef53a4676e9 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-3.prql +--- +from employees +sort [s"substr({first_name}, 2, 5)"] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap index 51c71b587af5..01b5c740c41a 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nsort tenure\nderive name = f\"{first_name} {last_name}\"\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-4.prql --- from employees sort tenure diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap new file mode 100644 index 000000000000..52f805544586 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/sort-5.prql +--- +from employees +sort tenure +join locations [==employee_id] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap new file mode 100644 index 000000000000..7f798967b647 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/take-0.prql +--- +from employees +take 10 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap new file mode 100644 index 000000000000..4107c86bfd92 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/take-1.prql +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap index 08d6e23e2468..2366506585b0 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup employee_id (\n sort month\n window rolling:12 (\n derive [trail_12_m_comp = sum paycheck]\n )\n)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/window-0.prql --- from employees group employee_id ( diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap rename to book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap index c0663a94bc4a..afffeb8eb185 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap @@ -1,6 +1,7 @@ --- source: book/tests/snapshot.rs -expression: "from orders\nsort day\nwindow rows:-3..3 (\n derive [centered_weekly_average = average value]\n)\ngroup [order_month] (\n sort day\n window expanding:true (\n derive [monthly_running_total = sum value]\n )\n)\n" +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/window-1.prql --- from orders sort day diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap new file mode 100644 index 000000000000..3015829b90db --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/window-2.prql +--- +from employees +sort age +derive rnk = rank + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap new file mode 100644 index 000000000000..26a5eb5d9d46 --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/window-3.prql +--- +from employees +group department ( + sort age + derive rnk = rank +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap new file mode 100644 index 000000000000..be549656354d --- /dev/null +++ b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() +input_file: book/tests/prql/transforms/window-4.prql +--- +from employees +filter salary < ( average salary ) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap deleted file mode 100644 index 8566dfaeb2b2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect salary\n" ---- -from employees -select salary - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap deleted file mode 100644 index 055af64b363a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect [salary]\n" ---- -from employees -select [salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap deleted file mode 100644 index 63b13a31ec56..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap +++ /dev/null @@ -1,25 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" ---- -let parts = ( - from seq_1_to_5 -) - - - -from pl = prospect_lists_prospects -filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" -join a = accounts [a.id == pl.related_id] -join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] -join ea = email_addresses [ea.id == er.email_address_id] -select ea.email_address -derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" -derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" -select [ - email_address, - stub, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap deleted file mode 100644 index 50dcca896ea5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from club_ratings\nfilter rating != null\n# TODO: this is real ugly. `average rating` should not require parenthesis\n# TODO: why cannot we put comments in group's pipeline?\ngroup year (\n derive [rating_norm = rating - (average rating) / (stddev rating)]\n)\n" ---- -from club_ratings -filter rating != null -group year ( - derive [rating_norm = rating - ( average rating ) / ( stddev rating )] -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap deleted file mode 100644 index 4b1f4fce84c1..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter country == \"USA\" # Each line transforms the previous result.\nderive [ # This adds columns / variables.\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost # Variables can use other variables.\n]\nfilter gross_cost > 0\ngroup [title, country] ( # For each group use a nested pipeline\n aggregate [ # Aggregate each group to a single row\n average salary,\n average gross_salary,\n sum salary,\n sum gross_salary,\n average gross_cost,\n sum_gross_cost = sum gross_cost,\n ct = count,\n ]\n)\nsort sum_gross_cost\nfilter ct > 200\ntake 20\n" ---- -from employees -filter country == "USA" -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average salary, - average gross_salary, - sum salary, - sum gross_salary, - average gross_cost, - sum_gross_cost = sum gross_cost, - ct = count, -] -) -sort sum_gross_cost -filter ct > 200 -take 20 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap deleted file mode 100644 index cfb45e96a801..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup [emp_no] (\n aggregate [\n emp_salary = average salary # average salary resolves to \"AVG(salary)\" (from stdlib)\n ]\n)\njoin titles [==emp_no]\ngroup [title] (\n aggregate [\n avg_salary = average emp_salary\n ]\n)\nselect salary_k = avg_salary / 1000 # avg_salary should resolve to \"AVG(emp_salary)\"\ntake 10 # induces new SELECT\nderive salary = salary_k * 1000 # salary_k should not resolve to \"avg_salary / 1000\"\n" ---- -from employees -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join titles [==emp_no] -group [title] ( - aggregate [avg_salary = average emp_salary] -) -select salary_k = avg_salary / 1000 -take 10 -derive salary = salary_k * 1000 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap deleted file mode 100644 index 1bd2d905e16d..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter age > 50\nsort name\n" ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap deleted file mode 100644 index da4b761a9e4b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees | filter age > 50 | sort name\n" ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap deleted file mode 100644 index 7da897d0dd14..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "filter age > 50 (from employees) | sort name\n" ---- -filter age > 50 ( - from employees -) -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap deleted file mode 100644 index 045c663815a8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "sort name (filter age > 50 (from employees))\n" ---- -sort name ( - filter age > 50 ( - from employees -) -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap deleted file mode 100644 index 96f55b8ab057..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" ---- -from employees -filter start_date > @2021-01-01 -derive [ - gross_salary = salary + tax ?? 0, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average gross_salary, - sum_gross_cost = sum gross_cost, -] -) -filter sum_gross_cost > 100000 -derive id = f"{title}_{country}" -derive country_code = s"LEFT(country, 2)" -sort [ - sum_gross_cost, - -country, -] -take 1..20 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap deleted file mode 100644 index 24ff749cfbc8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nderive amount ?? 0\n" ---- -from orders -derive amount ?? 0 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap deleted file mode 100644 index acb71c71fc9a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive age_at_year_end = (@2022-12-31 - dob)\n" ---- -from employees -derive age_at_year_end = @2022-12-31 - dob - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap deleted file mode 100644 index fd2fe52b3f6c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nderive should_have_shipped_today = (order_time < @08:30)\n" ---- -from orders -derive should_have_shipped_today = order_time < @08:30 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap deleted file mode 100644 index 1507a39b0252..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-0800\n" ---- -from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap deleted file mode 100644 index 70ac66f365a2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from projects\nderive first_check_in = start + 10days\n" ---- -from projects -derive first_check_in = start + 10days - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap deleted file mode 100644 index 7929401e23b6..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect department\ngroup department (\n take 1\n)\n" ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap deleted file mode 100644 index 22ba087f087c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect department\ngroup department (take 1)\n" ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap deleted file mode 100644 index ceb0035e6601..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "# youngest employee from each department\nfrom employees\ngroup department (\n sort age\n take 1\n)\n" ---- -from employees -group department ( - sort age - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap deleted file mode 100644 index 5f490aa52f00..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect full_name = f\"{first_name} {last_name}\"\n" ---- -from employees -select full_name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap deleted file mode 100644 index f00e2becbab2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from web\nselect url = f\"http{tls}://www.{domain}.{tld}/{page}\"\n" ---- -from web -select url = f"http{tls}://www.{domain}.{tld}/{page}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap deleted file mode 100644 index 73594522238f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter first_name == null\nfilter null != last_name\n" ---- -from employees -filter first_name == null -filter null != last_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap deleted file mode 100644 index b68c1920a669..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap deleted file mode 100644 index 12abfcc2518c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect db_version = s\"version()\"\n" ---- -from my_table -select db_version = s"version()" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap deleted file mode 100644 index c57ed2561d58..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\naggregate [average salary]\n" ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap deleted file mode 100644 index 011d5f416c47..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" ---- -from employees -derive [ - gross_salary = ( - salary + payroll_tax - as int -), - gross_salary_rounded = ( - gross_salary - round 0 -), - time = s"NOW()", -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap deleted file mode 100644 index 6a1d79036036..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"hello world\"\n" ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap deleted file mode 100644 index 2da7a07937de..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = 'hello world'\n" ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap deleted file mode 100644 index 8d79cd8cedbc..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = '\"hello world\"'\n" ---- -from my_table -select x = '"hello world"' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap deleted file mode 100644 index a681bc62a036..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\"\"I said \"hello world\"!\"\"\"\n" ---- -from my_table -select x = 'I said "hello world"!' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap deleted file mode 100644 index 0bae3f836774..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\"\"\"\"I said \"\"\"hello world\"\"\"!\"\"\"\"\"\n" ---- -from my_table -select x = 'I said """hello world"""!' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap deleted file mode 100644 index b22539422ae4..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" ---- -prql target:sql.postgres - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap deleted file mode 100644 index ed7e10fd7388..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" ---- -prql target:sql.mssql - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap deleted file mode 100644 index b05787ed8bae..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql version:\"0.5\"\n\nfrom employees\n" ---- -prql version:^0.5 - - - -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap deleted file mode 100644 index 8ef6dce0bb66..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n" ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap deleted file mode 100644 index b2b18409f03a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = (salary + payroll_tax)\n" ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap deleted file mode 100644 index 3c4edace1010..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" ---- -let top_50 = ( - from employees - sort salary - take 50 - aggregate [total_salary = sum salary] -) - - - -from top_50 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap deleted file mode 100644 index acd1651bdbb9..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from `dir/*.parquet`\n" ---- -from `dir/*.parquet` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap deleted file mode 100644 index fc9310bcceea..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from `music.albums`\n" ---- -from `music.albums` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap deleted file mode 100644 index 429e57d0faf3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter id == $1\n" ---- -from employees -filter id == $1 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap deleted file mode 100644 index 4077d71aaa9b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect [first_name]\n" ---- -from employees -select [first_name] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap deleted file mode 100644 index b9f326d968cc..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap +++ /dev/null @@ -1,39 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" ---- -from employees -derive is_proximate = ( - distance - in 0..20 -) -derive ( - total_distance = sum distance -) -derive ( - min_capped_distance = min distance ?? 5 -) -derive travel_time = distance / 40 -derive ( - distance_rounded_2_dp = round 1 + 1 distance -) -derive [ - is_far = ( - distance - in 100.. -), - is_negative = ( - distance - in -100..0 -), - is_negative = ( - distance - in -100..0 -), - average_distance = average distance, -] -sort -distance -sort [-distance] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap deleted file mode 100644 index 4f94033b1f86..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap deleted file mode 100644 index 1c202ec4ba25..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\naggregate [\n average salary,\n ct = count\n]\n" ---- -from employees -aggregate [ - average salary, - ct = count, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap deleted file mode 100644 index 9b49b51df2a5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [avg_sal = average salary]\n" ---- -from employees -derive [avg_sal = average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap deleted file mode 100644 index cbbd0478001b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nappend employees_2\n" ---- -from employees_1 -append employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap deleted file mode 100644 index e2b9a1338479..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nremove employees_2\n" ---- -from employees_1 -remove employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap deleted file mode 100644 index 1971d287b890..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nintersect employees_2\n" ---- -from employees_1 -intersect employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap deleted file mode 100644 index 183b59f98112..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = salary + payroll_tax\n" ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap deleted file mode 100644 index bd5e2c425e25..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter age > 25\n" ---- -from employees -filter age > 25 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap deleted file mode 100644 index a6cb5b5b569e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter (age > 25 or department != \"IT\")\n" ---- -from employees -filter age > 25 or department != "IT" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap deleted file mode 100644 index d3b04cd4de31..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter (age | in 25..40)\n" ---- -from employees -filter ( - age - in 25..40 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap deleted file mode 100644 index 8ef6dce0bb66..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n" ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap deleted file mode 100644 index ef1312a86941..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e = employees\nselect e.first_name\n" ---- -from e = employees -select e.first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap deleted file mode 100644 index da17c3b1fe6f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" ---- -let x = ( - from_text format:json '{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}' -) - - - -let y = ( - from_text format:json ' - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -' -) - - - -from x -join y [==a] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap deleted file mode 100644 index 2517396a1418..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort join_date\ntake 1\n" ---- -from employees -sort join_date -take 1 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap deleted file mode 100644 index 11467687bbbb..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup role (\n sort join_date # taken from above\n take 1\n)\n" ---- -from employees -group role ( - sort join_date - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap deleted file mode 100644 index ba833fa01b02..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\njoin positions [==emp_no]\n" ---- -from employees -join positions [==emp_no] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap deleted file mode 100644 index ef3e65965333..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect name = f\"{first_name} {last_name}\"\n" ---- -from employees -select name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap deleted file mode 100644 index 059b92276754..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e=employees\nselect [e.first_name, e.last_name]\n" ---- -from e = employees -select [ - e.first_name, - e.last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap deleted file mode 100644 index 19b65db61c48..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from artists\nderive nick = name\nselect ![artists.*]\n" ---- -from artists -derive nick = name -select not [artists.`*`] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap deleted file mode 100644 index cb41ef4b5ddb..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort age\n" ---- -from employees -sort age - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap deleted file mode 100644 index 12203dcc78d3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [-age]\n" ---- -from employees -sort [-age] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap deleted file mode 100644 index 23c2050900c8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [age, -tenure, +salary]\n" ---- -from employees -sort [ - age, - -tenure, - salary, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap deleted file mode 100644 index 01b0d75eb4e3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" ---- -from employees -sort [s"substr({first_name}, 2, 5)"] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap deleted file mode 100644 index 405c461df7e4..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort tenure\njoin locations [==employee_id]\n" ---- -from employees -sort tenure -join locations [==employee_id] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap deleted file mode 100644 index 4c39e0cddcea..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ntake 10\n" ---- -from employees -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap deleted file mode 100644 index b68c1920a669..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap deleted file mode 100644 index dc3037c993b3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort age\nderive rnk = rank\n" ---- -from employees -sort age -derive rnk = rank - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap deleted file mode 100644 index b71455102a11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup department (\n sort age\n derive rnk = rank\n)\n" ---- -from employees -group department ( - sort age - derive rnk = rank -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap deleted file mode 100644 index 9e104fbe34a9..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter salary < (average salary)\n" ---- -from employees -filter salary < ( average salary ) - - - From d878788fc84cef86d42f958039451205b8204123 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 19:47:37 -0800 Subject: [PATCH 025/184] build: Disable prql-elixir on Mac (#1902) * build: Disable prql-elixir on Mac A temporary pause on building `prql-elixir` on Mac, as it's causing some build caching issues, as described in the Readme There are lots of ways to re-enable when we're ready. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .cargo/config.toml | 7 ---- .github/workflows/test-elixir.yaml | 3 +- Taskfile.yml | 40 +++++++--------------- book/book.toml | 5 +-- prql-compiler/Cargo.toml | 2 +- prql-elixir/README.md | 31 +++++++++++++++++ prql-elixir/native/prql/.cargo/config.toml | 3 ++ prql-elixir/native/prql/Cargo.toml | 6 ++-- prql-elixir/native/prql/src/lib.rs | 2 ++ 9 files changed, 57 insertions(+), 42 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 22fe7e245bd6..4ec2f3b86203 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,9 +1,2 @@ [target.wasm32-unknown-unknown] runner = 'wasm-bindgen-test-runner' - -[target.'cfg(target_os = "macos")'] -# Required for prql-elixir on Mac -rustflags = [ - "-C", "link-arg=-undefined", - "-C", "link-arg=dynamic_lookup", -] diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index 5c091d8e3543..31d4c9caaea9 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -25,7 +25,8 @@ jobs: test: strategy: matrix: - os: [ubuntu-latest, windows-latest, macos-latest] + # Currently disabling mac tests, see prql-elixir/readme.md for more details. + os: [ubuntu-latest, windows-latest] otp: ["25.1.2"] elixir: ["1.14.2"] runs-on: ${{matrix.os}} diff --git a/Taskfile.yml b/Taskfile.yml index bcdf31a59a4b..ec901be0fa55 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -64,7 +64,7 @@ tasks: # Can't install atm with `--locked` - cargo install mdbook-footnote - cmd: | - [ "$(which default-target)" ] || echo "๐Ÿ”ด Can't find a binary that cargo just installed. Is the cargo bin path (generally at ~/.cargo/bin) on the \$PATH?" + [ "$(which cargo-insta)" ] || echo "๐Ÿ”ด Can't find a binary that cargo just installed. Is the cargo bin path (generally at ~/.cargo/bin) on the \$PATH?" silent: true install-maturin: @@ -151,17 +151,9 @@ tasks: Build everything. Running this isn't required when developing; it's for caching or as a reference. - vars: - default_target: - sh: default-target - targets: | - {{ .default_target }} - wasm32-unknown-unknown cmds: - - | - {{ range ( .targets | trim | splitLines ) -}} - cargo build --all-targets --target={{.}} - {{ end -}} + - cargo build --all-targets --target=wasm32-unknown-unknown + - cargo build --all-targets - task: build-web test-all: @@ -177,14 +169,10 @@ tasks: - task: test-rust - task: build-all - task: test-js - - task: test-elixir - pre-commit run -a test-rust: desc: Test all rust code, accepting snapshots. - vars: - default_target: - sh: default-target # Commenting out the ability to watch, since Task seems to trip over itself, # starting a new process before the old one has finished when a process # changes output files. @@ -212,13 +200,11 @@ tasks: # tests to extract them, which include compiling prql-compiler, c) not # fail other compilation steps if they can't be extracted. - cargo insta test --accept -p mdbook-prql --test snapshot - --target={{.default_target}} # Only delete unreferenced snapshots on the default target โ€” lots are # excluded under wasm. Note that this will also over-delete on Windows. # Note that we need to pass the target explicitly to manage # https://github.com/rust-lang/cargo/issues/8899 - - cargo insta test --accept --target={{.default_target}} - --unreferenced=auto + - cargo insta test --accept --unreferenced=auto - cargo insta test --accept --target=wasm32-unknown-unknown # We build the book too, because that acts as a test - cd book && mdbook build @@ -248,7 +234,6 @@ tasks: - "prql-compiler/**/*.snap" cmds: - cargo insta test --accept -p prql-compiler --lib - --target=$(default-target) build-web: desc: Build the website, including the book & playground. @@ -276,14 +261,15 @@ tasks: - npm run build - npm cit - test-elixir: - dir: prql-elixir - cmds: - # We could move this line into an `install` task - - mix local.hex --force - - mix deps.get --force - - mix compile - - mix test + # Currently disabled; see prql-elixir/README.md for details + # test-elixir: + # dir: prql-elixir + # cmds: + # # We could move this line into an `install` task + # - mix local.hex --force + # - mix deps.get --force + # - mix compile + # - mix test run-website: desc: Build & serve the static website. diff --git a/book/book.toml b/book/book.toml index f503dc2bb7a9..6849dde897c5 100644 --- a/book/book.toml +++ b/book/book.toml @@ -13,10 +13,7 @@ git-repository-url = "https://github.com/PRQL/prql" # This is required because mdbook-prql isn't necessarily installed; maybe # there's a better way. # -# We put the target directory in `target-book` because of -# https://github.com/rust-lang/cargo/issues/8899, as an alternative to requiring -# `default-target` to be installed. -command = "cargo run --bin mdbook-prql --target-dir=target-book" +command = "cargo run --bin mdbook-prql" [preprocessor.admonish] assets_version = "2.0.0" # do not edit: managed by `mdbook-admonish install` diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index 296cf5b954fe..cd74ecc67c24 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -40,9 +40,9 @@ insta = {version = "1.28", features = ["colors", "glob", "yaml"]} # For integration tests [target.'cfg(not(target_family="wasm"))'.dev-dependencies] chrono = "0.4" -pretty_assertions = "1.3.0" criterion = "0.4.0" postgres = "0.19.3" +pretty_assertions = "1.3.0" rusqlite = {version = "0.28.0", features = ["bundled", "csvtab"]} # Re-enable on windows when duckdb supports it diff --git a/prql-elixir/README.md b/prql-elixir/README.md index 2ff3e499141c..ed30ffa0ab2e 100644 --- a/prql-elixir/README.md +++ b/prql-elixir/README.md @@ -38,3 +38,34 @@ crate from this repo: Future work includes publishing pre-compiled artifacts, so Elixir projects can run PRQL without needing a Rust toolchain. + +## Mac + +We currently don't enable compilation for Mac. This is possible to enable, but +causes some issues with cargo's compilation cache. Briefly: it requires +`RUST_FLAGS` to be set, and because of + & +, any compilation of a different +target will bust the cache. + +The possible future workarounds include: + +- Passing `--target=aarch64-apple-darwin` to every cargo call, which is + inconvenient and can be difficult in some situations; e.g. Rust Analyzer. This + disables passing `RUST_FLAGS` (I'm actually unclear why `prql-elixir` builds + successfully in that case...) +- Directing other cargo calls to different paths, such as `/target-ra` for Rust + Analyzer and `/target-book` for the book building. But one `cargo build` from + the terminal without either the `target` or `target_dir` specified will bust + the cache! +- Never compiling for other targets. But our standard tests run for + `--target=wasm32-unknown-unknown`, so this requires refraining from using + them. +- Removing `prql-elixir` from our workspace, so that `cargo` commands in the + PRQL workspace don't require rust flags. This would work well, but means we + need separate test coverage for this crate, which adds some weight to the + tests. + +If `prql-elixir` becomes more used (for example, we start publishing to Hex, or +Mac developers want to work on it), then we can re-enable and deal with the +caching issues. We can also re-enable them if the `cargo` issue is resolved. diff --git a/prql-elixir/native/prql/.cargo/config.toml b/prql-elixir/native/prql/.cargo/config.toml index 20f03f3d8054..a0a666544142 100644 --- a/prql-elixir/native/prql/.cargo/config.toml +++ b/prql-elixir/native/prql/.cargo/config.toml @@ -1,3 +1,6 @@ +# Note that this doesn't apply when compiling from the workspace root. Because +# we're not currently compiling for Mac, it's also impotent for now. + [target.'cfg(target_os = "macos")'] rustflags = [ "-C", "link-arg=-undefined", diff --git a/prql-elixir/native/prql/Cargo.toml b/prql-elixir/native/prql/Cargo.toml index 51fdb36cc87c..a39a9eee25db 100644 --- a/prql-elixir/native/prql/Cargo.toml +++ b/prql-elixir/native/prql/Cargo.toml @@ -16,6 +16,8 @@ name = "prql" path = "src/lib.rs" [dependencies] -prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.2" } -[target.'cfg(not(any(target_family="wasm")))'.dependencies] +prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.2"} + +# See Readme for details on Mac +[target.'cfg(not(any(target_family="wasm", target_os = "macos")))'.dependencies] rustler = "0.27.0" diff --git a/prql-elixir/native/prql/src/lib.rs b/prql-elixir/native/prql/src/lib.rs index 8ff3aeea7303..2a5967eb9ba1 100644 --- a/prql-elixir/native/prql/src/lib.rs +++ b/prql-elixir/native/prql/src/lib.rs @@ -1,3 +1,5 @@ +// See Readme for more information on Mac compiling +#![cfg(not(target_os = "macos"))] // These bindings aren't relevant on wasm #![cfg(not(target_family = "wasm"))] // TODO: unclear why we need this `allow`; it's required in `CompileOptions`, From c186b135ce607fe851e026c037a7ef12cdd228f4 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 19 Feb 2023 20:34:23 -0800 Subject: [PATCH 026/184] test: Refactor book snapshot tests (#1904) * test: Refactor book snapshot tests Re-reverting #1900 --- book/tests/snapshot.rs | 200 +++++++++++------- ...rql@examples__list-equivalence-0.prql.snap | 10 - ...rql@examples__list-equivalence-1.prql.snap | 10 - ..._reference_prql@examples__misc-0.prql.snap | 26 --- ..._reference_prql@examples__misc-1.prql.snap | 13 -- ...rence_prql@examples__variables-0.prql.snap | 32 --- ...rence_prql@examples__variables-1.prql.snap | 19 -- ...rql@internals__functional-lang-0.prql.snap | 11 - ...rql@internals__functional-lang-1.prql.snap | 11 - ...rql@internals__functional-lang-2.prql.snap | 12 -- ...rql@internals__functional-lang-3.prql.snap | 13 -- ...prql@internals__name-resolving-0.prql.snap | 10 - ...ay_reference_prql@introduction-0.prql.snap | 32 --- ...ql@language-features__coalesce-0.prql.snap | 10 - ...uage-features__dates-and-times-0.prql.snap | 10 - ...uage-features__dates-and-times-1.prql.snap | 10 - ...uage-features__dates-and-times-2.prql.snap | 10 - ...uage-features__dates-and-times-3.prql.snap | 10 - ...ql@language-features__distinct-0.prql.snap | 13 -- ...ql@language-features__distinct-1.prql.snap | 13 -- ...ql@language-features__distinct-2.prql.snap | 13 -- ...l@language-features__f-strings-0.prql.snap | 10 - ...l@language-features__f-strings-1.prql.snap | 10 - ...e_prql@language-features__null-0.prql.snap | 11 - ...prql@language-features__ranges-1.prql.snap | 14 -- ...l@language-features__s-strings-0.prql.snap | 10 - ...l@language-features__s-strings-1.prql.snap | 10 - ...age-features__standard-library-0.prql.snap | 20 -- ...rql@language-features__strings-0.prql.snap | 10 - ...rql@language-features__strings-1.prql.snap | 10 - ...rql@language-features__strings-2.prql.snap | 10 - ...rql@language-features__strings-3.prql.snap | 10 - ...rql@language-features__strings-4.prql.snap | 10 - ...prql@language-features__target-0.prql.snap | 15 -- ...prql@language-features__target-1.prql.snap | 15 -- ...prql@language-features__target-2.prql.snap | 13 -- ...erence_prql@queries__pipelines-0.prql.snap | 9 - ...erence_prql@queries__pipelines-1.prql.snap | 10 - ...erence_prql@queries__variables-0.prql.snap | 18 -- ...display_reference_prql@syntax-11.prql.snap | 9 - ...display_reference_prql@syntax-13.prql.snap | 9 - ...display_reference_prql@syntax-14.prql.snap | 10 - ..._display_reference_prql@syntax-3.prql.snap | 10 - ..._display_reference_prql@syntax-4.prql.snap | 10 - ..._display_reference_prql@syntax-6.prql.snap | 40 ---- ..._display_reference_prql@syntax-8.prql.snap | 10 - ...nce_prql@transforms__aggregate-0.prql.snap | 13 -- ...nce_prql@transforms__aggregate-2.prql.snap | 10 - ...erence_prql@transforms__append-0.prql.snap | 10 - ...erence_prql@transforms__append-1.prql.snap | 10 - ...erence_prql@transforms__append-2.prql.snap | 10 - ...erence_prql@transforms__derive-0.prql.snap | 10 - ...erence_prql@transforms__filter-0.prql.snap | 10 - ...erence_prql@transforms__filter-1.prql.snap | 10 - ...erence_prql@transforms__filter-2.prql.snap | 13 -- ...eference_prql@transforms__from-0.prql.snap | 9 - ...eference_prql@transforms__from-1.prql.snap | 10 - ...nce_prql@transforms__from_text-2.prql.snap | 33 --- ...ference_prql@transforms__group-1.prql.snap | 11 - ...ference_prql@transforms__group-2.prql.snap | 13 -- ...eference_prql@transforms__join-2.prql.snap | 10 - ...erence_prql@transforms__select-0.prql.snap | 10 - ...erence_prql@transforms__select-2.prql.snap | 10 - ...erence_prql@transforms__select-3.prql.snap | 13 -- ...erence_prql@transforms__select-6.prql.snap | 11 - ...eference_prql@transforms__sort-0.prql.snap | 10 - ...eference_prql@transforms__sort-1.prql.snap | 10 - ...eference_prql@transforms__sort-2.prql.snap | 14 -- ...eference_prql@transforms__sort-3.prql.snap | 10 - ...eference_prql@transforms__sort-5.prql.snap | 11 - ...eference_prql@transforms__take-0.prql.snap | 10 - ...eference_prql@transforms__take-1.prql.snap | 14 -- ...erence_prql@transforms__window-2.prql.snap | 11 - ...erence_prql@transforms__window-3.prql.snap | 13 -- ...erence_prql@transforms__window-4.prql.snap | 10 - ...t__tests__prql__examples__cte-0.prql.snap} | 3 +- ...ts__prql__examples__employees-0.prql.snap} | 3 +- ...ts__prql__examples__employees-1.prql.snap} | 3 +- ...ts__prql__examples__employees-2.prql.snap} | 3 +- ...ts__prql__examples__employees-3.prql.snap} | 3 +- ...ql__examples__list-equivalence-0.prql.snap | 9 + ...ql__examples__list-equivalence-1.prql.snap | 9 + ...l__examples__list-equivalence-2.prql.snap} | 3 +- ...l__examples__list-equivalence-3.prql.snap} | 3 +- ...t__tests__prql__examples__misc-0.prql.snap | 25 +++ ...t__tests__prql__examples__misc-1.prql.snap | 12 ++ ...sts__prql__examples__variables-0.prql.snap | 31 +++ ...sts__prql__examples__variables-1.prql.snap | 18 ++ ...ql__internals__functional-lang-0.prql.snap | 10 + ...ql__internals__functional-lang-1.prql.snap | 10 + ...ql__internals__functional-lang-2.prql.snap | 11 + ...ql__internals__functional-lang-3.prql.snap | 12 ++ ...rql__internals__name-resolving-0.prql.snap | 9 + ...ql__internals__name-resolving-1.prql.snap} | 3 +- ...hot__tests__prql__introduction-0.prql.snap | 31 +++ ...l__language-features__coalesce-0.prql.snap | 9 + ...uage-features__dates-and-times-0.prql.snap | 9 + ...uage-features__dates-and-times-1.prql.snap | 9 + ...uage-features__dates-and-times-2.prql.snap | 9 + ...uage-features__dates-and-times-3.prql.snap | 9 + ...l__language-features__distinct-0.prql.snap | 12 ++ ...l__language-features__distinct-1.prql.snap | 12 ++ ...l__language-features__distinct-2.prql.snap | 12 ++ ...__language-features__f-strings-0.prql.snap | 9 + ...__language-features__f-strings-1.prql.snap | 9 + ..._prql__language-features__null-0.prql.snap | 10 + ...ql__language-features__ranges-0.prql.snap} | 3 +- ...rql__language-features__ranges-1.prql.snap | 13 ++ ...__language-features__s-strings-0.prql.snap | 9 + ...__language-features__s-strings-1.prql.snap | 9 + ..._language-features__s-strings-2.prql.snap} | 3 +- ..._language-features__s-strings-3.prql.snap} | 3 +- ..._language-features__s-strings-4.prql.snap} | 3 +- ..._language-features__s-strings-5.prql.snap} | 3 +- ..._language-features__s-strings-6.prql.snap} | 3 +- ...age-features__standard-library-0.prql.snap | 19 ++ ...ql__language-features__strings-0.prql.snap | 9 + ...ql__language-features__strings-1.prql.snap | 9 + ...ql__language-features__strings-2.prql.snap | 9 + ...ql__language-features__strings-3.prql.snap | 9 + ...ql__language-features__strings-4.prql.snap | 9 + ...ql__language-features__switch-0.prql.snap} | 3 +- ...ql__language-features__switch-1.prql.snap} | 3 +- ...rql__language-features__target-0.prql.snap | 14 ++ ...rql__language-features__target-1.prql.snap | 14 ++ ...rql__language-features__target-2.prql.snap | 12 ++ ...sts__prql__queries__functions-0.prql.snap} | 3 +- ...sts__prql__queries__functions-1.prql.snap} | 3 +- ...sts__prql__queries__functions-2.prql.snap} | 3 +- ...sts__prql__queries__functions-3.prql.snap} | 3 +- ...sts__prql__queries__functions-4.prql.snap} | 3 +- ...ests__prql__queries__pipelines-0.prql.snap | 8 + ...ests__prql__queries__pipelines-1.prql.snap | 9 + ...sts__prql__queries__pipelines-2.prql.snap} | 3 +- ...ests__prql__queries__variables-0.prql.snap | 17 ++ ...sts__prql__queries__variables-1.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-0.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-1.prql.snap} | 3 +- ...napshot__tests__prql__syntax-10.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-11.prql.snap | 8 + ...napshot__tests__prql__syntax-12.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-13.prql.snap | 8 + ...snapshot__tests__prql__syntax-14.prql.snap | 9 + ...napshot__tests__prql__syntax-15.prql.snap} | 3 +- ...snapshot__tests__prql__syntax-2.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-3.prql.snap | 9 + .../snapshot__tests__prql__syntax-4.prql.snap | 9 + ...snapshot__tests__prql__syntax-5.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-6.prql.snap | 39 ++++ ...snapshot__tests__prql__syntax-7.prql.snap} | 3 +- .../snapshot__tests__prql__syntax-8.prql.snap | 9 + ...snapshot__tests__prql__syntax-9.prql.snap} | 3 +- ...s__prql__transforms__aggregate-0.prql.snap | 12 ++ ...__prql__transforms__aggregate-1.prql.snap} | 3 +- ...s__prql__transforms__aggregate-2.prql.snap | 9 + ...ests__prql__transforms__append-0.prql.snap | 9 + ...ests__prql__transforms__append-1.prql.snap | 9 + ...ests__prql__transforms__append-2.prql.snap | 9 + ...ests__prql__transforms__derive-0.prql.snap | 9 + ...sts__prql__transforms__derive-1.prql.snap} | 3 +- ...ests__prql__transforms__filter-0.prql.snap | 9 + ...ests__prql__transforms__filter-1.prql.snap | 9 + ...ests__prql__transforms__filter-2.prql.snap | 12 ++ ..._tests__prql__transforms__from-0.prql.snap | 8 + ..._tests__prql__transforms__from-1.prql.snap | 9 + ...__prql__transforms__from_text-0.prql.snap} | 3 +- ...__prql__transforms__from_text-1.prql.snap} | 3 +- ...s__prql__transforms__from_text-2.prql.snap | 32 +++ ...ests__prql__transforms__group-0.prql.snap} | 3 +- ...tests__prql__transforms__group-1.prql.snap | 10 + ...tests__prql__transforms__group-2.prql.snap | 12 ++ ...tests__prql__transforms__join-0.prql.snap} | 3 +- ...tests__prql__transforms__join-1.prql.snap} | 3 +- ..._tests__prql__transforms__join-2.prql.snap | 9 + ...ests__prql__transforms__select-0.prql.snap | 9 + ...sts__prql__transforms__select-1.prql.snap} | 3 +- ...ests__prql__transforms__select-2.prql.snap | 9 + ...ests__prql__transforms__select-3.prql.snap | 12 ++ ...sts__prql__transforms__select-4.prql.snap} | 3 +- ...sts__prql__transforms__select-5.prql.snap} | 3 +- ...ests__prql__transforms__select-6.prql.snap | 10 + ..._tests__prql__transforms__sort-0.prql.snap | 9 + ..._tests__prql__transforms__sort-1.prql.snap | 9 + ..._tests__prql__transforms__sort-2.prql.snap | 13 ++ ..._tests__prql__transforms__sort-3.prql.snap | 9 + ...tests__prql__transforms__sort-4.prql.snap} | 3 +- ..._tests__prql__transforms__sort-5.prql.snap | 10 + ..._tests__prql__transforms__take-0.prql.snap | 9 + ..._tests__prql__transforms__take-1.prql.snap | 13 ++ ...sts__prql__transforms__window-0.prql.snap} | 3 +- ...sts__prql__transforms__window-1.prql.snap} | 3 +- ...ests__prql__transforms__window-2.prql.snap | 10 + ...ests__prql__transforms__window-3.prql.snap | 12 ++ ...ests__prql__transforms__window-4.prql.snap | 9 + 194 files changed, 1029 insertions(+), 1112 deletions(-) delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__cte-0.prql.snap => snapshot__tests__prql__examples__cte-0.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-0.prql.snap => snapshot__tests__prql__examples__employees-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-1.prql.snap => snapshot__tests__prql__examples__employees-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-2.prql.snap => snapshot__tests__prql__examples__employees-2.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__employees-3.prql.snap => snapshot__tests__prql__examples__employees-3.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap => snapshot__tests__prql__examples__list-equivalence-2.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap => snapshot__tests__prql__examples__list-equivalence-3.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap => snapshot__tests__prql__internals__name-resolving-1.prql.snap} (56%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap => snapshot__tests__prql__language-features__ranges-0.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap => snapshot__tests__prql__language-features__s-strings-2.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap => snapshot__tests__prql__language-features__s-strings-3.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap => snapshot__tests__prql__language-features__s-strings-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap => snapshot__tests__prql__language-features__s-strings-5.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap => snapshot__tests__prql__language-features__s-strings-6.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__switch-0.prql.snap => snapshot__tests__prql__language-features__switch-0.prql.snap} (53%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@language-features__switch-1.prql.snap => snapshot__tests__prql__language-features__switch-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-0.prql.snap => snapshot__tests__prql__queries__functions-0.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-1.prql.snap => snapshot__tests__prql__queries__functions-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-2.prql.snap => snapshot__tests__prql__queries__functions-2.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-3.prql.snap => snapshot__tests__prql__queries__functions-3.prql.snap} (54%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__functions-4.prql.snap => snapshot__tests__prql__queries__functions-4.prql.snap} (52%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap => snapshot__tests__prql__queries__pipelines-2.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@queries__variables-1.prql.snap => snapshot__tests__prql__queries__variables-1.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-0.prql.snap => snapshot__tests__prql__syntax-0.prql.snap} (55%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-1.prql.snap => snapshot__tests__prql__syntax-1.prql.snap} (55%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-10.prql.snap => snapshot__tests__prql__syntax-10.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-12.prql.snap => snapshot__tests__prql__syntax-12.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-15.prql.snap => snapshot__tests__prql__syntax-15.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-2.prql.snap => snapshot__tests__prql__syntax-2.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-5.prql.snap => snapshot__tests__prql__syntax-5.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-7.prql.snap => snapshot__tests__prql__syntax-7.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@syntax-9.prql.snap => snapshot__tests__prql__syntax-9.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap => snapshot__tests__prql__transforms__aggregate-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__derive-1.prql.snap => snapshot__tests__prql__transforms__derive-1.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap => snapshot__tests__prql__transforms__from_text-0.prql.snap} (50%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap => snapshot__tests__prql__transforms__from_text-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__group-0.prql.snap => snapshot__tests__prql__transforms__group-0.prql.snap} (54%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__join-0.prql.snap => snapshot__tests__prql__transforms__join-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__join-1.prql.snap => snapshot__tests__prql__transforms__join-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-1.prql.snap => snapshot__tests__prql__transforms__select-1.prql.snap} (53%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-4.prql.snap => snapshot__tests__prql__transforms__select-4.prql.snap} (51%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__select-5.prql.snap => snapshot__tests__prql__transforms__select-5.prql.snap} (55%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__sort-4.prql.snap => snapshot__tests__prql__transforms__sort-4.prql.snap} (50%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__window-0.prql.snap => snapshot__tests__prql__transforms__window-0.prql.snap} (52%) rename book/tests/snapshots/{snapshot__run_display_reference_prql@transforms__window-1.prql.snap => snapshot__tests__prql__transforms__window-1.prql.snap} (51%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index e86b59ae20fc..384b5dd578a4 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -1,8 +1,12 @@ #![cfg(not(target_family = "wasm"))] /// This test: -/// - Extracts PRQL code blocks into the `examples` path. -/// - Converts them to SQL using insta, raising an error if there's a diff. -/// - Replaces the PRQL code block with a comparison table. +/// - Extracts PRQL code blocks into files in the `examples` path, skipping +/// where the matching example is already present. +/// - Compiles them to SQL, comparing to a snapshot. Insta raises an error if +/// there's a diff. +/// +/// Then, when the book is built, the PRQL code block in the book is replaced +/// with a comparison table. /// /// We also use this test to run tests on our Display trait output, currently as /// another set of snapshots (more comments inline). @@ -18,69 +22,39 @@ // us. They introduce a bunch of non-rust dependencies, which is not ideal, but // passable. They don't let us customize our formatting (e.g. in a table). // -use anyhow::{bail, Result}; +use anyhow::{bail, Error, Result}; use globset::Glob; -use insta::{assert_display_snapshot, assert_snapshot, glob}; +use insta::{assert_snapshot, glob}; use log::warn; use prql_compiler::*; -use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; -use std::fs; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::{collections::HashMap, fs}; use walkdir::WalkDir; #[test] -fn run_examples() -> Result<()> { - // TODO: In CI this could pass by replacing incorrect files. To catch that, - // we could check if there are any diffs after this has run? - - // Note that on windows, markdown is read differently, and so - // writing on Windows. ref https://github.com/PRQL/prql/issues/356 - #[cfg(not(target_family = "windows"))] - write_reference_prql()?; - run_reference_prql(); - - // TODO: Currently we run this in the same test, since we need the - // `write_reference_prql` function to have been run. If we could iterate - // over the PRQL examples without writing them to disk, we could run this as - // a separate test. (Though then we'd lose the deferred failures feature - // that insta's `glob!` macro provides.) - run_display_reference_prql(); +fn test_examples() -> Result<()> { + // Note that on windows, markdown is read differently, and so we don't write + // on Windows (we write from the same place we read as a workaround). ref + // https://github.com/PRQL/prql/issues/356 + + write_prql_examples(collect_book_examples()?)?; + test_prql_examples(); Ok(()) } -/// Extract reference examples from the PRQL docs and write them to the -/// `tests/prql` path, one in each file. -// We could alternatively have used something like -// https://github.com/earldouglas/codedown, but it's not much code, and it -// requires no dependencies. -// -// We allow dead_code because of the window issue described above. (Can we allow -// it only for windows?) -#[allow(dead_code)] -fn write_reference_prql() -> Result<()> { - // Remove old .prql files, since we're going to rewrite them, and we don't want - // old files which wouldn't be rewritten from hanging around. - // We use `trash`, since we don't want to be removing files with test code - // in case there's a bug. - // - // A more elegant approach would be to keep a list of the files and remove - // the ones we don't write. - - let examples_path = Path::new("tests/prql"); - if examples_path.exists() { - trash::delete(Path::new("tests/prql")).unwrap_or_else(|e| { - warn!("Failed to delete old examples: {}", e); - }); - } +const ROOT_EXAMPLES_PATH: &str = "tests/prql"; +/// Collect all the PRQL examples in the book, as a map of . +#[cfg(not(target_family = "windows"))] +fn collect_book_examples() -> Result> { + use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; let glob = Glob::new("**/*.md")?.compile_matcher(); - - WalkDir::new(Path::new("./src/")) + let examples_in_book: HashMap = WalkDir::new(Path::new("./src/")) .into_iter() .flatten() .filter(|x| glob.is_match(x.path())) - .try_for_each(|dir_entry| { + .flat_map(|dir_entry| { let text = fs::read_to_string(dir_entry.path())?; let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; @@ -102,33 +76,90 @@ fn write_reference_prql() -> Result<()> { _ => {} } } - - // Write each one to a new file. - prql_blocks + let snapshot_prefix = &dir_entry + .path() + .strip_prefix("./src/")? + .to_str() + .unwrap() + .trim_end_matches(".md"); + Ok(prql_blocks .iter() .enumerate() - .try_for_each(|(i, example)| { - let file_relative = &dir_entry - .path() - .strip_prefix("./src/")? - .to_str() - .unwrap() - .trim_end_matches(".md"); - let prql_path = format!("tests/prql/{file_relative}-{i}.prql"); - - fs::create_dir_all(Path::new(&prql_path).parent().unwrap())?; - fs::write(prql_path, example.to_string())?; - - Ok::<(), anyhow::Error>(()) - })?; - Ok(()) - })?; + .map(|(i, example)| { + ( + Path::new(&format!("{ROOT_EXAMPLES_PATH}/{snapshot_prefix}-{i}.prql")) + .to_path_buf(), + example.to_string(), + ) + }) + .collect::>()) + }) + .flatten() + .collect(); + + Ok(examples_in_book) +} + +/// Collect examples which we've already written to disk, as a map of . +fn collect_snapshot_examples() -> Result> { + use itertools::Itertools; + let glob = Glob::new("**/*.prql")?.compile_matcher(); + let existing_examples = WalkDir::new(Path::new(ROOT_EXAMPLES_PATH)) + .into_iter() + .flatten() + .filter(|x| glob.is_match(x.path())) + .map(|x| Ok::<_, Error>((x.clone().into_path(), fs::read_to_string(x.path())?))) + .try_collect()?; + + Ok(existing_examples) +} + +// On Windows, we grab them from the written files, because of the markdown issue. +#[cfg(target_family = "windows")] +fn collect_book_examples() -> Result> { + collect_snapshot_examples() +} + +/// Write the passed examples as snapshots to the `tests/prql` path, one in each file. +// We could alternatively have used something like +// https://github.com/earldouglas/codedown, but it's not much code, and it +// requires no dependencies. +fn write_prql_examples(examples: HashMap) -> Result<()> { + // If we have to modify any files, raise an error at the end, so it fails in CI. + let mut is_snapshots_updated = false; + + let mut existing_snapshots: HashMap<_, _> = collect_snapshot_examples()?; + // Write any new snapshots, or update any that have changed + examples.iter().try_for_each(|(prql_path, example)| { + if existing_snapshots + .remove(prql_path) + .map(|existing| existing != *example) + .unwrap_or(true) + { + is_snapshots_updated = true; + fs::create_dir_all(Path::new(prql_path).parent().unwrap())?; + fs::write(prql_path, example)?; + } + + Ok::<(), anyhow::Error>(()) + })?; + // If there are any files left in `existing_snapshots`, we remove them, since + // they don't reference anything. + existing_snapshots.iter().for_each(|(path, _)| { + trash::delete(path).unwrap_or_else(|e| { + warn!("Failed to delete unreferenced example: {}", e); + }) + }); + + if is_snapshots_updated { + bail!("Some book snapshots were not consistent with the queries in the book. The snapshots have now been updated. Subsequent runs should pass."); + } Ok(()) } -/// Snapshot the output of each example. -fn run_reference_prql() { +/// Snapshot the SQL output of each example. +fn test_prql_examples() { glob!("prql/**/*.prql", |path| { let prql = fs::read_to_string(path).unwrap(); @@ -147,20 +178,25 @@ fn run_reference_prql() { } /// Snapshot the display trait output of each example. -// Currently not a separate test, see notes in caller. // // TODO: this involves writing out almost the same PRQL again โ€” instead we could // compare the output of Display to the auto-formatted source. But we need an // autoformatter for that (unless we want to raise on any non-matching input, // which seems very strict) -fn run_display_reference_prql() { - glob!("prql/**/*.prql", |path| { - let prql = fs::read_to_string(path).unwrap(); - - if prql.contains("skip_test") { - return; - } +#[test] +fn test_display() -> Result<(), ErrorMessages> { + use prql_compiler::downcast; + collect_book_examples() + .map_err(downcast)? + .iter() + .try_for_each(|(path, example)| { + assert_snapshot!( + path.to_string_lossy().to_string(), + prql_to_pl(example).and_then(pl_to_prql)?, + example + ); + Ok::<(), ErrorMessages>(()) + })?; - assert_display_snapshot!(prql_to_pl(&prql).and_then(pl_to_prql).unwrap()); - }); + Ok(()) } diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap deleted file mode 100644 index 085bada98319..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-0.prql ---- -from employees -select salary - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap deleted file mode 100644 index 6ab6d90cdd10..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-1.prql ---- -from employees -select [salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap deleted file mode 100644 index 930d29f6d477..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-0.prql.snap +++ /dev/null @@ -1,26 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/misc-0.prql ---- -let parts = ( - from seq_1_to_5 -) - - - -from pl = prospect_lists_prospects -filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" -join a = accounts [a.id == pl.related_id] -join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] -join ea = email_addresses [ea.id == er.email_address_id] -select ea.email_address -derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" -derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" -select [ - email_address, - stub, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap deleted file mode 100644 index d48e3fe1307a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__misc-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/misc-1.prql ---- -from club_ratings -filter rating != null -group year ( - derive [rating_norm = rating - ( average rating ) / ( stddev rating )] -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap deleted file mode 100644 index c4e1df527811..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-0.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/variables-0.prql ---- -from employees -filter country == "USA" -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average salary, - average gross_salary, - sum salary, - sum gross_salary, - average gross_cost, - sum_gross_cost = sum gross_cost, - ct = count, -] -) -sort sum_gross_cost -filter ct > 200 -take 20 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap deleted file mode 100644 index 1f588bf0d309..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__variables-1.prql.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/variables-1.prql ---- -from employees -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join titles [==emp_no] -group [title] ( - aggregate [avg_salary = average emp_salary] -) -select salary_k = avg_salary / 1000 -take 10 -derive salary = salary_k * 1000 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap deleted file mode 100644 index 96d5d50a00e1..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-0.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-0.prql ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap deleted file mode 100644 index ae83420f23d3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-1.prql ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap deleted file mode 100644 index f15a84e195b3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-2.prql ---- -filter age > 50 ( - from employees -) -sort name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap deleted file mode 100644 index aa777d923706..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__functional-lang-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/functional-lang-3.prql ---- -sort name ( - filter age > 50 ( - from employees -) -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap deleted file mode 100644 index a7bd8bc3730a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/name-resolving-0.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap deleted file mode 100644 index bc40a390e21a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@introduction-0.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/introduction-0.prql ---- -from employees -filter start_date > @2021-01-01 -derive [ - gross_salary = salary + tax ?? 0, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average gross_salary, - sum_gross_cost = sum gross_cost, -] -) -filter sum_gross_cost > 100000 -derive id = f"{title}_{country}" -derive country_code = s"LEFT(country, 2)" -sort [ - sum_gross_cost, - -country, -] -take 1..20 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap deleted file mode 100644 index 16833c5f8cfa..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__coalesce-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/coalesce-0.prql ---- -from orders -derive amount ?? 0 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap deleted file mode 100644 index ca08e6d69631..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-0.prql ---- -from employees -derive age_at_year_end = @2022-12-31 - dob - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap deleted file mode 100644 index 07d9b568eac6..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-1.prql ---- -from orders -derive should_have_shipped_today = order_time < @08:30 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap deleted file mode 100644 index 6e0b688f7f7a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-2.prql ---- -from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap deleted file mode 100644 index 5080f647a12c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__dates-and-times-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/dates-and-times-3.prql ---- -from projects -derive first_check_in = start + 10days - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap deleted file mode 100644 index 587f75ff1bd2..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-0.prql ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap deleted file mode 100644 index d6bcee7acf86..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-1.prql ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap deleted file mode 100644 index 4f2e5f381a88..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__distinct-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/distinct-2.prql ---- -from employees -group department ( - sort age - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap deleted file mode 100644 index 2b8a822ba481..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/f-strings-0.prql ---- -from employees -select full_name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap deleted file mode 100644 index b61f8780aa34..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__f-strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/f-strings-1.prql ---- -from web -select url = f"http{tls}://www.{domain}.{tld}/{page}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap deleted file mode 100644 index 016809741efe..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__null-0.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/null-0.prql ---- -from employees -filter first_name == null -filter null != last_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap deleted file mode 100644 index 46ce8b767eb3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/ranges-1.prql ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap deleted file mode 100644 index fa9c95fb9f4c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-0.prql ---- -from my_table -select db_version = s"version()" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap deleted file mode 100644 index 7de6990c149c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-1.prql ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap deleted file mode 100644 index 691cabab4a62..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__standard-library-0.prql.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/standard-library-0.prql ---- -from employees -derive [ - gross_salary = ( - salary + payroll_tax - as int -), - gross_salary_rounded = ( - gross_salary - round 0 -), - time = s"NOW()", -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap deleted file mode 100644 index 08b198a45ab3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-0.prql ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap deleted file mode 100644 index 014e0927ce0e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-1.prql ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap deleted file mode 100644 index 52b190fec22a..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-2.prql ---- -from my_table -select x = '"hello world"' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap deleted file mode 100644 index eddb87ee8834..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-3.prql ---- -from my_table -select x = 'I said "hello world"!' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap deleted file mode 100644 index 5966be260e48..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__strings-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/strings-4.prql ---- -from my_table -select x = 'I said """hello world"""!' - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap deleted file mode 100644 index 8d46fc69595c..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-0.prql.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-0.prql ---- -prql target:sql.postgres - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap deleted file mode 100644 index 2719c8e16911..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-1.prql.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-1.prql ---- -prql target:sql.mssql - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap deleted file mode 100644 index 5bf77265c6a4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__target-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/target-2.prql ---- -prql version:^0.5 - - - -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap deleted file mode 100644 index 7162e861b213..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-0.prql ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap deleted file mode 100644 index f64f5d68dc56..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-1.prql ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap deleted file mode 100644 index fbb8c9dfa00f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-0.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/variables-0.prql ---- -let top_50 = ( - from employees - sort salary - take 50 - aggregate [total_salary = sum salary] -) - - - -from top_50 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap deleted file mode 100644 index f719b0acbbd4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-11.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-11.prql ---- -from `dir/*.parquet` - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap deleted file mode 100644 index 6316d2280516..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-13.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-13.prql ---- -from `music.albums` - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap deleted file mode 100644 index a38f2f750602..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-14.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-14.prql ---- -from employees -filter id == $1 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap deleted file mode 100644 index 6820f7c5e628..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-3.prql ---- -from employees -select [first_name] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap deleted file mode 100644 index 6e06fe3ee2e5..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-4.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap deleted file mode 100644 index d6668fe305c7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-6.prql.snap +++ /dev/null @@ -1,40 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-6.prql ---- -from employees -derive is_proximate = ( - distance - in 0..20 -) -derive ( - total_distance = sum distance -) -derive ( - min_capped_distance = min distance ?? 5 -) -derive travel_time = distance / 40 -derive ( - distance_rounded_2_dp = round 1 + 1 distance -) -derive [ - is_far = ( - distance - in 100.. -), - is_negative = ( - distance - in -100..0 -), - is_negative = ( - distance - in -100..0 -), - average_distance = average distance, -] -sort -distance -sort [-distance] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap deleted file mode 100644 index 55a51e5d833f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-8.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-8.prql ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap deleted file mode 100644 index 89e3271c8316..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-0.prql ---- -from employees -aggregate [ - average salary, - ct = count, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap deleted file mode 100644 index 21468ff11aeb..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-2.prql ---- -from employees -derive [avg_sal = average salary] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap deleted file mode 100644 index 821c0f010d36..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-0.prql ---- -from employees_1 -append employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap deleted file mode 100644 index 2a61ec1251b1..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-1.prql ---- -from employees_1 -remove employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap deleted file mode 100644 index dddeb63b7c9f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__append-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/append-2.prql ---- -from employees_1 -intersect employees_2 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap deleted file mode 100644 index e90d9add3db4..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/derive-0.prql ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap deleted file mode 100644 index 8a68bf997bd7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-0.prql ---- -from employees -filter age > 25 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap deleted file mode 100644 index 1bc8cf6d4a34..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-1.prql ---- -from employees -filter age > 25 or department != "IT" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap deleted file mode 100644 index ad800e09070f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__filter-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/filter-2.prql ---- -from employees -filter ( - age - in 25..40 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap deleted file mode 100644 index 0adcf6191d9e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from-0.prql ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap deleted file mode 100644 index b90898f6f93e..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from-1.prql ---- -from e = employees -select e.first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap deleted file mode 100644 index a0aaabe15cb7..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-2.prql.snap +++ /dev/null @@ -1,33 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-2.prql ---- -let x = ( - from_text format:json '{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}' -) - - - -let y = ( - from_text format:json ' - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -' -) - - - -from x -join y [==a] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap deleted file mode 100644 index f916e255f991..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-1.prql ---- -from employees -sort join_date -take 1 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap deleted file mode 100644 index 6b2cb62586b3..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-2.prql ---- -from employees -group role ( - sort join_date - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap deleted file mode 100644 index 19b950c9d24b..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-2.prql ---- -from employees -join positions [==emp_no] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap deleted file mode 100644 index 9841ec3d8249..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-0.prql ---- -from employees -select name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap deleted file mode 100644 index 522050c7dd99..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-2.prql ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap deleted file mode 100644 index d6596a9ce634..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-3.prql ---- -from e = employees -select [ - e.first_name, - e.last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap deleted file mode 100644 index 102555240bdb..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-6.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-6.prql ---- -from artists -derive nick = name -select not [artists.`*`] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap deleted file mode 100644 index 91b36c10532f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-0.prql ---- -from employees -sort age - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap deleted file mode 100644 index d7f443472fc9..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-1.prql ---- -from employees -sort [-age] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap deleted file mode 100644 index 1df292e0b57f..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-2.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-2.prql ---- -from employees -sort [ - age, - -tenure, - salary, -] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap deleted file mode 100644 index 3ef53a4676e9..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-3.prql ---- -from employees -sort [s"substr({first_name}, 2, 5)"] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap deleted file mode 100644 index 52f805544586..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-5.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-5.prql ---- -from employees -sort tenure -join locations [==employee_id] - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap deleted file mode 100644 index 7f798967b647..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/take-0.prql ---- -from employees -take 10 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap deleted file mode 100644 index 4107c86bfd92..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__take-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/take-1.prql ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap deleted file mode 100644 index 3015829b90db..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-2.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-2.prql ---- -from employees -sort age -derive rnk = rank - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap deleted file mode 100644 index 26a5eb5d9d46..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-3.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-3.prql ---- -from employees -group department ( - sort age - derive rnk = rank -) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap deleted file mode 100644 index be549656354d..000000000000 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-4.prql ---- -from employees -filter salary < ( average salary ) - - - diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap index b246de058091..83e9f48a0e9e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/cte-0.prql +expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" --- let newest_employees = ( from employees diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap index 692c476512cc..ac80804d08a1 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-0.prql +expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" --- from salaries group [emp_no] ( diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap index 665754bd3fb5..c5d5366f6306 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-1.prql +expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap index 3823173006c7..d957c280a5c6 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-2.prql +expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" --- from e = employees join salaries [==emp_no] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap index 611769e8f06d..9cc6115f24bd 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/employees-3.prql +expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap new file mode 100644 index 000000000000..8566dfaeb2b2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect salary\n" +--- +from employees +select salary + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap new file mode 100644 index 000000000000..055af64b363a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect [salary]\n" +--- +from employees +select [salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap index 5ba483c522d7..3d298b6f9b55 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-2.prql +expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap index c1c8e138f806..254f07187889 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@examples__list-equivalence-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/examples/list-equivalence-3.prql +expression: "from employees\nderive gross_salary = salary + payroll_tax\nderive gross_cost = gross_salary + benefits_cost\n" --- from employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap new file mode 100644 index 000000000000..63b13a31ec56 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap @@ -0,0 +1,25 @@ +--- +source: book/tests/snapshot.rs +expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" +--- +let parts = ( + from seq_1_to_5 +) + + + +from pl = prospect_lists_prospects +filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" +join a = accounts [a.id == pl.related_id] +join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] +join ea = email_addresses [ea.id == er.email_address_id] +select ea.email_address +derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" +derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" +select [ + email_address, + stub, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap new file mode 100644 index 000000000000..50dcca896ea5 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from club_ratings\nfilter rating != null\n# TODO: this is real ugly. `average rating` should not require parenthesis\n# TODO: why cannot we put comments in group's pipeline?\ngroup year (\n derive [rating_norm = rating - (average rating) / (stddev rating)]\n)\n" +--- +from club_ratings +filter rating != null +group year ( + derive [rating_norm = rating - ( average rating ) / ( stddev rating )] +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap new file mode 100644 index 000000000000..4b1f4fce84c1 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap @@ -0,0 +1,31 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter country == \"USA\" # Each line transforms the previous result.\nderive [ # This adds columns / variables.\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost # Variables can use other variables.\n]\nfilter gross_cost > 0\ngroup [title, country] ( # For each group use a nested pipeline\n aggregate [ # Aggregate each group to a single row\n average salary,\n average gross_salary,\n sum salary,\n sum gross_salary,\n average gross_cost,\n sum_gross_cost = sum gross_cost,\n ct = count,\n ]\n)\nsort sum_gross_cost\nfilter ct > 200\ntake 20\n" +--- +from employees +filter country == "USA" +derive [ + gross_salary = salary + payroll_tax, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average salary, + average gross_salary, + sum salary, + sum gross_salary, + average gross_cost, + sum_gross_cost = sum gross_cost, + ct = count, +] +) +sort sum_gross_cost +filter ct > 200 +take 20 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap new file mode 100644 index 000000000000..cfb45e96a801 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap @@ -0,0 +1,18 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup [emp_no] (\n aggregate [\n emp_salary = average salary # average salary resolves to \"AVG(salary)\" (from stdlib)\n ]\n)\njoin titles [==emp_no]\ngroup [title] (\n aggregate [\n avg_salary = average emp_salary\n ]\n)\nselect salary_k = avg_salary / 1000 # avg_salary should resolve to \"AVG(emp_salary)\"\ntake 10 # induces new SELECT\nderive salary = salary_k * 1000 # salary_k should not resolve to \"avg_salary / 1000\"\n" +--- +from employees +group [emp_no] ( + aggregate [emp_salary = average salary] +) +join titles [==emp_no] +group [title] ( + aggregate [avg_salary = average emp_salary] +) +select salary_k = avg_salary / 1000 +take 10 +derive salary = salary_k * 1000 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap new file mode 100644 index 000000000000..1bd2d905e16d --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter age > 50\nsort name\n" +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap new file mode 100644 index 000000000000..da4b761a9e4b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees | filter age > 50 | sort name\n" +--- +from employees +filter age > 50 +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap new file mode 100644 index 000000000000..7da897d0dd14 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "filter age > 50 (from employees) | sort name\n" +--- +filter age > 50 ( + from employees +) +sort name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap new file mode 100644 index 000000000000..045c663815a8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "sort name (filter age > 50 (from employees))\n" +--- +sort name ( + filter age > 50 ( + from employees +) +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap similarity index 56% rename from book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap index 6161fd5892e6..a9d9e5bada6d 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@internals__name-resolving-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/internals/name-resolving-1.prql +expression: "from employees\nderive [first_name, dept_id]\njoin d=departments [==dept_id]\nselect [first_name, d.title]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap new file mode 100644 index 000000000000..96f55b8ab057 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap @@ -0,0 +1,31 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" +--- +from employees +filter start_date > @2021-01-01 +derive [ + gross_salary = salary + tax ?? 0, + gross_cost = gross_salary + benefits_cost, +] +filter gross_cost > 0 +group [ + title, + country, +] ( + aggregate [ + average gross_salary, + sum_gross_cost = sum gross_cost, +] +) +filter sum_gross_cost > 100000 +derive id = f"{title}_{country}" +derive country_code = s"LEFT(country, 2)" +sort [ + sum_gross_cost, + -country, +] +take 1..20 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap new file mode 100644 index 000000000000..24ff749cfbc8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nderive amount ?? 0\n" +--- +from orders +derive amount ?? 0 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap new file mode 100644 index 000000000000..acb71c71fc9a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive age_at_year_end = (@2022-12-31 - dob)\n" +--- +from employees +derive age_at_year_end = @2022-12-31 - dob + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap new file mode 100644 index 000000000000..fd2fe52b3f6c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nderive should_have_shipped_today = (order_time < @08:30)\n" +--- +from orders +derive should_have_shipped_today = order_time < @08:30 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap new file mode 100644 index 000000000000..1507a39b0252 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-0800\n" +--- +from commits +derive first_prql_commit = @2020-01-01T13:19:55-0800 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap new file mode 100644 index 000000000000..70ac66f365a2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from projects\nderive first_check_in = start + 10days\n" +--- +from projects +derive first_check_in = start + 10days + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap new file mode 100644 index 000000000000..7929401e23b6 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect department\ngroup department (\n take 1\n)\n" +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap new file mode 100644 index 000000000000..22ba087f087c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect department\ngroup department (take 1)\n" +--- +from employees +select department +group department ( + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap new file mode 100644 index 000000000000..ceb0035e6601 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "# youngest employee from each department\nfrom employees\ngroup department (\n sort age\n take 1\n)\n" +--- +from employees +group department ( + sort age + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap new file mode 100644 index 000000000000..5f490aa52f00 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect full_name = f\"{first_name} {last_name}\"\n" +--- +from employees +select full_name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap new file mode 100644 index 000000000000..f00e2becbab2 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from web\nselect url = f\"http{tls}://www.{domain}.{tld}/{page}\"\n" +--- +from web +select url = f"http{tls}://www.{domain}.{tld}/{page}" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap new file mode 100644 index 000000000000..73594522238f --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter first_name == null\nfilter null != last_name\n" +--- +from employees +filter first_name == null +filter null != last_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap index e20b2b97240c..2d5baa98ae2d 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__ranges-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/ranges-0.prql +expression: "from events\nfilter (date | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" --- from events filter ( diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap new file mode 100644 index 000000000000..b68c1920a669 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nsort [-value, date]\ntake 101..110\n" +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap new file mode 100644 index 000000000000..12abfcc2518c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect db_version = s\"version()\"\n" +--- +from my_table +select db_version = s"version()" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap new file mode 100644 index 000000000000..c57ed2561d58 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\naggregate [average salary]\n" +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap index 8d39feed0f0d..e28b7f46ed0a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-2.prql +expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"\"\"({s.from_date}, {s.to_date})\n OVERLAPS\n ({de.from_date}, {de.to_date})\"\"\"\n]\n" --- from de = dept_emp join side:left s = salaries [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap index 85661196009c..2cb93849dda8 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-3.prql +expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" --- from s"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC" join s = s"SELECT * FROM salaries" [==id] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap index d7482d2f4cfb..00c1d5e17349 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-4.prql +expression: "from employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" --- from employees derive [has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){2,}')"] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap index 4313e1e554a7..9bd3b0d3fe16 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-5.prql +expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"{gross_salary} / 365\"\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap index 8ac94b9d968f..3dc30b6885ae 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__s-strings-6.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/s-strings-6.prql +expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"({gross_salary}) / 365\"\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap new file mode 100644 index 000000000000..011d5f416c47 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap @@ -0,0 +1,19 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" +--- +from employees +derive [ + gross_salary = ( + salary + payroll_tax + as int +), + gross_salary_rounded = ( + gross_salary + round 0 +), + time = s"NOW()", +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap new file mode 100644 index 000000000000..6a1d79036036 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"hello world\"\n" +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap new file mode 100644 index 000000000000..2da7a07937de --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = 'hello world'\n" +--- +from my_table +select x = "hello world" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap new file mode 100644 index 000000000000..8d79cd8cedbc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = '\"hello world\"'\n" +--- +from my_table +select x = '"hello world"' + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap new file mode 100644 index 000000000000..a681bc62a036 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\"\"I said \"hello world\"!\"\"\"\n" +--- +from my_table +select x = 'I said "hello world"!' + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap new file mode 100644 index 000000000000..0bae3f836774 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\"\"\"\"I said \"\"\"hello world\"\"\"!\"\"\"\"\"\n" +--- +from my_table +select x = 'I said """hello world"""!' + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap index 85bb6bac32b8..7618b9e71723 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/switch-0.prql +expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap index dd4c64e0b6b0..f9ee3312b92b 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@language-features__switch-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/language-features/switch-1.prql +expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" --- from employees derive distance = switch [ diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap new file mode 100644 index 000000000000..b22539422ae4 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" +--- +prql target:sql.postgres + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap new file mode 100644 index 000000000000..ed7e10fd7388 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap @@ -0,0 +1,14 @@ +--- +source: book/tests/snapshot.rs +expression: "prql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" +--- +prql target:sql.mssql + + + +from employees +sort age +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap new file mode 100644 index 000000000000..b05787ed8bae --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "prql version:\"0.5\"\n\nfrom employees\n" +--- +prql version:^0.5 + + + +from employees + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap index bde459b05cf8..e5bb0a64491b 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-0.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap index d8d3e0185fd9..ef971e8402bc 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-1.prql +expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp lower:0 1600 sat_score),\n]\n" --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap index 49560fe48496..2e8f243ea009 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-2.prql +expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp lower:0 1600),\n]\n" --- func interp higher x lower:0 -> x - lower / higher - lower diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap index 83e91977fe3f..bc1453813dc9 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-3.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (temp_f | fahrenheit_to_celsius)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap index 8ed62cca5158..3deae6fcab9c 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__functions-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/functions-4.prql +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap new file mode 100644 index 000000000000..8ef6dce0bb66 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n" +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap new file mode 100644 index 000000000000..b2b18409f03a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive gross_salary = (salary + payroll_tax)\n" +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap index e3ff662251a8..5c74bd2eeb81 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/pipelines-2.prql +expression: "from e = employees\nderive gross_salary = (salary + payroll_tax)\nsort gross_salary\ntake 10\njoin d = department [==dept_no]\nselect [e.name, gross_salary, d.name]\n" --- from e = employees derive gross_salary = salary + payroll_tax diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap new file mode 100644 index 000000000000..3c4edace1010 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap @@ -0,0 +1,17 @@ +--- +source: book/tests/snapshot.rs +expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" +--- +let top_50 = ( + from employees + sort salary + take 50 + aggregate [total_salary = sum salary] +) + + + +from top_50 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap index f7a3cbcd9431..dd72ddc9b4bb 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@queries__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/queries/variables-1.prql +expression: "let grouping = s\"\"\"\n SELECT SUM(a)\n FROM tbl\n GROUP BY\n GROUPING SETS\n ((b, c, d), (d), (b, d))\n\"\"\"\n\nfrom grouping\n" --- let grouping = s" SELECT SUM(a) diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap index 16788f8c5410..ee78d7a29c00 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-0.prql +expression: "from employees\nfilter department == \"Product\"\nselect [first_name, last_name]\n" --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap index 7d3684118966..ae9d7fcbb81c 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-1.prql +expression: "from employees | filter department == \"Product\" | select [first_name, last_name]\n" --- from employees filter department == "Product" diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap index e12239744931..0ef6f6c5ea4e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-10.prql +expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" --- prql target:sql.postgres diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap new file mode 100644 index 000000000000..acd1651bdbb9 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from `dir/*.parquet`\n" +--- +from `dir/*.parquet` + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap index 79ec4c9aa74d..6be462d1cb08 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-12.prql +expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap new file mode 100644 index 000000000000..fc9310bcceea --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from `music.albums`\n" +--- +from `music.albums` + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap new file mode 100644 index 000000000000..429e57d0faf3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter id == $1\n" +--- +from employees +filter id == $1 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap index 34d44267ba17..7aa2caf4c217 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-15.prql +expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" --- from numbers select [ diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap index 8c5b5825e8c4..a12652162d23 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-2.prql +expression: "from numbers\nderive [x = 1, y = 2]\nderive [\n a = x,\n b = y\n]\nderive [\n c = a,\n d = b,\n]\n" --- from numbers derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap new file mode 100644 index 000000000000..4077d71aaa9b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect [first_name]\n" +--- +from employees +select [first_name] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap index f3ebf960c4bf..027e1a5e000f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-5.prql +expression: "from foo\nselect [\n circumference = diameter * 3.14159,\n color,\n]\nfilter circumference > 10 and color != \"red\"\n" --- from foo select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap new file mode 100644 index 000000000000..b9f326d968cc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap @@ -0,0 +1,39 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" +--- +from employees +derive is_proximate = ( + distance + in 0..20 +) +derive ( + total_distance = sum distance +) +derive ( + min_capped_distance = min distance ?? 5 +) +derive travel_time = distance / 40 +derive ( + distance_rounded_2_dp = round 1 + 1 distance +) +derive [ + is_far = ( + distance + in 100.. +), + is_negative = ( + distance + in -100..0 +), + is_negative = ( + distance + in -100..0 +), + average_distance = average distance, +] +sort -distance +sort [-distance] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap index 29e0c6d26c1e..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-7.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap new file mode 100644 index 000000000000..4f94033b1f86 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" +--- +from employees +aggregate [average salary] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap index 9e5a61c3e446..19c4de64822f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/syntax-9.prql +expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" --- prql target:sql.mysql diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap new file mode 100644 index 000000000000..1c202ec4ba25 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\naggregate [\n average salary,\n ct = count\n]\n" +--- +from employees +aggregate [ + average salary, + ct = count, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap index bbf253ec6dd5..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__aggregate-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/aggregate-1.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap new file mode 100644 index 000000000000..9b49b51df2a5 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive [avg_sal = average salary]\n" +--- +from employees +derive [avg_sal = average salary] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap new file mode 100644 index 000000000000..cbbd0478001b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nappend employees_2\n" +--- +from employees_1 +append employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap new file mode 100644 index 000000000000..e2b9a1338479 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nremove employees_2\n" +--- +from employees_1 +remove employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap new file mode 100644 index 000000000000..1971d287b890 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees_1\nintersect employees_2\n" +--- +from employees_1 +intersect employees_2 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap new file mode 100644 index 000000000000..183b59f98112 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nderive gross_salary = salary + payroll_tax\n" +--- +from employees +derive gross_salary = salary + payroll_tax + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap index f2b9dd7bd20d..3d298b6f9b55 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__derive-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/derive-1.prql +expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" --- from employees derive [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap new file mode 100644 index 000000000000..bd5e2c425e25 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter age > 25\n" +--- +from employees +filter age > 25 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap new file mode 100644 index 000000000000..a6cb5b5b569e --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter (age > 25 or department != \"IT\")\n" +--- +from employees +filter age > 25 or department != "IT" + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap new file mode 100644 index 000000000000..d3b04cd4de31 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter (age | in 25..40)\n" +--- +from employees +filter ( + age + in 25..40 +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap new file mode 100644 index 000000000000..8ef6dce0bb66 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap @@ -0,0 +1,8 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\n" +--- +from employees + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap new file mode 100644 index 000000000000..ef1312a86941 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from e = employees\nselect e.first_name\n" +--- +from e = employees +select e.first_name + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap index d86f2e1e86bb..6a730d3a1f7e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-0.prql +expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" --- from_text " a,b,c diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap index 740349748e00..6f9f848bbd6e 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/from_text-1.prql +expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" --- let temp_format_lookup = ( from_text format:csv " diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap new file mode 100644 index 000000000000..da17c3b1fe6f --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap @@ -0,0 +1,32 @@ +--- +source: book/tests/snapshot.rs +expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" +--- +let x = ( + from_text format:json '{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}' +) + + + +let y = ( + from_text format:json ' + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +' +) + + + +from x +join y [==a] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap similarity index 54% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap index 754f23c1d76e..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__group-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/group-0.prql +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees group [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap new file mode 100644 index 000000000000..2517396a1418 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort join_date\ntake 1\n" +--- +from employees +sort join_date +take 1 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap new file mode 100644 index 000000000000..11467687bbbb --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup role (\n sort join_date # taken from above\n take 1\n)\n" +--- +from employees +group role ( + sort join_date + take 1 +) + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap index 0334411b6614..4d113382409a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-0.prql +expression: "from employees\njoin side:left positions [employees.id==positions.employee_id]\n" --- from employees join side:left positions [employees.id == positions.employee_id] diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap index 073e5b79b5ee..b3e13a1d23f8 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__join-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/join-1.prql +expression: "from employees\njoin side:left p=positions [employees.id==p.employee_id]\n" --- from employees join side:left p = positions [employees.id == p.employee_id] diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap new file mode 100644 index 000000000000..ba833fa01b02 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\njoin positions [==emp_no]\n" +--- +from employees +join positions [==emp_no] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap new file mode 100644 index 000000000000..ef3e65965333 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect name = f\"{first_name} {last_name}\"\n" +--- +from employees +select name = f"{first_name} {last_name}" + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap similarity index 53% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap index 1ecfbb0be8f6..57c345371217 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-1.prql +expression: "from employees\nselect [\n name = f\"{first_name} {last_name}\",\n age_eoy = dob - @2022-12-31,\n]\n" --- from employees select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap new file mode 100644 index 000000000000..56e49df27e11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nselect first_name\n" +--- +from employees +select first_name + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap new file mode 100644 index 000000000000..059b92276754 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from e=employees\nselect [e.first_name, e.last_name]\n" +--- +from e = employees +select [ + e.first_name, + e.last_name, +] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap index c8837e7a5780..6445588450d2 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-4.prql +expression: "prql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" --- prql target:sql.bigquery diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap similarity index 55% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap index ee470cf35cf6..568bc821ba4f 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__select-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/select-5.prql +expression: "from tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" --- from tracks select [ diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap new file mode 100644 index 000000000000..19b65db61c48 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from artists\nderive nick = name\nselect ![artists.*]\n" +--- +from artists +derive nick = name +select not [artists.`*`] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap new file mode 100644 index 000000000000..cb41ef4b5ddb --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort age\n" +--- +from employees +sort age + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap new file mode 100644 index 000000000000..12203dcc78d3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [-age]\n" +--- +from employees +sort [-age] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap new file mode 100644 index 000000000000..23c2050900c8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [age, -tenure, +salary]\n" +--- +from employees +sort [ + age, + -tenure, + salary, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap new file mode 100644 index 000000000000..01b0d75eb4e3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" +--- +from employees +sort [s"substr({first_name}, 2, 5)"] + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap similarity index 50% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap index 01b5c740c41a..51c71b587af5 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__sort-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/sort-4.prql +expression: "from employees\nsort tenure\nderive name = f\"{first_name} {last_name}\"\n" --- from employees sort tenure diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap new file mode 100644 index 000000000000..405c461df7e4 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort tenure\njoin locations [==employee_id]\n" +--- +from employees +sort tenure +join locations [==employee_id] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap new file mode 100644 index 000000000000..4c39e0cddcea --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ntake 10\n" +--- +from employees +take 10 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap new file mode 100644 index 000000000000..b68c1920a669 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "from orders\nsort [-value, date]\ntake 101..110\n" +--- +from orders +sort [ + -value, + date, +] +take 101..110 + + + diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap similarity index 52% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap index 2366506585b0..08d6e23e2468 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-0.prql +expression: "from employees\ngroup employee_id (\n sort month\n window rolling:12 (\n derive [trail_12_m_comp = sum paycheck]\n )\n)\n" --- from employees group employee_id ( diff --git a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap similarity index 51% rename from book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap index afffeb8eb185..c0663a94bc4a 100644 --- a/book/tests/snapshots/snapshot__run_display_reference_prql@transforms__window-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: prql_to_pl(&prql).and_then(pl_to_prql).unwrap() -input_file: book/tests/prql/transforms/window-1.prql +expression: "from orders\nsort day\nwindow rows:-3..3 (\n derive [centered_weekly_average = average value]\n)\ngroup [order_month] (\n sort day\n window expanding:true (\n derive [monthly_running_total = sum value]\n )\n)\n" --- from orders sort day diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap new file mode 100644 index 000000000000..dc3037c993b3 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nsort age\nderive rnk = rank\n" +--- +from employees +sort age +derive rnk = rank + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap new file mode 100644 index 000000000000..b71455102a11 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup department (\n sort age\n derive rnk = rank\n)\n" +--- +from employees +group department ( + sort age + derive rnk = rank +) + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap new file mode 100644 index 000000000000..9e104fbe34a9 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\nfilter salary < (average salary)\n" +--- +from employees +filter salary < ( average salary ) + + + From 950996a1bfe4ca2033b1b53cdd23194163e54078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Mon, 20 Feb 2023 09:40:23 +0100 Subject: [PATCH 027/184] build: use released minijinja (#1906) --- Cargo.lock | 5 +++-- prql-compiler/prqlc/Cargo.toml | 2 +- prql-compiler/prqlc/src/jinja.rs | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f94ad387bfbf..5eb860296819 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1671,8 +1671,9 @@ dependencies = [ [[package]] name = "minijinja" -version = "0.30.2" -source = "git+https://github.com/aljazerzen/minijinja#af5a4fd89e5ee5455d673a23098dcbc3d8444229" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f95c8f0999f88dd509934824ce03582ffbbcabf8af6484107572618732660c54" dependencies = [ "serde", ] diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 621fdc071a43..a90627b1530d 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -18,7 +18,7 @@ color-eyre = "0.6.1" env_logger = {version = "0.9.1", features = ["termcolor"]} itertools = "0.10.3" notify = "^5.1.0" -minijinja = {git = "https://github.com/aljazerzen/minijinja"} +minijinja = {version = "0.30.4", features = ["unstable_machinery"]} prql-compiler = {path = '..', version = "0.5.2"} regex = {version = "1.7.1", features = ["std", "unicode"]} serde_json = "1.0.81" diff --git a/prql-compiler/prqlc/src/jinja.rs b/prql-compiler/prqlc/src/jinja.rs index ac8835747a37..6bec828644c8 100644 --- a/prql-compiler/prqlc/src/jinja.rs +++ b/prql-compiler/prqlc/src/jinja.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use anyhow::Result; -use minijinja::compiler::tokens::{Span, Token}; +use minijinja::machinery::{Span, Token}; use regex::Regex; const ANCHOR_PREFIX: &str = "_jinja_"; @@ -41,7 +41,7 @@ pub fn pre_process(source: &str) -> Result<(String, JinjaContext)> { let mut blocks = Vec::new(); let mut current_block = Vec::new(); - for res in minijinja::compiler::lexer::tokenize(source, false) { + for res in minijinja::machinery::tokenize(source, false) { let (token, span) = res?; if let Token::TemplateData(data) = token { From c6c73ef3631b414730cc14aa1fa4130183f6519f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 20 Feb 2023 01:23:31 -0800 Subject: [PATCH 028/184] refactor: Options as &Options (#1905) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Options as &Options Not sure if this is worthwhile โ€” I started in one function and then kept on replacing. Fine to close if not an improvement. * . --- book/src/lib.rs | 2 +- book/tests/snapshot.rs | 4 ++-- prql-compiler/README.md | 6 +++--- prql-compiler/benches/bench.rs | 2 +- prql-compiler/examples/compile-files/build.rs | 2 +- prql-compiler/prql-compiler-macros/src/lib.rs | 2 +- prql-compiler/prqlc/src/cli.rs | 2 +- prql-compiler/prqlc/src/watch.rs | 2 +- prql-compiler/src/lib.rs | 12 ++++++------ prql-compiler/src/sql/dialect.rs | 1 + prql-compiler/src/sql/mod.rs | 6 +++--- prql-compiler/src/test.rs | 12 ++++++------ prql-compiler/tests/integration/main.rs | 6 +++--- prql-elixir/native/prql/src/lib.rs | 4 ++-- prql-java/src/lib.rs | 2 +- prql-js/src/lib.rs | 4 ++-- prql-lib/src/lib.rs | 2 +- prql-python/src/lib.rs | 4 ++-- 18 files changed, 38 insertions(+), 37 deletions(-) diff --git a/book/src/lib.rs b/book/src/lib.rs index 9c69858dc66a..1d8a8e067edc 100644 --- a/book/src/lib.rs +++ b/book/src/lib.rs @@ -109,7 +109,7 @@ fn replace_examples(text: &str) -> Result { let options = prql_compiler::Options::default().no_signature(); let html = table_of_comparison( text.as_str().unwrap(), - &compile(&prql, options).unwrap(), + &compile(&prql, &options).unwrap(), ); cmark_acc.push(Event::Html(html.into())); diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 384b5dd578a4..a454da7c80da 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -160,6 +160,7 @@ fn write_prql_examples(examples: HashMap) -> Result<()> { /// Snapshot the SQL output of each example. fn test_prql_examples() { + let opts = Options::default().no_signature(); glob!("prql/**/*.prql", |path| { let prql = fs::read_to_string(path).unwrap(); @@ -167,8 +168,7 @@ fn test_prql_examples() { return; } - let opts = Options::default().no_signature(); - let sql = compile(&prql, opts).unwrap_or_else(|e| format!("{prql}\n\n{e}")); + let sql = compile(&prql, &opts).unwrap_or_else(|e| format!("{prql}\n\n{e}")); // `glob!` gives us the file path in the test name anyway, so we pass an // empty name. We pass `&prql` so the prql is in the snapshot (albeit in // a single line, and, in the rare case that the SQL doesn't change, the diff --git a/prql-compiler/README.md b/prql-compiler/README.md index 900be541dc03..abcdc1202bbe 100644 --- a/prql-compiler/README.md +++ b/prql-compiler/README.md @@ -8,7 +8,7 @@ For more on PRQL, check out the [PRQL website](https://prql-lang.org) or the For more usage examples and the library documentation, check out the [`prql-compiler` documentation](https://docs.rs/prql-compiler/latest/prql_compiler/). -# Installation +## Installation ```shell cargo add prql-compiler @@ -24,12 +24,12 @@ Compile a PRQL string to a SQLite dialect string. use prql_compiler::{compile, Options, Target, sql::Dialect}; let prql = "from employees | select [name, age]"; -let opt = Options { +let opts = &Options { format: false, target: Target::Sql(Some(Dialect::SQLite)), signature_comment: false }; -let sql = compile(&prql, opt).unwrap(); +let sql = compile(&prql, opts).unwrap(); assert_eq!("SELECT name, age FROM employees", sql); ``` diff --git a/prql-compiler/benches/bench.rs b/prql-compiler/benches/bench.rs index 8ab830c42513..bda16db184c0 100644 --- a/prql-compiler/benches/bench.rs +++ b/prql-compiler/benches/bench.rs @@ -18,7 +18,7 @@ cfg_if::cfg_if! { const CONTENT: &str = include_str!("../../book/tests/prql/examples/variables-0.prql"); fn compile_query() -> Result { - compile(CONTENT, Options::default()) + compile(CONTENT, &Options::default()) } fn criterion_benchmark(c: &mut Criterion) { diff --git a/prql-compiler/examples/compile-files/build.rs b/prql-compiler/examples/compile-files/build.rs index 6eb9eea9ee68..6edbd2f1d397 100644 --- a/prql-compiler/examples/compile-files/build.rs +++ b/prql-compiler/examples/compile-files/build.rs @@ -19,7 +19,7 @@ fn main() { let prql_string = fs::read_to_string(prql_path).unwrap(); // compile - let sql_string = compile(&prql_string, Options::default()).unwrap(); + let sql_string = compile(&prql_string, &Options::default()).unwrap(); // write file fs::write(sql_path, sql_string).unwrap(); diff --git a/prql-compiler/prql-compiler-macros/src/lib.rs b/prql-compiler/prql-compiler-macros/src/lib.rs index 2e36ebf24760..88e65b2eb281 100644 --- a/prql-compiler/prql-compiler-macros/src/lib.rs +++ b/prql-compiler/prql-compiler-macros/src/lib.rs @@ -26,7 +26,7 @@ pub fn prql_to_sql(input: TokenStream) -> TokenStream { let opts = prql_compiler::Options::default().no_format().no_signature(); - let sql_string = match prql_compiler::compile(&prql_string, opts) { + let sql_string = match prql_compiler::compile(&prql_string, &opts) { Ok(r) => r, Err(err) => { panic!("{}", err); diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index 555b4c4aa479..0ea1694b5bf1 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -136,7 +136,7 @@ impl Cli { serde_json::to_string_pretty(&ir)?.into_bytes() } - Cli::Compile(_) => compile(source, Options::default()) + Cli::Compile(_) => compile(source, &Options::default()) .map_or_else(|x| x.to_string(), |x| x) .as_bytes() .to_vec(), diff --git a/prql-compiler/prqlc/src/watch.rs b/prql-compiler/prqlc/src/watch.rs index 6c0f70121372..4084439627ba 100644 --- a/prql-compiler/prqlc/src/watch.rs +++ b/prql-compiler/prqlc/src/watch.rs @@ -115,7 +115,7 @@ fn compile_path(path: &Path, opt: &prql_compiler::Options) -> Result<()> { // compile println!("Compiling {}", prql_path.display()); - let sql_string = match prql_compiler::compile(&prql_string, opt.clone()) { + let sql_string = match prql_compiler::compile(&prql_string, opt) { Ok(sql_string) => sql_string, Err(err) => { let source_id = &prql_path.to_str().unwrap_or_default(); diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs index 2288b537b201..25d50b652745 100644 --- a/prql-compiler/src/lib.rs +++ b/prql-compiler/src/lib.rs @@ -42,7 +42,7 @@ //! # fn main() -> Result<(), prql_compiler::ErrorMessages> { //! let sql = prql_compiler::compile( //! "from albums | select [title, artist_id]", -//! prql_compiler::Options::default().no_format() +//! &prql_compiler::Options::default().no_format() //! )?; //! assert_eq!(&sql[..35], "SELECT title, artist_id FROM albums"); //! # Ok(()) @@ -109,19 +109,19 @@ pub static PRQL_VERSION: Lazy = /// ``` /// use prql_compiler::{compile, Options, Target, sql::Dialect}; /// -/// let prql = "from employees | select [name,age] "; -/// let opt = Options { +/// let prql = "from employees | select [name,age]"; +/// let opts = Options { /// format: false, /// target: Target::Sql(Some(Dialect::SQLite)), /// signature_comment: false /// }; -/// let sql = compile(&prql, opt).unwrap(); +/// let sql = compile(&prql, &opts).unwrap(); /// println!("PRQL: {}\nSQLite: {}", prql, &sql); /// assert_eq!("SELECT name, age FROM employees", sql) /// /// ``` /// See [`sql::Options`](sql/struct.Options.html) and [`sql::Dialect`](sql/enum.Dialect.html) for options and supported SQL dialects. -pub fn compile(prql: &str, options: Options) -> Result { +pub fn compile(prql: &str, options: &Options) -> Result { parser::parse(prql) .and_then(semantic::resolve) .and_then(|rq| sql::compile(rq, options)) @@ -237,7 +237,7 @@ pub fn pl_to_rq(pl: Vec) -> Result } /// Generate SQL from RQ. -pub fn rq_to_sql(rq: ast::rq::Query, options: Options) -> Result { +pub fn rq_to_sql(rq: ast::rq::Query, options: &Options) -> Result { sql::compile(rq, options).map_err(error::downcast) } diff --git a/prql-compiler/src/sql/dialect.rs b/prql-compiler/src/sql/dialect.rs index ecf767817cff..6bc52b2859c7 100644 --- a/prql-compiler/src/sql/dialect.rs +++ b/prql-compiler/src/sql/dialect.rs @@ -28,6 +28,7 @@ use strum::{EnumMessage, IntoEnumIterator}; PartialEq, Eq, Clone, + Copy, Serialize, Deserialize, strum::Display, diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index c109bc0deab0..76b8fe6b11dc 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -18,9 +18,9 @@ use crate::{ast::rq::Query, Options, PRQL_VERSION}; use self::{context::AnchorContext, dialect::DialectHandler}; /// Translate a PRQL AST into a SQL string. -pub fn compile(query: Query, options: Options) -> Result { +pub fn compile(query: Query, options: &Options) -> Result { let crate::Target::Sql(dialect) = options.target; - let sql_ast = gen_query::translate_query(query, dialect.clone())?; + let sql_ast = gen_query::translate_query(query, dialect)?; let sql = sql_ast.to_string(); @@ -76,7 +76,7 @@ mod test { #[test] fn test_end_with_new_line() { - let sql = compile("from a", Options::default().no_signature()).unwrap(); + let sql = compile("from a", &Options::default().no_signature()).unwrap(); assert_eq!(sql, "SELECT\n *\nFROM\n a\n") } } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index e695ed15b6fd..170c8cd42f45 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -4,7 +4,7 @@ use crate::{parser::parse, sql, Options, Target}; use insta::{assert_display_snapshot, assert_snapshot}; pub fn compile(prql: &str) -> Result { - crate::compile(prql, Options::default().no_signature()) + crate::compile(prql, &Options::default().no_signature()) } #[test] @@ -1493,14 +1493,14 @@ select [mng_name, managers.gender, salary_avg, salary_sd]"#; let sql_from_prql = parse(original_prql) .and_then(crate::semantic::resolve) - .and_then(|rq| sql::compile(rq, Options::default())) + .and_then(|rq| sql::compile(rq, &Options::default())) .unwrap(); let sql_from_json = crate::prql_to_pl(original_prql) .and_then(crate::json::from_pl) .and_then(|json| crate::json::to_pl(&json)) .and_then(crate::pl_to_rq) - .and_then(|rq| crate::rq_to_sql(rq, Options::default())) + .and_then(|rq| crate::rq_to_sql(rq, &Options::default())) .unwrap(); assert_eq!(sql_from_prql, sql_from_json); @@ -1537,7 +1537,7 @@ fn test_f_string() { assert_display_snapshot!( crate::compile( query, - Options::default() + &Options::default() .no_signature() .with_target(Target::Sql(Some(sql::Dialect::SQLite))) @@ -2776,13 +2776,13 @@ fn test_switch() { #[test] fn test_sql_options() { let options = Options::default(); - let sql = crate::compile("from x", options).unwrap(); + let sql = crate::compile("from x", &options).unwrap(); assert!(sql.contains('\n')); assert!(sql.contains("-- Generated by")); let options = Options::default().no_signature().no_format(); - let sql = crate::compile("from x", options).unwrap(); + let sql = crate::compile("from x", &options).unwrap(); assert!(!sql.contains('\n')); assert!(!sql.contains("-- Generated by")); diff --git a/prql-compiler/tests/integration/main.rs b/prql-compiler/tests/integration/main.rs index c51ae2fd1dc7..484e05bc124d 100644 --- a/prql-compiler/tests/integration/main.rs +++ b/prql-compiler/tests/integration/main.rs @@ -34,14 +34,14 @@ mod tests { let opts = Options::default() .with_target(Target::Sql(Some(Dialect::SQLite))) .no_format(); - let sql = prql_compiler::compile(&prql, opts).unwrap(); + let sql = prql_compiler::compile(&prql, &opts).unwrap(); let sqlite_out = sqlite::query_csv(&sqlite_conn, &sql); // save both csv files as same snapshot let opts = Options::default() .with_target(Target::Sql(Some(Dialect::DuckDb))) .no_format(); - let sql = prql_compiler::compile(&prql, opts).unwrap(); + let sql = prql_compiler::compile(&prql, &opts).unwrap(); let duckdb_out = duckdb::query_csv(&duckdb_conn, &sql); pretty_assertions::assert_eq!(sqlite_out, duckdb_out, "SQLite == DuckDB: {test_name}"); @@ -49,7 +49,7 @@ mod tests { let opts = Options::default() .with_target(Target::Sql(Some(Dialect::PostgreSql))) .no_format(); - let sql = prql_compiler::compile(&prql, opts).unwrap(); + let sql = prql_compiler::compile(&prql, &opts).unwrap(); let pg_out = postgres::query_csv(pg_client, &sql); pretty_assertions::assert_eq!(sqlite_out, pg_out, "SQLite == PG: {test_name}"); } diff --git a/prql-elixir/native/prql/src/lib.rs b/prql-elixir/native/prql/src/lib.rs index 2a5967eb9ba1..97eaa11f1c97 100644 --- a/prql-elixir/native/prql/src/lib.rs +++ b/prql-elixir/native/prql/src/lib.rs @@ -120,7 +120,7 @@ pub struct Response { #[rustler::nif] /// compile a prql query into sql pub fn compile(prql_query: &str, options: CompileOptions) -> NifResult { - to_result_tuple(prql_compiler::compile(prql_query, options.into())) + to_result_tuple(prql_compiler::compile(prql_query, &options.into())) } #[rustler::nif] @@ -152,7 +152,7 @@ pub fn rq_to_sql(rq_json: &str) -> NifResult { .and_then(prql_compiler::json::to_rq) // Currently just using default options here; probably should pass // an argument from this func. - .and_then(|x| prql_compiler::rq_to_sql(x, prql_compiler::Options::default())), + .and_then(|x| prql_compiler::rq_to_sql(x, &prql_compiler::Options::default())), ) } diff --git a/prql-java/src/lib.rs b/prql-java/src/lib.rs index b4238032486c..6c59dfa9fb24 100644 --- a/prql-java/src/lib.rs +++ b/prql-java/src/lib.rs @@ -14,7 +14,7 @@ pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_toSql( .get_string(query) .expect("Couldn't get java string!") .into(); - let rs_sql_str: String = prql_compiler::compile(&prql_query, Options::default()) + let rs_sql_str: String = prql_compiler::compile(&prql_query, &Options::default()) .expect("Couldn't compile query to prql!"); env.new_string(rs_sql_str) .expect("Couldn't create java string!") diff --git a/prql-js/src/lib.rs b/prql-js/src/lib.rs index aa4caca95c46..2e17e7e48703 100644 --- a/prql-js/src/lib.rs +++ b/prql-js/src/lib.rs @@ -10,7 +10,7 @@ use wasm_bindgen::prelude::*; #[wasm_bindgen] pub fn compile(prql_query: &str, options: Option) -> Option { return_or_throw( - prql_compiler::compile(prql_query, options.map(|x| x.into()).unwrap_or_default()) + prql_compiler::compile(prql_query, &options.map(|x| x.into()).unwrap_or_default()) .map_err(|e| e.composed("", prql_query, false)), ) } @@ -39,7 +39,7 @@ pub fn rq_to_sql(rq_json: &str) -> Option { return_or_throw( Ok(rq_json) .and_then(prql_compiler::json::to_rq) - .and_then(|x| prql_compiler::rq_to_sql(x, prql_compiler::Options::default())), + .and_then(|x| prql_compiler::rq_to_sql(x, &prql_compiler::Options::default())), ) } diff --git a/prql-lib/src/lib.rs b/prql-lib/src/lib.rs index 2d920ad2474c..2f741b3a40ac 100644 --- a/prql-lib/src/lib.rs +++ b/prql-lib/src/lib.rs @@ -16,7 +16,7 @@ use std::ffi::CString; pub unsafe extern "C" fn to_sql(query: *const c_char, out: *mut c_char) -> c_int { let prql_query: String = CStr::from_ptr(query).to_string_lossy().into_owned(); - let (isErr, sql_result) = match prql_compiler::compile(&prql_query, Options::default()) { + let (isErr, sql_result) = match prql_compiler::compile(&prql_query, &Options::default()) { Ok(sql_str) => (false, sql_str), Err(err) => { //let err_str = format!("{}", err); diff --git a/prql-python/src/lib.rs b/prql-python/src/lib.rs index 4e7919d3aff7..1202df209d82 100644 --- a/prql-python/src/lib.rs +++ b/prql-python/src/lib.rs @@ -9,7 +9,7 @@ pub fn compile(prql_query: &str, options: Option) -> PyResult(e.into_only().unwrap().reason))) } @@ -35,7 +35,7 @@ pub fn pl_to_rq(pl_json: &str) -> PyResult { pub fn rq_to_sql(rq_json: &str) -> PyResult { Ok(rq_json) .and_then(prql_compiler::json::to_rq) - .and_then(|x| prql_compiler::rq_to_sql(x, prql_compiler::Options::default())) + .and_then(|x| prql_compiler::rq_to_sql(x, &prql_compiler::Options::default())) .map_err(|err| (PyErr::new::(err.to_json()))) } From 311ccd92ded62b151dc034708002824df4014a69 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Feb 2023 11:02:59 -0800 Subject: [PATCH 029/184] chore: pre-commit autoupdate (#1908) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/charliermarsh/ruff-pre-commit: v0.0.246 โ†’ v0.0.248](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.246...v0.0.248) - [github.com/pre-commit/mirrors-mypy: v1.0.0 โ†’ v1.0.1](https://github.com/pre-commit/mirrors-mypy/compare/v1.0.0...v1.0.1) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a2623a4cf4ae..5f4006248d49 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -21,7 +21,7 @@ repos: - prettier - prettier-plugin-go-template - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.246 + rev: v0.0.248 hooks: - id: ruff - repo: https://github.com/psf/black @@ -34,7 +34,7 @@ repos: - id: fmt - id: clippy - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.0.0 + rev: v1.0.1 hooks: - id: mypy additional_dependencies: ["types-PyYAML==6.0.12.4"] From 043f401cedb4e1a72f8fa01d9d08d3ab6626ef92 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 20 Feb 2023 12:16:23 -0800 Subject: [PATCH 030/184] docs: Add a doc on `prql-elixir` on Mac (#1909) * docs: Add a doc on `prql-elixir` on Mac --- prql-elixir/README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/prql-elixir/README.md b/prql-elixir/README.md index ed30ffa0ab2e..e3b7c7e0b956 100644 --- a/prql-elixir/README.md +++ b/prql-elixir/README.md @@ -69,3 +69,34 @@ The possible future workarounds include: If `prql-elixir` becomes more used (for example, we start publishing to Hex, or Mac developers want to work on it), then we can re-enable and deal with the caching issues. We can also re-enable them if the `cargo` issue is resolved. + +To test on Mac temporarily โ€”ย for example if there's an error in GHA and we're on +a Mac locally โ€” apply a diff like this, and then run `cargo build` from the +`prql-elixir` path, which will enable the local +[`.cargo/config.toml`](native/prql/.cargo/config.toml)). (We could also make a +feature like `elixir-mac` which enabled building on Mac). + +```diff +diff --git a/prql-elixir/native/prql/Cargo.toml b/prql-elixir/native/prql/Cargo.toml +index a39a9ee..218abad 100644 +--- a/prql-elixir/native/prql/Cargo.toml ++++ b/prql-elixir/native/prql/Cargo.toml +@@ -17,7 +17,4 @@ path = "src/lib.rs" + + [dependencies] + prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.2"} +- +-# See Readme for details on Mac +-[target.'cfg(not(any(target_family="wasm", target_os = "macos")))'.dependencies] + rustler = "0.27.0" +diff --git a/prql-elixir/native/prql/src/lib.rs b/prql-elixir/native/prql/src/lib.rs +index 97eaa11..7525479 100644 +--- a/prql-elixir/native/prql/src/lib.rs ++++ b/prql-elixir/native/prql/src/lib.rs +@@ -1,5 +1,3 @@ +-// See Readme for more information on Mac compiling +-#![cfg(not(target_os = "macos"))] + // These bindings aren't relevant on wasm + #![cfg(not(target_family = "wasm"))] + // TODO: unclear why we need this `allow`; it's required in `CompileOptions`, +``` From cab50cccae8d1f6c3d47759b1a22c0d508a732ba Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 20 Feb 2023 13:29:58 -0800 Subject: [PATCH 031/184] ci: Run non-core tests through `test-all.yaml` (#1911) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ci: Run non-core tests through `test-all.yaml` As pointed out in https://github.com/PRQL/prql/pull/1860/files#r1112279486, we're currently running these tests twice โ€” once because they're in the `test-all.yaml` workflow, which is called on `main` commits, and once because they're called on `main` themselves. This disables them being called by `main` commits. It's possible the existing mode is required to generate caches; let's try disabling and assess, though. --- .github/workflows/test-elixir.yaml | 3 --- .github/workflows/test-java.yaml | 3 --- .github/workflows/test-js.yaml | 3 --- .github/workflows/test-python.yaml | 3 --- .github/workflows/test-taskfile.yaml | 4 ---- 5 files changed, 16 deletions(-) diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index 31d4c9caaea9..89b0b34097ac 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -1,9 +1,6 @@ name: test-elixir on: - push: - branches: - - main pull_request: paths: - "prql-elixir/**" diff --git a/.github/workflows/test-java.yaml b/.github/workflows/test-java.yaml index 7eac03959c0c..780c87f3da28 100644 --- a/.github/workflows/test-java.yaml +++ b/.github/workflows/test-java.yaml @@ -1,9 +1,6 @@ name: test-java on: - push: - branches: - - main pull_request: paths: - "prql-java/**" diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index bb25f46cc634..dd2e4892b4fb 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -1,9 +1,6 @@ name: test-js on: - push: - branches: - - main pull_request: paths: - "prql-js/**" diff --git a/.github/workflows/test-python.yaml b/.github/workflows/test-python.yaml index fd00d6c82242..212967b4928a 100644 --- a/.github/workflows/test-python.yaml +++ b/.github/workflows/test-python.yaml @@ -1,9 +1,6 @@ name: test-python on: - push: - branches: - - main pull_request: paths: - "prql-python/**" diff --git a/.github/workflows/test-taskfile.yaml b/.github/workflows/test-taskfile.yaml index cb6ab15be302..5a9fe8c3449c 100644 --- a/.github/workflows/test-taskfile.yaml +++ b/.github/workflows/test-taskfile.yaml @@ -2,11 +2,7 @@ name: test-taskfile on: - push: - branches: - - main pull_request: - types: [opened, reopened, synchronize, labeled] paths: - Taskfile.yml - .github/workflows/test-taskfile.yaml From 4a8b915eef940b5ef1231b915ceaa210b7a1e86b Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 20 Feb 2023 22:41:05 +0100 Subject: [PATCH 032/184] build: Add PHP binding (#1860) * Update README.md * Create php.md * Create .gitignore * Add files via upload * Update composer.json * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update composer.json * Update Compiler.php * Update prql-php/.gitignore Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Add composer lock file * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Create test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update composer.json * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update composer.json * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Uncomment unit tests * Pass test dir as args * Bootstrap the autoloader * Build library and copy library file * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Update test-php.yaml * Add more unit tests * Update CompilerTest.php * Update test-php.yaml * Update CompilerTest.php * Update test-php.yaml * Add test-php * Add concurrency thing Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Remove php-actions/phpunit * Update .github/workflows/test-php.yaml --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: Maximilian Roos --- .github/workflows/test-all.yaml | 3 + .github/workflows/test-php.yaml | 42 + book/src/bindings/README.md | 1 + book/src/bindings/php.md | 1 + prql-php/.gitignore | 1 + prql-php/README.md | 25 + prql-php/composer.json | 37 + prql-php/composer.lock | 1471 +++++++++++++++++++++++++++++++ prql-php/src/Compiler.php | 162 ++++ prql-php/src/Options.php | 54 ++ prql-php/tests/CompilerTest.php | 49 + 11 files changed, 1846 insertions(+) create mode 100644 .github/workflows/test-php.yaml create mode 100644 book/src/bindings/php.md create mode 100644 prql-php/.gitignore create mode 100644 prql-php/README.md create mode 100644 prql-php/composer.json create mode 100644 prql-php/composer.lock create mode 100644 prql-php/src/Compiler.php create mode 100644 prql-php/src/Options.php create mode 100644 prql-php/tests/CompilerTest.php diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 3646199f3c43..065698e9baca 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -32,6 +32,9 @@ jobs: os: ${{ matrix.os }} target_option: ${{ matrix.target_option }} + test-php: + uses: ./.github/workflows/test-php.yaml + test-python: uses: ./.github/workflows/test-python.yaml diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml new file mode 100644 index 000000000000..af2b19202350 --- /dev/null +++ b/.github/workflows/test-php.yaml @@ -0,0 +1,42 @@ +name: test-php + +on: + pull_request: + paths: + - "prql-php/**" + - ".github/workflows/test-php.yaml" + workflow_call: + +concurrency: + # See notes in `pull-request.yaml` + group: ${{ github.workflow }}-${{ github.ref }}-php + cancel-in-progress: true + +jobs: + test: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest] + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: stable + - run: cargo build + working-directory: prql-lib + - run: | + mv ../target/debug/libprql_lib.so ../prql-php/src/libprql_lib.so + ls -l ../target/debug/ + uname -a + ls -lR ../prql-php/ + working-directory: prql-lib + - name: ๐Ÿ“ฆ Install dependencies using Composer + uses: php-actions/composer@v6 + with: + args: --working-dir=prql-php + php_extensions: FFI + - name: ๐Ÿงช Run tests using PHPUnit + run: vendor/bin/phpunit tests + working-directory: prql-php diff --git a/book/src/bindings/README.md b/book/src/bindings/README.md index f7056439154f..7d02f68f90dc 100644 --- a/book/src/bindings/README.md +++ b/book/src/bindings/README.md @@ -4,6 +4,7 @@ PRQL has bindings for many languages. These include: - [Java](./java.md) - [JavaScript](./javascript.md) +- [PHP](./php.md) - [Python](./python.md) - [R](./r.md) - [Rust](./rust.md) diff --git a/book/src/bindings/php.md b/book/src/bindings/php.md new file mode 100644 index 000000000000..e168db425270 --- /dev/null +++ b/book/src/bindings/php.md @@ -0,0 +1 @@ +{{#include ../../../prql-php/README.md}} diff --git a/prql-php/.gitignore b/prql-php/.gitignore new file mode 100644 index 000000000000..61ead86667ca --- /dev/null +++ b/prql-php/.gitignore @@ -0,0 +1 @@ +/vendor diff --git a/prql-php/README.md b/prql-php/README.md new file mode 100644 index 000000000000..3b417479a4c4 --- /dev/null +++ b/prql-php/README.md @@ -0,0 +1,25 @@ +# prql-php + +`prql-php` offers PHP bindings through FFI. + +It provides the `Compiler` class which contains the `toJson` and `toSql` +methods. + +It's still at an early stage, and isn't published to Composer. Contributions are +welcome. + +## Installation + +The [PHP FFI extension](https://www.php.net/manual/en/book.ffi.php) needs to be +enabled. Set `ffi.enable` in your php.ini configuration file to `"true"`. + +## Usage + +```php +toSql("from employees"); +``` diff --git a/prql-php/composer.json b/prql-php/composer.json new file mode 100644 index 000000000000..7fad323e451e --- /dev/null +++ b/prql-php/composer.json @@ -0,0 +1,37 @@ +{ + "name": "prql/compiler", + "description": "PRQL compiler bindings.", + "keywords": [ + "prql", + "sql" + ], + "homepage": "https://prql-lang.org/", + "type": "library", + "license": "Apache-2.0", + "autoload": { + "psr-4": { + "Prql\\Compiler\\": "src/" + } + }, + "autoload-dev": { + "psr-4": { + "Prql\\Tests\\": "tests/" + } + }, + "authors": [ + { + "name": "Jonathan" + } + ], + "support": { + "issues": "https://github.com/PRQL/prql/issues", + "source": "https://github.com/PRQL/prql", + "docs": "https://prql-lang.org/book/" + }, + "require": { + "ext-ffi": "*" + }, + "require-dev": { + "phpunit/phpunit": "^10" + } +} diff --git a/prql-php/composer.lock b/prql-php/composer.lock new file mode 100644 index 000000000000..bb8cb1d27700 --- /dev/null +++ b/prql-php/composer.lock @@ -0,0 +1,1471 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "a4068cec0f3425baf61d7b880f827bea", + "packages": [], + "packages-dev": [ + { + "name": "myclabs/deep-copy", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/14daed4296fae74d9e3201d2c4925d1acb7aa614", + "reference": "14daed4296fae74d9e3201d2c4925d1acb7aa614", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": ["src/DeepCopy/deep_copy.php"], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["MIT"], + "description": "Create deep copies (clones) of your objects", + "keywords": ["clone", "copy", "duplicate", "object", "object graph"], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2022-03-03T13:19:32+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.15.3", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "reference": "570e980a201d8ed0236b0a62ddf2c9cbb2034039", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": ["bin/php-parse"], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": ["parser", "php"], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.3" + }, + "time": "2023-01-16T22:05:37+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "bf4fbc9c13af7da12b3ea807574fb460f255daba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bf4fbc9c13af7da12b3ea807574fb460f255daba", + "reference": "bf4fbc9c13af7da12b3ea807574fb460f255daba", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.14", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcov": "*", + "ext-xdebug": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": ["coverage", "testing", "xunit"], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:14:34+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/fd9329ab3368f59fe1fe808a189c51086bd4b6bd", + "reference": "fd9329ab3368f59fe1fe808a189c51086bd4b6bd", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": ["filesystem", "iterator"], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-10T16:53:14+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": ["process"], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": ["template"], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:46+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": ["timer"], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.0.7", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "a6f61c5629dd95db79af72f1e94d56702187479a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a6f61c5629dd95db79af72f1e94d56702187479a", + "reference": "a6f61c5629dd95db79af72f1e94d56702187479a", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.0", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.0", + "sebastian/global-state": "^6.0", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "*" + }, + "bin": ["phpunit"], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.0-dev" + } + }, + "autoload": { + "files": ["src/Framework/Assert/Functions.php"], + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": ["phpunit", "testing", "xunit"], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.0.7" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-02-08T15:16:31+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/72f01e6586e0caf6af81297897bd112eb7e9627c", + "reference": "72f01e6586e0caf6af81297897bd112eb7e9627c", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": ["comparator", "compare", "equality"], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:07:16+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:47+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "70dd1b20bc198da394ad542e988381b44e64e39f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/70dd1b20bc198da394ad542e988381b44e64e39f", + "reference": "70dd1b20bc198da394ad542e988381b44e64e39f", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": ["diff", "udiff", "unidiff", "unified diff"], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:00:31+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "b6f3694c6386c7959915a0037652e0c40f6f69cc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/b6f3694c6386c7959915a0037652e0c40f6f69cc", + "reference": "b6f3694c6386c7959915a0037652e0c40f6f69cc", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": ["Xdebug", "environment", "hhvm"], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:03:04+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": ["export", "exporter"], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:49+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "aab257c712de87b90194febd52e4d184551c2d44" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/aab257c712de87b90194febd52e4d184551c2d44", + "reference": "aab257c712de87b90194febd52e4d184551c2d44", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": ["global state"], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:07:38+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:02+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": ["src/"] + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "ext-ffi": "*" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/prql-php/src/Compiler.php b/prql-php/src/Compiler.php new file mode 100644 index 000000000000..5be55ea51962 --- /dev/null +++ b/prql-php/src/Compiler.php @@ -0,0 +1,162 @@ +new("struct options"); + $ffi_options->format = $options->format; + $ffi_options->signature_comment = $options->signature_comment; + + if (isset($options->target)) { + $target_len = strlen($options->target); + $ffi_options->target = $ffi->new('char[$target_len]', 0); + FFI::memcpy($ffi_options->target, $options->target, $target_len); + FFI::free($ffi_options->target); + } + + $out = str_pad("", 1024); + if ($libprql->compile($prql_query, \FFI::addr($$ffi_options)) !== 0) { + throw new \InvalidArgumentException("Could not compile query."); + } + + return trim($out); + } + + /** + * Compile a PRQL string into a JSON string. + * + * @param string $prql_query A PRQL query. + * + * @return string JSON string. + * @throws \InvalidArgumentException If no query is given or the query cannot + * be compiled. + * @api + */ + function toJson(string $prql_query): string + { + if (!$prql_query) { + throw new \InvalidArgumentException("No query given."); + } + + $library = "/libprql_lib.so"; + + if (PHP_OS_FAMILY === "Windows") { + $library = "\libprql_lib.dll"; + } + + $libprql = \FFI::cdef( + "int to_json(char *prql_query, char *json_query);", + __DIR__ . $library + ); + + $out = str_pad("", 1024); + if ($libprql->to_json($prql_query, $out) !== 0) { + throw new \InvalidArgumentException("Could not compile query."); + } + + return trim($out); + } + + /** + * Compile a PRQL string into a SQL string. + * + * @param string $prql_query A PRQL query. + * + * @return string SQL query. + * @throws \InvalidArgumentException If no query is given or the query cannot + * be compiled. + * @api + */ + function toSql(string $prql_query): string + { + if (!$prql_query) { + throw new \InvalidArgumentException("No query given."); + } + + $library = "/libprql_lib.so"; + + if (PHP_OS_FAMILY === "Windows") { + $library = "\libprql_lib.dll"; + } + + $libprql = \FFI::cdef( + "int to_sql(char *prql_query, char *sql_query);", + __DIR__ . $library + ); + + $out = str_pad("", 1024); + if ($libprql->to_sql($prql_query, $out) !== 0) { + throw new \InvalidArgumentException("Could not compile query."); + } + + return trim($out); + } +} diff --git a/prql-php/src/Options.php b/prql-php/src/Options.php new file mode 100644 index 000000000000..3b76344df3e2 --- /dev/null +++ b/prql-php/src/Options.php @@ -0,0 +1,54 @@ +assertTrue(extension_loaded("ffi")); + } + + public function testPrqlLibraryFileExists(): void + { + $this->assertFileExists("src/libprql_lib.so"); + } + + public function testPrqlLibraryLoads(): void + { + $code = "int to_sql(char *prql_query, char *sql_query);"; + $ffi = FFI::cdef($code, "src/libprql_lib.so"); + $this->assertInstanceOf(FFI::class, $ffi); + } + + public function testInvalidQueryThrows(): void + { + $this->expectException(\InvalidArgumentException::class); + + $prql = new Compiler(); + $prql->toSql("invalid"); + } + + public function testToSqlWorks(): void + { + $expected = <<<'EOD' +SELECT + * +FROM + employees + +-- Generated by PRQL compiler version:0.5.0 (https://prql-lang.org) +EOD; + $expected = substr($expected, 0, strpos($expected, "Generated by PRQL compiler")); + $prql = new Compiler(); + $actual = $prql->toSql("from employees"); + $actual = substr($actual, 0, strpos($actual, "Generated by PRQL compiler")); + $this->assertEquals($expected, $actual); + } +} From b965aba270777f811897cec2678cc98c537e9a0a Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 01:53:53 +0100 Subject: [PATCH 033/184] chore: Add PHP bindings changelog (#1914) Add PHP bindings --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa1d666d8796..81379273a7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ **Integrations**: +- [prql-php] Added PHP bindings (@vanillajonathan, #1860) - [prql-lib] Added C header file (@vanillajonathan, #1879) **Internal changes**: From 2ecdfaac4796e12772afd0394268fdd9f366ab02 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 02:16:33 +0100 Subject: [PATCH 034/184] build: Package prqlc as .deb package (#1883) * Create create-deb.yaml * Update create-deb.yaml * Update create-deb.yaml * Update create-deb.yaml * Add build-deb-package job * Delete create-deb.yaml * Update .github/workflows/release.yaml * Update .github/workflows/release.yaml * Update .github/workflows/release.yaml --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: Maximilian Roos --- .github/workflows/release.yaml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d7d944410b54..252d16dbabdb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -24,6 +24,30 @@ jobs: } }) + build-deb-package: + # TODO: currently this doesn't publish it as an artifact; would be a welcome contribution + # to add that (and eventually as a release asset) + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - name: ๐Ÿ‘ท Build prql-compiler + run: cargo build --release + - name: Copy files into .deb package + run: | + mkdir -p .debpkg/usr/bin + cp target/release/prqlc .debpkg/usr/bin/prqlc + chmod +x .debpkg/usr/bin/prqlc + - name: ๐Ÿ“ฆ Build .deb package + uses: jiro4989/build-deb-action@v2 + with: + package: prqlc + package_root: .debpkg + maintainer: The PRQL Project + version: "${{ github.ref }}" + desc: + prqlc is the CLI for PRQL, a modern language for transforming data + build-python-wheels: runs-on: ${{ matrix.os }} strategy: From 68752b7806cee40af10b22d44609230ed2a78dc1 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 20 Feb 2023 23:48:07 -0800 Subject: [PATCH 035/184] test: Add `--quiet` to fast-loop taskfile command (#1916) Otherwise cargo lists the name of every test; very verbose IMO. --- Taskfile.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Taskfile.yml b/Taskfile.yml index ec901be0fa55..15995412728a 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -233,7 +233,7 @@ tasks: - "prql-compiler/**/*.pest" - "prql-compiler/**/*.snap" cmds: - - cargo insta test --accept -p prql-compiler --lib + - cargo insta test --accept -p prql-compiler --lib -- --quiet build-web: desc: Build the website, including the book & playground. From f489690d0db2ddd391f229002509fa8fb97b8469 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 18:58:42 +0100 Subject: [PATCH 036/184] build: Package`prqlc` as Snap (#1881) * Create snapcraft.yaml * Update snapcraft.yaml * Create publish-snap.yaml * Update publish-snap.yaml * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update prql-compiler/snap/snapcraft.yaml Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update publish-snap.yaml * Update snapcraft.yaml * Update and rename prql-compiler/snap/snapcraft.yaml to snap/snapcraft.yaml * Update publish-snap.yaml * Update snap/snapcraft.yaml Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Add step to build and publish Snap * Delete publish-snap.yaml --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- .github/workflows/release.yaml | 19 +++++++++++++++++++ snap/snapcraft.yaml | 28 ++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 snap/snapcraft.yaml diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 252d16dbabdb..d743b489baf7 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -48,6 +48,25 @@ jobs: desc: prqlc is the CLI for PRQL, a modern language for transforming data + build-and-publish-snap: + runs-on: ubuntu-latest + + # Skip running workflow on forks + if: github.repository_owner == 'prql' + + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - name: ๐Ÿ“ฆ Build Snap + uses: snapcore/action-build@v1 + - name: ๐Ÿ†™ Publish Snap + uses: snapcore/action-publish@v1 + env: + SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.STORE_LOGIN }} + with: + snap: ${{ steps.build.outputs.snap }} + release: edge + build-python-wheels: runs-on: ${{ matrix.os }} strategy: diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml new file mode 100644 index 000000000000..6f9bda5cd9a7 --- /dev/null +++ b/snap/snapcraft.yaml @@ -0,0 +1,28 @@ +name: prqlc # you probably want to 'snapcraft register ' +title: PRQL Compiler +base: core20 # the base snap is the execution environment for this snap +version: git +summary: PRQL is a modern language for transforming data +description: | + PRQL is a modern language for transforming data โ€” a simple, powerful, + pipelined SQL replacement. +issues: https://github.com/PRQL/prql/issues +source-code: https://github.com/PRQL/prql +contact: https://twitter.com/prql_lang +website: https://prql-lang.org/ +license: Apache-2.0 +grade: devel # must be 'stable' to release into candidate/stable channels +confinement: strict +icon: website/themes/prql-theme/static/icon.svg + +parts: + prqlc: + plugin: rust + source: . + rust-path: [prql-compiler/prqlc] + +apps: + prqlc: + command: bin/prqlc + plugs: + - home From f765378e654f520173ef38e3cddedc4a64096a41 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 21 Feb 2023 10:33:18 -0800 Subject: [PATCH 037/184] chore: Add changelog for #1883 (#1920) As requested by @vanillajonathan. @vanillajonathan one thing we could add for all these is to upload them as artifacts, as an easy way to have them published, using something like https://github.com/PRQL/prql/pull/1883#discussion_r1112342801. It's less permanent than publishing them as release assets, but we can do the artifact upload now without changing our release process. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81379273a7f8..80645f98bf6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ - [prql-php] Added PHP bindings (@vanillajonathan, #1860) - [prql-lib] Added C header file (@vanillajonathan, #1879) +- Added a workflow building a `.deb` on each release. (Note that it's not yet + published on each release). (@vanillajonathan, #1883) **Internal changes**: From ba2c01c7a7ed013ff3cf4f9ec80a7a08024df16b Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 21:47:13 +0100 Subject: [PATCH 038/184] chore: Add Snap package changelog (#1921) * Add Snap package * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80645f98bf6d..340164cfa4a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,10 +12,12 @@ **Integrations**: -- [prql-php] Added PHP bindings (@vanillajonathan, #1860) -- [prql-lib] Added C header file (@vanillajonathan, #1879) +- [prql-php] Added PHP bindings. (@vanillajonathan, #1860) +- [prql-lib] Added C header file. (@vanillajonathan, #1879) - Added a workflow building a `.deb` on each release. (Note that it's not yet published on each release). (@vanillajonathan, #1883) +- Added a workflow building a Snap package on each release. (@vanillajonathan, + #1881) **Internal changes**: From 83b5a79c19d5fc89742e450626b6ab6883b0f18c Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 21:55:32 +0100 Subject: [PATCH 039/184] build: Package prqlc as .rpm package (#1918) * Create create-rpm.yaml * Update create-rpm.yaml * Add job for building .rpm package * Delete create-rpm.yaml * Update .github/workflows/release.yaml Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update .github/workflows/release.yaml Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update release.yaml * Update .github/workflows/release.yaml Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update .github/workflows/release.yaml * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: Maximilian Roos Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/release.yaml | 29 ++++++++++++++++++++++++++++- prql-compiler/prqlc/x.prql | 3 +++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 prql-compiler/prqlc/x.prql diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d743b489baf7..854963fbb02a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -44,10 +44,37 @@ jobs: package: prqlc package_root: .debpkg maintainer: The PRQL Project - version: "${{ github.ref }}" + version: ${{ github.ref }} desc: prqlc is the CLI for PRQL, a modern language for transforming data + build-rpm-package: + # TODO: This doesn't publish the rpm yet, that would be a welcome follow-up (even as a CI artifact) + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - name: ๐Ÿ‘ท Build prqlc + run: cargo build --bin prqlc --release + - name: Copy files into .rpm package + run: | + mkdir -p .rpmpkg/usr/bin + cp target/release/prqlc .rpmpkg/usr/bin/prqlc + chmod +x .rpmpkg/usr/bin/prqlc + - name: ๐Ÿ“ฆ Build .rpm package + uses: jiro4989/build-rpm-action@v2 + with: + summary: CLI for PRQL, a modern language for transforming data + package: prqlc + package_root: .rpmpkg + maintainer: The PRQL Project + version: ${{ github.ref }} + desc: | + prqlc is the CLI for the PRQL compiler. It compiles PRQL to SQL, and offers various diagnostics. + + PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement. + license: Apache-2.0 + build-and-publish-snap: runs-on: ubuntu-latest diff --git a/prql-compiler/prqlc/x.prql b/prql-compiler/prqlc/x.prql new file mode 100644 index 000000000000..ed56de0b1bc9 --- /dev/null +++ b/prql-compiler/prqlc/x.prql @@ -0,0 +1,3 @@ +let x = 2 + 2 + +from x From 36a0a1e7a26fff594043cf26575ba1dd378d4d7a Mon Sep 17 00:00:00 2001 From: Jonathan Date: Tue, 21 Feb 2023 22:51:35 +0100 Subject: [PATCH 040/184] feat: Add .NET bindings (#1917) --- .github/workflows/test-dotnet.yaml | 33 +++++ CHANGELOG.md | 1 + book/src/bindings/README.md | 1 + book/src/bindings/net.md | 1 + .../PrqlCompiler.Tests/CompilerTest.cs | 23 ++++ .../PrqlCompiler.Tests.csproj | 28 +++++ prql-dotnet/PrqlCompiler.Tests/Usings.cs | 1 + prql-dotnet/PrqlCompiler/PrqlCompiler.cs | 113 ++++++++++++++++++ prql-dotnet/PrqlCompiler/PrqlCompiler.csproj | 28 +++++ .../PrqlCompiler/PrqlCompilerOptions.cs | 26 ++++ prql-dotnet/README.md | 33 +++++ prql-dotnet/prql-net.sln | 28 +++++ 12 files changed, 316 insertions(+) create mode 100644 .github/workflows/test-dotnet.yaml create mode 100644 book/src/bindings/net.md create mode 100644 prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs create mode 100644 prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj create mode 100644 prql-dotnet/PrqlCompiler.Tests/Usings.cs create mode 100644 prql-dotnet/PrqlCompiler/PrqlCompiler.cs create mode 100644 prql-dotnet/PrqlCompiler/PrqlCompiler.csproj create mode 100644 prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs create mode 100644 prql-dotnet/README.md create mode 100644 prql-dotnet/prql-net.sln diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml new file mode 100644 index 000000000000..eae9601d8d02 --- /dev/null +++ b/.github/workflows/test-dotnet.yaml @@ -0,0 +1,33 @@ +name: test-dotnet + +on: + pull_request: + paths: + - "prql-dotnet/**" + - ".github/workflows/test-dotnet.yaml" + workflow_call: + +concurrency: + # See notes in `pull-request.yaml` + group: ${{ github.workflow }}-${{ github.ref }}-dotnet + cancel-in-progress: true + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - name: ๐Ÿ— Build prql-lib + run: cargo build + working-directory: prql-lib + - name: ๐Ÿ”ง Setup dotnet + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 7 + - name: ๐Ÿงช Build and test + run: | + dotnet build prql-dotnet + cp target/debug/libprql_lib.* prql-dotnet/PrqlCompiler/bin/Debug/net*/ + cp target/debug/libprql_lib.* prql-dotnet/PrqlCompiler.Tests/bin/Debug/net*/ + dotnet test prql-dotnet diff --git a/CHANGELOG.md b/CHANGELOG.md index 340164cfa4a6..f0908cbf315b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ **Integrations**: - [prql-php] Added PHP bindings. (@vanillajonathan, #1860) +- [prql-dotnet] Added .NET bindings. (@vanillajonathan, #1917) - [prql-lib] Added C header file. (@vanillajonathan, #1879) - Added a workflow building a `.deb` on each release. (Note that it's not yet published on each release). (@vanillajonathan, #1883) diff --git a/book/src/bindings/README.md b/book/src/bindings/README.md index 7d02f68f90dc..216ac63f40aa 100644 --- a/book/src/bindings/README.md +++ b/book/src/bindings/README.md @@ -4,6 +4,7 @@ PRQL has bindings for many languages. These include: - [Java](./java.md) - [JavaScript](./javascript.md) +- [.NET](./net.md) - [PHP](./php.md) - [Python](./python.md) - [R](./r.md) diff --git a/book/src/bindings/net.md b/book/src/bindings/net.md new file mode 100644 index 000000000000..a1cdb27aa1e3 --- /dev/null +++ b/book/src/bindings/net.md @@ -0,0 +1 @@ +{{#include ../../../prql-net/README.md}} diff --git a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs new file mode 100644 index 000000000000..a5afa68f0942 --- /dev/null +++ b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs @@ -0,0 +1,23 @@ +using Prql.Compiler; + +namespace Prql.Compiler.Tests; + +sealed public class CompilerTest +{ + [Fact] + public void ToSql_Works() + { + // Arrange + var expected = "SELECT\n *\nFROM\n employees\n\n" + + "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; + var signature = "-- Generated by PRQL compiler"; + expected = expected.Substring(0, expected.IndexOf(signature)); + + // Act + var sqlQuery = PrqlCompiler.ToSql("from employees"); + sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); + + // Assert + Assert.Equal(expected, sqlQuery); + } +} diff --git a/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj b/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj new file mode 100644 index 000000000000..9fb2ba1630fb --- /dev/null +++ b/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj @@ -0,0 +1,28 @@ + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/prql-dotnet/PrqlCompiler.Tests/Usings.cs b/prql-dotnet/PrqlCompiler.Tests/Usings.cs new file mode 100644 index 000000000000..c802f4480b19 --- /dev/null +++ b/prql-dotnet/PrqlCompiler.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; diff --git a/prql-dotnet/PrqlCompiler/PrqlCompiler.cs b/prql-dotnet/PrqlCompiler/PrqlCompiler.cs new file mode 100644 index 000000000000..04843d088d05 --- /dev/null +++ b/prql-dotnet/PrqlCompiler/PrqlCompiler.cs @@ -0,0 +1,113 @@ +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Prql.Compiler +{ + /// + /// The PRQL compiler transpiles RPQL queries. + /// + public static class PrqlCompiler + { + /// + /// Compile a PRQL string into a SQL string. + /// + /// A PRQL query. + /// SQL query. + /// is null or empty. + /// cannot be compiled. + public static string Compile(string prqlQuery) + { + if (string.IsNullOrEmpty(prqlQuery)) + { + throw new ArgumentException(nameof(prqlQuery)); + } + + return CompileExtern(prqlQuery); + } + + /// + /// Compile a PRQL string into a SQL string. + /// + /// A PRQL query. + /// PRQL compiler options. + /// SQL query. + /// is null or empty. + /// is null. + /// cannot be compiled. + public static string Compile(string prqlQuery, PrqlCompilerOptions options) + { + if (string.IsNullOrEmpty(prqlQuery)) + { + throw new ArgumentException(nameof(prqlQuery)); + } + + if (options == null) + { + throw new ArgumentNullException(nameof(options)); + } + + return CompileExtern(prqlQuery); + } + + /// + /// Compile a PRQL string into a JSON string. + /// + /// A PRQL query. + /// JSON. + /// is null or empty. + /// cannot be compiled. + public static string ToJson(string prqlQuery) + { + if (string.IsNullOrEmpty(prqlQuery)) + { + throw new ArgumentException(nameof(prqlQuery)); + } + + byte[] bytes = new byte[1024]; + if (ToJsonExtern(prqlQuery, bytes) != 0) + { + throw new FormatException("Could not compile query."); + } + + bytes = bytes.TakeWhile(x => ((char)x) != '\0').ToArray(); + + return Encoding.UTF8.GetString(bytes); + } + + /// + /// Compile a PRQL string into a SQL query. + /// + /// A PRQL query. + /// SQL query. + /// is null or empty. + /// cannot be compiled. + public static string ToSql(string prqlQuery) + { + if (string.IsNullOrEmpty(prqlQuery)) + { + throw new ArgumentException(nameof(prqlQuery)); + } + + byte[] bytes = new byte[1024]; + if (ToSqlExtern(prqlQuery, bytes) != 0) + { + throw new FormatException("Could not compile query."); + } + + bytes = bytes.TakeWhile(x => ((char)x) != '\0').ToArray(); + + return Encoding.UTF8.GetString(bytes); + } + + [DllImport("libprql_lib", EntryPoint = "compile")] + private static extern string CompileExtern(string prql_query); + + [DllImport("libprql_lib", EntryPoint = "to_json")] + private static extern int ToJsonExtern(string prql_query, byte[] json); + + [DllImport("libprql_lib", EntryPoint = "to_sql")] + private static extern int ToSqlExtern(string prql_query, byte[] sql_query); + } +} diff --git a/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj b/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj new file mode 100644 index 000000000000..2d530e70a232 --- /dev/null +++ b/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj @@ -0,0 +1,28 @@ + + + + netstandard2.0 + + + + Prql.Compiler + 0.1.0 + PRQL Compiler + PRQL + Copyright ยฉ The PRQL Project 2023 + .NET bindings for the PRQL compiler. PRQL is a modern language for transforming data + Apache-2.0 + https://prql-lang.org/ + README.md + prql;sql + https://github.com/PRQL/prql + + + + + True + \ + + + + diff --git a/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs b/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs new file mode 100644 index 000000000000..0dc48e2169af --- /dev/null +++ b/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs @@ -0,0 +1,26 @@ +namespace Prql.Compiler +{ + /// + /// Compilation options for SQL backend of the compiler. + /// + public class PrqlCompilerOptions + { + /// + /// Pass generated SQL string trough a formatter that splits it into + /// multiple lines and prettifies indentation and spacing. + /// + /// Defaults to true. + public bool Format { get; set; } = true; + + /// + /// Target and dialect to compile to. + /// + public string Target { get; set; } + + /// + /// Emits the compiler signature as a comment after generated SQL. + /// + /// Defaults to true. + public bool SignatureComment { get; set; } = true; + } +} diff --git a/prql-dotnet/README.md b/prql-dotnet/README.md new file mode 100644 index 000000000000..7b81f6cfdd23 --- /dev/null +++ b/prql-dotnet/README.md @@ -0,0 +1,33 @@ +# prql-dotnet + +`prql-net` offers PRQL bindings for .NET bindings as a `netstandard2.0` library. + +It provides the `PrqlCompiler` class which contains the `ToJson` and `ToSql` +static methods. + +It's still at an early stage, and isn't published to NuGet. Contributions are +welcome. + +## Installation + +Make sure that `libprql_lib.so` (Linux), `libprql_lib.dylib` (macOS) or +`libprql_lib.dll` (Windows) is in your project's `bin` directory together with +`PrqlCompiler.dll` and the rest of your project's compiled files. I.e. +`{your_project}/bin/Debug/net7.0/`. + +The `libprql_lib` library gets dynamically imported at runtime. + +## Usage + +```csharp +using Prql.Compiler; + +var sql = PrqlCompiler.ToSql("from employees"); +Console.WriteLine(sql); +``` + +# TODO + +This is currently at 0.1.0 because we're waiting to update prql-lib for the +latest API. When we've done that, we can match the version here with the broader +PRQL version. diff --git a/prql-dotnet/prql-net.sln b/prql-dotnet/prql-net.sln new file mode 100644 index 000000000000..ce6fc11ae756 --- /dev/null +++ b/prql-dotnet/prql-net.sln @@ -0,0 +1,28 @@ +๏ปฟ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler", "PrqlCompiler\PrqlCompiler.csproj", "{339EA2A6-23D2-4938-884F-052431AC0674}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler.Tests", "PrqlCompiler.Tests\PrqlCompiler.Tests.csproj", "{78C1AD08-6FF5-444E-9298-385887ABAA80}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.Build.0 = Debug|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.ActiveCfg = Release|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.Build.0 = Release|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal From 16e6340a82c2a80324837ec2681fe25d3ebda539 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 21 Feb 2023 19:54:43 -0800 Subject: [PATCH 041/184] fix: Return a non-zero exit code for `prqlc compile` errors (#1924) * fix: Return a non-zero exit code for `prqlc compile` errors * . --- CHANGELOG.md | 3 +++ prql-compiler/prqlc/src/cli.rs | 23 +++++++++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0908cbf315b..f7780ba05e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ **Fixes**: +- `prqlc compile` returns a non-zero exit code for invalid queries. (@max-sixty, + #1924) + **Documentation**: **Web**: diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index 0ea1694b5bf1..bfecee864a5b 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -94,6 +94,8 @@ impl Cli { } fn execute(&self, source: &str) -> Result> { + // TODO: there's some repetiton here around converting strings to bytes; + // we could possibly extract that, but not sure it would neatly . Ok(match self { Cli::Parse(_) => { let ast = prql_to_pl(source).map_err(|e| anyhow!(e))?; @@ -137,7 +139,7 @@ impl Cli { serde_json::to_string_pretty(&ir)?.into_bytes() } Cli::Compile(_) => compile(source, &Options::default()) - .map_or_else(|x| x.to_string(), |x| x) + .map_err(|x| anyhow!(x))? .as_bytes() .to_vec(), Cli::Watch(_) => unreachable!(), @@ -208,7 +210,7 @@ fn combine_prql_and_frames(source: &str, frames: Vec<(Span, Frame)>) -> String { #[cfg(test)] mod tests { - use insta::assert_snapshot; + use insta::{assert_display_snapshot, assert_snapshot}; use super::*; @@ -267,4 +269,21 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag ) "###); } + + #[test] + fn compile() { + // Check we get an error on a bad input + let input = "asdf"; + let result = Cli::execute(&Cli::Compile(CommandIO::default()), input); + assert!(result.is_err()); + assert_display_snapshot!(result.unwrap_err(), @r###" + Error: + โ•ญโ”€[:1:1] + โ”‚ + 1 โ”‚ asdf + ยท โ”€โ”€โ”ฌโ”€ + ยท โ•ฐโ”€โ”€โ”€ Unknown name asdf + โ”€โ”€โ”€โ•ฏ + "###); + } } From 3f7585ea0fbe3fc588faae0d14e23b2940e325d0 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 21 Feb 2023 20:32:42 -0800 Subject: [PATCH 042/184] ci: Add `internal` & `devops` to semantic commit options (#1926) * ci: Add `internal` & `devops` to semantic commit options --- .github/workflows/pull-request-target.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/pull-request-target.yaml b/.github/workflows/pull-request-target.yaml index 0793964f36d0..21e238992728 100644 --- a/.github/workflows/pull-request-target.yaml +++ b/.github/workflows/pull-request-target.yaml @@ -19,6 +19,22 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: requireScope: false + # The standard ones plus "internal", for code quality / ergonomics + # improvements, and "devops" for developer ergonomics. + types: | + feat + fix + docs + style + refactor + perf + test + build + ci + chore + revert + internal + devops backport: # Backport to `web` branch on `pr-backport-web` From 6e79a28f927dbd1d2efb0147b94a748d3f918037 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:35:23 -0800 Subject: [PATCH 043/184] internal: Enable auto-conversion of anyhow's error to `ErrorMessages` (#1913) --- book/tests/snapshot.rs | 4 +--- prql-compiler/src/error.rs | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index a454da7c80da..0d8479b528fc 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -185,9 +185,7 @@ fn test_prql_examples() { // which seems very strict) #[test] fn test_display() -> Result<(), ErrorMessages> { - use prql_compiler::downcast; - collect_book_examples() - .map_err(downcast)? + collect_book_examples()? .iter() .try_for_each(|(path, example)| { assert_snapshot!( diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index e9f9d9d78839..7f75045572f1 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -181,6 +181,12 @@ pub fn downcast(error: anyhow::Error) -> ErrorMessages { .into() } +impl From for ErrorMessages { + fn from(e: anyhow::Error) -> Self { + downcast(e) + } +} + impl ErrorMessages { pub fn to_json(&self) -> String { serde_json::to_string(self).unwrap() From 883a12312eda66513241ba6cbe767e312e38bb3a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 00:35:50 -0800 Subject: [PATCH 044/184] internal: Implement std::error::Error for ErrorMessages (#1925) --- prql-compiler/prqlc/src/cli.rs | 21 +++++++-------------- prql-compiler/src/ast/pl/expr.rs | 2 -- prql-compiler/src/error.rs | 1 + 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index bfecee864a5b..06c2361b9c52 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -1,4 +1,4 @@ -use anyhow::{anyhow, Result}; +use anyhow::Result; use ariadne::Source; use clap::Parser; use clio::{Input, Output}; @@ -98,17 +98,13 @@ impl Cli { // we could possibly extract that, but not sure it would neatly . Ok(match self { Cli::Parse(_) => { - let ast = prql_to_pl(source).map_err(|e| anyhow!(e))?; + let ast = prql_to_pl(source)?; serde_yaml::to_string(&ast)?.into_bytes() } - Cli::Format(_) => prql_to_pl(source) - .and_then(pl_to_prql) - .map_err(|x| anyhow!(x))? - .as_bytes() - .to_vec(), + Cli::Format(_) => prql_to_pl(source).and_then(pl_to_prql)?.as_bytes().to_vec(), Cli::Debug(_) => { - let stmts = prql_to_pl(source).map_err(|x| anyhow!(x))?; + let stmts = prql_to_pl(source)?; let (stmts, context) = semantic::resolve_only(stmts, None)?; let (references, stmts) = @@ -122,7 +118,7 @@ impl Cli { .concat() } Cli::Annotate(_) => { - let stmts = prql_to_pl(source).map_err(|x| anyhow!(x))?; + let stmts = prql_to_pl(source)?; // resolve let (stmts, _) = semantic::resolve_only(stmts, None)?; @@ -133,15 +129,12 @@ impl Cli { combine_prql_and_frames(source, frames).as_bytes().to_vec() } Cli::Resolve(_) => { - let ast = prql_to_pl(source).map_err(|x| anyhow!(x))?; + let ast = prql_to_pl(source)?; let ir = semantic::resolve(ast)?; serde_json::to_string_pretty(&ir)?.into_bytes() } - Cli::Compile(_) => compile(source, &Options::default()) - .map_err(|x| anyhow!(x))? - .as_bytes() - .to_vec(), + Cli::Compile(_) => compile(source, &Options::default())?.as_bytes().to_vec(), Cli::Watch(_) => unreachable!(), }) } diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index ea3dc6f0a7b7..630d4725f32f 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -430,7 +430,6 @@ impl From for anyhow::Error { // https://github.com/bluejekyll/enum-as-inner/issues/84 #[allow(unreachable_code)] fn from(kind: ExprKind) -> Self { - // panic!("Failed to convert {item}") anyhow!("Failed to convert `{}`", Expr::from(kind)) } } @@ -439,7 +438,6 @@ impl From for anyhow::Error { // https://github.com/bluejekyll/enum-as-inner/issues/84 #[allow(unreachable_code)] fn from(kind: TransformKind) -> Self { - // panic!("Failed to convert {item}") anyhow!("Failed to convert `{kind:?}`") } } diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index 7f75045572f1..4d0151b3ff6e 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -120,6 +120,7 @@ impl Display for Error { pub struct ErrorMessages { pub inner: Vec, } +impl StdError for ErrorMessages {} impl From for ErrorMessages { fn from(e: ErrorMessage) -> Self { From 7c317ad7ebcf7de340641a103dd7d18418b8d8dc Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 01:33:20 -0800 Subject: [PATCH 045/184] build: Bump dependencies (#1927) --- Cargo.lock | 508 ++++++++++++++++----------------- prql-compiler/prqlc/Cargo.toml | 6 +- 2 files changed, 255 insertions(+), 259 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5eb860296819..ae6103343766 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", "const-random", @@ -76,9 +76,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" dependencies = [ "backtrace", ] @@ -104,7 +104,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d948f553cf556656eb89265700258e1032d26fec9b7920cd20319336e06afd" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-arith", "arrow-array", "arrow-buffer", @@ -130,7 +130,7 @@ dependencies = [ "arrow-data", "arrow-schema", "chrono", - "half 2.1.0", + "half 2.2.1", "num", ] @@ -140,13 +140,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fe66ec388d882a61fff3eb613b5266af133aa08a3318e5e493daf0f5c1696cb" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-buffer", "arrow-data", "arrow-schema", "chrono", - "half 2.1.0", - "hashbrown 0.13.1", + "half 2.2.1", + "hashbrown 0.13.2", "num", ] @@ -156,7 +156,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef967dadbccd4586ec8d7aab27d7033ecb5dfae8a605c839613039eac227bda" dependencies = [ - "half 2.1.0", + "half 2.2.1", "num", ] @@ -184,7 +184,7 @@ checksum = "ee0c0e3c5d3b80be8f267f4b2af714c08cad630569be01a8379cfe27b4866495" dependencies = [ "arrow-buffer", "arrow-schema", - "half 2.1.0", + "half 2.2.1", "num", ] @@ -208,13 +208,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e064ac4e64960ebfbe35f218f5e7d9dc9803b59c2e56f611da28ce6d008f839e" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-array", "arrow-buffer", "arrow-data", "arrow-schema", - "half 2.1.0", - "hashbrown 0.13.1", + "half 2.2.1", + "hashbrown 0.13.2", ] [[package]] @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.60" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -317,19 +317,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown 0.13.2", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", @@ -362,20 +362,21 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ - "lazy_static", "memchr", + "once_cell", "regex-automata", + "serde", ] [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytecheck" @@ -406,9 +407,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cast" @@ -418,9 +419,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -502,13 +503,13 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.1" +version = "4.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2" +checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" dependencies = [ "bitflags", "clap_derive", - "clap_lex 0.3.0", + "clap_lex 0.3.1", "is-terminal", "once_cell", "strsim", @@ -518,11 +519,11 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.0.6" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da" +checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe" dependencies = [ - "clap 4.1.1", + "clap 4.1.6", ] [[package]] @@ -549,9 +550,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] @@ -562,9 +563,9 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b38784f05c5e908bb8751e9b9f29fbcd470f636c0d0a76a0f90c0c823f3b68" dependencies = [ - "clap 4.1.1", + "clap 4.1.6", "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -616,9 +617,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "6.1.3" +version = "6.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" +checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" dependencies = [ "strum", "strum_macros", @@ -634,14 +635,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -819,9 +820,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -831,9 +832,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -846,15 +847,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -899,9 +900,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "encode_unicode" @@ -921,19 +922,6 @@ dependencies = [ "syn", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.10.0" @@ -992,23 +980,23 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1037,9 +1025,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1047,15 +1035,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1064,21 +1052,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-core", "futures-macro", @@ -1121,15 +1109,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -1146,9 +1134,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "half" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ "crunchy", "num-traits", @@ -1168,15 +1156,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1188,9 +1167,12 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] [[package]] name = "hashlink" @@ -1203,9 +1185,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -1225,6 +1207,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hmac" version = "0.12.1" @@ -1292,9 +1280,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inotify" @@ -1343,24 +1331,24 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1409,9 +1397,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1508,9 +1496,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libduckdb-sys" @@ -1600,15 +1588,15 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" +checksum = "0f387adfd85d2eeebe3d47d67b1e3f8c9d83ef327582558c5ca88f78d171e73a" dependencies = [ "anyhow", "chrono", - "clap 4.1.1", + "clap 4.1.6", "clap_complete", - "env_logger 0.10.0", + "env_logger", "handlebars", "log", "memchr", @@ -1629,7 +1617,7 @@ name = "mdbook-prql" version = "0.5.2" dependencies = [ "anyhow", - "clap 4.1.1", + "clap 4.1.6", "globset", "insta", "itertools", @@ -1695,21 +1683,21 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -1730,7 +1718,7 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1760,9 +1748,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits", ] @@ -1831,18 +1819,18 @@ dependencies = [ [[package]] name = "object" -version = "0.30.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -1852,9 +1840,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opener" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" +checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", "winapi", @@ -1893,15 +1881,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1912,9 +1900,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" +checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" dependencies = [ "thiserror", "ucd-trie", @@ -1922,9 +1910,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" +checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69" dependencies = [ "pest", "pest_generator", @@ -1932,9 +1920,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" +checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202" dependencies = [ "pest", "pest_meta", @@ -1945,13 +1933,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" +checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616" dependencies = [ "once_cell", "pest", - "sha1", + "sha2", ] [[package]] @@ -2120,9 +2108,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -2220,10 +2208,10 @@ dependencies = [ "anyhow", "ariadne", "atty", - "clap 4.1.1", + "clap 4.1.6", "clio", "color-eyre", - "env_logger 0.9.3", + "env_logger", "insta", "itertools", "minijinja", @@ -2279,9 +2267,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd4149c8c3975099622b4e1962dac27565cf5663b76452c3e2b66e0b6824277" +checksum = "06a3d8e8a46ab2738109347433cb7b96dffda2e4a218b03ef27090238886b147" dependencies = [ "cfg-if", "indoc", @@ -2296,9 +2284,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd09fe469834db21ee60e0051030339e5d361293d8cb5ec02facf7fdcf52dbf" +checksum = "75439f995d07ddfad42b192dfcf3bc66a7ecfd8b4a1f5f6f046aa5c2c5d7677d" dependencies = [ "once_cell", "target-lexicon", @@ -2306,9 +2294,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c427c9a96b9c5b12156dbc11f76b14f49e9aae8905ca783ea87c249044ef137" +checksum = "839526a5c07a17ff44823679b68add4a58004de00512a95b6c1c98a6dcac0ee5" dependencies = [ "libc", "pyo3-build-config", @@ -2316,9 +2304,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b822bbba9d60630a44d2109bc410489bb2f439b33e3a14ddeb8a40b378a7c4" +checksum = "bd44cf207476c6a9760c4653559be4f206efafb924d3e4cbf2721475fc0d6cc5" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2328,9 +2316,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84ae898104f7c99db06231160770f3e40dad6eb9021daddc0fedfa3e41dff10a" +checksum = "dc1f43d8e30460f36350d18631ccf85ded64c059829208fe680904c65bcd0a4c" dependencies = [ "proc-macro2", "quote", @@ -2388,9 +2376,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -2441,18 +2429,18 @@ dependencies = [ [[package]] name = "rend" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "c30f1d45d9aa61cbc8cd1eb87705470892289bb2d01943e7803b873a57404dc3" dependencies = [ "bytecheck", "hashbrown 0.12.3", @@ -2464,9 +2452,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "ff26ed6c7c4dfc2aa9480b86a60e3c7233543a270a680e10758a507c5a4ce476" dependencies = [ "proc-macro2", "quote", @@ -2490,9 +2478,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec", "borsh", @@ -2514,16 +2502,16 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustix" -version = "0.36.5" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2615,18 +2603,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -2635,9 +2623,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", @@ -2646,9 +2634,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.16" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" +checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" dependencies = [ "indexmap", "itoa", @@ -2657,17 +2645,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" version = "0.10.6" @@ -2708,9 +2685,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -2815,9 +2792,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" [[package]] name = "tempfile" @@ -2835,21 +2812,21 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +checksum = "4c9afddd2cec1c0909f06b00ef33f94ab2cc0578c4a610aa208ddfec8aa2b43a" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2880,10 +2857,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] @@ -2928,9 +2906,9 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" @@ -2945,7 +2923,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2974,9 +2952,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -2988,9 +2966,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -3045,9 +3023,9 @@ dependencies = [ [[package]] name = "trash" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f74274f95c7e7340d7c5bcd4863af87a9ed6a117cf73cf483c71cb4d744a948" +checksum = "a27b2a127810fceb959593bbc6c7b8e0282c2d318d76f0749252197c52a1dd0c" dependencies = [ "chrono", "libc", @@ -3082,9 +3060,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" @@ -3194,9 +3172,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3204,9 +3182,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", "log", @@ -3219,9 +3197,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if", "js-sys", @@ -3231,9 +3209,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3241,9 +3219,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ "proc-macro2", "quote", @@ -3254,15 +3232,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.83" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "wasm-bindgen-test" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" +checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3274,9 +3252,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.33" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" +checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9" dependencies = [ "proc-macro2", "quote", @@ -3284,9 +3262,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.60" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -3325,9 +3303,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.43.0" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3340,9 +3327,18 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3355,45 +3351,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "yaml-rust" diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index a90627b1530d..371096c04967 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -15,15 +15,15 @@ atty = "0.2.14" clap = {version = "4.1.1", features = ["derive"]} clio = {version = "0.2.4", features = ['clap-parse']} color-eyre = "0.6.1" -env_logger = {version = "0.9.1", features = ["termcolor"]} +env_logger = {version = "0.10.0", features = ["color"]} itertools = "0.10.3" -notify = "^5.1.0" minijinja = {version = "0.30.4", features = ["unstable_machinery"]} +notify = "^5.1.0" prql-compiler = {path = '..', version = "0.5.2"} regex = {version = "1.7.1", features = ["std", "unicode"]} +serde = "^1" serde_json = "1.0.81" serde_yaml = "0.9.1" -serde = "^1" walkdir = "^2.3.2" [target.'cfg(not(target_family="wasm"))'.dev-dependencies] From 14f6e7180cd8e10ddea8ecbae731b044fdd758d6 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 01:35:35 -0800 Subject: [PATCH 046/184] docs: Embolden `prqlc` description (#1919) --- .github/workflows/release.yaml | 6 ++++-- prql-compiler/prqlc/Cargo.toml | 2 +- snap/snapcraft.yaml | 7 ++++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 854963fbb02a..add1048a8405 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -45,8 +45,10 @@ jobs: package_root: .debpkg maintainer: The PRQL Project version: ${{ github.ref }} - desc: - prqlc is the CLI for PRQL, a modern language for transforming data + desc: | + prqlc is the CLI for the PRQL compiler. It compiles PRQL to SQL, and offers various diagnostics. + + PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement. build-rpm-package: # TODO: This doesn't publish the rpm yet, that would be a welcome follow-up (even as a CI artifact) diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 371096c04967..40b0ced399be 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -1,5 +1,5 @@ [package] -description = "CLI interface for the PRQL compiler" +description = "CLI for the PRQL compiler" name = "prqlc" edition.workspace = true diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index 6f9bda5cd9a7..dfa1fd7c1fa4 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -2,10 +2,11 @@ name: prqlc # you probably want to 'snapcraft register ' title: PRQL Compiler base: core20 # the base snap is the execution environment for this snap version: git -summary: PRQL is a modern language for transforming data +summary: CLI for PRQL, a modern language for transforming data description: | - PRQL is a modern language for transforming data โ€” a simple, powerful, - pipelined SQL replacement. + prqlc is the CLI for the PRQL compiler. It compiles PRQL to SQL, and offers various diagnostics. + + PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement. issues: https://github.com/PRQL/prql/issues source-code: https://github.com/PRQL/prql contact: https://twitter.com/prql_lang From 4d02cf35cd3e3a8100afece5d776a4cd9df25a0f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 11:36:34 -0800 Subject: [PATCH 047/184] revert: "build: Bump dependencies (#1927)" (#1935) Revert "build: Bump dependencies (#1927)" This reverts commit 7c317ad7ebcf7de340641a103dd7d18418b8d8dc. --- Cargo.lock | 508 +++++++++++++++++---------------- prql-compiler/prqlc/Cargo.toml | 6 +- 2 files changed, 259 insertions(+), 255 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae6103343766..5eb860296819 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.3" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" dependencies = [ "cfg-if", "const-random", @@ -76,9 +76,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.69" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" dependencies = [ "backtrace", ] @@ -104,7 +104,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d948f553cf556656eb89265700258e1032d26fec9b7920cd20319336e06afd" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.2", "arrow-arith", "arrow-array", "arrow-buffer", @@ -130,7 +130,7 @@ dependencies = [ "arrow-data", "arrow-schema", "chrono", - "half 2.2.1", + "half 2.1.0", "num", ] @@ -140,13 +140,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fe66ec388d882a61fff3eb613b5266af133aa08a3318e5e493daf0f5c1696cb" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.2", "arrow-buffer", "arrow-data", "arrow-schema", "chrono", - "half 2.2.1", - "hashbrown 0.13.2", + "half 2.1.0", + "hashbrown 0.13.1", "num", ] @@ -156,7 +156,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef967dadbccd4586ec8d7aab27d7033ecb5dfae8a605c839613039eac227bda" dependencies = [ - "half 2.2.1", + "half 2.1.0", "num", ] @@ -184,7 +184,7 @@ checksum = "ee0c0e3c5d3b80be8f267f4b2af714c08cad630569be01a8379cfe27b4866495" dependencies = [ "arrow-buffer", "arrow-schema", - "half 2.2.1", + "half 2.1.0", "num", ] @@ -208,13 +208,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e064ac4e64960ebfbe35f218f5e7d9dc9803b59c2e56f611da28ce6d008f839e" dependencies = [ - "ahash 0.8.3", + "ahash 0.8.2", "arrow-array", "arrow-buffer", "arrow-data", "arrow-schema", - "half 2.2.1", - "hashbrown 0.13.2", + "half 2.1.0", + "hashbrown 0.13.1", ] [[package]] @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.64" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" +checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" dependencies = [ "proc-macro2", "quote", @@ -317,19 +317,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.10.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" +checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" dependencies = [ "borsh-derive", - "hashbrown 0.13.2", + "hashbrown 0.11.2", ] [[package]] name = "borsh-derive" -version = "0.10.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" +checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.10.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" +checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" dependencies = [ "proc-macro2", "quote", @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.10.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" +checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" dependencies = [ "proc-macro2", "quote", @@ -362,21 +362,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.3.0" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", - "once_cell", "regex-automata", - "serde", ] [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "bytecheck" @@ -407,9 +406,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cast" @@ -419,9 +418,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" dependencies = [ "jobserver", ] @@ -503,13 +502,13 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.6" +version = "4.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" +checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2" dependencies = [ "bitflags", "clap_derive", - "clap_lex 0.3.1", + "clap_lex 0.3.0", "is-terminal", "once_cell", "strsim", @@ -519,11 +518,11 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.1.2" +version = "4.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe" +checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da" dependencies = [ - "clap 4.1.6", + "clap 4.1.1", ] [[package]] @@ -550,9 +549,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" dependencies = [ "os_str_bytes", ] @@ -563,9 +562,9 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b38784f05c5e908bb8751e9b9f29fbcd470f636c0d0a76a0f90c0c823f3b68" dependencies = [ - "clap 4.1.6", + "clap 4.1.1", "libc", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -617,9 +616,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "6.1.4" +version = "6.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" +checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" dependencies = [ "strum", "strum_macros", @@ -635,14 +634,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.5" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -820,9 +819,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.91" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" +checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" dependencies = [ "cc", "cxxbridge-flags", @@ -832,9 +831,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.91" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" +checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" dependencies = [ "cc", "codespan-reporting", @@ -847,15 +846,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.91" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" +checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" [[package]] name = "cxxbridge-macro" -version = "1.0.91" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" +checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" dependencies = [ "proc-macro2", "quote", @@ -900,9 +899,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "encode_unicode" @@ -922,6 +921,19 @@ dependencies = [ "syn", ] +[[package]] +name = "env_logger" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "env_logger" version = "0.10.0" @@ -980,23 +992,23 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.9.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.20" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1025,9 +1037,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" +checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" dependencies = [ "futures-core", "futures-sink", @@ -1035,15 +1047,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" +checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" [[package]] name = "futures-macro" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" +checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ "proc-macro2", "quote", @@ -1052,21 +1064,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" +checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" [[package]] name = "futures-task" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" +checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" [[package]] name = "futures-util" -version = "0.3.26" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" +checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" dependencies = [ "futures-core", "futures-macro", @@ -1109,15 +1121,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", "bstr", @@ -1134,9 +1146,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "half" -version = "2.2.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" +checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" dependencies = [ "crunchy", "num-traits", @@ -1158,22 +1170,28 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.12.3" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" dependencies = [ "ahash 0.7.6", ] [[package]] name = "hashbrown" -version = "0.13.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" dependencies = [ - "ahash 0.8.3", + "ahash 0.7.6", ] +[[package]] +name = "hashbrown" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" + [[package]] name = "hashlink" version = "0.8.1" @@ -1185,9 +1203,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -1207,12 +1225,6 @@ dependencies = [ "libc", ] -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - [[package]] name = "hmac" version = "0.12.1" @@ -1280,9 +1292,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.9" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" +checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780" [[package]] name = "inotify" @@ -1331,24 +1343,24 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.5" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" dependencies = [ "libc", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "is-terminal" -version = "0.4.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" dependencies = [ - "hermit-abi 0.3.1", + "hermit-abi 0.2.6", "io-lifetimes", "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1397,9 +1409,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" dependencies = [ "wasm-bindgen", ] @@ -1496,9 +1508,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.139" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "libduckdb-sys" @@ -1588,15 +1600,15 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.27" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f387adfd85d2eeebe3d47d67b1e3f8c9d83ef327582558c5ca88f78d171e73a" +checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" dependencies = [ "anyhow", "chrono", - "clap 4.1.6", + "clap 4.1.1", "clap_complete", - "env_logger", + "env_logger 0.10.0", "handlebars", "log", "memchr", @@ -1617,7 +1629,7 @@ name = "mdbook-prql" version = "0.5.2" dependencies = [ "anyhow", - "clap 4.1.6", + "clap 4.1.1", "globset", "insta", "itertools", @@ -1683,21 +1695,21 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] name = "nom" -version = "7.1.3" +version = "7.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" dependencies = [ "memchr", "minimal-lexical", @@ -1718,7 +1730,7 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1748,9 +1760,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" +checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" dependencies = [ "num-traits", ] @@ -1819,18 +1831,18 @@ dependencies = [ [[package]] name = "object" -version = "0.30.3" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "oorandom" @@ -1840,9 +1852,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opener" -version = "0.5.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" +checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" dependencies = [ "bstr", "winapi", @@ -1881,15 +1893,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1900,9 +1912,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.5" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" +checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" dependencies = [ "thiserror", "ucd-trie", @@ -1910,9 +1922,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.5" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69" +checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" dependencies = [ "pest", "pest_generator", @@ -1920,9 +1932,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.5" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202" +checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" dependencies = [ "pest", "pest_meta", @@ -1933,13 +1945,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.5.5" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616" +checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" dependencies = [ "once_cell", "pest", - "sha2", + "sha1", ] [[package]] @@ -2108,9 +2120,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] @@ -2208,10 +2220,10 @@ dependencies = [ "anyhow", "ariadne", "atty", - "clap 4.1.6", + "clap 4.1.1", "clio", "color-eyre", - "env_logger", + "env_logger 0.9.3", "insta", "itertools", "minijinja", @@ -2267,9 +2279,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.18.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06a3d8e8a46ab2738109347433cb7b96dffda2e4a218b03ef27090238886b147" +checksum = "ccd4149c8c3975099622b4e1962dac27565cf5663b76452c3e2b66e0b6824277" dependencies = [ "cfg-if", "indoc", @@ -2284,9 +2296,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.18.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75439f995d07ddfad42b192dfcf3bc66a7ecfd8b4a1f5f6f046aa5c2c5d7677d" +checksum = "9cd09fe469834db21ee60e0051030339e5d361293d8cb5ec02facf7fdcf52dbf" dependencies = [ "once_cell", "target-lexicon", @@ -2294,9 +2306,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.18.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "839526a5c07a17ff44823679b68add4a58004de00512a95b6c1c98a6dcac0ee5" +checksum = "0c427c9a96b9c5b12156dbc11f76b14f49e9aae8905ca783ea87c249044ef137" dependencies = [ "libc", "pyo3-build-config", @@ -2304,9 +2316,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.18.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd44cf207476c6a9760c4653559be4f206efafb924d3e4cbf2721475fc0d6cc5" +checksum = "16b822bbba9d60630a44d2109bc410489bb2f439b33e3a14ddeb8a40b378a7c4" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2316,9 +2328,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.18.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1f43d8e30460f36350d18631ccf85ded64c059829208fe680904c65bcd0a4c" +checksum = "84ae898104f7c99db06231160770f3e40dad6eb9021daddc0fedfa3e41dff10a" dependencies = [ "proc-macro2", "quote", @@ -2376,9 +2388,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.2" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -2429,18 +2441,18 @@ dependencies = [ [[package]] name = "rend" -version = "0.4.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" +checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.40" +version = "0.7.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c30f1d45d9aa61cbc8cd1eb87705470892289bb2d01943e7803b873a57404dc3" +checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" dependencies = [ "bytecheck", "hashbrown 0.12.3", @@ -2452,9 +2464,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.40" +version = "0.7.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff26ed6c7c4dfc2aa9480b86a60e3c7233543a270a680e10758a507c5a4ce476" +checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" dependencies = [ "proc-macro2", "quote", @@ -2478,9 +2490,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.28.1" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" +checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" dependencies = [ "arrayvec", "borsh", @@ -2502,16 +2514,16 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustix" -version = "0.36.8" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" +checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -2603,18 +2615,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.152" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.152" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -2623,9 +2635,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.93" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -2634,9 +2646,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.17" +version = "0.9.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" +checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" dependencies = [ "indexmap", "itoa", @@ -2645,6 +2657,17 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "sha1" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.6" @@ -2685,9 +2708,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" dependencies = [ "autocfg", ] @@ -2792,9 +2815,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.6" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" +checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" [[package]] name = "tempfile" @@ -2812,21 +2835,21 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.2.0" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.2.5" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9afddd2cec1c0909f06b00ef33f94ab2cc0578c4a610aa208ddfec8aa2b43a" +checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" dependencies = [ "rustix", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -2857,11 +2880,10 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" dependencies = [ - "cfg-if", "once_cell", ] @@ -2906,9 +2928,9 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.1" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" @@ -2923,7 +2945,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2952,9 +2974,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" dependencies = [ "bytes", "futures-core", @@ -2966,9 +2988,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.11" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] @@ -3023,9 +3045,9 @@ dependencies = [ [[package]] name = "trash" -version = "3.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a27b2a127810fceb959593bbc6c7b8e0282c2d318d76f0749252197c52a1dd0c" +checksum = "6f74274f95c7e7340d7c5bcd4863af87a9ed6a117cf73cf483c71cb4d744a948" dependencies = [ "chrono", "libc", @@ -3060,9 +3082,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.10" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" @@ -3172,9 +3194,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3182,9 +3204,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -3197,9 +3219,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d" dependencies = [ "cfg-if", "js-sys", @@ -3209,9 +3231,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3219,9 +3241,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -3232,15 +3254,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasm-bindgen-test" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db36fc0f9fb209e88fb3642590ae0205bb5a56216dabd963ba15879fe53a30b" +checksum = "09d2fff962180c3fadf677438054b1db62bee4aa32af26a45388af07d1287e1d" dependencies = [ "console_error_panic_hook", "js-sys", @@ -3252,9 +3274,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.34" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0734759ae6b3b1717d661fe4f016efcfb9828f5edb4520c18eaee05af3b43be9" +checksum = "4683da3dfc016f704c9f82cf401520c4f1cb3ee440f7f52b3d6ac29506a49ca7" dependencies = [ "proc-macro2", "quote", @@ -3262,9 +3284,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" dependencies = [ "js-sys", "wasm-bindgen", @@ -3303,18 +3325,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" +version = "0.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3327,18 +3340,9 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3351,45 +3355,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" +checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" [[package]] name = "windows_aarch64_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" +checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" [[package]] name = "windows_i686_gnu" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" +checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" [[package]] name = "windows_i686_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" +checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" [[package]] name = "windows_x86_64_gnu" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" +checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" +checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" [[package]] name = "windows_x86_64_msvc" -version = "0.42.1" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" +checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" [[package]] name = "yaml-rust" diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 40b0ced399be..f159b4c20431 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -15,15 +15,15 @@ atty = "0.2.14" clap = {version = "4.1.1", features = ["derive"]} clio = {version = "0.2.4", features = ['clap-parse']} color-eyre = "0.6.1" -env_logger = {version = "0.10.0", features = ["color"]} +env_logger = {version = "0.9.1", features = ["termcolor"]} itertools = "0.10.3" -minijinja = {version = "0.30.4", features = ["unstable_machinery"]} notify = "^5.1.0" +minijinja = {version = "0.30.4", features = ["unstable_machinery"]} prql-compiler = {path = '..', version = "0.5.2"} regex = {version = "1.7.1", features = ["std", "unicode"]} -serde = "^1" serde_json = "1.0.81" serde_yaml = "0.9.1" +serde = "^1" walkdir = "^2.3.2" [target.'cfg(not(target_family="wasm"))'.dev-dependencies] From 7bac7f89d22735a02a2fec00cbf887760caf6e49 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 16:04:13 -0800 Subject: [PATCH 048/184] devops: Add `web` to semantic commit categories (#1938) --- .github/workflows/pull-request-target.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/pull-request-target.yaml b/.github/workflows/pull-request-target.yaml index 21e238992728..81b8762bf0d7 100644 --- a/.github/workflows/pull-request-target.yaml +++ b/.github/workflows/pull-request-target.yaml @@ -19,8 +19,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: requireScope: false - # The standard ones plus "internal", for code quality / ergonomics - # improvements, and "devops" for developer ergonomics. + # The standard ones plus + # - "internal" for code quality / ergonomics improvements + # - "devops" for developer ergonomics + # - "web" for playground / website (but not docs) types: | feat fix @@ -35,6 +37,7 @@ jobs: revert internal devops + web backport: # Backport to `web` branch on `pr-backport-web` From 5cf0779e148e436b90e19e211120e28a8972f768 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 22 Feb 2023 16:04:34 -0800 Subject: [PATCH 049/184] build: Re-revert #1935 (#1937) Locked wasm-bindgen, I think because of a wasm-pack problem --- Cargo.lock | 468 +++++++++--------- prql-compiler/prql-compiler-macros/Cargo.toml | 6 +- prql-compiler/prqlc/Cargo.toml | 6 +- prql-js/Cargo.toml | 7 +- 4 files changed, 245 insertions(+), 242 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5eb860296819..754ecb3bc58f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" dependencies = [ "cfg-if", "const-random", @@ -76,9 +76,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anyhow" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" dependencies = [ "backtrace", ] @@ -104,7 +104,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87d948f553cf556656eb89265700258e1032d26fec9b7920cd20319336e06afd" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-arith", "arrow-array", "arrow-buffer", @@ -130,7 +130,7 @@ dependencies = [ "arrow-data", "arrow-schema", "chrono", - "half 2.1.0", + "half 2.2.1", "num", ] @@ -140,13 +140,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fe66ec388d882a61fff3eb613b5266af133aa08a3318e5e493daf0f5c1696cb" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-buffer", "arrow-data", "arrow-schema", "chrono", - "half 2.1.0", - "hashbrown 0.13.1", + "half 2.2.1", + "hashbrown 0.13.2", "num", ] @@ -156,7 +156,7 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ef967dadbccd4586ec8d7aab27d7033ecb5dfae8a605c839613039eac227bda" dependencies = [ - "half 2.1.0", + "half 2.2.1", "num", ] @@ -184,7 +184,7 @@ checksum = "ee0c0e3c5d3b80be8f267f4b2af714c08cad630569be01a8379cfe27b4866495" dependencies = [ "arrow-buffer", "arrow-schema", - "half 2.1.0", + "half 2.2.1", "num", ] @@ -208,13 +208,13 @@ version = "32.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e064ac4e64960ebfbe35f218f5e7d9dc9803b59c2e56f611da28ce6d008f839e" dependencies = [ - "ahash 0.8.2", + "ahash 0.8.3", "arrow-array", "arrow-buffer", "arrow-data", "arrow-schema", - "half 2.1.0", - "hashbrown 0.13.1", + "half 2.2.1", + "hashbrown 0.13.2", ] [[package]] @@ -253,9 +253,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.60" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" +checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2" dependencies = [ "proc-macro2", "quote", @@ -317,19 +317,19 @@ dependencies = [ [[package]] name = "borsh" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15bf3650200d8bffa99015595e10f1fbd17de07abbc25bb067da79e769939bfa" +checksum = "40f9ca3698b2e4cb7c15571db0abc5551dca417a21ae8140460b50309bb2cc62" dependencies = [ "borsh-derive", - "hashbrown 0.11.2", + "hashbrown 0.13.2", ] [[package]] name = "borsh-derive" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6441c552f230375d18e3cc377677914d2ca2b0d36e52129fe15450a2dce46775" +checksum = "598b3eacc6db9c3ee57b22707ad8f6a8d2f6d442bfe24ffeb8cbb70ca59e6a35" dependencies = [ "borsh-derive-internal", "borsh-schema-derive-internal", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "borsh-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5449c28a7b352f2d1e592a8a28bf139bc71afb0764a14f3c02500935d8c44065" +checksum = "186b734fa1c9f6743e90c95d7233c9faab6360d1a96d4ffa19d9cfd1e9350f8a" dependencies = [ "proc-macro2", "quote", @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "borsh-schema-derive-internal" -version = "0.9.3" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdbd5696d8bfa21d53d9fe39a714a18538bad11492a42d066dbbc395fb1951c0" +checksum = "99b7ff1008316626f485991b960ade129253d4034014616b94f309a15366cc49" dependencies = [ "proc-macro2", "quote", @@ -362,20 +362,21 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.17" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1" dependencies = [ - "lazy_static", "memchr", + "once_cell", "regex-automata", + "serde", ] [[package]] name = "bumpalo" -version = "3.11.1" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" +checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" [[package]] name = "bytecheck" @@ -406,9 +407,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cast" @@ -418,9 +419,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" dependencies = [ "jobserver", ] @@ -502,13 +503,13 @@ dependencies = [ [[package]] name = "clap" -version = "4.1.1" +version = "4.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2" +checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" dependencies = [ "bitflags", "clap_derive", - "clap_lex 0.3.0", + "clap_lex 0.3.1", "is-terminal", "once_cell", "strsim", @@ -518,11 +519,11 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.0.6" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7b3c9eae0de7bf8e3f904a5e40612b21fb2e2e566456d177809a48b892d24da" +checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe" dependencies = [ - "clap 4.1.1", + "clap 4.1.6", ] [[package]] @@ -549,9 +550,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8" +checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" dependencies = [ "os_str_bytes", ] @@ -562,9 +563,9 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94b38784f05c5e908bb8751e9b9f29fbcd470f636c0d0a76a0f90c0c823f3b68" dependencies = [ - "clap 4.1.1", + "clap 4.1.6", "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -616,9 +617,9 @@ dependencies = [ [[package]] name = "comfy-table" -version = "6.1.3" +version = "6.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e621e7e86c46fd8a14c32c6ae3cb95656621b4743a27d0cffedb831d46e7ad21" +checksum = "6e7b787b0dc42e8111badfdbe4c3059158ccb2db8780352fa1b01e8ccf45cc4d" dependencies = [ "strum", "strum_macros", @@ -634,14 +635,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -819,9 +820,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5add3fc1717409d029b20c5b6903fc0c0b02fa6741d820054f4a2efa5e5816fd" +checksum = "86d3488e7665a7a483b57e25bdd90d0aeb2bc7608c8d0346acf2ad3f1caf1d62" dependencies = [ "cc", "cxxbridge-flags", @@ -831,9 +832,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c87959ba14bc6fbc61df77c3fcfe180fc32b93538c4f1031dd802ccb5f2ff0" +checksum = "48fcaf066a053a41a81dfb14d57d99738b767febb8b735c3016e469fac5da690" dependencies = [ "cc", "codespan-reporting", @@ -846,15 +847,15 @@ dependencies = [ [[package]] name = "cxxbridge-flags" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69a3e162fde4e594ed2b07d0f83c6c67b745e7f28ce58c6df5e6b6bef99dfb59" +checksum = "a2ef98b8b717a829ca5603af80e1f9e2e48013ab227b68ef37872ef84ee479bf" [[package]] name = "cxxbridge-macro" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e7e2adeb6a0d4a282e581096b06e1791532b7d576dcde5ccd9382acf55db8e6" +checksum = "086c685979a698443656e5cf7856c95c642295a38599f12fb1ff76fb28d19892" dependencies = [ "proc-macro2", "quote", @@ -899,9 +900,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "encode_unicode" @@ -921,19 +922,6 @@ dependencies = [ "syn", ] -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - [[package]] name = "env_logger" version = "0.10.0" @@ -992,23 +980,23 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.19" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" +checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1037,9 +1025,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed" +checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5" dependencies = [ "futures-core", "futures-sink", @@ -1047,15 +1035,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" +checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" [[package]] name = "futures-macro" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" +checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70" dependencies = [ "proc-macro2", "quote", @@ -1064,21 +1052,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9" +checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" [[package]] name = "futures-task" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea" +checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" [[package]] name = "futures-util" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6" +checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" dependencies = [ "futures-core", "futures-macro", @@ -1121,15 +1109,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ "aho-corasick", "bstr", @@ -1146,9 +1134,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "half" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad6a9459c9c30b177b925162351f97e7d967c7ea8bab3b8352805327daf45554" +checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" dependencies = [ "crunchy", "num-traits", @@ -1168,15 +1156,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "hashbrown" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" -dependencies = [ - "ahash 0.7.6", -] - [[package]] name = "hashbrown" version = "0.12.3" @@ -1188,9 +1167,12 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash 0.8.3", +] [[package]] name = "hashlink" @@ -1203,9 +1185,9 @@ dependencies = [ [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -1225,6 +1207,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "hmac" version = "0.12.1" @@ -1292,9 +1280,9 @@ dependencies = [ [[package]] name = "indoc" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2d6f23ffea9d7e76c53eee25dfb67bcd8fde7f1198b0855350698c9f07c780" +checksum = "bfa799dd5ed20a7e349f3b4639aa80d74549c81716d9ec4f994c9b5815598306" [[package]] name = "inotify" @@ -1343,24 +1331,24 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "is-terminal" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.1", "io-lifetimes", "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1508,9 +1496,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.138" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libduckdb-sys" @@ -1600,15 +1588,15 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.4.25" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ed28d5903dde77bd5182645078a37ee57014cac6ccb2d54e1d6496386648e4" +checksum = "0f387adfd85d2eeebe3d47d67b1e3f8c9d83ef327582558c5ca88f78d171e73a" dependencies = [ "anyhow", "chrono", - "clap 4.1.1", + "clap 4.1.6", "clap_complete", - "env_logger 0.10.0", + "env_logger", "handlebars", "log", "memchr", @@ -1629,7 +1617,7 @@ name = "mdbook-prql" version = "0.5.2" dependencies = [ "anyhow", - "clap 4.1.1", + "clap 4.1.6", "globset", "insta", "itertools", @@ -1695,21 +1683,21 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] name = "nom" -version = "7.1.1" +version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ "memchr", "minimal-lexical", @@ -1730,7 +1718,7 @@ dependencies = [ "libc", "mio", "walkdir", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -1760,9 +1748,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19" +checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" dependencies = [ "num-traits", ] @@ -1831,18 +1819,18 @@ dependencies = [ [[package]] name = "object" -version = "0.30.0" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -1852,9 +1840,9 @@ checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opener" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" +checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", "winapi", @@ -1893,15 +1881,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.5" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" +checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1912,9 +1900,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0" +checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660" dependencies = [ "thiserror", "ucd-trie", @@ -1922,9 +1910,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344" +checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69" dependencies = [ "pest", "pest_generator", @@ -1932,9 +1920,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c" +checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202" dependencies = [ "pest", "pest_meta", @@ -1945,13 +1933,13 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.5.1" +version = "2.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20" +checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616" dependencies = [ "once_cell", "pest", - "sha1", + "sha2", ] [[package]] @@ -2120,9 +2108,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] @@ -2220,10 +2208,10 @@ dependencies = [ "anyhow", "ariadne", "atty", - "clap 4.1.1", + "clap 4.1.6", "clio", "color-eyre", - "env_logger 0.9.3", + "env_logger", "insta", "itertools", "minijinja", @@ -2279,9 +2267,9 @@ dependencies = [ [[package]] name = "pyo3" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccd4149c8c3975099622b4e1962dac27565cf5663b76452c3e2b66e0b6824277" +checksum = "06a3d8e8a46ab2738109347433cb7b96dffda2e4a218b03ef27090238886b147" dependencies = [ "cfg-if", "indoc", @@ -2296,9 +2284,9 @@ dependencies = [ [[package]] name = "pyo3-build-config" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cd09fe469834db21ee60e0051030339e5d361293d8cb5ec02facf7fdcf52dbf" +checksum = "75439f995d07ddfad42b192dfcf3bc66a7ecfd8b4a1f5f6f046aa5c2c5d7677d" dependencies = [ "once_cell", "target-lexicon", @@ -2306,9 +2294,9 @@ dependencies = [ [[package]] name = "pyo3-ffi" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c427c9a96b9c5b12156dbc11f76b14f49e9aae8905ca783ea87c249044ef137" +checksum = "839526a5c07a17ff44823679b68add4a58004de00512a95b6c1c98a6dcac0ee5" dependencies = [ "libc", "pyo3-build-config", @@ -2316,9 +2304,9 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b822bbba9d60630a44d2109bc410489bb2f439b33e3a14ddeb8a40b378a7c4" +checksum = "bd44cf207476c6a9760c4653559be4f206efafb924d3e4cbf2721475fc0d6cc5" dependencies = [ "proc-macro2", "pyo3-macros-backend", @@ -2328,9 +2316,9 @@ dependencies = [ [[package]] name = "pyo3-macros-backend" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84ae898104f7c99db06231160770f3e40dad6eb9021daddc0fedfa3e41dff10a" +checksum = "dc1f43d8e30460f36350d18631ccf85ded64c059829208fe680904c65bcd0a4c" dependencies = [ "proc-macro2", "quote", @@ -2388,9 +2376,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.10.1" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" +checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -2441,18 +2429,18 @@ dependencies = [ [[package]] name = "rend" -version = "0.3.6" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79af64b4b6362ffba04eef3a4e10829718a4896dac19daa741851c86781edf95" +checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" dependencies = [ "bytecheck", ] [[package]] name = "rkyv" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cec2b3485b07d96ddfd3134767b8a447b45ea4eb91448d0a35180ec0ffd5ed15" +checksum = "c30f1d45d9aa61cbc8cd1eb87705470892289bb2d01943e7803b873a57404dc3" dependencies = [ "bytecheck", "hashbrown 0.12.3", @@ -2464,9 +2452,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.39" +version = "0.7.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eaedadc88b53e36dd32d940ed21ae4d850d5916f2581526921f553a72ac34c4" +checksum = "ff26ed6c7c4dfc2aa9480b86a60e3c7233543a270a680e10758a507c5a4ce476" dependencies = [ "proc-macro2", "quote", @@ -2490,9 +2478,9 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.27.0" +version = "1.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c321ee4e17d2b7abe12b5d20c1231db708dd36185c8a21e9de5fed6da4dbe9" +checksum = "e13cf35f7140155d02ba4ec3294373d513a3c7baa8364c162b030e33c61520a8" dependencies = [ "arrayvec", "borsh", @@ -2514,16 +2502,16 @@ checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustix" -version = "0.36.5" +version = "0.36.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588" +checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2615,18 +2603,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.151" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ "proc-macro2", "quote", @@ -2635,9 +2623,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" dependencies = [ "itoa", "ryu", @@ -2646,9 +2634,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.16" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b5b431e8907b50339b51223b97d102db8d987ced36f6e4d03621db9316c834" +checksum = "8fb06d4b6cdaef0e0c51fa881acb721bed3c924cfaa71d9c94a3b771dfdf6567" dependencies = [ "indexmap", "itoa", @@ -2657,17 +2645,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - [[package]] name = "sha2" version = "0.10.6" @@ -2708,9 +2685,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" [[package]] name = "slab" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -2815,9 +2792,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9410d0f6853b1d94f0e519fb95df60f29d2c1eff2d921ffdf01a4c8a3b54f12d" +checksum = "8ae9980cab1db3fceee2f6c6f643d5d8de2997c58ee8d25fb0cc8a9e9e7348e5" [[package]] name = "tempfile" @@ -2835,21 +2812,21 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb20089a8ba2b69debd491f8d2d023761cbf196e999218c591fa1e7e15a21907" +checksum = "4c9afddd2cec1c0909f06b00ef33f94ab2cc0578c4a610aa208ddfec8aa2b43a" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -2880,10 +2857,11 @@ dependencies = [ [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if", "once_cell", ] @@ -2928,9 +2906,9 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" @@ -2945,7 +2923,7 @@ dependencies = [ "mio", "pin-project-lite", "socket2", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] @@ -2974,9 +2952,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.4" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -2988,9 +2966,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -3045,9 +3023,9 @@ dependencies = [ [[package]] name = "trash" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f74274f95c7e7340d7c5bcd4863af87a9ed6a117cf73cf483c71cb4d744a948" +checksum = "a27b2a127810fceb959593bbc6c7b8e0282c2d318d76f0749252197c52a1dd0c" dependencies = [ "chrono", "libc", @@ -3082,9 +3060,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" [[package]] name = "unicode-ident" @@ -3325,9 +3303,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.43.0" +version = "0.44.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3340,9 +3327,18 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.42.0" +version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", @@ -3355,45 +3351,45 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" +checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" [[package]] name = "windows_aarch64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" +checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" [[package]] name = "windows_i686_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" +checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" [[package]] name = "windows_i686_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" +checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" [[package]] name = "windows_x86_64_gnu" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed" +checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" +checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" [[package]] name = "windows_x86_64_msvc" -version = "0.42.0" +version = "0.42.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5" +checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" [[package]] name = "yaml-rust" diff --git a/prql-compiler/prql-compiler-macros/Cargo.toml b/prql-compiler/prql-compiler-macros/Cargo.toml index 460ff18a7d27..2244c503b04d 100644 --- a/prql-compiler/prql-compiler-macros/Cargo.toml +++ b/prql-compiler/prql-compiler-macros/Cargo.toml @@ -14,8 +14,10 @@ proc_macro = true test = false [dependencies] -prql-compiler = {path = "..", default-features = false, version = "0.5.2" } -syn = "1.0" +prql-compiler = {path = "..", default-features = false, version = "0.5.2"} +# Was getting build errors with more recent versions; can remove pin if it +# successfully builds. +syn = "=1.0.107" [package.metadata.release] tag-name = "{{version}}" diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index f159b4c20431..40b0ced399be 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -15,15 +15,15 @@ atty = "0.2.14" clap = {version = "4.1.1", features = ["derive"]} clio = {version = "0.2.4", features = ['clap-parse']} color-eyre = "0.6.1" -env_logger = {version = "0.9.1", features = ["termcolor"]} +env_logger = {version = "0.10.0", features = ["color"]} itertools = "0.10.3" -notify = "^5.1.0" minijinja = {version = "0.30.4", features = ["unstable_machinery"]} +notify = "^5.1.0" prql-compiler = {path = '..', version = "0.5.2"} regex = {version = "1.7.1", features = ["std", "unicode"]} +serde = "^1" serde_json = "1.0.81" serde_yaml = "0.9.1" -serde = "^1" walkdir = "^2.3.2" [target.'cfg(not(target_family="wasm"))'.dev-dependencies] diff --git a/prql-js/Cargo.toml b/prql-js/Cargo.toml index ef5a64a6610a..c74ee4057dec 100644 --- a/prql-js/Cargo.toml +++ b/prql-js/Cargo.toml @@ -23,7 +23,12 @@ default = ["console_error_panic_hook"] [dependencies] prql-compiler = {path = "../prql-compiler", default-features = false} -wasm-bindgen = "0.2.80" +# This was preventing the playground from working. It's possibly +# https://github.com/rustwasm/wasm-bindgen/issues/3276 +# If the playground works with a later version, we can unpin this. It's likely +# related to wasm-pack. So https://github.com/PRQL/prql/issues/1836 would likely +# solve it, along with simplifying the build process. +wasm-bindgen = "=0.2.83" # The `console_error_panic_hook` crate provides better debugging of panics by # logging them with `console.error`. This is great for development, but requires From ce8bdb40fbadefcc5cbdf2ee35375355f4f7d41f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 23 Feb 2023 14:42:17 +0100 Subject: [PATCH 050/184] refactor: remove trailing whitespace (#1943) --- .../PrqlCompiler.Tests/CompilerTest.cs | 46 +++++++-------- .../PrqlCompiler.Tests.csproj | 56 +++++++++---------- prql-dotnet/prql-net.sln | 56 +++++++++---------- 3 files changed, 79 insertions(+), 79 deletions(-) diff --git a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs index a5afa68f0942..a405d2c75fa5 100644 --- a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs +++ b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs @@ -1,23 +1,23 @@ -using Prql.Compiler; - -namespace Prql.Compiler.Tests; - -sealed public class CompilerTest -{ - [Fact] - public void ToSql_Works() - { - // Arrange - var expected = "SELECT\n *\nFROM\n employees\n\n" + - "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; - var signature = "-- Generated by PRQL compiler"; - expected = expected.Substring(0, expected.IndexOf(signature)); - - // Act - var sqlQuery = PrqlCompiler.ToSql("from employees"); - sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); - - // Assert - Assert.Equal(expected, sqlQuery); - } -} +using Prql.Compiler; + +namespace Prql.Compiler.Tests; + +sealed public class CompilerTest +{ + [Fact] + public void ToSql_Works() + { + // Arrange + var expected = "SELECT\n *\nFROM\n employees\n\n" + + "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; + var signature = "-- Generated by PRQL compiler"; + expected = expected.Substring(0, expected.IndexOf(signature)); + + // Act + var sqlQuery = PrqlCompiler.ToSql("from employees"); + sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); + + // Assert + Assert.Equal(expected, sqlQuery); + } +} diff --git a/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj b/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj index 9fb2ba1630fb..eeddc9523e9a 100644 --- a/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj +++ b/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj @@ -1,28 +1,28 @@ - - - - net7.0 - enable - enable - - false - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - - - - + + + + net7.0 + enable + enable + + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/prql-dotnet/prql-net.sln b/prql-dotnet/prql-net.sln index ce6fc11ae756..76842e4e1189 100644 --- a/prql-dotnet/prql-net.sln +++ b/prql-dotnet/prql-net.sln @@ -1,28 +1,28 @@ -๏ปฟ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.0.31903.59 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler", "PrqlCompiler\PrqlCompiler.csproj", "{339EA2A6-23D2-4938-884F-052431AC0674}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler.Tests", "PrqlCompiler.Tests\PrqlCompiler.Tests.csproj", "{78C1AD08-6FF5-444E-9298-385887ABAA80}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.Build.0 = Debug|Any CPU - {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.ActiveCfg = Release|Any CPU - {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.Build.0 = Release|Any CPU - {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.ActiveCfg = Release|Any CPU - {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal +๏ปฟ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler", "PrqlCompiler\PrqlCompiler.csproj", "{339EA2A6-23D2-4938-884F-052431AC0674}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrqlCompiler.Tests", "PrqlCompiler.Tests\PrqlCompiler.Tests.csproj", "{78C1AD08-6FF5-444E-9298-385887ABAA80}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Debug|Any CPU.Build.0 = Debug|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.ActiveCfg = Release|Any CPU + {339EA2A6-23D2-4938-884F-052431AC0674}.Release|Any CPU.Build.0 = Release|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Debug|Any CPU.Build.0 = Debug|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.ActiveCfg = Release|Any CPU + {78C1AD08-6FF5-444E-9298-385887ABAA80}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal From 6846d6a983bff32210b003fc7f2bfda158a1c83a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 23 Feb 2023 15:10:26 +0100 Subject: [PATCH 051/184] build: update prql-lib API (#1941) --- .github/workflows/test-lib.yaml | 28 +++ .gitignore | 4 + .../PrqlCompiler.Tests/CompilerTest.cs | 29 ++-- prql-lib/README.md | 15 +- prql-lib/examples/minimal-c/Makefile | 14 ++ prql-lib/examples/minimal-c/README.md | 7 + prql-lib/examples/minimal-c/main.c | 47 +++++ prql-lib/libprql_lib.h | 58 ++++++- prql-lib/src/lib.rs | 161 +++++++++++++----- 9 files changed, 301 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/test-lib.yaml create mode 100644 prql-lib/examples/minimal-c/Makefile create mode 100644 prql-lib/examples/minimal-c/README.md create mode 100644 prql-lib/examples/minimal-c/main.c diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml new file mode 100644 index 000000000000..7937d0066449 --- /dev/null +++ b/.github/workflows/test-lib.yaml @@ -0,0 +1,28 @@ +name: test-lib + +on: + pull_request: + paths: + - "prql-lib/**" + - ".github/workflows/test-lib.yaml" + workflow_call: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: ๐Ÿ“‚ Checkout code + uses: actions/checkout@v3 + - name: ๐Ÿ’ฐ Cache + uses: Swatinem/rust-cache@v2 + with: + key: ${{ inputs.target_option }} + save-if: ${{ github.ref == 'refs/heads/main' }} + - name: Build + uses: richb-hanover/cargo@v1.1.0 + with: + command: build + args: --release -p prql-lib + - name: Run basic C example + working-directory: prql-lib/examples/minimal-c + run: make run diff --git a/.gitignore b/.gitignore index 362d0c3c3c71..51c4f04938a9 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ dist target* +*.out lcov.info @@ -19,3 +20,6 @@ _*.prql **/node_modules/ .task + +prql-dotnet/**/bin +prql-dotnet/**/obj diff --git a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs index a405d2c75fa5..2505b7a7350e 100644 --- a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs +++ b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs @@ -4,20 +4,21 @@ namespace Prql.Compiler.Tests; sealed public class CompilerTest { - [Fact] - public void ToSql_Works() - { - // Arrange - var expected = "SELECT\n *\nFROM\n employees\n\n" + - "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; - var signature = "-- Generated by PRQL compiler"; - expected = expected.Substring(0, expected.IndexOf(signature)); + // TODO: update to the new c-api + // [Fact] + // public void ToSql_Works() + // { + // // Arrange + // var expected = "SELECT\n *\nFROM\n employees\n\n" + + // "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; + // var signature = "-- Generated by PRQL compiler"; + // expected = expected.Substring(0, expected.IndexOf(signature)); - // Act - var sqlQuery = PrqlCompiler.ToSql("from employees"); - sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); + // // Act + // var sqlQuery = PrqlCompiler.ToSql("from employees"); + // sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); - // Assert - Assert.Equal(expected, sqlQuery); - } + // // Assert + // Assert.Equal(expected, sqlQuery); + // } } diff --git a/prql-lib/README.md b/prql-lib/README.md index ba49ff9fffa5..b56e0cb8e1ba 100644 --- a/prql-lib/README.md +++ b/prql-lib/README.md @@ -1,18 +1,23 @@ -# PRQL library target +# PRQL C library ## Description This module compiles PRQL as a library (both `.a` and `.so` are generated). This allows embedding in languages that support FFI - looking at Golang. -## Usage +## Linking + +See [examples/minimal-c/Makefile](examples/minimal-c/Makefile). Copy the `.a` and `.so` files in a convenient place and add the following compile flags to Go (cgo): `CGO_LDFLAGS="-L/path/to/libprql_lib.a -lprql_lib -pthread -ldl" go build` -## Code +## Examples + +For a minimal example, see +[examples/minimal-c/main.c](examples/minimal-c/main.c). Below is an example from an actual application that is using PRQL in Go. @@ -83,7 +88,9 @@ func ToJSON(prql string) (string, error) { } ``` -## C header file +## Development + +### C header file The C header file `libprql_lib.h` was generated using [cbindgen](https://github.com/eqrion/cbindgen). To generate a new one run: diff --git a/prql-lib/examples/minimal-c/Makefile b/prql-lib/examples/minimal-c/Makefile new file mode 100644 index 000000000000..e1ceb0b6c435 --- /dev/null +++ b/prql-lib/examples/minimal-c/Makefile @@ -0,0 +1,14 @@ +PRQL_PROJECT=../../.. + +build-prql: + cargo build -p prql-lib --release + +build: main.c build-prql + gcc main.c -o main.out \ + -I${PRQL_PROJECT}/prql-lib \ + -L${PRQL_PROJECT}/target/release \ + -l:libprql_lib.a \ + -pthread -ldl -lm + +run: build + ./main.out diff --git a/prql-lib/examples/minimal-c/README.md b/prql-lib/examples/minimal-c/README.md new file mode 100644 index 000000000000..b1762921ca3f --- /dev/null +++ b/prql-lib/examples/minimal-c/README.md @@ -0,0 +1,7 @@ +# Basic C example + +A minimal example for using prql-lib with `gcc` and `make`. + +## How to run + + make run diff --git a/prql-lib/examples/minimal-c/main.c b/prql-lib/examples/minimal-c/main.c new file mode 100644 index 000000000000..62d57dbc78a5 --- /dev/null +++ b/prql-lib/examples/minimal-c/main.c @@ -0,0 +1,47 @@ +#include + +#include + +int main() { + char *prql_query; + prql_query = "from albums | select [album_id, title] | take 3"; + + int res; + char res_buffer[256]; + + // default compile option + res = compile(prql_query, NULL, res_buffer); + printf("%s\n\n", res_buffer); + + // custom compile options + Options opts; + opts.format = false; + opts.signature_comment = false; + opts.target = "sql.mssql"; + res = compile(prql_query, &opts, res_buffer); + printf("%s\n\n", res_buffer); + + // error handling + res = compile("from album | select [album_id] | select [title]", NULL, res_buffer); + if (res == 0) { + printf("success\n\n"); + } + if (res < 0) { + printf("error with code %d!\n%s\n\n", res, res_buffer); + } + + // intermediate results + char* pl_buffer = (char*) malloc(sizeof(char) * 512); + char* rq_buffer = (char*) malloc(sizeof(char) * 512); + + res = prql_to_pl(prql_query, pl_buffer); + printf("PL JSON: %s\n\n", pl_buffer); + + res = pl_to_rq(pl_buffer, rq_buffer); + printf("RQ JSON: %s\n\n", rq_buffer); + + free(pl_buffer); + free(rq_buffer); + + return 0; +} diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h index 8a1ed325e4f0..7667c24dca1b 100644 --- a/prql-lib/libprql_lib.h +++ b/prql-lib/libprql_lib.h @@ -4,15 +4,61 @@ #include /** - * # Safety + * Compilation options + */ +typedef struct Options { + /** + * Pass generated SQL string trough a formatter that splits it + * into multiple lines and prettifies indentation and spacing. + * + * Defaults to true. + */ + bool format; + /** + * Target and dialect to compile to. + */ + char *target; + /** + * Emits the compiler signature as a comment after generated SQL + * + * Defaults to true. + */ + bool signature_comment; +} Options; + +/** + * Compile a PRQL string into a SQL string. + * + * This is a wrapper for: `prql_to_pl`, `pl_to_rq` and `rq_to_sql` without converting to JSON + * between each of the functions. * - * This function is inherently unsafe because it is using C ABI. + * See `Options` struct for available compilation options. */ -int to_sql(const char *query, char *out); +int compile(const char *prql_query, const struct Options *options, char *out); /** - * # Safety + * Build PL AST from a PRQL string + * + * Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer. + * + * Returns 0 on success and a negative number -1 on failure. + */ +int prql_to_pl(const char *prql_query, char *out); + +/** + * Finds variable references, validates functions calls, determines frames and converts PL to RQ. + * + * Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer. + * + * Returns 0 on success and a negative number -1 on failure. + */ +int pl_to_rq(const char *pl_json, char *out); + +/** + * Convert RQ AST into an SQL string. + * + * Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer. * - * This function is inherently unsafe because it using C ABI. + * Returns 0 on success and a negative number -1 on failure. */ -int to_json(const char *query, char *out); +int rq_to_sql(const char *rq_json, char *out); diff --git a/prql-lib/src/lib.rs b/prql-lib/src/lib.rs index 2f741b3a40ac..cf0fac70f5e8 100644 --- a/prql-lib/src/lib.rs +++ b/prql-lib/src/lib.rs @@ -3,65 +3,150 @@ extern crate libc; use libc::{c_char, c_int}; -use prql_compiler::Options; -use prql_compiler::{json, prql_to_pl}; +use prql_compiler::ErrorMessages; +use prql_compiler::Target; use std::ffi::CStr; use std::ffi::CString; +use std::str::FromStr; -#[no_mangle] -#[allow(non_snake_case)] +/// Compile a PRQL string into a SQL string. +/// +/// This is a wrapper for: `prql_to_pl`, `pl_to_rq` and `rq_to_sql` without converting to JSON +/// between each of the functions. +/// +/// See `Options` struct for available compilation options. +/// /// # Safety /// -/// This function is inherently unsafe because it is using C ABI. -pub unsafe extern "C" fn to_sql(query: *const c_char, out: *mut c_char) -> c_int { - let prql_query: String = CStr::from_ptr(query).to_string_lossy().into_owned(); +/// This function assumes zero-terminated strings and sufficiently large output buffers. +#[no_mangle] +pub unsafe extern "C" fn compile( + prql_query: *const c_char, + options: *const Options, + out: *mut c_char, +) -> c_int { + let prql_query: String = c_str_to_string(prql_query); - let (isErr, sql_result) = match prql_compiler::compile(&prql_query, &Options::default()) { - Ok(sql_str) => (false, sql_str), - Err(err) => { - //let err_str = format!("{}", err); - (true, err.to_string()) - } - }; + let result = Ok(prql_query.as_str()) + .and_then(prql_compiler::prql_to_pl) + .and_then(prql_compiler::pl_to_rq) + .and_then(|rq| { + prql_compiler::rq_to_sql(rq, &options.as_ref().map(|o| o.into()).unwrap_or_default()) + }) + .map_err(|e| e.composed("", &prql_query, false)); - let copylen = sql_result.len(); - let c_str = CString::new(sql_result).unwrap(); + result_into_c_str(result, out) +} - out.copy_from(c_str.as_ptr(), copylen); - let end_of_string_ptr = out.add(copylen); - *end_of_string_ptr = 0; +/// Build PL AST from a PRQL string +/// +/// Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// +/// # Safety +/// +/// This function assumes zero-terminated strings and sufficiently large output buffers. +#[no_mangle] +pub unsafe extern "C" fn prql_to_pl(prql_query: *const c_char, out: *mut c_char) -> c_int { + let prql_query: String = c_str_to_string(prql_query); - match isErr { - true => -1, - false => 0, - } + let result = Ok(prql_query.as_str()) + .and_then(prql_compiler::prql_to_pl) + .and_then(prql_compiler::json::from_pl); + result_into_c_str(result, out) } +/// Finds variable references, validates functions calls, determines frames and converts PL to RQ. +/// +/// Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// +/// # Safety +/// +/// This function assumes zero-terminated strings and sufficiently large output buffers. #[no_mangle] -#[allow(non_snake_case)] +pub unsafe extern "C" fn pl_to_rq(pl_json: *const c_char, out: *mut c_char) -> c_int { + let pl_json: String = c_str_to_string(pl_json); + + let result = Ok(pl_json.as_str()) + .and_then(prql_compiler::json::to_pl) + .and_then(prql_compiler::pl_to_rq) + .and_then(prql_compiler::json::from_rq); + result_into_c_str(result, out) +} + +/// Convert RQ AST into an SQL string. +/// +/// Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// /// # Safety /// -/// This function is inherently unsafe because it using C ABI. -pub unsafe extern "C" fn to_json(query: *const c_char, out: *mut c_char) -> c_int { - let prql_query: String = CStr::from_ptr(query).to_string_lossy().into_owned(); +/// This function assumes zero-terminated strings and sufficiently large output buffers. +#[no_mangle] +pub unsafe extern "C" fn rq_to_sql(rq_json: *const c_char, out: *mut c_char) -> c_int { + let rq_json: String = c_str_to_string(rq_json); - let (isErr, sql_result) = match prql_to_pl(&prql_query).and_then(json::from_pl) { - Ok(sql_str) => (false, sql_str), - Err(err) => { - //let err_str = format!("{}", err); - (true, err.to_string()) - } + let result = Ok(rq_json.as_str()) + .and_then(prql_compiler::json::to_rq) + .and_then(|x| prql_compiler::rq_to_sql(x, &prql_compiler::Options::default())); + result_into_c_str(result, out) +} + +/// Compilation options +#[repr(C)] +pub struct Options { + /// Pass generated SQL string trough a formatter that splits it + /// into multiple lines and prettifies indentation and spacing. + /// + /// Defaults to true. + pub format: bool, + + /// Target and dialect to compile to. + pub target: *mut c_char, + + /// Emits the compiler signature as a comment after generated SQL + /// + /// Defaults to true. + pub signature_comment: bool, +} + +unsafe fn result_into_c_str(result: Result, out: *mut c_char) -> i32 { + let (is_err, string) = match result { + Ok(string) => (false, string), + Err(err) => (true, err.to_string()), }; - let copylen = sql_result.len(); - let c_str = CString::new(sql_result).unwrap(); + let copy_len = string.bytes().len(); + let c_str = CString::new(string).unwrap(); - out.copy_from(c_str.as_ptr(), copylen); - let end_of_string_ptr = out.add(copylen); + out.copy_from(c_str.as_ptr(), copy_len); + let end_of_string_ptr = out.add(copy_len); *end_of_string_ptr = 0; - match isErr { + match is_err { true => -1, false => 0, } } + +unsafe fn c_str_to_string(c_str: *const c_char) -> String { + // inefficient, but simple + CStr::from_ptr(c_str).to_string_lossy().into_owned() +} + +impl From<&Options> for prql_compiler::Options { + fn from(o: &Options) -> Self { + let target = unsafe { c_str_to_string(o.target) }; + let target = Target::from_str(&target).unwrap_or_default(); + + prql_compiler::Options { + format: o.format, + target, + signature_comment: o.signature_comment, + } + } +} From 40f65710c2cb99d5949d9e1e47a69e488e18fc04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 23 Feb 2023 16:34:57 +0100 Subject: [PATCH 052/184] docs: prql-lib docs (#1945) --- prql-lib/libprql_lib.h | 24 ++++++++++++++++++++++-- prql-lib/src/lib.rs | 8 ++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h index 7667c24dca1b..e605d46b9987 100644 --- a/prql-lib/libprql_lib.h +++ b/prql-lib/libprql_lib.h @@ -33,32 +33,52 @@ typedef struct Options { * between each of the functions. * * See `Options` struct for available compilation options. + * + * # Safety + * + * This function assumes zero-terminated strings and sufficiently large output buffers. */ int compile(const char *prql_query, const struct Options *options, char *out); /** - * Build PL AST from a PRQL string + * Build PL AST from a PRQL string. PL in documented in the + * [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/pl). * * Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer. * * Returns 0 on success and a negative number -1 on failure. + * + * # Safety + * + * This function assumes zero-terminated strings and sufficiently large output buffers. */ int prql_to_pl(const char *prql_query, char *out); /** * Finds variable references, validates functions calls, determines frames and converts PL to RQ. + * PL and RQ are documented in the + * [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast). * * Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer. * * Returns 0 on success and a negative number -1 on failure. + * + * # Safety + * + * This function assumes zero-terminated strings and sufficiently large output buffers. */ int pl_to_rq(const char *pl_json, char *out); /** - * Convert RQ AST into an SQL string. + * Convert RQ AST into an SQL string. RQ is documented in the + * [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/rq). * * Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer. * * Returns 0 on success and a negative number -1 on failure. + * + * # Safety + * + * This function assumes zero-terminated strings and sufficiently large output buffers. */ int rq_to_sql(const char *rq_json, char *out); diff --git a/prql-lib/src/lib.rs b/prql-lib/src/lib.rs index cf0fac70f5e8..ef00c96d5ccd 100644 --- a/prql-lib/src/lib.rs +++ b/prql-lib/src/lib.rs @@ -38,7 +38,8 @@ pub unsafe extern "C" fn compile( result_into_c_str(result, out) } -/// Build PL AST from a PRQL string +/// Build PL AST from a PRQL string. PL in documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/pl). /// /// Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer. /// @@ -58,6 +59,8 @@ pub unsafe extern "C" fn prql_to_pl(prql_query: *const c_char, out: *mut c_char) } /// Finds variable references, validates functions calls, determines frames and converts PL to RQ. +/// PL and RQ are documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast). /// /// Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer. /// @@ -77,7 +80,8 @@ pub unsafe extern "C" fn pl_to_rq(pl_json: *const c_char, out: *mut c_char) -> c result_into_c_str(result, out) } -/// Convert RQ AST into an SQL string. +/// Convert RQ AST into an SQL string. RQ is documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/rq). /// /// Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer. /// From 61dc66395143db5ffea0c3f60c142d0adaa43567 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 08:28:30 -0800 Subject: [PATCH 053/184] fix: Panic with multiple terms after a `from` transform (#1928) --- prql-compiler/src/semantic/resolver.rs | 12 ++++++++++- prql-compiler/src/test.rs | 29 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/prql-compiler/src/semantic/resolver.rs b/prql-compiler/src/semantic/resolver.rs index dcc68bdf1b62..b0cd8af29b40 100644 --- a/prql-compiler/src/semantic/resolver.rs +++ b/prql-compiler/src/semantic/resolver.rs @@ -409,7 +409,17 @@ impl Resolver { closure.args.len(), closure.params.len() ); - let enough_args = closure.args.len() >= closure.params.len(); + + if closure.args.len() > closure.params.len() { + return Err(Error::new_simple(format!( + "Too many arguments to function `{}`", + closure.as_debug_name() + )) + .with_span(span) + .into()); + } + + let enough_args = closure.args.len() == closure.params.len(); let mut r = if enough_args { // push the env diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 170c8cd42f45..fbe73829bf12 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2883,6 +2883,35 @@ fn test_closures_and_pipelines() { /// Start testing some error messages. This can hopefully be expanded significantly. // It's also fine to put errors by the things that they're testing. fn test_errors() { + assert_display_snapshot!(compile(r###" + func addadd a b -> a + b + + from x + derive y = (addadd 4 5 6) + "###).unwrap_err(), + @r###" + Error: + โ•ญโ”€[:5:12] + โ”‚ + 5 โ”‚ derive y = (addadd 4 5 6) + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `addadd` + โ”€โ”€โ”€โ•ฏ + "###); + + assert_display_snapshot!(compile(r###" + from a select b + "###).unwrap_err(), + @r###" + Error: + โ•ญโ”€[:2:5] + โ”‚ + 2 โ”‚ from a select b + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `from` + โ”€โ”€โ”€โ•ฏ + "###); + assert_display_snapshot!(compile(r###" from x select a From 473170251d1482aa17f7534b4d98d835432bc8c7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 23 Feb 2023 17:31:19 +0100 Subject: [PATCH 054/184] chore: bump chumsky from 0.8.0 to 0.9.0 (#1723) --- Cargo.lock | 15 +++------------ prql-compiler/Cargo.toml | 4 +++- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 754ecb3bc58f..013e31762293 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,15 +17,6 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" -dependencies = [ - "const-random", -] - [[package]] name = "ahash" version = "0.7.6" @@ -455,11 +446,11 @@ dependencies = [ [[package]] name = "chumsky" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4" +checksum = "c4d619fba796986dd538d82660b76e0b9756c6e19b2e4d4559ba5a57f9f00810" dependencies = [ - "ahash 0.3.8", + "hashbrown 0.12.3", ] [[package]] diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index cd74ecc67c24..9323ff5f59d3 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -15,7 +15,9 @@ metadata.msrv = "1.65.0" [dependencies] anyhow = {version = "1.0.57", features = ["backtrace"]} ariadne = "0.1.5" -chumsky = "0.8.0" +# We don't include the `spill-stack` feature, since it causes builds in GHA to +# fail. If that no longer happens, we can re-enable it. +chumsky = {version = "0.9.0", features = ["ahash", "std"], default-features = false } csv = "1.2.0" enum-as-inner = "0.5.0" itertools = "0.10.3" From de474182a23ccc7de70b417692228905e717a697 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Thu, 23 Feb 2023 18:45:05 +0100 Subject: [PATCH 055/184] build: Fix .NET bindings (#1946) * Update CompilerTest.cs * Update README.md * Update PrqlCompilerOptions.cs * Update PrqlCompiler.cs --- .../PrqlCompiler.Tests/CompilerTest.cs | 30 +++++++------- prql-dotnet/PrqlCompiler/PrqlCompiler.cs | 41 ++++--------------- .../PrqlCompiler/PrqlCompilerOptions.cs | 3 ++ prql-dotnet/README.md | 7 +++- 4 files changed, 33 insertions(+), 48 deletions(-) diff --git a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs index 2505b7a7350e..3b07fb20b183 100644 --- a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs +++ b/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs @@ -4,21 +4,21 @@ namespace Prql.Compiler.Tests; sealed public class CompilerTest { - // TODO: update to the new c-api - // [Fact] - // public void ToSql_Works() - // { - // // Arrange - // var expected = "SELECT\n *\nFROM\n employees\n\n" + - // "-- Generated by PRQL compiler version:x.y.z (https://prql-lang.org)\n"; - // var signature = "-- Generated by PRQL compiler"; - // expected = expected.Substring(0, expected.IndexOf(signature)); + [Fact] + public void ToCompile_Works() + { + // Arrange + var expected = "SELECT * FROM employees"; - // // Act - // var sqlQuery = PrqlCompiler.ToSql("from employees"); - // sqlQuery = sqlQuery.Substring(0, sqlQuery.IndexOf(signature)); + // Act + var options = new PrqlCompilerOptions + { + Format = false, + SignatureComment = false, + }; + var sqlQuery = PrqlCompiler.Compile("from employees", options); - // // Assert - // Assert.Equal(expected, sqlQuery); - // } + // Assert + Assert.Equal(expected, sqlQuery); + } } diff --git a/prql-dotnet/PrqlCompiler/PrqlCompiler.cs b/prql-dotnet/PrqlCompiler/PrqlCompiler.cs index 04843d088d05..500fb4c7ea70 100644 --- a/prql-dotnet/PrqlCompiler/PrqlCompiler.cs +++ b/prql-dotnet/PrqlCompiler/PrqlCompiler.cs @@ -24,7 +24,9 @@ public static string Compile(string prqlQuery) throw new ArgumentException(nameof(prqlQuery)); } - return CompileExtern(prqlQuery); + var options = new PrqlCompilerOptions(); + + return Compile(prqlQuery, options); } /// @@ -43,30 +45,8 @@ public static string Compile(string prqlQuery, PrqlCompilerOptions options) throw new ArgumentException(nameof(prqlQuery)); } - if (options == null) - { - throw new ArgumentNullException(nameof(options)); - } - - return CompileExtern(prqlQuery); - } - - /// - /// Compile a PRQL string into a JSON string. - /// - /// A PRQL query. - /// JSON. - /// is null or empty. - /// cannot be compiled. - public static string ToJson(string prqlQuery) - { - if (string.IsNullOrEmpty(prqlQuery)) - { - throw new ArgumentException(nameof(prqlQuery)); - } - byte[] bytes = new byte[1024]; - if (ToJsonExtern(prqlQuery, bytes) != 0) + if (CompileExtern(prqlQuery, ref options, bytes) != 0) { throw new FormatException("Could not compile query."); } @@ -77,13 +57,13 @@ public static string ToJson(string prqlQuery) } /// - /// Compile a PRQL string into a SQL query. + /// Compile a PRQL string into a JSON string. /// /// A PRQL query. - /// SQL query. + /// JSON. /// is null or empty. /// cannot be compiled. - public static string ToSql(string prqlQuery) + public static string ToJson(string prqlQuery) { if (string.IsNullOrEmpty(prqlQuery)) { @@ -91,7 +71,7 @@ public static string ToSql(string prqlQuery) } byte[] bytes = new byte[1024]; - if (ToSqlExtern(prqlQuery, bytes) != 0) + if (ToJsonExtern(prqlQuery, bytes) != 0) { throw new FormatException("Could not compile query."); } @@ -102,12 +82,9 @@ public static string ToSql(string prqlQuery) } [DllImport("libprql_lib", EntryPoint = "compile")] - private static extern string CompileExtern(string prql_query); + private static extern int CompileExtern(string prql_query, ref PrqlCompilerOptions options, byte[] sql_query); [DllImport("libprql_lib", EntryPoint = "to_json")] private static extern int ToJsonExtern(string prql_query, byte[] json); - - [DllImport("libprql_lib", EntryPoint = "to_sql")] - private static extern int ToSqlExtern(string prql_query, byte[] sql_query); } } diff --git a/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs b/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs index 0dc48e2169af..4b827e91073f 100644 --- a/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs +++ b/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs @@ -1,8 +1,11 @@ +using System.Runtime.InteropServices; + namespace Prql.Compiler { /// /// Compilation options for SQL backend of the compiler. /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public class PrqlCompilerOptions { /// diff --git a/prql-dotnet/README.md b/prql-dotnet/README.md index 7b81f6cfdd23..6021e017b360 100644 --- a/prql-dotnet/README.md +++ b/prql-dotnet/README.md @@ -22,7 +22,12 @@ The `libprql_lib` library gets dynamically imported at runtime. ```csharp using Prql.Compiler; -var sql = PrqlCompiler.ToSql("from employees"); +var options = new PrqlCompilerOptions +{ + Format = false, + SignatureComment = false, +}; +var sql = PrqlCompiler.Compile("from employees", options); Console.WriteLine(sql); ``` From 7fec008a04847fdb391b76750fea97e6fefd6eed Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 10:18:01 -0800 Subject: [PATCH 056/184] test: Disable PHP tests until aligned with `prql-lib` (#1947) Just to ensure the build stays green as discussed in https://discord.com/channels/936728116712316989/1078360136978022510. Thanks to @aljazerzen & @vanillajonathan for the changes. --- .github/workflows/test-php.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml index af2b19202350..97f1e72bd1be 100644 --- a/.github/workflows/test-php.yaml +++ b/.github/workflows/test-php.yaml @@ -38,5 +38,7 @@ jobs: args: --working-dir=prql-php php_extensions: FFI - name: ๐Ÿงช Run tests using PHPUnit + # TODO: enable when aligned with https://github.com/PRQL/prql/pull/1941 + if: false run: vendor/bin/phpunit tests working-directory: prql-php From e3988c809aaadab83e8deb6de8bbbd4188817252 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 12:06:49 -0800 Subject: [PATCH 057/184] chore: Add `testng` to typos exclusion (#1948) Required in https://github.com/PRQL/prql/pull/1929#issuecomment-1441671378 --- _typos.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_typos.toml b/_typos.toml index 1480bde0ec83..2038bb357644 100644 --- a/_typos.toml +++ b/_typos.toml @@ -5,3 +5,7 @@ extend-exclude = [ "website/themes/prql-theme/static/plugins/bootstrap", "website/themes/prql-theme/static/plugins/highlight/highlight.min.js", ] + +[default.extend-words] +# Java test framework +testng = "testng" From b52df6f0478e9c1d51e11df16f7792347dfae337 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 19:50:20 -0800 Subject: [PATCH 058/184] docs: Add a note re reverting (#1952) --- book/src/contributing/development.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index cca2d9145743..2f482a58f65d 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -182,7 +182,9 @@ change! - We should revert quickly if the impact of a PR turns out not to be consistent with our expectations, or there isn't as much consensus on a decision as we had hoped. It's very easy to revert code and then re-revert when we've - resolved the issue; it's a sign of moving quickly. + resolved the issue; it's a sign of moving quickly. Other options which resolve + the build immediately are also fine, such as commenting out an incorrect test + or adding a quick fix for the underlying issue. ## Components of PRQL From 6388d7c05dea77908c95e55a42018d699ba75212 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 20:12:02 -0800 Subject: [PATCH 059/184] revert: re-revert loop (#1951) * revert: re-revert loop Re-reverts #1899 & #1901 * fix book link --- .github/workflows/test-all.yaml | 6 + .github/workflows/test-dotnet.yaml | 1 + .github/workflows/test-java.yaml | 1 + .github/workflows/test-lib.yaml | 6 + .github/workflows/test-php.yaml | 1 + CHANGELOG.md | 2 + book/README.md | 2 +- book/book.toml | 2 +- book/src/SUMMARY.md | 4 +- book/src/integrations/jupyter.md | 2 +- book/src/integrations/rill.md | 2 +- book/src/internals/name-resolving.md | 2 +- book/src/language-features/README.md | 1 - .../README.md} | 4 +- .../standard-library/from-text.md | 63 ++ .../standard-library/loop.md | 50 ++ book/src/syntax.md | 2 +- book/src/transforms/from_text.md | 61 -- .../README-0.prql} | 0 .../standard-library/from-text-0.prql} | 0 .../standard-library/from-text-1.prql} | 0 .../standard-library/from-text-2.prql} | 0 .../standard-library/loop-0.prql | 7 + .../snapshot__@examples__cte-0.prql.snap | 22 +- ...snapshot__@examples__employees-0.prql.snap | 21 +- ...snapshot__@examples__employees-1.prql.snap | 27 +- ...snapshot__@examples__employees-2.prql.snap | 23 +- ...snapshot__@examples__employees-3.prql.snap | 11 +- .../snapshot__@examples__misc-0.prql.snap | 15 +- ...snapshot__@examples__variables-0.prql.snap | 3 +- ...snapshot__@examples__variables-1.prql.snap | 9 +- .../snapshot__@introduction-0.prql.snap | 5 +- ...__@language-features__distinct-2.prql.snap | 3 +- ..._@language-features__s-strings-3.prql.snap | 13 +- ...res__standard-library__README-0.prql.snap} | 3 +- ...__standard-library__from-text-0.prql.snap} | 6 +- ...__standard-library__from-text-1.prql.snap} | 2 +- ...__standard-library__from-text-2.prql.snap} | 2 +- ...atures__standard-library__loop-0.prql.snap | 34 + .../snapshot__@queries__pipelines-2.prql.snap | 9 +- .../snapshot__@queries__variables-0.prql.snap | 4 +- .../snapshots/snapshot__@syntax-5.prql.snap | 3 +- .../snapshot__@transforms__group-2.prql.snap | 3 +- .../snapshot__@transforms__sort-3.prql.snap | 17 +- .../snapshot__@transforms__sort-5.prql.snap | 7 +- .../snapshot__@transforms__window-4.prql.snap | 3 +- ...res__standard-library__README-0.prql.snap} | 0 ...__standard-library__from-text-0.prql.snap} | 0 ...__standard-library__from-text-1.prql.snap} | 0 ...__standard-library__from-text-2.prql.snap} | 0 ...atures__standard-library__loop-0.prql.snap | 12 + prql-compiler/src/ast/pl/expr.rs | 1 + prql-compiler/src/ast/pl/fold.rs | 1 + prql-compiler/src/ast/pl/types.rs | 8 +- prql-compiler/src/ast/rq/fold.rs | 1 + prql-compiler/src/ast/rq/transform.rs | 1 + prql-compiler/src/semantic/lowering.rs | 33 +- prql-compiler/src/semantic/std.prql | 1 + prql-compiler/src/semantic/transforms.rs | 8 + .../prql_compiler__test__prql_to_sql_2.snap | 3 +- prql-compiler/src/sql/anchor.rs | 87 ++- prql-compiler/src/sql/context.rs | 61 +- prql-compiler/src/sql/gen_expr.rs | 75 +- prql-compiler/src/sql/gen_query.rs | 687 ++++++++++-------- prql-compiler/src/sql/mod.rs | 35 + prql-compiler/src/sql/preprocess.rs | 68 +- ...query__test__variable_after_aggregate.snap | 3 +- prql-compiler/src/test.rs | 291 +++++--- .../tests/integration/queries/loop.prql | 7 + .../integration__tests__test@loop.prql.snap | 12 + website/content/_index.md | 2 +- 71 files changed, 1119 insertions(+), 742 deletions(-) rename book/src/language-features/{standard-library.md => standard-library/README.md} (92%) create mode 100644 book/src/language-features/standard-library/from-text.md create mode 100644 book/src/language-features/standard-library/loop.md rename book/tests/prql/language-features/{standard-library-0.prql => standard-library/README-0.prql} (100%) rename book/tests/prql/{transforms/from_text-0.prql => language-features/standard-library/from-text-0.prql} (100%) rename book/tests/prql/{transforms/from_text-1.prql => language-features/standard-library/from-text-1.prql} (100%) rename book/tests/prql/{transforms/from_text-2.prql => language-features/standard-library/from-text-2.prql} (100%) create mode 100644 book/tests/prql/language-features/standard-library/loop-0.prql rename book/tests/snapshots/{snapshot__@language-features__standard-library-0.prql.snap => snapshot__@language-features__standard-library__README-0.prql.snap} (84%) rename book/tests/snapshots/{snapshot__@transforms__from_text-0.prql.snap => snapshot__@language-features__standard-library__from-text-0.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@transforms__from_text-1.prql.snap => snapshot__@language-features__standard-library__from-text-1.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@transforms__from_text-2.prql.snap => snapshot__@language-features__standard-library__from-text-2.prql.snap} (91%) create mode 100644 book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap rename book/tests/snapshots/{snapshot__tests__prql__language-features__standard-library-0.prql.snap => snapshot__tests__prql__language-features__standard-library__README-0.prql.snap} (100%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__from_text-0.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap} (100%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__from_text-1.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap} (100%) rename book/tests/snapshots/{snapshot__tests__prql__transforms__from_text-2.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap} (100%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap create mode 100644 prql-compiler/tests/integration/queries/loop.prql create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 065698e9baca..34ea805c7de4 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -47,6 +47,12 @@ jobs: test-elixir: uses: ./.github/workflows/test-elixir.yaml + test-dotnet: + uses: ./.github/workflows/test-dotnet.yaml + + test-lib: + uses: ./.github/workflows/test-lib.yaml + measure-code-cov: # Currently disabled due to https://github.com/actions-rs/tarpaulin/issues/21 if: false diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml index eae9601d8d02..402f9a7046f9 100644 --- a/.github/workflows/test-dotnet.yaml +++ b/.github/workflows/test-dotnet.yaml @@ -4,6 +4,7 @@ on: pull_request: paths: - "prql-dotnet/**" + - "prql-lib/**" - ".github/workflows/test-dotnet.yaml" workflow_call: diff --git a/.github/workflows/test-java.yaml b/.github/workflows/test-java.yaml index 780c87f3da28..ed3a8754510f 100644 --- a/.github/workflows/test-java.yaml +++ b/.github/workflows/test-java.yaml @@ -4,6 +4,7 @@ on: pull_request: paths: - "prql-java/**" + - "prql-lib/**" - ".github/workflows/test-java.yaml" workflow_call: diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml index 7937d0066449..7bd0f8d36c19 100644 --- a/.github/workflows/test-lib.yaml +++ b/.github/workflows/test-lib.yaml @@ -3,10 +3,16 @@ name: test-lib on: pull_request: paths: + # We also run the tests for the libraries that depend on this, from their workflow files. - "prql-lib/**" - ".github/workflows/test-lib.yaml" workflow_call: +concurrency: + # See notes in `pull-request.yaml` + group: ${{ github.workflow }}-${{ github.ref }}-lib + cancel-in-progress: true + jobs: test: runs-on: ubuntu-latest diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml index 97f1e72bd1be..608b5d20e114 100644 --- a/.github/workflows/test-php.yaml +++ b/.github/workflows/test-php.yaml @@ -4,6 +4,7 @@ on: pull_request: paths: - "prql-php/**" + - "prql-lib/**" - ".github/workflows/test-php.yaml" workflow_call: diff --git a/CHANGELOG.md b/CHANGELOG.md index f7780ba05e38..47a1ba3bf508 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ **Features**: +- `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) + **Fixes**: - `prqlc compile` returns a non-zero exit code for invalid queries. (@max-sixty, diff --git a/book/README.md b/book/README.md index ec088b512dcb..57b803d93865 100644 --- a/book/README.md +++ b/book/README.md @@ -1,4 +1,4 @@ -# PRQL Language Book +# PRQL language book These docs serve as a language book, for users of the language. They should be friendly & accessible, at a minimum to those who understand basic SQL. diff --git a/book/book.toml b/book/book.toml index 6849dde897c5..1ce7a8769425 100644 --- a/book/book.toml +++ b/book/book.toml @@ -2,7 +2,7 @@ description = "Modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement" language = "en" multilingual = false -title = "PRQL Language Book" +title = "PRQL language book" [output.html] additional-css = ["comparison-table.css", "mdbook-admonish.css"] diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index 153e70bdb090..cc27566b74a2 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -36,7 +36,9 @@ - [Ranges](./language-features/ranges.md) - [Regex](./language-features/regex.md) - - [Stdlib](./language-features/standard-library.md) + - [Standard library](./language-features/standard-library/README.md) + - [From text](./language-features/standard-library/from-text.md) + - [Loop](./language-features/standard-library/loop.md) - [Strings](./language-features/strings.md) - [S-strings](./language-features/s-strings.md) - [F-strings](./language-features/f-strings.md) diff --git a/book/src/integrations/jupyter.md b/book/src/integrations/jupyter.md index 176a47ac11ad..7b0bdd3c063d 100644 --- a/book/src/integrations/jupyter.md +++ b/book/src/integrations/jupyter.md @@ -24,7 +24,7 @@ could to go! We bundle in `IPython` and `pandas`, though you'll need to install pip install pyprql ``` -### Set Up +### Set up Open up either an `IPython` terminal or `Jupyter` notebook. First, we need to load the extension and connect to a database. diff --git a/book/src/integrations/rill.md b/book/src/integrations/rill.md index 950e0b5fb50d..0e2f4729e32e 100644 --- a/book/src/integrations/rill.md +++ b/book/src/integrations/rill.md @@ -1,5 +1,5 @@ # Rill PRQL has had some work to integrate with Rill. See the -[Rill Issues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more +[Rill ssues](https://github.com/PRQL/prql/issues?q=is%3Aissue+rill) for more details. diff --git a/book/src/internals/name-resolving.md b/book/src/internals/name-resolving.md index 74b590e93a14..78a153358959 100644 --- a/book/src/internals/name-resolving.md +++ b/book/src/internals/name-resolving.md @@ -50,7 +50,7 @@ three things can happen: ## Translating to SQL -When translating into a SQL statement which references only one table, there is +When translating into an SQL statement which references only one table, there is no need to reference column names with table prefix. ```prql diff --git a/book/src/language-features/README.md b/book/src/language-features/README.md index c03c67d19706..45b07178b7d4 100644 --- a/book/src/language-features/README.md +++ b/book/src/language-features/README.md @@ -11,7 +11,6 @@ language. | Null handling | [Handle `NULL` values](./null.md) | | Ranges | [Syntax for all forms of ranges](./ranges.md) | | Regex | [Handle regular expressions](./regex.md) | -| Stdlib | [PRQL's "builtin" set of functions](./standard-library.md) | | Strings | [Rules for creating strings](./strings.md) | | S-strings | [Insert SQL directly into a query with an S-string](./s-strings.md) | | F-strings | [Combine several column's data with F-strings](./f-strings.md) | diff --git a/book/src/language-features/standard-library.md b/book/src/language-features/standard-library/README.md similarity index 92% rename from book/src/language-features/standard-library.md rename to book/src/language-features/standard-library/README.md index 220565d5cf3d..d4dbec6dbf5f 100644 --- a/book/src/language-features/standard-library.md +++ b/book/src/language-features/standard-library/README.md @@ -1,4 +1,4 @@ -# Standard Library +# Standard library The standard library currently contains commonly used functions that are used in SQL. It's not yet as broad as we'd like, and we're very open to expanding it. @@ -17,7 +17,7 @@ Here's the source of the current [PRQL `std`](https://github.com/PRQL/prql/blob/main/prql-compiler/src/semantic/std.prql): ```prql_no_test -{{#include ../../../prql-compiler/src/semantic/std.prql}} +{{#include ../../../../prql-compiler/src/semantic/std.prql}} ``` And a couple of examples: diff --git a/book/src/language-features/standard-library/from-text.md b/book/src/language-features/standard-library/from-text.md new file mode 100644 index 000000000000..29229f6db0ef --- /dev/null +++ b/book/src/language-features/standard-library/from-text.md @@ -0,0 +1,63 @@ +# From text + +It's often useful to make a small table inline, for example when exploring how a +database will evaluate an expression, or to have a small lookup table inline. +This can be quite verbose in SQL. + +PRQL uses `from_text` for this. + +It accepts a few formats: + +- `format:csv` parses CSV (default), +- `format:json` parses either: + - an array of objects each of which represents a row, or + - an object with fields `columns` & `data`, where `columns` take an array of + column names and `data` takes an array of arrays. + +```prql +from_text """ +a,b,c +1,2,3 +4,5,6 +""" +derive [ + d = b + c, + answer = 20 * 2 + 2, +] +``` + +An example of adding a small lookup table: + +```prql +let temp_format_lookup = from_text format:csv """ +country_code,format +uk,C +us,F +lr,F +de,C +""" + +from temperatures +join temp_format_lookup [==country_code] +``` + +And JSON: + +```prql +let x = from_text format:json """{ + "columns": ["a", "b", "c"], + "data": [ + [1, "x", false], + [4, "y", null] + ] +}""" + +let y = from_text format:json """ + [ + {"a": 1, "m": "5"}, + {"a": 4, "n": "6"} + ] +""" + +from x | join y [==a] +``` diff --git a/book/src/language-features/standard-library/loop.md b/book/src/language-features/standard-library/loop.md new file mode 100644 index 000000000000..97f462a8b5cc --- /dev/null +++ b/book/src/language-features/standard-library/loop.md @@ -0,0 +1,50 @@ +# Loop + +> _experimental_ + +```prql_no_test +loop {step_function} {initial_relation} +``` + +Iteratively applies `step` function to `initial` relation until the `step` +returns an empty table. Returns a relation that contains rows of initial +relation and all intermediate relations. + +This behavior could be expressed with following pseudo-code: + +``` +def loop(step, initial): + result = [] + current = initial + while current is not empty: + result = append(result, current) + current = step(current) + + return result +``` + +## Examples + +```prql +from_text format:json '[{"n": 1 }]' +loop ( + filter n<4 + select n = n+1 +) + +# returns [1, 2, 3, 4] +``` + +```admonish +Behavior of WITH RECURSIVE may depend on database configuration (MySQL). +prql-compiler assumes behavior described by +[Postgres documentation](https://www.postgresql.org/docs/15/queries-with.html#QUERIES-WITH-RECURSIVE) +and will not produce correct results for +[alternative configurations of MySQL](https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive). +``` + +```admonish +Currently, `loop` may produce references to the recursive CTE in sub-queries, +which is not supported by some database engines (SQLite). For now, we suggest you keep step +functions simple enough to fit into a single SELECT statement. +``` diff --git a/book/src/syntax.md b/book/src/syntax.md index 3c0afc5dd5b7..b23537228f4c 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -166,7 +166,7 @@ sort (-distance) sort [-distance] ``` -## Inner Transforms +## Inner transforms Parentheses are also used for transforms (such as `group` and `window`) that pass their result to an "inner transform". The example below applies the diff --git a/book/src/transforms/from_text.md b/book/src/transforms/from_text.md index 0a9b51160ca7..a05d2a4b011d 100644 --- a/book/src/transforms/from_text.md +++ b/book/src/transforms/from_text.md @@ -1,62 +1 @@ # From Text - -It's often useful to make a small table inline, for example when exploring how a -database will evaluate an expression, or to have a small lookup table inline. -This can be quite verbose in SQL. - -PRQL uses `from_text` for this. - -It accepts a few formats: - -- `format:csv`; also the default, for CSV. -- `format:json` for either: - - A list of dicts, - - or a schema of `columns` & `data>`. - -```prql -from_text """ -a,b,c -1,2,3 -4,5,6 -""" -derive [ - d = b + c, - answer = 20 * 2 + 2, -] -``` - -An example of adding a small lookup table: - -```prql -let temp_format_lookup = from_text format:csv """ -country_code,format -uk,C -us,F -lr,F -de,C -""" - -from temperatures -join temp_format_lookup [==country_code] -``` - -And JSON: - -```prql -let x = from_text format:json """{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}""" - -let y = from_text format:json """ - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -""" - -from x | join y [==a] -``` diff --git a/book/tests/prql/language-features/standard-library-0.prql b/book/tests/prql/language-features/standard-library/README-0.prql similarity index 100% rename from book/tests/prql/language-features/standard-library-0.prql rename to book/tests/prql/language-features/standard-library/README-0.prql diff --git a/book/tests/prql/transforms/from_text-0.prql b/book/tests/prql/language-features/standard-library/from-text-0.prql similarity index 100% rename from book/tests/prql/transforms/from_text-0.prql rename to book/tests/prql/language-features/standard-library/from-text-0.prql diff --git a/book/tests/prql/transforms/from_text-1.prql b/book/tests/prql/language-features/standard-library/from-text-1.prql similarity index 100% rename from book/tests/prql/transforms/from_text-1.prql rename to book/tests/prql/language-features/standard-library/from-text-1.prql diff --git a/book/tests/prql/transforms/from_text-2.prql b/book/tests/prql/language-features/standard-library/from-text-2.prql similarity index 100% rename from book/tests/prql/transforms/from_text-2.prql rename to book/tests/prql/language-features/standard-library/from-text-2.prql diff --git a/book/tests/prql/language-features/standard-library/loop-0.prql b/book/tests/prql/language-features/standard-library/loop-0.prql new file mode 100644 index 000000000000..5dccfdba14ae --- /dev/null +++ b/book/tests/prql/language-features/standard-library/loop-0.prql @@ -0,0 +1,7 @@ +from_text format:json '[{"n": 1 }]' +loop ( + filter n<4 + select n = n+1 +) + +# returns [1, 2, 3, 4] diff --git a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap index 5e55e6c27d2b..36a99fd31e3f 100644 --- a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap @@ -1,18 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "table newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\ntable average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" +expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" input_file: book/tests/prql/examples/cte-0.prql --- -WITH average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country -), -newest_employees AS ( +WITH newest_employees AS ( SELECT * FROM @@ -21,6 +12,14 @@ newest_employees AS ( tenure LIMIT 50 +), average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country ) SELECT newest_employees.name, @@ -29,3 +28,4 @@ SELECT FROM newest_employees JOIN average_salaries ON newest_employees.country = average_salaries.country + diff --git a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap index 2ed2d4eba75e..47650f37675d 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" input_file: book/tests/prql/examples/employees-0.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT AVG(salary) AS _expr_0, emp_no @@ -12,23 +12,24 @@ WITH table_1 AS ( GROUP BY emp_no ), -table_2 AS ( +table_1 AS ( SELECT t.title, - AVG(table_1._expr_0) AS avg_salary, + AVG(table_2._expr_0) AS avg_salary, dept_emp.dept_no FROM - table_1 - JOIN titles AS t ON table_1.emp_no = t.emp_no - LEFT JOIN dept_emp ON table_1.emp_no = dept_emp.emp_no + table_3 AS table_2 + JOIN titles AS t ON table_2.emp_no = t.emp_no + LEFT JOIN dept_emp ON table_2.emp_no = dept_emp.emp_no GROUP BY dept_emp.dept_no, t.title ) SELECT departments.dept_name, - table_2.title, - table_2.avg_salary + table_0.title, + table_0.avg_salary FROM - table_2 - JOIN departments ON table_2.dept_no = departments.dept_no + table_1 AS table_0 + JOIN departments ON table_0.dept_no = departments.dept_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap index 434d377e6067..88f00f10486c 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-1.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,24 +15,25 @@ WITH table_1 AS ( e.emp_no, e.gender ), -table_2 AS ( +table_1 AS ( SELECT - table_1.gender, - AVG(table_1._expr_0) AS salary_avg, - STDDEV(table_1._expr_0) AS salary_sd, + table_2.gender, + AVG(table_2._expr_0) AS salary_avg, + STDDEV(table_2._expr_0) AS salary_sd, de.dept_no FROM - table_1 - LEFT JOIN dept_emp AS de ON table_1.emp_no = de.emp_no + table_3 AS table_2 + LEFT JOIN dept_emp AS de ON table_2.emp_no = de.emp_no GROUP BY de.dept_no, - table_1.gender + table_2.gender ) SELECT departments.dept_name, - table_2.gender, - table_2.salary_avg, - table_2.salary_sd + table_0.gender, + table_0.salary_avg, + table_0.salary_sd FROM - table_2 - JOIN departments ON table_2.dept_no = departments.dept_no + table_1 AS table_0 + JOIN departments ON table_0.dept_no = departments.dept_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap index 6918730104c0..612ece4db0c6 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" input_file: book/tests/prql/examples/employees-2.prql --- -WITH table_1 AS ( +WITH table_3 AS ( SELECT e.gender, AVG(salaries.salary) AS _expr_0, @@ -15,25 +15,26 @@ WITH table_1 AS ( e.emp_no, e.gender ), -table_2 AS ( +table_1 AS ( SELECT - AVG(table_1._expr_0) AS salary_avg, - STDDEV(table_1._expr_0) AS salary_sd, + AVG(table_2._expr_0) AS salary_avg, + STDDEV(table_2._expr_0) AS salary_sd, dm.emp_no FROM - table_1 - JOIN dept_emp AS de ON table_1.emp_no = de.emp_no + table_3 AS table_2 + JOIN dept_emp AS de ON table_2.emp_no = de.emp_no JOIN dept_manager AS dm ON dm.dept_no = de.dept_no AND (de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date) GROUP BY dm.emp_no, - table_1.gender + table_2.gender ) SELECT managers.first_name || ' ' || managers.last_name AS mng_name, managers.gender, - table_2.salary_avg, - table_2.salary_sd + table_0.salary_avg, + table_0.salary_sd FROM - table_2 - JOIN employees AS managers ON table_2.emp_no = managers.emp_no + table_1 AS table_0 + JOIN employees AS managers ON table_0.emp_no = managers.emp_no + diff --git a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap index fa439fbf23c0..68c457076ef7 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap @@ -17,11 +17,12 @@ WITH table_1 AS ( de.dept_no ) SELECT - table_1.dept_no, - table_1.salary, + table_0.dept_no, + table_0.salary, employees.gender, titles.title FROM - table_1 - JOIN employees ON table_1.emp_no = employees.emp_no - JOIN titles ON table_1.emp_no = titles.emp_no + table_1 AS table_0 + JOIN employees ON table_0.emp_no = employees.emp_no + JOIN titles ON table_0.emp_no = titles.emp_no + diff --git a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap index b12126c24dd3..676b3103af9c 100644 --- a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap @@ -1,15 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\ntable parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" +expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" input_file: book/tests/prql/examples/misc-0.prql --- -WITH parts AS ( - SELECT - * - FROM - seq_1_to_5 -), -table_1 AS ( +WITH table_1 AS ( SELECT related_id FROM @@ -33,8 +27,9 @@ SELECT -1 ) AS stub FROM - table_1 - JOIN accounts AS a ON a.id = table_1.related_id + table_1 AS table_0 + JOIN accounts AS a ON a.id = table_0.related_id JOIN email_addr_bean_rel AS er ON er.bean_id = a.id AND er.primary_address = '1' JOIN email_addresses AS ea ON ea.id = er.email_address_id + diff --git a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap index 9f7411a758ba..69e10cb2c16d 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap @@ -26,7 +26,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -38,3 +38,4 @@ ORDER BY sum_gross_cost LIMIT 20 + diff --git a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap index ea3da8460bb5..77b68ee0c7d1 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap @@ -13,12 +13,13 @@ WITH table_1 AS ( emp_no ) SELECT - AVG(table_1._expr_0) / 1000 AS salary_k, - AVG(table_1._expr_0) / 1000 * 1000 AS salary + AVG(table_0._expr_0) / 1000 AS salary_k, + AVG(table_0._expr_0) / 1000 * 1000 AS salary FROM - table_1 - JOIN titles ON table_1.emp_no = titles.emp_no + table_1 AS table_0 + JOIN titles ON table_0.emp_no = titles.emp_no GROUP BY titles.title LIMIT 10 + diff --git a/book/tests/snapshots/snapshot__@introduction-0.prql.snap b/book/tests/snapshots/snapshot__@introduction-0.prql.snap index 741163b2be4d..2cfecfb1a71d 100644 --- a/book/tests/snapshots/snapshot__@introduction-0.prql.snap +++ b/book/tests/snapshots/snapshot__@introduction-0.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" +expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" input_file: book/tests/prql/introduction-0.prql --- WITH table_1 AS ( @@ -22,7 +22,7 @@ SELECT CONCAT(title, '_', country) AS id, LEFT(country, 2) AS country_code FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -35,3 +35,4 @@ ORDER BY country DESC LIMIT 20 + diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap index 2d9d6d5178f5..693c04dcf449 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap @@ -17,6 +17,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 1 + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap index 3f5c880fd181..3d97e867fc17 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" input_file: book/tests/prql/language-features/s-strings-3.prql --- -WITH table_2 AS ( +WITH table_0 AS ( SELECT DISTINCT ON first_name, id, @@ -13,15 +13,16 @@ WITH table_2 AS ( ORDER BY age ASC ), -table_3 AS ( +table_1 AS ( SELECT * FROM salaries ) SELECT - table_0.*, - table_1.* + table_2.*, + table_3.* FROM - table_2 AS table_0 - JOIN table_3 AS table_1 ON table_0.id = table_1.id + table_0 AS table_2 + JOIN table_1 AS table_3 ON table_2.id = table_3.id + diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap index 31e030d55e0b..b3a371283e07 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" -input_file: book/tests/prql/language-features/standard-library-0.prql +input_file: book/tests/prql/language-features/standard-library/README-0.prql --- SELECT *, @@ -10,3 +10,4 @@ SELECT NOW() AS time FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap index 59de499b2072..904a45d549da 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" -input_file: book/tests/prql/transforms/from_text-0.prql +input_file: book/tests/prql/language-features/standard-library/from-text-0.prql --- -WITH table_1 AS ( +WITH table_0 AS ( SELECT '1' AS a, '2' AS b, @@ -22,5 +22,5 @@ SELECT b + c AS d, 42 AS answer FROM - table_1 AS table_0 + table_0 AS table_1 diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap index 9ae070f052eb..670e58dfc204 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-1.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" -input_file: book/tests/prql/transforms/from_text-1.prql +input_file: book/tests/prql/language-features/standard-library/from-text-1.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap similarity index 91% rename from book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap rename to book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap index 085bbccf68f8..becf706977bb 100644 --- a/book/tests/snapshots/snapshot__@transforms__from_text-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap @@ -1,7 +1,7 @@ --- source: book/tests/snapshot.rs expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" -input_file: book/tests/prql/transforms/from_text-2.prql +input_file: book/tests/prql/language-features/standard-library/from-text-2.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap new file mode 100644 index 000000000000..5515357a6c0c --- /dev/null +++ b/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap @@ -0,0 +1,34 @@ +--- +source: book/tests/snapshot.rs +expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" +input_file: book/tests/prql/language-features/standard-library/loop-0.prql +--- +WITH table_0 AS ( + SELECT + 1 AS n +), +table_4 AS ( + WITH RECURSIVE loop AS ( + SELECT + n + FROM + table_0 AS table_1 + UNION + ALL + SELECT + n + 1 + FROM + loop AS table_2 + WHERE + n < 4 + ) + SELECT + * + FROM + loop +) +SELECT + n +FROM + table_4 AS table_3 + diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap index 48c578cb780a..8a7e0fd99bc5 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap @@ -16,9 +16,10 @@ WITH table_1 AS ( 10 ) SELECT - table_1.name, - table_1.gross_salary, + table_0.name, + table_0.gross_salary, d.name FROM - table_1 - JOIN department AS d ON table_1.dept_no = d.dept_no + table_1 AS table_0 + JOIN department AS d ON table_0.dept_no = d.dept_no + diff --git a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap index e37a88722453..ca97469b4749 100644 --- a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap @@ -3,7 +3,7 @@ source: book/tests/snapshot.rs expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" input_file: book/tests/prql/queries/variables-0.prql --- -WITH table_0 AS ( +WITH table_1 AS ( SELECT salary FROM @@ -16,7 +16,7 @@ WITH table_0 AS ( SELECT SUM(salary) AS total_salary FROM - table_0 + table_1 AS table_0 ) SELECT total_salary diff --git a/book/tests/snapshots/snapshot__@syntax-5.prql.snap b/book/tests/snapshots/snapshot__@syntax-5.prql.snap index 374cbd663cf3..9095768d6603 100644 --- a/book/tests/snapshots/snapshot__@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-5.prql.snap @@ -14,7 +14,8 @@ SELECT circumference, color FROM - table_1 + table_1 AS table_0 WHERE circumference > 10 AND color <> 'red' + diff --git a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap index a11503ab56c8..03289443cc04 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap @@ -17,6 +17,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 1 + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap index 7b6e784e1da0..fb7acd653ec6 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap @@ -3,16 +3,11 @@ source: book/tests/snapshot.rs expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" input_file: book/tests/prql/transforms/sort-3.prql --- -WITH table_1 AS ( - SELECT - *, - substr(first_name, 2, 5) AS _expr_0 - FROM - employees - ORDER BY - _expr_0 -) SELECT - * + *, + substr(first_name, 2, 5) AS _expr_0 FROM - table_1 + employees +ORDER BY + _expr_0 + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap index de8d52ca5f42..b969c19b2a4d 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap @@ -12,8 +12,9 @@ WITH table_1 AS ( tenure ) SELECT - table_1.*, + table_0.*, locations.* FROM - table_1 - JOIN locations ON table_1.employee_id = locations.employee_id + table_1 AS table_0 + JOIN locations ON table_0.employee_id = locations.employee_id + diff --git a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap index 13bb14a01bc7..0dcf1866c987 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap @@ -13,6 +13,7 @@ WITH table_1 AS ( SELECT * FROM - table_1 + table_1 AS table_0 WHERE salary < _expr_0 + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from_text-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from_text-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from_text-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap new file mode 100644 index 000000000000..0c143248892b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap @@ -0,0 +1,12 @@ +--- +source: book/tests/snapshot.rs +expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" +--- +from_text format:json '[{"n": 1 }]' +loop ( + filter n < 4 + select n = n + 1 +) + + + diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index 630d4725f32f..e6792d7d8f10 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -310,6 +310,7 @@ pub enum TransformKind { pipeline: Box, }, Append(Box), + Loop(Box), } #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index 3af403b8525d..b82f9178a296 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -273,6 +273,7 @@ pub fn fold_transform_kind( range: fold_range(fold, range)?, pipeline: Box::new(fold.fold_expr(*pipeline)?), }, + Loop(pipeline) => Loop(Box::new(fold.fold_expr(*pipeline)?)), }) } diff --git a/prql-compiler/src/ast/pl/types.rs b/prql-compiler/src/ast/pl/types.rs index 3d4c428d5d75..cb1463940c7b 100644 --- a/prql-compiler/src/ast/pl/types.rs +++ b/prql-compiler/src/ast/pl/types.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use super::Frame; -#[derive(Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] pub enum Ty { Empty, Literal(TyLit), @@ -162,9 +162,3 @@ impl Display for Ty { } } } - -impl Debug for Ty { - fn fmt(&self, f: &mut Formatter<'_>) -> Result { - Display::fmt(self, f) - } -} diff --git a/prql-compiler/src/ast/rq/fold.rs b/prql-compiler/src/ast/rq/fold.rs index d84d6385ba37..1c799e35dfe0 100644 --- a/prql-compiler/src/ast/rq/fold.rs +++ b/prql-compiler/src/ast/rq/fold.rs @@ -187,6 +187,7 @@ pub fn fold_transform( filter: fold.fold_expr(filter)?, }, Append(bottom) => Append(fold.fold_table_ref(bottom)?), + Loop(transforms) => Loop(fold_transforms(fold, transforms)?), }; Ok(transform) } diff --git a/prql-compiler/src/ast/rq/transform.rs b/prql-compiler/src/ast/rq/transform.rs index 7a946e1d2c13..875bc3d922b6 100644 --- a/prql-compiler/src/ast/rq/transform.rs +++ b/prql-compiler/src/ast/rq/transform.rs @@ -25,6 +25,7 @@ pub enum Transform { filter: Expr, }, Append(TableRef), + Loop(Vec), } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index bb595dd20da0..25383b9dd744 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -269,7 +269,7 @@ impl Lowerer { let ty = expr.ty.clone(); let prev_pipeline = self.pipeline.drain(..).collect_vec(); - self.lower_pipeline(expr)?; + self.lower_pipeline(expr, None)?; let mut transforms = self.pipeline.drain(..).collect_vec(); let columns = self.push_select(ty, &mut transforms)?; @@ -284,10 +284,22 @@ impl Lowerer { } // Result is stored in self.pipeline - fn lower_pipeline(&mut self, ast: pl::Expr) -> Result<()> { + fn lower_pipeline(&mut self, ast: pl::Expr, closure_param: Option) -> Result<()> { let transform_call = match ast.kind { pl::ExprKind::TransformCall(transform) => transform, + pl::ExprKind::Closure(closure) => { + let param = closure.params.first(); + let param = param.and_then(|p| p.name.parse::().ok()); + return self.lower_pipeline(*closure.body, param); + } _ => { + if let Some(target) = ast.target_id { + if Some(target) == closure_param { + // ast is a closure param, so we can skip pushing From + return Ok(()); + } + } + let table_ref = self.lower_table_ref(ast)?; self.pipeline.push(Transform::From(table_ref)); return Ok(()); @@ -295,7 +307,7 @@ impl Lowerer { }; // lower input table - self.lower_pipeline(*transform_call.input)?; + self.lower_pipeline(*transform_call.input, closure_param)?; // ... and continues with transforms created in this function @@ -362,8 +374,16 @@ impl Lowerer { pl::TransformKind::Append(bottom) => { let bottom = self.lower_table_ref(*bottom)?; - let transform = Transform::Append(bottom); - self.pipeline.push(transform); + self.pipeline.push(Transform::Append(bottom)); + } + pl::TransformKind::Loop(pipeline) => { + let relation = self.lower_relation(*pipeline)?; + let mut pipeline = relation.kind.into_pipeline().unwrap(); + + // last select is not needed here + pipeline.pop(); + + self.pipeline.push(Transform::Loop(pipeline)); } pl::TransformKind::Group { .. } | pl::TransformKind::Window { .. } => unreachable!( "transform `{}` cannot be lowered.", @@ -680,9 +700,10 @@ impl Lowerer { let name = match name { Some(v) => RelationColumn::Single(Some(v.clone())), None => return Err(Error::new_simple( - "This table contains unnamed columns, that need to be referenced by name", + "This table contains unnamed columns that need to be referenced by name", ) .with_span(self.context.span_map.get(&id).cloned()) + .with_help("The name may have been overridden later in the pipeline.") .into()), }; log::trace!("lookup cid of name={name:?} in input {input_columns:?}"); diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index f906e2dc7b23..586a9dcaf94f 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -48,6 +48,7 @@ func remove
`default_db.bottom`
top
-> ( filter (all (map _is_null b.*)) select t.* ) +func loop
pipeline top
-> null # List functions func all list -> null diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs index b517b2a81c33..15c73cbbe44f 100644 --- a/prql-compiler/src/semantic/transforms.rs +++ b/prql-compiler/src/semantic/transforms.rs @@ -192,6 +192,13 @@ pub fn cast_transform(resolver: &mut Resolver, closure: Closure) -> Result { + let [pipeline, tbl] = unpack::<2>(closure); + + let pipeline = fold_by_simulating_eval(resolver, pipeline, tbl.ty.clone().unwrap())?; + + (TransformKind::Loop(Box::new(pipeline)), tbl) + } "std.in" => { // yes, this is not a transform, but this is the most appropriate place for it @@ -582,6 +589,7 @@ impl TransformCall { let bottom = ty_frame_or_default(bottom)?; append(top, bottom)? } + Loop(_) => ty_frame_or_default(&self.input)?, Sort { .. } | Filter { .. } | Take { .. } => ty_frame_or_default(&self.input)?, }) } diff --git a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap index bbc44298cbb5..23a1cc2ad749 100644 --- a/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap +++ b/prql-compiler/src/snapshots/prql_compiler__test__prql_to_sql_2.snap @@ -25,7 +25,7 @@ SELECT SUM(_expr_0) AS sum_gross_cost, COUNT(*) AS ct FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 0 GROUP BY @@ -37,3 +37,4 @@ ORDER BY sum_gross_cost LIMIT 20 + diff --git a/prql-compiler/src/sql/anchor.rs b/prql-compiler/src/sql/anchor.rs index 6740cd2cc391..4c0e0ece9b76 100644 --- a/prql-compiler/src/sql/anchor.rs +++ b/prql-compiler/src/sql/anchor.rs @@ -3,28 +3,28 @@ use itertools::Itertools; use std::collections::{HashMap, HashSet}; use crate::ast::rq::{ - self, fold_transform, CId, Compute, Expr, Relation, RelationColumn, RelationKind, RqFold, - TableDecl, TableRef, Transform, + self, fold_transform, CId, Compute, Expr, RelationColumn, RqFold, TableRef, Transform, }; +use crate::sql::context::SqlTableDecl; +use crate::sql::preprocess::{SqlRelation, SqlRelationKind}; use super::{ context::{AnchorContext, ColumnDecl}, preprocess::{SqlFold, SqlTransform}, }; -type RemainingPipeline = (Vec, Vec); - /// Splits pipeline into two parts, such that the second part contains /// maximum number of transforms while "fitting" into a SELECT query. pub(super) fn split_off_back( - ctx: &mut AnchorContext, - output: Vec, mut pipeline: Vec, -) -> (Option, Vec) { + ctx: &mut AnchorContext, +) -> (Option>, Vec) { if pipeline.is_empty() { return (None, Vec::new()); } + let output = AnchorContext::determine_select_columns(&pipeline); + log::debug!("traversing pipeline to obtain columns: {output:?}"); let mut following_transforms: HashSet = HashSet::new(); @@ -137,8 +137,9 @@ pub(super) fn split_off_back( None } else { // drop inputs that were satisfied in current pipeline + pipeline.push(SqlTransform::Super(Transform::Select(missing))); - Some((pipeline, missing)) + Some(pipeline) }; curr_pipeline_rev.reverse(); @@ -166,20 +167,23 @@ fn can_materialize(compute: &Compute, inputs_required: &[Requirement]) -> bool { } /// Applies adjustments to second part of a pipeline when it's split: -/// - prepend pipeline with From -/// - redefine columns materialized in preceding pipeline +/// - append Select to proceeding pipeline +/// - prepend From to atomic pipeline +/// - redefine columns materialized in atomic pipeline /// - redirect all references to original columns to the new ones pub(super) fn anchor_split( ctx: &mut AnchorContext, - first_table_name: &str, - cols_at_split: &[CId], - second_pipeline: Vec, + preceding: Vec, + atomic: Vec, ) -> Vec { let new_tid = ctx.tid.gen(); + let preceding_select = &preceding.last().unwrap().as_super().unwrap(); + let cols_at_split = preceding_select.as_select().unwrap(); + log::debug!("split pipeline, first pipeline output: {cols_at_split:?}"); - // define columns of the new CTE + // redefine columns of the atomic pipeline let mut cid_redirects = HashMap::::new(); let mut new_columns = Vec::new(); for old_cid in cols_at_split { @@ -204,32 +208,31 @@ pub(super) fn anchor_split( // define a new table ctx.table_decls.insert( new_tid, - TableDecl { + SqlTableDecl { id: new_tid, - name: Some(first_table_name.to_string()), - // here we should put the pipeline, but because how this function is called, - // we need to return the pipeline directly, so we just insert dummy expr instead - relation: Relation { - kind: RelationKind::SString(vec![]), - columns: vec![], - }, + name: None, + relation: Some(SqlRelation { + columns: cols_at_split + .iter() + .map(|_| RelationColumn::Single(None)) + .collect_vec(), + kind: SqlRelationKind::PreprocessedPipeline(preceding), + }), }, ); // define instance of that table - let table_ref = TableRef { + let table_ref = ctx.create_table_instance(TableRef { source: new_tid, - name: Some(first_table_name.to_string()), + name: None, columns: new_columns, - }; - ctx.create_table_instance(table_ref.clone()); + }); // adjust second part: prepend from and rewrite expressions to use new columns - let mut second = second_pipeline; + let mut second = atomic; second.insert(0, SqlTransform::Super(Transform::From(table_ref))); - let mut redirector = CidRedirector { ctx, cid_redirects }; - redirector.fold_sql_transforms(second).unwrap() + CidRedirector::redirect(second, cid_redirects, ctx) } /// Determines whether a pipeline must be split at a transform to @@ -248,6 +251,7 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) // - take (no limit) // - distinct // - append/except/intersect (no limit) + // - loop (max 1x) // // Select is not affected by the order. use SqlTransform::*; @@ -306,6 +310,7 @@ fn is_split_required(transform: &SqlTransform, following: &mut HashSet) "Distinct", ], ), + SqlTransform::Loop(_) => !following.is_empty(), _ => false, }; @@ -387,12 +392,13 @@ pub(super) fn get_requirements( cids } - Super(Append(_)) => unreachable!(), - Super(Select(_) | From(_) | Aggregate { .. }) + Super(Aggregate { .. } | Append(_) | Transform::Loop(_)) => unreachable!(), + Super(Select(_) | From(_)) | Distinct | Union { .. } | Except { .. } - | Intersect { .. } => return Vec::new(), + | Intersect { .. } + | SqlTransform::Loop(_) => return Vec::new(), }; // general case: determine complexity @@ -502,9 +508,20 @@ impl RqFold for CidCollector { } } -struct CidRedirector<'a> { - ctx: &'a mut AnchorContext, - cid_redirects: HashMap, +pub(super) struct CidRedirector<'a> { + pub ctx: &'a mut AnchorContext, + pub cid_redirects: HashMap, +} + +impl<'a> CidRedirector<'a> { + pub fn redirect( + pipeline: Vec, + cid_redirects: HashMap, + ctx: &mut AnchorContext, + ) -> Vec { + let mut redirector = CidRedirector { ctx, cid_redirects }; + redirector.fold_sql_transforms(pipeline).unwrap() + } } impl<'a> RqFold for CidRedirector<'a> { diff --git a/prql-compiler/src/sql/context.rs b/prql-compiler/src/sql/context.rs index 4fa41ea51e71..b9b38e1ae2bf 100644 --- a/prql-compiler/src/sql/context.rs +++ b/prql-compiler/src/sql/context.rs @@ -10,19 +10,19 @@ use itertools::Itertools; use crate::ast::pl::TableExternRef; use crate::ast::rq::{ - fold_table, CId, Compute, Query, RelationColumn, RelationKind, RqFold, TId, TableDecl, - TableRef, Transform, + fold_table, CId, Compute, Query, Relation, RelationColumn, RelationKind, RqFold, TId, + TableDecl, TableRef, Transform, }; use crate::utils::{IdGenerator, NameGenerator}; -use super::preprocess::SqlTransform; +use super::preprocess::{SqlRelation, SqlTransform}; #[derive(Default)] pub struct AnchorContext { pub(super) column_decls: HashMap, pub(super) column_names: HashMap, - pub(super) table_decls: HashMap, + pub(super) table_decls: HashMap, pub(super) table_instances: HashMap, @@ -33,6 +33,20 @@ pub struct AnchorContext { pub(super) tid: IdGenerator, pub(super) tiid: IdGenerator, } + +#[derive(Debug, Clone)] +pub(super) struct SqlTableDecl { + #[allow(dead_code)] + pub id: TId, + + pub name: Option, + + /// Relation that still needs to be defined (usually as CTE) so it can be referenced by name. + /// None means that it has already been defined, or was not needed to be defined in the + /// first place. + pub relation: Option, +} + /// Table instance id #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TIId(usize); @@ -51,7 +65,7 @@ pub enum ColumnDecl { } impl AnchorContext { - pub fn of(query: Query) -> (Self, Query) { + pub fn of(query: Query) -> (Self, Relation) { let (cid, tid, query) = IdGenerator::load(query); let context = AnchorContext { @@ -78,7 +92,7 @@ impl AnchorContext { self.column_decls.insert(id, decl); } - pub fn create_table_instance(&mut self, mut table_ref: TableRef) { + pub fn create_table_instance(&mut self, mut table_ref: TableRef) -> TableRef { let tiid = self.tiid.gen(); for (col, cid) in &table_ref.columns { @@ -90,7 +104,8 @@ impl AnchorContext { table_ref.name = Some(self.table_name.gen()) } - self.table_instances.insert(tiid, table_ref); + self.table_instances.insert(tiid, table_ref.clone()); + table_ref } pub(crate) fn ensure_column_name(&mut self, cid: CId) -> Option<&String> { @@ -193,29 +208,45 @@ struct QueryLoader { } impl QueryLoader { - fn load(context: AnchorContext, query: Query) -> (AnchorContext, Query) { + fn load(context: AnchorContext, query: Query) -> (AnchorContext, Relation) { let mut loader = QueryLoader { context }; - let query = loader.fold_query(query).unwrap(); - (loader.context, query) + + for t in query.tables { + loader.load_table(t).unwrap(); + } + let relation = loader.fold_relation(query.relation).unwrap(); + (loader.context, relation) } -} -impl RqFold for QueryLoader { - fn fold_table(&mut self, table: TableDecl) -> Result { + fn load_table(&mut self, table: TableDecl) -> Result<()> { let mut decl = fold_table(self, table)?; + // assume name of the LocalTable that the relation is referencing if let RelationKind::ExternRef(TableExternRef::LocalTable(table)) = &decl.relation.kind { decl.name = Some(table.clone()); } + // generate name (if not present) if decl.name.is_none() && decl.relation.kind.as_extern_ref().is_none() { decl.name = Some(self.context.table_name.gen()); } - self.context.table_decls.insert(decl.id, decl.clone()); - Ok(decl) + let sql_decl = SqlTableDecl { + id: decl.id, + name: decl.name, + relation: if matches!(decl.relation.kind, RelationKind::ExternRef(_)) { + None + } else { + Some(decl.relation.into()) + }, + }; + + self.context.table_decls.insert(decl.id, sql_decl); + Ok(()) } +} +impl RqFold for QueryLoader { fn fold_compute(&mut self, compute: Compute) -> Result { self.context.register_compute(compute.clone()); Ok(compute) diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 51d00a1cdd8a..271b4a6a1833 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -6,8 +6,7 @@ use lazy_static::lazy_static; use regex::Regex; use sqlparser::ast::{ self as sql_ast, BinaryOperator, DateTimeField, Function, FunctionArg, FunctionArgExpr, Ident, - Join, JoinConstraint, JoinOperator, ObjectName, OrderByExpr, SelectItem, TableAlias, - TableFactor, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, + ObjectName, OrderByExpr, SelectItem, Top, UnaryOperator, Value, WindowFrameBound, WindowSpec, }; use sqlparser::keywords::{ Keyword, ALL_KEYWORDS, ALL_KEYWORDS_INDEX, RESERVED_FOR_COLUMN_ALIAS, RESERVED_FOR_TABLE_ALIAS, @@ -15,8 +14,7 @@ use sqlparser::keywords::{ use std::collections::HashSet; use crate::ast::pl::{ - BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, SortDirection, TableExternRef, - WindowFrame, WindowKind, + BinOp, ColumnSort, InterpolateItem, Literal, Range, SortDirection, WindowFrame, WindowKind, }; use crate::ast::rq::*; use crate::error::{Error, Span}; @@ -187,7 +185,7 @@ pub(super) fn translate_literal(l: Literal, ctx: &Context) -> Result Result { - if ctx.pre_projection { + if ctx.query.pre_projection { log::debug!("translating {cid:?} pre projection"); let decl = ctx.anchor.column_decls.get(&cid).expect("bad RQ ids"); @@ -231,7 +229,7 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result { let name = ctx.anchor.column_names.get(&cid).cloned(); - name.expect("a name of this column to be set before generating SQL") + name.expect("name of this column has not been to be set before generating SQL") } }; @@ -244,38 +242,6 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result TableFactor { - let decl = ctx.anchor.table_decls.get(&table_ref.source).unwrap(); - - let name = match &decl.relation.kind { - // special case for anchor - RelationKind::ExternRef(TableExternRef::Anchor(anchor_id)) => { - sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]) - } - - // base case - _ => { - let decl_name = decl.name.clone().unwrap(); - - sql_ast::ObjectName(translate_ident(Some(decl_name), None, ctx)) - } - }; - - TableFactor::Table { - name, - alias: if decl.name == table_ref.name { - None - } else { - table_ref.name.map(|ident| TableAlias { - name: translate_ident_part(ident, ctx), - columns: vec![], - }) - }, - args: None, - with_hints: vec![], - } -} - pub(super) fn translate_sstring( items: Vec>, ctx: &mut Context, @@ -623,23 +589,6 @@ pub(super) fn translate_column_sort( }) } -pub(super) fn translate_join( - (side, with, filter): (JoinSide, TableRef, Expr), - ctx: &mut Context, -) -> Result { - let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); - - Ok(Join { - relation: table_factor_of_tid(with, ctx), - join_operator: match side { - JoinSide::Inner => JoinOperator::Inner(constraint), - JoinSide::Left => JoinOperator::LeftOuter(constraint), - JoinSide::Right => JoinOperator::RightOuter(constraint), - JoinSide::Full => JoinOperator::FullOuter(constraint), - }, - }) -} - /// Translate a PRQL Ident to a Vec of SQL Idents. // We return a vec of SQL Idents because sqlparser sometimes uses // [ObjectName](sql_ast::ObjectName) and sometimes uses @@ -651,7 +600,7 @@ pub(super) fn translate_ident( ctx: &Context, ) -> Vec { let mut parts = Vec::with_capacity(4); - if !ctx.omit_ident_prefix || column.is_none() { + if !ctx.query.omit_ident_prefix || column.is_none() { if let Some(table) = table_name { #[allow(clippy::if_same_then_else)] if ctx.dialect.big_query_quoting() { @@ -954,22 +903,12 @@ mod test { { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_with_concat_function = Context { - dialect: Box::new(GenericDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + context_with_concat_function = Context::new(Box::new(GenericDialect {}), anchor); } { let query = resolve(parse("from foo")?)?; let (anchor, _) = AnchorContext::of(query); - context_without_concat_function = Context { - dialect: Box::new(SQLiteDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + context_without_concat_function = Context::new(Box::new(SQLiteDialect {}), anchor); } fn str_lit(s: &str) -> InterpolateItem { diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index a109eb8b0aa1..fba04d0be692 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -6,21 +6,23 @@ use std::collections::HashSet; use std::str::FromStr; use anyhow::{anyhow, Result}; -use enum_as_inner::EnumAsInner; use itertools::Itertools; use sqlparser::ast::{ - self as sql_ast, Ident, Select, SelectItem, SetExpr, TableAlias, TableFactor, TableWithJoins, + self as sql_ast, Ident, Join, JoinConstraint, JoinOperator, Select, SelectItem, SetExpr, + TableAlias, TableFactor, TableWithJoins, }; -use crate::ast::pl::{BinOp, Literal, RelationLiteral}; -use crate::ast::rq::{CId, Expr, ExprKind, Query, Relation, RelationKind, TableDecl, Transform}; +use crate::ast::pl::{BinOp, JoinSide, Literal, RelationLiteral}; +use crate::ast::rq::{CId, Expr, ExprKind, Query, RelationKind, TableRef, Transform}; +use crate::sql::anchor::anchor_split; +use crate::sql::preprocess::SqlRelationKind; use crate::utils::{BreakUp, IntoOnly, Pluck}; use crate::Target; use super::context::AnchorContext; use super::gen_expr::*; use super::gen_projection::*; -use super::preprocess::{self, SqlTransform}; +use super::preprocess::{self, SqlRelation, SqlTransform}; use super::{anchor, Context, Dialect}; pub fn translate_query(query: Query, dialect: Option) -> Result { @@ -36,77 +38,17 @@ pub fn translate_query(query: Query, dialect: Option) -> Result { - // preprocess - let pipeline = Ok(pipeline) - .map(preprocess::normalize) - .map(preprocess::push_down_selects) - .map(preprocess::prune_inputs) - .map(preprocess::wrap) - .and_then(|p| preprocess::distinct(p, &mut context)) - .map(preprocess::union) - .and_then(|p| preprocess::except(p, &context)) - .and_then(|p| preprocess::intersect(p, &context)) - .map(preprocess::reorder)?; - - // load names of output columns - context.anchor.load_names(&pipeline, table.relation.columns); - - // split to atomics - let ats = split_into_atomics(name, pipeline, &mut context.anchor); - - // ensure names for all columns that need it - ensure_names(&ats, &mut context.anchor); - - atomics.extend(ats); - } - RelationKind::Literal(_) | RelationKind::SString(_) => atomics.push(AtomicQuery { - name, - relation: SqlRelation::Super(table.relation.kind), - }), - RelationKind::ExternRef(_) => { - // ref does not need it's own CTE - } - } - } - - // take last table - let main_query = atomics.remove(atomics.len() - 1); - let ctes = atomics; - - // convert each of the CTEs - let ctes: Vec<_> = ctes - .into_iter() - .map(|t| table_to_sql_cte(t, &mut context)) - .try_collect()?; + let mut ctx = Context::new(dialect, anchor); - // convert main query - let mut main_query = sql_query_of_relation(main_query.relation, &mut context)?; + // compile main relation that will recursively compile CTEs + let mut main_query = sql_query_of_sql_relation(main_relation.into(), &mut ctx)?; // attach CTEs - if !ctes.is_empty() { + if !ctx.ctes.is_empty() { main_query.with = Some(sql_ast::With { - cte_tables: ctes, + cte_tables: ctx.ctes.drain(..).collect_vec(), recursive: false, }); } @@ -114,99 +56,188 @@ pub fn translate_query(query: Query, dialect: Option) -> Result Result { + use RelationKind::*; -#[derive(Debug, EnumAsInner)] -enum SqlRelation { - Super(RelationKind), - Pipeline(Vec), -} + // preprocess & split into atomics + match sql_relation.kind { + // base case + SqlRelationKind::Super(Pipeline(pipeline)) => { + // preprocess + let pipeline = Ok(pipeline) + .map(preprocess::normalize) + .map(preprocess::prune_inputs) + .map(preprocess::wrap) + .and_then(|p| preprocess::distinct(p, ctx)) + .map(preprocess::union) + .and_then(|p| preprocess::except(p, ctx)) + .and_then(|p| preprocess::intersect(p, ctx)) + .map(preprocess::reorder)?; + + // load names of output columns + ctx.anchor.load_names(&pipeline, sql_relation.columns); + + sql_query_of_pipeline(pipeline, ctx) + } -fn into_tables( - main_pipeline: Relation, - tables: Vec, - context: &mut Context, -) -> Result> { - let main = TableDecl { - id: context.anchor.tid.gen(), - name: None, - relation: main_pipeline, - }; - Ok([tables, vec![main]].concat()) + // no need to preprocess, has been done already + SqlRelationKind::PreprocessedPipeline(pipeline) => sql_query_of_pipeline(pipeline, ctx), + + // special case: literals + SqlRelationKind::Super(Literal(lit)) => sql_of_sample_data(lit, ctx), + + // special case: s-strings + SqlRelationKind::Super(SString(items)) => translate_query_sstring(items, ctx), + + // ref cannot be converted directly into query and does not need it's own CTE + SqlRelationKind::Super(ExternRef(_)) => unreachable!(), + } } -fn table_to_sql_cte(table: AtomicQuery, context: &mut Context) -> Result { - let alias = sql_ast::TableAlias { - name: translate_ident_part(table.name, context), - columns: vec![], +fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result { + let table_ref_alias = (table_ref.name.clone()) + .map(|ident| translate_ident_part(ident, ctx)) + .map(simple_table_alias); + + let decl = ctx.anchor.table_decls.get_mut(&table_ref.source).unwrap(); + + // prepare names + let table_name = match &decl.name { + None => { + decl.name = Some(ctx.anchor.table_name.gen()); + decl.name.clone().unwrap() + } + Some(n) => n.clone(), }; - Ok(sql_ast::Cte { - alias, - query: Box::new(sql_query_of_relation(table.relation, context)?), - from: None, - }) -} -fn sql_query_of_relation(relation: SqlRelation, context: &mut Context) -> Result { - use RelationKind::*; + // ensure that the table is declared + if let Some(sql_relation) = decl.relation.take() { + // if we cannot use CTEs + if ctx.query.forbid_ctes { + // restore relation for other references + decl.relation = Some(sql_relation.clone()); + + // return a sub-query + let query = sql_query_of_sql_relation(sql_relation, ctx)?; + return Ok(TableFactor::Derived { + lateral: false, + subquery: Box::new(query), + alias: table_ref_alias, + }); + } + + let query = sql_query_of_sql_relation(sql_relation, ctx)?; + let alias = sql_ast::TableAlias { + name: translate_ident_part(table_name.clone(), ctx), + columns: vec![], + }; - match relation { - SqlRelation::Super(ExternRef(_)) | SqlRelation::Super(Pipeline(_)) => unreachable!(), - SqlRelation::Pipeline(pipeline) => sql_query_of_pipeline(pipeline, context), - SqlRelation::Super(Literal(lit)) => Ok(sql_of_sample_data(lit, context)?), - SqlRelation::Super(SString(items)) => translate_query_sstring(items, context), + ctx.ctes.push(sql_ast::Cte { + alias, + query: Box::new(query), + from: None, + }) } + + // let name = match &decl.relation { + // // special case for anchor + // // TODO + // // Some(SqlRelationKind::Super(RelationKind::ExternRef(TableExternRef::Anchor( + // // anchor_id, + // // )))) => sql_ast::ObjectName(vec![Ident::new(anchor_id.clone())]), + + // // base case + // _ => { + + // } + // }; + + let name = sql_ast::ObjectName(translate_ident(Some(table_name.clone()), None, ctx)); + + Ok(TableFactor::Table { + name, + alias: if Some(table_name) == table_ref.name { + None + } else { + table_ref_alias + }, + args: None, + with_hints: vec![], + }) +} + +fn translate_join( + (side, with, filter): (JoinSide, TableRef, Expr), + ctx: &mut Context, +) -> Result { + let relation = table_factor_of_table_ref(with, ctx)?; + + let constraint = JoinConstraint::On(translate_expr_kind(filter.kind, ctx)?); + + Ok(Join { + relation, + join_operator: match side { + JoinSide::Inner => JoinOperator::Inner(constraint), + JoinSide::Left => JoinOperator::LeftOuter(constraint), + JoinSide::Right => JoinOperator::RightOuter(constraint), + JoinSide::Full => JoinOperator::FullOuter(constraint), + }, + }) } fn sql_query_of_pipeline( - pipeline: Vec, - context: &mut Context, + mut pipeline: Vec, + ctx: &mut Context, ) -> Result { use SqlTransform::*; + // special case: loop + if pipeline.iter().any(|t| matches!(t, Loop(_))) { + pipeline = sql_of_loop(pipeline, ctx)?; + } + + // extract an atomic pipeline from back of the pipeline and stash preceding part into context + let pipeline = extract_atomic(pipeline, &mut ctx.anchor); + + // ensure names for all columns that need it + ensure_names(&pipeline, &mut ctx.anchor); + let (select, set_ops) = pipeline.break_up(|t| matches!(t, Union { .. } | Except { .. } | Intersect { .. })); - let select = sql_select_query_of_pipeline(select, context)?; + let select = sql_select_query_of_pipeline(select, ctx)?; - sql_set_ops_of_pipeline(select, set_ops, context) + sql_set_ops_of_pipeline(select, set_ops, ctx) } fn sql_select_query_of_pipeline( mut pipeline: Vec, - context: &mut Context, + ctx: &mut Context, ) -> Result { let table_count = count_tables(&pipeline); log::debug!("atomic query contains {table_count} tables"); - context.omit_ident_prefix = table_count == 1; - - context.pre_projection = true; - - let projection = pipeline - .pluck(|t| t.into_super_and(|t| t.into_select())) - .into_only() - .unwrap(); - let projection = translate_wildcards(&context.anchor, projection); - let projection = translate_select_items(projection.0, projection.1, context)?; + ctx.push_query(); + ctx.query.omit_ident_prefix = table_count == 1; + ctx.query.pre_projection = true; - let mut from = pipeline + let mut from: Vec<_> = pipeline .pluck(|t| t.into_super_and(|t| t.into_from())) .into_iter() - .map(|source| TableWithJoins { - relation: table_factor_of_tid(source, context), - joins: vec![], + .map(|source| -> Result { + Ok(TableWithJoins { + relation: table_factor_of_table_ref(source, ctx)?, + joins: vec![], + }) }) - .collect::>(); + .try_collect()?; let joins = pipeline .pluck(|t| t.into_super_and(|t| t.into_join())) .into_iter() - .map(|j| translate_join(j, context)) + .map(|j| translate_join(j, ctx)) .collect::>>()?; if !joins.is_empty() { if let Some(from) = from.last_mut() { @@ -216,6 +247,13 @@ fn sql_select_query_of_pipeline( } } + let projection = pipeline + .pluck(|t| t.into_super_and(|t| t.into_select())) + .into_only() + .unwrap(); + let projection = translate_wildcards(&ctx.anchor, projection); + let projection = translate_select_items(projection.0, projection.1, ctx)?; + let sorts = pipeline.pluck(|t| t.into_super_and(|t| t.into_sort())); let takes = pipeline.pluck(|t| t.into_super_and(|t| t.into_take())); let distinct = pipeline.iter().any(|t| matches!(t, SqlTransform::Distinct)); @@ -231,11 +269,11 @@ fn sql_select_query_of_pipeline( // WHERE and HAVING let where_ = filter_of_conditions( before_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - context, + ctx, )?; let having = filter_of_conditions( after_agg.pluck(|t| t.into_super_and(|t| t.into_filter())), - context, + ctx, )?; // GROUP BY @@ -244,9 +282,9 @@ fn sql_select_query_of_pipeline( .into_iter() .next(); let group_by: Vec = aggregate.map(|(part, _)| part).unwrap_or_default(); - let group_by = try_into_exprs(group_by, context, None)?; + let group_by = try_into_exprs(group_by, ctx, None)?; - context.pre_projection = false; + ctx.query.pre_projection = false; let ranges = takes.into_iter().map(|x| x.range).collect(); let take = range_of_ranges(ranges)?; @@ -257,7 +295,7 @@ fn sql_select_query_of_pipeline( None } else { Some(sqlparser::ast::Offset { - value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), context)?, + value: translate_expr_kind(ExprKind::Literal(Literal::Integer(offset)), ctx)?, rows: sqlparser::ast::OffsetRows::None, }) }; @@ -268,17 +306,20 @@ fn sql_select_query_of_pipeline( .map(|sorts| { sorts .iter() - .map(|s| translate_column_sort(s, context)) + .map(|s| translate_column_sort(s, ctx)) .try_collect() }) .transpose()? .unwrap_or_default(); - let (top, limit) = if context.dialect.use_top() { - (limit.map(|l| top_of_i64(l, context)), None) + let (top, limit) = if ctx.dialect.use_top() { + (limit.map(|l| top_of_i64(l, ctx)), None) } else { (None, limit.map(expr_of_i64)) }; + + ctx.pop_query(); + Ok(sql_ast::Query { order_by, limit, @@ -322,36 +363,7 @@ fn sql_set_ops_of_pipeline( }; // prepare top - let top_is_simple = top.with.is_none() - && top.order_by.is_empty() - && top.limit.is_none() - && top.offset.is_none() - && top.fetch.is_none() - && top.locks.is_empty(); - - let left = if top_is_simple { - top.body - } else { - // top is not simple, so we need to wrap it into - // `SELECT * FROM top` - Box::new(SetExpr::Select(Box::new(Select { - projection: vec![SelectItem::Wildcard( - sql_ast::WildcardAdditionalOptions::default(), - )], - from: vec![TableWithJoins { - relation: TableFactor::Derived { - lateral: false, - subquery: Box::new(top), - alias: Some(TableAlias { - name: Ident::new(context.anchor.table_name.gen()), - columns: Vec::new(), - }), - }, - joins: vec![], - }], - ..default_select() - }))) - }; + let left = query_to_set_expr(top, context); top = default_query(SetExpr::SetOperation { left, @@ -360,7 +372,7 @@ fn sql_set_ops_of_pipeline( sql_ast::WildcardAdditionalOptions::default(), )], from: vec![TableWithJoins { - relation: table_factor_of_tid(bottom, context), + relation: table_factor_of_table_ref(bottom, context)?, joins: vec![], }], ..default_select() @@ -381,6 +393,99 @@ fn sql_set_ops_of_pipeline( Ok(top) } +fn sql_of_loop(pipeline: Vec, ctx: &mut Context) -> Result> { + // split the pipeline + let (mut initial, mut following) = pipeline.break_up(|t| matches!(t, SqlTransform::Loop(_))); + let loop_ = following.remove(0); + let step = loop_.into_loop().unwrap(); + + // RECURSIVE can only follow WITH directly, which means that if we want to use it for + // an arbitrary query, we have to defined a *nested* WITH RECURSIVE and not use + // the top-level list of CTEs. + + // determine columns of the initial table + let recursive_columns = AnchorContext::determine_select_columns(&initial); + + // do the same thing we do when splitting a pipeline + // (defining new columns, redirecting cids) + let recursive_columns = SqlTransform::Super(Transform::Select(recursive_columns)); + initial.push(recursive_columns.clone()); + let step = anchor_split(&mut ctx.anchor, initial, step); + let from = step.first().unwrap().as_super().unwrap().as_from().unwrap(); + + let initial = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); + initial.name = Some("loop".to_string()); + let initial_relation = initial.relation.take().unwrap(); + + let initial = initial_relation.kind.into_preprocessed_pipeline().unwrap(); + + // compile initial + let initial = query_to_set_expr(sql_query_of_pipeline(initial, ctx)?, ctx); + + // compile step (without producing CTEs) + ctx.push_query(); + ctx.query.forbid_ctes = true; + + let step = query_to_set_expr(sql_query_of_pipeline(step, ctx)?, ctx); + + ctx.pop_query(); + + // build CTE and it's SELECT + let cte = sql_ast::Cte { + alias: simple_table_alias(Ident::new("loop")), + query: Box::new(default_query(SetExpr::SetOperation { + op: sql_ast::SetOperator::Union, + set_quantifier: sql_ast::SetQuantifier::All, + left: initial, + right: step, + })), + from: None, + }; + let query = Box::new(sql_ast::Query { + with: Some(sql_ast::With { + recursive: true, + cte_tables: vec![cte], + }), + ..default_query(sql_ast::SetExpr::Select(Box::new(sql_ast::Select { + projection: vec![SelectItem::Wildcard( + sql_ast::WildcardAdditionalOptions::default(), + )], + from: vec![TableWithJoins { + relation: TableFactor::Table { + name: sql_ast::ObjectName(vec![Ident::new("loop")]), + alias: None, + args: None, + with_hints: Vec::new(), + }, + joins: vec![], + }], + ..default_select() + }))) + }); + + // create a split between the loop SELECT statement and the following pipeline + let mut following = anchor_split(&mut ctx.anchor, vec![recursive_columns], following); + + let from = following.first_mut().unwrap(); + let from = from.as_super().unwrap().as_from().unwrap(); + + // this will be table decl that references the whole loop expression + let loop_decl = ctx.anchor.table_decls.get_mut(&from.source).unwrap(); + + let loop_name = ctx.anchor.table_name.gen(); + loop_decl.name = Some(loop_name.clone()); + loop_decl.relation = None; + + // push the whole thing into WITH of the main query + ctx.ctes.push(sql_ast::Cte { + alias: simple_table_alias(Ident::new(loop_name)), + query, + from: None, + }); + + Ok(following) +} + fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result { // TODO: this could be made to use VALUES instead of SELECT UNION ALL SELECT // I'm not sure about compatibility though. @@ -416,121 +521,65 @@ fn sql_of_sample_data(data: RelationLiteral, ctx: &Context) -> Result, - ctx: &mut AnchorContext, -) -> Vec { - let outputs_cid = AnchorContext::determine_select_columns(&pipeline); - - let mut required_cols = outputs_cid.clone(); - - // split pipeline, back to front - let mut parts_rev = Vec::new(); - loop { - let (preceding, split) = anchor::split_off_back(ctx, required_cols, pipeline); - - if let Some((preceding, cols_at_split)) = preceding { - log::debug!( - "pipeline split after {}", - preceding.last().unwrap().as_str() - ); - parts_rev.push((split, cols_at_split.clone())); - - pipeline = preceding; - required_cols = cols_at_split; - } else { - parts_rev.push((split, Vec::new())); - break; - } - } - parts_rev.reverse(); - let mut parts = parts_rev; +/// Extract last part of pipeline that is able to "fit" into a single SELECT statement. +/// Remaining proceeding pipeline is declared as a table and stored in AnchorContext. +fn extract_atomic(pipeline: Vec, ctx: &mut AnchorContext) -> Vec { + let (preceding, atomic) = anchor::split_off_back(pipeline, ctx); - // sometimes, additional columns will be added into select, which have to - // be filtered out here, using additional CTE - if let Some((pipeline, _)) = parts.last() { - let select_cols = pipeline - .first() - .unwrap() - .as_super() - .unwrap() - .as_select() - .unwrap(); - - if select_cols.iter().any(|c| !outputs_cid.contains(c)) { - parts.push(( - vec![SqlTransform::Super(Transform::Select(outputs_cid))], - select_cols.clone(), - )); - } - } + if let Some(preceding) = preceding { + log::debug!( + "pipeline split after {}", + preceding.last().unwrap().as_str() + ); - // add names to pipelines, anchor, front to back - let mut atomics = Vec::with_capacity(parts.len()); - let last = parts.pop().unwrap(); - - let last_pipeline = if parts.is_empty() { - last.0 + anchor::anchor_split(ctx, preceding, atomic) } else { - // this code chunk is bloated but I cannot find a more concise alternative - let first = parts.remove(0); - - let first_name = ctx.table_name.gen(); - atomics.push(AtomicQuery { - name: first_name.clone(), - relation: SqlRelation::Pipeline(first.0), - }); - - let mut prev_name = first_name; - for (pipeline, cols_before) in parts.into_iter() { - let name = ctx.table_name.gen(); - let pipeline = anchor::anchor_split(ctx, &prev_name, &cols_before, pipeline); - - atomics.push(AtomicQuery { - name: name.clone(), - relation: SqlRelation::Pipeline(pipeline), - }); - - prev_name = name; - } - - anchor::anchor_split(ctx, &prev_name, &last.1, last.0) - }; - atomics.push(AtomicQuery { - name, - relation: SqlRelation::Pipeline(last_pipeline), - }); + atomic + } - atomics + // TODO + // sometimes, additional columns will be added into select, which have to + // be filtered out here, using additional CTE + // if let Some((pipeline, _)) = parts.last() { + // let select_cols = pipeline + // .first() + // .unwrap() + // .as_super() + // .unwrap() + // .as_select() + // .unwrap(); + + // if select_cols.iter().any(|c| !outputs_cid.contains(c)) { + // parts.push(( + // vec![SqlTransform::Super(Transform::Select(outputs_cid))], + // select_cols.clone(), + // )); + // } + // } } -fn ensure_names(atomics: &[AtomicQuery], ctx: &mut AnchorContext) { - // ensure column names for columns that need it - for a in atomics { - let empty = HashSet::new(); - for t in a.relation.as_pipeline().unwrap() { - match t { - SqlTransform::Super(Transform::Sort(_)) => { - for r in anchor::get_requirements(t, &empty) { - ctx.ensure_column_name(r.col); - } +fn ensure_names(transforms: &[SqlTransform], ctx: &mut AnchorContext) { + let empty = HashSet::new(); + for t in transforms { + match t { + SqlTransform::Super(Transform::Sort(_)) => { + for r in anchor::get_requirements(t, &empty) { + ctx.ensure_column_name(r.col); } - SqlTransform::Super(Transform::Select(cids)) => { - for cid in cids { - let _decl = &ctx.column_decls[cid]; - //let name = match decl { - // ColumnDecl::RelationColumn(_, _, _) => todo!(), - // ColumnDecl::Compute(_) => ctx.column_names[..], - //}; - } + } + SqlTransform::Super(Transform::Select(cids)) => { + for cid in cids { + let _decl = &ctx.column_decls[cid]; + //let name = match decl { + // ColumnDecl::RelationColumn(_, _, _) => todo!(), + // ColumnDecl::Compute(_) => ctx.column_names[..], + //}; } - _ => (), } + _ => (), } } } - fn filter_of_conditions(exprs: Vec, context: &mut Context) -> Result> { Ok(if let Some(cond) = all(exprs) { Some(translate_expr_kind(cond.kind, context)?) @@ -584,6 +633,45 @@ fn default_select() -> Select { } } +fn simple_table_alias(name: Ident) -> TableAlias { + TableAlias { + name, + columns: Vec::new(), + } +} + +fn query_to_set_expr(query: sql_ast::Query, context: &mut Context) -> Box { + let is_simple = query.with.is_none() + && query.order_by.is_empty() + && query.limit.is_none() + && query.offset.is_none() + && query.fetch.is_none() + && query.locks.is_empty(); + + if is_simple { + return query.body; + } + + // query is not simple, so we need to wrap it into + // `SELECT * FROM (query)` + Box::new(SetExpr::Select(Box::new(Select { + projection: vec![SelectItem::Wildcard( + sql_ast::WildcardAdditionalOptions::default(), + )], + from: vec![TableWithJoins { + relation: TableFactor::Derived { + lateral: false, + subquery: Box::new(query), + alias: Some(simple_table_alias(Ident::new( + context.anchor.table_name.gen(), + ))), + }, + joins: vec![], + }], + ..default_select() + }))) +} + fn count_tables(transforms: &[SqlTransform]) -> usize { let mut count = 0; for transform in transforms { @@ -603,19 +691,36 @@ mod test { fn parse_and_resolve(prql: &str) -> Result<(Vec, Context)> { let query = resolve(parse(prql)?)?; - let (anchor, query) = AnchorContext::of(query); - let context = Context { - dialect: Box::new(GenericDialect {}), - anchor, - omit_ident_prefix: false, - pre_projection: false, - }; + let (anchor, main_relation) = AnchorContext::of(query); + let context = Context::new(Box::new(GenericDialect {}), anchor); - let pipeline = query.relation.kind.into_pipeline().unwrap(); + let pipeline = main_relation.kind.into_pipeline().unwrap(); Ok((preprocess::reorder(preprocess::wrap(pipeline)), context)) } + fn count_atomics(prql: &str) -> usize { + let (mut pipeline, mut context) = parse_and_resolve(prql).unwrap(); + context.anchor.table_decls.clear(); + + let mut atomics = 0; + loop { + let _ = extract_atomic(pipeline, &mut context.anchor); + atomics += 1; + + if let Some((_, decl)) = context.anchor.table_decls.drain().next() { + if let Some(relation) = decl.relation { + if let SqlRelationKind::PreprocessedPipeline(p) = relation.kind { + pipeline = p; + continue; + } + } + } + break; + } + atomics + } + #[test] fn test_ctes_of_pipeline() { // One aggregate, take at the end @@ -627,9 +732,7 @@ mod test { take 20 "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 1); + assert_eq!(count_atomics(prql), 1); // One aggregate, but take at the top let prql: &str = r###" @@ -640,9 +743,7 @@ mod test { sort sal "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 2); + assert_eq!(count_atomics(prql), 2); // A take, then two aggregates let prql: &str = r###" @@ -654,9 +755,7 @@ mod test { sort sal2 "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 3); + assert_eq!(count_atomics(prql), 3); // A take, then a select let prql: &str = r###" @@ -665,9 +764,7 @@ mod test { select first_name "###; - let (pipeline, mut context) = parse_and_resolve(prql).unwrap(); - let queries = split_into_atomics("".to_string(), pipeline, &mut context.anchor); - assert_eq!(queries.len(), 1); + assert_eq!(count_atomics(prql), 1); } #[test] @@ -719,7 +816,7 @@ mod test { *, RANK() OVER () AS rank FROM - table_1 + table_1 AS table_0 WHERE country = 'USA' "###); @@ -744,7 +841,7 @@ mod test { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 > 3 "###); diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index 76b8fe6b11dc..8e3c3da14c36 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -60,6 +60,18 @@ struct Context { pub dialect: Box, pub anchor: AnchorContext, + // stuff regarding current query + query: QueryOpts, + + // stuff regarding parent queries + query_stack: Vec, + + pub ctes: Vec, +} + +#[derive(Default, Clone)] +struct QueryOpts { + /// When true, column references will not include table names prefixes. pub omit_ident_prefix: bool, /// True iff codegen should generate expressions before SELECT's projection is applied. @@ -67,6 +79,29 @@ struct Context { /// - WHERE needs `pre_projection=true`, but /// - ORDER BY needs `pre_projection=false`. pub pre_projection: bool, + + /// When true, queries will contain nested sub-queries instead of WITH CTEs. + pub forbid_ctes: bool, +} + +impl Context { + fn new(dialect: Box, anchor: AnchorContext) -> Self { + Context { + dialect, + anchor, + query: QueryOpts::default(), + query_stack: Vec::new(), + ctes: Vec::new(), + } + } + + fn push_query(&mut self) { + self.query_stack.push(self.query.clone()); + } + + fn pop_query(&mut self) { + self.query = self.query_stack.pop().unwrap(); + } } #[cfg(test)] diff --git a/prql-compiler/src/sql/preprocess.rs b/prql-compiler/src/sql/preprocess.rs index 7c04c4cbf7cb..035f6858dd30 100644 --- a/prql-compiler/src/sql/preprocess.rs +++ b/prql-compiler/src/sql/preprocess.rs @@ -10,7 +10,8 @@ use crate::ast::pl::{ BinOp, ColumnSort, InterpolateItem, JoinSide, Literal, Range, WindowFrame, WindowKind, }; use crate::ast::rq::{ - self, new_binop, CId, Compute, Expr, ExprKind, RqFold, TableRef, Transform, Window, + self, new_binop, CId, Compute, Expr, ExprKind, Relation, RelationColumn, RelationKind, RqFold, + TableRef, Transform, Window, }; use crate::error::Error; use crate::sql::context::AnchorContext; @@ -18,31 +19,45 @@ use crate::sql::context::AnchorContext; use super::anchor::{infer_complexity, CidCollector, Complexity}; use super::Context; -#[derive(Debug, EnumAsInner, strum::AsRefStr)] +#[derive(Debug, Clone, EnumAsInner)] +pub(super) enum SqlRelationKind { + Super(RelationKind), + PreprocessedPipeline(Vec), +} + +#[derive(Debug, Clone)] +pub(super) struct SqlRelation { + pub kind: SqlRelationKind, + pub columns: Vec, +} + +#[derive(Debug, Clone, EnumAsInner, strum::AsRefStr)] pub(super) enum SqlTransform { Super(Transform), Distinct, Except { bottom: TableRef, distinct: bool }, Intersect { bottom: TableRef, distinct: bool }, Union { bottom: TableRef, distinct: bool }, + Loop(Vec), } -/// Pushes all [Transform::Select]s to the back of the pipeline. -pub(super) fn push_down_selects(pipeline: Vec) -> Vec { - let mut select = None; - let mut res = Vec::with_capacity(pipeline.len()); - for t in pipeline { - if let Transform::Select(_) = t { - select = Some(t); - } else { - res.push(t); - } - } - if let Some(select) = select { - res.push(select); - } - res -} +// This function was disabled because it changes semantics of the pipeline in some cases. +// /// Pushes all [Transform::Select]s to the back of the pipeline. +// pub(super) fn push_down_selects(pipeline: Vec) -> Vec { +// let mut select = None; +// let mut res = Vec::with_capacity(pipeline.len()); +// for t in pipeline { +// if let Transform::Select(_) = t { +// select = Some(t); +// } else { +// res.push(t); +// } +// } +// if let Some(select) = select { +// res.push(select); +// } +// res +// } /// Removes unused relation inputs pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { @@ -76,7 +91,12 @@ pub(super) fn prune_inputs(mut pipeline: Vec) -> Vec { } pub(super) fn wrap(pipe: Vec) -> Vec { - pipe.into_iter().map(SqlTransform::Super).collect() + pipe.into_iter() + .map(|t| match t { + Transform::Loop(pipeline) => SqlTransform::Loop(wrap(pipeline)), + _ => SqlTransform::Super(t), + }) + .collect() } /// Creates [SqlTransform::Distinct] from [Transform::Take] @@ -557,6 +577,15 @@ impl SqlTransform { } } +impl From for SqlRelation { + fn from(rel: Relation) -> Self { + SqlRelation { + kind: SqlRelationKind::Super(rel.kind), + columns: rel.columns, + } + } +} + pub(super) trait SqlFold: RqFold { fn fold_sql_transforms(&mut self, transforms: Vec) -> Result> { transforms @@ -581,6 +610,7 @@ pub(super) trait SqlFold: RqFold { bottom: self.fold_table_ref(bottom)?, distinct, }, + SqlTransform::Loop(pipeline) => SqlTransform::Loop(self.fold_sql_transforms(pipeline)?), }) } } diff --git a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap index 5b7e140a157a..1164db5605aa 100644 --- a/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap +++ b/prql-compiler/src/sql/snapshots/prql_compiler__sql__gen_query__test__variable_after_aggregate.snap @@ -16,6 +16,7 @@ SELECT title, AVG(_expr_0) AS avg_salary FROM - table_1 + table_1 AS table_0 GROUP BY title + diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index fbe73829bf12..4b3f16018b5f 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -205,7 +205,7 @@ fn test_append() { take 10 ) "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT *, name, @@ -227,13 +227,13 @@ fn test_append() { employees LIMIT 3 - ) AS table_3 + ) AS table_2 UNION ALL SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "###); assert_display_snapshot!(compile(r###" @@ -310,7 +310,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -325,7 +325,7 @@ fn test_remove() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -337,7 +337,7 @@ fn test_remove() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -348,9 +348,9 @@ fn test_remove() { album.title FROM album - LEFT JOIN table_1 AS table_0 ON album.artist_id = table_0.artist_id + LEFT JOIN table_0 AS table_1 ON album.artist_id = table_1.artist_id WHERE - table_0.artist_id IS NULL + table_1.artist_id IS NULL "### ); @@ -382,11 +382,11 @@ fn test_remove() { album ) SELECT - table_1.artist_id, - table_1.title + table_0.artist_id, + table_0.title FROM - table_1 - LEFT JOIN bottom AS b ON table_1.artist_id = b.* + table_1 AS table_0 + LEFT JOIN bottom AS b ON table_0.artist_id = b.* WHERE b.* IS NULL "### @@ -443,7 +443,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -458,7 +458,7 @@ fn test_intersect() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -474,22 +474,28 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM artist + ), + table_3 AS ( + SELECT + artist_id + FROM + album + INTERSECT + DISTINCT + SELECT + * + FROM + table_0 AS table_1 ) SELECT - artist_id + DISTINCT artist_id FROM - album - INTERSECT - DISTINCT - SELECT - * - FROM - table_1 AS table_0 + table_3 AS table_2 "### ); @@ -504,22 +510,28 @@ fn test_intersect() { distinct "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM artist + ), + table_3 AS ( + SELECT + artist_id + FROM + album + INTERSECT + ALL + SELECT + * + FROM + table_0 AS table_1 ) SELECT - artist_id - FROM - album - INTERSECT - DISTINCT - SELECT - * + DISTINCT artist_id FROM - table_1 AS table_0 + table_3 AS table_2 "### ); @@ -534,7 +546,7 @@ fn test_intersect() { ) "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT artist_id FROM @@ -549,7 +561,7 @@ fn test_intersect() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -574,28 +586,28 @@ fn test_rn_ids_are_unique() { take 3 ) "###).unwrap()), @r###" - WITH table_1 AS ( + WITH table_3 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_0 + ROW_NUMBER() OVER (PARTITION BY y_id) AS _expr_1 FROM y_orig ), - table_2 AS ( + table_1 AS ( SELECT *, - ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_1 + ROW_NUMBER() OVER (PARTITION BY x_id) AS _expr_0 FROM - table_1 + table_3 AS table_2 WHERE - _expr_0 <= 2 + _expr_1 <= 2 ) SELECT * FROM - table_2 + table_1 AS table_0 WHERE - _expr_1 <= 3 + _expr_0 <= 3 "###); } @@ -690,19 +702,13 @@ fn test_sorts() { select [renamed = somefield] "### ).unwrap()), @r###" - WITH table_1 AS ( - SELECT - 'something' AS renamed, - 'something' AS _expr_0 - FROM - x - ORDER BY - _expr_0 - ) SELECT - renamed + 'something' AS renamed, + 'something' AS _expr_0 FROM - table_1 + x + ORDER BY + _expr_0 "###); } @@ -877,7 +883,7 @@ fn test_window_functions_02() { order_day ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS num_books_last_week FROM - table_1 + table_1 AS table_0 ORDER BY order_day "###); @@ -1261,7 +1267,7 @@ fn test_take() { SELECT * FROM - table_1 + table_1 AS table_0 ORDER BY name LIMIT @@ -1340,7 +1346,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE rn > 2 "###); @@ -1397,7 +1403,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 3 "###); @@ -1420,7 +1426,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 BETWEEN 2 AND 3 "###); @@ -1443,7 +1449,7 @@ fn test_distinct() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 = 4 "###); @@ -1819,16 +1825,7 @@ fn test_prql_to_sql_table() { let sql = compile(query).unwrap(); assert_display_snapshot!(sql, @r###" - WITH average_salaries AS ( - SELECT - country, - AVG(salary) AS average_country_salary - FROM - salaries - GROUP BY - country - ), - newest_employees AS ( + WITH newest_employees AS ( SELECT * FROM @@ -1837,6 +1834,14 @@ fn test_prql_to_sql_table() { tenure LIMIT 50 + ), average_salaries AS ( + SELECT + country, + AVG(salary) AS average_country_salary + FROM + salaries + GROUP BY + country ) SELECT newest_employees.name, @@ -1870,7 +1875,7 @@ fn test_nonatomic() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_1 AS ( + WITH table_3 AS ( SELECT title, country, @@ -1879,13 +1884,13 @@ fn test_nonatomic() { employees LIMIT 20 - ), table_2 AS ( + ), table_1 AS ( SELECT title, country, AVG(salary) AS _expr_0 FROM - table_1 + table_3 AS table_2 WHERE country = 'USA' GROUP BY @@ -1897,7 +1902,7 @@ fn test_nonatomic() { country, AVG(_expr_0) AS sum_gross_cost FROM - table_2 + table_1 AS table_0 GROUP BY title, country @@ -1950,7 +1955,7 @@ fn test_nonatomic_table() { "###; assert_display_snapshot!((compile(query).unwrap()), @r###" - WITH table_0 AS ( + WITH table_1 AS ( SELECT country FROM @@ -1962,7 +1967,7 @@ fn test_nonatomic_table() { country, count(*) FROM - table_0 + table_1 AS table_0 GROUP BY country ) @@ -1999,12 +2004,12 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_1.emp_no, - table_1.name, + table_0.emp_no, + table_0.name, s.salary FROM - table_1 - JOIN salaries AS s ON table_1.emp_no = s.emp_no + table_1 AS table_0 + JOIN salaries AS s ON table_0.emp_no = s.emp_no "###); let prql = r###" @@ -2024,11 +2029,11 @@ fn test_table_names_between_splits() { 10 ) SELECT - table_1.*, + table_0.*, salaries.salary FROM - table_1 - JOIN salaries ON table_1.emp_no = salaries.emp_no + table_1 AS table_0 + JOIN salaries ON table_0.emp_no = salaries.emp_no "###); } @@ -2308,12 +2313,6 @@ fn test_toposort() { * FROM somesource - ), - a AS ( - SELECT - * - FROM - b ) SELECT * @@ -2333,7 +2332,7 @@ fn test_inline_tables() { join s = (from salaries | select [emp_id, salary]) [==emp_id] "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT emp_id, salary @@ -2346,11 +2345,11 @@ fn test_inline_tables() { employees.surname, employees.type, employees.amount, - table_0.emp_id, - table_0.salary + table_1.emp_id, + table_1.salary FROM employees - JOIN table_1 AS table_0 ON employees.emp_id = table_0.emp_id + JOIN table_0 AS table_1 ON employees.emp_id = table_1.emp_id "### ); } @@ -2435,7 +2434,7 @@ fn test_table_s_string() { s"SELECT DISTINCT ON first_name, age FROM employees ORDER BY age ASC" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT DISTINCT ON first_name, age @@ -2446,7 +2445,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -2457,7 +2456,7 @@ fn test_table_s_string() { join s = s"SELECT * FROM salaries" [==id] "###).unwrap(), @r###" - WITH table_2 AS ( + WITH table_0 AS ( SELECT DISTINCT ON first_name, id, @@ -2467,18 +2466,18 @@ fn test_table_s_string() { ORDER BY age ASC ), - table_3 AS ( + table_1 AS ( SELECT * FROM salaries ) SELECT - table_0.*, - table_1.* + table_2.*, + table_3.* FROM - table_2 AS table_0 - JOIN table_3 AS table_1 ON table_0.id = table_1.id + table_0 AS table_2 + JOIN table_1 AS table_3 ON table_2.id = table_3.id "### ); @@ -2487,7 +2486,7 @@ fn test_table_s_string() { filter country == "USA" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2496,7 +2495,7 @@ fn test_table_s_string() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 WHERE country = 'USA' "### @@ -2507,7 +2506,7 @@ fn test_table_s_string() { filter e.country == "USA" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2516,7 +2515,7 @@ fn test_table_s_string() { SELECT * FROM - table_1 AS table_0 + table_0 AS table_1 WHERE country = 'USA' "### @@ -2529,7 +2528,7 @@ fn test_table_s_string() { weeks_between @2022-06-03 (current_week + 4) "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT generate_series( DATE '2022-06-03', @@ -2539,7 +2538,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -2547,7 +2546,7 @@ fn test_table_s_string() { s"SELECT * FROM {default_db.x}" "###).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT * FROM @@ -2555,7 +2554,7 @@ fn test_table_s_string() { ) SELECT FROM - table_1 AS table_0 + table_0 AS table_1 "### ); } @@ -2655,13 +2654,13 @@ fn test_group_all() { 10 ) SELECT - table_1.*, + table_0.*, SUM(salaries.salary) AS sal FROM - table_1 - JOIN salaries ON table_1.emp_no = salaries.emp_no + table_1 AS table_0 + JOIN salaries ON table_0.emp_no = salaries.emp_no GROUP BY - table_1.* + table_0.* "### ); @@ -2692,7 +2691,7 @@ fn test_output_column_deduplication() { SELECT * FROM - table_1 + table_1 AS table_0 WHERE r = 1 "### @@ -2766,7 +2765,7 @@ fn test_switch() { category, COUNT(*) FROM - table_1 + table_1 AS table_0 GROUP BY category "### @@ -3151,7 +3150,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT '1' AS a, '2' AS b, @@ -3167,7 +3166,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -3178,7 +3177,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT 1 AS a, 'x' AS b, @@ -3194,7 +3193,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); @@ -3209,7 +3208,7 @@ a,b,c select [b, c] "#).unwrap(), @r###" - WITH table_1 AS ( + WITH table_0 AS ( SELECT 1 AS a, 'x' AS b, @@ -3225,7 +3224,7 @@ a,b,c b, c FROM - table_1 AS table_0 + table_0 AS table_1 "### ); } @@ -3242,3 +3241,55 @@ fn test_header_target_error() { from a "#).unwrap_err(),@r###"target `"sql.foo"` not found"###) } + +#[test] +fn test_loop() { + assert_display_snapshot!(compile(r#" + from_text format:json '[{"n": 1 }]' + select n = n - 2 + loop ( + select n = n+1 + filter n<5 + ) + select n = n * 2 + take 4 + "#).unwrap(), + @r###" + WITH table_0 AS ( + SELECT + 1 AS n + ), + table_6 AS ( + WITH RECURSIVE loop AS ( + SELECT + n - 2 AS _expr_0 + FROM + table_0 AS table_1 + UNION + ALL + SELECT + _expr_1 + FROM + ( + SELECT + _expr_0 + 1 AS _expr_1 + FROM + loop AS table_2 + ) AS table_3 + WHERE + _expr_1 < 5 + ) + SELECT + * + FROM + loop + ) + SELECT + _expr_0 * 2 AS n + FROM + table_6 AS table_5 + LIMIT + 4 + "### + ); +} diff --git a/prql-compiler/tests/integration/queries/loop.prql b/prql-compiler/tests/integration/queries/loop.prql new file mode 100644 index 000000000000..e83d02e37057 --- /dev/null +++ b/prql-compiler/tests/integration/queries/loop.prql @@ -0,0 +1,7 @@ +from_text format:json '[{"n": 1 }]' +select n = n - 2 +loop ( + filter n<4 + select n = n+1 +) +select n = n * 2 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap new file mode 100644 index 000000000000..482dc9933c4d --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@loop.prql.snap @@ -0,0 +1,12 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/loop.prql +--- +n +-2 +0 +2 +4 +6 +8 diff --git a/website/content/_index.md b/website/content/_index.md index 035f4eaedfe2..349317aaf594 100644 --- a/website/content/_index.md +++ b/website/content/_index.md @@ -246,7 +246,7 @@ showcase_section: SELECT * FROM - table_1 + table_1 AS table_0 WHERE _expr_0 <= 1 From 5a382e759d959e0a9101fd0b97d5c118b229208a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 22:06:32 -0800 Subject: [PATCH 060/184] ci: Only cache docker on main branch (#1953) --- .github/workflows/test-all.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 34ea805c7de4..9c3e24912499 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -105,6 +105,8 @@ jobs: load: true cache-from: type=gha cache-to: type=gha,mode=max + # Don't cache if the branch isn't main... + no-cache: ${{ github.ref != 'refs/heads/main' }} test-min-rust-version: runs-on: ubuntu-latest From c3d777b7cbe433b2b6e8ec0a43e0b8e43928b60f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 23 Feb 2023 22:16:51 -0800 Subject: [PATCH 061/184] revert: #1953 (#1954) Revert "ci: Only cache docker on main branch (#1953)" This reverts commit 5a382e759d959e0a9101fd0b97d5c118b229208a. --- .github/workflows/test-all.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 9c3e24912499..34ea805c7de4 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -105,8 +105,6 @@ jobs: load: true cache-from: type=gha cache-to: type=gha,mode=max - # Don't cache if the branch isn't main... - no-cache: ${{ github.ref != 'refs/heads/main' }} test-min-rust-version: runs-on: ubuntu-latest From b0276bcbfcca93f7db1b8d695181c1afa0b6f45e Mon Sep 17 00:00:00 2001 From: Jonathan Date: Fri, 24 Feb 2023 11:32:44 +0100 Subject: [PATCH 062/184] refactor: Improve PHP bindings (#1949) --- prql-php/src/Compiler.php | 133 +++++++++++++++++++------------- prql-php/src/Options.php | 2 +- prql-php/tests/CompilerTest.php | 35 +++++---- 3 files changed, 101 insertions(+), 69 deletions(-) diff --git a/prql-php/src/Compiler.php b/prql-php/src/Compiler.php index 5be55ea51962..baa470c4fa29 100644 --- a/prql-php/src/Compiler.php +++ b/prql-php/src/Compiler.php @@ -30,6 +30,45 @@ */ final class Compiler { + private \FFI $_libprql; + + /** + * Initializes a new instance of the Compiler. + * + * @param ?string|null $lib_path Path to the libprql library. + */ + function __construct(?string $lib_path = null) + { + $library = $lib_path; + + if ($lib_path === null) { + $library = __DIR__; + } + + if (PHP_OS_FAMILY === "Windows") { + $library .= "\libprql_lib.dll"; + } elseif (PHP_OS_FAMILY === "Darwin") { + $library .= "/libprql_lib.dylib"; + } else { + $library .= "/libprql_lib.so"; + } + + $this->_libprql = \FFI::cdef( + " + typedef struct Options { + bool format; + char *target; + bool signature_comment; + } Options; + + int compile(const char *prql_query, const struct Options *options, char *out); + int prql_to_pl(const char *prql_query, char *out); + int pl_to_rq(const char *pl_json, char *out); + int rq_to_sql(const char *rq_json, char *out); + ", $library + ); + } + /** * Compile a PRQL string into a SQL string. * @@ -37,9 +76,9 @@ final class Compiler * @param Options|null $options PRQL compiler options. * * @return string SQL query. - * @throws \InvalidArgumentException If no query is given or the query cannot - * @api + * @throws \InvalidArgumentException If no query is given or the query canno * be compiled. + * @api * @todo FIX THIS. THIS DOES NOT WORK! * @ignore Ignore this function until fixed. */ @@ -53,72 +92,45 @@ function compile(string $prql_query, ?Options $options = null): string $options = new Options(); } - $library = "/libprql_lib.so"; - - if (PHP_OS_FAMILY === "Windows") { - $library = "\libprql_lib.dll"; - } - - $libprql = \FFI::cdef( - " - struct options { - bool format; - char* target; - bool signature_comment; - }; - - char* compile(const char *prql_query, struct options *opt); - ", __DIR__ . $library - ); - - $ffi_options = $libprql->new("struct options"); + $ffi_options = $this->_libprql->new("struct Options"); $ffi_options->format = $options->format; $ffi_options->signature_comment = $options->signature_comment; if (isset($options->target)) { $target_len = strlen($options->target); - $ffi_options->target = $ffi->new('char[$target_len]', 0); - FFI::memcpy($ffi_options->target, $options->target, $target_len); - FFI::free($ffi_options->target); + $ffi_options->target = \FFI::new("char[$target_len]", false); + \FFI::memcpy($ffi_options->target, $options->target, $target_len); + \FFI::free($ffi_options->target); } $out = str_pad("", 1024); - if ($libprql->compile($prql_query, \FFI::addr($$ffi_options)) !== 0) { + if ($this->_libprql->compile($prql_query, \FFI::addr($ffi_options), $out) !== 0) { throw new \InvalidArgumentException("Could not compile query."); } + unset($ffi_options); + return trim($out); } /** - * Compile a PRQL string into a JSON string. + * Compile a PRQL string into PL. * * @param string $prql_query A PRQL query. * - * @return string JSON string. + * @return string Pipelined Language (PL) JSON string. * @throws \InvalidArgumentException If no query is given or the query cannot * be compiled. * @api */ - function toJson(string $prql_query): string + function prqlToPL(string $prql_query): string { if (!$prql_query) { throw new \InvalidArgumentException("No query given."); } - $library = "/libprql_lib.so"; - - if (PHP_OS_FAMILY === "Windows") { - $library = "\libprql_lib.dll"; - } - - $libprql = \FFI::cdef( - "int to_json(char *prql_query, char *json_query);", - __DIR__ . $library - ); - $out = str_pad("", 1024); - if ($libprql->to_json($prql_query, $out) !== 0) { + if ($this->_libprql->prql_to_pl($prql_query, $out) !== 0) { throw new \InvalidArgumentException("Could not compile query."); } @@ -126,35 +138,48 @@ function toJson(string $prql_query): string } /** - * Compile a PRQL string into a SQL string. + * Converts PL to RQ. * - * @param string $prql_query A PRQL query. + * @param string $pl_json PL in JSON format. * - * @return string SQL query. + * @return string RQ string. * @throws \InvalidArgumentException If no query is given or the query cannot * be compiled. * @api */ - function toSql(string $prql_query): string + function plToRQ(string $pl_json): string { if (!$prql_query) { throw new \InvalidArgumentException("No query given."); } - $library = "/libprql_lib.so"; - - if (PHP_OS_FAMILY === "Windows") { - $library = "\libprql_lib.dll"; + $out = str_pad("", 1024); + if ($this->_libprql->pl_to_rq($pl_json, $out) !== 0) { + throw new \InvalidArgumentException("Could not convert PL."); } - $libprql = \FFI::cdef( - "int to_sql(char *prql_query, char *sql_query);", - __DIR__ . $library - ); + return trim($out); + } + + /** + * Converts RQ to SQL. + * + * @param string $rq_json PL in JSON format. + * + * @return string SQL string. + * @throws \InvalidArgumentException If no query is given or the query cannot + * be compiled. + * @api + */ + function rQToSql(string $rq_json): string + { + if (!$prql_query) { + throw new \InvalidArgumentException("No query given."); + } $out = str_pad("", 1024); - if ($libprql->to_sql($prql_query, $out) !== 0) { - throw new \InvalidArgumentException("Could not compile query."); + if ($this->_libprql->rq_to_sql($rq_json, $out) !== 0) { + throw new \InvalidArgumentException("Could not convert RQ."); } return trim($out); diff --git a/prql-php/src/Options.php b/prql-php/src/Options.php index 3b76344df3e2..574d59075a8c 100644 --- a/prql-php/src/Options.php +++ b/prql-php/src/Options.php @@ -28,7 +28,7 @@ * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 * @link https://prql-lang.org/ */ -class Options +final class Options { /** * Pass generated SQL string trough a formatter that splits it into diff --git a/prql-php/tests/CompilerTest.php b/prql-php/tests/CompilerTest.php index a21957c17b47..de0d28131e43 100644 --- a/prql-php/tests/CompilerTest.php +++ b/prql-php/tests/CompilerTest.php @@ -1,6 +1,7 @@ assertInstanceOf(FFI::class, $ffi); } @@ -27,23 +28,29 @@ public function testInvalidQueryThrows(): void $this->expectException(\InvalidArgumentException::class); $prql = new Compiler(); - $prql->toSql("invalid"); + $prql->compile("invalid"); } - public function testToSqlWorks(): void + public function testCompileWorks(): void { - $expected = <<<'EOD' -SELECT - * -FROM - employees - --- Generated by PRQL compiler version:0.5.0 (https://prql-lang.org) -EOD; - $expected = substr($expected, 0, strpos($expected, "Generated by PRQL compiler")); + $options = new Options(); + $options->format = false; + $options->signature_comment = false; + $options->target = "sql.mssql"; $prql = new Compiler(); - $actual = $prql->toSql("from employees"); - $actual = substr($actual, 0, strpos($actual, "Generated by PRQL compiler")); + + $expected = "SELECT * FROM employees"; + $actual = $prql->compile("from employees", $options); + $this->assertEquals($expected, $actual); } + + public function testPrqlToPLWorks(): void + { + $prql = new Compiler(); + + $pl = $prql->prqlToPL("from employees"); + + $this->assertNotNull($pl); + } } From 8e2360f5710ad6df25ce3c691f9e67a63987b1b2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 24 Feb 2023 11:33:26 -0800 Subject: [PATCH 063/184] chore: bump monaco-editor from 0.35.0 to 0.36.0 in /playground (#1955) Bumps [monaco-editor](https://github.com/microsoft/monaco-editor) from 0.35.0 to 0.36.0. - [Release notes](https://github.com/microsoft/monaco-editor/releases) - [Changelog](https://github.com/microsoft/monaco-editor/blob/main/CHANGELOG.md) - [Commits](https://github.com/microsoft/monaco-editor/compare/v0.35.0...v0.36.0) --- updated-dependencies: - dependency-name: monaco-editor dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- playground/package-lock.json | 586 ++++++++++++++++++++++++++++++++++- playground/package.json | 2 +- 2 files changed, 580 insertions(+), 8 deletions(-) diff --git a/playground/package-lock.json b/playground/package-lock.json index a7e16715fc2f..3e8d7dd2ad9b 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -14,7 +14,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", - "monaco-editor": "^0.35.0", + "monaco-editor": "^0.36.0", "prql-js": "file:../prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3330,6 +3330,126 @@ "node": ">= 8" } }, + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "dependencies": { + "@octokit/types": "^6.0.3" + } + }, + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "dependencies": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" + } + }, + "node_modules/@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" + } + }, + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "node_modules/@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "dependencies": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "dependencies": { + "@octokit/openapi-types": "^12.11.0" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz", @@ -3928,6 +4048,15 @@ "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -4031,6 +4160,11 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" + }, "node_modules/@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", @@ -4124,6 +4258,15 @@ "@types/node": "*" } }, + "node_modules/@types/shelljs": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", + "integrity": "sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==", + "dependencies": { + "@types/glob": "*", + "@types/node": "*" + } + }, "node_modules/@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -5380,6 +5523,11 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, "node_modules/bfj": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", @@ -6775,6 +6923,11 @@ "node": ">= 0.8" } }, + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, "node_modules/destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -9250,6 +9403,14 @@ "node": ">= 0.4" } }, + "node_modules/interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", + "engines": { + "node": ">= 0.10" + } + }, "node_modules/ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -9482,6 +9643,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -12026,6 +12195,31 @@ "tmpl": "1.0.5" } }, + "node_modules/matcher": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/matcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -12234,9 +12428,14 @@ } }, "node_modules/monaco-editor": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.35.0.tgz", - "integrity": "sha512-BJfkAZ0EJ7JgrgWzqjfBNP9hPSS8NlfECEDMEIIiozV2UaPq22yeuOjgbd3TwMh3anH0krWZirXZfn8KUSxiOA==" + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.36.0.tgz", + "integrity": "sha512-1Pn3AatfK88flUigyBozA4mt8+SB5xlgloQDu1RqivARw9yKaml/jceIvndae7Z2Nq8T7xZccFlmH+n6rkFg6g==", + "dependencies": { + "@types/shelljs": "^0.8.11", + "pin-github-action": "^1.8.0", + "shelljs": "^0.8.5" + } }, "node_modules/ms": { "version": "2.1.3", @@ -12310,6 +12509,44 @@ "tslib": "^2.0.3" } }, + "node_modules/node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -12874,6 +13111,50 @@ "node": ">=0.10.0" } }, + "node_modules/pin-github-action": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pin-github-action/-/pin-github-action-1.8.0.tgz", + "integrity": "sha512-8QMKGbDUmMLFSyeV7hDIVmlI8B3ThJed1uFYuhcCBLi/w8xHPbrPhnCvJndYdugNc8aj1FrijrOMDLQ93ATc7A==", + "dependencies": { + "@octokit/rest": "^18", + "commander": "^9", + "debug": "^4.3.4", + "matcher": "^4.0.0", + "yaml": "^2.1.3" + }, + "bin": { + "pin-github-action": "bin.js" + } + }, + "node_modules/pin-github-action/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/pin-github-action/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/pin-github-action/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -14627,6 +14908,17 @@ "node": ">=8.10.0" } }, + "node_modules/rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -15344,6 +15636,22 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, + "node_modules/shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -16468,6 +16776,11 @@ "node": ">=8" } }, + "node_modules/universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -19904,6 +20217,118 @@ "fastq": "^1.6.0" } }, + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==" + }, + "@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", + "requires": { + "@octokit/types": "^6.40.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==", + "requires": {} + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", + "requires": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", + "requires": { + "@octokit/openapi-types": "^12.11.0" + } + }, "@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.7.tgz", @@ -20317,6 +20742,15 @@ "resolved": "https://registry.npmjs.org/@types/flatbuffers/-/flatbuffers-1.10.0.tgz", "integrity": "sha512-7btbphLrKvo5yl/5CC2OCxUSMx1wV1wvGT1qDXkSt7yi00/YW7E8k6qzXqJHsp+WU0eoG7r6MTQQXI9lIvd0qA==" }, + "@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "requires": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.5", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.5.tgz", @@ -20413,6 +20847,11 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" + }, "@types/node": { "version": "18.8.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.8.3.tgz", @@ -20506,6 +20945,15 @@ "@types/node": "*" } }, + "@types/shelljs": { + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.11.tgz", + "integrity": "sha512-x9yaMvEh5BEaZKeVQC4vp3l+QoFj3BXcd4aYfuKSzIIyihjdVARAadYy3SMNIz0WCCdS2vB9JL/U6GQk5PaxQw==", + "requires": { + "@types/glob": "*", + "@types/node": "*" + } + }, "@types/sockjs": { "version": "0.3.33", "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.33.tgz", @@ -21435,6 +21883,11 @@ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==" }, + "before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" + }, "bfj": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/bfj/-/bfj-7.0.2.tgz", @@ -22452,6 +22905,11 @@ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, "destroy": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", @@ -24243,6 +24701,11 @@ "side-channel": "^1.0.4" } }, + "interpret": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, "ipaddr.js": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.0.1.tgz", @@ -24384,6 +24847,11 @@ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz", "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==" }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, "is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -26390,6 +26858,21 @@ "tmpl": "1.0.5" } }, + "matcher": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", + "requires": { + "escape-string-regexp": "^4.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" + } + } + }, "mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -26537,9 +27020,14 @@ } }, "monaco-editor": { - "version": "0.35.0", - "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.35.0.tgz", - "integrity": "sha512-BJfkAZ0EJ7JgrgWzqjfBNP9hPSS8NlfECEDMEIIiozV2UaPq22yeuOjgbd3TwMh3anH0krWZirXZfn8KUSxiOA==" + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.36.0.tgz", + "integrity": "sha512-1Pn3AatfK88flUigyBozA4mt8+SB5xlgloQDu1RqivARw9yKaml/jceIvndae7Z2Nq8T7xZccFlmH+n6rkFg6g==", + "requires": { + "@types/shelljs": "^0.8.11", + "pin-github-action": "^1.8.0", + "shelljs": "^0.8.5" + } }, "ms": { "version": "2.1.3", @@ -26595,6 +27083,35 @@ "tslib": "^2.0.3" } }, + "node-fetch": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", + "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "node-forge": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", @@ -26991,6 +27508,38 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" }, + "pin-github-action": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/pin-github-action/-/pin-github-action-1.8.0.tgz", + "integrity": "sha512-8QMKGbDUmMLFSyeV7hDIVmlI8B3ThJed1uFYuhcCBLi/w8xHPbrPhnCvJndYdugNc8aj1FrijrOMDLQ93ATc7A==", + "requires": { + "@octokit/rest": "^18", + "commander": "^9", + "debug": "^4.3.4", + "matcher": "^4.0.0", + "yaml": "^2.1.3" + }, + "dependencies": { + "commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "pirates": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", @@ -28091,6 +28640,14 @@ "picomatch": "^2.2.1" } }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", + "requires": { + "resolve": "^1.1.6" + } + }, "recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -28605,6 +29162,16 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz", "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==" }, + "shelljs": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", + "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "requires": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + } + }, "side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -29450,6 +30017,11 @@ "crypto-random-string": "^2.0.0" } }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/playground/package.json b/playground/package.json index 8a2295b250b7..1de1b6c79627 100644 --- a/playground/package.json +++ b/playground/package.json @@ -17,7 +17,7 @@ "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", - "monaco-editor": "^0.35.0", + "monaco-editor": "^0.36.0", "prql-js": "file:../prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", From 9c5f2d59940c531d380e13336c5b7828bfc60b27 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 24 Feb 2023 17:04:36 -0800 Subject: [PATCH 064/184] internal: Defer to auto-conversion of some errors (#1931) Follow-up to #1914 --- prql-compiler/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs index 25d50b652745..18894b6b5348 100644 --- a/prql-compiler/src/lib.rs +++ b/prql-compiler/src/lib.rs @@ -233,12 +233,12 @@ pub fn prql_to_pl(prql: &str) -> Result, ErrorMessages> { /// Perform semantic analysis and convert PL to RQ. pub fn pl_to_rq(pl: Vec) -> Result { - semantic::resolve(pl).map_err(error::downcast) + semantic::resolve(pl).map_err(|e| e.into()) } /// Generate SQL from RQ. pub fn rq_to_sql(rq: ast::rq::Query, options: &Options) -> Result { - sql::compile(rq, options).map_err(error::downcast) + sql::compile(rq, options).map_err(|e| e.into()) } /// Generate PRQL code from PL AST @@ -252,22 +252,22 @@ pub mod json { /// JSON serialization pub fn from_pl(pl: Vec) -> Result { - serde_json::to_string(&pl).map_err(|e| error::downcast(anyhow::anyhow!(e))) + serde_json::to_string(&pl).map_err(|e| anyhow::anyhow!(e).into()) } /// JSON deserialization pub fn to_pl(json: &str) -> Result, ErrorMessages> { - serde_json::from_str(json).map_err(|e| error::downcast(anyhow::anyhow!(e))) + serde_json::from_str(json).map_err(|e| anyhow::anyhow!(e).into()) } /// JSON serialization pub fn from_rq(rq: ast::rq::Query) -> Result { - serde_json::to_string(&rq).map_err(|e| error::downcast(anyhow::anyhow!(e))) + serde_json::to_string(&rq).map_err(|e| anyhow::anyhow!(e).into()) } /// JSON deserialization pub fn to_rq(json: &str) -> Result { - serde_json::from_str(json).map_err(|e| error::downcast(anyhow::anyhow!(e))) + serde_json::from_str(json).map_err(|e| anyhow::anyhow!(e).into()) } } From 7281e34a5c7661f905caa8f2500b5f811e56af6a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 24 Feb 2023 23:04:43 -0800 Subject: [PATCH 065/184] web: Attempt to default to the SQL view in playground (#1939) web: Default to the SQL view in playground --- playground/src/examples.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/src/examples.js b/playground/src/examples.js index 751c1434e64a..e9955d897e75 100644 --- a/playground/src/examples.js +++ b/playground/src/examples.js @@ -1,6 +1,6 @@ const examples = { "introduction.prql": [ - "arrow", + "sql", `from invoices filter invoice_date >= @1970-01-16 derive [ # This adds columns @@ -27,7 +27,7 @@ derive db_version = s"version()" # S-string, escape hatch to SQL ], "let-table-0.prql": [ - "arrow", + "sql", `let soundtracks = ( from playlists filter name == 'TV Shows' @@ -56,7 +56,7 @@ take 10 ], "artists-0.prql": [ - "arrow", + "sql", `from tracks select [album_id, name, unit_price] sort [-unit_price, name] From ed8a1c0f2b8623dc91411503a6f6516e476e7cba Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 26 Feb 2023 10:02:00 -0800 Subject: [PATCH 066/184] feat: Add a `--format=yaml` option to `prqlc parse` (#1962) --- prql-compiler/prqlc/src/cli.rs | 93 ++++++++++++++++++++++++++++---- prql-compiler/prqlc/src/watch.rs | 2 +- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index 06c2361b9c52..9bac892e1c28 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -14,6 +14,7 @@ use prql_compiler::{downcast, Options}; use crate::watch; +/// Entrypoint called by [main::main] pub fn main() -> color_eyre::eyre::Result<()> { env_logger::builder().format_timestamp(None).init(); color_eyre::install()?; @@ -27,7 +28,7 @@ pub fn main() -> color_eyre::eyre::Result<()> { Ok(()) } -#[derive(Parser)] +#[derive(Parser, Debug)] #[clap(name = env!("CARGO_PKG_NAME"), about, version)] pub enum Cli { /// Parse PL AST @@ -53,13 +54,26 @@ pub enum Cli { Watch(watch::WatchCommand), } -#[derive(clap::Args, Default)] +// TODO: Should this be named `IoArgs`? IIUC it's just the args; its parent +// represents the Command. I struggled mapping this to clap docs for a while. +#[derive(clap::Args, Default, Debug)] pub struct CommandIO { #[clap(value_parser, default_value = "-")] input: Input, #[clap(value_parser, default_value = "-")] output: Output, + + // TODO: This should be only on some commands, is there an elegant way of + // doing that in Clap without lots of duplication? + #[arg(value_enum, long)] + format: Option, +} + +#[derive(clap::ValueEnum, Clone, Debug)] +enum Format { + Json, + Yaml, } fn is_stdin(input: &Input) -> bool { @@ -67,6 +81,7 @@ fn is_stdin(input: &Input) -> bool { } impl Cli { + /// Entrypoint called by [`main`] pub fn run(&mut self) -> Result<()> { if let Cli::Watch(command) = self { return watch::run(command); @@ -94,13 +109,13 @@ impl Cli { } fn execute(&self, source: &str) -> Result> { - // TODO: there's some repetiton here around converting strings to bytes; - // we could possibly extract that, but not sure it would neatly . Ok(match self { - Cli::Parse(_) => { + Cli::Parse(args) => { let ast = prql_to_pl(source)?; - - serde_yaml::to_string(&ast)?.into_bytes() + match args.format { + Some(Format::Json) | None => serde_json::to_string_pretty(&ast)?.into_bytes(), + Some(Format::Yaml) => serde_yaml::to_string(&ast)?.into_bytes(), + } } Cli::Format(_) => prql_to_pl(source).and_then(pl_to_prql)?.as_bytes().to_vec(), Cli::Debug(_) => { @@ -118,6 +133,9 @@ impl Cli { .concat() } Cli::Annotate(_) => { + // TODO: potentially if there is code performing a role beyond + // presentation, it should be a library function; and we could + // promote it to the `prql-compiler` crate. let stmts = prql_to_pl(source)?; // resolve @@ -128,12 +146,16 @@ impl Cli { // combine with source combine_prql_and_frames(source, frames).as_bytes().to_vec() } - Cli::Resolve(_) => { + Cli::Resolve(args) => { let ast = prql_to_pl(source)?; let ir = semantic::resolve(ast)?; - - serde_json::to_string_pretty(&ir)?.into_bytes() + match args.format { + Some(Format::Json) | None => serde_json::to_string_pretty(&ir)?.into_bytes(), + Some(Format::Yaml) => anyhow::bail!("YAML output is not yet supported for PL"), + // Some(Format::Yaml) => serde_yaml::to_string(&ir)?.into_bytes(), + } } + // TODO: Allow passing the `Options` to the CLI; map those through. Cli::Compile(_) => compile(source, &Options::default())?.as_bytes().to_vec(), Cli::Watch(_) => unreachable!(), }) @@ -268,7 +290,6 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag // Check we get an error on a bad input let input = "asdf"; let result = Cli::execute(&Cli::Compile(CommandIO::default()), input); - assert!(result.is_err()); assert_display_snapshot!(result.unwrap_err(), @r###" Error: โ•ญโ”€[:1:1] @@ -279,4 +300,54 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag โ”€โ”€โ”€โ•ฏ "###); } + + #[test] + // Currently failing based on serde_yaml not being able to serialize an + // Enum of an Enum; from https://github.com/dtolnay/serde-yaml/blob/68a9e95c9fd639498c85f55b5485f446b3f8465c/tests/test_error.rs#L175 + #[should_panic] + fn resolve() { + let _output = Cli::execute( + &Cli::Resolve(CommandIO { + input: CommandIO::default().input, + output: CommandIO::default().output, + format: Some(Format::Yaml), + }), + "from x | select y", + ) + .unwrap(); + } + #[test] + fn parse() { + let output = Cli::execute( + &Cli::Parse(CommandIO { + input: CommandIO::default().input, + output: CommandIO::default().output, + format: Some(Format::Yaml), + }), + "from x | select y", + ) + .unwrap(); + + assert_display_snapshot!(String::from_utf8(output).unwrap().trim(), @r###" + - Main: + Pipeline: + exprs: + - FuncCall: + name: + Ident: + - from + args: + - Ident: + - x + named_args: {} + - FuncCall: + name: + Ident: + - select + args: + - Ident: + - y + named_args: {} + "###); + } } diff --git a/prql-compiler/prqlc/src/watch.rs b/prql-compiler/prqlc/src/watch.rs index 4084439627ba..3383592170e6 100644 --- a/prql-compiler/prqlc/src/watch.rs +++ b/prql-compiler/prqlc/src/watch.rs @@ -10,7 +10,7 @@ use walkdir::WalkDir; use crate::jinja; -#[derive(Parser)] +#[derive(Parser, Debug)] pub struct WatchCommand { /// Directory or file to watch for changes pub path: OsString, From 84a74e2862054ea61c99ffa12f06191161d47621 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 26 Feb 2023 13:32:00 -0800 Subject: [PATCH 067/184] refactor: Refactor CLI arg handling (#1963) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: Add a `--format=yaml` option to `prqlc parse` * refactor: Refactor CLI arg handling Based of #1912 * Update prql-compiler/prqlc/src/cli.rs Co-authored-by: Aljaลพ Mur Erลพen * . --------- Co-authored-by: Aljaลพ Mur Erลพen --- prql-compiler/prqlc/src/cli.rs | 177 +++++++++++++++++-------------- prql-compiler/prqlc/src/watch.rs | 6 +- 2 files changed, 100 insertions(+), 83 deletions(-) diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index 9bac892e1c28..c8f03ec9d9e8 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -1,6 +1,6 @@ use anyhow::Result; use ariadne::Source; -use clap::Parser; +use clap::{Parser, Subcommand}; use clio::{Input, Output}; use itertools::Itertools; use std::io::{Read, Write}; @@ -14,13 +14,13 @@ use prql_compiler::{downcast, Options}; use crate::watch; -/// Entrypoint called by [main::main] +/// Entrypoint called by [crate::main] pub fn main() -> color_eyre::eyre::Result<()> { env_logger::builder().format_timestamp(None).init(); color_eyre::install()?; let mut cli = Cli::parse(); - if let Err(error) = cli.run() { + if let Err(error) = cli.command.run() { eprintln!("{error}"); exit(1) } @@ -28,36 +28,47 @@ pub fn main() -> color_eyre::eyre::Result<()> { Ok(()) } -#[derive(Parser, Debug)] +#[derive(Parser, Debug, Clone)] +struct Cli { + #[command(subcommand)] + command: Command, +} + +#[derive(Subcommand, Debug, Clone)] #[clap(name = env!("CARGO_PKG_NAME"), about, version)] -pub enum Cli { - /// Parse PL AST - Parse(CommandIO), +enum Command { + /// Parse into PL AST + Parse { + #[clap(value_parser, default_value = "-")] + input: Input, + #[clap(value_parser, default_value = "-")] + output: Output, + #[arg(value_enum, long)] + format: Option, + }, /// Parse & generate PRQL code back #[clap(name = "fmt")] - Format(CommandIO), + Format(IoArgs), /// Parse, resolve & combine source with comments annotating relation type - Annotate(CommandIO), + Annotate(IoArgs), /// Parse & resolve, but don't lower into RQ - Debug(CommandIO), + Debug(IoArgs), /// Parse, resolve & lower into RQ - Resolve(CommandIO), + Resolve(IoArgs), /// Parse, resolve, lower into RQ & compile to SQL - Compile(CommandIO), + Compile(IoArgs), /// Watch a directory and compile .prql files to .sql files - Watch(watch::WatchCommand), + Watch(watch::WatchArgs), } -// TODO: Should this be named `IoArgs`? IIUC it's just the args; its parent -// represents the Command. I struggled mapping this to clap docs for a while. -#[derive(clap::Args, Default, Debug)] -pub struct CommandIO { +#[derive(clap::Args, Default, Debug, Clone)] +pub struct IoArgs { #[clap(value_parser, default_value = "-")] input: Input, @@ -80,10 +91,10 @@ fn is_stdin(input: &Input) -> bool { input.path() == "-" } -impl Cli { +impl Command { /// Entrypoint called by [`main`] pub fn run(&mut self) -> Result<()> { - if let Cli::Watch(command) = self { + if let Command::Watch(command) = self { return watch::run(command); }; @@ -110,15 +121,15 @@ impl Cli { fn execute(&self, source: &str) -> Result> { Ok(match self { - Cli::Parse(args) => { + Command::Parse { format, .. } => { let ast = prql_to_pl(source)?; - match args.format { + match format { Some(Format::Json) | None => serde_json::to_string_pretty(&ast)?.into_bytes(), Some(Format::Yaml) => serde_yaml::to_string(&ast)?.into_bytes(), } } - Cli::Format(_) => prql_to_pl(source).and_then(pl_to_prql)?.as_bytes().to_vec(), - Cli::Debug(_) => { + Command::Format(_) => prql_to_pl(source).and_then(pl_to_prql)?.as_bytes().to_vec(), + Command::Debug(_) => { let stmts = prql_to_pl(source)?; let (stmts, context) = semantic::resolve_only(stmts, None)?; @@ -132,7 +143,7 @@ impl Cli { ] .concat() } - Cli::Annotate(_) => { + Command::Annotate(_) => { // TODO: potentially if there is code performing a role beyond // presentation, it should be a library function; and we could // promote it to the `prql-compiler` crate. @@ -146,50 +157,55 @@ impl Cli { // combine with source combine_prql_and_frames(source, frames).as_bytes().to_vec() } - Cli::Resolve(args) => { + Command::Resolve(_) => { + // We can't currently have `--format=yaml` here, because + // serde_yaml is unable to serialize an Enum of an Enum; from + // https://github.com/dtolnay/serde-yaml/blob/68a9e95c9fd639498c85f55b5485f446b3f8465c/tests/test_error.rs#L175 let ast = prql_to_pl(source)?; let ir = semantic::resolve(ast)?; - match args.format { - Some(Format::Json) | None => serde_json::to_string_pretty(&ir)?.into_bytes(), - Some(Format::Yaml) => anyhow::bail!("YAML output is not yet supported for PL"), - // Some(Format::Yaml) => serde_yaml::to_string(&ir)?.into_bytes(), - } + serde_json::to_string_pretty(&ir)?.into_bytes() } // TODO: Allow passing the `Options` to the CLI; map those through. - Cli::Compile(_) => compile(source, &Options::default())?.as_bytes().to_vec(), - Cli::Watch(_) => unreachable!(), + // We already do this in Watch. + Command::Compile(_) => compile(source, &Options::default())?.as_bytes().to_vec(), + Command::Watch(_) => unreachable!(), }) } fn read_input(&mut self) -> Result<(String, String)> { - use Cli::*; - match self { - Parse(io) | Format(io) | Debug(io) | Annotate(io) | Resolve(io) | Compile(io) => { - // Don't wait without a prompt when running `prql-compiler compile` โ€” - // it's confusing whether it's waiting for input or not. This - // offers the prompt. - if is_stdin(&io.input) && atty::is(atty::Stream::Stdin) { - println!("Enter PRQL, then ctrl-d:"); - println!(); - } - - let mut source = String::new(); - io.input.read_to_string(&mut source)?; - let source_id = (*io.input.path()).to_str().unwrap().to_string(); - Ok((source, source_id)) - } - Cli::Watch(_) => unreachable!(), + // TODO: possibly this should be called by the relevant subcommands + // passing in `input`, rather than matching on them and grabbing `input` + // from `self`. + use Command::*; + let mut input = match self { + Parse { input, .. } => input.clone(), + Format(io) | Debug(io) | Annotate(io) | Resolve(io) | Compile(io) => io.input.clone(), + Watch(_) => unreachable!(), + }; + // Don't wait without a prompt when running `prqlc compile` โ€” + // it's confusing whether it's waiting for input or not. This + // offers the prompt. + if is_stdin(&input) && atty::is(atty::Stream::Stdin) { + println!("Enter PRQL, then ctrl-d:"); + println!(); } + + let mut source = String::new(); + (input).read_to_string(&mut source)?; + let source_id = (input.path()).to_str().unwrap().to_string(); + Ok((source, source_id)) } fn write_output(&mut self, data: &[u8]) -> std::io::Result<()> { - use Cli::*; - match self { - Parse(io) | Format(io) | Debug(io) | Annotate(io) | Resolve(io) | Compile(io) => { - io.output.write_all(data) + use Command::*; + let mut output = match self { + Parse { output, .. } => output.to_owned(), + Format(io) | Debug(io) | Annotate(io) | Resolve(io) | Compile(io) => { + io.output.to_owned() } - Cli::Watch(_) => unreachable!(), - } + Watch(_) => unreachable!(), + }; + output.write_all(data) } } @@ -227,12 +243,28 @@ fn combine_prql_and_frames(source: &str, frames: Vec<(Span, Frame)>) -> String { mod tests { use insta::{assert_display_snapshot, assert_snapshot}; + // TODO: would be good to test the basic CLI interface โ€” i.e. snapshotting this: + + // $ prqlc parse --help + // + // Parse PL AST + // + // Usage: prqlc parse [OPTIONS] [INPUT] [OUTPUT] + // + // Arguments: + // [INPUT] [default: -] + // [OUTPUT] [default: -] + // + // Options: + // --format [possible values: json, yaml] + // -h, --help Print help + use super::*; #[test] fn layouts() { - let output = Cli::execute( - &Cli::Annotate(CommandIO::default()), + let output = Command::execute( + &Command::Annotate(IoArgs::default()), r#" from initial_table select [f = first_name, l = last_name, gender] @@ -256,8 +288,8 @@ sort full #[test] fn format() { - let output = Cli::execute( - &Cli::Format(CommandIO::default()), + let output = Command::execute( + &Command::Format(IoArgs::default()), r#" from table.subdivision derive `ลพelva_means_turtle` = (`column with spaces` + 1) * 3 @@ -289,7 +321,7 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag fn compile() { // Check we get an error on a bad input let input = "asdf"; - let result = Cli::execute(&Cli::Compile(CommandIO::default()), input); + let result = Command::execute(&Command::Compile(IoArgs::default()), input); assert_display_snapshot!(result.unwrap_err(), @r###" Error: โ•ญโ”€[:1:1] @@ -301,29 +333,14 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag "###); } - #[test] - // Currently failing based on serde_yaml not being able to serialize an - // Enum of an Enum; from https://github.com/dtolnay/serde-yaml/blob/68a9e95c9fd639498c85f55b5485f446b3f8465c/tests/test_error.rs#L175 - #[should_panic] - fn resolve() { - let _output = Cli::execute( - &Cli::Resolve(CommandIO { - input: CommandIO::default().input, - output: CommandIO::default().output, - format: Some(Format::Yaml), - }), - "from x | select y", - ) - .unwrap(); - } #[test] fn parse() { - let output = Cli::execute( - &Cli::Parse(CommandIO { - input: CommandIO::default().input, - output: CommandIO::default().output, + let output = Command::execute( + &Command::Parse { + input: IoArgs::default().input, + output: IoArgs::default().output, format: Some(Format::Yaml), - }), + }, "from x | select y", ) .unwrap(); diff --git a/prql-compiler/prqlc/src/watch.rs b/prql-compiler/prqlc/src/watch.rs index 3383592170e6..a57322e116af 100644 --- a/prql-compiler/prqlc/src/watch.rs +++ b/prql-compiler/prqlc/src/watch.rs @@ -10,8 +10,8 @@ use walkdir::WalkDir; use crate::jinja; -#[derive(Parser, Debug)] -pub struct WatchCommand { +#[derive(Parser, Debug, Clone)] +pub struct WatchArgs { /// Directory or file to watch for changes pub path: OsString, @@ -22,7 +22,7 @@ pub struct WatchCommand { pub no_signature: bool, } -pub fn run(command: &mut WatchCommand) -> Result<()> { +pub fn run(command: &mut WatchArgs) -> Result<()> { let opt = prql_compiler::Options { format: !command.no_format, target: prql_compiler::Target::Sql(None), From 002b10654da515c90df946c102e3ad535021e125 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 26 Feb 2023 13:39:01 -0800 Subject: [PATCH 068/184] chore: Add changelog for `--format` (#1968) --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 47a1ba3bf508..1a24f5f12bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ **Features**: - `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) +- Add a `--format` option to `prqlc parse` which can return the AST in YAML + (@max-sixty, #1962) **Fixes**: From 0e625be63ed983044f1376e476dd51ce8069d5a7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Feb 2023 11:06:07 -0800 Subject: [PATCH 069/184] chore: pre-commit autoupdate (#1975) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/crate-ci/typos: typos-dict-v0.9.16 โ†’ v1.13.12](https://github.com/crate-ci/typos/compare/typos-dict-v0.9.16...v1.13.12) - [github.com/charliermarsh/ruff-pre-commit: v0.0.248 โ†’ v0.0.252](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.248...v0.0.252) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5f4006248d49..5c1f89d13d77 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,7 +8,7 @@ repos: - id: check-yaml - id: mixed-line-ending - repo: https://github.com/crate-ci/typos - rev: typos-dict-v0.9.16 + rev: v1.13.12 hooks: - id: typos # https://github.com/crate-ci/typos/issues/347 @@ -21,7 +21,7 @@ repos: - prettier - prettier-plugin-go-template - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.248 + rev: v0.0.252 hooks: - id: ruff - repo: https://github.com/psf/black From ced220bf28c2a1a6ef0c012ac0422a7923ed543e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Mon, 27 Feb 2023 21:21:42 +0100 Subject: [PATCH 070/184] feat: rewrite parser with chumsky (#1818) --- .github/workflows/test-all.yaml | 5 + .github/workflows/test-js.yaml | 4 + CHANGELOG.md | 15 + Cargo.lock | 39 +- book/src/language-features/dates-and-times.md | 2 +- book/src/language-features/f-strings.md | 3 + book/src/language-features/s-strings.md | 7 +- book/src/language-features/strings.md | 16 +- book/src/syntax.md | 39 +- .../language-features/dates-and-times-2.prql | 2 +- .../prql/language-features/strings-5.prql | 2 + book/tests/prql/syntax-16.prql | 3 + ...uage-features__dates-and-times-2.prql.snap | 5 +- ...t__@language-features__strings-5.prql.snap | 11 + .../snapshots/snapshot__@syntax-16.prql.snap | 13 + ...uage-features__dates-and-times-2.prql.snap | 4 +- ...ql__language-features__strings-5.prql.snap | 10 + ...snapshot__tests__prql__syntax-16.prql.snap | 13 + ..._tests__prql__transforms__sort-2.prql.snap | 2 +- prql-compiler/Cargo.toml | 8 +- prql-compiler/prqlc/src/cli.rs | 2 - prql-compiler/src/ast/pl/expr.rs | 16 +- prql-compiler/src/error.rs | 97 +- prql-compiler/src/parser/chumsky.rs | 80 - prql-compiler/src/parser/expr.rs | 305 ++++ prql-compiler/src/parser/interpolation.rs | 55 + prql-compiler/src/parser/lexer.rs | 399 ++++ prql-compiler/src/parser/mod.rs | 1616 +++++++---------- prql-compiler/src/parser/prql.pest | 150 -- ...r__parser__test__pipeline_parse_tree.snap} | 17 +- prql-compiler/src/parser/stmt.rs | 154 ++ prql-compiler/src/semantic/resolver.rs | 5 + ...tic__resolver__test__functions_nested.snap | 70 +- prql-compiler/src/test.rs | 22 +- 34 files changed, 1871 insertions(+), 1320 deletions(-) create mode 100644 book/tests/prql/language-features/strings-5.prql create mode 100644 book/tests/prql/syntax-16.prql create mode 100644 book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__@syntax-16.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap delete mode 100644 prql-compiler/src/parser/chumsky.rs create mode 100644 prql-compiler/src/parser/expr.rs create mode 100644 prql-compiler/src/parser/interpolation.rs create mode 100644 prql-compiler/src/parser/lexer.rs delete mode 100644 prql-compiler/src/parser/prql.pest rename prql-compiler/src/parser/snapshots/{prql_compiler__parser__test__parse_pipeline_parse_tree.snap => prql_compiler__parser__test__pipeline_parse_tree.snap} (85%) create mode 100644 prql-compiler/src/parser/stmt.rs diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 34ea805c7de4..0582d00a4983 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -27,6 +27,11 @@ jobs: matrix: os: [ubuntu-latest, windows-latest, macos-latest] target_option: ["", --target=wasm32-unknown-unknown] + + # Combination of macos and wasm32 has a problem with crate psm, a dependency of chumsky + exclude: + - os: macos-latest + target_option: --target=wasm32-unknown-unknown uses: ./.github/workflows/test-rust.yaml with: os: ${{ matrix.os }} diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index dd2e4892b4fb..baa88eeda2b2 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -17,6 +17,10 @@ jobs: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] + + # Combination of macos and wasm32 has a problem with crate psm, a dependency of chumsky + exclude: + - os: macos-latest steps: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a24f5f12bda..c60fe61f27a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,19 @@ **Features**: - `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) +- Convert parser from pest to Chumsky (@aljazerzen, #1818) + - Improved error messages, and the potential to make even better in the + future. Many of these improvements come from error recovery. + - String escapes (`\n \t`). + - Raw strings that don't escape backslashes. + - String interpolations can only contain identifiers and not any expression. + - Operator associativity has been changed from right-to-left to left-to-right + to be more similar to other conventional languages. + - `and` now has a higher precedence than `or` (of same reason as the previous + point). + - Dates, times and timestamps have a stricter parsing rules. + - `let`, `func`, `prql`, `switch` are now treated as keywords. + - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) @@ -15,6 +28,8 @@ **Documentation**: +- Operator precedence (@aljazerzen, #1818) + **Web**: **Integrations**: diff --git a/Cargo.lock b/Cargo.lock index 013e31762293..e23cb065dab2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -451,6 +451,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4d619fba796986dd538d82660b76e0b9756c6e19b2e4d4559ba5a57f9f00810" dependencies = [ "hashbrown 0.12.3", + "stacker", ] [[package]] @@ -500,7 +501,7 @@ checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3" dependencies = [ "bitflags", "clap_derive", - "clap_lex 0.3.1", + "clap_lex 0.3.2", "is-terminal", "once_cell", "strsim", @@ -510,9 +511,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.1.2" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd125be87bf4c255ebc50de0b7f4d2a6201e8ac3dc86e39c0ad081dc5e7236fe" +checksum = "0012995dc3a54314f4710f5631d74767e73c534b8757221708303e48eef7a19b" dependencies = [ "clap 4.1.6", ] @@ -541,9 +542,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" dependencies = [ "os_str_bytes", ] @@ -1332,9 +1333,9 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" dependencies = [ "hermit-abi 0.3.1", "io-lifetimes", @@ -2132,8 +2133,6 @@ dependencies = [ "lazy_static", "log", "once_cell", - "pest", - "pest_derive", "postgres", "pretty_assertions", "regex", @@ -2215,6 +2214,15 @@ dependencies = [ "walkdir", ] +[[package]] +name = "psm" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5787f7cda34e3033a72192c018bc5883100330f362ef279a8cbccfce8bb4e874" +dependencies = [ + "cc", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -2720,6 +2728,19 @@ dependencies = [ "serde", ] +[[package]] +name = "stacker" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c886bd4480155fd3ef527d45e9ac8dd7118a898a46530b7b94c3e21866259fce" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "winapi", +] + [[package]] name = "static_assertions" version = "1.1.0" diff --git a/book/src/language-features/dates-and-times.md b/book/src/language-features/dates-and-times.md index 55d26e009a67..529eda6a6521 100644 --- a/book/src/language-features/dates-and-times.md +++ b/book/src/language-features/dates-and-times.md @@ -41,7 +41,7 @@ ISO8601 datetime format, which uses `T` to separate date & time. ```prql from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 +derive first_prql_commit = @2020-01-01T13:19:55-08:00 ``` ## Intervals diff --git a/book/src/language-features/f-strings.md b/book/src/language-features/f-strings.md index 1e1ada7cae71..24df646f9c8e 100644 --- a/book/src/language-features/f-strings.md +++ b/book/src/language-features/f-strings.md @@ -16,6 +16,9 @@ from web select url = f"http{tls}://www.{domain}.{tld}/{page}" ``` +Note that interpolations can only contain plain variable names and not whole +expression like Python. + ## Roadmap In the future, f-strings may incorporate string formatting such as datetimes, diff --git a/book/src/language-features/s-strings.md b/book/src/language-features/s-strings.md index fe2d133ef001..ed70b1923dbe 100644 --- a/book/src/language-features/s-strings.md +++ b/book/src/language-features/s-strings.md @@ -38,8 +38,11 @@ join s=salaries side:left [ For those who have used Python, s-strings are similar to Python's f-strings, but the result is SQL code, rather than a string literal. For example, a Python -f-string of `f"average{col}"` would produce `"average(salary)"`, with quotes; -while in PRQL, `s"average{col}"` produces `average(salary)`, without quotes. +f-string of `f"average({col})"` would produce `"average(salary)"`, with quotes; +while in PRQL, `s"average({col})"` produces `average(salary)`, without quotes. + +Note that interpolations can only contain plain variable names and not whole +expression like Python. We can also use s-strings to produce a full table: diff --git a/book/src/language-features/strings.md b/book/src/language-features/strings.md index db4b9d9e07db..922c5cac5e76 100644 --- a/book/src/language-features/strings.md +++ b/book/src/language-features/strings.md @@ -13,7 +13,7 @@ select x = 'hello world' ``` To quote a string containing quotes, either use the "other" type of quote, or -use three-or-more quotes, and close with the same number. +use 3, 4, 5 or 6 quotes, and close with the same number. ```prql from my_table @@ -30,7 +30,15 @@ from my_table select x = """""I said """hello world"""!""""" ``` -## F-strings and s-strings +Strings can also contain any escape defined by +[JSON standard](https://www.ecma-international.org/publications-and-standards/standards/ecma-404/). + +```prql +from my_table +select x = "\t\tline ends here\n \\ " +``` + +## F-Strings and S-Strings These special case strings can be used to: @@ -40,10 +48,6 @@ values [S-strings](./s-strings.md) - Insert SQL statements directly into the query. Use when PRQL doesn't have an equivalent facility. -```admonish note -Currently PRQL does not adjust escape characters. -``` - ```admonish warning Currently PRQL allows multiline strings with either a single character or multiple character quotes. This may change for strings using a single character diff --git a/book/src/syntax.md b/book/src/syntax.md index b23537228f4c..4c7ca169eccc 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -166,7 +166,24 @@ sort (-distance) sort [-distance] ``` -## Inner transforms +For a more formal definition, refer to this precedence table. Because function +call has the lowest precedence, nested function calls or arguments that start or +end with an operator require parenthesis. + +| Group | Operators | Precedence | Associativity | +| -------------- | ----------------- | ---------- | ------------- | +| identifier dot | `.` | 1 | | +| unary | `- + ! ==` | 2 | | +| range | `..` | 3 | | +| mul | `* / %` | 4 | left-to-right | +| add | `+ -` | 5 | left-to-right | +| compare | `== != <= >= < >` | 6 | left-to-right | +| coalesce | `??` | 7 | left-to-right | +| and | `and` | 8 | left-to-right | +| or | `or` | 9 | left-to-right | +| function call | | 10 | | + +## Inner Transforms Parentheses are also used for transforms (such as `group` and `window`) that pass their result to an "inner transform". The example below applies the @@ -261,3 +278,23 @@ select [ big = 5_000_000, ] ``` + +## Keywords + +At the moment, PRQL uses only four keywords: + +- `prql` +- `let` +- `func` +- `switch` + +To use these names as columns or relations, use backticks: `` `switch` ``. + +It may seem that transforms are also keywords, but they are normal function +within std namespace: + +```prql +std.from my_table +std.select [from = my_table.a, take = my_table.b] +std.take 3 +``` diff --git a/book/tests/prql/language-features/dates-and-times-2.prql b/book/tests/prql/language-features/dates-and-times-2.prql index 12687310b181..9efc7883716b 100644 --- a/book/tests/prql/language-features/dates-and-times-2.prql +++ b/book/tests/prql/language-features/dates-and-times-2.prql @@ -1,2 +1,2 @@ from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 +derive first_prql_commit = @2020-01-01T13:19:55-08:00 diff --git a/book/tests/prql/language-features/strings-5.prql b/book/tests/prql/language-features/strings-5.prql new file mode 100644 index 000000000000..491c9f04bdd1 --- /dev/null +++ b/book/tests/prql/language-features/strings-5.prql @@ -0,0 +1,2 @@ +from my_table +select x = "\t\tline ends here\n \\ " diff --git a/book/tests/prql/syntax-16.prql b/book/tests/prql/syntax-16.prql new file mode 100644 index 000000000000..029a0ea82464 --- /dev/null +++ b/book/tests/prql/syntax-16.prql @@ -0,0 +1,3 @@ +std.from my_table +std.select [from = my_table.a, take = my_table.b] +std.take 3 diff --git a/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap index c7886ddfa16a..55668e17d93e 100644 --- a/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap @@ -1,10 +1,11 @@ --- source: book/tests/snapshot.rs -expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-0800\n" +expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-08:00\n" input_file: book/tests/prql/language-features/dates-and-times-2.prql --- SELECT *, - TIMESTAMP '2020-01-01T13:19:55-0800' AS first_prql_commit + TIMESTAMP '2020-01-01T13:19:55-08:00' AS first_prql_commit FROM commits + diff --git a/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap b/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap new file mode 100644 index 000000000000..1e5ef589937a --- /dev/null +++ b/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\\t\\tline ends here\\n \\\\ \"\n" +input_file: book/tests/prql/language-features/strings-5.prql +--- +SELECT + ' line ends here + \ ' AS x +FROM + my_table + diff --git a/book/tests/snapshots/snapshot__@syntax-16.prql.snap b/book/tests/snapshots/snapshot__@syntax-16.prql.snap new file mode 100644 index 000000000000..e62eb76cf856 --- /dev/null +++ b/book/tests/snapshots/snapshot__@syntax-16.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +input_file: book/tests/prql/syntax-16.prql +--- +SELECT + a AS "from", + b AS take +FROM + my_table +LIMIT + 3 + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap index 1507a39b0252..a2f42142ebb6 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-0800\n" +expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-08:00\n" --- from commits -derive first_prql_commit = @2020-01-01T13:19:55-0800 +derive first_prql_commit = @2020-01-01T13:19:55-08:00 diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap new file mode 100644 index 000000000000..4a0b8ddabd77 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "from my_table\nselect x = \"\\t\\tline ends here\\n \\\\ \"\n" +--- +from my_table +select x = " line ends here + \ " + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap new file mode 100644 index 000000000000..ddc2d6ddb49a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +--- +std.from my_table +std.select [ + from = my_table.a, + take = my_table.b, +] +std.take 3 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap index 23c2050900c8..a7ddb76e2ecc 100644 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap @@ -6,7 +6,7 @@ from employees sort [ age, -tenure, - salary, + +salary, ] diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index 9323ff5f59d3..3faa6d29a725 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -15,17 +15,13 @@ metadata.msrv = "1.65.0" [dependencies] anyhow = {version = "1.0.57", features = ["backtrace"]} ariadne = "0.1.5" -# We don't include the `spill-stack` feature, since it causes builds in GHA to -# fail. If that no longer happens, we can re-enable it. -chumsky = {version = "0.9.0", features = ["ahash", "std"], default-features = false } +chumsky = "0.9.0" csv = "1.2.0" enum-as-inner = "0.5.0" itertools = "0.10.3" lazy_static = "1.4.0" log = "0.4.17" once_cell = "1.17.0" -pest = "2.5.0" -pest_derive = "2.5.0" regex = "1.7.0" semver = {version = "1.0.14", features = ["serde"]} serde = {version = "1.0.137", features = ["derive"]} @@ -41,7 +37,7 @@ insta = {version = "1.28", features = ["colors", "glob", "yaml"]} # For integration tests [target.'cfg(not(target_family="wasm"))'.dev-dependencies] -chrono = "0.4" +chrono = {version = "0.4", features = [], default-features = false } criterion = "0.4.0" postgres = "0.19.3" pretty_assertions = "1.3.0" diff --git a/prql-compiler/prqlc/src/cli.rs b/prql-compiler/prqlc/src/cli.rs index c8f03ec9d9e8..41db7dc8825a 100644 --- a/prql-compiler/prqlc/src/cli.rs +++ b/prql-compiler/prqlc/src/cli.rs @@ -356,7 +356,6 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag args: - Ident: - x - named_args: {} - FuncCall: name: Ident: @@ -364,7 +363,6 @@ group a_column (take 10 | sort b_column | derive [the_number = rank, last = lag args: - Ident: - y - named_args: {} "###); } } diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index e6792d7d8f10..cfba08fc4934 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -89,7 +89,16 @@ impl ExprKind { } #[derive( - Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, strum::Display, strum::EnumString, + Debug, + PartialEq, + Eq, + Clone, + Copy, + Hash, + Serialize, + Deserialize, + strum::Display, + strum::EnumString, )] pub enum BinOp { #[strum(to_string = "*")] @@ -122,12 +131,12 @@ pub enum BinOp { Coalesce, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize, strum::EnumString)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Serialize, Deserialize, strum::EnumString)] pub enum UnOp { #[strum(to_string = "-")] Neg, #[strum(to_string = "+")] - Add, + Add, // TODO: rename to Pos #[strum(to_string = "!")] Not, #[strum(to_string = "==")] @@ -142,6 +151,7 @@ pub struct ListItem(pub Expr); pub struct FuncCall { pub name: Box, pub args: Vec, + #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub named_args: HashMap, } diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index 4d0151b3ff6e..92f3f3492210 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -6,7 +6,6 @@ use std::error::Error as StdError; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::{Add, Range}; -use crate::parser::PestError; use crate::utils::IntoOnly; #[derive(Clone, PartialEq, Eq, Copy, Serialize, Deserialize)] @@ -22,6 +21,9 @@ pub struct Error { pub help: Option, } +#[derive(Debug, Clone)] +pub struct Errors(pub Vec); + /// Location within the source file. /// Tuples contain: /// - line number (0-based), @@ -109,6 +111,9 @@ impl Display for ErrorMessage { // Needed for anyhow impl StdError for Error {} +// Needed for anyhow +impl StdError for Errors {} + // Needed for StdError impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -116,6 +121,13 @@ impl Display for Error { } } +// Needed for StdError +impl Display for Errors { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Debug::fmt(&self, f) + } +} + #[derive(Debug, Clone, Serialize)] pub struct ErrorMessages { pub inner: Vec, @@ -146,6 +158,19 @@ pub fn downcast(error: anyhow::Error) -> ErrorMessages { Err(error) => error, }; + let error = match error.downcast::() { + Ok(messages) => { + return ErrorMessages { + inner: messages + .0 + .into_iter() + .flat_map(|e| downcast(e.into()).inner) + .collect(), + } + } + Err(error) => error, + }; + let reason = match error.downcast::() { Ok(error) => { span = error.span; @@ -154,21 +179,8 @@ pub fn downcast(error: anyhow::Error) -> ErrorMessages { error.reason.message() } Err(error) => { - match error.downcast::() { - Ok(error) => { - let range = pest::as_range(&error); - span = Some(Span { - start: range.start, - end: range.end, - }); - - pest::as_message(&error) - } - Err(error) => { - // default to basic Display - format!("{:#?}", error) - } - } + // default to basic Display + format!("{:#?}", error) } }; @@ -267,59 +279,6 @@ impl Reason { } } -mod pest { - use pest::error::{ErrorVariant, InputLocation}; - use std::ops::Range; - - use crate::parser::{PestError, PestRule}; - - pub fn as_range(error: &PestError) -> Range { - match error.location { - InputLocation::Pos(r) => r..r + 1, - InputLocation::Span(r) => r.0..r.1, - } - } - - pub fn as_message(error: &PestError) -> String { - match error.variant { - ErrorVariant::ParsingError { - ref positives, - ref negatives, - } => parsing_error_message(positives, negatives), - ErrorVariant::CustomError { ref message } => message.clone(), - } - } - - fn parsing_error_message(positives: &[PestRule], negatives: &[PestRule]) -> String { - match (negatives.is_empty(), positives.is_empty()) { - (false, false) => format!( - "unexpected {}; expected {}", - enumerate(negatives), - enumerate(positives) - ), - (false, true) => format!("unexpected {}", enumerate(negatives)), - (true, false) => format!("expected {}", enumerate(positives)), - (true, true) => "unknown parsing error".to_owned(), - } - } - - fn enumerate(rules: &[PestRule]) -> String { - match rules.len() { - 1 => format!("{:?}", rules[0]), - 2 => format!("{:?} or {:?}", rules[0], rules[1]), - l => { - let separated = rules - .iter() - .take(l - 1) - .map(|x| format!("{:?}", x)) - .collect::>() - .join(", "); - format!("{}, or {:?}", separated, rules[l - 1]) - } - } - } -} - impl From for Range { fn from(a: Span) -> Self { a.start..a.end diff --git a/prql-compiler/src/parser/chumsky.rs b/prql-compiler/src/parser/chumsky.rs deleted file mode 100644 index 95c031453c5e..000000000000 --- a/prql-compiler/src/parser/chumsky.rs +++ /dev/null @@ -1,80 +0,0 @@ -#![allow(dead_code)] - -use chumsky::prelude::*; - -use crate::ast::pl::*; - -fn str(chars: &str) -> impl Parser> + '_ { - just(chars).to(()) -} - -fn operator() -> impl Parser> { - operator_binary().to(()).or(operator_unary().to(())) -} - -fn operator_binary() -> impl Parser> { - operator_mul() - .or(operator_add()) - .or(operator_compare()) - .or(operator_logical()) - .or(operator_coalesce()) -} -fn operator_unary() -> impl Parser> { - just('-') - .to(UnOp::Neg) - .or(just('+').to(UnOp::Add)) - .or(just('!').to(UnOp::Not)) - .or(str("==").to(UnOp::EqSelf)) -} -fn operator_mul() -> impl Parser> { - (just('*').to(BinOp::Mul)) - .or(just('/').to(BinOp::Div)) - .or(just('%').to(BinOp::Mod)) -} -fn operator_add() -> impl Parser> { - just('+').to(BinOp::Add).or(just('-').to(BinOp::Sub)) -} -fn operator_compare() -> impl Parser> { - str("==") - .to(BinOp::Eq) - .or(str("!=").to(BinOp::Ne)) - .or(str(">=").to(BinOp::Gte)) - .or(str("<=").to(BinOp::Lte)) - .or(str(">").to(BinOp::Gt)) - .or(str("<").to(BinOp::Lt)) -} -fn operator_logical() -> impl Parser> { - (just("and").to(BinOp::Add)) - .or(just("or").to(BinOp::Or)) - .then_ignore(text::whitespace()) -} -fn operator_coalesce() -> impl Parser> { - just("??").map(|_| BinOp::Coalesce) -} - -fn ident_part() -> impl Parser> { - let plain = filter(|c: &char| c.is_ascii_alphabetic() || *c == '_' || *c == '$') - .map(Some) - .chain::, _>( - filter(|c: &char| c.is_ascii_alphanumeric() || *c == '_').repeated(), - ) - .collect(); - - let backticks = just('`') - .ignore_then(filter(|c| *c != '`').repeated()) - .then_ignore(just('`')) - .collect::(); - - plain.or(backticks) -} - -pub fn ident() -> impl Parser> { - let star = just('*').map(|c| c.to_string()); - - // TODO: !operator ~ !(keyword ~ WHITESPACE) - // we probably need combinator::Not, which has not been released yet. - - ident_part() - .chain(just('.').ignore_then(ident_part().or(star)).repeated()) - .map(Ident::from_path::) -} diff --git a/prql-compiler/src/parser/expr.rs b/prql-compiler/src/parser/expr.rs new file mode 100644 index 000000000000..ea9c2d32cbc7 --- /dev/null +++ b/prql-compiler/src/parser/expr.rs @@ -0,0 +1,305 @@ +use std::collections::HashMap; + +use chumsky::prelude::*; + +use crate::ast::pl::*; + +use super::common::*; +use super::interpolation; +use super::lexer::Token; + +pub fn expr_call() -> impl Parser> { + func_call(expr()) +} + +pub fn expr() -> impl Parser> + Clone { + recursive(|expr| { + let literal = select! { Token::Literal(lit) => ExprKind::Literal(lit) }; + + let ident_kind = ident().map(ExprKind::Ident); + + let nested_expr = pipeline(func_call(expr.clone())).boxed(); + + let list = ident_part() + .then_ignore(ctrl('=')) + .or_not() + .then(nested_expr.clone().map_with_span(into_expr)) + .map(|(alias, expr)| Expr { alias, ..expr }) + .padded_by(new_line().repeated()) + .separated_by(ctrl(',')) + .allow_trailing() + .then_ignore(new_line().repeated()) + .delimited_by(ctrl('['), ctrl(']')) + .recover_with(nested_delimiters( + Token::Control('['), + Token::Control(']'), + [ + (Token::Control('['), Token::Control(']')), + (Token::Control('('), Token::Control(')')), + ], + |_| vec![], + )) + .map(ExprKind::List) + .labelled("list"); + + let pipeline = + nested_expr + .delimited_by(ctrl('('), ctrl(')')) + .recover_with(nested_delimiters( + Token::Control('('), + Token::Control(')'), + [ + (Token::Control('['), Token::Control(']')), + (Token::Control('('), Token::Control(')')), + ], + |_| Expr::null().kind, + )); + + let interpolation = + select! { + Token::Interpolation('s', string) => (ExprKind::SString as fn(_) -> _, string), + Token::Interpolation('f', string) => (ExprKind::FString as fn(_) -> _, string), + } + .validate(|(finish, string), span: std::ops::Range, emit| { + match interpolation::parse(string, span.start + 2) { + Ok(items) => finish(items), + Err(errors) => { + for err in errors { + emit(err) + } + finish(vec![]) + } + } + }); + + let switch = keyword("switch") + .ignore_then( + func_call(expr.clone()) + .then_ignore(just(Token::Arrow)) + .then(func_call(expr)) + .map(|(condition, value)| SwitchCase { condition, value }) + .padded_by(new_line().repeated()) + .separated_by(ctrl(',')) + .allow_trailing() + .then_ignore(new_line().repeated()) + .delimited_by(ctrl('['), ctrl(']')), + ) + .map(ExprKind::Switch); + + let term = choice((literal, list, pipeline, interpolation, ident_kind, switch)) + .map_with_span(into_expr) + .boxed(); + + // Unary operators + let term = term + .clone() + .or(operator_unary() + .then(term.map(Box::new)) + .map(|(op, expr)| ExprKind::Unary { op, expr }) + .map_with_span(into_expr)) + .boxed(); + + // Ranges have five cases we need to parse: + // x..y (bounded) + // x.. (only start bound) + // x (no-op) + // ..y (only end bound) + // .. (unbounded) + #[derive(Clone)] + enum RangeCase { + NoOp(Expr), + Range(Option, Option), + } + let term = choice(( + // with start bound (first 3 cases) + term.clone() + .then(choice(( + // range and end bound + just(Token::range(true, true)) + .ignore_then(term.clone()) + .map(|x| Some(Some(x))), + // range and no end bound + select! { Token::Range { bind_left: true, .. } => Some(None) }, + // no range + empty().to(None), + ))) + .map(|(start, range)| { + if let Some(end) = range { + RangeCase::Range(Some(start), end) + } else { + RangeCase::NoOp(start) + } + }), + // only end bound + select! { Token::Range { bind_right: true, .. } => () } + .ignore_then(term) + .map(|range| RangeCase::Range(None, Some(range))), + // unbounded + select! { Token::Range { .. } => RangeCase::Range(None, None) }, + )) + .map_with_span(|case, span| match case { + RangeCase::NoOp(x) => x, + RangeCase::Range(start, end) => { + let kind = ExprKind::Range(Range { + start: start.map(Box::new), + end: end.map(Box::new), + }); + into_expr(kind, span) + } + }) + .boxed(); + + // Binary operators + let expr = term; + let expr = binary_op_parser(expr, operator_mul()); + let expr = binary_op_parser(expr, operator_add()); + let expr = binary_op_parser(expr, operator_compare()); + let expr = binary_op_parser(expr, operator_coalesce()); + let expr = binary_op_parser(expr, operator_and()); + + binary_op_parser(expr, operator_or()) + }) +} + +pub fn pipeline(expr: E) -> impl Parser> +where + E: Parser>, +{ + // expr has to be a param, because it can be either a normal expr() or + // a recursive expr called from within expr() + + new_line() + .repeated() + .ignore_then( + expr.separated_by(ctrl('|').or(new_line().repeated().at_least(1).ignored())) + .at_least(1) + .map(|mut exprs| { + if exprs.len() == 1 { + exprs.remove(0).kind + } else { + ExprKind::Pipeline(Pipeline { exprs }) + } + }), + ) + .then_ignore(new_line().repeated()) + .labelled("pipeline") +} + +fn binary_op_parser<'a, Term, Op>( + term: Term, + op: Op, +) -> impl Parser> + 'a +where + Term: Parser> + 'a, + Op: Parser> + 'a, +{ + let term = term.map_with_span(|e, s| (e, s)).boxed(); + + (term.clone()) + .then(op.then(term).repeated()) + .foldl(|left, (op, right)| { + let span = left.1.start..right.1.end; + let kind = ExprKind::Binary { + left: Box::new(left.0), + op, + right: Box::new(right.0), + }; + (into_expr(kind, span.clone()), span) + }) + .map(|(e, _)| e) + .boxed() +} + +fn func_call(expr: E) -> impl Parser> +where + E: Parser> + Clone, +{ + let func = expr.clone(); + + let named_arg = ident_part() + .map(Some) + .then_ignore(ctrl(':')) + .then(expr.clone()); + + let assign_call = + ident_part() + .then_ignore(ctrl('=')) + .then(expr.clone()) + .map(|(alias, expr)| Expr { + alias: Some(alias), + ..expr + }); + let positional_arg = assign_call.or(expr).map(|expr| (None, expr)); + + let args = named_arg.or(positional_arg).repeated(); + + func.then(args) + .validate(|(name, args), span, emit| { + if args.is_empty() { + return name.kind; + } + + let mut named_args = HashMap::new(); + let mut positional = Vec::new(); + for (name, arg) in args { + if let Some(name) = name { + if named_args.contains_key(&name) { + let err = Simple::custom(span.clone(), "argument is used multiple times"); + emit(err) + } + named_args.insert(name, arg); + } else { + positional.push(arg); + } + } + + ExprKind::FuncCall(FuncCall { + name: Box::new(name), + args: positional, + named_args, + }) + }) + .map_with_span(into_expr) + .labelled("function call") +} + +pub fn ident() -> impl Parser> { + let star = ctrl('*').to("*".to_string()); + + ident_part() + .chain(ctrl('.').ignore_then(ident_part().or(star)).repeated()) + .map(Ident::from_path::) + .labelled("identifier") +} + +fn operator_unary() -> impl Parser> { + (ctrl('+').to(UnOp::Add)) + .or(ctrl('-').to(UnOp::Neg)) + .or(ctrl('!').to(UnOp::Not)) + .or(just(Token::Eq).to(UnOp::EqSelf)) +} +fn operator_mul() -> impl Parser> { + (ctrl('*').to(BinOp::Mul)) + .or(ctrl('/').to(BinOp::Div)) + .or(ctrl('%').to(BinOp::Mod)) +} +fn operator_add() -> impl Parser> { + (ctrl('+').to(BinOp::Add)).or(ctrl('-').to(BinOp::Sub)) +} +fn operator_compare() -> impl Parser> { + (just(Token::Eq).to(BinOp::Eq)) + .or(just(Token::Ne).to(BinOp::Ne)) + .or(just(Token::Lte).to(BinOp::Lte)) + .or(just(Token::Gte).to(BinOp::Gte)) + .or(ctrl('<').to(BinOp::Lt)) + .or(ctrl('>').to(BinOp::Gt)) +} +fn operator_and() -> impl Parser> { + just(Token::And).to(BinOp::And) +} +fn operator_or() -> impl Parser> { + just(Token::Or).to(BinOp::Or) +} +fn operator_coalesce() -> impl Parser> { + just(Token::Coalesce).to(BinOp::Coalesce) +} diff --git a/prql-compiler/src/parser/interpolation.rs b/prql-compiler/src/parser/interpolation.rs new file mode 100644 index 000000000000..2b3c75f92f5a --- /dev/null +++ b/prql-compiler/src/parser/interpolation.rs @@ -0,0 +1,55 @@ +use chumsky::{error::Cheap, prelude::*}; +use itertools::Itertools; + +use crate::ast::pl::*; + +use super::{common::into_expr, lexer::*}; + +/// Parses interpolated strings +pub fn parse( + string: String, + span_offset: usize, +) -> Result, Vec>> { + let res = parser(span_offset).parse(string); + + match res { + Ok(items) => Ok(items), + Err(errors) => Err(errors + .into_iter() + .map(|err| { + Simple::expected_input_found(offset_span(err.span(), span_offset), None, None) + }) + .collect_vec()), + } +} + +fn parser(span_offset: usize) -> impl Parser, Error = Cheap> { + let expr = ident_part() + .separated_by(just('.')) + .delimited_by(just('{'), just('}')) + .map(Ident::from_path) + .map(ExprKind::Ident) + .map_with_span(move |e, s| into_expr(e, offset_span(s, span_offset))) + .map(Box::new) + .map(InterpolateItem::Expr); + + let escape = (just("{{").to('{')) + .chain(just("}}").not().repeated()) + .chain(just("}}").to('}')) + .collect::() + .map(InterpolateItem::String); + + let string = none_of('{') + .repeated() + .at_least(1) + .collect::() + .map(InterpolateItem::String); + + escape.or(expr).or(string).repeated().then_ignore(end()) +} + +fn offset_span(mut span: std::ops::Range, span_offset: usize) -> std::ops::Range { + span.start += span_offset; + span.end += span_offset; + span +} diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs new file mode 100644 index 000000000000..11d63f491300 --- /dev/null +++ b/prql-compiler/src/parser/lexer.rs @@ -0,0 +1,399 @@ +use chumsky::{error::Cheap, prelude::*}; + +use crate::ast::pl::*; + +#[derive(Clone, PartialEq, Debug)] +pub enum Token { + NewLine, + + Ident(String), + Keyword(String), + Literal(Literal), + + Range { + bind_left: bool, + bind_right: bool, + }, + Interpolation(char, String), + + /// single-char control tokens + Control(char), + + Arrow, // -> + ArrowDouble, // => + Eq, // == + Ne, // != + Gte, // >= + Lte, // <= + And, // and + Or, // or + Coalesce, // ?? +} + +pub fn lexer() -> impl Parser)>, Error = Cheap> { + let new_line = just('\n').to(Token::NewLine); + let whitespace = one_of("\t \r").repeated().at_least(1).ignored(); + + let control_multi = choice(( + just("->").to(Token::Arrow), + just("=>").to(Token::ArrowDouble), + just("==").to(Token::Eq), + just("!=").to(Token::Ne), + just(">=").to(Token::Gte), + just("<=").to(Token::Lte), + just("and").then_ignore(end_expr()).to(Token::And), + just("or").then_ignore(end_expr()).to(Token::Or), + just("??").to(Token::Coalesce), + )); + + let control = one_of("> impl Parser> { + let plain = filter(|c: &char| c.is_ascii_alphabetic() || *c == '_' || *c == '$') + .map(Some) + .chain::, _>( + filter(|c: &char| c.is_ascii_alphanumeric() || *c == '_').repeated(), + ) + .collect(); + + let backticks = just('`') + .ignore_then(none_of('`').repeated()) + .then_ignore(just('`')) + .collect::(); + + plain.or(backticks) +} + +fn literal() -> impl Parser> { + let exp = just('e').or(just('E')).ignore_then( + just('+') + .or(just('-')) + .or_not() + .chain::(text::digits(10)), + ); + + let integer = filter(|c: &char| c.is_ascii_digit() && *c != '0') + .chain::<_, Vec, _>(filter(|c: &char| c.is_ascii_digit() || *c == '_').repeated()) + .or(just('0').map(|c| vec![c])); + + let frac = just('.') + .chain::(filter(|c: &char| c.is_ascii_digit())) + .chain::(filter(|c: &char| c.is_ascii_digit() || *c == '_').repeated()); + + let number = just('+') + .or(just('-')) + .or_not() + .chain::(integer) + .chain::(frac.or_not().flatten()) + .chain::(exp.or_not().flatten()) + .try_map(|chars, span| { + let str = chars.into_iter().filter(|c| *c != '_').collect::(); + + if let Ok(i) = str.parse::() { + Ok(Literal::Integer(i)) + } else if let Ok(f) = str.parse::() { + Ok(Literal::Float(f)) + } else { + Err(Cheap::expected_input_found(span, None, None)) + } + }) + .labelled("number"); + + let string = quoted_string(true).map(Literal::String); + + let raw_string = just("r") + .ignore_then(quoted_string(false)) + .map(Literal::String); + + let bool = (just("true").to(true)) + .or(just("false").to(false)) + .then_ignore(end_expr()) + .map(Literal::Boolean); + + let null = just("null").to(Literal::Null).then_ignore(end_expr()); + + let value_and_unit = integer + .then(choice(( + just("microseconds"), + just("milliseconds"), + just("seconds"), + just("minutes"), + just("hours"), + just("days"), + just("weeks"), + just("months"), + just("years"), + ))) + .then_ignore(end_expr()) + .try_map(|(number, unit), span| { + let str = number.into_iter().filter(|c| *c != '_').collect::(); + if let Ok(n) = str.parse::() { + let unit = unit.to_string(); + Ok(ValueAndUnit { n, unit }) + } else { + Err(Cheap::expected_input_found(span, None, None)) + } + }) + .map(Literal::ValueAndUnit); + + let date_inner = digits(4) + .chain(just('-')) + .chain::(digits(2)) + .chain::(just('-')) + .chain::(digits(2)) + .boxed(); + + let time_inner = digits(2) + // minutes + .chain::(just(':').chain(digits(2)).or_not().flatten()) + // seconds + .chain::(just(':').chain(digits(2)).or_not().flatten()) + // milliseconds + .chain::( + just('.') + .chain( + filter(|c: &char| c.is_ascii_digit()) + .repeated() + .at_least(1) + .at_most(6), + ) + .or_not() + .flatten(), + ) + // timezone offset + .chain::( + one_of("-+") + .chain( + digits(2) + .chain(just(':')) + .chain(digits(2)) + .or(just('Z').map(|x| vec![x])), + ) + .or_not() + .flatten(), + ) + .boxed(); + + let date = just('@') + .ignore_then(date_inner.clone()) + .then_ignore(end_expr()) + .collect::() + .map(Literal::Date); + + let time = just('@') + .ignore_then(time_inner.clone()) + .then_ignore(end_expr()) + .collect::() + .map(Literal::Time); + + let datetime = just('@') + .ignore_then(date_inner) + .chain(just('T')) + .chain::(time_inner) + .then_ignore(end_expr()) + .collect::() + .map(Literal::Timestamp); + + choice(( + string, + raw_string, + value_and_unit, + number, + bool, + null, + datetime, + date, + time, + )) +} + +fn quoted_string(escaped: bool) -> impl Parser> { + // I don't know how this could be simplified and implemented for n>3 in general + choice(( + quoted_string_inner(r#""""""""#, escaped), + quoted_string_inner(r#"""""""#, escaped), + quoted_string_inner(r#""""""#, escaped), + quoted_string_inner(r#"""""#, escaped), + quoted_string_inner(r#"""#, escaped), + quoted_string_inner(r#"''''''"#, escaped), + quoted_string_inner(r#"'''''"#, escaped), + quoted_string_inner(r#"''''"#, escaped), + quoted_string_inner(r#"'''"#, escaped), + quoted_string_inner(r#"'"#, escaped), + )) + .collect::() + .labelled("string") +} + +fn quoted_string_inner( + quotes: &str, + escaping: bool, +) -> impl Parser, Error = Cheap> + '_ { + let mut forbidden = just(quotes).boxed(); + + if escaping { + forbidden = just(quotes).or(just("\\")).boxed() + }; + + let mut inner = forbidden.not().boxed(); + + if escaping { + inner = inner + .or(just('\\').ignore_then( + just('\\') + .or(just('/')) + .or(just('"')) + .or(just('b').to('\x08')) + .or(just('f').to('\x0C')) + .or(just('n').to('\n')) + .or(just('r').to('\r')) + .or(just('t').to('\t')) + .or(just('u').ignore_then( + filter(|c: &char| c.is_ascii_hexdigit()) + .repeated() + .exactly(4) + .collect::() + .validate(|digits, span, emit| { + char::from_u32(u32::from_str_radix(&digits, 16).unwrap()) + .unwrap_or_else(|| { + emit(Cheap::expected_input_found(span, None, None)); + '\u{FFFD}' // unicode replacement character + }) + }), + )), + )) + .boxed(); + } + + inner.repeated().delimited_by(just(quotes), just(quotes)) +} + +fn digits(count: usize) -> impl Parser, Error = Cheap> { + filter(|c: &char| c.is_ascii_digit()) + .repeated() + .exactly(count) +} + +fn end_expr() -> impl Parser> { + choice((end(), one_of(",)]\r\n\t ").ignored(), just("..").ignored())).rewind() +} + +impl Token { + pub fn range(bind_left: bool, bind_right: bool) -> Self { + Token::Range { + bind_left, + bind_right, + } + } +} + +// This is here because Literal::Float(f64) does not implement Hash, so we cannot simply derive it. +// There are reasons for that, but chumsky::Error needs Hash for the Token, so it can deduplicate +// tokens in error. +// So this hack could lead to duplicated tokens in error messages. Oh no. +#[allow(clippy::derive_hash_xor_eq)] +impl std::hash::Hash for Token { + fn hash(&self, state: &mut H) { + core::mem::discriminant(self).hash(state); + } +} + +impl std::cmp::Eq for Token {} + +impl std::fmt::Display for Token { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::NewLine => write!(f, "new line"), + Self::Ident(arg0) => { + if arg0.is_empty() { + write!(f, "an identifier") + } else { + write!(f, "`{arg0}`") + } + } + Self::Keyword(arg0) => write!(f, "keyword {arg0}"), + Self::Literal(arg0) => write!(f, "{arg0}"), + Self::Control(arg0) => write!(f, "{arg0}"), + + Self::Arrow => f.write_str("->"), + Self::ArrowDouble => f.write_str("=>"), + Self::Eq => f.write_str("=="), + Self::Ne => f.write_str("!="), + Self::Gte => f.write_str(">="), + Self::Lte => f.write_str("<="), + Self::And => f.write_str("and"), + Self::Or => f.write_str("or"), + Self::Coalesce => f.write_str("??"), + + Self::Range { + bind_left, + bind_right, + } => write!( + f, + "'{}..{}'", + if *bind_left { "" } else { " " }, + if *bind_right { "" } else { " " } + ), + Self::Interpolation(c, s) => { + write!(f, "{c}\"{}\"", s) + } + } + } +} diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 4483911c5604..461cc0eb5d5f 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -2,453 +2,210 @@ //! of pest pairs into a tree of AST Items. It has a small function to call into //! pest to get the parse tree / concrete syntax tree, and then a large //! function for turning that into PRQL AST. -mod chumsky; - -use std::collections::HashMap; -use std::str::FromStr; - -use anyhow::bail; -use anyhow::{anyhow, Result}; +mod expr; +mod interpolation; +mod lexer; +mod stmt; + +use anyhow::Result; +use chumsky::{ + error::{Cheap, SimpleReason}, + prelude::*, + Stream, +}; use itertools::Itertools; -use pest::iterators::Pair; -use pest::iterators::Pairs; -use pest::Parser; -use pest_derive::Parser; -use super::ast::pl::*; -use super::utils::*; -use crate::error::Span; +use self::lexer::Token; -#[derive(Parser)] -#[grammar = "parser/prql.pest"] -struct PrqlParser; +use super::ast::pl::*; -pub(crate) type PestError = pest::error::Error; -pub(crate) type PestRule = Rule; +use crate::error::{Error, Errors, Reason}; /// Build PL AST from a PRQL query string. -pub fn parse(string: &str) -> Result> { - let pairs = parse_tree_of_str(string, Rule::statements)?; - - stmts_of_parse_pairs(pairs) -} - -/// Parse a string into a parse tree / concrete syntax tree, made up of pest Pairs. -fn parse_tree_of_str(source: &str, rule: Rule) -> Result> { - Ok(PrqlParser::parse(rule, source)?) -} +pub fn parse(source: &str) -> Result> { + let mut errors = Vec::new(); -/// Parses a parse tree of pest Pairs into a list of statements. -fn stmts_of_parse_pairs(pairs: Pairs) -> Result> { - pairs - .filter(|p| !matches!(p.as_rule(), Rule::EOI)) - .map(stmt_of_parse_pair) - .collect() -} + let (tokens, lex_errors) = ::chumsky::Parser::parse_recovery(&lexer::lexer(), source); -fn stmt_of_parse_pair(pair: Pair) -> Result { - let span = pair.as_span(); - let rule = pair.as_rule(); + errors.extend( + lex_errors + .into_iter() + .map(|e| convert_lexer_error(source, e)), + ); - let kind = match rule { - Rule::pipeline_stmt => { - let pipeline = expr_of_parse_pair(pair.into_inner().next().unwrap())?; - StmtKind::Main(Box::new(pipeline)) - } - Rule::query_def => { - let mut params: HashMap<_, _> = pair - .into_inner() - .map(|x| parse_named(x.into_inner())) - .try_collect()?; - - let version = params - .remove("version") - .map(|v| v.try_cast(|i| i.parse_version(), None, "semver version number string")) - .transpose()?; - - let other = params - .into_iter() - .flat_map(|(key, value)| match value.kind { - ExprKind::Ident(value) => Some((key, value.to_string())), - _ => None, - }) - .collect(); - - StmtKind::QueryDef(QueryDef { version, other }) - } - Rule::func_def => { - let mut pairs = pair.into_inner(); - let name = pairs.next().unwrap(); - let params = pairs.next().unwrap(); - let body = pairs.next().unwrap(); - - let (name, return_type, _) = parse_typed_ident(name)?; - - let params: Vec<_> = params - .into_inner() - .into_iter() - .map(parse_typed_ident) - .try_collect()?; - - let mut positional_params = vec![]; - let mut named_params = vec![]; - for (name, ty, default_value) in params { - let param = FuncParam { - name, - ty, - default_value, - }; - if param.default_value.is_some() { - named_params.push(param) - } else { - positional_params.push(param) - } - } + let ast = if let Some(tokens) = tokens { + let len = source.chars().count(); + let stream = Stream::from_iter(len..len + 1, tokens.into_iter()); - StmtKind::FuncDef(FuncDef { - name, - positional_params, - named_params, - body: Box::from(expr_of_parse_pair(body)?), - return_ty: return_type, - }) - } - Rule::var_def => { - let mut pairs = pair.into_inner(); + let (ast, parse_errors) = ::chumsky::Parser::parse_recovery(&stmt::source(), stream); - let name = parse_ident_part(pairs.next().unwrap()); - let value = Box::new(expr_of_parse_pair(pairs.next().unwrap())?); + errors.extend(parse_errors.into_iter().map(convert_parser_error)); - StmtKind::VarDef(VarDef { name, value }) - } - _ => unreachable!("{pair}"), + ast + } else { + None }; - let mut stmt = Stmt::from(kind); - stmt.span = Some(Span { - start: span.start(), - end: span.end(), - }); - Ok(stmt) -} -/// Parses a parse tree of pest Pairs into an AST. -fn exprs_of_parse_pairs(pairs: Pairs) -> Result> { - pairs - .filter(|p| !matches!(p.as_rule(), Rule::EOI)) - .map(expr_of_parse_pair) - .collect() + if errors.is_empty() { + Ok(ast.unwrap_or_default()) + } else { + Err(Errors(errors).into()) + } } -fn expr_of_parse_pair(pair: Pair) -> Result { - let span = pair.as_span(); - let rule = pair.as_rule(); - let mut alias = None; - - let kind = match rule { - Rule::list => ExprKind::List(exprs_of_parse_pairs(pair.into_inner())?), - Rule::expr_mul | Rule::expr_add | Rule::expr_compare | Rule::expr => { - let mut pairs = pair.into_inner(); - - let mut expr = expr_of_parse_pair(pairs.next().unwrap())?; - if let Some(op) = pairs.next() { - let op = BinOp::from_str(op.as_str())?; - - expr = Expr::from(ExprKind::Binary { - op, - left: Box::new(expr), - right: Box::new(expr_of_parse_pair(pairs.next().unwrap())?), - }); - } +fn convert_lexer_error(source: &str, e: Cheap) -> Error { + let found = source[e.span()].to_string(); + let span = common::into_span(e.span()); - expr.kind - } - Rule::expr_unary => { - let mut pairs = pair.into_inner(); - - let op = pairs.next().unwrap(); - - let expr = expr_of_parse_pair(pairs.next().unwrap())?; - let op = UnOp::from_str(op.as_str()).unwrap(); - match op { - UnOp::Add => expr.kind, - _ => ExprKind::Unary { - op, - expr: Box::new(expr), - }, - } - } + Error::new(Reason::Unexpected { found }).with_span(span) +} - // With coalesce, we need to grab the left and the right, - // because we're transforming it into a function call rather - // than passing along the operator. So this is unlike the rest - // of the parsing (and maybe isn't optimal). - Rule::expr_coalesce => { - let mut pairs = pair.into_inner(); - let left = expr_of_parse_pair(pairs.next().unwrap())?; - - if pairs.next().is_none() { - // If there's no coalescing, just return the single expression. - left.kind +fn convert_parser_error(e: Simple) -> Error { + let just_whitespace = e + .expected() + .all(|t| matches!(t, None | Some(Token::NewLine))); + let expected = e + .expected() + .filter(|t| { + if just_whitespace { + true } else { - let right = expr_of_parse_pair(pairs.next().unwrap())?; - ExprKind::Binary { - left: Box::new(left), - op: BinOp::Coalesce, - right: Box::new(right), - } - } - } - // This makes the previous parsing a bit easier, but is hacky; - // ideally find a better way (but it doesn't seem that easy to - // parse parts of a Pairs). - Rule::operator_coalesce => ExprKind::Ident(Ident::from_name("-")), - - Rule::assign | Rule::alias => { - let (a, expr) = parse_named(pair.into_inner())?; - alias = Some(a); - expr.kind - } - Rule::func_call => { - let mut pairs = pair.into_inner(); - - let name = expr_of_parse_pair(pairs.next().unwrap())?; - - let mut named = HashMap::new(); - let mut positional = Vec::new(); - for arg in pairs { - match arg.as_rule() { - Rule::named_arg => { - let (a, expr) = parse_named(arg.into_inner())?; - named.insert(a, expr); - } - _ => { - positional.push(expr_of_parse_pair(arg)?); - } - } + !matches!(t, None | Some(Token::NewLine)) } + }) + .map(|t| match t { + Some(t) => t.to_string(), + None => "end of input".to_string(), + }) + .collect_vec(); - ExprKind::FuncCall(FuncCall { - name: Box::new(name), - args: positional, - named_args: named, - }) - } - Rule::ident => { - // Pest has already parsed, so Chumsky should never fail - let ident = ::chumsky::Parser::parse(&chumsky::ident(), pair.as_str()).unwrap(); + let found = e.found().map(|c| c.to_string()).unwrap_or_default(); - ExprKind::Ident(ident) - } + let span = common::into_span(e.span()); - Rule::number => { - // pest is responsible for ensuring these are in the correct place, - // so we just need to remove them. - let str = pair.as_str().replace('_', ""); + if let SimpleReason::Custom(message) = e.reason() { + return Error::new_simple(message).with_span(span); + } - let lit = if let Ok(i) = str.parse::() { - Literal::Integer(i) - } else if let Ok(f) = str.parse::() { - Literal::Float(f) - } else { - bail!("cannot parse {str} as number") - }; - ExprKind::Literal(lit) - } - Rule::null => ExprKind::Literal(Literal::Null), - Rule::boolean => ExprKind::Literal(Literal::Boolean(pair.as_str() == "true")), - Rule::string => { - // Takes the string_inner, without the quotes - let inner = pair.into_inner().into_only(); - let inner = inner.map(|x| x.as_str().to_string()).unwrap_or_default(); - ExprKind::Literal(Literal::String(inner)) - } - Rule::s_string => ExprKind::SString(ast_of_interpolate_items(pair)?), - Rule::f_string => ExprKind::FString(ast_of_interpolate_items(pair)?), - Rule::pipeline => { - let mut nodes = exprs_of_parse_pairs(pair.into_inner())?; - match nodes.len() { - 0 => unreachable!(), - 1 => nodes.remove(0).kind, - _ => ExprKind::Pipeline(Pipeline { exprs: nodes }), - } - } - Rule::nested_pipeline => { - if let Some(pipeline) = pair.into_inner().next() { - expr_of_parse_pair(pipeline)?.kind - } else { - ExprKind::Literal(Literal::Null) + if expected.is_empty() || expected.len() > 10 { + Error::new(Reason::Unexpected { found }) + } else { + let mut expected = expected; + let expected = match expected.len() { + 1 => expected.remove(0), + 2 => expected.join(" or "), + _ => { + let last = expected.pop().unwrap(); + format!("one of {} or {last}", expected.join(", ")) } - } - Rule::range => { - let [start, end]: [Option>; 2] = pair - .into_inner() - // Iterate over `start` & `end` (separator is not a term). - .into_iter() - .map(|x| { - // Parse & Box each one. - exprs_of_parse_pairs(x.into_inner()) - .and_then(|x| x.into_only()) - .map(Box::new) - .ok() - }) - .collect::>() - .try_into() - .map_err(|e| anyhow!("Expected start, separator, end; {e:?}"))?; - ExprKind::Range(Range { start, end }) - } + }; - Rule::value_and_unit => { - let pairs: Vec<_> = pair.into_inner().into_iter().collect(); - let [n, unit]: [Pair; 2] = pairs - .try_into() - .map_err(|e| anyhow!("Expected two items; {e:?}"))?; - - ExprKind::Literal(Literal::ValueAndUnit(ValueAndUnit { - n: n.as_str().parse()?, - unit: unit.as_str().to_owned(), - })) - } - - Rule::date | Rule::time | Rule::timestamp => { - let inner = pair.into_inner().into_only()?.as_str().to_string(); - - ExprKind::Literal(match rule { - Rule::date => Literal::Date(inner), - Rule::time => Literal::Time(inner), - Rule::timestamp => Literal::Timestamp(inner), - _ => unreachable!(), - }) - } + Error::new(Reason::Expected { + who: e.label().map(|x| x.to_string()), + expected, + found, + }) + } + .with_span(span) +} - Rule::switch => { - let cases = pair - .into_inner() - .map(|pair| -> Result<_> { - let [condition, value]: [Expr; 2] = pair - .into_inner() - .map(expr_of_parse_pair) - .collect::>>()? - .try_into() - .unwrap(); - Ok(SwitchCase { condition, value }) - }) - .try_collect()?; - - ExprKind::Switch(cases) - } +mod common { + use chumsky::prelude::*; - _ => unreachable!("{pair}"), - }; - Ok(Expr { - span: Some(Span { - start: span.start(), - end: span.end(), - }), - alias, - ..Expr::from(kind) - }) -} + use super::lexer::Token; + use crate::{ast::pl::*, Span}; -fn type_of_parse_pair(pair: Pair) -> Result { - let any_of_terms: Vec<_> = pair - .into_inner() - .into_iter() - .map(|pair| -> Result { - let mut pairs = pair.into_inner(); - let name = parse_ident_part(pairs.next().unwrap()); - let typ = match TyLit::from_str(&name) { - Ok(t) => Ty::from(t), - Err(_) if name == "table" => Ty::Table(Frame::default()), - Err(_) => { - eprintln!("named type: {}", name); - Ty::Named(name.to_string()) - } - }; - - let param = pairs.next().map(type_of_parse_pair).transpose()?; - - Ok(if let Some(param) = param { - Ty::Parameterized(Box::new(typ), Box::new(param)) - } else { - typ - }) + pub fn ident_part() -> impl Parser> { + select! { Token::Ident(ident) => ident }.map_err(|e: Simple| { + Simple::expected_input_found( + e.span(), + [Some(Token::Ident("".to_string()))], + e.found().cloned(), + ) }) - .try_collect()?; + } - // is there only a single element? - Ok(match <[_; 1]>::try_from(any_of_terms) { - Ok([only]) => only, - Err(many) => Ty::AnyOf(many), - }) -} + pub fn keyword(kw: &'static str) -> impl Parser> + Clone { + just(Token::Keyword(kw.to_string())).ignored() + } -fn parse_typed_ident(pair: Pair) -> Result<(String, Option, Option)> { - let mut pairs = pair.into_inner(); + pub fn new_line() -> impl Parser> + Clone { + just(Token::NewLine).ignored() + } - let name = parse_ident_part(pairs.next().unwrap()); + pub fn ctrl(char: char) -> impl Parser> + Clone { + just(Token::Control(char)).ignored() + } - let mut ty = None; - let mut default = None; - for pair in pairs { - if matches!(pair.as_rule(), Rule::type_def) { - ty = Some(type_of_parse_pair(pair)?); - } else { - default = Some(expr_of_parse_pair(pair)?); + pub fn into_stmt(kind: StmtKind, span: std::ops::Range) -> Stmt { + Stmt { + span: into_span(span), + ..Stmt::from(kind) } } - Ok((name, ty, default)) -} - -fn parse_named(mut pairs: Pairs) -> Result<(String, Expr)> { - let alias = parse_ident_part(pairs.next().unwrap()); - let expr = expr_of_parse_pair(pairs.next().unwrap())?; - - Ok((alias, expr)) -} - -fn parse_ident_part(pair: Pair) -> String { - pair.into_inner().next().unwrap().as_str().to_string() -} + pub fn into_expr(kind: ExprKind, span: std::ops::Range) -> Expr { + Expr { + span: into_span(span), + ..Expr::from(kind) + } + } -fn ast_of_interpolate_items(pair: Pair) -> Result> { - pair.into_inner() - .map(|x| { - Ok(match x.as_rule() { - Rule::interpolate_string_inner_literal => { - InterpolateItem::String(x.as_str().to_string()) - } - Rule::double_open_bracket => InterpolateItem::String("{".to_string()), - Rule::double_close_bracket => InterpolateItem::String("}".to_string()), - _ => InterpolateItem::Expr(Box::new(expr_of_parse_pair(x)?)), - }) + pub fn into_span(span: std::ops::Range) -> Option { + Some(Span { + start: span.start, + end: span.end, }) - .collect::>() + } } #[cfg(test)] mod test { use super::*; + use anyhow::anyhow; use insta::assert_yaml_snapshot; - fn stmts_of_string(string: &str) -> Result> { - let pairs = parse_tree_of_str(string, Rule::statements)?; - - stmts_of_parse_pairs(pairs) + fn parse_expr(source: &str) -> Result> { + let tokens = Parser::parse(&lexer::lexer(), source).map_err(|errs| { + errs.into_iter() + .map(|e| anyhow!(convert_lexer_error(source, e))) + .collect_vec() + })?; + + let len = source.chars().count(); + let stream = Stream::from_iter(len..len + 1, tokens.into_iter()); + Parser::parse(&expr::expr_call().then_ignore(end()), stream) + .map_err(|errs| errs.into_iter().map(|e| anyhow!(e)).collect_vec()) } - fn expr_of_string(string: &str, rule: Rule) -> Result { - let mut pairs = parse_tree_of_str(string, rule)?; - - expr_of_parse_pair(pairs.next().unwrap()) + #[test] + fn test_pipeline_parse_tree() { + assert_yaml_snapshot!(parse( + // It's useful to have canonical examples rather than copy-pasting + // everything, so we reference the prql file here. But a downside of + // this implementation is: if there's an error in extracting the + // example from the docs into the file specified here, this test + // won't compile. Because `cargo insta test --accept` on the + // workspace โ€” which extracts the example โ€” requires compiling this, + // we can get stuck. + // + // Breaking out of that requires running this `cargo insta test + // --accept` within `book`, and then running it on the workspace. + // `task test-all` does this. + // + // If we change this, it would great if we can retain having + // examples tested in the docs. + include_str!("../../../book/tests/prql/examples/variables-0.prql"), + ) + .unwrap()); } #[test] - fn test_parse_take() -> Result<()> { - parse_tree_of_str("take 10", Rule::statements)?; + fn test_take() { + parse("take 10").unwrap(); - assert_yaml_snapshot!(stmts_of_string(r#"take 10"#)?, @r###" + assert_yaml_snapshot!(parse(r#"take 10"#).unwrap(), @r###" --- - Main: FuncCall: @@ -458,10 +215,24 @@ mod test { args: - Literal: Integer: 10 - named_args: {} "###); - assert_yaml_snapshot!(stmts_of_string(r#"take 1..10"#)?, @r###" + assert_yaml_snapshot!(parse(r#"take ..10"#).unwrap(), @r###" + --- + - Main: + FuncCall: + name: + Ident: + - take + args: + - Range: + start: ~ + end: + Literal: + Integer: 10 + "###); + + assert_yaml_snapshot!(parse(r#"take 1..10"#).unwrap(), @r###" --- - Main: FuncCall: @@ -476,44 +247,128 @@ mod test { end: Literal: Integer: 10 - named_args: {} "###); - - Ok(()) } #[test] - fn test_parse_pipeline_parse_tree() { - assert_yaml_snapshot!(stmts_of_parse_pairs( - parse_tree_of_str( - // It's useful to have canonical examples rather than copy-pasting - // everything, so we reference the prql file here. But a downside of - // this implementation is: if there's an error in extracting the - // example from the docs into the file specified here, this test - // won't compile. Because `cargo insta test --accept` on the - // workspace โ€” which extracts the example โ€” requires compiling this, - // we can get stuck. - // - // Breaking out of that requires running this `cargo insta test - // --accept` within `book`, and then running it on the workspace. - // `task test-all` does this. - // - // If we change this, it would great if we can retain having - // examples tested in the docs. - &include_str!("../../../book/tests/prql/examples/variables-0.prql") - .trim() - // Required for Windows - .replace("\r\n", "\n"), - Rule::statements - ) - .unwrap() - ) - .unwrap()); + fn test_ranges() { + assert_yaml_snapshot!(parse_expr(r#"3..5"#).unwrap(), @r###" + --- + Range: + start: + Literal: + Integer: 3 + end: + Literal: + Integer: 5 + "###); + + assert_yaml_snapshot!(parse_expr(r#"-2..-5"#).unwrap(), @r###" + --- + Range: + start: + Unary: + op: Neg + expr: + Literal: + Integer: 2 + end: + Unary: + op: Neg + expr: + Literal: + Integer: 5 + "###); + + assert_yaml_snapshot!(parse_expr(r#"(-2..(-5 | abs))"#).unwrap(), @r###" + --- + Range: + start: + Unary: + op: Neg + expr: + Literal: + Integer: 2 + end: + Pipeline: + exprs: + - Unary: + op: Neg + expr: + Literal: + Integer: 5 + - Ident: + - abs + "###); + + assert_yaml_snapshot!(parse_expr(r#"(2 + 5)..'a'"#).unwrap(), @r###" + --- + Range: + start: + Binary: + left: + Literal: + Integer: 2 + op: Add + right: + Literal: + Integer: 5 + end: + Literal: + String: a + "###); + + assert_yaml_snapshot!(parse_expr(r#"1.6..rel.col"#).unwrap(), @r###" + --- + Range: + start: + Literal: + Float: 1.6 + end: + Ident: + - rel + - col + "###); + + assert_yaml_snapshot!(parse_expr(r#"6.."#).unwrap(), @r###" + --- + Range: + start: + Literal: + Integer: 6 + end: ~ + "###); + assert_yaml_snapshot!(parse_expr(r#"..7"#).unwrap(), @r###" + --- + Range: + start: ~ + end: + Literal: + Integer: 7 + "###); + + assert_yaml_snapshot!(parse_expr(r#".."#).unwrap(), @r###" + --- + Range: + start: ~ + end: ~ + "###); + + assert_yaml_snapshot!(parse_expr(r#"@2020-01-01..@2021-01-01"#).unwrap(), @r###" + --- + Range: + start: + Literal: + Date: 2020-01-01 + end: + Literal: + Date: 2021-01-01 + "###); } #[test] - fn test_parse_basic_exprs() -> Result<()> { - assert_yaml_snapshot!(expr_of_string(r#"country == "USA""#, Rule::expr)?, @r###" + fn test_basic_exprs() { + assert_yaml_snapshot!(parse_expr(r#"country == "USA""#).unwrap(), @r###" --- Binary: left: @@ -524,7 +379,7 @@ mod test { Literal: String: USA "###); - assert_yaml_snapshot!(expr_of_string("select [a, b, c]", Rule::func_call)?, @r###" + assert_yaml_snapshot!(parse_expr("select [a, b, c]").unwrap(), @r###" --- FuncCall: name: @@ -538,14 +393,12 @@ mod test { - b - Ident: - c - named_args: {} "###); - assert_yaml_snapshot!(expr_of_string( + assert_yaml_snapshot!(parse_expr( "group [title, country] ( aggregate [sum salary] - )", - Rule::pipeline - )?, @r###" + )" + ).unwrap(), @r###" --- FuncCall: name: @@ -570,14 +423,10 @@ mod test { args: - Ident: - salary - named_args: {} - named_args: {} - named_args: {} "###); - assert_yaml_snapshot!(expr_of_string( - r#" filter country == "USA""#, - Rule::pipeline - )?, @r###" + assert_yaml_snapshot!(parse_expr( + r#" filter country == "USA""# + ).unwrap(), @r###" --- FuncCall: name: @@ -592,9 +441,8 @@ mod test { right: Literal: String: USA - named_args: {} "###); - assert_yaml_snapshot!(expr_of_string("[a, b, c,]", Rule::list)?, @r###" + assert_yaml_snapshot!(parse_expr("[a, b, c,]").unwrap(), @r###" --- List: - Ident: @@ -604,13 +452,12 @@ mod test { - Ident: - c "###); - assert_yaml_snapshot!(expr_of_string( + assert_yaml_snapshot!(parse_expr( r#"[ gross_salary = salary + payroll_tax, gross_cost = gross_salary + benefits_cost -]"#, - Rule::list - )?, @r###" +]"# + ).unwrap(), @r###" --- List: - Binary: @@ -633,10 +480,10 @@ mod test { alias: gross_cost "###); // Currently not putting comments in our parse tree, so this is blank. - assert_yaml_snapshot!(stmts_of_string( + assert_yaml_snapshot!(parse( r#"# this is a comment select a"# - )?, @r###" + ).unwrap(), @r###" --- - Main: FuncCall: @@ -646,12 +493,10 @@ mod test { args: - Ident: - a - named_args: {} "###); - assert_yaml_snapshot!(expr_of_string( - "join side:left country [id==employee_id]", - Rule::func_call - )?, @r###" + assert_yaml_snapshot!(parse_expr( + "join side:left country [id==employee_id]" + ).unwrap(), @r###" --- FuncCall: name: @@ -674,7 +519,7 @@ mod test { Ident: - left "###); - assert_yaml_snapshot!(expr_of_string("1 + 2", Rule::expr)?, @r###" + assert_yaml_snapshot!(parse_expr("1 + 2").unwrap(), @r###" --- Binary: left: @@ -684,101 +529,73 @@ mod test { right: Literal: Integer: 2 - "###); - Ok(()) + "###) } #[test] - fn test_parse_string() -> Result<()> { - let double_quoted_ast = expr_of_string(r#"" U S A ""#, Rule::string)?; + fn test_string() { + let double_quoted_ast = parse_expr(r#"" U S A ""#).unwrap(); assert_yaml_snapshot!(double_quoted_ast, @r###" --- Literal: String: " U S A " "###); - let single_quoted_ast = expr_of_string(r#"' U S A '"#, Rule::string)?; + let single_quoted_ast = parse_expr(r#"' U S A '"#).unwrap(); assert_eq!(single_quoted_ast, double_quoted_ast); // Single quotes within double quotes should produce a string containing // the single quotes (and vice versa). - assert_yaml_snapshot!(expr_of_string(r#""' U S A '""#, Rule::string)? , @r###" + assert_yaml_snapshot!(parse_expr(r#""' U S A '""#).unwrap(), @r###" --- Literal: String: "' U S A '" "###); - assert_yaml_snapshot!(expr_of_string(r#"'" U S A "'"#, Rule::string)? , @r###" + assert_yaml_snapshot!(parse_expr(r#"'" U S A "'"#).unwrap(), @r###" --- Literal: String: "\" U S A \"" "###); - assert!(expr_of_string(r#"" U S A"#, Rule::string).is_err()); - assert!(expr_of_string(r#"" U S A '"#, Rule::string).is_err()); + parse_expr(r#"" U S A"#).unwrap_err(); + parse_expr(r#"" U S A '"#).unwrap_err(); - // Escapes get passed through (the insta snapshot has them escaped I - // think, which isn't that clear, so repeated below). - let escaped_string = expr_of_string(r#"" \U S A ""#, Rule::string)?; - assert_yaml_snapshot!(escaped_string, @r###" + assert_yaml_snapshot!(parse_expr(r#"" \nU S A ""#).unwrap(), @r###" --- Literal: - String: " \\U S A " - "###); - assert_eq!( - escaped_string - .kind - .as_literal() - .unwrap() - .as_string() - .unwrap(), - r#" \U S A "# - ); + String: " \nU S A " + "###); - // Currently we don't allow escaping closing quotes โ€”ย because it's not - // trivial to do in pest, and I'm not sure it's a great idea either โ€”ย we - // should arguably encourage multiline-strings. (Though no objection if - // someone wants to implement it, this test is recording current - // behavior rather than maintaining a contract). - let escaped_quotes = expr_of_string(r#"" Canada \""#, Rule::string)?; - assert_yaml_snapshot!(escaped_quotes, @r###" + assert_yaml_snapshot!(parse_expr(r#"r" \nU S A ""#).unwrap(), @r###" --- Literal: - String: " Canada \\" - "###); - assert_eq!( - escaped_quotes - .kind - .as_literal() - .unwrap() - .as_string() - .unwrap(), - r#" Canada \"# - ); + String: " \\nU S A " + "###); - let multi_double = expr_of_string( + let multi_double = parse_expr( r#"""" '' Canada " """"#, - Rule::string, - )?; + ) + .unwrap(); assert_yaml_snapshot!(multi_double, @r###" --- Literal: String: "\n''\nCanada\n\"\n\n" "###); - let multi_single = expr_of_string( + let multi_single = parse_expr( r#"''' Canada " """ '''"#, - Rule::string, - )?; + ) + .unwrap(); assert_yaml_snapshot!(multi_single, @r###" --- Literal: @@ -786,19 +603,17 @@ Canada "###); assert_yaml_snapshot!( - expr_of_string("''", Rule::string).unwrap(), + parse_expr("''").unwrap(), @r###" --- Literal: String: "" "###); - - Ok(()) } #[test] - fn test_parse_s_string() -> Result<()> { - assert_yaml_snapshot!(expr_of_string(r#"s"SUM({col})""#, Rule::expr_call)?, @r###" + fn test_s_string() { + assert_yaml_snapshot!(parse_expr(r#"s"SUM({col})""#).unwrap(), @r###" --- SString: - String: SUM( @@ -807,47 +622,32 @@ Canada - col - String: ) "###); - assert_yaml_snapshot!(expr_of_string(r#"s"SUM({2 + 2})""#, Rule::expr_call)?, @r###" + assert_yaml_snapshot!(parse_expr(r#"s"SUM({rel.`Col name`})""#).unwrap(), @r###" --- SString: - String: SUM( - Expr: - Binary: - left: - Literal: - Integer: 2 - op: Add - right: - Literal: - Integer: 2 + Ident: + - rel + - Col name - String: ) - "###); - Ok(()) + "###) } #[test] - fn test_parse_s_string_braces() -> Result<()> { - assert_yaml_snapshot!(expr_of_string(r#"s"{{?crystal_var}}""#, Rule::expr_call)?, @r###" - --- - SString: - - String: "{" - - String: "?crystal_var" - - String: "}" - "###); - assert_yaml_snapshot!(expr_of_string(r#"s"foo{{bar""#, Rule::expr_call)?, @r###" + fn test_s_string_braces() { + assert_yaml_snapshot!(parse_expr(r#"s"{{?crystal_var}}""#).unwrap(), @r###" --- SString: - - String: foo - - String: "{" - - String: bar + - String: "{?crystal_var}" "###); - - Ok(()) + parse_expr(r#"s"foo{{bar""#).unwrap_err(); } #[test] - fn test_parse_jinja() { - stmts_of_string( + #[ignore] + fn test_jinja() { + parse( r#" from {{ ref('stg_orders') }} aggregate (sum order_id) @@ -857,8 +657,8 @@ Canada } #[test] - fn test_parse_list() { - assert_yaml_snapshot!(expr_of_string(r#"[1 + 1, 2]"#, Rule::list).unwrap(), @r###" + fn test_list() { + assert_yaml_snapshot!(parse_expr(r#"[1 + 1, 2]"#).unwrap(), @r###" --- List: - Binary: @@ -872,7 +672,7 @@ Canada - Literal: Integer: 2 "###); - assert_yaml_snapshot!(expr_of_string(r#"[1 + (f 1), 2]"#, Rule::list).unwrap(), @r###" + assert_yaml_snapshot!(parse_expr(r#"[1 + (f 1), 2]"#).unwrap(), @r###" --- List: - Binary: @@ -888,16 +688,15 @@ Canada args: - Literal: Integer: 1 - named_args: {} - Literal: Integer: 2 "###); // Line breaks - assert_yaml_snapshot!(expr_of_string( + assert_yaml_snapshot!(parse_expr( r#"[1, - 2]"#, - Rule::list).unwrap(), @r###" + 2]"# + ).unwrap(), @r###" --- List: - Literal: @@ -906,8 +705,8 @@ Canada Integer: 2 "###); // Function call in a list - let ab = expr_of_string(r#"[a b]"#, Rule::list).unwrap(); - let a_comma_b = expr_of_string(r#"[a, b]"#, Rule::list).unwrap(); + let ab = parse_expr(r#"[a b]"#).unwrap(); + let a_comma_b = parse_expr(r#"[a, b]"#).unwrap(); assert_yaml_snapshot!(ab, @r###" --- List: @@ -918,7 +717,6 @@ Canada args: - Ident: - b - named_args: {} "###); assert_yaml_snapshot!(a_comma_b, @r###" --- @@ -930,13 +728,16 @@ Canada "###); assert_ne!(ab, a_comma_b); - assert_yaml_snapshot!(expr_of_string(r#"[amount, +amount, -amount]"#, Rule::list).unwrap(), @r###" + assert_yaml_snapshot!(parse_expr(r#"[amount, +amount, -amount]"#).unwrap(), @r###" --- List: - Ident: - amount - - Ident: - - amount + - Unary: + op: Add + expr: + Ident: + - amount - Unary: op: Neg expr: @@ -944,13 +745,16 @@ Canada - amount "###); // Operators in list items - assert_yaml_snapshot!(expr_of_string(r#"[amount, +amount, -amount]"#, Rule::list).unwrap(), @r###" + assert_yaml_snapshot!(parse_expr(r#"[amount, +amount, -amount]"#).unwrap(), @r###" --- List: - - Ident: - - amount - Ident: - amount + - Unary: + op: Add + expr: + Ident: + - amount - Unary: op: Neg expr: @@ -960,28 +764,28 @@ Canada } #[test] - fn test_parse_number() -> Result<()> { - assert_yaml_snapshot!(expr_of_string(r#"23"#, Rule::number)?, @r###" + fn test_number() { + assert_yaml_snapshot!(parse_expr(r#"23"#).unwrap(), @r###" --- Literal: Integer: 23 "###); - assert_yaml_snapshot!(expr_of_string(r#"2_3_4.5_6"#, Rule::number)?, @r###" + assert_yaml_snapshot!(parse_expr(r#"2_3_4.5_6"#).unwrap(), @r###" --- Literal: Float: 234.56 "###); - assert_yaml_snapshot!(expr_of_string(r#"23.6"#, Rule::number)?, @r###" + assert_yaml_snapshot!(parse_expr(r#"23.6"#).unwrap(), @r###" --- Literal: Float: 23.6 "###); - assert_yaml_snapshot!(expr_of_string(r#"23.0"#, Rule::number)?, @r###" + assert_yaml_snapshot!(parse_expr(r#"23.0"#).unwrap(), @r###" --- Literal: Float: 23 "###); - assert_yaml_snapshot!(expr_of_string(r#"2 + 2"#, Rule::expr_add)?, @r###" + assert_yaml_snapshot!(parse_expr(r#"2 + 2"#).unwrap(), @r###" --- Binary: left: @@ -993,23 +797,22 @@ Canada Integer: 2 "###); - // Underscores can't go at the beginning or end of numbers - assert!(expr_of_string("_2", Rule::number).is_err()); - assert!(expr_of_string("_", Rule::number).is_err()); - assert!(expr_of_string("_2.3", Rule::number).is_err()); - // We need to test these with `stmts_of_string` because they start with - // a valid number (and pest will return as much as possible and then return) - let bad_numbers = vec!["2_", "2.3_"]; - for bad_number in bad_numbers { - assert!(stmts_of_string(bad_number).is_err()); - } - Ok(()) + // Underscores at the beginning are parsed as ident + parse_expr("_2").unwrap().kind.into_ident().unwrap(); + parse_expr("_").unwrap().kind.into_ident().unwrap(); + + // We don't allow empty fractions. + parse_expr(r#"add 1. 2"#).unwrap_err(); + + parse_expr("_2.3").unwrap_err(); + // expr_of_string("2_").unwrap_err(); // TODO + // expr_of_string("2.3_").unwrap_err(); // TODO } #[test] - fn test_parse_filter() { + fn test_filter() { assert_yaml_snapshot!( - stmts_of_string(r#"filter country == "USA""#).unwrap(), @r###" + parse(r#"filter country == "USA""#).unwrap(), @r###" --- - Main: FuncCall: @@ -1025,11 +828,10 @@ Canada right: Literal: String: USA - named_args: {} "###); assert_yaml_snapshot!( - stmts_of_string(r#"filter (upper country) == "USA""#).unwrap(), @r###" + parse(r#"filter (upper country) == "USA""#).unwrap(), @r###" --- - Main: FuncCall: @@ -1046,19 +848,17 @@ Canada args: - Ident: - country - named_args: {} op: Eq right: Literal: String: USA - named_args: {} "### ); } #[test] - fn test_parse_aggregate() { - let aggregate = stmts_of_string( + fn test_aggregate() { + let aggregate = parse( r"group [title] ( aggregate [sum salary, count] )", @@ -1089,13 +889,10 @@ Canada args: - Ident: - salary - named_args: {} - Ident: - count - named_args: {} - named_args: {} "###); - let aggregate = stmts_of_string( + let aggregate = parse( r"group [title] ( aggregate [sum salary] )", @@ -1126,16 +923,13 @@ Canada args: - Ident: - salary - named_args: {} - named_args: {} - named_args: {} "###); } #[test] - fn test_parse_derive() -> Result<()> { + fn test_derive() { assert_yaml_snapshot!( - expr_of_string(r#"derive [x = 5, y = (-x)]"#, Rule::func_call)? + parse_expr(r#"derive [x = 5, y = (-x)]"#).unwrap() , @r###" --- FuncCall: @@ -1153,16 +947,13 @@ Canada Ident: - x alias: y - named_args: {} "###); - - Ok(()) } #[test] - fn test_parse_select() -> Result<()> { + fn test_select() { assert_yaml_snapshot!( - expr_of_string(r#"select x"#, Rule::func_call)? + parse_expr(r#"select x"#).unwrap() , @r###" --- FuncCall: @@ -1172,11 +963,10 @@ Canada args: - Ident: - x - named_args: {} "###); assert_yaml_snapshot!( - expr_of_string(r#"select ![x]"#, Rule::func_call)? + parse_expr(r#"select ![x]"#).unwrap() , @r###" --- FuncCall: @@ -1190,11 +980,10 @@ Canada List: - Ident: - x - named_args: {} "###); assert_yaml_snapshot!( - expr_of_string(r#"select [x, y]"#, Rule::func_call)? + parse_expr(r#"select [x, y]"#).unwrap() , @r###" --- FuncCall: @@ -1207,16 +996,13 @@ Canada - x - Ident: - y - named_args: {} "###); - - Ok(()) } #[test] - fn test_parse_expr() -> Result<()> { + fn test_expr() { assert_yaml_snapshot!( - expr_of_string(r#"country == "USA""#, Rule::expr)? + parse_expr(r#"country == "USA""#).unwrap() , @r###" --- Binary: @@ -1228,12 +1014,11 @@ Canada Literal: String: USA "###); - assert_yaml_snapshot!(expr_of_string( + assert_yaml_snapshot!(parse_expr( r#"[ gross_salary = salary + payroll_tax, gross_cost = gross_salary + benefits_cost, -]"#, - Rule::list)?, @r###" +]"#).unwrap(), @r###" --- List: - Binary: @@ -1256,10 +1041,9 @@ Canada alias: gross_cost "###); assert_yaml_snapshot!( - expr_of_string( - "gross_salary = (salary + payroll_tax) * (1 + tax_rate)", - Rule::alias, - )?, + parse_expr( + "(salary + payroll_tax) * (1 + tax_rate)" + ).unwrap(), @r###" --- Binary: @@ -1282,14 +1066,12 @@ Canada right: Ident: - tax_rate - alias: gross_salary - "###); - Ok(()) + "###) } #[test] - fn test_parse_function() -> Result<()> { - assert_yaml_snapshot!(stmts_of_string("func plus_one x -> x + 1")?, @r###" + fn test_function() { + assert_yaml_snapshot!(parse("func plus_one x -> x + 1\n").unwrap(), @r###" --- - FuncDef: name: plus_one @@ -1308,7 +1090,7 @@ Canada Integer: 1 return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string("func identity x -> x")? + assert_yaml_snapshot!(parse("func identity x -> x\n").unwrap() , @r###" --- - FuncDef: @@ -1322,7 +1104,7 @@ Canada - x return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string("func plus_one x -> (x + 1)")? + assert_yaml_snapshot!(parse("func plus_one x -> (x + 1)\n").unwrap() , @r###" --- - FuncDef: @@ -1342,7 +1124,7 @@ Canada Integer: 1 return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string("func plus_one x -> x + 1")? + assert_yaml_snapshot!(parse("func plus_one x -> x + 1\n").unwrap() , @r###" --- - FuncDef: @@ -1362,7 +1144,8 @@ Canada Integer: 1 return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string("func foo x -> some_func (foo bar + 1) (plax) - baz")? + + assert_yaml_snapshot!(parse("func foo x -> some_func (foo bar + 1) (plax) - baz\n").unwrap() , @r###" --- - FuncDef: @@ -1390,7 +1173,6 @@ Canada right: Literal: Integer: 1 - named_args: {} - Binary: left: Ident: @@ -1399,11 +1181,10 @@ Canada right: Ident: - baz - named_args: {} return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string("func return_constant -> 42")?, @r###" + assert_yaml_snapshot!(parse("func return_constant -> 42\n").unwrap(), @r###" --- - FuncDef: name: return_constant @@ -1414,7 +1195,9 @@ Canada Integer: 42 return_ty: ~ "###); - assert_yaml_snapshot!(stmts_of_string(r#"func count X -> s"SUM({X})""#)?, @r###" + + assert_yaml_snapshot!(parse(r#"func count X -> s"SUM({X})" + "#).unwrap(), @r###" --- - FuncDef: name: count @@ -1432,24 +1215,59 @@ Canada return_ty: ~ "###); - /* TODO: Does not yet parse because `window` not yet implemented. - assert_debug_snapshot!(ast_of_parse_tree( - parse_tree_of_str( - r#" - func lag_day x -> ( - window x - by sec_id - sort date - lag 1 + assert_yaml_snapshot!(parse( + r#" + func lag_day x -> ( + window x + by sec_id + sort date + lag 1 + ) + "# ) - "#, - Rule::func_def - ) - .unwrap() - )); - */ + .unwrap(), @r###" + --- + - FuncDef: + name: lag_day + positional_params: + - name: x + default_value: ~ + named_params: [] + body: + Pipeline: + exprs: + - FuncCall: + name: + Ident: + - window + args: + - Ident: + - x + - FuncCall: + name: + Ident: + - by + args: + - Ident: + - sec_id + - FuncCall: + name: + Ident: + - sort + args: + - Ident: + - date + - FuncCall: + name: + Ident: + - lag + args: + - Literal: + Integer: 1 + return_ty: ~ + "###); - assert_yaml_snapshot!(stmts_of_string(r#"func add x to:a -> x + to"#)?, @r###" + assert_yaml_snapshot!(parse("func add x to:a -> x + to\n").unwrap(), @r###" --- - FuncDef: name: add @@ -1472,14 +1290,12 @@ Canada - to return_ty: ~ "###); - - Ok(()) } #[test] - fn test_parse_func_call() { + fn test_func_call() { // Function without argument - let ast = expr_of_string(r#"count"#, Rule::expr).unwrap(); + let ast = parse_expr(r#"count"#).unwrap(); let ident = ast.kind.into_ident().unwrap(); assert_yaml_snapshot!( ident, @r###" @@ -1487,8 +1303,21 @@ Canada - count "###); + let ast = parse_expr(r#"s 'foo'"#).unwrap(); + assert_yaml_snapshot!( + ast, @r###" + --- + FuncCall: + name: + Ident: + - s + args: + - Literal: + String: foo + "###); + // A non-friendly option for #154 - let ast = expr_of_string(r#"count s'*'"#, Rule::expr_call).unwrap(); + let ast = parse_expr(r#"count s'*'"#).unwrap(); let func_call: FuncCall = ast.kind.into_func_call().unwrap(); assert_yaml_snapshot!( func_call, @r###" @@ -1499,64 +1328,11 @@ Canada args: - SString: - String: "*" - named_args: {} "###); - assert_yaml_snapshot!(parse(r#"from mytable | select [a and b + c or (d e) and f]"#).unwrap(), @r###" - --- - - Main: - Pipeline: - exprs: - - FuncCall: - name: - Ident: - - from - args: - - Ident: - - mytable - named_args: {} - - FuncCall: - name: - Ident: - - select - args: - - List: - - Binary: - left: - Ident: - - a - op: And - right: - Binary: - left: - Binary: - left: - Ident: - - b - op: Add - right: - Ident: - - c - op: Or - right: - Binary: - left: - FuncCall: - name: - Ident: - - d - args: - - Ident: - - e - named_args: {} - op: And - right: - Ident: - - f - named_args: {} - "###); + parse_expr("plus_one x:0 x:0 ").unwrap_err(); - let ast = expr_of_string(r#"add bar to=3"#, Rule::expr_call).unwrap(); + let ast = parse_expr(r#"add bar to=3"#).unwrap(); assert_yaml_snapshot!( ast, @r###" --- @@ -1570,15 +1346,130 @@ Canada - Literal: Integer: 3 alias: to - named_args: {} "###); } #[test] - fn test_parse_table() -> Result<()> { - assert_yaml_snapshot!(stmts_of_string( + fn test_op_precedence() { + assert_yaml_snapshot!(parse_expr(r#"1 + 2 - 3 - 4"#).unwrap(), @r###" + --- + Binary: + left: + Binary: + left: + Binary: + left: + Literal: + Integer: 1 + op: Add + right: + Literal: + Integer: 2 + op: Sub + right: + Literal: + Integer: 3 + op: Sub + right: + Literal: + Integer: 4 + "###); + + assert_yaml_snapshot!(parse_expr(r#"1 / 2 - 3 * 4 + 1"#).unwrap(), @r###" + --- + Binary: + left: + Binary: + left: + Binary: + left: + Literal: + Integer: 1 + op: Div + right: + Literal: + Integer: 2 + op: Sub + right: + Binary: + left: + Literal: + Integer: 3 + op: Mul + right: + Literal: + Integer: 4 + op: Add + right: + Literal: + Integer: 1 + "###); + + assert_yaml_snapshot!(parse_expr(r#"a and b or c and d"#).unwrap(), @r###" + --- + Binary: + left: + Binary: + left: + Ident: + - a + op: And + right: + Ident: + - b + op: Or + right: + Binary: + left: + Ident: + - c + op: And + right: + Ident: + - d + "###); + + assert_yaml_snapshot!(parse_expr(r#"a and b + c or (d e) and f"#).unwrap(), @r###" + --- + Binary: + left: + Binary: + left: + Ident: + - a + op: And + right: + Binary: + left: + Ident: + - b + op: Add + right: + Ident: + - c + op: Or + right: + Binary: + left: + FuncCall: + name: + Ident: + - d + args: + - Ident: + - e + op: And + right: + Ident: + - f + "###); + } + + #[test] + fn test_var_def() { + assert_yaml_snapshot!(parse( "let newest_employees = (from employees)" - )?, @r###" + ).unwrap(), @r###" --- - VarDef: name: newest_employees @@ -1590,10 +1481,9 @@ Canada args: - Ident: - employees - named_args: {} "###); - assert_yaml_snapshot!(stmts_of_string( + assert_yaml_snapshot!(parse( r#" let newest_employees = ( from employees @@ -1604,7 +1494,7 @@ Canada ) sort tenure take 50 - )"#.trim())?, + )"#.trim()).unwrap(), @r###" --- - VarDef: @@ -1619,7 +1509,6 @@ Canada args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -1640,10 +1529,7 @@ Canada args: - Ident: - salary - named_args: {} alias: average_country_salary - named_args: {} - named_args: {} - FuncCall: name: Ident: @@ -1651,7 +1537,6 @@ Canada args: - Ident: - tenure - named_args: {} - FuncCall: name: Ident: @@ -1659,12 +1544,11 @@ Canada args: - Literal: Integer: 50 - named_args: {} "###); - assert_yaml_snapshot!(stmts_of_string(r#" + assert_yaml_snapshot!(parse(r#" let e = s"SELECT * FROM employees" - "#)?, @r###" + "#).unwrap(), @r###" --- - VarDef: name: e @@ -1673,7 +1557,7 @@ Canada - String: SELECT * FROM employees "###); - assert_yaml_snapshot!(stmts_of_string( + assert_yaml_snapshot!(parse( "let x = ( from x_table @@ -1683,7 +1567,7 @@ Canada ) from x" - )?, @r###" + ).unwrap(), @r###" --- - VarDef: name: x @@ -1697,7 +1581,6 @@ Canada args: - Ident: - x_table - named_args: {} - FuncCall: name: Ident: @@ -1706,7 +1589,6 @@ Canada - Ident: - foo alias: only_in_x - named_args: {} - Main: FuncCall: name: @@ -1715,15 +1597,12 @@ Canada args: - Ident: - x - named_args: {} "###); - - Ok(()) } #[test] fn test_inline_pipeline() { - assert_yaml_snapshot!(expr_of_string("(salary | percentile 50)", Rule::nested_pipeline).unwrap(), @r###" + assert_yaml_snapshot!(parse_expr("(salary | percentile 50)").unwrap(), @r###" --- Pipeline: exprs: @@ -1736,9 +1615,8 @@ Canada args: - Literal: Integer: 50 - named_args: {} "###); - assert_yaml_snapshot!(stmts_of_string("func median x -> (x | percentile 50)").unwrap(), @r###" + assert_yaml_snapshot!(parse("func median x -> (x | percentile 50)\n").unwrap(), @r###" --- - FuncDef: name: median @@ -1758,20 +1636,19 @@ Canada args: - Literal: Integer: 50 - named_args: {} return_ty: ~ "###); } #[test] - fn test_parse_sql_parameters() -> Result<()> { + fn test_sql_parameters() { assert_yaml_snapshot!(parse(r#" from mytable filter [ first_name == $1, last_name == $2.name ] - "#)?, @r###" + "#).unwrap(), @r###" --- - Main: Pipeline: @@ -1783,7 +1660,6 @@ Canada args: - Ident: - mytable - named_args: {} - FuncCall: name: Ident: @@ -1807,28 +1683,25 @@ Canada Ident: - $2 - name - named_args: {} "###); - Ok(()) } #[test] - fn test_tab_characters() -> Result<()> { + fn test_tab_characters() { // #284 - - let prql = "from c_invoice + parse( + "from c_invoice join doc:c_doctype [==c_invoice_id] select [ \tinvoice_no, \tdocstatus -]"; - parse(prql)?; - - Ok(()) +]", + ) + .unwrap(); } #[test] - fn test_parse_backticks() -> Result<()> { + fn test_backticks() { let prql = " from `a/*.parquet` aggregate [max c] @@ -1837,7 +1710,7 @@ join `my-proj.dataset.table` join `my-proj`.`dataset`.`table` "; - assert_yaml_snapshot!(parse(prql)?, @r###" + assert_yaml_snapshot!(parse(prql).unwrap(), @r###" --- - Main: Pipeline: @@ -1849,7 +1722,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - a/*.parquet - named_args: {} - FuncCall: name: Ident: @@ -1863,8 +1735,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - c - named_args: {} - named_args: {} - FuncCall: name: Ident: @@ -1878,7 +1748,6 @@ join `my-proj`.`dataset`.`table` expr: Ident: - id - named_args: {} - FuncCall: name: Ident: @@ -1886,7 +1755,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - my-proj.dataset.table - named_args: {} - FuncCall: name: Ident: @@ -1896,14 +1764,11 @@ join `my-proj`.`dataset`.`table` - my-proj - dataset - table - named_args: {} "###); - - Ok(()) } #[test] - fn test_parse_sort() -> Result<()> { + fn test_sort() { assert_yaml_snapshot!(parse(" from invoices sort issued_at @@ -1923,7 +1788,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - invoices - named_args: {} - FuncCall: name: Ident: @@ -1931,7 +1795,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - issued_at - named_args: {} - FuncCall: name: Ident: @@ -1942,7 +1805,6 @@ join `my-proj`.`dataset`.`table` expr: Ident: - issued_at - named_args: {} - FuncCall: name: Ident: @@ -1951,7 +1813,6 @@ join `my-proj`.`dataset`.`table` - List: - Ident: - issued_at - named_args: {} - FuncCall: name: Ident: @@ -1963,7 +1824,6 @@ join `my-proj`.`dataset`.`table` expr: Ident: - issued_at - named_args: {} - FuncCall: name: Ident: @@ -1977,137 +1837,16 @@ join `my-proj`.`dataset`.`table` expr: Ident: - amount - - Ident: - - num_of_articles - named_args: {} - "###); - - Ok(()) - } - - #[test] - fn test_range() { - assert_yaml_snapshot!(parse(" - from employees - filter (distance | in 0..40) - filter (distance | in (0)..40) - derive [ - greater_than_ten = 11.., - less_than_ten = ..9, - negative = (-5..), - more_negative = -10.., - dates_open = @2020-01-01.., - dates = @2020-01-01..@2021-01-01, - ] - ").unwrap(), @r###" - --- - - Main: - Pipeline: - exprs: - - FuncCall: - name: - Ident: - - from - args: - - Ident: - - employees - named_args: {} - - FuncCall: - name: - Ident: - - filter - args: - - Pipeline: - exprs: - - Ident: - - distance - - FuncCall: - name: - Ident: - - in - args: - - Range: - start: - Literal: - Integer: 0 - end: - Literal: - Integer: 40 - named_args: {} - named_args: {} - - FuncCall: - name: - Ident: - - filter - args: - - Pipeline: - exprs: - - Ident: - - distance - - FuncCall: - name: - Ident: - - in - args: - - Range: - start: - Literal: - Integer: 0 - end: - Literal: - Integer: 40 - named_args: {} - named_args: {} - - FuncCall: - name: - Ident: - - derive - args: - - List: - - Range: - start: - Literal: - Integer: 11 - end: ~ - alias: greater_than_ten - - Range: - start: ~ - end: - Literal: - Integer: 9 - alias: less_than_ten - - Range: - start: - Literal: - Integer: -5 - end: ~ - alias: negative - - Range: - start: - Literal: - Integer: -10 - end: ~ - alias: more_negative - - Range: - start: - Literal: - Date: 2020-01-01 - end: ~ - alias: dates_open - - Range: - start: - Literal: - Date: 2020-01-01 - end: - Literal: - Date: 2021-01-01 - alias: dates - named_args: {} + - Unary: + op: Add + expr: + Ident: + - num_of_articles "###); } #[test] - fn test_dates() -> Result<()> { + fn test_dates() { assert_yaml_snapshot!(parse(" from employees derive [age_plus_two_years = (age + 2years)] @@ -2123,7 +1862,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -2141,40 +1879,30 @@ join `my-proj`.`dataset`.`table` n: 2 unit: years alias: age_plus_two_years - named_args: {} "###); - assert_yaml_snapshot!(parse(" - derive [ - date = @2011-02-01, - timestamp = @2011-02-01T10:00, - time = @14:00, - # datetime = @2011-02-01T10:00, - ] - ").unwrap(), @r###" + assert_yaml_snapshot!(parse_expr("@2011-02-01").unwrap(), @r###" --- - - Main: - FuncCall: - name: - Ident: - - derive - args: - - List: - - Literal: - Date: 2011-02-01 - alias: date - - Literal: - Timestamp: "2011-02-01T10:00" - alias: timestamp - - Literal: - Time: "14:00" - alias: time - named_args: {} + Literal: + Date: 2011-02-01 "###); + assert_yaml_snapshot!(parse_expr("@2011-02-01T10:00").unwrap(), @r###" + --- + Literal: + Timestamp: "2011-02-01T10:00" + "###); + assert_yaml_snapshot!(parse_expr("@14:00").unwrap(), @r###" + --- + Literal: + Time: "14:00" + "###); + // assert_yaml_snapshot!(parse_expr("@2011-02-01T10:00").unwrap(), @""); + + parse_expr("@2020-01-0").unwrap_err(); - assert!(parse("derive x = @2020-01-0").is_err()); + parse_expr("@2020-01-011").unwrap_err(); - Ok(()) + parse_expr("@2020-01-01T111").unwrap_err(); } #[test] @@ -2192,12 +1920,11 @@ join `my-proj`.`dataset`.`table` - Ident: - r alias: x - named_args: {} "### ) } #[test] - fn test_parse_coalesce() { + fn test_coalesce() { assert_yaml_snapshot!(parse(r###" from employees derive amount = amount ?? 0 @@ -2213,7 +1940,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -2228,12 +1954,11 @@ join `my-proj`.`dataset`.`table` Literal: Integer: 0 alias: amount - named_args: {} "### ) } #[test] - fn test_parse_literal() { + fn test_literal() { assert_yaml_snapshot!(parse(r###" derive x = true "###).unwrap(), @r###" @@ -2247,12 +1972,11 @@ join `my-proj`.`dataset`.`table` - Literal: Boolean: true alias: x - named_args: {} "###) } #[test] - fn test_parse_allowed_idents() { + fn test_allowed_idents() { assert_yaml_snapshot!(parse(r###" from employees join _salary [==employee_id] # table with leading underscore @@ -2270,7 +1994,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -2284,7 +2007,6 @@ join `my-proj`.`dataset`.`table` expr: Ident: - employee_id - named_args: {} - FuncCall: name: Ident: @@ -2298,7 +2020,6 @@ join `my-proj`.`dataset`.`table` right: Ident: - $1 - named_args: {} - FuncCall: name: Ident: @@ -2308,12 +2029,11 @@ join `my-proj`.`dataset`.`table` - Ident: - _employees - _underscored_column - named_args: {} "###) } #[test] - fn test_parse_gt_lt_gte_lte() { + fn test_gt_lt_gte_lte() { assert_yaml_snapshot!(parse(r###" from people filter age >= 100 @@ -2332,7 +2052,6 @@ join `my-proj`.`dataset`.`table` args: - Ident: - people - named_args: {} - FuncCall: name: Ident: @@ -2346,7 +2065,6 @@ join `my-proj`.`dataset`.`table` right: Literal: Integer: 100 - named_args: {} - FuncCall: name: Ident: @@ -2360,7 +2078,6 @@ join `my-proj`.`dataset`.`table` right: Literal: Integer: 10 - named_args: {} - FuncCall: name: Ident: @@ -2374,7 +2091,6 @@ join `my-proj`.`dataset`.`table` right: Literal: Integer: 0 - named_args: {} - FuncCall: name: Ident: @@ -2388,7 +2104,6 @@ join `my-proj`.`dataset`.`table` right: Literal: Integer: 2 - named_args: {} "###) } @@ -2409,7 +2124,6 @@ join s=salaries [==id] args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -2424,7 +2138,63 @@ join s=salaries [==id] expr: Ident: - id - named_args: {} + "###); + } + + #[test] + fn test_ident_with_keywords() { + assert_yaml_snapshot!(parse_expr(r"select [andrew, orion, lettuce, falsehood, null0]").unwrap(), @r###" + --- + FuncCall: + name: + Ident: + - select + args: + - List: + - Ident: + - andrew + - Ident: + - orion + - Ident: + - lettuce + - Ident: + - falsehood + - Ident: + - null0 + "###); + + assert_yaml_snapshot!(parse_expr(r"[false]").unwrap(), @r###" + --- + List: + - Literal: + Boolean: false + "###); + } + + #[test] + fn test_switch() { + assert_yaml_snapshot!(parse_expr(r#"switch [ + nickname != null -> nickname, + true -> null + ]"#).unwrap(), @r###" + --- + Switch: + - condition: + Binary: + left: + Ident: + - nickname + op: Ne + right: + Literal: "Null" + value: + Ident: + - nickname + - condition: + Literal: + Boolean: true + value: + Literal: "Null" "###); } } diff --git a/prql-compiler/src/parser/prql.pest b/prql-compiler/src/parser/prql.pest deleted file mode 100644 index b30651838c25..000000000000 --- a/prql-compiler/src/parser/prql.pest +++ /dev/null @@ -1,150 +0,0 @@ -WHITESPACE = _{ " " | "\t" } - -// TODO: maybe pass comments to AST (and potentially put them into SQL comments) -COMMENT = _{ "#" ~ (!NEWLINE ~ ANY) * } - -statements = _{ SOI ~ NEWLINE* ~ query_def ? ~ (func_def | var_def)* ~ pipeline_stmt? ~ EOI } - -query_def = { "prql" ~ named_arg* ~ NEWLINE+ } - -func_def = { "func" ~ func_def_name ~ func_def_params ~ "->" ~ expr_call ~ ( NEWLINE+ | &EOI ) } - -func_def_name = { ident_part ~ type_def? } -func_def_params = { func_def_param* } -func_def_param = { ident_part ~ type_def? ~ (":" ~ expr)? } -type_def = { "<" ~ type_term ~ ( "|" ~ type_term)* ~ ">" } -type_term = { ident_part ~ type_def? } - -var_def = { "let" ~ ident_part ~ "=" ~ expr_call ~ ( NEWLINE+ | &EOI ) } - -pipeline_stmt = { pipeline ~ ( NEWLINE+ | &EOI ) } - -// An ident is a sequence of word-like terms, separated by `.`. Where surrounded -// by backticks, the term is taken as-is, including any periods it contains. -// We allow `e.*`, but not just `*`, since it would conflict with multiply in some cases. -ident = ${ - !operator - ~ (ident_plain | ident_backticks) - ~ ("." ~ (ident_plain | ident_backticks | ident_star))* -} -ident_part = ${ ident_plain | ident_backticks } -// Either a normal ident (starting with a letter, `$` or `_`), or any string surrounded -// by backticks. -ident_plain = { ((ASCII_ALPHA | "$" | "_") ~ (ASCII_ALPHANUMERIC | "_" )* ) } -ident_backticks = _{ PUSH("`") ~ (!NEWLINE ~ string_inner)* ~ POP } -// This is split out so we can make `ident_part_next` silent, but still capture it. -ident_star = { "*" } - -pipe = _{ NEWLINE+ | "|" } -pipeline = { WHITESPACE* ~ expr_call ~ (pipe ~ expr_call)* } - -// Whitespace is required to prevent matching s"string". Forbid `operator_binary` so `a -// - b` can't parse as `a` & `-b` (but allow `select ![a]`) -func_call = ${ ident ~ WHITESPACE+ ~ (!operator_binary ~ (named_arg | alias | expr) ~ WHITESPACE*)+ } - -named_arg = !{ ident_part ~ ":" ~ !":" ~ expr } -// alias needs to be distinct from assign, so that in `join s=salaries [==id]`, -// `s=salaries` is parsed separately from `[==id]`, since aliases allow for an -// expr as an rvalue, but not a function call. -alias = !{ ident_part ~ "=" ~ !"=" ~ expr } -assign = !{ ident_part ~ "=" ~ !"=" ~ expr_call } - -expr_call = _{ (func_call | expr) } - -expr = !{ expr_coalesce ~ (operator_logical ~ expr)? } -expr_coalesce = { expr_compare ~ (operator_coalesce ~ expr_coalesce)? } -expr_compare = { expr_add ~ (operator_compare ~ expr_add)? } -expr_add = { expr_mul ~ (operator_add ~ expr_add)? } -expr_mul = { term ~ (operator_mul ~ expr_mul)? } - -term = _{ ( switch | s_string | f_string | range | literal | ident | nested_pipeline | expr_unary | list ) } -expr_unary = { ( operator_unary ~ ( nested_pipeline | ident | list )) } -literal = _{ value_and_unit | number | boolean | null | string | timestamp | date | time | "(" ~ literal ~ ")" } -// `assign | pipeline` based on discussion in #648 -list = { "[" ~ (NEWLINE* ~ (assign | pipeline) ~ ("," ~ NEWLINE* ~ (assign | pipeline) )* ~ ","?)? ~ NEWLINE* ~ "]" } -nested_pipeline = { "(" ~ (WHITESPACE | NEWLINE)* ~ pipeline? ~ (WHITESPACE | NEWLINE)* ~ ")" } - -// We haven't implemented escapes โ€”ย I think we can mostly pass those through to -// SQL, but there may be things we're missing. -// https://pest.rs/book/examples/rust/literals.html - -// We need to have a non-silent rule which contains the quotes -// โ€”ย `string` in this case โ€” because of -// https://github.com/pest-parser/pest/issues/583. Then when converting to AST, -// we only keep the `string_inner` and discard the `string` given it contains -// the quotes. -// -// TODO: I'm still a bit unclear how preceding and trailing spaces are working -// -- it seems that inner spaces are included without an atomic operator (or -// with `ANY`), but prceeding & trailing spaces require both `ANY` _and_ an -// atomic operator. We have some rudimentary tests for these. - -single_quote = _{ "\"" | "'" } -multi_quote = _{ "\""{3,} | "'"{3,} } -opening_quote = _{ PUSH(multi_quote) | PUSH(single_quote) } -// PEEK refers to the opening quote; `"` or `'` or multiple quotes. -string_inner = { ( !( PEEK ) ~ ANY )+ } -// Either > 3 quotes, or just one. Currently both of those can be multiline. -string = ${ opening_quote ~ string_inner? ~ POP } - -// We can use underscores within numbers -number_char = _{ ASCII_DIGIT | "_" } -// Numbers need to start and end with a digit. We implement the end by matching -// either a number_char that's not the final char, or a final char that's a digit. -number_part = _{ ( ASCII_DIGIT ) ~ (( number_char ~ &number_char )* ~ ( ASCII_DIGIT ~ !number_char ))? } -number = ${ operator_add? ~ number_part ~ ("." ~ number_part)? } - -boolean = ${ "true" | "false" } - -null = ${ "null" } - -range = ${ range_edge ~ ".." ~ range_edge } -range_edge = ${ literal? } - -operator = _{ operator_unary | operator_binary } -operator_binary = _{ operator_mul | operator_add | operator_compare | operator_logical | operator_coalesce } -operator_unary = ${ "-" | "+" | "!" | "==" } -operator_mul = ${ "*" | "/" | "%" } -operator_add = ${ "+" | "-" } -operator_compare = ${ "==" | "!=" | ">=" | "<=" | ">" | "<" } -operator_logical = ${ ("and" | "or") ~ &WHITESPACE } -operator_coalesce = ${ "??" } - -// If we have lots more string prefixes then we could just have a type -// `prefixed` string and parse in the parser, but manageable for now. -s_string = ${ "s" ~ opening_quote ~ interpolate_string_inner ~ POP } -f_string = ${ "f" ~ opening_quote ~ interpolate_string_inner ~ POP } -interpolate_string_inner = _{ - ( - interpolate_string_inner_literal | - double_open_bracket | - double_close_bracket | - ( "{" ~ pipeline ~ "}" ) - )* -} -double_open_bracket = { "{{" } -double_close_bracket = { "}}" } -// Anything apart from the quote (PEEK), the beginning of an expr (`{`), or a `}}` -interpolate_string_inner_literal = { ( !( PEEK | "{" | double_close_bracket ) ~ ANY )+ } - -unit = { "microseconds" | "milliseconds" | "seconds" | "minutes" | "hours" | "days" | "weeks" | "months" | "years" } -value_and_unit = ${ number ~ unit } - -date = ${ "@" ~ date_inner ~ &end_expr } -time = ${ "@" ~ time_inner ~ &end_expr } -timestamp = ${ "@" ~ timestamp_inner ~ &end_expr } -// We use the `inner` types as containing the data that we want to retain in the AST. -date_inner = ${ ASCII_DIGIT{4} ~ "-" ~ ASCII_DIGIT{2} ~ "-" ~ ASCII_DIGIT{2} } -// Times are liberally defined atm, we could make this more robust. -time_inner = ${ ASCII_DIGIT{2} ~ (( ":" | "." ) ~ ASCII_DIGIT* )* ~ ((( "+" | "-" ) ~ (ASCII_DIGIT | ":" )*) | "Z")? } -timestamp_inner = ${ date_inner ~ "T" ~ time_inner } - -// We can use this when want to ensure something is ending, like a date, so `@20-01-0` -// isn't treated like a time `@20-01` `-` (minus) `0`. -// (Not sure whether `..` should be here or in the items that allow it; feel -// free to demote it to those items if `end_expr` is used somewhere where it's -// not supported) -end_expr = _{ WHITESPACE | "," | ")" | "]" | EOI | NEWLINE | ".." } - -switch = { "switch" ~ "[" ~ (NEWLINE* ~ switch_case ~ ("," ~ NEWLINE* ~ switch_case )* ~ ","?)? ~ NEWLINE* ~ "]" } -switch_case = { expr_call ~ "->" ~ expr_call } diff --git a/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap b/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap similarity index 85% rename from prql-compiler/src/parser/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap rename to prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap index 66faeab9a4cb..d973041eff4d 100644 --- a/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__parse_pipeline_parse_tree.snap +++ b/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap @@ -1,6 +1,6 @@ --- source: prql-compiler/src/parser/mod.rs -expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../book/tests/prql/examples/variables-0.prql\").trim().replace(\"\\r\\n\",\n \"\\n\"), Rule::statements).unwrap()).unwrap()" +expression: "parse(&include_str!(\"../../../book/tests/prql/examples/variables-0.prql\")).unwrap()" --- - Main: Pipeline: @@ -12,7 +12,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - employees - named_args: {} - FuncCall: name: Ident: @@ -26,7 +25,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo right: Literal: String: USA - named_args: {} - FuncCall: name: Ident: @@ -51,7 +49,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo Ident: - benefits_cost alias: gross_cost - named_args: {} - FuncCall: name: Ident: @@ -65,7 +62,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo right: Literal: Integer: 0 - named_args: {} - FuncCall: name: Ident: @@ -89,7 +85,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - salary - named_args: {} - FuncCall: name: Ident: @@ -97,7 +92,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - gross_salary - named_args: {} - FuncCall: name: Ident: @@ -105,7 +99,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - salary - named_args: {} - FuncCall: name: Ident: @@ -113,7 +106,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - gross_salary - named_args: {} - FuncCall: name: Ident: @@ -121,7 +113,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - gross_cost - named_args: {} - FuncCall: name: Ident: @@ -129,13 +120,10 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - gross_cost - named_args: {} alias: sum_gross_cost - Ident: - count alias: ct - named_args: {} - named_args: {} - FuncCall: name: Ident: @@ -143,7 +131,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Ident: - sum_gross_cost - named_args: {} - FuncCall: name: Ident: @@ -157,7 +144,6 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo right: Literal: Integer: 200 - named_args: {} - FuncCall: name: Ident: @@ -165,5 +151,4 @@ expression: "stmts_of_parse_pairs(parse_tree_of_str(&include_str!(\"../../../boo args: - Literal: Integer: 20 - named_args: {} diff --git a/prql-compiler/src/parser/stmt.rs b/prql-compiler/src/parser/stmt.rs new file mode 100644 index 000000000000..3006cfbe0c1f --- /dev/null +++ b/prql-compiler/src/parser/stmt.rs @@ -0,0 +1,154 @@ +use std::{collections::HashMap, str::FromStr}; + +use chumsky::prelude::*; +use semver::VersionReq; + +use crate::ast::pl::*; + +use super::common::*; +use super::expr::*; +use super::lexer::Token; + +pub fn source() -> impl Parser, Error = Simple> { + query_def() + .or_not() + .chain::( + var_def() + .or(function_def()) + .separated_by(new_line().repeated()) + .allow_leading() + .allow_trailing(), + ) + .chain(main_pipeline().or_not()) + .then_ignore(end()) + .labelled("source file") +} + +fn main_pipeline() -> impl Parser> { + pipeline(expr_call()) + .map_with_span(into_expr) + .map(Box::new) + .map(StmtKind::Main) + .map_with_span(into_stmt) + .labelled("main pipeline") +} + +fn query_def() -> impl Parser> { + new_line() + .repeated() + .ignore_then(keyword("prql")) + .ignore_then( + // named arg + ident_part().then_ignore(ctrl(':')).then(expr()).repeated(), + ) + .then_ignore(new_line()) + .try_map(|args, span| { + let mut args: HashMap<_, _> = args.into_iter().collect(); + + let version = args + .remove("version") + .map(|v| match v.kind { + ExprKind::Literal(Literal::String(v)) => { + VersionReq::parse(&v).map_err(|e| e.to_string()) + } + _ => Err("version must be a sting literal".to_string()), + }) + .transpose() + .map_err(|msg| Simple::custom(span, msg))?; + + let other = args + .into_iter() + .flat_map(|(key, value)| match value.kind { + ExprKind::Ident(value) => Some((key, value.to_string())), + _ => None, + }) + .collect(); + + Ok(StmtKind::QueryDef(QueryDef { version, other })) + }) + .map_with_span(into_stmt) + .labelled("query header") +} + +fn var_def() -> impl Parser> { + keyword("let") + .ignore_then(ident_part()) + .then_ignore(ctrl('=')) + .then(expr_call().map(Box::new)) + .map(|(name, value)| VarDef { name, value }) + .map(StmtKind::VarDef) + .map_with_span(into_stmt) + .labelled("variable definition") +} + +fn function_def() -> impl Parser> { + keyword("func") + .ignore_then( + // func name + ident_part().then(type_expr().or_not()), + ) + .then( + // params + ident_part() + .then(type_expr().or_not()) + .then(ctrl(':').ignore_then(expr()).or_not()) + .repeated(), + ) + .then_ignore(just(Token::Arrow)) + .then(expr_call().map(Box::new)) + .then_ignore(new_line()) + .map(|(((name, return_ty), params), body)| { + let (pos, nam) = params + .into_iter() + .map(|((name, ty), default_value)| FuncParam { + name, + ty, + default_value, + }) + .partition(|p| p.default_value.is_none()); + + FuncDef { + name, + positional_params: pos, + named_params: nam, + body, + return_ty, + } + }) + .map(StmtKind::FuncDef) + .map_with_span(into_stmt) + .labelled("function definition") +} + +pub fn type_expr() -> impl Parser> { + recursive(|type_expr| { + let type_term = ident_part().then(type_expr.or_not()).map(|(name, param)| { + let ty = match TyLit::from_str(&name) { + Ok(t) => Ty::from(t), + Err(_) if name == "table" => Ty::Table(Frame::default()), + Err(_) => { + eprintln!("named type: {}", name); + Ty::Named(name.to_string()) + } + }; + + if let Some(param) = param { + Ty::Parameterized(Box::new(ty), Box::new(param)) + } else { + ty + } + }); + + type_term + .separated_by(ctrl('|')) + .delimited_by(ctrl('<'), ctrl('>')) + .map(|mut terms| { + if terms.len() == 1 { + terms.remove(0) + } else { + Ty::AnyOf(terms) + } + }) + }) + .labelled("type expression") +} diff --git a/prql-compiler/src/semantic/resolver.rs b/prql-compiler/src/semantic/resolver.rs index b0cd8af29b40..d4c4bcc0e948 100644 --- a/prql-compiler/src/semantic/resolver.rs +++ b/prql-compiler/src/semantic/resolver.rs @@ -227,6 +227,11 @@ impl AstFold for Resolver { Expr { kind, ..node } } + ExprKind::Unary { + op: UnOp::Add, + expr, + } => self.fold_expr(*expr)?, + ExprKind::Unary { op: UnOp::Not, expr, diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap index 7901f4f36660..7f629f209879 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap @@ -8,48 +8,48 @@ expression: "resolve_derive(r#\"\n func lag_day x -> s\"lag_day_todo( id: 15 Binary: left: - id: 12 - Ident: - - _frame - - a - - b - target_id: 6 + id: 16 + Binary: + left: + id: 12 + Ident: + - _frame + - a + - b + target_id: 6 + ty: Infer + op: Div + right: + id: 21 + SString: + - String: lag_day_todo( + - Expr: + id: 12 + Ident: + - _frame + - a + - b + target_id: 6 + ty: Infer + - String: ) + ty: Infer ty: Infer - op: Div + op: Sub right: - id: 20 - SString: - - String: lag_day_todo( - - Expr: - id: 12 - Ident: - - _frame - - a - - b - target_id: 6 - ty: Infer - - String: ) - ty: Infer - ty: Infer - op: Sub - right: - id: 22 - Binary: - left: id: 23 Literal: Integer: 1 ty: Literal: Integer - op: Add - right: - id: 13 - Ident: - - _frame - - a - - c - target_id: 6 - ty: Infer + ty: Infer + op: Add + right: + id: 13 + Ident: + - _frame + - a + - c + target_id: 6 ty: Infer ty: Literal: Column diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 4b3f16018b5f..0afc74a533bc 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2417,11 +2417,11 @@ fn test_unused_alias() { select n = [account.name] "###).unwrap_err(), @r###" Error: - โ•ญโ”€[:3:12] + โ•ญโ”€[:3:16] โ”‚ 3 โ”‚ select n = [account.name] - ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ unexpected assign to `n` + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ unexpected assign to `n` ยท ยท Help: move assign into the list: `[n = ...]` โ”€โ”€โ”€โ•ฏ @@ -2569,11 +2569,11 @@ fn test_direct_table_references() { ) .unwrap_err(), @r###" Error: - โ•ญโ”€[:3:15] + โ•ญโ”€[:3:14] โ”‚ 3 โ”‚ select s"{x}.field" - ยท โ”ฌ - ยท โ•ฐโ”€โ”€ table instance cannot be referenced directly + ยท โ”€โ”ฌโ”€ + ยท โ•ฐโ”€โ”€โ”€ table instance cannot be referenced directly ยท ยท Help: did you forget to specify the column name? โ”€โ”€โ”€โ•ฏ @@ -2890,11 +2890,11 @@ fn test_errors() { "###).unwrap_err(), @r###" Error: - โ•ญโ”€[:5:12] + โ•ญโ”€[:5:16] โ”‚ 5 โ”‚ derive y = (addadd 4 5 6) - ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ - ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `addadd` + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `addadd` โ”€โ”€โ”€โ•ฏ "###); @@ -2906,8 +2906,8 @@ fn test_errors() { โ•ญโ”€[:2:5] โ”‚ 2 โ”‚ from a select b - ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€ - ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `from` + ยท โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Too many arguments to function `from` โ”€โ”€โ”€โ•ฏ "###); From e40a6201617baff35751f5e1e4be3792cc4552cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Mon, 27 Feb 2023 21:50:47 +0100 Subject: [PATCH 071/184] feat: parse and compile params (#1957) --- CHANGELOG.md | 1 + prql-compiler/src/ast/pl/expr.rs | 8 +++++- prql-compiler/src/ast/pl/fold.rs | 1 + prql-compiler/src/ast/rq/expr.rs | 3 ++ prql-compiler/src/ast/rq/fold.rs | 1 + prql-compiler/src/parser/expr.rs | 16 +++++++++-- prql-compiler/src/parser/lexer.rs | 11 +++++++- prql-compiler/src/parser/mod.rs | 23 ++++++++++----- prql-compiler/src/semantic/context.rs | 2 +- prql-compiler/src/semantic/lowering.rs | 4 +-- prql-compiler/src/semantic/std.prql | 1 - prql-compiler/src/semantic/transforms.rs | 36 +----------------------- prql-compiler/src/sql/anchor.rs | 1 + prql-compiler/src/sql/gen_expr.rs | 1 + prql-compiler/src/test.rs | 27 ++++++++++++++++++ 15 files changed, 85 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c60fe61f27a1..953ea069121f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) +- Support for SQL parameters with similar syntax (#1957, @aljazerzen) **Fixes**: diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index cfba08fc4934..d23926e458f6 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -77,6 +77,9 @@ pub enum ExprKind { name: String, args: Vec, }, + + /// a placeholder for values provided after query is compiled + Param(String), } impl ExprKind { @@ -338,7 +341,7 @@ pub enum TableExternRef { /// Placeholder for a relation that will be provided later. /// This is very similar to relational s-strings and may not even be needed for now, so /// it's not documented anywhere. But it will be used in the future. - Anchor(String), + Param(String), // TODO: add other sources such as files, URLs } @@ -580,6 +583,9 @@ impl Display for Expr { ExprKind::BuiltInFunction { .. } => { f.write_str("")?; } + ExprKind::Param(id) => { + writeln!(f, "${id}")?; + } } Ok(()) diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index b82f9178a296..9d7664f80fe6 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -110,6 +110,7 @@ pub fn fold_expr_kind(fold: &mut T, expr_kind: ExprKind) -> name, args: fold.fold_exprs(args)?, }, + Param(id) => Param(id), // None of these capture variables, so we don't need to fold them. Literal(_) => expr_kind, diff --git a/prql-compiler/src/ast/rq/expr.rs b/prql-compiler/src/ast/rq/expr.rs index bf70f4745ffd..ba9f07a8bc40 100644 --- a/prql-compiler/src/ast/rq/expr.rs +++ b/prql-compiler/src/ast/rq/expr.rs @@ -40,6 +40,9 @@ pub enum ExprKind { name: String, args: Vec, }, + + /// Placeholder for + Param(String), } #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] diff --git a/prql-compiler/src/ast/rq/fold.rs b/prql-compiler/src/ast/rq/fold.rs index 1c799e35dfe0..ca0920244f41 100644 --- a/prql-compiler/src/ast/rq/fold.rs +++ b/prql-compiler/src/ast/rq/fold.rs @@ -233,6 +233,7 @@ pub fn fold_expr_kind(fold: &mut F, kind: ExprKind) -> Resul name, args: args.into_iter().map(|a| fold.fold_expr(a)).try_collect()?, }, + ExprKind::Param(id) => ExprKind::Param(id), ExprKind::Literal(_) => kind, }) diff --git a/prql-compiler/src/parser/expr.rs b/prql-compiler/src/parser/expr.rs index ea9c2d32cbc7..6a24915f7a44 100644 --- a/prql-compiler/src/parser/expr.rs +++ b/prql-compiler/src/parser/expr.rs @@ -86,9 +86,19 @@ pub fn expr() -> impl Parser> + Clone { ) .map(ExprKind::Switch); - let term = choice((literal, list, pipeline, interpolation, ident_kind, switch)) - .map_with_span(into_expr) - .boxed(); + let param = select! { Token::Param(id) => ExprKind::Param(id) }; + + let term = choice(( + literal, + list, + pipeline, + interpolation, + ident_kind, + switch, + param, + )) + .map_with_span(into_expr) + .boxed(); // Unary operators let term = term diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 11d63f491300..2fb468c716ad 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -9,6 +9,7 @@ pub enum Token { Ident(String), Keyword(String), Literal(Literal), + Param(String), Range { bind_left: bool, @@ -57,6 +58,11 @@ pub fn lexer() -> impl Parser)>, Error let literal = literal().map(Token::Literal); + let param = just('$') + .ignore_then(filter(|c: &char| c.is_alphanumeric() || *c == '_' || *c == '.').repeated()) + .collect::() + .map(Token::Param); + // s-string and f-strings let interpolation = one_of("sf") .then(quoted_string(true)) @@ -66,6 +72,7 @@ pub fn lexer() -> impl Parser)>, Error new_line.clone(), control_multi, interpolation, + param, control, literal, keyword, @@ -106,7 +113,7 @@ pub fn lexer() -> impl Parser)>, Error } pub fn ident_part() -> impl Parser> { - let plain = filter(|c: &char| c.is_ascii_alphabetic() || *c == '_' || *c == '$') + let plain = filter(|c: &char| c.is_ascii_alphabetic() || *c == '_') .map(Some) .chain::, _>( filter(|c: &char| c.is_ascii_alphanumeric() || *c == '_').repeated(), @@ -382,6 +389,8 @@ impl std::fmt::Display for Token { Self::Or => f.write_str("or"), Self::Coalesce => f.write_str("??"), + Self::Param(id) => write!(f, "${id}"), + Self::Range { bind_left, bind_right, diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 461cc0eb5d5f..466850b1cc26 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -1672,17 +1672,14 @@ Canada - first_name op: Eq right: - Ident: - - $1 + Param: "1" - Binary: left: Ident: - last_name op: Eq right: - Ident: - - $2 - - name + Param: 2.name "###); } @@ -2018,8 +2015,7 @@ join `my-proj`.`dataset`.`table` - first_name op: Eq right: - Ident: - - $1 + Param: "1" - FuncCall: name: Ident: @@ -2197,4 +2193,17 @@ join s=salaries [==id] Literal: "Null" "###); } + + #[test] + fn test_params() { + assert_yaml_snapshot!(parse_expr(r#"$2"#).unwrap(), @r###" + --- + Param: "2" + "###); + + assert_yaml_snapshot!(parse_expr(r#"$2_any_text"#).unwrap(), @r###" + --- + Param: 2_any_text + "###); + } } diff --git a/prql-compiler/src/semantic/context.rs b/prql-compiler/src/semantic/context.rs index e61af872ad52..a49fa788fbf3 100644 --- a/prql-compiler/src/semantic/context.rs +++ b/prql-compiler/src/semantic/context.rs @@ -75,7 +75,7 @@ pub enum TableExpr { LocalTable, /// A placeholder for a relation that will be provided later. - Anchor(String), + Param(String), } #[derive(Clone, Eq, Debug, PartialEq, Serialize, Deserialize)] diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index 25383b9dd744..32d1ab558d05 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -653,7 +653,7 @@ impl Lowerer { rq::ExprKind::BuiltInFunction { name, args } } - + pl::ExprKind::Param(id) => rq::ExprKind::Param(id), pl::ExprKind::FuncCall(_) | pl::ExprKind::Range(_) | pl::ExprKind::List(_) @@ -820,7 +820,7 @@ fn lower_table(lowerer: &mut Lowerer, table: context::TableDecl, fq_ident: Ident TableExpr::LocalTable => { extern_ref_to_relation(columns, TableExternRef::LocalTable(fq_ident.name)) } - TableExpr::Anchor(id) => extern_ref_to_relation(columns, TableExternRef::Anchor(id)), + TableExpr::Param(id) => extern_ref_to_relation(columns, TableExternRef::Param(id)), }; log::debug!("lowering table {name:?}, columns = {:?}", relation.columns); diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index 586a9dcaf94f..201bf929ad4a 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -59,4 +59,3 @@ func _is_null a -> _param.a == null # Misc func from_text
text `noresolve.format`:csv -> null -func anchor
id -> null diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs index 15c73cbbe44f..661ddc1de351 100644 --- a/prql-compiler/src/semantic/transforms.rs +++ b/prql-compiler/src/semantic/transforms.rs @@ -10,7 +10,7 @@ use crate::ast::pl::*; use crate::ast::rq::RelationColumn; use crate::error::{Error, Reason, WithErrorInfo}; -use super::context::{Decl, DeclKind, TableDecl, TableExpr}; +use super::context::{Decl, DeclKind}; use super::module::{Module, NS_FRAME, NS_PARAM}; use super::resolver::Resolver; use super::{Context, Frame}; @@ -375,40 +375,6 @@ pub fn cast_transform(resolver: &mut Resolver, closure: Closure) -> Result { - // yes, this is not a transform, but this is the most appropriate place for it - - let [id_expr] = unpack::<1>(closure); - - let id = match id_expr.kind { - ExprKind::Literal(Literal::String(text)) => text, - _ => { - return Err(Error::new(Reason::Expected { - who: Some("std.anchor".to_string()), - expected: "a string literal".to_string(), - found: format!("`{id_expr}`"), - }) - .with_span(id_expr.span) - .into()); - } - }; - - let ident = Ident::from_path(vec!["_anchor".to_string(), id.clone()]); - let entry = Decl { - declared_at: id_expr.id, - kind: DeclKind::TableDecl(TableDecl { - columns: vec![RelationColumn::Wildcard], - expr: TableExpr::Anchor(id), - }), - order: 0, - }; - resolver.context.root_mod.insert(ident.clone(), entry)?; - - let mut res = Expr::from(ExprKind::Ident(ident)); - res.alias = Some("anchor".to_string()); - return Ok(Ok(res)); - } - _ => return Ok(Err(closure)), }; diff --git a/prql-compiler/src/sql/anchor.rs b/prql-compiler/src/sql/anchor.rs index 4c0e0ece9b76..a81bcc37d63c 100644 --- a/prql-compiler/src/sql/anchor.rs +++ b/prql-compiler/src/sql/anchor.rs @@ -476,6 +476,7 @@ pub fn infer_complexity_expr(expr: &Expr) -> Complexity { rq::ExprKind::ColumnRef(_) | rq::ExprKind::Literal(_) | rq::ExprKind::SString(_) + | rq::ExprKind::Param(_) | rq::ExprKind::FString(_) => Complexity::Plain, } } diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 271b4a6a1833..f062989289e2 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -91,6 +91,7 @@ pub(super) fn translate_expr_kind(item: ExprKind, ctx: &mut Context) -> Result sql_ast::Expr::Identifier(sql_ast::Ident::new(format!("${id}"))), ExprKind::FString(f_string_items) => translate_fstring(f_string_items, ctx)?, ExprKind::Literal(l) => translate_literal(l, ctx)?, ExprKind::Switch(mut cases) => { diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 0afc74a533bc..7fe43edc3c11 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3293,3 +3293,30 @@ fn test_loop() { "### ); } + +#[test] +fn test_params() { + assert_display_snapshot!(compile(r#" + from i = invoices + filter $1 <= i.date or i.date <= $2 + select [ + i.id, + i.total, + ] + filter i.total > $3 + "#).unwrap(), + @r###" + SELECT + id, + total + FROM + invoices AS i + WHERE + ( + $1 <= date + OR date <= $2 + ) + AND total > $3 + "### + ); +} From 8fe72ecd1902f69adbaf377fdf02c9978888cb52 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 13:16:47 -0800 Subject: [PATCH 072/184] chore: Remove reference to pest grammar (#1977) This was causing a build failure on main --- book/src/internals/syntax-highlighting.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/book/src/internals/syntax-highlighting.md b/book/src/internals/syntax-highlighting.md index 2a2c3d8b0ca7..506d15e3a4f3 100644 --- a/book/src/internals/syntax-highlighting.md +++ b/book/src/internals/syntax-highlighting.md @@ -30,8 +30,3 @@ an index. and helix. The grammar can be found at [https://github.com/matthias-Q/tree-sitter-prql](https://github.com/matthias-Q/tree-sitter-prql). This is in a very early stage. - -While the [pest](https://pest.rs/) grammar at -[`prql-compiler/src/parser/prql.pest`](https://github.com/PRQL/prql/blob/main/prql-compiler/src/parser/prql.pest) -isn't used for syntax highlighting, it's the arbiter of truth given it currently -powers the PRQL compiler. From 410068ed2c712c9e30a636ce09d4c741b944671e Mon Sep 17 00:00:00 2001 From: Matthias Q <35303817+matthias-Q@users.noreply.github.com> Date: Mon, 27 Feb 2023 22:32:00 +0100 Subject: [PATCH 073/184] docs: update tree-sitter information (#1976) Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- book/src/internals/syntax-highlighting.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/book/src/internals/syntax-highlighting.md b/book/src/internals/syntax-highlighting.md index 506d15e3a4f3..7249f249f37f 100644 --- a/book/src/internals/syntax-highlighting.md +++ b/book/src/internals/syntax-highlighting.md @@ -28,5 +28,4 @@ an index. - [Tree-Sitter](https://tree-sitter.github.io/tree-sitter) โ€” used by the neovim and helix. The grammar can be found at - [https://github.com/matthias-Q/tree-sitter-prql](https://github.com/matthias-Q/tree-sitter-prql). - This is in a very early stage. + [https://github.com/PRQL/tree-sitter-prql](https://github.com/PRQL/tree-sitter-prql). From 340455f04ff1d94e02ea0ca46c0a56f93672a6d6 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 15:49:46 -0800 Subject: [PATCH 074/184] ci: Move to `baptiste0928/cargo-install` for CI (#1979) We were getting 404s on the existing action, and this is also faster once it's cached --- .github/actions/build-prql-js/action.yaml | 5 ++--- .github/workflows/test-rust.yaml | 4 +++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/actions/build-prql-js/action.yaml b/.github/actions/build-prql-js/action.yaml index 8843384d437c..804ed072502e 100644 --- a/.github/actions/build-prql-js/action.yaml +++ b/.github/actions/build-prql-js/action.yaml @@ -6,10 +6,9 @@ description: "" runs: using: composite steps: - - name: Install wasm-pack - uses: jetli/wasm-pack-action@v0.4.0 + - uses: baptiste0928/cargo-install@next with: - version: "latest" + crate: wasm-pack - name: Setup Node uses: actions/setup-node@v3 diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index c983bc6dab46..2c8d0f3b9625 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -20,7 +20,9 @@ jobs: with: key: ${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - - uses: jetli/wasm-bindgen-action@v0.2.0 + - uses: baptiste0928/cargo-install@next + with: + crate: wasm-bindgen-cli if: inputs.target_option == '--target=wasm32-unknown-unknown' - name: ๐Ÿ“Ž Clippy uses: richb-hanover/cargo@v1.1.0 From e934ce8138d65660b2c00541e8aa8990e71230f5 Mon Sep 17 00:00:00 2001 From: hbc Date: Tue, 28 Feb 2023 08:44:02 +0800 Subject: [PATCH 075/184] test: repro timestamp parsing issue (#1980) * test: repro timestamp parsing issue * Update prql-compiler/src/test.rs Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update prql-compiler/src/test.rs Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- prql-compiler/src/test.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 7fe43edc3c11..b47bedd5c3ad 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3320,3 +3320,22 @@ fn test_params() { "### ); } + +// TODO: fix this based on https://github.com/PRQL/prql/pull/1818 +#[test] +#[should_panic] +fn test_datetime_parsing() { + assert_display_snapshot!(compile(r#" + from test_tables + select [date = @2022-12-31, time = @08:30, timestamp = @2020-01-01T13:19:55-0800] + "#).unwrap(), + @r###" + SELECT + DATE '2022-12-31' AS date, + TIME '08:30' AS time, + TIMESTAMP '2020-01-01T13:19:55-0800' AS timestamp + FROM + test_table + "### + ); +} From 5d620566f0cd7b12be7a8b8eeb1ed8c88c978a1a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 16:59:52 -0800 Subject: [PATCH 076/184] chore: Fix typo (#1981) --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5507308038bd..9232d5453e70 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ rust-version = "1.65.0" version = "0.5.2" [profile.release.package.prql-js] -# Tell `rustc` to optimize for small code size. +# Tell `rust-js` to optimize for small code size. opt-level = "s" [workspace.metadata.release] From 9e6306c9b37eeb2ccc1ed3ef50a9a3d3401dc180 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 18:17:37 -0800 Subject: [PATCH 077/184] chore: Remove extraneous file (#1984) I must have committed this by mistake --- prql-compiler/prqlc/x.prql | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 prql-compiler/prqlc/x.prql diff --git a/prql-compiler/prqlc/x.prql b/prql-compiler/prqlc/x.prql deleted file mode 100644 index ed56de0b1bc9..000000000000 --- a/prql-compiler/prqlc/x.prql +++ /dev/null @@ -1,3 +0,0 @@ -let x = 2 + 2 - -from x From 3da40beea2b216862f72ccff456ab924c8232493 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 19:09:51 -0800 Subject: [PATCH 078/184] fix: Attempt to fix the chumsky break on MacOS (#1978) * fix: Attempt to fix the chumsky break on MacOS * Re-enable workflows * Excluding features from macos vs. wasm --- .github/workflows/test-all.yaml | 4 ---- .github/workflows/test-js.yaml | 3 --- Cargo.toml | 1 + prql-compiler/Cargo.toml | 9 +++++++-- prql-js/tests/test_all.js | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 0582d00a4983..653edc9acdbb 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -28,10 +28,6 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] target_option: ["", --target=wasm32-unknown-unknown] - # Combination of macos and wasm32 has a problem with crate psm, a dependency of chumsky - exclude: - - os: macos-latest - target_option: --target=wasm32-unknown-unknown uses: ./.github/workflows/test-rust.yaml with: os: ${{ matrix.os }} diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index baa88eeda2b2..b018d0e9414b 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -18,9 +18,6 @@ jobs: matrix: os: [ubuntu-latest, macos-latest, windows-latest] - # Combination of macos and wasm32 has a problem with crate psm, a dependency of chumsky - exclude: - - os: macos-latest steps: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 diff --git a/Cargo.toml b/Cargo.toml index 9232d5453e70..04b449a500f7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ members = [ # Note we don't have a `default-members = ["prql-compiler"]`, since that causes # commands like `cargo test` to only run tests from the default package. And # `cargo insta test` doesn't have a `--workspace` flag. +resolver = "2" [workspace.package] edition = "2021" diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index 3faa6d29a725..d2df7ea01bf7 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -15,7 +15,6 @@ metadata.msrv = "1.65.0" [dependencies] anyhow = {version = "1.0.57", features = ["backtrace"]} ariadne = "0.1.5" -chumsky = "0.9.0" csv = "1.2.0" enum-as-inner = "0.5.0" itertools = "0.10.3" @@ -31,13 +30,19 @@ sqlparser = {version = "0.30.0", features = ["serde"]} strum = {version = "0.24.0", features = ["std", "derive"]}# for converting enum variants to string strum_macros = "0.24.0" +# Chumsky issues in wasm (though we only see it when compiling on MacOS) +[target.'cfg(not(target_family="wasm"))'.dependencies] +chumsky = "0.9.0" +[target.'cfg(target_family="wasm")'.dependencies] +chumsky = {version = "0.9.0", features = ["ahash", "std"], default-features = false} + [dev-dependencies] cfg-if = "1.0" insta = {version = "1.28", features = ["colors", "glob", "yaml"]} # For integration tests [target.'cfg(not(target_family="wasm"))'.dev-dependencies] -chrono = {version = "0.4", features = [], default-features = false } +chrono = {version = "0.4", features = [], default-features = false} criterion = "0.4.0" postgres = "0.19.3" pretty_assertions = "1.3.0" diff --git a/prql-js/tests/test_all.js b/prql-js/tests/test_all.js index 624ab4040efb..7732e2c1e090 100644 --- a/prql-js/tests/test_all.js +++ b/prql-js/tests/test_all.js @@ -35,7 +35,7 @@ describe("prql-js", () => { it("should throw an error on invalid prql", () => { expect(() => - prql.compile("Mississippi has four Sโ€™s and four Iโ€™s.") + prql.compile("Mississippi has four Ss and four Is.") ).to.throw("Error"); }); From ea4c70895629ea73cee156c90ea6ab2e188a38c4 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 27 Feb 2023 22:01:06 -0800 Subject: [PATCH 079/184] ci: Reset cache (#1986) --- .github/workflows/test-rust.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index 2c8d0f3b9625..0ac9ed479b11 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -18,6 +18,11 @@ jobs: - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 with: + # Based on https://github.com/PRQL/prql/issues/1985, attempting to + # reset the cache. If necessary, we could do this on each release and + # have this update automatically (there's no variable that contains + # the current version unfortunately, though). + prefix-key: "0.5.2" key: ${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - uses: baptiste0928/cargo-install@next From 800c7a7926fa0317dbfb496c134512960903a36d Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 28 Feb 2023 01:02:26 -0800 Subject: [PATCH 080/184] test: Add test for query which blocks on chumsky (#1982) * test: Add test for query which blocks on chumsky Based on #1978. It will block tests, probably until timeout * Add a very minimal test --- prql-compiler/src/parser/lexer.rs | 6 +++-- prql-compiler/src/parser/mod.rs | 39 +++++++++++++++++++++++++++++-- prql-compiler/src/test.rs | 10 ++++++++ 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 2fb468c716ad..63ffae47357c 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -77,8 +77,10 @@ pub fn lexer() -> impl Parser)>, Error literal, keyword, ident, - )) - .recover_with(skip_then_retry_until([]).skip_start()); + )); + // TODO: Add this back when https://github.com/zesterer/chumsky/issues/301 + // is fixed. + // .recover_with(skip_then_retry_until([]).skip_start()); let comment = just('#').then(none_of('\n').repeated()); let comments = comment diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 466850b1cc26..ab2e6320c209 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -54,7 +54,13 @@ pub fn parse(source: &str) -> Result> { } fn convert_lexer_error(source: &str, e: Cheap) -> Error { - let found = source[e.span()].to_string(); + // TODO: is there a neater way of taking a span? We want to take it based on + // the chars, not the bytes, so can't just index into the str. + let found = source + .chars() + .skip(e.span().start) + .take(e.span().end() - e.span().start) + .collect(); let span = common::into_span(e.span()); Error::new(Reason::Unexpected { found }).with_span(span) @@ -164,7 +170,7 @@ mod test { use super::*; use anyhow::anyhow; - use insta::assert_yaml_snapshot; + use insta::{assert_debug_snapshot, assert_yaml_snapshot}; fn parse_expr(source: &str) -> Result> { let tokens = Parser::parse(&lexer::lexer(), source).map_err(|errs| { @@ -2206,4 +2212,33 @@ join s=salaries [==id] Param: 2_any_text "###); } + + #[test] + fn test_error_unicode_string() { + // Test various unicode strings successfully parse errors. We were + // getting loops in the lexer before. + parse("sโ€™ ").unwrap_err(); + parse("sโ€™").unwrap_err(); + parse(" sโ€™").unwrap_err(); + parse(" โ€™ s").unwrap_err(); + parse("โ€™s").unwrap_err(); + parse("๐Ÿ‘ sโ€™").unwrap_err(); + + let source = "Mississippi has four Sโ€™s and four Iโ€™s."; + assert_debug_snapshot!(parse(source).unwrap_err(), @r###" + Errors( + [ + Error { + span: Some( + span-chars-22-23, + ), + reason: Unexpected { + found: "โ€™", + }, + help: None, + }, + ], + ) + "###); + } } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index b47bedd5c3ad..be139b81725b 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2939,6 +2939,16 @@ fn test_errors() { ยท โ•ฐโ”€โ”€โ”€ `take` expected int or range, but found 1.8 โ”€โ”€โ”€โ•ฏ "###); + + assert_display_snapshot!(compile("Mississippi has four Sโ€™s and four Iโ€™s.").unwrap_err(), @r###" + Error: + โ•ญโ”€[:1:23] + โ”‚ + 1 โ”‚ Mississippi has four Sโ€™s and four Iโ€™s. + ยท โ”ฌ + ยท โ•ฐโ”€โ”€ unexpected โ€™ + โ”€โ”€โ”€โ•ฏ + "###); } #[test] From 7fce2b3607110ad19809c776a3a5ffca596a200b Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Wed, 1 Mar 2023 01:15:30 +0900 Subject: [PATCH 081/184] chore: fix typo (#1988) --- .github/workflows/test-all.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 653edc9acdbb..69658da969e6 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -115,7 +115,7 @@ jobs: - uses: baptiste0928/cargo-install@next with: crate: cargo-msrv - # Note this currently uses a manually mantained key in + # Note this currently uses a manually maintained key in # `prql-compiler/Cargo.toml`, because of # https://github.com/foresterre/cargo-msrv/issues/590 - name: Verify minimum rust version From 63b01fa4e343cd1e4e347bfaf81fd1cdc5676070 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 28 Feb 2023 11:11:53 -0800 Subject: [PATCH 082/184] refactor: Attempt to replace our `IntoOnly` with `ExactlyOne` (#1915) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: Attempt to replace our `IntoOnly` with `ExactlyOne` Since I originally wrote this (and others have iterated on it), Itertools released `ExactlyOne`, which has better errors and reduces our custom code. Unfortunately, I couldn't fix a rust type error, and spent too long on it already. So pushing what I have in case anyone wants to take a look. There's also a decent chance that we replace the `parser.rs` code, in which case this type error becomes moot, and we can merge this anyway. * remove IntoOnly completely - even from public API * Allow multiple ErrorMessages in prql-python --------- Co-authored-by: Aljaลพ Mur Erลพen --- prql-compiler/src/error.rs | 10 ----- prql-compiler/src/lib.rs | 1 - prql-compiler/src/semantic/resolver.rs | 4 +- prql-compiler/src/sql/gen_query.rs | 6 ++- prql-compiler/src/utils/mod.rs | 2 +- prql-compiler/src/utils/only.rs | 59 +++----------------------- prql-python/src/lib.rs | 4 +- 7 files changed, 14 insertions(+), 72 deletions(-) diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index 92f3f3492210..7861baeab3fd 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -6,8 +6,6 @@ use std::error::Error as StdError; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::{Add, Range}; -use crate::utils::IntoOnly; - #[derive(Clone, PartialEq, Eq, Copy, Serialize, Deserialize)] pub struct Span { pub start: usize, @@ -218,14 +216,6 @@ impl ErrorMessages { } } -impl IntoOnly for ErrorMessages { - type Item = ErrorMessage; - - fn into_only(self) -> Result { - self.inner.into_only() - } -} - impl ErrorMessage { fn compose_display<'a, C>(&self, source_id: &'a str, cache: C, color: bool) -> Option where diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs index 18894b6b5348..7107f45baaa6 100644 --- a/prql-compiler/src/lib.rs +++ b/prql-compiler/src/lib.rs @@ -87,7 +87,6 @@ mod test; mod utils; pub use error::{downcast, Error, ErrorMessage, ErrorMessages, Reason, SourceLocation, Span}; -pub use utils::IntoOnly; use once_cell::sync::Lazy; use semver::Version; diff --git a/prql-compiler/src/semantic/resolver.rs b/prql-compiler/src/semantic/resolver.rs index d4c4bcc0e948..f15003f4e3c5 100644 --- a/prql-compiler/src/semantic/resolver.rs +++ b/prql-compiler/src/semantic/resolver.rs @@ -760,15 +760,15 @@ fn env_of_closure(closure: Closure) -> (Module, Expr) { mod test { use anyhow::Result; use insta::assert_yaml_snapshot; + use itertools::Itertools; use crate::ast::pl::{Expr, Ty}; use crate::semantic::resolve_only; - use crate::utils::IntoOnly; fn parse_and_resolve(query: &str) -> Result { let (stmts, _) = resolve_only(crate::parser::parse(query)?, None)?; - Ok(*stmts.into_only()?.kind.into_main()?) + Ok(*stmts.into_iter().exactly_one()?.kind.into_main()?) } fn resolve_type(query: &str) -> Result { diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index fba04d0be692..421ce63d3170 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -16,7 +16,8 @@ use crate::ast::pl::{BinOp, JoinSide, Literal, RelationLiteral}; use crate::ast::rq::{CId, Expr, ExprKind, Query, RelationKind, TableRef, Transform}; use crate::sql::anchor::anchor_split; use crate::sql::preprocess::SqlRelationKind; -use crate::utils::{BreakUp, IntoOnly, Pluck}; +use crate::utils::{BreakUp, Pluck}; + use crate::Target; use super::context::AnchorContext; @@ -249,7 +250,8 @@ fn sql_select_query_of_pipeline( let projection = pipeline .pluck(|t| t.into_super_and(|t| t.into_select())) - .into_only() + .into_iter() + .exactly_one() .unwrap(); let projection = translate_wildcards(&ctx.anchor, projection); let projection = translate_select_items(projection.0, projection.1, ctx)?; diff --git a/prql-compiler/src/utils/mod.rs b/prql-compiler/src/utils/mod.rs index 0ff61841b1b1..792d55fbdf64 100644 --- a/prql-compiler/src/utils/mod.rs +++ b/prql-compiler/src/utils/mod.rs @@ -3,11 +3,11 @@ mod only; mod toposort; pub use id_gen::{IdGenerator, NameGenerator}; -use itertools::Itertools; pub use only::*; pub use toposort::toposort; use anyhow::Result; +use itertools::Itertools; pub trait OrMap { /// Merges two options into one using `f`. diff --git a/prql-compiler/src/utils/only.rs b/prql-compiler/src/utils/only.rs index 1a52e97027ee..0eef8df16664 100644 --- a/prql-compiler/src/utils/only.rs +++ b/prql-compiler/src/utils/only.rs @@ -1,46 +1,14 @@ -use anyhow::{anyhow, Result}; -use itertools::{Itertools, Position}; +use anyhow::Result; use crate::ast::pl::Expr; use crate::error::{Error, Reason}; -// Inspired by version in sqlparser-rs; I'm surprised there isn't a version in -// the stdlib / Itertools. -/// Returns the only element of an Iterator, or an error if it has more than one element. -pub trait IntoOnly { - type Item; - - fn into_only(self) -> Result; -} - -impl IntoOnly for I -where - I: IntoIterator, - // See below re using Debug. - // I: std::fmt::Debug, - // ::IntoIter: std::fmt::Debug, -{ - type Item = T; - - fn into_only(self) -> Result { - match self.into_iter().with_position().next() { - Some(Position::Only(item)) => Ok(item), - // Can't get the debug of the iterator because it's already - // consumed; is there a way around this? I guess we could show - // the items after the second, which is kinda weird. - Some(Position::First(_)) => Err(anyhow!("Expected only one element, but found more.",)), - None => Err(anyhow!("Expected one element, but found none.",)), - _ => unreachable!(), - } - } -} - -pub trait IntoOnlyNode { - fn into_only_node(self, who: &str, occupation: &str) -> Result; +pub trait ExactlyOneNode { + fn exactly_one_node(self, who: &str, occupation: &str) -> Result; } -impl IntoOnlyNode for Vec { - fn into_only_node(mut self, who: &str, occupation: &str) -> Result { +impl ExactlyOneNode for Vec { + fn exactly_one_node(mut self, who: &str, occupation: &str) -> Result { match self.len() { 1 => Ok(self.remove(0)), 0 => Err(Error { @@ -64,20 +32,3 @@ impl IntoOnlyNode for Vec { } } } - -pub trait Only { - fn only(&self) -> Result<&T>; -} - -impl Only for [T] -where - T: std::fmt::Debug, -{ - fn only(&self) -> Result<&T> { - if self.len() == 1 { - Ok(self.first().unwrap()) - } else { - Err(anyhow!("Expected 1 item, got {}; {:?}", self.len(), self)) - } - } -} diff --git a/prql-python/src/lib.rs b/prql-python/src/lib.rs index 1202df209d82..6beebe154a69 100644 --- a/prql-python/src/lib.rs +++ b/prql-python/src/lib.rs @@ -1,7 +1,7 @@ #![cfg(not(target_family = "wasm"))] use std::str::FromStr; -use prql_compiler::{self, IntoOnly, Target}; +use prql_compiler::{self, Target}; use pyo3::{exceptions, prelude::*}; #[pyfunction] @@ -11,7 +11,7 @@ pub fn compile(prql_query: &str, options: Option) -> PyResult(e.into_only().unwrap().reason))) + .map_err(|e| (PyErr::new::(e.to_string()))) } #[pyfunction] From 2a4b9e887d692f5079b8c57f4188c98ca9cce11a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 28 Feb 2023 11:47:53 -0800 Subject: [PATCH 083/184] devops: Add `bacon` config file (#1989) * devops: Add `bacon` config file I recently discovered `bacon`, which is great (thanks to @snth for the link), and replaces some of the `watchexec` and `task` watch tasks. This is an initial config file; it'll get some updates as folks use it more. I'll also update `development.md` once I've used it more (unless anyone gets there first...). * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- Taskfile.yml | 2 +- bacon.toml | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 bacon.toml diff --git a/Taskfile.yml b/Taskfile.yml index 15995412728a..0407891f50f6 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -58,7 +58,7 @@ tasks: cmds: # `--locked` installs from the underlying lock files (which is not the # default?!) - - cargo install --locked cargo-audit cargo-insta cargo-release + - cargo install --locked bacon cargo-audit cargo-insta cargo-release default-target mdbook mdbook-admonish mdbook-toc wasm-bindgen-cli wasm-pack # Can't install atm with `--locked` diff --git a/bacon.toml b/bacon.toml new file mode 100644 index 000000000000..765e2d35ba32 --- /dev/null +++ b/bacon.toml @@ -0,0 +1,64 @@ +# Initial bacon config file; edits and contributions welcome. + +default_job = "check" + +# PRQL additions +[jobs.test-rust-fast] +command = ['cargo', 'insta', 'test', '--accept', "--color=always", "-p=prql-compiler", "--lib"] +[jobs.test-rust] +command = ['cargo', 'insta', 'test', '--accept', "--color=always"] + +# Standard tasks + +[jobs.check] +command = ["cargo", "check", "--color", "always"] +need_stdout = false + +[jobs.check-all] +command = ["cargo", "check", "--all-targets", "--color", "always"] +need_stdout = false +watch = ["tests", "benches", "examples"] + +[jobs.clippy] +command = ["cargo", "clippy", "--all-targets", "--color", "always"] +need_stdout = false +watch = ["tests", "benches", "examples"] + +[jobs.test] +command = ["cargo", "test", "--color", "always"] +need_stdout = true +watch = ["tests"] + +[jobs.doc] +command = ["cargo", "doc", "--color", "always", "--no-deps"] +need_stdout = false + +# If the doc compiles, then it opens in your browser and bacon switches +# to the previous job +[jobs.doc-open] +command = ["cargo", "doc", "--color", "always", "--no-deps", "--open"] +need_stdout = false +on_success = "back" # so that we don't open the browser at each change + +# You can run your application and have the result displayed in bacon, +# *if* it makes sense for this crate. You can run an example the same +# way. Don't forget the `--color always` part or the errors won't be +# properly parsed. +# If you want to pass options to your program, a `--` separator +# will be needed. +[jobs.run] +allow_warnings = true +command = ["cargo", "run", "--color", "always"] +need_stdout = true + +# You may define here keybindings that would be specific to +# a project, for example a shortcut to launch a specific job. +# Shortcuts to internal functions (scrolling, toggling, etc.) +# should go in your personal prefs.toml file instead. +[keybindings] +a = "job:check-all" +c = "job:clippy" +d = "job:doc-open" +i = "job:initial" +r = "job:run" +t = "job:test" From 9cd58a4bdbe43e112711e5624a895f13abee5315 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 28 Feb 2023 16:28:33 -0800 Subject: [PATCH 084/184] fix: Allow no `:` in timezones (#1991) feat: Allow no `:` in timezones Fixes issue in #1818 --- CHANGELOG.md | 2 ++ book/src/language-features/dates-and-times.md | 12 ++++++------ prql-compiler/src/parser/lexer.rs | 12 +++++++++--- prql-compiler/src/test.rs | 14 ++++++-------- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 953ea069121f..466005ed691d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) - Support for SQL parameters with similar syntax (#1957, @aljazerzen) +- Allow `:` to be elided in timezones, such as `0800` in + `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). **Fixes**: diff --git a/book/src/language-features/dates-and-times.md b/book/src/language-features/dates-and-times.md index 529eda6a6521..e788ffc33165 100644 --- a/book/src/language-features/dates-and-times.md +++ b/book/src/language-features/dates-and-times.md @@ -36,8 +36,8 @@ derive should_have_shipped_today = (order_time < @08:30) Timestamps are represented by `@{yyyy-mm-ddTHH:mm:ss.SSSยฑZ}` / `@{date}T{time}`, with any time parts not supplied being rounded to zero, including the timezone, -which is represented by `+HH:mm`, `-HH:mm` or `Z`. This isย `@` followed by the -ISO8601 datetime format, which uses `T` to separate date & time. +which is represented by `+HH:mm`, `-HH:mm` or `Z` (`:` is optional). This isย `@` +followed by the ISO8601 datetime format, which uses `T` to separate date & time. ```prql from commits @@ -66,9 +66,9 @@ derive first_check_in = start + 10days Here's a fuller list of examples: -- `@20221231` is forbidden โ€” it must contain full punctuation (`-` and `:`), +- `@20221231` is invalid โ€” it must contain full punctuation (`-` and `:`), - `@2022-12-31` is a date -- `@2022-12` or `@2022` are forbidden โ€” SQL can't express a month, only a date +- `@2022-12` or `@2022` are invalid โ€” SQL can't express a month, only a date - `@16:54:32.123456` is a time - `@16:54:32`, `@16:54`, `@16` are all allowed, expressing `@16:54:32.000000`, `@16:54:00.000000`, `@16:00:00.000000` respectively @@ -76,8 +76,8 @@ Here's a fuller list of examples: - `@2022-12-31T16:54:32.123456Z` is a timestamp in UTC - `@2022-12-31T16:54+02` is timestamp in UTC+2 - `@2022-12-31T16:54+02:00` and `@2022-12-31T16:54+02` are datetimes in UTC+2 -- `@16:54+02` is forbidden โ€” time is always local, so it cannot have a timezone -- `@2022-12-31+02` is forbidden โ€” date is always local, so it cannot have a +- `@16:54+02` is invalid โ€” time is always local, so it cannot have a timezone +- `@2022-12-31+02` is invalid โ€” date is always local, so it cannot have a timezone ## Roadmap diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 63ffae47357c..7874aced3c19 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -230,9 +230,15 @@ fn literal() -> impl Parser> { .chain::( one_of("-+") .chain( - digits(2) - .chain(just(':')) - .chain(digits(2)) + // TODO: This is repeated without the `:`~ with an `or` + // because using `.or_not` triggers a request for + // type hints, which seems difficult to provide... Is there + // an easier way? + // + // (digits(2).chain(just(':').or_not()).chain(digits(2))) + // + (digits(2).chain(just(':')).chain(digits(2))) + .or(digits(2).chain(digits(2))) .or(just('Z').map(|x| vec![x])), ) .or_not() diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index be139b81725b..994347860a24 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3331,21 +3331,19 @@ fn test_params() { ); } -// TODO: fix this based on https://github.com/PRQL/prql/pull/1818 #[test] -#[should_panic] fn test_datetime_parsing() { assert_display_snapshot!(compile(r#" from test_tables select [date = @2022-12-31, time = @08:30, timestamp = @2020-01-01T13:19:55-0800] "#).unwrap(), @r###" - SELECT - DATE '2022-12-31' AS date, - TIME '08:30' AS time, - TIMESTAMP '2020-01-01T13:19:55-0800' AS timestamp - FROM - test_table + SELECT + DATE '2022-12-31' AS date, + TIME '08:30' AS time, + TIMESTAMP '2020-01-01T13:19:55-0800' AS timestamp + FROM + test_tables "### ); } From b666fb60b533cb25d29c141b5836b9acfb61eb8f Mon Sep 17 00:00:00 2001 From: hbc Date: Wed, 1 Mar 2023 08:36:30 +0800 Subject: [PATCH 085/184] fix: Fix sqlite datetime output (#1970) * test: add test case for sqlite datetime * feat: implement `is` helper for DialectHandler * fix: use datetime functions for sqlite dialect * style: fix lint issues * Update prql-compiler/src/sql/gen_expr.rs Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update prql-compiler/src/sql/gen_expr.rs Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update prql-compiler/src/sql/gen_expr.rs Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * test: move tests to test.rs * style: lint fix --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- prql-compiler/src/sql/dialect.rs | 10 +- prql-compiler/src/sql/gen_expr.rs | 212 ++++++++++++++++++++++++++++-- prql-compiler/src/test.rs | 44 +++++++ 3 files changed, 255 insertions(+), 11 deletions(-) diff --git a/prql-compiler/src/sql/dialect.rs b/prql-compiler/src/sql/dialect.rs index 6bc52b2859c7..18a74ef5e729 100644 --- a/prql-compiler/src/sql/dialect.rs +++ b/prql-compiler/src/sql/dialect.rs @@ -14,6 +14,7 @@ use core::fmt::Debug; use serde::{Deserialize, Serialize}; +use std::any::{Any, TypeId}; use strum::{EnumMessage, IntoEnumIterator}; /// SQL dialect. @@ -109,7 +110,7 @@ pub(super) enum ColumnExclude { Except, } -pub(super) trait DialectHandler { +pub(super) trait DialectHandler: Any { fn use_top(&self) -> bool { false } @@ -155,6 +156,13 @@ pub(super) trait DialectHandler { } } +impl dyn DialectHandler { + #[inline] + pub fn is(&self) -> bool { + TypeId::of::() == self.type_id() + } +} + impl DialectHandler for GenericDialect {} impl DialectHandler for PostgresDialect { diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index f062989289e2..2a6ed8aed55a 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -144,18 +144,17 @@ pub(super) fn translate_literal(l: Literal, ctx: &Context) -> Result sql_ast::Expr::Value(Value::Boolean(b)), Literal::Float(f) => sql_ast::Expr::Value(Value::Number(format!("{f:?}"), false)), Literal::Integer(i) => sql_ast::Expr::Value(Value::Number(format!("{i}"), false)), - Literal::Date(value) => sql_ast::Expr::TypedString { - data_type: sql_ast::DataType::Date, + Literal::Date(value) => translate_datetime_literal(sql_ast::DataType::Date, value, ctx), + Literal::Time(value) => translate_datetime_literal( + sql_ast::DataType::Time(None, sql_ast::TimezoneInfo::None), value, - }, - Literal::Time(value) => sql_ast::Expr::TypedString { - data_type: sql_ast::DataType::Time(None, sql_ast::TimezoneInfo::None), - value, - }, - Literal::Timestamp(value) => sql_ast::Expr::TypedString { - data_type: sql_ast::DataType::Timestamp(None, sql_ast::TimezoneInfo::None), + ctx, + ), + Literal::Timestamp(value) => translate_datetime_literal( + sql_ast::DataType::Timestamp(None, sql_ast::TimezoneInfo::None), value, - }, + ctx, + ), Literal::ValueAndUnit(vau) => { let sql_parser_datetime = match vau.unit.as_str() { "years" => DateTimeField::Year, @@ -185,6 +184,62 @@ pub(super) fn translate_literal(l: Literal, ctx: &Context) -> Result sql_ast::Expr { + if ctx.dialect.is::() { + translate_datetime_literal_with_sqlite_function(data_type, value) + } else { + translate_datetime_literal_with_typed_string(data_type, value) + } +} + +fn translate_datetime_literal_with_typed_string( + data_type: sql_ast::DataType, + value: String, +) -> sql_ast::Expr { + sql_ast::Expr::TypedString { data_type, value } +} + +fn translate_datetime_literal_with_sqlite_function( + data_type: sql_ast::DataType, + value: String, +) -> sql_ast::Expr { + // TODO: promote parsing timezone handling to the parser; we should be storing + // structured data rather than strings in the AST + let timezone_indicator_regex = Regex::new(r"([+-]\d{2}):?(\d{2})$").unwrap(); + let time_value = if let Some(groups) = timezone_indicator_regex.captures(value.as_str()) { + // formalize the timezone indicator to be [+-]HH:MM + // ref: https://www.sqlite.org/lang_datefunc.html + timezone_indicator_regex + .replace(&value, format!("{}:{}", &groups[1], &groups[2]).as_str()) + .to_string() + } else { + value + }; + + let arg = FunctionArg::Unnamed(FunctionArgExpr::Expr(sql_ast::Expr::Value( + Value::SingleQuotedString(time_value), + ))); + + let func_name = match data_type { + sql_ast::DataType::Date => data_type.to_string(), + sql_ast::DataType::Time(..) => data_type.to_string(), + sql_ast::DataType::Timestamp(..) => "DATETIME".to_string(), + _ => unreachable!(), + }; + + sql_ast::Expr::Function(Function { + name: ObjectName(vec![sql_ast::Ident::new(func_name)]), + args: vec![arg], + over: None, + distinct: false, + special: false, + }) +} + pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result { if ctx.query.pre_projection { log::debug!("translating {cid:?} pre projection"); @@ -931,4 +986,141 @@ mod test { Ok(()) } + + #[test] + fn test_translate_datetime_literal_with_sqlite_function() -> Result<()> { + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Date, + "2020-01-01".to_string(), + ), + @r###" +--- +Function: + name: + - value: DATE + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: 2020-01-01 + over: ~ + distinct: false + special: false +"### + ); + + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Time(None, sql_ast::TimezoneInfo::None), + "03:05".to_string(), + ), + @r###" +--- +Function: + name: + - value: TIME + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: "03:05" + over: ~ + distinct: false + special: false +"### + ); + + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Time(None, sql_ast::TimezoneInfo::None), + "03:05+08:00".to_string(), + ), + @r###" +--- +Function: + name: + - value: TIME + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: "03:05+08:00" + over: ~ + distinct: false + special: false +"### + ); + + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Time(None, sql_ast::TimezoneInfo::None), + "03:05+0800".to_string(), + ), + @r###" +--- +Function: + name: + - value: TIME + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: "03:05+08:00" + over: ~ + distinct: false + special: false +"### + ); + + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Timestamp(None, sql_ast::TimezoneInfo::None), + "2021-03-14T03:05+0800".to_string(), + ), + @r###" +--- +Function: + name: + - value: DATETIME + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: "2021-03-14T03:05+08:00" + over: ~ + distinct: false + special: false +"### + ); + + assert_yaml_snapshot!( + translate_datetime_literal_with_sqlite_function( + sql_ast::DataType::Timestamp(None, sql_ast::TimezoneInfo::None), + "2021-03-14T03:05+08:00".to_string(), + ), + @r###" +--- +Function: + name: + - value: DATETIME + quote_style: ~ + args: + - Unnamed: + Expr: + Value: + SingleQuotedString: "2021-03-14T03:05+08:00" + over: ~ + distinct: false + special: false +"### + ); + + Ok(()) + } } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 994347860a24..a99e58ce425f 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3328,6 +3328,50 @@ fn test_params() { ) AND total > $3 "### + ) +} + +// for #1969 +#[test] +fn test_datetime() { + let query = &r#" + from test_table + select [date = @2022-12-31, time = @08:30, timestamp = @2020-01-01T13:19:55-0800] + "#; + + assert_snapshot!( + compile(query).unwrap(), + @r###"SELECT + DATE '2022-12-31' AS date, + TIME '08:30' AS time, + TIMESTAMP '2020-01-01T13:19:55-0800' AS timestamp +FROM + test_table +"### + ) +} + +// for #1969 +#[test] +fn test_datetime_sqlite() { + let query = &r#" + from test_table + select [date = @2022-12-31, time = @08:30, timestamp = @2020-01-01T13:19:55-0800] + "#; + + let opts = Options::default() + .no_signature() + .with_target(Target::Sql(Some(sql::Dialect::SQLite))); + + assert_snapshot!( + crate::compile(query, &opts).unwrap(), + @r###"SELECT + DATE('2022-12-31') AS date, + TIME('08:30') AS time, + DATETIME('2020-01-01T13:19:55-08:00') AS timestamp +FROM + test_table +"### ); } From 4b4a8107670260645f0592a6bf4e13582b14cc15 Mon Sep 17 00:00:00 2001 From: Libing Chen Date: Wed, 1 Mar 2023 13:17:22 +0800 Subject: [PATCH 086/184] feat: adjust panic to Java Exception (#1971) * build: update to version 0.5.2 * feat: add Exception for method signature * chore: add Exception for test method * feat: adjust panic to Java Exception and add format method * chore: use implicit return * test: add compileWithError() to test compile with error * feat: add dialect, format and signature parameters for toSql method * chore: update toSql method signature * lint: code polishing reported by clippy * chore: code format * docs: adjust signature for toSQL() * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * docs: format * chore: introduce target dialect from https://github.com/PRQL/prql/blob/main/book/src/language-features/target.md * chore: rename dialect to target * Use target rather than dialect * lint * docs: add javadoc for toSql() --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos --- prql-java/DEVELOPMENT.md | 4 +- prql-java/java/pom.xml | 2 +- .../java/org/prql/prql4j/PrqlCompiler.java | 15 ++++- .../org/prql/prql4j/PrqlCompilerTest.java | 9 ++- prql-java/src/lib.rs | 61 +++++++++++++++---- 5 files changed, 72 insertions(+), 19 deletions(-) diff --git a/prql-java/DEVELOPMENT.md b/prql-java/DEVELOPMENT.md index a8dc766aa1eb..5d2933a86a32 100644 --- a/prql-java/DEVELOPMENT.md +++ b/prql-java/DEVELOPMENT.md @@ -8,8 +8,8 @@ We implement Rust bindings to Java with [JNI](https://docs.oracle.com/javase/8/docs/technotes/guides/jni/). First, define a native method -- -`public static native String toSql(String query)` for PrqlCompiler, `toJson` is -same. +`public static native String toSql(String query, String target, boolean format, boolean signature)` +for PrqlCompiler, `toJson` is same. And then implement it in Rust with this [crate](https://docs.rs/jni/latest/jni/). diff --git a/prql-java/java/pom.xml b/prql-java/java/pom.xml index 84d8bddd2339..d7276e6edff1 100644 --- a/prql-java/java/pom.xml +++ b/prql-java/java/pom.xml @@ -6,7 +6,7 @@ org.prqllang prql-java - 0.2.1 + 0.5.2 ${project.groupId}:${project.artifactId} prql-compiler api for java diff --git a/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java b/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java index 49f47d19728d..bf0efbf46f23 100644 --- a/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java +++ b/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java @@ -3,8 +3,19 @@ import java.io.IOException; public class PrqlCompiler { - public static native String toSql(String query); - public static native String toJson(String query); + + /** + * compile PRQL to SQL + * @param query PRQL query + * @param target target dialect, such as sql.mysql etc. Please refer PRQL Target and Version + * @param format format SQL or not + * @param signature comment signature or not + * @return SQL + * @throws Exception PRQL compile exception + */ + public static native String toSql(String query, String target, boolean format, boolean signature) throws Exception; + public static native String toJson(String query) throws Exception; + public static native String format(String query) throws Exception; static { try { diff --git a/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java b/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java index 4ca948b87959..5a8627d62c57 100644 --- a/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java +++ b/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java @@ -4,8 +4,8 @@ public class PrqlCompilerTest { @Test - public void compile() { - String found = PrqlCompiler.toSql("from table"); + public void compile() throws Exception { + String found = PrqlCompiler.toSql("from table", "sql.mysql", true, true); // remove signature found = found.substring(0, found.indexOf("\n\n--")); @@ -16,4 +16,9 @@ public void compile() { " table"; assert expected.equalsIgnoreCase(found); } + + @Test(expected = Exception.class) + public void compileWithError() throws Exception { + PrqlCompiler.toSql("from table | filter id >> 1", "sql.mysql", true, true); + } } diff --git a/prql-java/src/lib.rs b/prql-java/src/lib.rs index 6c59dfa9fb24..93e7052dc160 100644 --- a/prql-java/src/lib.rs +++ b/prql-java/src/lib.rs @@ -1,7 +1,8 @@ use jni::objects::{JClass, JString}; -use jni::sys::jstring; +use jni::sys::{jboolean, jstring}; use jni::JNIEnv; -use prql_compiler::{json, prql_to_pl, Options}; +use prql_compiler::{json, pl_to_prql, prql_to_pl, ErrorMessages, Options, Target}; +use std::str::FromStr; #[no_mangle] #[allow(non_snake_case)] @@ -9,16 +10,41 @@ pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_toSql( env: JNIEnv, _class: JClass, query: JString, + target: JString, + format: jboolean, + signature: jboolean, ) -> jstring { let prql_query: String = env .get_string(query) .expect("Couldn't get java string!") .into(); - let rs_sql_str: String = prql_compiler::compile(&prql_query, &Options::default()) - .expect("Couldn't compile query to prql!"); - env.new_string(rs_sql_str) - .expect("Couldn't create java string!") - .into_raw() + let target_str: String = env + .get_string(target) + .expect("Couldn't get java string") + .into(); + let prql_dialect: Target = Target::from_str(&target_str).unwrap_or(Target::Sql(None)); + let opt = Options { + format: format != 0, + target: prql_dialect, + signature_comment: signature != 0, + }; + let result = prql_compiler::compile(&prql_query, &opt); + java_string_with_exception(result, &env) +} + +#[no_mangle] +#[allow(non_snake_case)] +pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_format( + env: JNIEnv, + _class: JClass, + query: JString, +) -> jstring { + let prql_query: String = env + .get_string(query) + .expect("Couldn't get java string!") + .into(); + let result = prql_to_pl(&prql_query).and_then(pl_to_prql); + java_string_with_exception(result, &env) } #[no_mangle] @@ -32,9 +58,20 @@ pub extern "system" fn Java_org_prql_prql4j_PrqlCompiler_toJson( .get_string(query) .expect("Couldn't get java string!") .into(); - let rs_json_str: String = { prql_to_pl(&prql_query).and_then(json::from_pl) } - .expect("Couldn't get json from prql query!"); - env.new_string(rs_json_str) - .expect("Couldn't create java string!") - .into_raw() + let result = prql_to_pl(&prql_query).and_then(json::from_pl); + java_string_with_exception(result, &env) +} + +fn java_string_with_exception(result: Result, env: &JNIEnv) -> jstring { + if let Ok(text) = result { + env.new_string(text) + .expect("Couldn't create java string!") + .into_raw() + } else { + let exception = env.find_class("java/lang/Exception").unwrap(); + if let Err(e) = env.throw_new(exception, result.err().unwrap().to_string()) { + println!("Error throwing exception: {:?}", e); + } + std::ptr::null_mut() as jstring + } } From c75c7852756470c7359dddc5a603a2a94913dc8b Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Wed, 1 Mar 2023 18:46:19 +0900 Subject: [PATCH 087/184] build: add very experimental MegaLinter config files (#1974) * build: add MegaLinter config files * build: disable errors of some linters * chore: temporarily enable linting for all codes * build: disable stylelint because of looong time required in CI * chore: auto formatting * build: disable all Linter errors that are currently causing errors * build: disable markdown-link-chack's error * build: disable megalinter's GitHub comment reporter * chore: add comments in megalinter config files * docs: add note about MegaLinter * Revert "chore: temporarily enable linting for all codes" This reverts commit a665b2dd19bf6b16ba437d76b106a4e2e1582a43. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * build: fix workflow trigger not to run twice in PR from other branch --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/workflows/mega-linter.yaml | 105 +++++++++++++++++++++++++++ .mega-linter.yaml | 34 +++++++++ book/src/contributing/development.md | 3 + 3 files changed, 142 insertions(+) create mode 100644 .github/workflows/mega-linter.yaml create mode 100644 .mega-linter.yaml diff --git a/.github/workflows/mega-linter.yaml b/.github/workflows/mega-linter.yaml new file mode 100644 index 000000000000..542bcb365b59 --- /dev/null +++ b/.github/workflows/mega-linter.yaml @@ -0,0 +1,105 @@ +# This MegaLinter workflow is very experimental stage. Open to changes and updates. +# https://github.com/PRQL/prql/pull/1974 + +# MegaLinter GitHub Action configuration file +# More info at https://megalinter.io +name: MegaLinter + +on: + push: + branches: + - main + pull_request: + branches: + - main + +env: # Comment env block if you do not want to apply fixes + # Apply linter fixes configuration + # APPLY_FIXES: all # When active, APPLY_FIXES must also be defined as environment variable (in github/workflows/mega-linter.yml or other CI tool) + APPLY_FIXES_EVENT: pull_request # Decide which event triggers application of fixes in a commit or a PR (pull_request, push, all) + APPLY_FIXES_MODE: commit # If APPLY_FIXES is used, defines if the fixes are directly committed (commit) or posted in a PR (pull_request) + +concurrency: + group: ${{ github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + build: + name: MegaLinter + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 # If you use VALIDATE_ALL_CODEBASE = true, you can remove this line to improve performances + + # MegaLinter + - name: MegaLinter + id: ml + # You can override MegaLinter flavor used to have faster performances + # More info at https://megalinter.io/flavors/ + uses: oxsecurity/megalinter@v6 + env: + # All available variables are described in documentation + # https://megalinter.io/configuration/ + VALIDATE_ALL_CODEBASE: ${{ github.event_name == 'push' && github.ref + == 'refs/heads/main' }} # Validates all source when push on main, else just the git diff with main. Override with true if you always want to lint all sources + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ADD YOUR CUSTOM ENV VARIABLES HERE OR DEFINE THEM IN A FILE .mega-linter.yml AT THE ROOT OF YOUR REPOSITORY + # DISABLE: COPYPASTE,SPELL # Uncomment to disable copy-paste and spell checks + + # Upload MegaLinter artifacts + - name: Archive production artifacts + if: ${{ success() }} || ${{ failure() }} + uses: actions/upload-artifact@v3 + with: + name: MegaLinter reports + path: | + megalinter-reports + mega-linter.log + + # Create pull request if applicable (for now works only on PR from same repository, not from forks) + - name: Create Pull Request with applied fixes + id: cpr + if: + steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == + 'all' || env.APPLY_FIXES_EVENT == github.event_name) && + env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' + || github.event.pull_request.head.repo.full_name == github.repository) + uses: peter-evans/create-pull-request@v4 + with: + token: ${{ secrets.PAT || secrets.GITHUB_TOKEN }} + commit-message: "[MegaLinter] Apply linters automatic fixes" + title: "[MegaLinter] Apply linters automatic fixes" + labels: bot + - name: Create PR output + if: + steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == + 'all' || env.APPLY_FIXES_EVENT == github.event_name) && + env.APPLY_FIXES_MODE == 'pull_request' && (github.event_name == 'push' + || github.event.pull_request.head.repo.full_name == github.repository) + run: | + echo "Pull Request Number - ${{ steps.cpr.outputs.pull-request-number }}" + echo "Pull Request URL - ${{ steps.cpr.outputs.pull-request-url }}" + + # Push new commit if applicable (for now works only on PR from same repository, not from forks) + - name: Prepare commit + if: + steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == + 'all' || env.APPLY_FIXES_EVENT == github.event_name) && + env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && + (github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository) + run: sudo chown -Rc $UID .git/ + - name: Commit and push applied linter fixes + if: + steps.ml.outputs.has_updated_sources == 1 && (env.APPLY_FIXES_EVENT == + 'all' || env.APPLY_FIXES_EVENT == github.event_name) && + env.APPLY_FIXES_MODE == 'commit' && github.ref != 'refs/heads/main' && + (github.event_name == 'push' || + github.event.pull_request.head.repo.full_name == github.repository) + uses: stefanzweifel/git-auto-commit-action@v4 + with: + branch: + ${{ github.event.pull_request.head.ref || github.head_ref || + github.ref }} + commit_message: "[MegaLinter] Apply linters fixes" diff --git a/.mega-linter.yaml b/.mega-linter.yaml new file mode 100644 index 000000000000..680a2e9edbe4 --- /dev/null +++ b/.mega-linter.yaml @@ -0,0 +1,34 @@ +# This MegaLinter config is very experimental stage. Open to changes and updates. +# https://github.com/PRQL/prql/pull/1974 + +GITHUB_COMMENT_REPORTER: false +DISABLE: + - RUST + - JAVASCRIPT + - PYTHON +DISABLE_LINTERS: + - SPELL_CSPELL + - CSS_STYLELINT +DISABLE_ERRORS_LINTERS: + - COPYPASTE_JSCPD + - REPOSITORY_TRIVY + - REPOSITORY_CHECKOV + - REPOSITORY_DEVSKIM + - ACTION_ACTIONLINT + - BASH_SHELLCHECK + - C_CPPLINT + - CPP_CPPLINT + - DOCKERFILE_HADOLINT + - HTML_DJLINT + - HTML_HTMLHINT + - JAVA_CHECKSTYLE + - JAVA_PMD + - JSON_JSONLINT + - MAKEFILE_CHECKMAKE + - MARKDOWN_MARKDOWN_LINK_CHECK + - PHP_PHPCS + - PHP_PHPSTAN + - PHP_PSALM + - SPELL_MISSPELL + - SQL_TSQLLINT + - YAML_V8R diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index 2f482a58f65d..1d8e6666c362 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -253,6 +253,9 @@ Our tests, from the bottom of the pyramid to the top: on GitHub on every commit; any changes they make are added onto the branch automatically in an additional commit. + - Checking by [MegaLinter](https://megalinter.io/latest/), which includes more + Linters, is also done automatically on GitHub. (experimental) + - **Unit tests & inline insta snapshots** โ€” we rely on unit tests to rapidly check that our code basically works. We extensively use [Insta](https://insta.rs/), a snapshot testing tool which writes out the From 42112a5a760e839d93a5fc2c605c221b9b898d74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Wed, 1 Mar 2023 14:16:59 +0100 Subject: [PATCH 088/184] feat: error code (#1993) --- prql-compiler/src/error.rs | 23 ++++++++++++++++++-- prql-compiler/src/lib.rs | 2 ++ prql-compiler/src/parser/mod.rs | 1 + prql-compiler/src/semantic/lowering.rs | 3 ++- prql-compiler/src/test.rs | 28 ++++++++++++++++++++----- prql-compiler/src/utils/only.rs | 29 ++++++++++---------------- prql-js/package.json | 2 +- prql-js/tests/test_all.js | 24 +++++++++++++++++++++ 8 files changed, 85 insertions(+), 27 deletions(-) diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index 7861baeab3fd..e823777afa4d 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -17,6 +17,7 @@ pub struct Error { pub span: Option, pub reason: Reason, pub help: Option, + pub code: Option<&'static str>, } #[derive(Debug, Clone)] @@ -56,6 +57,7 @@ impl Error { span: None, reason, help: None, + code: None, } } @@ -72,10 +74,17 @@ impl Error { self.span = span; self } + + pub fn with_code(mut self, code: &'static str) -> Self { + self.code = Some(code); + self + } } #[derive(Debug, Clone, Serialize)] pub struct ErrorMessage { + /// Plain text of the error + pub code: Option, /// Plain text of the error pub reason: String, /// A list of suggestions of how to fix the error @@ -100,7 +109,11 @@ impl Display for ErrorMessage { .join("\n"); f.write_str(&message_without_trailing_spaces)?; } else { - f.write_str(&self.reason)?; + let code = (self.code.as_ref()) + .map(|c| format!("[{c}] ")) + .unwrap_or_default(); + + writeln!(f, "{}Error: {}", code, &self.reason)?; } Ok(()) } @@ -148,6 +161,7 @@ impl Display for ErrorMessages { } pub fn downcast(error: anyhow::Error) -> ErrorMessages { + let mut code = None; let mut span = None; let mut hint = None; @@ -171,6 +185,7 @@ pub fn downcast(error: anyhow::Error) -> ErrorMessages { let reason = match error.downcast::() { Ok(error) => { + code = error.code.map(|x| x.to_string()); span = error.span; hint = error.help; @@ -183,6 +198,7 @@ pub fn downcast(error: anyhow::Error) -> ErrorMessages { }; ErrorMessage { + code, reason, hint, span, @@ -227,9 +243,12 @@ impl ErrorMessage { let mut report = Report::build(ReportKind::Error, source_id, span.start) .with_config(config) - .with_message("") .with_label(Label::new((source_id, span)).with_message(&self.reason)); + if let Some(code) = &self.code { + report = report.with_code(code); + } + if let Some(hint) = &self.hint { report.set_help(hint); } diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs index 7107f45baaa6..4e5c2557db7f 100644 --- a/prql-compiler/src/lib.rs +++ b/prql-compiler/src/lib.rs @@ -297,6 +297,7 @@ mod tests { namespace: "target", }, help: None, + code: None, }, ) "###); @@ -310,6 +311,7 @@ mod tests { namespace: "target", }, help: None, + code: None, }, ) "###); diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index ab2e6320c209..60de65d6c7b3 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -2236,6 +2236,7 @@ join s=salaries [==id] found: "โ€™", }, help: None, + code: None, }, ], ) diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index 32d1ab558d05..92f36d1c4428 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -45,7 +45,8 @@ pub fn lower_ast_to_ir(statements: Vec, context: Context) -> Result { fn exactly_one_node(mut self, who: &str, occupation: &str) -> Result { match self.len() { 1 => Ok(self.remove(0)), - 0 => Err(Error { - reason: Reason::Expected { - who: Some(who.to_string()), - expected: format!("only one {occupation}"), - found: "none".to_string(), - }, - span: None, - help: None, - }), - _ => Err(Error { - reason: Reason::Expected { - who: Some(who.to_string()), - expected: format!("only one {occupation}"), - found: "more".to_string(), - }, - span: self[1].span, - help: None, - }), + 0 => Err(Error::new(Reason::Expected { + who: Some(who.to_string()), + expected: format!("only one {occupation}"), + found: "none".to_string(), + })), + _ => Err(Error::new(Reason::Expected { + who: Some(who.to_string()), + expected: format!("only one {occupation}"), + found: "more".to_string(), + }) + .with_span(self[1].span)), } } } diff --git a/prql-js/package.json b/prql-js/package.json index 06e58721e5ed..9e25e8fed74f 100644 --- a/prql-js/package.json +++ b/prql-js/package.json @@ -21,7 +21,7 @@ "build:bundler": "wasm-pack build --target bundler --release --out-dir dist/bundler && rm dist/bundler/.gitignore", "build:node": "wasm-pack build --target nodejs --release --out-dir dist/node && rm dist/node/.gitignore", "build:web": "wasm-pack build --target no-modules --release --out-dir dist/web && rm dist/web/.gitignore", - "test": "wasm-pack test --firefox && mocha tests" + "test": "mocha tests" }, "types": "dist/node/prql_js.d.ts", "version": "0.5.2" diff --git a/prql-js/tests/test_all.js b/prql-js/tests/test_all.js index 7732e2c1e090..57cc9d5a781c 100644 --- a/prql-js/tests/test_all.js +++ b/prql-js/tests/test_all.js @@ -100,4 +100,28 @@ describe("prql-js", () => { assert(targets.includes("sql.sqlite")); }); }); + + describe("compile error", () => { + it("should contain json", () => { + try { + prql.compile("from x | select a | select b"); + } catch (error) { + const errorMessages = JSON.parse(error.message).inner; + + assert(errorMessages.length > 0); + assert(errorMessages[0].display.includes("\n")); + assert(!errorMessages[0].reason.includes("\n")); + } + }); + + it("should contain error code", () => { + try { + prql.compile("let a = (from x)"); + } catch (error) { + const errorMessages = JSON.parse(error.message).inner; + + assert(errorMessages[0].code == "E0001"); + } + }); + }); }); From e835c28748f7633e774ee5a1060ab87fe67bb1b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Wed, 1 Mar 2023 16:17:17 +0100 Subject: [PATCH 089/184] feat: validate Options.target and allow sql.any (#1995) --- prql-compiler/src/lib.rs | 38 +++++++++++---------- prql-compiler/src/test.rs | 9 ++++- prql-js/src/lib.rs | 7 ++-- prql-js/tests/test_all.js | 2 +- prql-lib/libprql_lib.h | 3 ++ prql-lib/src/lib.rs | 45 ++++++++++++++++--------- prql-python/python/tests/test_all.py | 22 ++++++++----- prql-python/src/lib.rs | 49 ++++++++++++++-------------- 8 files changed, 102 insertions(+), 73 deletions(-) diff --git a/prql-compiler/src/lib.rs b/prql-compiler/src/lib.rs index 4e5c2557db7f..f88d4f133281 100644 --- a/prql-compiler/src/lib.rs +++ b/prql-compiler/src/lib.rs @@ -142,10 +142,12 @@ impl Default for Target { impl Target { pub fn names() -> Vec { - sql::Dialect::names() - .into_iter() - .map(|d| format!("sql.{d}")) - .collect() + let mut names = vec!["sql.any".to_string()]; + + let dialects = sql::Dialect::names(); + names.extend(dialects.into_iter().map(|d| format!("sql.{d}"))); + + names } } @@ -153,20 +155,20 @@ impl FromStr for Target { type Err = Error; fn from_str(s: &str) -> Result { - // We have a closure here because we can't create the error in the - // pipeline, since it needs to be in two places, and we'd need to clone. - // (Though possibly it's too optimize-y.) - let not_found_error = |s| { - Error::new(Reason::NotFound { - name: format!("{s:?}"), - namespace: "target".to_string(), - }) - }; - s.strip_prefix("sql.") - .ok_or_else(|| not_found_error(s)) - .map(sql::Dialect::from_str)? - .map(|x| Target::Sql(Some(x))) - .map_err(|_| not_found_error(s)) + if let Some(dialect) = s.strip_prefix("sql.") { + if dialect == "any" { + return Ok(Target::Sql(None)); + } + + if let Ok(dialect) = sql::Dialect::from_str(dialect) { + return Ok(Target::Sql(Some(dialect))); + } + } + + Err(Error::new(Reason::NotFound { + name: format!("{s:?}"), + namespace: "target".to_string(), + })) } } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 8312ff4c775b..b8133c689024 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3267,7 +3267,14 @@ fn test_header_target_error() { from a "#).unwrap_err(),@r###" Error: target `"sql.foo"` not found - "###) + "###); + + assert_display_snapshot!(compile(r#" + prql target:foo.bar + from a + "#).unwrap_err(),@r###" + Error: target `"foo.bar"` not found + "###); } #[test] diff --git a/prql-js/src/lib.rs b/prql-js/src/lib.rs index 2e17e7e48703..6a7a7add9571 100644 --- a/prql-js/src/lib.rs +++ b/prql-js/src/lib.rs @@ -53,9 +53,6 @@ pub struct CompileOptions { /// Defaults to true. pub format: bool, - /// Target to compile to (e.g. sql.postgres) - /// - /// If `None` is used, the `target` argument from the query header is used. #[wasm_bindgen(skip)] pub target: String, @@ -90,6 +87,10 @@ impl CompileOptions { Self::default() } + /// Target to compile to (e.g. sql.postgres) + /// + /// Defaults to `sql.any`, which uses `target` argument from the query header to determine + /// the SQL dialect. #[wasm_bindgen(getter)] pub fn target(&self) -> String { self.target.clone() diff --git a/prql-js/tests/test_all.js b/prql-js/tests/test_all.js index 57cc9d5a781c..5fb0b8a5256f 100644 --- a/prql-js/tests/test_all.js +++ b/prql-js/tests/test_all.js @@ -86,7 +86,7 @@ describe("prql-js", () => { it("should fallback to the target in header", () => { const opts = new prql.CompileOptions(); - opts.target = "sql.not_existing"; + opts.target = "sql.any"; const res = prql.compile("prql target:sql.mssql\nfrom a | take 1", opts); assert(res.includes("TOP (1)")); diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h index e605d46b9987..7e9ca050049c 100644 --- a/prql-lib/libprql_lib.h +++ b/prql-lib/libprql_lib.h @@ -16,6 +16,9 @@ typedef struct Options { bool format; /** * Target and dialect to compile to. + * + * Defaults to `sql.any`, which uses `target` argument from the query header to determine + * the SQL dialect. */ char *target; /** diff --git a/prql-lib/src/lib.rs b/prql-lib/src/lib.rs index ef00c96d5ccd..7c7e39f5eef8 100644 --- a/prql-lib/src/lib.rs +++ b/prql-lib/src/lib.rs @@ -27,11 +27,14 @@ pub unsafe extern "C" fn compile( ) -> c_int { let prql_query: String = c_str_to_string(prql_query); - let result = Ok(prql_query.as_str()) - .and_then(prql_compiler::prql_to_pl) - .and_then(prql_compiler::pl_to_rq) - .and_then(|rq| { - prql_compiler::rq_to_sql(rq, &options.as_ref().map(|o| o.into()).unwrap_or_default()) + let options = options.as_ref().map(convert_options).transpose(); + + let result = options + .and_then(|opts| { + Ok(prql_query.as_str()) + .and_then(prql_compiler::prql_to_pl) + .and_then(prql_compiler::pl_to_rq) + .and_then(|rq| prql_compiler::rq_to_sql(rq, &opts.unwrap_or_default())) }) .map_err(|e| e.composed("", &prql_query, false)); @@ -110,6 +113,9 @@ pub struct Options { pub format: bool, /// Target and dialect to compile to. + /// + /// Defaults to `sql.any`, which uses `target` argument from the query header to determine + /// the SQL dialect. pub target: *mut c_char, /// Emits the compiler signature as a comment after generated SQL @@ -142,15 +148,22 @@ unsafe fn c_str_to_string(c_str: *const c_char) -> String { CStr::from_ptr(c_str).to_string_lossy().into_owned() } -impl From<&Options> for prql_compiler::Options { - fn from(o: &Options) -> Self { - let target = unsafe { c_str_to_string(o.target) }; - let target = Target::from_str(&target).unwrap_or_default(); - - prql_compiler::Options { - format: o.format, - target, - signature_comment: o.signature_comment, - } - } +fn convert_options(o: &Options) -> Result { + let target = if o.target.is_null() { + Some(unsafe { c_str_to_string(o.target) }) + } else { + None + }; + let target = target + .as_deref() + .filter(|x| !x.is_empty()) + .unwrap_or("sql.any"); + + let target = Target::from_str(target).map_err(|e| prql_compiler::downcast(e.into()))?; + + Ok(prql_compiler::Options { + format: o.format, + target, + signature_comment: o.signature_comment, + }) } diff --git a/prql-python/python/tests/test_all.py b/prql-python/python/tests/test_all.py index a1a364f0a840..481f9055cae2 100644 --- a/prql-python/python/tests/test_all.py +++ b/prql-python/python/tests/test_all.py @@ -49,24 +49,28 @@ def test_compile_options(): """ query_mssql = "prql target:sql.mssql\nfrom a | take 3" + assert prql.compile(query_mssql).startswith("SELECT\n TOP (3) *\nFROM\n a") + options_with_known_target = prql.CompileOptions( format=False, signature_comment=False, target="sql.sqlite" ) - options_without_target = prql.CompileOptions(format=False, signature_comment=False) - options_with_unknown_target = prql.CompileOptions( - format=False, signature_comment=False, target="foo" - ) - - assert prql.compile(query_mssql).startswith("SELECT\n TOP (3) *\nFROM\n a") assert ( prql.compile(query_mssql, options_with_known_target) == "SELECT * FROM a LIMIT 3" ) + + options_without_target = prql.CompileOptions(format=False, signature_comment=False) assert ( prql.compile(query_mssql, options_without_target) == "SELECT TOP (3) * FROM a" ) - # TODO: This should be unknown target error? + + options_with_any_target = prql.CompileOptions( + format=False, signature_comment=False, target="sql.any" + ) assert ( - prql.compile(query_mssql, options_with_unknown_target) - == "SELECT TOP (3) * FROM a" + prql.compile(query_mssql, options_with_any_target) == "SELECT TOP (3) * FROM a" ) + + options_default = prql.CompileOptions() + res = prql.compile(query_mssql, options_default) + assert res.startswith("SELECT\n TOP (3)") diff --git a/prql-python/src/lib.rs b/prql-python/src/lib.rs index 6beebe154a69..332afdcd6df4 100644 --- a/prql-python/src/lib.rs +++ b/prql-python/src/lib.rs @@ -6,10 +6,15 @@ use pyo3::{exceptions, prelude::*}; #[pyfunction] pub fn compile(prql_query: &str, options: Option) -> PyResult { - Ok(prql_query) - .and_then(prql_compiler::prql_to_pl) - .and_then(prql_compiler::pl_to_rq) - .and_then(|rq| prql_compiler::rq_to_sql(rq, &options.map(|o| o.into()).unwrap_or_default())) + let options = options.map(convert_options).transpose(); + + options + .and_then(|opts| { + Ok(prql_query) + .and_then(prql_compiler::prql_to_pl) + .and_then(prql_compiler::pl_to_rq) + .and_then(|rq| prql_compiler::rq_to_sql(rq, &opts.unwrap_or_default())) + }) .map_err(|e| e.composed("", prql_query, false)) .map_err(|e| (PyErr::new::(e.to_string()))) } @@ -63,16 +68,10 @@ pub struct CompileOptions { /// Defaults to true. pub format: bool, - /// Target dialect to compile to. - /// - /// This is only changes the output for a relatively small subset of - /// features. + /// Target to compile to. /// - /// If something does not work in a specific dialect, please raise in a - /// GitHub issue. - /// - /// If `None` is used, the `target` argument from the query header is used. - /// If it does not exist, [Dialect::Generic] is used. + /// Defaults to "sql.any", which uses the `target` argument from the query + /// header to determine The SQL dialect. pub target: String, /// Emits the compiler signature as a comment after generated SQL @@ -84,8 +83,8 @@ pub struct CompileOptions { #[pymethods] impl CompileOptions { #[new] - pub fn new(format: bool, signature_comment: bool, target: Option) -> Self { - let target = target.unwrap_or_default(); + #[pyo3(signature = (*, format=true, signature_comment=true, target="sql.any".to_string()))] + pub fn new(format: bool, signature_comment: bool, target: String) -> Self { CompileOptions { format, target, @@ -94,16 +93,16 @@ impl CompileOptions { } } -impl From for prql_compiler::Options { - fn from(o: CompileOptions) -> Self { - let target = Target::from_str(&o.target).unwrap_or_default(); +fn convert_options( + o: CompileOptions, +) -> Result { + let target = Target::from_str(&o.target).map_err(|e| prql_compiler::downcast(e.into()))?; - prql_compiler::Options { - format: o.format, - target, - signature_comment: o.signature_comment, - } - } + Ok(prql_compiler::Options { + format: o.format, + target, + signature_comment: o.signature_comment, + }) } #[pyfunction] @@ -121,7 +120,7 @@ mod test { fn parse_for_python() { let opts = Some(CompileOptions { format: true, - target: String::new(), + target: "sql.any".to_string(), signature_comment: false, }); From 3fdb0c10e3aa2e824ef67b1b0c1b2b8ae330762f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 1 Mar 2023 22:56:16 -0800 Subject: [PATCH 090/184] test: Fix Elixir test from #1995 (#1999) --- prql-elixir/test/prql_test.exs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prql-elixir/test/prql_test.exs b/prql-elixir/test/prql_test.exs index 9053244598ce..bb7648b371a1 100644 --- a/prql-elixir/test/prql_test.exs +++ b/prql-elixir/test/prql_test.exs @@ -16,7 +16,7 @@ defmodule PRQLTest do test "return errors on invalid query" do excepted_result = - "{\"inner\":[{\"reason\":\"Unknown name invalid\",\"hint\":null,\"span\":{\"start\":0,\"end\":7},\"display\":\"Error: \\n โ•ญโ”€[:1:1]\\n โ”‚\\n 1 โ”‚ invalid\\n ยท โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ \\n ยท โ•ฐโ”€โ”€โ”€โ”€โ”€ Unknown name invalid\\nโ”€โ”€โ”€โ•ฏ\\n\",\"location\":{\"start\":[0,0],\"end\":[0,7]}}]}" + "{\"inner\":[{\"code\":null,\"reason\":\"Unknown name invalid\",\"hint\":null,\"span\":{\"start\":0,\"end\":7},\"display\":\"Error: \\n โ•ญโ”€[:1:1]\\n โ”‚\\n 1 โ”‚ invalid\\n ยท โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ \\n ยท โ•ฐโ”€โ”€โ”€โ”€โ”€ Unknown name invalid\\nโ”€โ”€โ”€โ•ฏ\\n\",\"location\":{\"start\":[0,0],\"end\":[0,7]}}]}" assert PRQL.compile("invalid", @compile_opts) == {:error, excepted_result} end From 7e8094f5b6d28e65aac4d7ee1ae73f191a141c39 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 10:07:51 -0800 Subject: [PATCH 091/184] chore: bump @duckdb/duckdb-wasm from 1.21.0 to 1.24.0 in /playground (#2000) Bumps [@duckdb/duckdb-wasm](https://github.com/duckdb/duckdb-wasm) from 1.21.0 to 1.24.0. - [Release notes](https://github.com/duckdb/duckdb-wasm/releases) - [Commits](https://github.com/duckdb/duckdb-wasm/compare/v1.21.0...v1.24.0) --- updated-dependencies: - dependency-name: "@duckdb/duckdb-wasm" dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- playground/package-lock.json | 46 ++++++++++++++++++------------------ playground/package.json | 2 +- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/playground/package-lock.json b/playground/package-lock.json index 3e8d7dd2ad9b..3cae1d7b48db 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "hasInstallScript": true, "dependencies": { - "@duckdb/duckdb-wasm": "^1.21.0", + "@duckdb/duckdb-wasm": "^1.24.0", "@monaco-editor/react": "^4.4.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", @@ -2281,11 +2281,11 @@ } }, "node_modules/@duckdb/duckdb-wasm": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@duckdb/duckdb-wasm/-/duckdb-wasm-1.21.0.tgz", - "integrity": "sha512-3HBqwAhkjGWUGY2zSk2YG9i6bjNeTO5tyhBTJC9asv4ChTjx4mY6j4PFpAgUNomLm+QEFx1XXZN/BjRfENLdZQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@duckdb/duckdb-wasm/-/duckdb-wasm-1.24.0.tgz", + "integrity": "sha512-ow3y5kNV5saNd9dK1PkoKq7I0yqOJsnuRA15p92/gIl37wsNq/hI1R5m1HBe02CAEBQPi14w7+EV9xzvduSfZA==", "dependencies": { - "apache-arrow": "^9.0.0" + "apache-arrow": "^11.0.0" } }, "node_modules/@eslint/eslintrc": { @@ -5056,14 +5056,14 @@ } }, "node_modules/apache-arrow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-9.0.0.tgz", - "integrity": "sha512-Myt0vtm7eRtg4dYQp1hb2A77jbPhCYZcPeNp1F0u7te3rWQtcDI3EOSLxToFywdLQ1hfPzhzdLfDL0tPQObJjw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-11.0.0.tgz", + "integrity": "sha512-M8J4y+DimIyS44w2KOmVfzNHbTroR1oDpBKK6BYnlu8xVB41lxTz0yLmapo8/WJVAt5XcinAxMm14M771dm/rA==", "dependencies": { "@types/command-line-args": "5.2.0", "@types/command-line-usage": "5.0.2", "@types/flatbuffers": "*", - "@types/node": "^17.0.36", + "@types/node": "18.7.23", "@types/pad-left": "2.1.1", "command-line-args": "5.2.1", "command-line-usage": "6.1.3", @@ -5077,9 +5077,9 @@ } }, "node_modules/apache-arrow/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "version": "18.7.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", + "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" }, "node_modules/arg": { "version": "5.0.2", @@ -19376,11 +19376,11 @@ "requires": {} }, "@duckdb/duckdb-wasm": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@duckdb/duckdb-wasm/-/duckdb-wasm-1.21.0.tgz", - "integrity": "sha512-3HBqwAhkjGWUGY2zSk2YG9i6bjNeTO5tyhBTJC9asv4ChTjx4mY6j4PFpAgUNomLm+QEFx1XXZN/BjRfENLdZQ==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@duckdb/duckdb-wasm/-/duckdb-wasm-1.24.0.tgz", + "integrity": "sha512-ow3y5kNV5saNd9dK1PkoKq7I0yqOJsnuRA15p92/gIl37wsNq/hI1R5m1HBe02CAEBQPi14w7+EV9xzvduSfZA==", "requires": { - "apache-arrow": "^9.0.0" + "apache-arrow": "^11.0.0" } }, "@eslint/eslintrc": { @@ -21525,14 +21525,14 @@ } }, "apache-arrow": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-9.0.0.tgz", - "integrity": "sha512-Myt0vtm7eRtg4dYQp1hb2A77jbPhCYZcPeNp1F0u7te3rWQtcDI3EOSLxToFywdLQ1hfPzhzdLfDL0tPQObJjw==", + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/apache-arrow/-/apache-arrow-11.0.0.tgz", + "integrity": "sha512-M8J4y+DimIyS44w2KOmVfzNHbTroR1oDpBKK6BYnlu8xVB41lxTz0yLmapo8/WJVAt5XcinAxMm14M771dm/rA==", "requires": { "@types/command-line-args": "5.2.0", "@types/command-line-usage": "5.0.2", "@types/flatbuffers": "*", - "@types/node": "^17.0.36", + "@types/node": "18.7.23", "@types/pad-left": "2.1.1", "command-line-args": "5.2.1", "command-line-usage": "6.1.3", @@ -21543,9 +21543,9 @@ }, "dependencies": { "@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==" + "version": "18.7.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.23.tgz", + "integrity": "sha512-DWNcCHolDq0ZKGizjx2DZjR/PqsYwAcYUJmfMWqtVU2MBMG5Mo+xFZrhGId5r/O5HOuMPyQEcM6KUBp5lBZZBg==" } } }, diff --git a/playground/package.json b/playground/package.json index 1de1b6c79627..379af98d2616 100644 --- a/playground/package.json +++ b/playground/package.json @@ -12,7 +12,7 @@ ] }, "dependencies": { - "@duckdb/duckdb-wasm": "^1.21.0", + "@duckdb/duckdb-wasm": "^1.24.0", "@monaco-editor/react": "^4.4.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^14.0.0", From db7b517972e68b673d9a3eea9b9b4c75180656d9 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 2 Mar 2023 20:25:33 -0800 Subject: [PATCH 092/184] fix: Allow unicode in identifiers (#2005) * fix: Allow unicode in identifiers Closes #2003. Thanks to @vanillajonathan for the report. --- CHANGELOG.md | 1 + prql-compiler/src/parser/lexer.rs | 6 ++---- prql-compiler/src/parser/mod.rs | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 466005ed691d..5672e83a7623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ - `prqlc compile` returns a non-zero exit code for invalid queries. (@max-sixty, #1924) +- Identifiers can contain any alphabetic unicode characters (@max-sixty, #2003) **Documentation**: diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 7874aced3c19..3b5e684dff12 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -115,11 +115,9 @@ pub fn lexer() -> impl Parser)>, Error } pub fn ident_part() -> impl Parser> { - let plain = filter(|c: &char| c.is_ascii_alphabetic() || *c == '_') + let plain = filter(|c: &char| c.is_alphabetic() || *c == '_') .map(Some) - .chain::, _>( - filter(|c: &char| c.is_ascii_alphanumeric() || *c == '_').repeated(), - ) + .chain::, _>(filter(|c: &char| c.is_alphanumeric() || *c == '_').repeated()) .collect(); let backticks = just('`') diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 60de65d6c7b3..12c6227a8368 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -2213,6 +2213,22 @@ join s=salaries [==id] "###); } + #[test] + fn test_unicode() { + let source = "from tรจte"; + assert_yaml_snapshot!(parse(source).unwrap(), @r###" + --- + - Main: + FuncCall: + name: + Ident: + - from + args: + - Ident: + - tรจte + "###); + } + #[test] fn test_error_unicode_string() { // Test various unicode strings successfully parse errors. We were From 5aa13a52468a28ecaf8faef71b430dbfcd9c1416 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Fri, 3 Mar 2023 14:51:23 +0100 Subject: [PATCH 093/184] test: convert a few unit tests to integration (#2006) --- prql-compiler/src/error.rs | 8 +- prql-compiler/src/sql/dialect.rs | 9 ++ prql-compiler/src/sql/gen_expr.rs | 18 ++- prql-compiler/src/sql/gen_projection.rs | 52 ++++----- prql-compiler/src/sql/gen_query.rs | 2 + prql-compiler/src/sql/mod.rs | 3 + prql-compiler/src/test.rs | 54 ++------- prql-compiler/tests/integration/main.rs | 15 ++- .../tests/integration/queries/distinct.prql | 4 + .../tests/integration/queries/group_all.prql | 5 + .../tests/integration/queries/pipelines.prql | 4 + .../tests/integration/queries/switch.prql | 8 ++ ...ntegration__tests__test@distinct.prql.snap | 106 ++++++++++++++++++ ...tegration__tests__test@group_all.prql.snap | 16 +++ ...tegration__tests__test@pipelines.prql.snap | 12 ++ .../integration__tests__test@switch.prql.snap | 16 +++ 16 files changed, 256 insertions(+), 76 deletions(-) create mode 100644 prql-compiler/tests/integration/queries/distinct.prql create mode 100644 prql-compiler/tests/integration/queries/group_all.prql create mode 100644 prql-compiler/tests/integration/queries/pipelines.prql create mode 100644 prql-compiler/tests/integration/queries/switch.prql create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@distinct.prql.snap create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@group_all.prql.snap create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@pipelines.prql.snap create mode 100644 prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index e823777afa4d..5ba0ece52685 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -81,7 +81,7 @@ impl Error { } } -#[derive(Debug, Clone, Serialize)] +#[derive(Clone, Serialize)] pub struct ErrorMessage { /// Plain text of the error pub code: Option, @@ -119,6 +119,12 @@ impl Display for ErrorMessage { } } +impl Debug for ErrorMessage { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + Display::fmt(&self, f) + } +} + // Needed for anyhow impl StdError for Error {} diff --git a/prql-compiler/src/sql/dialect.rs b/prql-compiler/src/sql/dialect.rs index 18a74ef5e729..64bbeb08e766 100644 --- a/prql-compiler/src/sql/dialect.rs +++ b/prql-compiler/src/sql/dialect.rs @@ -154,6 +154,11 @@ pub(super) trait DialectHandler: Any { fn requires_quotes_intervals(&self) -> bool { false } + + /// Support for GROUP BY * + fn stars_in_group(&self) -> bool { + true + } } impl dyn DialectHandler { @@ -183,6 +188,10 @@ impl DialectHandler for SQLiteDialect { fn has_concat_function(&self) -> bool { false } + + fn stars_in_group(&self) -> bool { + false + } } impl DialectHandler for MsSqlDialect { diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 2a6ed8aed55a..a1e90216c005 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -260,7 +260,7 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result { let column = match col.clone() { - RelationColumn::Wildcard => "*".to_string(), + RelationColumn::Wildcard => translate_star(ctx, None)?, RelationColumn::Single(name) => name.unwrap(), }; let t = &ctx.anchor.table_instances[tiid]; @@ -281,7 +281,9 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result "*".to_string(), + ColumnDecl::RelationColumn(_, _, RelationColumn::Wildcard) => { + translate_star(ctx, None)? + } _ => { let name = ctx.anchor.column_names.get(&cid).cloned(); @@ -298,6 +300,18 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result) -> Result { + if ctx.query.forbid_stars { + Err( + Error::new_simple("Target dialect does not support * in this position.") + .with_span(span) + .into(), + ) + } else { + Ok("*".to_string()) + } +} + pub(super) fn translate_sstring( items: Vec>, ctx: &mut Context, diff --git a/prql-compiler/src/sql/gen_projection.rs b/prql-compiler/src/sql/gen_projection.rs index 5d2504fb33da..8b7bb862dfca 100644 --- a/prql-compiler/src/sql/gen_projection.rs +++ b/prql-compiler/src/sql/gen_projection.rs @@ -23,33 +23,35 @@ pub(super) fn try_into_exprs( ) -> Result> { let (cids, excluded) = translate_wildcards(&ctx.anchor, cids); - cids.into_iter() - .map(|cid| { - let decl = ctx.anchor.column_decls.get(&cid).unwrap(); - - let ColumnDecl::RelationColumn(tiid, _, RelationColumn::Wildcard) = decl else { - // base case - return translate_cid(cid, ctx) - }; - - // wildcard - let t = &ctx.anchor.table_instances[tiid]; - let table_name = t.name.clone(); - - let ident = translate_ident(table_name, Some("*".to_string()), ctx); - if let Some(excluded) = excluded.get(&cid) { - if !excluded.is_empty() { - return Err(Error::new_simple( - "Excluding columns not supported as this position", - ) - .with_span(span) - .into()); - } + let mut res = Vec::new(); + for cid in cids { + let decl = ctx.anchor.column_decls.get(&cid).unwrap(); + + let ColumnDecl::RelationColumn(tiid, _, RelationColumn::Wildcard) = decl else { + // base case + res.push(translate_cid(cid, ctx)?); + continue; + }; + + // star + let t = &ctx.anchor.table_instances[tiid]; + let table_name = t.name.clone(); + + let ident = translate_star(ctx, span)?; + if let Some(excluded) = excluded.get(&cid) { + if !excluded.is_empty() { + return Err( + Error::new_simple("Excluding columns not supported as this position") + .with_span(span) + .into(), + ); } + } + let ident = translate_ident(table_name, Some(ident), ctx); - Ok(sql_ast::Expr::CompoundIdentifier(ident)) - }) - .try_collect() + res.push(sql_ast::Expr::CompoundIdentifier(ident)); + } + Ok(res) } type Excluded = HashMap>; diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index 421ce63d3170..6a8ba10805e5 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -284,7 +284,9 @@ fn sql_select_query_of_pipeline( .into_iter() .next(); let group_by: Vec = aggregate.map(|(part, _)| part).unwrap_or_default(); + ctx.query.forbid_stars = !ctx.dialect.stars_in_group(); let group_by = try_into_exprs(group_by, ctx, None)?; + ctx.query.forbid_stars = false; ctx.query.pre_projection = false; diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index 8e3c3da14c36..350d2d1defc1 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -82,6 +82,9 @@ struct QueryOpts { /// When true, queries will contain nested sub-queries instead of WITH CTEs. pub forbid_ctes: bool, + + /// When true, * are not allowed. + pub forbid_stars: bool, } impl Context { diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index b8133c689024..e57cc80fe3d5 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -154,29 +154,6 @@ fn test_precedence() { ); } -#[test] -fn test_pipelines() { - assert_display_snapshot!((compile(r###" - from employees - group dept (take 1) - "###).unwrap()), @r###" - SELECT - DISTINCT * - FROM - employees - "###); - - assert_display_snapshot!((compile(r###" - from employees - select [age | in 5..10] - "###).unwrap()), @r###" - SELECT - age BETWEEN 5 AND 10 - FROM - employees - "###); -} - #[test] fn test_append() { assert_display_snapshot!(compile(r###" @@ -2643,30 +2620,13 @@ fn test_name_shadowing() { fn test_group_all() { assert_display_snapshot!(compile( r###" - from e=employees - take 10 - join salaries [==emp_no] - group [e.*] (aggregate sal = (sum salaries.salary)) - "###).unwrap(), - @r###" - WITH table_1 AS ( - SELECT - * - FROM - employees AS e - LIMIT - 10 - ) - SELECT - table_0.*, - SUM(salaries.salary) AS sal - FROM - table_1 AS table_0 - JOIN salaries ON table_0.emp_no = salaries.emp_no - GROUP BY - table_0.* - "### - ); + prql target:sql.sqlite + + from a=albums + group a.* (aggregate count) + "###).unwrap_err(), @r###" + Error: Target dialect does not support * in this position. + "###); assert_display_snapshot!(compile( r###" diff --git a/prql-compiler/tests/integration/main.rs b/prql-compiler/tests/integration/main.rs index 484e05bc124d..6ead5ffe1ded 100644 --- a/prql-compiler/tests/integration/main.rs +++ b/prql-compiler/tests/integration/main.rs @@ -86,7 +86,13 @@ mod tests { } pub fn query_csv(conn: &Connection, sql: &str) -> String { - let mut statement = conn.prepare(sql).unwrap(); + let mut statement = conn + .prepare(sql) + .map_err(|e| { + println!("{e}"); + e + }) + .unwrap(); let csv_header = statement.column_names().join(","); let column_count = statement.column_count(); @@ -173,6 +179,13 @@ mod tests { let dt = DateTime::::column_result(value).unwrap(); dt.format("%Y-%m-%d %H:%M:%S").to_string() } + ValueRef::Boolean(b) => { + if b { + "1".to_string() + } else { + "0".to_string() + } + } t => unimplemented!("{t:?}"), } }) diff --git a/prql-compiler/tests/integration/queries/distinct.prql b/prql-compiler/tests/integration/queries/distinct.prql new file mode 100644 index 000000000000..593d4fdea3de --- /dev/null +++ b/prql-compiler/tests/integration/queries/distinct.prql @@ -0,0 +1,4 @@ +from tracks +select [album_id, genre_id] +group tracks.* (take 1) +sort tracks.* diff --git a/prql-compiler/tests/integration/queries/group_all.prql b/prql-compiler/tests/integration/queries/group_all.prql new file mode 100644 index 000000000000..a5a73e1c98ae --- /dev/null +++ b/prql-compiler/tests/integration/queries/group_all.prql @@ -0,0 +1,5 @@ +from a=albums +sort album_id +take 10 +join tracks [==album_id] +group [a.album_id, a.title] (aggregate price = (sum tracks.unit_price)) diff --git a/prql-compiler/tests/integration/queries/pipelines.prql b/prql-compiler/tests/integration/queries/pipelines.prql new file mode 100644 index 000000000000..2b3c6c6cf64a --- /dev/null +++ b/prql-compiler/tests/integration/queries/pipelines.prql @@ -0,0 +1,4 @@ +from tracks +sort track_id +take 20..25 +select [is_in_range = album_id | in 5..10] diff --git a/prql-compiler/tests/integration/queries/switch.prql b/prql-compiler/tests/integration/queries/switch.prql new file mode 100644 index 000000000000..19497776665a --- /dev/null +++ b/prql-compiler/tests/integration/queries/switch.prql @@ -0,0 +1,8 @@ +from tracks +sort milliseconds +select display = switch [ + composer != null -> composer, + genre_id < 17 -> 'no composer', + true -> f'unknown composer' +] +take 10 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@distinct.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@distinct.prql.snap new file mode 100644 index 000000000000..765cba4ceca1 --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@distinct.prql.snap @@ -0,0 +1,106 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/distinct.prql +--- +album_id,genre_id +1,1 +2,1 +3,1 +4,1 +5,1 +6,1 +7,1 +8,2 +9,3 +10,1 +11,4 +12,5 +13,2 +14,3 +15,3 +16,3 +17,3 +18,4 +19,3 +20,6 +21,7 +22,7 +23,7 +24,7 +25,7 +26,8 +27,8 +28,7 +29,9 +30,1 +31,1 +32,10 +33,7 +34,7 +35,3 +36,1 +37,1 +38,2 +39,4 +40,1 +41,7 +42,4 +43,1 +44,1 +45,7 +46,1 +47,7 +48,2 +49,2 +50,1 +51,2 +52,11 +53,7 +54,1 +55,1 +56,7 +57,7 +58,1 +59,1 +60,1 +61,1 +62,1 +63,1 +64,1 +65,1 +66,1 +67,1 +68,2 +69,7 +70,7 +71,7 +72,6 +73,6 +73,7 +74,4 +75,4 +76,1 +77,4 +78,7 +79,1 +80,1 +81,4 +82,1 +83,12 +84,7 +85,10 +86,7 +87,2 +88,3 +89,4 +90,1 +91,1 +92,3 +93,2 +94,1 +95,3 +96,3 +97,1 +98,13 +99,1 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@group_all.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@group_all.prql.snap new file mode 100644 index 000000000000..1b5c0359f1bb --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@group_all.prql.snap @@ -0,0 +1,16 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/group_all.prql +--- +album_id,title,price +1,For Those About To Rock We Salute You,9.9 +2,Balls to the Wall,0.99 +3,Restless and Wild,2.9699999999999998 +4,Let There Be Rock,7.920000000000001 +5,Big Ones,14.850000000000001 +6,Jagged Little Pill,12.870000000000001 +7,Facelift,11.88 +8,Warner 25 Anos,13.860000000000001 +9,Plays Metallica By Four Cellos,7.920000000000001 +10,Audioslave,13.860000000000001 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@pipelines.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@pipelines.prql.snap new file mode 100644 index 000000000000..f039b00e19b4 --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@pipelines.prql.snap @@ -0,0 +1,12 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/pipelines.prql +--- +is_in_range,track_id +0,20 +0,21 +0,22 +1,23 +1,24 +1,25 diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap new file mode 100644 index 000000000000..b53c9cc01eb9 --- /dev/null +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap @@ -0,0 +1,16 @@ +--- +source: prql-compiler/tests/integration/main.rs +expression: sqlite_out +input_file: prql-compiler/tests/integration/queries/switch.prql +--- +display,milliseconds +Samuel Rosa,1071 +no composer,4884 +no composer,6373 +no composer,6635 +L. Muggerud,7941 +no composer,11650 +L. Muggerud,21211 +unknown composer,29048 +Gilberto Gil,32287 +Chico Science,33149 From 0a1e6944cf7a9d458e8bb7670898acfff0bb02ff Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 3 Mar 2023 10:43:30 -0800 Subject: [PATCH 094/184] feat: Improve lexer error recovery (#2002) * feat: Improve lexer error recovery Upgrade to Chumsky 0.9.2 and add back recovery --- Cargo.lock | 4 ++-- prql-compiler/src/parser/lexer.rs | 6 ++---- prql-compiler/src/parser/mod.rs | 25 +++++++++++++++++++++++++ prql-compiler/src/test.rs | 14 ++++++++++++++ 4 files changed, 43 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e23cb065dab2..277baa6309a4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -446,9 +446,9 @@ dependencies = [ [[package]] name = "chumsky" -version = "0.9.0" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4d619fba796986dd538d82660b76e0b9756c6e19b2e4d4559ba5a57f9f00810" +checksum = "23170228b96236b5a7299057ac284a321457700bc8c41a4476052f0f4ba5349d" dependencies = [ "hashbrown 0.12.3", "stacker", diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 3b5e684dff12..2043ea8d9847 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -77,10 +77,8 @@ pub fn lexer() -> impl Parser)>, Error literal, keyword, ident, - )); - // TODO: Add this back when https://github.com/zesterer/chumsky/issues/301 - // is fixed. - // .recover_with(skip_then_retry_until([]).skip_start()); + )) + .recover_with(skip_then_retry_until([]).skip_start()); let comment = just('#').then(none_of('\n').repeated()); let comments = comment diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 12c6227a8368..f0680198ae66 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -97,6 +97,7 @@ fn convert_parser_error(e: Simple) -> Error { Error::new(Reason::Unexpected { found }) } else { let mut expected = expected; + expected.sort(); let expected = match expected.len() { 1 => expected.remove(0), 2 => expected.join(" or "), @@ -2254,6 +2255,30 @@ join s=salaries [==id] help: None, code: None, }, + Error { + span: Some( + span-chars-35-36, + ), + reason: Unexpected { + found: "โ€™", + }, + help: None, + code: None, + }, + Error { + span: Some( + span-chars-38-39, + ), + reason: Expected { + who: Some( + "identifier", + ), + expected: "* or an identifier", + found: "", + }, + help: None, + code: None, + }, ], ) "###); diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index e57cc80fe3d5..093bee57f2f0 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2914,6 +2914,20 @@ fn test_errors() { ยท โ”ฌ ยท โ•ฐโ”€โ”€ unexpected โ€™ โ”€โ”€โ”€โ•ฏ + Error: + โ•ญโ”€[:1:36] + โ”‚ + 1 โ”‚ Mississippi has four Sโ€™s and four Iโ€™s. + ยท โ”ฌ + ยท โ•ฐโ”€โ”€ unexpected โ€™ + โ”€โ”€โ”€โ•ฏ + Error: + โ•ญโ”€[:1:39] + โ”‚ + 1 โ”‚ Mississippi has four Sโ€™s and four Iโ€™s. + ยท โ”ฌ + ยท โ•ฐโ”€โ”€ identifier expected * or an identifier, but found + โ”€โ”€โ”€โ•ฏ "###); let err = compile( From 9afbd78ce7e48078845d8c5b551102272e4072bc Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 4 Mar 2023 10:50:43 -0800 Subject: [PATCH 095/184] feat: Improve error messages on EOI (#2008) * feat: Improve lexer error recovery Upgrade to Chumsky 0.9.2 and add back recovery * feat: Improve error messages on EOI Based on https://github.com/PRQL/prql/pull/2002#discussion_r1124184718 Also simplifies a code block * . --- prql-compiler/src/parser/mod.rs | 24 ++++++++++++------------ prql-compiler/src/test.rs | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index f0680198ae66..6c2fa9cf09e3 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -72,20 +72,20 @@ fn convert_parser_error(e: Simple) -> Error { .all(|t| matches!(t, None | Some(Token::NewLine))); let expected = e .expected() - .filter(|t| { - if just_whitespace { - true - } else { - !matches!(t, None | Some(Token::NewLine)) - } - }) - .map(|t| match t { - Some(t) => t.to_string(), - None => "end of input".to_string(), + // TODO: could we collapse this into a `filter_map`? (though semantically + // identical) + .filter(|t| just_whitespace || !matches!(t, None | Some(Token::NewLine))) + .map(|t| { + t.clone() + .map(|t| t.to_string()) + .unwrap_or_else(|| "end of input".to_string()) }) .collect_vec(); - let found = e.found().map(|c| c.to_string()).unwrap_or_default(); + let found = e + .found() + .map(|c| c.to_string()) + .unwrap_or_else(|| "end of input".to_owned()); let span = common::into_span(e.span()); @@ -2274,7 +2274,7 @@ join s=salaries [==id] "identifier", ), expected: "* or an identifier", - found: "", + found: "end of input", }, help: None, code: None, diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 093bee57f2f0..350b0b53f30b 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2926,7 +2926,7 @@ fn test_errors() { โ”‚ 1 โ”‚ Mississippi has four Sโ€™s and four Iโ€™s. ยท โ”ฌ - ยท โ•ฐโ”€โ”€ identifier expected * or an identifier, but found + ยท โ•ฐโ”€โ”€ identifier expected * or an identifier, but found end of input โ”€โ”€โ”€โ•ฏ "###); From 52aa29a5b46e514d4d1fc57c0afd5221fe656783 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 4 Mar 2023 13:55:37 -0800 Subject: [PATCH 096/184] devops: Adjust gitignore so `bacon` works with `insta` (#2011) --- .gitignore | 7 +++++-- bacon.toml | 3 ++- prql-dotnet/.gitignore | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 prql-dotnet/.gitignore diff --git a/.gitignore b/.gitignore index 51c4f04938a9..711ac9dd9583 100644 --- a/.gitignore +++ b/.gitignore @@ -21,5 +21,8 @@ _*.prql .task -prql-dotnet/**/bin -prql-dotnet/**/obj +# These shouldn't be committed, and cause watchers to re-run when they're +# created, which we don't want. That said, if ignoring them causes confusion +# (e.g. folks look at their git status to assess whether there are pending +# snapshots), we can adjust. +**/*.pending-snap diff --git a/bacon.toml b/bacon.toml index 765e2d35ba32..9e9e82362080 100644 --- a/bacon.toml +++ b/bacon.toml @@ -59,6 +59,7 @@ need_stdout = true a = "job:check-all" c = "job:clippy" d = "job:doc-open" -i = "job:initial" +# i for `insta` +i = "job:test-rust-fast" r = "job:run" t = "job:test" diff --git a/prql-dotnet/.gitignore b/prql-dotnet/.gitignore new file mode 100644 index 000000000000..1746e3269ed0 --- /dev/null +++ b/prql-dotnet/.gitignore @@ -0,0 +1,2 @@ +bin +obj From f2a1b884e2e5fbc48cbdbf55bd7327f6858bedba Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 4 Mar 2023 14:44:18 -0800 Subject: [PATCH 097/184] feat: Improve error messages for EOI more (#2012) Follow-up to #2008 --- prql-compiler/src/parser/mod.rs | 76 ++++++++++++++++++--------------- prql-compiler/src/test.rs | 2 +- 2 files changed, 43 insertions(+), 35 deletions(-) diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 6c2fa9cf09e3..aacc2a30a86b 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -67,14 +67,22 @@ fn convert_lexer_error(source: &str, e: Cheap) -> Error { } fn convert_parser_error(e: Simple) -> Error { - let just_whitespace = e + let span = common::into_span(e.span()); + + if let SimpleReason::Custom(message) = e.reason() { + return Error::new_simple(message).with_span(span); + } + + let is_all_whitespace = e .expected() .all(|t| matches!(t, None | Some(Token::NewLine))); - let expected = e + let expecteds = e .expected() // TODO: could we collapse this into a `filter_map`? (though semantically // identical) - .filter(|t| just_whitespace || !matches!(t, None | Some(Token::NewLine))) + // + // Only include whitespace if we're _only_ expecting whitespace + .filter(|t| is_all_whitespace || !matches!(t, None | Some(Token::NewLine))) .map(|t| { t.clone() .map(|t| t.to_string()) @@ -82,36 +90,40 @@ fn convert_parser_error(e: Simple) -> Error { }) .collect_vec(); - let found = e - .found() - .map(|c| c.to_string()) - .unwrap_or_else(|| "end of input".to_owned()); - - let span = common::into_span(e.span()); - - if let SimpleReason::Custom(message) = e.reason() { - return Error::new_simple(message).with_span(span); - } - - if expected.is_empty() || expected.len() > 10 { - Error::new(Reason::Unexpected { found }) + let expected = if expecteds.is_empty() || expecteds.len() > 10 { + return Error::new(Reason::Unexpected { + found: e + .found() + .map(|c| c.to_string()) + // I think a rare case where we have both no `expected` and no `found`. + // Would be good to know how often this happens; can improve if we are + // hitting it. + .unwrap_or_else(|| "end of input".to_string()), + }); } else { - let mut expected = expected; - expected.sort(); - let expected = match expected.len() { - 1 => expected.remove(0), - 2 => expected.join(" or "), + let mut expecteds = expecteds; + expecteds.sort(); + + match expecteds.len() { + 1 => expecteds.remove(0), + 2 => expecteds.join(" or "), _ => { - let last = expected.pop().unwrap(); - format!("one of {} or {last}", expected.join(", ")) + let last = expecteds.pop().unwrap(); + format!("one of {} or {last}", expecteds.join(", ")) } - }; + } + }; - Error::new(Reason::Expected { + match e.found() { + Some(found) => Error::new(Reason::Expected { who: e.label().map(|x| x.to_string()), expected, - found, - }) + found: found.to_string(), + }), + // We want a friendlier message than "found end of input"... + None => Error::new(Reason::Simple(format!( + "Expected {expected}, but didn't find anything before the end." + ))), } .with_span(span) } @@ -2269,13 +2281,9 @@ join s=salaries [==id] span: Some( span-chars-38-39, ), - reason: Expected { - who: Some( - "identifier", - ), - expected: "* or an identifier", - found: "end of input", - }, + reason: Simple( + "Expected * or an identifier, but didn't find anything before the end.", + ), help: None, code: None, }, diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 350b0b53f30b..d03dead1b9e2 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2926,7 +2926,7 @@ fn test_errors() { โ”‚ 1 โ”‚ Mississippi has four Sโ€™s and four Iโ€™s. ยท โ”ฌ - ยท โ•ฐโ”€โ”€ identifier expected * or an identifier, but found end of input + ยท โ•ฐโ”€โ”€ Expected * or an identifier, but didn't find anything before the end. โ”€โ”€โ”€โ•ฏ "###); From a07567231bed35562feb6283b648cc2cb17c04d2 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 4 Mar 2023 19:28:42 -0800 Subject: [PATCH 098/184] fix: Fix regression in @2012 (#2013) Demonstrates we don't have enough tests for error messages! (And that I was not conscientious...) --- prql-compiler/src/parser/mod.rs | 23 ++++++++++++++++++++++- prql-compiler/src/test.rs | 10 ++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index aacc2a30a86b..247a881dbfd9 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -99,7 +99,8 @@ fn convert_parser_error(e: Simple) -> Error { // Would be good to know how often this happens; can improve if we are // hitting it. .unwrap_or_else(|| "end of input".to_string()), - }); + }) + .with_span(span); } else { let mut expecteds = expecteds; expecteds.sort(); @@ -2291,4 +2292,24 @@ join s=salaries [==id] ) "###); } + + #[test] + fn test_error_unexpected() { + assert_debug_snapshot!(parse("Answer: T-H-A-T!").unwrap_err(), @r###" + Errors( + [ + Error { + span: Some( + span-chars-6-7, + ), + reason: Unexpected { + found: ":", + }, + help: None, + code: None, + }, + ], + ) + "###); + } } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index d03dead1b9e2..413fcae6ee06 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2937,6 +2937,16 @@ fn test_errors() { ) .unwrap_err(); assert_eq!(err.inner[0].code.as_ref().unwrap(), "E0001"); + + assert_display_snapshot!(compile("Answer: T-H-A-T!").unwrap_err(), @r###" + Error: + โ•ญโ”€[:1:7] + โ”‚ + 1 โ”‚ Answer: T-H-A-T! + ยท โ”ฌ + ยท โ•ฐโ”€โ”€ unexpected : + โ”€โ”€โ”€โ•ฏ + "###); } #[test] From b78ee5e0ab8ef4d74004461af49ee8970385eccb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 4 Mar 2023 19:48:27 -0800 Subject: [PATCH 099/184] chore: bump sqlparser from 0.30.0 to 0.31.0 (#2001) * chore: bump sqlparser from 0.30.0 to 0.31.0 Bumps [sqlparser](https://github.com/sqlparser-rs/sqlparser-rs) from 0.30.0 to 0.31.0. - [Release notes](https://github.com/sqlparser-rs/sqlparser-rs/releases) - [Changelog](https://github.com/sqlparser-rs/sqlparser-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/sqlparser-rs/sqlparser-rs/compare/v0.30.0...v0.31.0) --- updated-dependencies: - dependency-name: sqlparser dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] * . --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- Cargo.lock | 4 ++-- prql-compiler/Cargo.toml | 2 +- prql-compiler/src/sql/gen_query.rs | 2 ++ 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 277baa6309a4..b6d5897963b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2720,9 +2720,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.30.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67dc6ef36edb658196c3fef0464a80b53dbbc194a904e81f9bd4190f9ecc5b" +checksum = "f064eb7b163863163c29801910f763c6bfb563b8a8ca4c54193da4c1eea57547" dependencies = [ "log", "serde", diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index d2df7ea01bf7..c8ba776d9e0b 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -26,7 +26,7 @@ semver = {version = "1.0.14", features = ["serde"]} serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" sqlformat = "0.2.0" -sqlparser = {version = "0.30.0", features = ["serde"]} +sqlparser = {version = "0.31.0", features = ["serde"]} strum = {version = "0.24.0", features = ["std", "derive"]}# for converting enum variants to string strum_macros = "0.24.0" diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index 6a8ba10805e5..4465ba22c879 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -167,6 +167,7 @@ fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result, ctx: &mut Context) -> Result Date: Sat, 4 Mar 2023 22:57:00 -0800 Subject: [PATCH 100/184] docs: Add error messages to the book (#2015) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: Add error messages to the book This allows us to show and test error messages in the book, and adds an initial example. Unfortunately the initial example doesn't have a great error message! So that's something we could work on. It also updates the docs to add late binding โ€” now functions support that! * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * . * . * . * . * . --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 4 +- book/highlight-prql.js | 4 + book/src/lib.rs | 93 +++++++++++++++---- book/src/queries/functions.md | 25 ++--- book/src/syntax.md | 12 ++- book/tests/prql/queries/functions-5.prql | 9 ++ book/tests/prql/syntax-10.prql | 2 +- book/tests/prql/syntax-11.prql | 4 +- book/tests/prql/syntax-12.prql | 4 +- book/tests/prql/syntax-13.prql | 4 +- book/tests/prql/syntax-14.prql | 3 +- book/tests/prql/syntax-15.prql | 7 +- book/tests/prql/syntax-16.prql | 8 +- book/tests/prql/syntax-17.prql | 3 + book/tests/prql/syntax-7.prql | 7 +- book/tests/prql/syntax-8.prql | 10 +- book/tests/prql/syntax-9.prql | 6 +- book/tests/snapshot.rs | 27 ++++-- .../snapshot__@queries__functions-4.prql.snap | 1 + .../snapshot__@queries__functions-5.prql.snap | 16 ++++ .../snapshots/snapshot__@syntax-10.prql.snap | 5 +- .../snapshots/snapshot__@syntax-11.prql.snap | 7 +- .../snapshots/snapshot__@syntax-12.prql.snap | 9 +- .../snapshots/snapshot__@syntax-13.prql.snap | 9 +- .../snapshots/snapshot__@syntax-14.prql.snap | 7 +- .../snapshots/snapshot__@syntax-15.prql.snap | 10 +- .../snapshots/snapshot__@syntax-16.prql.snap | 10 +- .../snapshots/snapshot__@syntax-17.prql.snap | 13 +++ .../snapshots/snapshot__@syntax-7.prql.snap | 20 ++-- .../snapshots/snapshot__@syntax-8.prql.snap | 11 ++- .../snapshots/snapshot__@syntax-9.prql.snap | 5 +- ...ests__prql__queries__functions-5.prql.snap | 23 +++++ ...snapshot__tests__prql__syntax-10.prql.snap | 4 +- ...snapshot__tests__prql__syntax-11.prql.snap | 9 +- ...snapshot__tests__prql__syntax-12.prql.snap | 9 +- ...snapshot__tests__prql__syntax-13.prql.snap | 9 +- ...snapshot__tests__prql__syntax-14.prql.snap | 5 +- ...snapshot__tests__prql__syntax-15.prql.snap | 10 +- ...snapshot__tests__prql__syntax-16.prql.snap | 11 +-- ...snapshot__tests__prql__syntax-17.prql.snap | 13 +++ .../snapshot__tests__prql__syntax-7.prql.snap | 12 +-- .../snapshot__tests__prql__syntax-8.prql.snap | 12 ++- .../snapshot__tests__prql__syntax-9.prql.snap | 8 +- 43 files changed, 324 insertions(+), 156 deletions(-) create mode 100644 book/tests/prql/queries/functions-5.prql create mode 100644 book/tests/prql/syntax-17.prql create mode 100644 book/tests/snapshots/snapshot__@queries__functions-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__@syntax-17.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 5672e83a7623..0d1d273293ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ to be more similar to other conventional languages. - `and` now has a higher precedence than `or` (of same reason as the previous point). - - Dates, times and timestamps have a stricter parsing rules. + - Dates, times and timestamps have stricter parsing rules. - `let`, `func`, `prql`, `switch` are now treated as keywords. - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML @@ -33,6 +33,8 @@ **Documentation**: - Operator precedence (@aljazerzen, #1818) +- Error messages for invalid queries are displayed in the book (@max-sixty, + #2015) **Web**: diff --git a/book/highlight-prql.js b/book/highlight-prql.js index 6955c600b0cc..5f72ddd49f9e 100644 --- a/book/highlight-prql.js +++ b/book/highlight-prql.js @@ -215,6 +215,10 @@ Array.from(document.querySelectorAll("code.language-prql")).forEach( (a) => console.log(a) || hljs.highlightBlock(a) ); +Array.from(document.querySelectorAll("code.language-prql_error")).forEach( + (a) => console.log(a) || hljs.highlightBlock(a) +); + Array.from(document.querySelectorAll("code.language-prql_no_test")).forEach( (a) => console.log(a) || hljs.highlightBlock(a) ); diff --git a/book/src/lib.rs b/book/src/lib.rs index 1d8a8e067edc..74b749a61e80 100644 --- a/book/src/lib.rs +++ b/book/src/lib.rs @@ -13,7 +13,6 @@ use prql_compiler::compile; use pulldown_cmark::{CodeBlockKind, Event, Options, Parser, Tag}; use pulldown_cmark_to_cmark::cmark; use semver::{Version, VersionReq}; -use similar::DiffableStr; use std::{io, process}; /// Checks renderer support and runs the preprocessor. @@ -103,21 +102,50 @@ fn replace_examples(text: &str) -> Result { while let Some(event) = parser.next() { match event.clone() { - Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) if lang == "prql".into() => { - if let Some(Event::Text(text)) = parser.next() { - let prql = text.to_string(); - let options = prql_compiler::Options::default().no_signature(); - let html = table_of_comparison( - text.as_str().unwrap(), - &compile(&prql, &options).unwrap(), - ); - cmark_acc.push(Event::Html(html.into())); - - // Skip ending tag - parser.next(); - } else { - bail!("Expected text after PRQL code block"); - } + // Duplicative repetitive logic here and in + // [snapshot.rs/collect_book_examples]; could we unify? + Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) + if lang.starts_with("prql") => + { + let Some(Event::Text(text)) = parser.next() + else { + bail!("Expected text after PRQL code block") + }; + let prql = text.to_string(); + let options = prql_compiler::Options::default().no_signature(); + let result = &compile(&prql, &options); + match lang.to_string().as_str() { + "prql" => cmark_acc.push(Event::Html( + table_of_comparison( + &prql, + result + .clone() + .unwrap_or_else(|_| { + panic!("{}", format!("Query raised an error: {prql}")) + }) + .as_str(), + ) + .into(), + )), + "prql_error" => cmark_acc.push(Event::Html( + table_of_error( + &prql, + result + .clone() + .expect_err( + &format!("Query was labeled to raise an error, but succeeded.\n {prql}").to_string(), + ) + .to_string() + .as_str(), + ) + .into(), + )), + "prql_no_test" => {} + _ => bail!("Unknown code block language: {}", lang), + }; + + // Skip ending tag + parser.next(); } _ => cmark_acc.push(event.to_owned()), } @@ -160,6 +188,39 @@ fn table_of_comparison(prql: &str, sql: &str) -> String { .to_string() } +// Exactly the same as `table_of_comparison`, but with a different title for the second column. +fn table_of_error(prql: &str, error: &str) -> String { + format!( + r#" +
+ +
+

PRQL

+ +```prql +{prql} +``` + +
+ +
+

Error

+ +``` +{error} +``` + +
+ +
+"#, + prql = prql.trim(), + error = error, + ) + .trim_start() + .to_string() +} + #[test] fn test_table() -> Result<()> { use insta::assert_display_snapshot; diff --git a/book/src/queries/functions.md b/book/src/queries/functions.md index f49626786b04..14261442527e 100644 --- a/book/src/queries/functions.md +++ b/book/src/queries/functions.md @@ -75,21 +75,22 @@ from kettles derive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100) ``` -## Roadmap +## Scope ### Late binding -Currently, functions require a binding to variables in scope; they can't -late-bind to column names; so for example: +Functions can binding to any variables in scope when the function is executed. +For example, here `cost_total` refers to the column that's introduced in the +`from`. -```prql_no_test -func return price -> (price - dividend) / price_yesterday -``` - -...isn't yet a valid function, and instead would needs to be: +```prql +func cost_share cost -> cost / cost_total -```prql_no_test -func return price dividend price_yesterday -> (price - dividend) / (price_yesterday) +from costs +select [materials, labor, overhead, cost_total] +derive [ + materials_share = (cost_share materials), + labor_share = (cost_share labor), + overhead_share = (cost_share overhead), +] ``` - -(which makes functions in this case not useful) diff --git a/book/src/syntax.md b/book/src/syntax.md index 4c7ca169eccc..dbe7dd41820e 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -166,9 +166,17 @@ sort (-distance) sort [-distance] ``` +This doesn't work, for example (though it should provide a much better error +message): + +```prql_error +from employees +derive total_distance = sum distance +``` + For a more formal definition, refer to this precedence table. Because function -call has the lowest precedence, nested function calls or arguments that start or -end with an operator require parenthesis. +calls have the lowest precedence, nested function calls or arguments that start +or end with an operator require parenthesis. | Group | Operators | Precedence | Associativity | | -------------- | ----------------- | ---------- | ------------- | diff --git a/book/tests/prql/queries/functions-5.prql b/book/tests/prql/queries/functions-5.prql new file mode 100644 index 000000000000..7875927c0806 --- /dev/null +++ b/book/tests/prql/queries/functions-5.prql @@ -0,0 +1,9 @@ +func cost_share cost -> cost / cost_total + +from costs +select [materials, labor, overhead, cost_total] +derive [ + materials_share = (cost_share materials), + labor_share = (cost_share labor), + overhead_share = (cost_share overhead), +] diff --git a/book/tests/prql/syntax-10.prql b/book/tests/prql/syntax-10.prql index b2ebba1b6488..d768dedf3f09 100644 --- a/book/tests/prql/syntax-10.prql +++ b/book/tests/prql/syntax-10.prql @@ -1,3 +1,3 @@ -prql target:sql.postgres +prql target:sql.mysql from employees select `first name` diff --git a/book/tests/prql/syntax-11.prql b/book/tests/prql/syntax-11.prql index e855d0393136..b2ebba1b6488 100644 --- a/book/tests/prql/syntax-11.prql +++ b/book/tests/prql/syntax-11.prql @@ -1 +1,3 @@ -from `dir/*.parquet` +prql target:sql.postgres +from employees +select `first name` diff --git a/book/tests/prql/syntax-12.prql b/book/tests/prql/syntax-12.prql index a634b9554275..e855d0393136 100644 --- a/book/tests/prql/syntax-12.prql +++ b/book/tests/prql/syntax-12.prql @@ -1,3 +1 @@ -prql target:sql.bigquery -from `project-foo.dataset.table` -join `project-bar.dataset.table` [==col_bax] +from `dir/*.parquet` diff --git a/book/tests/prql/syntax-13.prql b/book/tests/prql/syntax-13.prql index a9ccfe89ed66..a634b9554275 100644 --- a/book/tests/prql/syntax-13.prql +++ b/book/tests/prql/syntax-13.prql @@ -1 +1,3 @@ -from `music.albums` +prql target:sql.bigquery +from `project-foo.dataset.table` +join `project-bar.dataset.table` [==col_bax] diff --git a/book/tests/prql/syntax-14.prql b/book/tests/prql/syntax-14.prql index 15be2cb62f61..a9ccfe89ed66 100644 --- a/book/tests/prql/syntax-14.prql +++ b/book/tests/prql/syntax-14.prql @@ -1,2 +1 @@ -from employees -filter id == $1 +from `music.albums` diff --git a/book/tests/prql/syntax-15.prql b/book/tests/prql/syntax-15.prql index 290e626cf825..15be2cb62f61 100644 --- a/book/tests/prql/syntax-15.prql +++ b/book/tests/prql/syntax-15.prql @@ -1,5 +1,2 @@ -from numbers -select [ - small = 1.000_000_1, - big = 5_000_000, -] +from employees +filter id == $1 diff --git a/book/tests/prql/syntax-16.prql b/book/tests/prql/syntax-16.prql index 029a0ea82464..290e626cf825 100644 --- a/book/tests/prql/syntax-16.prql +++ b/book/tests/prql/syntax-16.prql @@ -1,3 +1,5 @@ -std.from my_table -std.select [from = my_table.a, take = my_table.b] -std.take 3 +from numbers +select [ + small = 1.000_000_1, + big = 5_000_000, +] diff --git a/book/tests/prql/syntax-17.prql b/book/tests/prql/syntax-17.prql new file mode 100644 index 000000000000..029a0ea82464 --- /dev/null +++ b/book/tests/prql/syntax-17.prql @@ -0,0 +1,3 @@ +std.from my_table +std.select [from = my_table.a, take = my_table.b] +std.take 3 diff --git a/book/tests/prql/syntax-7.prql b/book/tests/prql/syntax-7.prql index f655f4637971..afd634e3eb36 100644 --- a/book/tests/prql/syntax-7.prql +++ b/book/tests/prql/syntax-7.prql @@ -1,7 +1,2 @@ from employees -group [title, country] ( - aggregate [ - average salary, - ct = count - ] -) +derive total_distance = sum distance diff --git a/book/tests/prql/syntax-8.prql b/book/tests/prql/syntax-8.prql index 7ee340a4259a..f655f4637971 100644 --- a/book/tests/prql/syntax-8.prql +++ b/book/tests/prql/syntax-8.prql @@ -1,3 +1,7 @@ -from employees # Comment 1 -# Comment 2 -aggregate [average salary] +from employees +group [title, country] ( + aggregate [ + average salary, + ct = count + ] +) diff --git a/book/tests/prql/syntax-9.prql b/book/tests/prql/syntax-9.prql index d768dedf3f09..7ee340a4259a 100644 --- a/book/tests/prql/syntax-9.prql +++ b/book/tests/prql/syntax-9.prql @@ -1,3 +1,3 @@ -prql target:sql.mysql -from employees -select `first name` +from employees # Comment 1 +# Comment 2 +aggregate [average salary] diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 0d8479b528fc..851d9db9a5c3 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -56,22 +56,27 @@ fn collect_book_examples() -> Result> { .filter(|x| glob.is_match(x.path())) .flat_map(|dir_entry| { let text = fs::read_to_string(dir_entry.path())?; + // TODO: Duplicative logic here and in [lib.rs/replace_examples]; + // could we unify? + // + // Could we have a function that takes text and returns a + // Vec, where expected is whether it + // should succeed or fail? let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; while let Some(event) = parser.next() { match event.clone() { // At the start of a PRQL code block, push the _next_ item. // Note that on windows, we only get the next _line_, and so - // we exclude the writing in windows below; + // this is disabled on windows. // https://github.com/PRQL/prql/issues/356 Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) - if lang == "prql".into() => + if lang == "prql".into() || lang == "prql_error".into() => { - if let Some(Event::Text(text)) = parser.next() { - prql_blocks.push(text); - } else { - bail!("Expected text after PRQL code block"); - } + let Some(Event::Text(text)) = parser.next() else { + bail!("Expected text after PRQL code block") + }; + prql_blocks.push(text); } _ => {} } @@ -153,7 +158,10 @@ fn write_prql_examples(examples: HashMap) -> Result<()> { }); if is_snapshots_updated { - bail!("Some book snapshots were not consistent with the queries in the book. The snapshots have now been updated. Subsequent runs should pass."); + bail!(r###" +Some book snapshots were not consistent with the queries in the book. +The snapshots have now been updated. Subsequent runs of this test should now pass."### + .trim()); } Ok(()) } @@ -168,7 +176,8 @@ fn test_prql_examples() { return; } - let sql = compile(&prql, &opts).unwrap_or_else(|e| format!("{prql}\n\n{e}")); + // Whether it's a success or a failure, get the string. + let sql = compile(&prql, &opts).unwrap_or_else(|e| e.to_string()); // `glob!` gives us the file path in the test name anyway, so we pass an // empty name. We pass `&prql` so the prql is in the snapshot (albeit in // a single line, and, in the rare case that the SQL doesn't change, the diff --git a/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap index 86c5ba85d58a..98117ed8ee3a 100644 --- a/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap +++ b/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap @@ -8,3 +8,4 @@ SELECT ((temp_c - 32) / 1.8 - 0) / 100 AS boiling_proportion FROM kettles + diff --git a/book/tests/snapshots/snapshot__@queries__functions-5.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-5.prql.snap new file mode 100644 index 000000000000..043fb613eb3f --- /dev/null +++ b/book/tests/snapshots/snapshot__@queries__functions-5.prql.snap @@ -0,0 +1,16 @@ +--- +source: book/tests/snapshot.rs +expression: "func cost_share cost -> cost / cost_total\n\nfrom costs\nselect [materials, labor, overhead, cost_total]\nderive [\n materials_share = (cost_share materials),\n labor_share = (cost_share labor),\n overhead_share = (cost_share overhead),\n]\n" +input_file: book/tests/prql/queries/functions-5.prql +--- +SELECT + materials, + labor, + overhead, + cost_total, + materials / cost_total AS materials_share, + labor / cost_total AS labor_share, + overhead / cost_total AS overhead_share +FROM + costs + diff --git a/book/tests/snapshots/snapshot__@syntax-10.prql.snap b/book/tests/snapshots/snapshot__@syntax-10.prql.snap index f1b7d23890a6..1b4420bac18f 100644 --- a/book/tests/snapshots/snapshot__@syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-10.prql.snap @@ -1,9 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" +expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" input_file: book/tests/prql/syntax-10.prql --- SELECT - "first name" + `first name` FROM employees + diff --git a/book/tests/snapshots/snapshot__@syntax-11.prql.snap b/book/tests/snapshots/snapshot__@syntax-11.prql.snap index 2ce70ad17f23..3e60cedc7a74 100644 --- a/book/tests/snapshots/snapshot__@syntax-11.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-11.prql.snap @@ -1,9 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "from `dir/*.parquet`\n" +expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" input_file: book/tests/prql/syntax-11.prql --- SELECT - * + "first name" FROM - "dir/*.parquet" + employees + diff --git a/book/tests/snapshots/snapshot__@syntax-12.prql.snap b/book/tests/snapshots/snapshot__@syntax-12.prql.snap index 89258a4e0a89..7372f8f76f8a 100644 --- a/book/tests/snapshots/snapshot__@syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-12.prql.snap @@ -1,11 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" +expression: "from `dir/*.parquet`\n" input_file: book/tests/prql/syntax-12.prql --- SELECT - `project-foo.dataset.table`.*, - `project-bar.dataset.table`.* + * FROM - `project-foo.dataset.table` - JOIN `project-bar.dataset.table` ON `project-foo.dataset.table`.col_bax = `project-bar.dataset.table`.col_bax + "dir/*.parquet" + diff --git a/book/tests/snapshots/snapshot__@syntax-13.prql.snap b/book/tests/snapshots/snapshot__@syntax-13.prql.snap index c1617c87e881..9f4f882ffaca 100644 --- a/book/tests/snapshots/snapshot__@syntax-13.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-13.prql.snap @@ -1,9 +1,12 @@ --- source: book/tests/snapshot.rs -expression: "from `music.albums`\n" +expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" input_file: book/tests/prql/syntax-13.prql --- SELECT - * + `project-foo.dataset.table`.*, + `project-bar.dataset.table`.* FROM - music.albums + `project-foo.dataset.table` + JOIN `project-bar.dataset.table` ON `project-foo.dataset.table`.col_bax = `project-bar.dataset.table`.col_bax + diff --git a/book/tests/snapshots/snapshot__@syntax-14.prql.snap b/book/tests/snapshots/snapshot__@syntax-14.prql.snap index 427590aa8b77..cc5fe4f92a62 100644 --- a/book/tests/snapshots/snapshot__@syntax-14.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-14.prql.snap @@ -1,11 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter id == $1\n" +expression: "from `music.albums`\n" input_file: book/tests/prql/syntax-14.prql --- SELECT * FROM - employees -WHERE - id = $1 + music.albums + diff --git a/book/tests/snapshots/snapshot__@syntax-15.prql.snap b/book/tests/snapshots/snapshot__@syntax-15.prql.snap index dddfae4b8812..0ee085bcefeb 100644 --- a/book/tests/snapshots/snapshot__@syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-15.prql.snap @@ -1,10 +1,12 @@ --- source: book/tests/snapshot.rs -expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" +expression: "from employees\nfilter id == $1\n" input_file: book/tests/prql/syntax-15.prql --- SELECT - 1.0000001 AS small, - 5000000 AS big + * FROM - numbers + employees +WHERE + id = $1 + diff --git a/book/tests/snapshots/snapshot__@syntax-16.prql.snap b/book/tests/snapshots/snapshot__@syntax-16.prql.snap index e62eb76cf856..5bae6263183d 100644 --- a/book/tests/snapshots/snapshot__@syntax-16.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-16.prql.snap @@ -1,13 +1,11 @@ --- source: book/tests/snapshot.rs -expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" input_file: book/tests/prql/syntax-16.prql --- SELECT - a AS "from", - b AS take + 1.0000001 AS small, + 5000000 AS big FROM - my_table -LIMIT - 3 + numbers diff --git a/book/tests/snapshots/snapshot__@syntax-17.prql.snap b/book/tests/snapshots/snapshot__@syntax-17.prql.snap new file mode 100644 index 000000000000..a944999d43cd --- /dev/null +++ b/book/tests/snapshots/snapshot__@syntax-17.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +input_file: book/tests/prql/syntax-17.prql +--- +SELECT + a AS "from", + b AS take +FROM + my_table +LIMIT + 3 + diff --git a/book/tests/snapshots/snapshot__@syntax-7.prql.snap b/book/tests/snapshots/snapshot__@syntax-7.prql.snap index ef01d0c90ef5..d25417d4c021 100644 --- a/book/tests/snapshots/snapshot__@syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-7.prql.snap @@ -1,15 +1,13 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" +expression: "from employees\nderive total_distance = sum distance\n" input_file: book/tests/prql/syntax-7.prql --- -SELECT - title, - country, - AVG(salary), - COUNT(*) AS ct -FROM - employees -GROUP BY - title, - country +Error: + โ•ญโ”€[:2:29] + โ”‚ + 2 โ”‚ derive total_distance = sum distance + ยท โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ + ยท โ•ฐโ”€โ”€โ”€โ”€โ”€ Unknown name distance +โ”€โ”€โ”€โ•ฏ + diff --git a/book/tests/snapshots/snapshot__@syntax-8.prql.snap b/book/tests/snapshots/snapshot__@syntax-8.prql.snap index ea09601c7034..9e7c1486e2a5 100644 --- a/book/tests/snapshots/snapshot__@syntax-8.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-8.prql.snap @@ -1,9 +1,16 @@ --- source: book/tests/snapshot.rs -expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" input_file: book/tests/prql/syntax-8.prql --- SELECT - AVG(salary) + title, + country, + AVG(salary), + COUNT(*) AS ct FROM employees +GROUP BY + title, + country + diff --git a/book/tests/snapshots/snapshot__@syntax-9.prql.snap b/book/tests/snapshots/snapshot__@syntax-9.prql.snap index 10db59599207..08fc131cabca 100644 --- a/book/tests/snapshots/snapshot__@syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-9.prql.snap @@ -1,9 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" +expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" input_file: book/tests/prql/syntax-9.prql --- SELECT - `first name` + AVG(salary) FROM employees + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap new file mode 100644 index 000000000000..4f4e9a5a8d3b --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap @@ -0,0 +1,23 @@ +--- +source: book/tests/snapshot.rs +expression: "func cost_share cost -> cost / cost_total\n\nfrom costs\nselect [materials, labor, overhead, cost_total]\nderive [\n materials_share = (cost_share materials),\n labor_share = (cost_share labor),\n overhead_share = (cost_share overhead),\n]\n" +--- +func cost_share cost -> cost / cost_total + + + +from costs +select [ + materials, + labor, + overhead, + cost_total, +] +derive [ + materials_share = cost_share materials, + labor_share = cost_share labor, + overhead_share = cost_share overhead, +] + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap index 0ef6f6c5ea4e..19c4de64822f 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap @@ -1,8 +1,8 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" +expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" --- -prql target:sql.postgres +prql target:sql.mysql diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap index acd1651bdbb9..0ef6f6c5ea4e 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap @@ -1,8 +1,13 @@ --- source: book/tests/snapshot.rs -expression: "from `dir/*.parquet`\n" +expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" --- -from `dir/*.parquet` +prql target:sql.postgres + + + +from employees +select `first name` diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap index 6be462d1cb08..acd1651bdbb9 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap @@ -1,13 +1,8 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" +expression: "from `dir/*.parquet`\n" --- -prql target:sql.bigquery - - - -from `project-foo.dataset.table` -join `project-bar.dataset.table` [==col_bax] +from `dir/*.parquet` diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap index fc9310bcceea..6be462d1cb08 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap @@ -1,8 +1,13 @@ --- source: book/tests/snapshot.rs -expression: "from `music.albums`\n" +expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" --- -from `music.albums` +prql target:sql.bigquery + + + +from `project-foo.dataset.table` +join `project-bar.dataset.table` [==col_bax] diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap index 429e57d0faf3..fc9310bcceea 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap @@ -1,9 +1,8 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nfilter id == $1\n" +expression: "from `music.albums`\n" --- -from employees -filter id == $1 +from `music.albums` diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap index 7aa2caf4c217..4e250a9bf506 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap @@ -1,12 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" +expression: "from employees\nfilter id == $1\n" --- -from numbers -select [ - small = 1.0000001, - big = 5000000, -] +from employees +filter id == $1 + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap index ddc2d6ddb49a..7aa2caf4c217 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap @@ -1,13 +1,12 @@ --- source: book/tests/snapshot.rs -expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" --- -std.from my_table -std.select [ - from = my_table.a, - take = my_table.b, +from numbers +select [ + small = 1.0000001, + big = 5000000, ] -std.take 3 diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap new file mode 100644 index 000000000000..ddc2d6ddb49a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap @@ -0,0 +1,13 @@ +--- +source: book/tests/snapshot.rs +expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" +--- +std.from my_table +std.select [ + from = my_table.a, + take = my_table.b, +] +std.take 3 + + + diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap index 81e0a3146955..87ed02336d92 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap @@ -1,17 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" +expression: "from employees\nderive total_distance = sum distance\n" --- from employees -group [ - title, - country, -] ( - aggregate [ - average salary, - ct = count, -] -) +derive total_distance = sum distance diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap index 4f94033b1f86..81e0a3146955 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap @@ -1,9 +1,17 @@ --- source: book/tests/snapshot.rs -expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" +expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" --- from employees -aggregate [average salary] +group [ + title, + country, +] ( + aggregate [ + average salary, + ct = count, +] +) diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap index 19c4de64822f..4f94033b1f86 100644 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap @@ -1,13 +1,9 @@ --- source: book/tests/snapshot.rs -expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" +expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" --- -prql target:sql.mysql - - - from employees -select `first name` +aggregate [average salary] From 613661a711645fcb58ee236dddb3b0a3c5a0b9a5 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 5 Mar 2023 10:39:04 -0800 Subject: [PATCH 101/184] refactor: Remove double-negatives (#2007) --- prql-compiler/src/sql/gen_expr.rs | 2 +- prql-compiler/src/sql/gen_query.rs | 8 ++++---- prql-compiler/src/sql/mod.rs | 21 ++++++++++++++++----- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index a1e90216c005..5f57a16670d7 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -301,7 +301,7 @@ pub(super) fn translate_cid(cid: CId, ctx: &mut Context) -> Result) -> Result { - if ctx.query.forbid_stars { + if !ctx.query.allow_stars { Err( Error::new_simple("Target dialect does not support * in this position.") .with_span(span) diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index 4465ba22c879..dfbf066f07d5 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -117,7 +117,7 @@ fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result = aggregate.map(|(part, _)| part).unwrap_or_default(); - ctx.query.forbid_stars = !ctx.dialect.stars_in_group(); + ctx.query.allow_stars = ctx.dialect.stars_in_group(); let group_by = try_into_exprs(group_by, ctx, None)?; - ctx.query.forbid_stars = false; + ctx.query.allow_stars = true; ctx.query.pre_projection = false; @@ -429,7 +429,7 @@ fn sql_of_loop(pipeline: Vec, ctx: &mut Context) -> Result, } -#[derive(Default, Clone)] +#[derive(Clone)] struct QueryOpts { /// When true, column references will not include table names prefixes. pub omit_ident_prefix: bool, @@ -80,11 +80,22 @@ struct QueryOpts { /// - ORDER BY needs `pre_projection=false`. pub pre_projection: bool, - /// When true, queries will contain nested sub-queries instead of WITH CTEs. - pub forbid_ctes: bool, + /// When false, queries will contain nested sub-queries instead of WITH CTEs. + pub allow_ctes: bool, - /// When true, * are not allowed. - pub forbid_stars: bool, + /// When false, * are not allowed. + pub allow_stars: bool, +} + +impl Default for QueryOpts { + fn default() -> Self { + QueryOpts { + omit_ident_prefix: false, + pre_projection: false, + allow_ctes: true, + allow_stars: true, + } + } } impl Context { From b02dbd0d167c1abf08e2daf8b9e6fe9411e3c241 Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Mon, 6 Mar 2023 04:52:12 +0900 Subject: [PATCH 102/184] docs: update changelog about sql.any (#2017) --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d1d273293ce..53f7ab0fea71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,9 @@ - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) +- A new spacial compile target `"sql.any"`. When `"sql.any"` is used as the + target of the compile function's option, the target contained in the query + header will be used. (@aljazerzen, #1995) - Support for SQL parameters with similar syntax (#1957, @aljazerzen) - Allow `:` to be elided in timezones, such as `0800` in `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). From e132c3de9b1099f0fa0d7929c921a301eaccccc4 Mon Sep 17 00:00:00 2001 From: Jelenkee <59470612+Jelenkee@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:54:48 +0100 Subject: [PATCH 103/184] feat: upper and lower function (#2019) --- CHANGELOG.md | 2 ++ book/src/queries/functions.md | 18 +++++------ book/src/syntax.md | 2 +- book/tests/prql/queries/functions-1.prql | 4 +-- book/tests/prql/queries/functions-2.prql | 4 +-- book/tests/prql/queries/functions-4.prql | 2 +- ...ests__prql__queries__functions-1.prql.snap | 6 ++-- ...ests__prql__queries__functions-2.prql.snap | 6 ++-- ...ests__prql__queries__functions-4.prql.snap | 4 +-- prql-compiler/src/semantic/std.prql | 4 +++ prql-compiler/src/sql/std_impl.prql | 4 +++ prql-compiler/src/test.rs | 32 +++++++++++++++++++ 12 files changed, 65 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 53f7ab0fea71..dbb9ffce3285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,8 @@ - Support for SQL parameters with similar syntax (#1957, @aljazerzen) - Allow `:` to be elided in timezones, such as `0800` in `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). +- Add `std.upper` and `std.lower` functions for changing string casing + (@Jelenkee, #2019). **Fixes**: diff --git a/book/src/queries/functions.md b/book/src/queries/functions.md index 14261442527e..e5fc746056dc 100644 --- a/book/src/queries/functions.md +++ b/book/src/queries/functions.md @@ -23,18 +23,18 @@ from cities derive temp_c = (fahrenheit_to_celsius temp_f) ``` -This function is named `interp`, and has two positional parameters named -`higher` and `x`, and one named parameter named `lower` which takes a default -argument of `0`. It calculates the proportion of the distance that `x` is -between `lower` and `higher`. +This function is named `interp`, and has two positional parameters named `high` +and `x`, and one named parameter named `low` which takes a default argument of +`0`. It calculates the proportion of the distance that `x` is between `low` and +`high`. ```prql -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from students derive [ sat_proportion_1 = (interp 1600 sat_score), - sat_proportion_2 = (interp lower:0 1600 sat_score), + sat_proportion_2 = (interp low:0 1600 sat_score), ] ``` @@ -47,12 +47,12 @@ positional parameter of the function. Here's the same result as the examples above with an alternative construction: ```prql -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from students derive [ sat_proportion_1 = (sat_score | interp 1600), - sat_proportion_2 = (sat_score | interp lower:0 1600), + sat_proportion_2 = (sat_score | interp low:0 1600), ] ``` @@ -69,7 +69,7 @@ We can combine a chain of functions, which makes logic more readable: ```prql func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from kettles derive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100) diff --git a/book/src/syntax.md b/book/src/syntax.md index dbe7dd41820e..c2adbe444394 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -14,7 +14,7 @@ A summary of PRQL syntax | --------------- | -------------------------------------------------------------------- | ------------------------------------------------------- | | \| | [Pipelines](queries/pipelines.md) | from employees \| select first_name | | `=` | [Assigns](transforms/select.md) & [Aliases](transforms/join.md) | `from e = employees`
`derive total = (sum salary)` | -| `:` | [Named args & Parameters](queries/functions.md) | `interp lower:0 1600 sat_score` | +| `:` | [Named args & Parameters](queries/functions.md) | `interp low:0 1600 sat_score` | | `[]` | [Lists](./syntax.md#lists) | `select [id, amount]` | | `()` | [Precedence & Parentheses](./syntax.md#precedence-and-parentheses) | `derive celsius = (fahrenheit - 32) / 1.8` | | `''` & `""` | [Strings](language-features/strings.md) | `derive name = 'Mary'` | diff --git a/book/tests/prql/queries/functions-1.prql b/book/tests/prql/queries/functions-1.prql index f2da76bdaed6..a03bbcd3ac0d 100644 --- a/book/tests/prql/queries/functions-1.prql +++ b/book/tests/prql/queries/functions-1.prql @@ -1,7 +1,7 @@ -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from students derive [ sat_proportion_1 = (interp 1600 sat_score), - sat_proportion_2 = (interp lower:0 1600 sat_score), + sat_proportion_2 = (interp low:0 1600 sat_score), ] diff --git a/book/tests/prql/queries/functions-2.prql b/book/tests/prql/queries/functions-2.prql index f7d6afdbd8ac..7fe11cbe86bc 100644 --- a/book/tests/prql/queries/functions-2.prql +++ b/book/tests/prql/queries/functions-2.prql @@ -1,7 +1,7 @@ -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from students derive [ sat_proportion_1 = (sat_score | interp 1600), - sat_proportion_2 = (sat_score | interp lower:0 1600), + sat_proportion_2 = (sat_score | interp low:0 1600), ] diff --git a/book/tests/prql/queries/functions-4.prql b/book/tests/prql/queries/functions-4.prql index f692e9ffbeb7..fc6ded8dc043 100644 --- a/book/tests/prql/queries/functions-4.prql +++ b/book/tests/prql/queries/functions-4.prql @@ -1,5 +1,5 @@ func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 -func interp lower:0 higher x -> (x - lower) / (higher - lower) +func interp low:0 high x -> (x - low) / (high - low) from kettles derive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100) diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap index ef971e8402bc..a8dfd8b7401d 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap @@ -1,15 +1,15 @@ --- source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp lower:0 1600 sat_score),\n]\n" +expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp low:0 1600 sat_score),\n]\n" --- -func interp higher x lower:0 -> x - lower / higher - lower +func interp high x low:0 -> x - low / high - low from students derive [ sat_proportion_1 = interp 1600 sat_score, - sat_proportion_2 = interp lower:0 1600 sat_score, + sat_proportion_2 = interp low:0 1600 sat_score, ] diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap index 2e8f243ea009..62b10ce1ebc0 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap @@ -1,8 +1,8 @@ --- source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp lower:0 1600),\n]\n" +expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp low:0 1600),\n]\n" --- -func interp higher x lower:0 -> x - lower / higher - lower +func interp high x low:0 -> x - low / high - low @@ -14,7 +14,7 @@ derive [ ), sat_proportion_2 = ( sat_score - interp lower:0 1600 + interp low:0 1600 ), ] diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap index 3deae6fcab9c..4ad7a7528df5 100644 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap @@ -1,12 +1,12 @@ --- source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp low:0 high x -> (x - low) / (high - low)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" --- func fahrenheit_to_celsius temp -> temp - 32 / 1.8 -func interp higher x lower:0 -> x - lower / higher - lower +func interp high x low:0 -> x - low / high - low diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index 201bf929ad4a..51027e667c4b 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -59,3 +59,7 @@ func _is_null a -> _param.a == null # Misc func from_text
text `noresolve.format`:csv -> null + +# String functions +func lower column -> null +func upper column -> null diff --git a/prql-compiler/src/sql/std_impl.prql b/prql-compiler/src/sql/std_impl.prql index 91013ab5f9eb..0545e05ebef4 100644 --- a/prql-compiler/src/sql/std_impl.prql +++ b/prql-compiler/src/sql/std_impl.prql @@ -21,3 +21,7 @@ func row_number -> s"ROW_NUMBER()" # Other functions func round n_digits column -> s"ROUND({column}, {n_digits})" func as `noresolve.type` column -> s"CAST({column} AS {type})" + +# String functions +func lower column -> s"LOWER({column})" +func upper column -> s"UPPER({column})" diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 413fcae6ee06..6d4dcb9b071d 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -3400,3 +3400,35 @@ fn test_datetime_parsing() { "### ); } + +#[test] +fn test_lower() { + assert_display_snapshot!(compile(r#" + from test_tables + derive [lower_name = (name | lower)] + "#).unwrap(), + @r###" + SELECT + *, + LOWER(name) AS lower_name + FROM + test_tables + "### + ); +} + +#[test] +fn test_upper() { + assert_display_snapshot!(compile(r#" + from test_tables + derive [upper_name = upper name] + select [upper_name] + "#).unwrap(), + @r###" + SELECT + UPPER(name) AS upper_name + FROM + test_tables + "### + ); +} From b476fb3c8c73dc6775390a6d4521a216e7c7f4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Sun, 5 Mar 2023 23:08:30 +0100 Subject: [PATCH 104/184] docs: fix website landing page (#2021) --- website/themes/prql-theme/layouts/_default/home.html | 2 +- website/themes/prql-theme/static/style.css | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/website/themes/prql-theme/layouts/_default/home.html b/website/themes/prql-theme/layouts/_default/home.html index 581c747d4558..9875e4dedfe7 100644 --- a/website/themes/prql-theme/layouts/_default/home.html +++ b/website/themes/prql-theme/layouts/_default/home.html @@ -2,7 +2,7 @@ {{ with .Params.hero_section }} {{ if .enable }} -
+
diff --git a/website/themes/prql-theme/static/style.css b/website/themes/prql-theme/static/style.css index df439c136c00..14458343e251 100644 --- a/website/themes/prql-theme/static/style.css +++ b/website/themes/prql-theme/static/style.css @@ -287,7 +287,7 @@ pre ::-webkit-scrollbar-thumb:hover { --------------------------------------------------------------*/ .hero { width: 100%; - min-height: 100vh; + min-height: calc(100vh - 81px); background: #f2f9ff; background: repeating-linear-gradient( 45deg, @@ -297,7 +297,10 @@ pre ::-webkit-scrollbar-thumb:hover { #f2f9ff 300px ), linear-gradient(#daeaff, #f2f9ff); - padding-top: 100px; + display: flex; + flex-direction: column; + justify-content: center; + flex: 1 0 fit-content; } .hero h4 { From 8daadbe7e080ee726e642f627e2f927421b5b3ea Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 5 Mar 2023 16:04:51 -0800 Subject: [PATCH 105/184] chore: Fix typo in changelog (#2023) --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbb9ffce3285..3b54a321c770 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,9 +20,9 @@ - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) -- A new spacial compile target `"sql.any"`. When `"sql.any"` is used as the - target of the compile function's option, the target contained in the query - header will be used. (@aljazerzen, #1995) +- A new compile target `"sql.any"`. When `"sql.any"` is used as the target of + the compile function's option, the target contained in the query header will + be used. (@aljazerzen, #1995) - Support for SQL parameters with similar syntax (#1957, @aljazerzen) - Allow `:` to be elided in timezones, such as `0800` in `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). From a3a34626a391ef5363ade281ffe1fd6bb8ca365c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 5 Mar 2023 20:29:00 -0800 Subject: [PATCH 106/184] test: Test formatted examples can compile (#2016) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * docs: Add error messages to the book This allows us to show and test error messages in the book, and adds an initial example. Unfortunately the initial example doesn't have a great error message! So that's something we could work on. It also updates the docs to add late binding โ€” now functions support that! * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * . * . * . * . * . * test: Test formatted examples can compile We remove the snapshot output of them all -- even having written these, I was getting confused what all the snapshots were. And we don't use them at all. I added a TODO in the code for a good design if we could make progress on the autoformatter. * Revert "" This reverts commit 193769233653947e5180620ceabe86d014f8a017. * clean up merge diff * . --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 + book/highlight-prql.js | 2 + book/src/examples/cte.md | 2 +- book/src/examples/employees.md | 2 +- book/src/language-features/s-strings.md | 2 +- book/src/language-features/strings.md | 2 +- book/src/language-features/switch.md | 4 +- book/src/language-features/target.md | 4 +- book/src/lib.rs | 2 +- book/src/queries/functions.md | 2 +- book/src/syntax.md | 2 +- book/src/transforms/select.md | 6 +- book/tests/prql/examples/cte-0.prql | 2 + book/tests/prql/examples/employees-3.prql | 2 + .../prql/language-features/s-strings-4.prql | 2 + .../prql/language-features/strings-5.prql | 2 + .../prql/language-features/switch-0.prql | 2 + .../prql/language-features/switch-1.prql | 2 + .../prql/language-features/target-1.prql | 2 + .../prql/language-features/target-2.prql | 2 + book/tests/prql/queries/functions-0.prql | 2 + book/tests/prql/syntax-6.prql | 2 + book/tests/prql/syntax-7.prql | 2 + book/tests/prql/transforms/select-4.prql | 2 + book/tests/prql/transforms/select-5.prql | 2 + book/tests/prql/transforms/select-6.prql | 2 + book/tests/snapshot.rs | 106 ++++++++++++------ .../snapshots/snapshot__@syntax-7.prql.snap | 6 +- ...ot__tests__prql__examples__cte-0.prql.snap | 33 ------ ...sts__prql__examples__employees-0.prql.snap | 25 ----- ...sts__prql__examples__employees-1.prql.snap | 32 ------ ...sts__prql__examples__employees-2.prql.snap | 35 ------ ...sts__prql__examples__employees-3.prql.snap | 28 ----- ...ql__examples__list-equivalence-0.prql.snap | 9 -- ...ql__examples__list-equivalence-1.prql.snap | 9 -- ...ql__examples__list-equivalence-2.prql.snap | 12 -- ...ql__examples__list-equivalence-3.prql.snap | 10 -- ...t__tests__prql__examples__misc-0.prql.snap | 25 ----- ...t__tests__prql__examples__misc-1.prql.snap | 12 -- ...sts__prql__examples__variables-0.prql.snap | 31 ----- ...sts__prql__examples__variables-1.prql.snap | 18 --- ...ql__internals__functional-lang-0.prql.snap | 10 -- ...ql__internals__functional-lang-1.prql.snap | 10 -- ...ql__internals__functional-lang-2.prql.snap | 11 -- ...ql__internals__functional-lang-3.prql.snap | 12 -- ...rql__internals__name-resolving-0.prql.snap | 9 -- ...rql__internals__name-resolving-1.prql.snap | 17 --- ...hot__tests__prql__introduction-0.prql.snap | 31 ----- ...l__language-features__coalesce-0.prql.snap | 9 -- ...uage-features__dates-and-times-0.prql.snap | 9 -- ...uage-features__dates-and-times-1.prql.snap | 9 -- ...uage-features__dates-and-times-2.prql.snap | 9 -- ...uage-features__dates-and-times-3.prql.snap | 9 -- ...l__language-features__distinct-0.prql.snap | 12 -- ...l__language-features__distinct-1.prql.snap | 12 -- ...l__language-features__distinct-2.prql.snap | 12 -- ...__language-features__f-strings-0.prql.snap | 9 -- ...__language-features__f-strings-1.prql.snap | 9 -- ..._prql__language-features__null-0.prql.snap | 10 -- ...rql__language-features__ranges-0.prql.snap | 20 ---- ...rql__language-features__ranges-1.prql.snap | 13 --- ...__language-features__s-strings-0.prql.snap | 9 -- ...__language-features__s-strings-1.prql.snap | 9 -- ...__language-features__s-strings-2.prql.snap | 14 --- ...__language-features__s-strings-3.prql.snap | 9 -- ...__language-features__s-strings-4.prql.snap | 9 -- ...__language-features__s-strings-5.prql.snap | 12 -- ...__language-features__s-strings-6.prql.snap | 12 -- ...ures__standard-library__README-0.prql.snap | 19 ---- ...s__standard-library__from-text-0.prql.snap | 16 --- ...s__standard-library__from-text-1.prql.snap | 21 ---- ...s__standard-library__from-text-2.prql.snap | 32 ------ ...atures__standard-library__loop-0.prql.snap | 12 -- ...ql__language-features__strings-0.prql.snap | 9 -- ...ql__language-features__strings-1.prql.snap | 9 -- ...ql__language-features__strings-2.prql.snap | 9 -- ...ql__language-features__strings-3.prql.snap | 9 -- ...ql__language-features__strings-4.prql.snap | 9 -- ...ql__language-features__strings-5.prql.snap | 10 -- ...rql__language-features__switch-0.prql.snap | 12 -- ...rql__language-features__switch-1.prql.snap | 13 --- ...rql__language-features__target-0.prql.snap | 14 --- ...rql__language-features__target-1.prql.snap | 14 --- ...rql__language-features__target-2.prql.snap | 12 -- ...ests__prql__queries__functions-0.prql.snap | 15 --- ...ests__prql__queries__functions-1.prql.snap | 16 --- ...ests__prql__queries__functions-2.prql.snap | 22 ---- ...ests__prql__queries__functions-3.prql.snap | 16 --- ...ests__prql__queries__functions-4.prql.snap | 21 ---- ...ests__prql__queries__functions-5.prql.snap | 23 ---- ...ests__prql__queries__pipelines-0.prql.snap | 8 -- ...ests__prql__queries__pipelines-1.prql.snap | 9 -- ...ests__prql__queries__pipelines-2.prql.snap | 17 --- ...ests__prql__queries__variables-0.prql.snap | 17 --- ...ests__prql__queries__variables-1.prql.snap | 18 --- .../snapshot__tests__prql__syntax-0.prql.snap | 13 --- .../snapshot__tests__prql__syntax-1.prql.snap | 13 --- ...snapshot__tests__prql__syntax-10.prql.snap | 13 --- ...snapshot__tests__prql__syntax-11.prql.snap | 13 --- ...snapshot__tests__prql__syntax-12.prql.snap | 8 -- ...snapshot__tests__prql__syntax-13.prql.snap | 13 --- ...snapshot__tests__prql__syntax-14.prql.snap | 8 -- ...snapshot__tests__prql__syntax-15.prql.snap | 10 -- ...snapshot__tests__prql__syntax-16.prql.snap | 12 -- ...snapshot__tests__prql__syntax-17.prql.snap | 13 --- .../snapshot__tests__prql__syntax-2.prql.snap | 20 ---- .../snapshot__tests__prql__syntax-3.prql.snap | 9 -- .../snapshot__tests__prql__syntax-4.prql.snap | 9 -- .../snapshot__tests__prql__syntax-5.prql.snap | 13 --- .../snapshot__tests__prql__syntax-6.prql.snap | 39 ------- .../snapshot__tests__prql__syntax-7.prql.snap | 9 -- .../snapshot__tests__prql__syntax-8.prql.snap | 17 --- .../snapshot__tests__prql__syntax-9.prql.snap | 9 -- ...s__prql__transforms__aggregate-0.prql.snap | 12 -- ...s__prql__transforms__aggregate-1.prql.snap | 17 --- ...s__prql__transforms__aggregate-2.prql.snap | 9 -- ...ests__prql__transforms__append-0.prql.snap | 9 -- ...ests__prql__transforms__append-1.prql.snap | 9 -- ...ests__prql__transforms__append-2.prql.snap | 9 -- ...ests__prql__transforms__derive-0.prql.snap | 9 -- ...ests__prql__transforms__derive-1.prql.snap | 12 -- ...ests__prql__transforms__filter-0.prql.snap | 9 -- ...ests__prql__transforms__filter-1.prql.snap | 9 -- ...ests__prql__transforms__filter-2.prql.snap | 12 -- ..._tests__prql__transforms__from-0.prql.snap | 8 -- ..._tests__prql__transforms__from-1.prql.snap | 9 -- ...tests__prql__transforms__group-0.prql.snap | 17 --- ...tests__prql__transforms__group-1.prql.snap | 10 -- ...tests__prql__transforms__group-2.prql.snap | 12 -- ..._tests__prql__transforms__join-0.prql.snap | 9 -- ..._tests__prql__transforms__join-1.prql.snap | 9 -- ..._tests__prql__transforms__join-2.prql.snap | 9 -- ...ests__prql__transforms__select-0.prql.snap | 9 -- ...ests__prql__transforms__select-1.prql.snap | 12 -- ...ests__prql__transforms__select-2.prql.snap | 9 -- ...ests__prql__transforms__select-3.prql.snap | 12 -- ...ests__prql__transforms__select-4.prql.snap | 16 --- ...ests__prql__transforms__select-5.prql.snap | 18 --- ...ests__prql__transforms__select-6.prql.snap | 10 -- ..._tests__prql__transforms__sort-0.prql.snap | 9 -- ..._tests__prql__transforms__sort-1.prql.snap | 9 -- ..._tests__prql__transforms__sort-2.prql.snap | 13 --- ..._tests__prql__transforms__sort-3.prql.snap | 9 -- ..._tests__prql__transforms__sort-4.prql.snap | 10 -- ..._tests__prql__transforms__sort-5.prql.snap | 10 -- ..._tests__prql__transforms__take-0.prql.snap | 9 -- ..._tests__prql__transforms__take-1.prql.snap | 13 --- ...ests__prql__transforms__window-0.prql.snap | 14 --- ...ests__prql__transforms__window-1.prql.snap | 18 --- ...ests__prql__transforms__window-2.prql.snap | 10 -- ...ests__prql__transforms__window-3.prql.snap | 12 -- ...ests__prql__transforms__window-4.prql.snap | 9 -- 152 files changed, 122 insertions(+), 1719 deletions(-) delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap delete mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b54a321c770..d5d7bec3f038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,9 @@ **Internal changes**: +- Test that the code our nascent autoformatter generates can be compiled into + SQL. Examples where it can't are now labeled. (@max-sixty, #2016) + **New Contributors**: ## 0.5.2 โ€” 2022-02-18 diff --git a/book/highlight-prql.js b/book/highlight-prql.js index 5f72ddd49f9e..6993b6f799d5 100644 --- a/book/highlight-prql.js +++ b/book/highlight-prql.js @@ -205,6 +205,8 @@ formatting = function (hljs) { hljs.registerLanguage("prql", formatting); hljs.registerLanguage("prql_no_test", formatting); +hljs.registerLanguage("prql_error", formatting); +hljs.registerLanguage("prql_no_fmt", formatting); hljs.registerLanguage("elm", formatting); // These lines should only exists in the book, not the website. diff --git a/book/src/examples/cte.md b/book/src/examples/cte.md index 138b47154575..eab8c1592c7a 100644 --- a/book/src/examples/cte.md +++ b/book/src/examples/cte.md @@ -1,4 +1,4 @@ -```prql +```prql_no_fmt let newest_employees = ( from employees sort tenure diff --git a/book/src/examples/employees.md b/book/src/examples/employees.md index 5090a78155e2..48467dc87ecb 100644 --- a/book/src/examples/employees.md +++ b/book/src/examples/employees.md @@ -99,7 +99,7 @@ select [mng_name, managers.gender, salary_avg, salary_sd] > Find distributions of titles, salaries and genders for each department. -```prql +```prql_no_fmt from de=dept_emp join s=salaries side:left [ (s.emp_no == de.emp_no), diff --git a/book/src/language-features/s-strings.md b/book/src/language-features/s-strings.md index ed70b1923dbe..8cde2da4560d 100644 --- a/book/src/language-features/s-strings.md +++ b/book/src/language-features/s-strings.md @@ -61,7 +61,7 @@ should implement it in PRQL or PRQL's stdlib. To output braces from an s-string, use double braces: -```prql +```prql_no_fmt from employees derive [ has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){{2,}}')" diff --git a/book/src/language-features/strings.md b/book/src/language-features/strings.md index 922c5cac5e76..23acb935ce77 100644 --- a/book/src/language-features/strings.md +++ b/book/src/language-features/strings.md @@ -33,7 +33,7 @@ select x = """""I said """hello world"""!""""" Strings can also contain any escape defined by [JSON standard](https://www.ecma-international.org/publications-and-standards/standards/ecma-404/). -```prql +```prql_no_fmt from my_table select x = "\t\tline ends here\n \\ " ``` diff --git a/book/src/language-features/switch.md b/book/src/language-features/switch.md index 9570570eeb9c..eb9353eee968 100644 --- a/book/src/language-features/switch.md +++ b/book/src/language-features/switch.md @@ -6,7 +6,7 @@ PRQL uses `switch` for both SQL's `CASE` and `IF` statements. Here's an example: -```prql +```prql_no_fmt from employees derive distance = switch [ city == "Calgary" -> 0, @@ -17,7 +17,7 @@ derive distance = switch [ If no condition is met, the value takes a `null` value. To set a default, use a `true` condition: -```prql +```prql_no_fmt from employees derive distance = switch [ city == "Calgary" -> 0, diff --git a/book/src/language-features/target.md b/book/src/language-features/target.md index 558e338292cc..979d9434f4c9 100644 --- a/book/src/language-features/target.md +++ b/book/src/language-features/target.md @@ -15,7 +15,7 @@ sort age take 10 ``` -```prql +```prql_no_fmt prql target:sql.mssql from employees @@ -47,7 +47,7 @@ very welcome. PRQL allows specifying a version of the language in the PRQL header, like: -```prql +```prql_no_fmt prql version:"0.5" from employees diff --git a/book/src/lib.rs b/book/src/lib.rs index 74b749a61e80..dc85ee7aa710 100644 --- a/book/src/lib.rs +++ b/book/src/lib.rs @@ -115,7 +115,7 @@ fn replace_examples(text: &str) -> Result { let options = prql_compiler::Options::default().no_signature(); let result = &compile(&prql, &options); match lang.to_string().as_str() { - "prql" => cmark_acc.push(Event::Html( + "prql" | "prql_no_fmt" => cmark_acc.push(Event::Html( table_of_comparison( &prql, result diff --git a/book/src/queries/functions.md b/book/src/queries/functions.md index e5fc746056dc..5f31e4de8903 100644 --- a/book/src/queries/functions.md +++ b/book/src/queries/functions.md @@ -16,7 +16,7 @@ Functions have two types of parameters: So this function is named `fahrenheit_to_celsius` and has one parameter `temp`: -```prql +```prql_no_fmt func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 from cities diff --git a/book/src/syntax.md b/book/src/syntax.md index c2adbe444394..2382e5be3d44 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -137,7 +137,7 @@ function call, like `foo + bar`. Here's a full rundown of times this applier: -```prql +```prql_no_fmt from employees # Requires parentheses, because it's contains a pipe derive is_proximate = (distance | in 0..20) diff --git a/book/src/transforms/select.md b/book/src/transforms/select.md index aa330ac45b8e..b6f9694ef6d9 100644 --- a/book/src/transforms/select.md +++ b/book/src/transforms/select.md @@ -50,19 +50,19 @@ We can use `!` to exclude a list of columns. This can operate in two ways: Some examples: -```prql +```prql_no_fmt prql target:sql.bigquery from tracks select ![milliseconds,bytes] ``` -```prql +```prql_no_fmt from tracks select [track_id, title, composer, bytes] select ![title, composer] ``` -```prql +```prql_no_fmt from artists derive nick = name select ![artists.*] diff --git a/book/tests/prql/examples/cte-0.prql b/book/tests/prql/examples/cte-0.prql index c5d23ce84ec6..e1f990d5a366 100644 --- a/book/tests/prql/examples/cte-0.prql +++ b/book/tests/prql/examples/cte-0.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + let newest_employees = ( from employees sort tenure diff --git a/book/tests/prql/examples/employees-3.prql b/book/tests/prql/examples/employees-3.prql index 9e9d9e47855f..41950b3019cb 100644 --- a/book/tests/prql/examples/employees-3.prql +++ b/book/tests/prql/examples/employees-3.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from de=dept_emp join s=salaries side:left [ (s.emp_no == de.emp_no), diff --git a/book/tests/prql/language-features/s-strings-4.prql b/book/tests/prql/language-features/s-strings-4.prql index 782542d16c58..39a20f5bae9a 100644 --- a/book/tests/prql/language-features/s-strings-4.prql +++ b/book/tests/prql/language-features/s-strings-4.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from employees derive [ has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){{2,}}')" diff --git a/book/tests/prql/language-features/strings-5.prql b/book/tests/prql/language-features/strings-5.prql index 491c9f04bdd1..190823141edf 100644 --- a/book/tests/prql/language-features/strings-5.prql +++ b/book/tests/prql/language-features/strings-5.prql @@ -1,2 +1,4 @@ +# Can't yet format & compile + from my_table select x = "\t\tline ends here\n \\ " diff --git a/book/tests/prql/language-features/switch-0.prql b/book/tests/prql/language-features/switch-0.prql index e3284d640b83..c2cd611f974a 100644 --- a/book/tests/prql/language-features/switch-0.prql +++ b/book/tests/prql/language-features/switch-0.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from employees derive distance = switch [ city == "Calgary" -> 0, diff --git a/book/tests/prql/language-features/switch-1.prql b/book/tests/prql/language-features/switch-1.prql index f8d840c11cb5..aba9837069df 100644 --- a/book/tests/prql/language-features/switch-1.prql +++ b/book/tests/prql/language-features/switch-1.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from employees derive distance = switch [ city == "Calgary" -> 0, diff --git a/book/tests/prql/language-features/target-1.prql b/book/tests/prql/language-features/target-1.prql index 53433b4b16c0..58ed8531c0e5 100644 --- a/book/tests/prql/language-features/target-1.prql +++ b/book/tests/prql/language-features/target-1.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + prql target:sql.mssql from employees diff --git a/book/tests/prql/language-features/target-2.prql b/book/tests/prql/language-features/target-2.prql index c452ea2a5aad..06bf38542363 100644 --- a/book/tests/prql/language-features/target-2.prql +++ b/book/tests/prql/language-features/target-2.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + prql version:"0.5" from employees diff --git a/book/tests/prql/queries/functions-0.prql b/book/tests/prql/queries/functions-0.prql index b09007f54290..f859ceaa151e 100644 --- a/book/tests/prql/queries/functions-0.prql +++ b/book/tests/prql/queries/functions-0.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 from cities diff --git a/book/tests/prql/syntax-6.prql b/book/tests/prql/syntax-6.prql index 9ce71c723b6a..ac2acdcd7a08 100644 --- a/book/tests/prql/syntax-6.prql +++ b/book/tests/prql/syntax-6.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from employees # Requires parentheses, because it's contains a pipe derive is_proximate = (distance | in 0..20) diff --git a/book/tests/prql/syntax-7.prql b/book/tests/prql/syntax-7.prql index afd634e3eb36..a7ee0af913aa 100644 --- a/book/tests/prql/syntax-7.prql +++ b/book/tests/prql/syntax-7.prql @@ -1,2 +1,4 @@ +# Error expected + from employees derive total_distance = sum distance diff --git a/book/tests/prql/transforms/select-4.prql b/book/tests/prql/transforms/select-4.prql index a473a7832655..5d89bfe51b61 100644 --- a/book/tests/prql/transforms/select-4.prql +++ b/book/tests/prql/transforms/select-4.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + prql target:sql.bigquery from tracks select ![milliseconds,bytes] diff --git a/book/tests/prql/transforms/select-5.prql b/book/tests/prql/transforms/select-5.prql index 06d8486c28a7..6296e2abd6e7 100644 --- a/book/tests/prql/transforms/select-5.prql +++ b/book/tests/prql/transforms/select-5.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from tracks select [track_id, title, composer, bytes] select ![title, composer] diff --git a/book/tests/prql/transforms/select-6.prql b/book/tests/prql/transforms/select-6.prql index 78a496224d09..0f5a238d4098 100644 --- a/book/tests/prql/transforms/select-6.prql +++ b/book/tests/prql/transforms/select-6.prql @@ -1,3 +1,5 @@ +# Can't yet format & compile + from artists derive nick = name select ![artists.*] diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 851d9db9a5c3..c742bf3caa4d 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -1,15 +1,6 @@ #![cfg(not(target_family = "wasm"))] -/// This test: -/// - Extracts PRQL code blocks into files in the `examples` path, skipping -/// where the matching example is already present. -/// - Compiles them to SQL, comparing to a snapshot. Insta raises an error if -/// there's a diff. -/// -/// Then, when the book is built, the PRQL code block in the book is replaced -/// with a comparison table. -/// -/// We also use this test to run tests on our Display trait output, currently as -/// another set of snapshots (more comments inline). +// +// Thoughts on the overall code: // // Overall, this is overengineered โ€”ย it's complicated and took a long time to // write. The intention is good โ€” have a version of the SQL that's committed @@ -17,6 +8,10 @@ // custom code for quite a general problem, even if our preferences are slightly // different from the general case. // +// Having an API for being able to read snapshots +// (https://github.com/mitsuhiko/insta/issues/353) would significantly reduce the need for +// custom code; +// // Possibly we should be using something like pandoc / // https://github.com/gpoore/codebraid / which would run the transformation for // us. They introduce a bunch of non-rust dependencies, which is not ideal, but @@ -25,6 +20,7 @@ use anyhow::{bail, Error, Result}; use globset::Glob; use insta::{assert_snapshot, glob}; +use itertools::Itertools; use log::warn; use prql_compiler::*; use std::path::{Path, PathBuf}; @@ -32,8 +28,16 @@ use std::{collections::HashMap, fs}; use walkdir::WalkDir; #[test] +/// This test: +/// - Extracts PRQL code blocks into files in the `examples` path, skipping +/// where the matching example is already present. +/// - Compiles them to SQL, comparing to a snapshot. Insta raises an error if +/// there's a diff. +/// +/// Then, when the book is built, the PRQL code block in the book is replaced +/// with a comparison table. fn test_examples() -> Result<()> { - // Note that on windows, markdown is read differently, and so we don't write + // Note that on Windows, markdown is read differently, and so we don't write // on Windows (we write from the same place we read as a workaround). ref // https://github.com/PRQL/prql/issues/356 @@ -71,12 +75,18 @@ fn collect_book_examples() -> Result> { // this is disabled on windows. // https://github.com/PRQL/prql/issues/356 Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) - if lang == "prql".into() || lang == "prql_error".into() => + if lang.starts_with("prql") => { let Some(Event::Text(text)) = parser.next() else { bail!("Expected text after PRQL code block") }; - prql_blocks.push(text); + if lang == "prql".into() { + prql_blocks.push(text.to_string()); + } else if lang == "prql_error".into() { + prql_blocks.push(format!("# Error expected\n\n{text}")); + } else if lang == "prql_no_fmt".into() { + prql_blocks.push(format!("# Can't yet format & compile\n\n{text}")); + } } _ => {} } @@ -107,7 +117,6 @@ fn collect_book_examples() -> Result> { /// Collect examples which we've already written to disk, as a map of . fn collect_snapshot_examples() -> Result> { - use itertools::Itertools; let glob = Glob::new("**/*.prql")?.compile_matcher(); let existing_examples = WalkDir::new(Path::new(ROOT_EXAMPLES_PATH)) .into_iter() @@ -131,7 +140,7 @@ fn collect_book_examples() -> Result> { // requires no dependencies. fn write_prql_examples(examples: HashMap) -> Result<()> { // If we have to modify any files, raise an error at the end, so it fails in CI. - let mut is_snapshots_updated = false; + let mut snapshots_updated = vec![]; let mut existing_snapshots: HashMap<_, _> = collect_snapshot_examples()?; // Write any new snapshots, or update any that have changed @@ -141,7 +150,7 @@ fn write_prql_examples(examples: HashMap) -> Result<()> { .map(|existing| existing != *example) .unwrap_or(true) { - is_snapshots_updated = true; + snapshots_updated.push(prql_path); fs::create_dir_all(Path::new(prql_path).parent().unwrap())?; fs::write(prql_path, example)?; } @@ -149,19 +158,28 @@ fn write_prql_examples(examples: HashMap) -> Result<()> { Ok::<(), anyhow::Error>(()) })?; - // If there are any files left in `existing_snapshots`, we remove them, since - // they don't reference anything. + // If there are any files left in `existing_snapshots`, we remove them, + // since they don't reference anything (like + // `--delete-unreferenced-snapshots` in insta). existing_snapshots.iter().for_each(|(path, _)| { trash::delete(path).unwrap_or_else(|e| { warn!("Failed to delete unreferenced example: {}", e); }) }); - if is_snapshots_updated { - bail!(r###" -Some book snapshots were not consistent with the queries in the book. + if !snapshots_updated.is_empty() { + let snapshots_updated = snapshots_updated + .iter() + .map(|x| format!(" - {}", x.to_str().unwrap())) + .join("\n"); + bail!(format!( + r###" +Some book snapshots were not consistent with the queries in the book: + +{snapshots_updated} + The snapshots have now been updated. Subsequent runs of this test should now pass."### - .trim()); + )); } Ok(()) } @@ -186,22 +204,42 @@ fn test_prql_examples() { }); } -/// Snapshot the display trait output of each example. +/// Test that the formatted result (the `Display` result) of each example can be +/// compiled. +// +// We previously snapshot all the queries. But that was a lot of output, for +// something we weren't yet looking at. // -// TODO: this involves writing out almost the same PRQL again โ€” instead we could -// compare the output of Display to the auto-formatted source. But we need an -// autoformatter for that (unless we want to raise on any non-matching input, -// which seems very strict) +// The ideal would be to auto-format the examples themselves, likely during the +// compilation. For that to provide a good output, we need to implement a proper +// autoformatter. #[test] fn test_display() -> Result<(), ErrorMessages> { collect_book_examples()? .iter() - .try_for_each(|(path, example)| { - assert_snapshot!( - path.to_string_lossy().to_string(), - prql_to_pl(example).and_then(pl_to_prql)?, - example - ); + .try_for_each(|(path, prql)| { + if prql.contains("# Error expected") || prql.contains("# Can't yet format & compile") { + return Ok(()); + } + prql_to_pl(prql) + .and_then(pl_to_prql) + .and_then(|formatted| compile(&formatted, &Options::default())) + .unwrap_or_else(|_| { + panic!( + " +Failed compiling the formatted result of {path:?} +To skip this test for an example, use `prql_no_fmt` as the language label. + +The original PRQL was: + +{prql} + +", + path = path.canonicalize().unwrap(), + prql = prql + ) + }); + Ok::<(), ErrorMessages>(()) })?; diff --git a/book/tests/snapshots/snapshot__@syntax-7.prql.snap b/book/tests/snapshots/snapshot__@syntax-7.prql.snap index d25417d4c021..d52ff256c269 100644 --- a/book/tests/snapshots/snapshot__@syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__@syntax-7.prql.snap @@ -1,12 +1,12 @@ --- source: book/tests/snapshot.rs -expression: "from employees\nderive total_distance = sum distance\n" +expression: "# Error expected\n\nfrom employees\nderive total_distance = sum distance\n" input_file: book/tests/prql/syntax-7.prql --- Error: - โ•ญโ”€[:2:29] + โ•ญโ”€[:4:29] โ”‚ - 2 โ”‚ derive total_distance = sum distance + 4 โ”‚ derive total_distance = sum distance ยท โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€ ยท โ•ฐโ”€โ”€โ”€โ”€โ”€ Unknown name distance โ”€โ”€โ”€โ•ฏ diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap deleted file mode 100644 index 83e9f48a0e9e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap +++ /dev/null @@ -1,33 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" ---- -let newest_employees = ( - from employees - sort tenure - take 50 -) - - - -let average_salaries = ( - from salaries - group country ( - aggregate ( - average_country_salary = average salary -) -) -) - - - -from newest_employees -join average_salaries [==country] -select [ - name, - salary, - average_country_salary, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap deleted file mode 100644 index ac80804d08a1..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap +++ /dev/null @@ -1,25 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" ---- -from salaries -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join t = titles [==emp_no] -join side:left dept_emp [==emp_no] -group [ - dept_emp.dept_no, - t.title, -] ( - aggregate [avg_salary = average emp_salary] -) -join departments [==dept_no] -select [ - dept_name, - title, - avg_salary, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap deleted file mode 100644 index c5d5366f6306..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" ---- -from e = employees -join salaries [==emp_no] -group [ - e.emp_no, - e.gender, -] ( - aggregate [emp_salary = average salaries.salary] -) -join side:left de = dept_emp [==emp_no] -group [ - de.dept_no, - gender, -] ( - aggregate [ - salary_avg = average emp_salary, - salary_sd = stddev emp_salary, -] -) -join departments [==dept_no] -select [ - dept_name, - gender, - salary_avg, - salary_sd, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap deleted file mode 100644 index d957c280a5c6..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" ---- -from e = employees -join salaries [==emp_no] -group [ - e.emp_no, - e.gender, -] ( - aggregate [emp_salary = average salaries.salary] -) -join de = dept_emp [==emp_no] -join dm = dept_manager [dm.dept_no == de.dept_no and s"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)"] -group [ - dm.emp_no, - gender, -] ( - aggregate [ - salary_avg = average emp_salary, - salary_sd = stddev emp_salary, -] -) -derive mng_no = emp_no -join managers = employees [==emp_no] -derive mng_name = s"managers.first_name || ' ' || managers.last_name" -select [ - mng_name, - managers.gender, - salary_avg, - salary_sd, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap deleted file mode 100644 index 9cc6115f24bd..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap +++ /dev/null @@ -1,28 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" ---- -from de = dept_emp -join side:left s = salaries [ - s.emp_no == de.emp_no, - s"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})", -] -group [ - de.emp_no, - de.dept_no, -] ( - aggregate ( - salary = average s.salary -) -) -join employees [==emp_no] -join titles [==emp_no] -select [ - dept_no, - salary, - employees.gender, - titles.title, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap deleted file mode 100644 index 8566dfaeb2b2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect salary\n" ---- -from employees -select salary - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap deleted file mode 100644 index 055af64b363a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect [salary]\n" ---- -from employees -select [salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap deleted file mode 100644 index 3d298b6f9b55..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" ---- -from employees -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap deleted file mode 100644 index 254f07187889..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = salary + payroll_tax\nderive gross_cost = gross_salary + benefits_cost\n" ---- -from employees -derive gross_salary = salary + payroll_tax -derive gross_cost = gross_salary + benefits_cost - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap deleted file mode 100644 index 63b13a31ec56..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap +++ /dev/null @@ -1,25 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" ---- -let parts = ( - from seq_1_to_5 -) - - - -from pl = prospect_lists_prospects -filter prospect_list_id == "cc675eee-8bd1-237f-be5e-622ba511d65e" -join a = accounts [a.id == pl.related_id] -join er = email_addr_bean_rel [er.bean_id == a.id and er.primary_address == "1"] -join ea = email_addresses [ea.id == er.email_address_id] -select ea.email_address -derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" -derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" -select [ - email_address, - stub, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap deleted file mode 100644 index 50dcca896ea5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from club_ratings\nfilter rating != null\n# TODO: this is real ugly. `average rating` should not require parenthesis\n# TODO: why cannot we put comments in group's pipeline?\ngroup year (\n derive [rating_norm = rating - (average rating) / (stddev rating)]\n)\n" ---- -from club_ratings -filter rating != null -group year ( - derive [rating_norm = rating - ( average rating ) / ( stddev rating )] -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap deleted file mode 100644 index 4b1f4fce84c1..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter country == \"USA\" # Each line transforms the previous result.\nderive [ # This adds columns / variables.\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost # Variables can use other variables.\n]\nfilter gross_cost > 0\ngroup [title, country] ( # For each group use a nested pipeline\n aggregate [ # Aggregate each group to a single row\n average salary,\n average gross_salary,\n sum salary,\n sum gross_salary,\n average gross_cost,\n sum_gross_cost = sum gross_cost,\n ct = count,\n ]\n)\nsort sum_gross_cost\nfilter ct > 200\ntake 20\n" ---- -from employees -filter country == "USA" -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average salary, - average gross_salary, - sum salary, - sum gross_salary, - average gross_cost, - sum_gross_cost = sum gross_cost, - ct = count, -] -) -sort sum_gross_cost -filter ct > 200 -take 20 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap deleted file mode 100644 index cfb45e96a801..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup [emp_no] (\n aggregate [\n emp_salary = average salary # average salary resolves to \"AVG(salary)\" (from stdlib)\n ]\n)\njoin titles [==emp_no]\ngroup [title] (\n aggregate [\n avg_salary = average emp_salary\n ]\n)\nselect salary_k = avg_salary / 1000 # avg_salary should resolve to \"AVG(emp_salary)\"\ntake 10 # induces new SELECT\nderive salary = salary_k * 1000 # salary_k should not resolve to \"avg_salary / 1000\"\n" ---- -from employees -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join titles [==emp_no] -group [title] ( - aggregate [avg_salary = average emp_salary] -) -select salary_k = avg_salary / 1000 -take 10 -derive salary = salary_k * 1000 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap deleted file mode 100644 index 1bd2d905e16d..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter age > 50\nsort name\n" ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap deleted file mode 100644 index da4b761a9e4b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees | filter age > 50 | sort name\n" ---- -from employees -filter age > 50 -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap deleted file mode 100644 index 7da897d0dd14..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "filter age > 50 (from employees) | sort name\n" ---- -filter age > 50 ( - from employees -) -sort name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap deleted file mode 100644 index 045c663815a8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "sort name (filter age > 50 (from employees))\n" ---- -sort name ( - filter age > 50 ( - from employees -) -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap deleted file mode 100644 index a9d9e5bada6d..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [first_name, dept_id]\njoin d=departments [==dept_id]\nselect [first_name, d.title]\n" ---- -from employees -derive [ - first_name, - dept_id, -] -join d = departments [==dept_id] -select [ - first_name, - d.title, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap deleted file mode 100644 index 96f55b8ab057..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap +++ /dev/null @@ -1,31 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" ---- -from employees -filter start_date > @2021-01-01 -derive [ - gross_salary = salary + tax ?? 0, - gross_cost = gross_salary + benefits_cost, -] -filter gross_cost > 0 -group [ - title, - country, -] ( - aggregate [ - average gross_salary, - sum_gross_cost = sum gross_cost, -] -) -filter sum_gross_cost > 100000 -derive id = f"{title}_{country}" -derive country_code = s"LEFT(country, 2)" -sort [ - sum_gross_cost, - -country, -] -take 1..20 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap deleted file mode 100644 index 24ff749cfbc8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nderive amount ?? 0\n" ---- -from orders -derive amount ?? 0 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap deleted file mode 100644 index acb71c71fc9a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive age_at_year_end = (@2022-12-31 - dob)\n" ---- -from employees -derive age_at_year_end = @2022-12-31 - dob - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap deleted file mode 100644 index fd2fe52b3f6c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nderive should_have_shipped_today = (order_time < @08:30)\n" ---- -from orders -derive should_have_shipped_today = order_time < @08:30 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap deleted file mode 100644 index a2f42142ebb6..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-08:00\n" ---- -from commits -derive first_prql_commit = @2020-01-01T13:19:55-08:00 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap deleted file mode 100644 index 70ac66f365a2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from projects\nderive first_check_in = start + 10days\n" ---- -from projects -derive first_check_in = start + 10days - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap deleted file mode 100644 index 7929401e23b6..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect department\ngroup department (\n take 1\n)\n" ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap deleted file mode 100644 index 22ba087f087c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect department\ngroup department (take 1)\n" ---- -from employees -select department -group department ( - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap deleted file mode 100644 index ceb0035e6601..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "# youngest employee from each department\nfrom employees\ngroup department (\n sort age\n take 1\n)\n" ---- -from employees -group department ( - sort age - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap deleted file mode 100644 index 5f490aa52f00..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect full_name = f\"{first_name} {last_name}\"\n" ---- -from employees -select full_name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap deleted file mode 100644 index f00e2becbab2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from web\nselect url = f\"http{tls}://www.{domain}.{tld}/{page}\"\n" ---- -from web -select url = f"http{tls}://www.{domain}.{tld}/{page}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap deleted file mode 100644 index 73594522238f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter first_name == null\nfilter null != last_name\n" ---- -from employees -filter first_name == null -filter null != last_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap deleted file mode 100644 index 2d5baa98ae2d..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from events\nfilter (date | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" ---- -from events -filter ( - date - in @1776-07-04..@1787-09-17 -) -filter ( - magnitude - in 50..100 -) -derive is_northern = ( - latitude - in 0.. -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap deleted file mode 100644 index b68c1920a669..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap deleted file mode 100644 index 12abfcc2518c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect db_version = s\"version()\"\n" ---- -from my_table -select db_version = s"version()" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap deleted file mode 100644 index c57ed2561d58..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\naggregate [average salary]\n" ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap deleted file mode 100644 index e28b7f46ed0a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"\"\"({s.from_date}, {s.to_date})\n OVERLAPS\n ({de.from_date}, {de.to_date})\"\"\"\n]\n" ---- -from de = dept_emp -join side:left s = salaries [ - s.emp_no == de.emp_no, - s"({s.from_date}, {s.to_date}) - OVERLAPS - ({de.from_date}, {de.to_date})", -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap deleted file mode 100644 index 2cb93849dda8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" ---- -from s"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC" -join s = s"SELECT * FROM salaries" [==id] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap deleted file mode 100644 index 00c1d5e17349..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" ---- -from employees -derive [has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){2,}')"] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap deleted file mode 100644 index 9bd3b0d3fe16..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"{gross_salary} / 365\"\n]\n" ---- -from employees -derive [ - gross_salary = salary + benefits, - daily_rate = s"{gross_salary} / 365", -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap deleted file mode 100644 index 3dc30b6885ae..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"({gross_salary}) / 365\"\n]\n" ---- -from employees -derive [ - gross_salary = salary + benefits, - daily_rate = s"({gross_salary}) / 365", -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap deleted file mode 100644 index 011d5f416c47..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" ---- -from employees -derive [ - gross_salary = ( - salary + payroll_tax - as int -), - gross_salary_rounded = ( - gross_salary - round 0 -), - time = s"NOW()", -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap deleted file mode 100644 index 6a730d3a1f7e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" ---- -from_text " -a,b,c -1,2,3 -4,5,6 -" -derive [ - d = b + c, - answer = 20 * 2 + 2, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap deleted file mode 100644 index 6f9f848bbd6e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap +++ /dev/null @@ -1,21 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" ---- -let temp_format_lookup = ( - from_text format:csv " -country_code,format -uk,C -us,F -lr,F -de,C -" -) - - - -from temperatures -join temp_format_lookup [==country_code] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap deleted file mode 100644 index da17c3b1fe6f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap +++ /dev/null @@ -1,32 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" ---- -let x = ( - from_text format:json '{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}' -) - - - -let y = ( - from_text format:json ' - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -' -) - - - -from x -join y [==a] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap deleted file mode 100644 index 0c143248892b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" ---- -from_text format:json '[{"n": 1 }]' -loop ( - filter n < 4 - select n = n + 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap deleted file mode 100644 index 6a1d79036036..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"hello world\"\n" ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap deleted file mode 100644 index 2da7a07937de..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = 'hello world'\n" ---- -from my_table -select x = "hello world" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap deleted file mode 100644 index 8d79cd8cedbc..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = '\"hello world\"'\n" ---- -from my_table -select x = '"hello world"' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap deleted file mode 100644 index a681bc62a036..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\"\"I said \"hello world\"!\"\"\"\n" ---- -from my_table -select x = 'I said "hello world"!' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap deleted file mode 100644 index 0bae3f836774..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\"\"\"\"I said \"\"\"hello world\"\"\"!\"\"\"\"\"\n" ---- -from my_table -select x = 'I said """hello world"""!' - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap deleted file mode 100644 index 4a0b8ddabd77..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\\t\\tline ends here\\n \\\\ \"\n" ---- -from my_table -select x = " line ends here - \ " - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap deleted file mode 100644 index 7618b9e71723..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" ---- -from employees -derive distance = switch [ - city == "Calgary" => 0 - city == "Edmonton" => 300 -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap deleted file mode 100644 index f9ee3312b92b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__switch-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" ---- -from employees -derive distance = switch [ - city == "Calgary" => 0 - city == "Edmonton" => 300 - true => "Unknown" -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap deleted file mode 100644 index b22539422ae4..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" ---- -prql target:sql.postgres - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap deleted file mode 100644 index ed7e10fd7388..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" ---- -prql target:sql.mssql - - - -from employees -sort age -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap deleted file mode 100644 index b05787ed8bae..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql version:\"0.5\"\n\nfrom employees\n" ---- -prql version:^0.5 - - - -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap deleted file mode 100644 index e5bb0a64491b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap +++ /dev/null @@ -1,15 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" ---- -func fahrenheit_to_celsius temp -> temp - 32 / 1.8 - - - -from cities -derive ( - temp_c = fahrenheit_to_celsius temp_f -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap deleted file mode 100644 index a8dfd8b7401d..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp low:0 1600 sat_score),\n]\n" ---- -func interp high x low:0 -> x - low / high - low - - - -from students -derive [ - sat_proportion_1 = interp 1600 sat_score, - sat_proportion_2 = interp low:0 1600 sat_score, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap deleted file mode 100644 index 62b10ce1ebc0..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap +++ /dev/null @@ -1,22 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp low:0 1600),\n]\n" ---- -func interp high x low:0 -> x - low / high - low - - - -from students -derive [ - sat_proportion_1 = ( - sat_score - interp 1600 -), - sat_proportion_2 = ( - sat_score - interp low:0 1600 -), -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap deleted file mode 100644 index bc1453813dc9..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (temp_f | fahrenheit_to_celsius)\n" ---- -func fahrenheit_to_celsius temp -> temp - 32 / 1.8 - - - -from cities -derive temp_c = ( - temp_f - fahrenheit_to_celsius -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap deleted file mode 100644 index 4ad7a7528df5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap +++ /dev/null @@ -1,21 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp low:0 high x -> (x - low) / (high - low)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" ---- -func fahrenheit_to_celsius temp -> temp - 32 / 1.8 - - - -func interp high x low:0 -> x - low / high - low - - - -from kettles -derive boiling_proportion = ( - temp_c - fahrenheit_to_celsius - interp 100 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap deleted file mode 100644 index 4f4e9a5a8d3b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap +++ /dev/null @@ -1,23 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func cost_share cost -> cost / cost_total\n\nfrom costs\nselect [materials, labor, overhead, cost_total]\nderive [\n materials_share = (cost_share materials),\n labor_share = (cost_share labor),\n overhead_share = (cost_share overhead),\n]\n" ---- -func cost_share cost -> cost / cost_total - - - -from costs -select [ - materials, - labor, - overhead, - cost_total, -] -derive [ - materials_share = cost_share materials, - labor_share = cost_share labor, - overhead_share = cost_share overhead, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap deleted file mode 100644 index 8ef6dce0bb66..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n" ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap deleted file mode 100644 index b2b18409f03a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = (salary + payroll_tax)\n" ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap deleted file mode 100644 index 5c74bd2eeb81..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e = employees\nderive gross_salary = (salary + payroll_tax)\nsort gross_salary\ntake 10\njoin d = department [==dept_no]\nselect [e.name, gross_salary, d.name]\n" ---- -from e = employees -derive gross_salary = salary + payroll_tax -sort gross_salary -take 10 -join d = department [==dept_no] -select [ - e.name, - gross_salary, - d.name, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap deleted file mode 100644 index 3c4edace1010..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" ---- -let top_50 = ( - from employees - sort salary - take 50 - aggregate [total_salary = sum salary] -) - - - -from top_50 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap deleted file mode 100644 index dd72ddc9b4bb..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "let grouping = s\"\"\"\n SELECT SUM(a)\n FROM tbl\n GROUP BY\n GROUPING SETS\n ((b, c, d), (d), (b, d))\n\"\"\"\n\nfrom grouping\n" ---- -let grouping = s" - SELECT SUM(a) - FROM tbl - GROUP BY - GROUPING SETS - ((b, c, d), (d), (b, d)) -" - - - -from grouping - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap deleted file mode 100644 index ee78d7a29c00..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter department == \"Product\"\nselect [first_name, last_name]\n" ---- -from employees -filter department == "Product" -select [ - first_name, - last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap deleted file mode 100644 index ae9d7fcbb81c..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees | filter department == \"Product\" | select [first_name, last_name]\n" ---- -from employees -filter department == "Product" -select [ - first_name, - last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap deleted file mode 100644 index 19c4de64822f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" ---- -prql target:sql.mysql - - - -from employees -select `first name` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap deleted file mode 100644 index 0ef6f6c5ea4e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" ---- -prql target:sql.postgres - - - -from employees -select `first name` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap deleted file mode 100644 index acd1651bdbb9..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from `dir/*.parquet`\n" ---- -from `dir/*.parquet` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap deleted file mode 100644 index 6be462d1cb08..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" ---- -prql target:sql.bigquery - - - -from `project-foo.dataset.table` -join `project-bar.dataset.table` [==col_bax] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap deleted file mode 100644 index fc9310bcceea..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from `music.albums`\n" ---- -from `music.albums` - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap deleted file mode 100644 index 4e250a9bf506..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter id == $1\n" ---- -from employees -filter id == $1 - - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap deleted file mode 100644 index 7aa2caf4c217..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" ---- -from numbers -select [ - small = 1.0000001, - big = 5000000, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap deleted file mode 100644 index ddc2d6ddb49a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" ---- -std.from my_table -std.select [ - from = my_table.a, - take = my_table.b, -] -std.take 3 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap deleted file mode 100644 index a12652162d23..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from numbers\nderive [x = 1, y = 2]\nderive [\n a = x,\n b = y\n]\nderive [\n c = a,\n d = b,\n]\n" ---- -from numbers -derive [ - x = 1, - y = 2, -] -derive [ - a = x, - b = y, -] -derive [ - c = a, - d = b, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap deleted file mode 100644 index 4077d71aaa9b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect [first_name]\n" ---- -from employees -select [first_name] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap deleted file mode 100644 index 027e1a5e000f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from foo\nselect [\n circumference = diameter * 3.14159,\n color,\n]\nfilter circumference > 10 and color != \"red\"\n" ---- -from foo -select [ - circumference = diameter * 3.14159, - color, -] -filter circumference > 10 and color != "red" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap deleted file mode 100644 index b9f326d968cc..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap +++ /dev/null @@ -1,39 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" ---- -from employees -derive is_proximate = ( - distance - in 0..20 -) -derive ( - total_distance = sum distance -) -derive ( - min_capped_distance = min distance ?? 5 -) -derive travel_time = distance / 40 -derive ( - distance_rounded_2_dp = round 1 + 1 distance -) -derive [ - is_far = ( - distance - in 100.. -), - is_negative = ( - distance - in -100..0 -), - is_negative = ( - distance - in -100..0 -), - average_distance = average distance, -] -sort -distance -sort [-distance] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap deleted file mode 100644 index 87ed02336d92..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive total_distance = sum distance\n" ---- -from employees -derive total_distance = sum distance - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap deleted file mode 100644 index 81e0a3146955..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" ---- -from employees -group [ - title, - country, -] ( - aggregate [ - average salary, - ct = count, -] -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap deleted file mode 100644 index 4f94033b1f86..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" ---- -from employees -aggregate [average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap deleted file mode 100644 index 1c202ec4ba25..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\naggregate [\n average salary,\n ct = count\n]\n" ---- -from employees -aggregate [ - average salary, - ct = count, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap deleted file mode 100644 index 81e0a3146955..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" ---- -from employees -group [ - title, - country, -] ( - aggregate [ - average salary, - ct = count, -] -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap deleted file mode 100644 index 9b49b51df2a5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [avg_sal = average salary]\n" ---- -from employees -derive [avg_sal = average salary] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap deleted file mode 100644 index cbbd0478001b..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nappend employees_2\n" ---- -from employees_1 -append employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap deleted file mode 100644 index e2b9a1338479..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nremove employees_2\n" ---- -from employees_1 -remove employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap deleted file mode 100644 index 1971d287b890..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees_1\nintersect employees_2\n" ---- -from employees_1 -intersect employees_2 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap deleted file mode 100644 index 183b59f98112..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive gross_salary = salary + payroll_tax\n" ---- -from employees -derive gross_salary = salary + payroll_tax - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap deleted file mode 100644 index 3d298b6f9b55..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" ---- -from employees -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap deleted file mode 100644 index bd5e2c425e25..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter age > 25\n" ---- -from employees -filter age > 25 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap deleted file mode 100644 index a6cb5b5b569e..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter (age > 25 or department != \"IT\")\n" ---- -from employees -filter age > 25 or department != "IT" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap deleted file mode 100644 index d3b04cd4de31..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter (age | in 25..40)\n" ---- -from employees -filter ( - age - in 25..40 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap deleted file mode 100644 index 8ef6dce0bb66..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap +++ /dev/null @@ -1,8 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n" ---- -from employees - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap deleted file mode 100644 index ef1312a86941..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e = employees\nselect e.first_name\n" ---- -from e = employees -select e.first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap deleted file mode 100644 index 81e0a3146955..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap +++ /dev/null @@ -1,17 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" ---- -from employees -group [ - title, - country, -] ( - aggregate [ - average salary, - ct = count, -] -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap deleted file mode 100644 index 2517396a1418..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort join_date\ntake 1\n" ---- -from employees -sort join_date -take 1 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap deleted file mode 100644 index 11467687bbbb..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup role (\n sort join_date # taken from above\n take 1\n)\n" ---- -from employees -group role ( - sort join_date - take 1 -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap deleted file mode 100644 index 4d113382409a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\njoin side:left positions [employees.id==positions.employee_id]\n" ---- -from employees -join side:left positions [employees.id == positions.employee_id] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap deleted file mode 100644 index b3e13a1d23f8..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\njoin side:left p=positions [employees.id==p.employee_id]\n" ---- -from employees -join side:left p = positions [employees.id == p.employee_id] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap deleted file mode 100644 index ba833fa01b02..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\njoin positions [==emp_no]\n" ---- -from employees -join positions [==emp_no] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap deleted file mode 100644 index ef3e65965333..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect name = f\"{first_name} {last_name}\"\n" ---- -from employees -select name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap deleted file mode 100644 index 57c345371217..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect [\n name = f\"{first_name} {last_name}\",\n age_eoy = dob - @2022-12-31,\n]\n" ---- -from employees -select [ - name = f"{first_name} {last_name}", - age_eoy = dob - @2022-12-31, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap deleted file mode 100644 index 56e49df27e11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nselect first_name\n" ---- -from employees -select first_name - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap deleted file mode 100644 index 059b92276754..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from e=employees\nselect [e.first_name, e.last_name]\n" ---- -from e = employees -select [ - e.first_name, - e.last_name, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap deleted file mode 100644 index 6445588450d2..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" ---- -prql target:sql.bigquery - - - -from tracks -select not [ - milliseconds, - bytes, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap deleted file mode 100644 index 568bc821ba4f..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" ---- -from tracks -select [ - track_id, - title, - composer, - bytes, -] -select not [ - title, - composer, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap deleted file mode 100644 index 19b65db61c48..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from artists\nderive nick = name\nselect ![artists.*]\n" ---- -from artists -derive nick = name -select not [artists.`*`] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap deleted file mode 100644 index cb41ef4b5ddb..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort age\n" ---- -from employees -sort age - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap deleted file mode 100644 index 12203dcc78d3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [-age]\n" ---- -from employees -sort [-age] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap deleted file mode 100644 index a7ddb76e2ecc..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [age, -tenure, +salary]\n" ---- -from employees -sort [ - age, - -tenure, - +salary, -] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap deleted file mode 100644 index 01b0d75eb4e3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" ---- -from employees -sort [s"substr({first_name}, 2, 5)"] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap deleted file mode 100644 index 51c71b587af5..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort tenure\nderive name = f\"{first_name} {last_name}\"\n" ---- -from employees -sort tenure -derive name = f"{first_name} {last_name}" - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap deleted file mode 100644 index 405c461df7e4..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort tenure\njoin locations [==employee_id]\n" ---- -from employees -sort tenure -join locations [==employee_id] - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap deleted file mode 100644 index 4c39e0cddcea..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ntake 10\n" ---- -from employees -take 10 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap deleted file mode 100644 index b68c1920a669..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap +++ /dev/null @@ -1,13 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" ---- -from orders -sort [ - -value, - date, -] -take 101..110 - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap deleted file mode 100644 index 08d6e23e2468..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup employee_id (\n sort month\n window rolling:12 (\n derive [trail_12_m_comp = sum paycheck]\n )\n)\n" ---- -from employees -group employee_id ( - sort month - window rolling:12 ( - derive [trail_12_m_comp = sum paycheck] -) -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap deleted file mode 100644 index c0663a94bc4a..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap +++ /dev/null @@ -1,18 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from orders\nsort day\nwindow rows:-3..3 (\n derive [centered_weekly_average = average value]\n)\ngroup [order_month] (\n sort day\n window expanding:true (\n derive [monthly_running_total = sum value]\n )\n)\n" ---- -from orders -sort day -window rows:-3..3 ( - derive [centered_weekly_average = average value] -) -group [order_month] ( - sort day - window expanding:true ( - derive [monthly_running_total = sum value] -) -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap deleted file mode 100644 index dc3037c993b3..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nsort age\nderive rnk = rank\n" ---- -from employees -sort age -derive rnk = rank - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap deleted file mode 100644 index b71455102a11..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\ngroup department (\n sort age\n derive rnk = rank\n)\n" ---- -from employees -group department ( - sort age - derive rnk = rank -) - - - diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap deleted file mode 100644 index 9e104fbe34a9..000000000000 --- a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nfilter salary < (average salary)\n" ---- -from employees -filter salary < ( average salary ) - - - From 0d2ff48168344c1e9e4f4cd356c96e214c43ce08 Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Mon, 6 Mar 2023 14:31:55 +0900 Subject: [PATCH 107/184] build: add definitions for devcontainer base image (#2025) * build: add definitions for devcontainer base image * build: split install-cargo-tools task to another Taskfile --- .devcontainer/base-image/Dockerfile | 15 +++++++ .github/dependabot.yml | 7 ++++ .github/workflows/devcontainer.yaml | 64 +++++++++++++++++++++++++++++ Taskfile.cargo-tools.yml | 19 +++++++++ Taskfile.yml | 20 ++++----- 5 files changed, 112 insertions(+), 13 deletions(-) create mode 100644 .devcontainer/base-image/Dockerfile create mode 100644 .github/workflows/devcontainer.yaml create mode 100644 Taskfile.cargo-tools.yml diff --git a/.devcontainer/base-image/Dockerfile b/.devcontainer/base-image/Dockerfile new file mode 100644 index 000000000000..00200fe5b006 --- /dev/null +++ b/.devcontainer/base-image/Dockerfile @@ -0,0 +1,15 @@ +FROM mcr.microsoft.com/devcontainers/rust:0.203.7-1 + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + cmake \ + && rm -rf /var/lib/apt/lists/* \ + && sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin + +# ========= Install cargo-tools for non-root user (vscode) ========= +COPY Taskfile.cargo-tools.yml /tmp/Taskfile.cargo-tools.yml +WORKDIR /tmp +USER vscode +RUN task -t Taskfile.cargo-tools.yml install + +USER root diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 9037733798b9..cf0f85edf82a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -29,6 +29,13 @@ updates: commit-message: prefix: "chore: " + - package-ecosystem: docker + directory: .devcontainer/base-image + schedule: + interval: daily + commit-message: + prefix: "chore: " + # For actions (rather than workflows), we need to list each directory, ref # https://github.com/dependabot/dependabot-core/issues/5137, from https://github.com/dependabot/dependabot-core/issues/4178#issuecomment-1118492006 - directory: ".github/actions/build-prql-js" diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml new file mode 100644 index 000000000000..1b28019a4975 --- /dev/null +++ b/.github/workflows/devcontainer.yaml @@ -0,0 +1,64 @@ +name: devcontainer + +on: + push: + paths: + - .devcontainer/base-image/Dockerfile + - Taskfile.cargo-tools.yml + pull_request: + paths: + - .devcontainer/base-image/Dockerfile + - Taskfile.cargo-tools.yml + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: docker/metadata-action@v4 + id: meta + with: + images: ghcr.io/${{ github.repository_owner }}/prql-devcontainer-base + tags: | + type=raw,latest + + - name: Login to GitHub Container Registry + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - id: set-platforms + run: | + if [ "${{ github.ref }}" = "refs/heads/main" ]; then + echo "platforms=linux/amd64,linux/arm64" >>$GITHUB_OUTPUT + echo "push=true" >>$GITHUB_OUTPUT + else + echo "platforms=linux/amd64" >>$GITHUB_OUTPUT + echo "push=false" >>$GITHUB_OUTPUT + fi + + - name: Build + uses: docker/build-push-action@v4 + with: + file: "./.devcontainer/base-image/Dockerfile" + tags: ${{ steps.meta.outputs.tags }} + platforms: ${{ steps.set-platforms.outputs.platforms }} + push: ${{ steps.set-platforms.outputs.push }} + cache-from: | + ${{ env.IMAGE_NAME }} + type=gha + cache-to: | + type=inline + type=gha,mode=max diff --git a/Taskfile.cargo-tools.yml b/Taskfile.cargo-tools.yml new file mode 100644 index 000000000000..814e4108fece --- /dev/null +++ b/Taskfile.cargo-tools.yml @@ -0,0 +1,19 @@ +# yaml-language-server: $schema=https://json.schemastore.org/taskfile.json + +version: 3 + +tasks: + install: + # factored this out because it takes a long time to build + desc: Install cargo tools for PRQL development. + cmds: + # `--locked` installs from the underlying lock files (which is not the + # default?!) + - cargo install --locked bacon cargo-audit cargo-insta cargo-release + default-target mdbook mdbook-admonish mdbook-toc wasm-bindgen-cli + wasm-pack + # Can't install atm with `--locked` + - cargo install mdbook-footnote + - cmd: | + [ "$(which cargo-insta)" ] || echo "๐Ÿ”ด Can't find a binary that cargo just installed. Is the cargo bin path (generally at ~/.cargo/bin) on the \$PATH?" + silent: true diff --git a/Taskfile.yml b/Taskfile.yml index 0407891f50f6..6ea88606fff2 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -11,6 +11,9 @@ version: "3" +includes: + cargo-tools: ./Taskfile.cargo-tools.yml + vars: # Keep in sync with .vscode/extensions.json vscode_extensions: | @@ -38,7 +41,7 @@ tasks: desc: Install tools for PRQL development. cmds: - - task: install-cargo-tools + - task: cargo-tools:install - task: install-brew-dependencies - task: install-maturin - task: install-pre-commit @@ -54,18 +57,9 @@ tasks: install-cargo-tools: # factored this out because it takes a long time to build - desc: Install cargo tools for PRQL development. - cmds: - # `--locked` installs from the underlying lock files (which is not the - # default?!) - - cargo install --locked bacon cargo-audit cargo-insta cargo-release - default-target mdbook mdbook-admonish mdbook-toc wasm-bindgen-cli - wasm-pack - # Can't install atm with `--locked` - - cargo install mdbook-footnote - - cmd: | - [ "$(which cargo-insta)" ] || echo "๐Ÿ”ด Can't find a binary that cargo just installed. Is the cargo bin path (generally at ~/.cargo/bin) on the \$PATH?" - silent: true + desc: Alias of `cargo-tools:install` + deps: + - cargo-tools:install install-maturin: desc: Install maturin. From 5d20e7facd1d69ef3de23290270031af77c645af Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Mon, 6 Mar 2023 14:43:52 +0900 Subject: [PATCH 108/184] build: fix concurrency of devcontainer.yaml (#2027) --- .github/workflows/devcontainer.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml index 1b28019a4975..840cd9b30f4e 100644 --- a/.github/workflows/devcontainer.yaml +++ b/.github/workflows/devcontainer.yaml @@ -12,7 +12,7 @@ on: workflow_dispatch: concurrency: - group: ${{ github.workflow }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: From dcfcb5f56a44b1a52041cd63a1def093b2691f70 Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Mon, 6 Mar 2023 16:17:29 +0900 Subject: [PATCH 109/184] build: fix docker build workflows (#2028) * build: always build amd64 and arm64 * build: fix copying Taskfile * chore: bump base image version and pin to bullseye * build: try only build arm64 * build: build amd64 only for now --- .devcontainer/base-image/Dockerfile | 2 +- .github/workflows/devcontainer.yaml | 9 ++++----- Dockerfile | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/.devcontainer/base-image/Dockerfile b/.devcontainer/base-image/Dockerfile index 00200fe5b006..6d71dcde78cb 100644 --- a/.devcontainer/base-image/Dockerfile +++ b/.devcontainer/base-image/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/devcontainers/rust:0.203.7-1 +FROM mcr.microsoft.com/devcontainers/rust:0.203.8-1-bullseye RUN apt-get update \ && apt-get install -y --no-install-recommends \ diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml index 840cd9b30f4e..86392d342c7c 100644 --- a/.github/workflows/devcontainer.yaml +++ b/.github/workflows/devcontainer.yaml @@ -39,13 +39,11 @@ jobs: - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - - id: set-platforms + - id: set-options run: | if [ "${{ github.ref }}" = "refs/heads/main" ]; then - echo "platforms=linux/amd64,linux/arm64" >>$GITHUB_OUTPUT echo "push=true" >>$GITHUB_OUTPUT else - echo "platforms=linux/amd64" >>$GITHUB_OUTPUT echo "push=false" >>$GITHUB_OUTPUT fi @@ -54,8 +52,9 @@ jobs: with: file: "./.devcontainer/base-image/Dockerfile" tags: ${{ steps.meta.outputs.tags }} - platforms: ${{ steps.set-platforms.outputs.platforms }} - push: ${{ steps.set-platforms.outputs.push }} + # TODO: add linux/arm64 + platforms: linux/amd64 + push: ${{ steps.set-options.outputs.push }} cache-from: | ${{ env.IMAGE_NAME }} type=gha diff --git a/Dockerfile b/Dockerfile index 98050395e45e..f97fd15bfcb5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -45,10 +45,10 @@ RUN sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/loc # ========= Set up workdir & copy the taskfile ========= WORKDIR /src -COPY Taskfile.yml . +COPY Taskfile.cargo-tools.yml . # ========= Install cargo-tools ========= -RUN task install-cargo-tools +RUN task -t Taskfile.cargo-tools.yml install # TODO: currently this doesn't support doing things like running the playground, # since we don't install hugo & node. Default `apt` doesn't install up-to-date From b05c626f9b6fb00aa18e7864e6b9b44e1a06a664 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Mar 2023 11:35:10 -0800 Subject: [PATCH 110/184] chore: pre-commit autoupdate (#2032) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/crate-ci/typos: v1.13.12 โ†’ v1.13.18](https://github.com/crate-ci/typos/compare/v1.13.12...v1.13.18) - [github.com/pre-commit/mirrors-prettier: v3.0.0-alpha.4 โ†’ v3.0.0-alpha.6](https://github.com/pre-commit/mirrors-prettier/compare/v3.0.0-alpha.4...v3.0.0-alpha.6) - [github.com/charliermarsh/ruff-pre-commit: v0.0.252 โ†’ v0.0.254](https://github.com/charliermarsh/ruff-pre-commit/compare/v0.0.252...v0.0.254) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5c1f89d13d77..f7ae30ed711c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,20 +8,20 @@ repos: - id: check-yaml - id: mixed-line-ending - repo: https://github.com/crate-ci/typos - rev: v1.13.12 + rev: v1.13.18 hooks: - id: typos # https://github.com/crate-ci/typos/issues/347 pass_filenames: false - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.0.0-alpha.4 + rev: v3.0.0-alpha.6 hooks: - id: prettier additional_dependencies: - prettier - prettier-plugin-go-template - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.0.252 + rev: v0.0.254 hooks: - id: ruff - repo: https://github.com/psf/black From a6c7455121d64875cdd76a092714c53242bad80d Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 6 Mar 2023 21:20:23 -0800 Subject: [PATCH 111/184] devops: Add shortcuts for insta in `bacon` (#2037) * devops: Add shortcuts for insta in `bacon` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- bacon.toml | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/bacon.toml b/bacon.toml index 9e9e82362080..5e8415c743c6 100644 --- a/bacon.toml +++ b/bacon.toml @@ -3,9 +3,9 @@ default_job = "check" # PRQL additions -[jobs.test-rust-fast] +[jobs.test-fast] command = ['cargo', 'insta', 'test', '--accept', "--color=always", "-p=prql-compiler", "--lib"] -[jobs.test-rust] +[jobs.test] command = ['cargo', 'insta', 'test', '--accept', "--color=always"] # Standard tasks @@ -24,11 +24,6 @@ command = ["cargo", "clippy", "--all-targets", "--color", "always"] need_stdout = false watch = ["tests", "benches", "examples"] -[jobs.test] -command = ["cargo", "test", "--color", "always"] -need_stdout = true -watch = ["tests"] - [jobs.doc] command = ["cargo", "doc", "--color", "always", "--no-deps"] need_stdout = false @@ -59,7 +54,6 @@ need_stdout = true a = "job:check-all" c = "job:clippy" d = "job:doc-open" -# i for `insta` -i = "job:test-rust-fast" +f = "job:test-fast" r = "job:run" t = "job:test" From 47ec070a6588ac012a770830431f0a25171f7ea5 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 6 Mar 2023 22:32:39 -0800 Subject: [PATCH 112/184] devops: Sync bacon command with `test-rust` (#2038) * devops: Sync bacon command with `test-rust` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- bacon.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bacon.toml b/bacon.toml index 5e8415c743c6..5361e3781741 100644 --- a/bacon.toml +++ b/bacon.toml @@ -6,7 +6,7 @@ default_job = "check" [jobs.test-fast] command = ['cargo', 'insta', 'test', '--accept', "--color=always", "-p=prql-compiler", "--lib"] [jobs.test] -command = ['cargo', 'insta', 'test', '--accept', "--color=always"] +command = ['cargo', 'insta', 'test', '--accept', "--color=always", "--unreferenced=auto"] # Standard tasks From f04baf22a69e02bfa858f23b77926ad702d56ee8 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Mon, 6 Mar 2023 22:33:17 -0800 Subject: [PATCH 113/184] feat!: Rename `switch` to `case` (#2036) * feat: Rename `switch` to `case` In case `switch` is confusing, this switches `switch` for `case`. Hopefully the switch won't lead to a case of confusion; or we can case the decision again. --- CHANGELOG.md | 16 +++++++----- book/highlight-prql.js | 2 +- book/src/SUMMARY.md | 2 +- book/src/language-features/README.md | 26 +++++++++---------- .../language-features/{switch.md => case.md} | 10 +++---- book/src/syntax.md | 4 +-- .../{switch-0.prql => case-0.prql} | 2 +- .../{switch-1.prql => case-1.prql} | 2 +- ...shot__@language-features__case-0.prql.snap | 15 +++++++++++ ...shot__@language-features__case-1.prql.snap | 15 +++++++++++ ...ot__@language-features__switch-0.prql.snap | 14 ---------- ...ot__@language-features__switch-1.prql.snap | 14 ---------- book/theme/highlight.js | 2 +- playground/src/workbench/prql-syntax.js | 2 +- prql-compiler/src/ast/pl/expr.rs | 6 ++--- prql-compiler/src/ast/pl/fold.rs | 2 +- prql-compiler/src/ast/rq/expr.rs | 2 +- prql-compiler/src/ast/rq/fold.rs | 2 +- prql-compiler/src/parser/expr.rs | 6 ++--- prql-compiler/src/parser/lexer.rs | 2 +- prql-compiler/src/parser/mod.rs | 6 ++--- prql-compiler/src/semantic/lowering.rs | 2 +- prql-compiler/src/semantic/static_analysis.rs | 4 +-- prql-compiler/src/sql/anchor.rs | 2 +- prql-compiler/src/sql/gen_expr.rs | 2 +- prql-compiler/src/test.rs | 10 +++---- .../tests/integration/data/chinook/tracks.csv | 2 +- .../tests/integration/queries/switch.prql | 2 +- .../integration__tests__test@switch.prql.snap | 2 +- prql-lezer/src/prql.grammar | 2 +- .../posts/2023-02-02-one-year/_index.md | 2 +- .../plugins/bootstrap/bootstrap.bundle.min.js | 2 +- .../static/plugins/highlight/highlight.min.js | 4 +-- .../static/plugins/highlight/prql.js | 2 +- 34 files changed, 97 insertions(+), 93 deletions(-) rename book/src/language-features/{switch.md => case.md} (59%) rename book/tests/prql/language-features/{switch-0.prql => case-0.prql} (79%) rename book/tests/prql/language-features/{switch-1.prql => case-1.prql} (82%) create mode 100644 book/tests/snapshots/snapshot__@language-features__case-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__@language-features__case-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@language-features__switch-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@language-features__switch-1.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index d5d7bec3f038..fc752c79d360 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,7 @@ - `and` now has a higher precedence than `or` (of same reason as the previous point). - Dates, times and timestamps have stricter parsing rules. - - `let`, `func`, `prql`, `switch` are now treated as keywords. + - `let`, `func`, `prql`, `case` are now treated as keywords. - Float literals without fraction part are not allowed anymore (`1.`). - Add a `--format` option to `prqlc parse` which can return the AST in YAML (@max-sixty, #1962) @@ -28,6 +28,8 @@ `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). - Add `std.upper` and `std.lower` functions for changing string casing (@Jelenkee, #2019). +- Rename the experimental `switch` to `case` given it more closely matches the + traditional semantics of `case`. (@max-sixty, #2036) **Fixes**: @@ -214,7 +216,7 @@ This release has 74 commits from 12 contributors. Selected changes: ## 0.4.0 โ€” 2022-01-15 -0.4.0 brings lots of new features including `switch`, `select ![]` and numbers +0.4.0 brings lots of new features including `case`, `select ![]` and numbers with underscores. We have initial (unpublished) bindings to Elixir. And there's the usual improvements to fixes & documentation (only a minority are listed below in this release). @@ -229,12 +231,12 @@ below in this release). [tables docs](https://prql-lang.org/book/queries/variables.html) for details. - _Experimental:_ The - [`switch`](https://prql-lang.org/book/language-features/switch.html) function - sets a variable to a value based on one of several expressions (@aljazerzen, + [`case`](https://prql-lang.org/book/language-features/case.html) function sets + a variable to a value based on one of several expressions (@aljazerzen, #1278). ```prql - derive var = switch [ + derive var = case [ score <= 10 -> "low", score <= 30 -> "medium", score <= 70 -> "high", @@ -258,8 +260,8 @@ below in this release). ``` Check out the - [`switch` docs](https://prql-lang.org/book/language-features/switch.html) for - more details. + [`case` docs](https://prql-lang.org/book/language-features/case.html) for more + details. - _Experimental:_ Columns can be excluded by name with `select` (@aljazerzen, #1329) diff --git a/book/highlight-prql.js b/book/highlight-prql.js index 6993b6f799d5..2f3e7136fdda 100644 --- a/book/highlight-prql.js +++ b/book/highlight-prql.js @@ -35,7 +35,7 @@ formatting = function (hljs) { "union", "window", ]; - const BUILTIN_FUNCTIONS = ["switch", "in", "as"]; + const BUILTIN_FUNCTIONS = ["case", "in", "as"]; const KEYWORDS = ["func", "let", "prql"]; return { name: "PRQL", diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index cc27566b74a2..d8dea5cd6719 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -42,7 +42,7 @@ - [Strings](./language-features/strings.md) - [S-strings](./language-features/s-strings.md) - [F-strings](./language-features/f-strings.md) - - [Switch](./language-features/switch.md) + - [Case](./language-features/case.md) - [Target & Version](./language-features/target.md) - [Bindings](./bindings/README.md) diff --git a/book/src/language-features/README.md b/book/src/language-features/README.md index 45b07178b7d4..a75dfe4e9e88 100644 --- a/book/src/language-features/README.md +++ b/book/src/language-features/README.md @@ -3,16 +3,16 @@ The pages of this section describe how PRQL handles various aspects of the language. -| Feature | Purpose | -| ---------------- | ------------------------------------------------------------------------- | -| Coalesce | [Handle potentially NULL values](./coalesce.md) | -| Dates & times | [Handle dates and times](./dates-and-times.md) | -| Distinct | [Equivalent of SQL `DISTINCT`](./distinct.md) | -| Null handling | [Handle `NULL` values](./null.md) | -| Ranges | [Syntax for all forms of ranges](./ranges.md) | -| Regex | [Handle regular expressions](./regex.md) | -| Strings | [Rules for creating strings](./strings.md) | -| S-strings | [Insert SQL directly into a query with an S-string](./s-strings.md) | -| F-strings | [Combine several column's data with F-strings](./f-strings.md) | -| Switch | [Create a new column based on the contents of other columns](./switch.md) | -| Target & Version | [Specify a target SQL engine and PRQL version](./target.md) | +| Feature | Purpose | +| ---------------- | ----------------------------------------------------------------------- | +| Coalesce | [Handle potentially NULL values](./coalesce.md) | +| Dates & times | [Handle dates and times](./dates-and-times.md) | +| Distinct | [Equivalent of SQL `DISTINCT`](./distinct.md) | +| Null handling | [Handle `NULL` values](./null.md) | +| Ranges | [Syntax for all forms of ranges](./ranges.md) | +| Regex | [Handle regular expressions](./regex.md) | +| Strings | [Rules for creating strings](./strings.md) | +| S-strings | [Insert SQL directly into a query with an S-string](./s-strings.md) | +| F-strings | [Combine several column's data with F-strings](./f-strings.md) | +| Case | [Create a new column based on the contents of other columns](./case.md) | +| Target & Version | [Specify a target SQL engine and PRQL version](./target.md) | diff --git a/book/src/language-features/switch.md b/book/src/language-features/case.md similarity index 59% rename from book/src/language-features/switch.md rename to book/src/language-features/case.md index eb9353eee968..a836e84b1b2b 100644 --- a/book/src/language-features/switch.md +++ b/book/src/language-features/case.md @@ -1,14 +1,14 @@ -# Switch +# Case ```admonish note -`switch` is currently experimental and may change behavior in the near future +`case` is currently experimental and may change behavior in the near future ``` -PRQL uses `switch` for both SQL's `CASE` and `IF` statements. Here's an example: +PRQL uses `case` for both SQL's `CASE` and `IF` statements. Here's an example: ```prql_no_fmt from employees -derive distance = switch [ +derive distance = case [ city == "Calgary" -> 0, city == "Edmonton" -> 300, ] @@ -19,7 +19,7 @@ If no condition is met, the value takes a `null` value. To set a default, use a ```prql_no_fmt from employees -derive distance = switch [ +derive distance = case [ city == "Calgary" -> 0, city == "Edmonton" -> 300, true -> "Unknown", diff --git a/book/src/syntax.md b/book/src/syntax.md index 2382e5be3d44..900f671388c3 100644 --- a/book/src/syntax.md +++ b/book/src/syntax.md @@ -294,9 +294,9 @@ At the moment, PRQL uses only four keywords: - `prql` - `let` - `func` -- `switch` +- `case` -To use these names as columns or relations, use backticks: `` `switch` ``. +To use these names as columns or relations, use backticks: `` `case` ``. It may seem that transforms are also keywords, but they are normal function within std namespace: diff --git a/book/tests/prql/language-features/switch-0.prql b/book/tests/prql/language-features/case-0.prql similarity index 79% rename from book/tests/prql/language-features/switch-0.prql rename to book/tests/prql/language-features/case-0.prql index c2cd611f974a..0845b3bf8fc7 100644 --- a/book/tests/prql/language-features/switch-0.prql +++ b/book/tests/prql/language-features/case-0.prql @@ -1,7 +1,7 @@ # Can't yet format & compile from employees -derive distance = switch [ +derive distance = case [ city == "Calgary" -> 0, city == "Edmonton" -> 300, ] diff --git a/book/tests/prql/language-features/switch-1.prql b/book/tests/prql/language-features/case-1.prql similarity index 82% rename from book/tests/prql/language-features/switch-1.prql rename to book/tests/prql/language-features/case-1.prql index aba9837069df..5a97534e00b1 100644 --- a/book/tests/prql/language-features/switch-1.prql +++ b/book/tests/prql/language-features/case-1.prql @@ -1,7 +1,7 @@ # Can't yet format & compile from employees -derive distance = switch [ +derive distance = case [ city == "Calgary" -> 0, city == "Edmonton" -> 300, true -> "Unknown", diff --git a/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap new file mode 100644 index 000000000000..c1b47f0b82e5 --- /dev/null +++ b/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap @@ -0,0 +1,15 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" +input_file: book/tests/prql/language-features/case-0.prql +--- +SELECT + *, + CASE + WHEN city = 'Calgary' THEN 0 + WHEN city = 'Edmonton' THEN 300 + ELSE NULL + END AS distance +FROM + employees + diff --git a/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap new file mode 100644 index 000000000000..816c9244da9b --- /dev/null +++ b/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap @@ -0,0 +1,15 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" +input_file: book/tests/prql/language-features/case-1.prql +--- +SELECT + *, + CASE + WHEN city = 'Calgary' THEN 0 + WHEN city = 'Edmonton' THEN 300 + ELSE 'Unknown' + END AS distance +FROM + employees + diff --git a/book/tests/snapshots/snapshot__@language-features__switch-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__switch-0.prql.snap deleted file mode 100644 index 3fc3b672a06b..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__switch-0.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" -input_file: book/tests/prql/language-features/switch-0.prql ---- -SELECT - *, - CASE - WHEN city = 'Calgary' THEN 0 - WHEN city = 'Edmonton' THEN 300 - ELSE NULL - END AS distance -FROM - employees diff --git a/book/tests/snapshots/snapshot__@language-features__switch-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__switch-1.prql.snap deleted file mode 100644 index 3ce88aec5690..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__switch-1.prql.snap +++ /dev/null @@ -1,14 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive distance = switch [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" -input_file: book/tests/prql/language-features/switch-1.prql ---- -SELECT - *, - CASE - WHEN city = 'Calgary' THEN 0 - WHEN city = 'Edmonton' THEN 300 - ELSE 'Unknown' - END AS distance -FROM - employees diff --git a/book/theme/highlight.js b/book/theme/highlight.js index 070264e2e698..7f5ea2af40b3 100644 --- a/book/theme/highlight.js +++ b/book/theme/highlight.js @@ -1 +1 @@ -var hljs=function(){"use strict";var e={exports:{}};function n(e){return e instanceof Map?e.clear=e.delete=e.set=()=>{throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{throw Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{var a=e[t];"object"!=typeof a||Object.isFrozen(a)||n(a)}),e}e.exports=n,e.exports.default=n;var t=e.exports;class a{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function i(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){const t=Object.create(null);for(const n in e)t[n]=e[n];return n.forEach(e=>{for(const n in e)t[n]=e[n]}),t}const s=e=>!!e.kind;class o{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=i(e)}openNode(e){if(!s(e))return;let n=e.kind;n=e.sublanguage?"language-"+n:((e,{prefix:n})=>{if(e.includes(".")){const t=e.split(".");return[`${n}${t.shift()}`,...t.map((e,n)=>`${e}${"_".repeat(n+1)}`)].join(" ")}return`${n}${e}`})(n,{prefix:this.classPrefix}),this.span(n)}closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){this.buffer+=``}}class l{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{l._collapse(e)}))}}class c extends l{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new o(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}function g(e){return m("(?=",e,")")}function u(e){return m("(?:",e,")*")}function b(e){return m("(?:",e,")?")}function m(...e){return e.map(e=>d(e)).join("")}function p(...e){const n=(e=>{const n=e[e.length-1];return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{}})(e);return"("+(n.capture?"":"?:")+e.map(e=>d(e)).join("|")+")"}function _(e){return RegExp(e.toString()+"|").exec("").length-1}const h=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function f(e,{joinWith:n}){let t=0;return e.map(e=>{t+=1;const n=t;let a=d(e),i="";for(;a.length>0;){const e=h.exec(a);if(!e){i+=a;break}i+=a.substring(0,e.index),a=a.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?i+="\\"+(Number(e[1])+n):(i+=e[0],"("===e[0]&&t++)}return i}).map(e=>`(${e})`).join(n)}const E="[a-zA-Z]\\w*",y="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",N="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",v="\\b(0b[01]+)",k={begin:"\\\\[\\s\\S]",relevance:0},O={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[k]},x={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[k]},M=(e,n,t={})=>{const a=r({scope:"comment",begin:e,end:n,contains:[]},t);a.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const i=p("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return a.contains.push({begin:m(/[ ]+/,"(",i,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),a},S=M("//","$"),A=M("/\\*","\\*/"),C=M("#","$");var T=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:E,UNDERSCORE_IDENT_RE:y,NUMBER_RE:w,C_NUMBER_RE:N,BINARY_NUMBER_RE:v,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=m(n,/.*\b/,e.binary,/\b.*/)),r({scope:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:k,APOS_STRING_MODE:O,QUOTE_STRING_MODE:x,PHRASAL_WORDS_MODE:{begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},COMMENT:M,C_LINE_COMMENT_MODE:S,C_BLOCK_COMMENT_MODE:A,HASH_COMMENT_MODE:C,NUMBER_MODE:{scope:"number",begin:w,relevance:0},C_NUMBER_MODE:{scope:"number",begin:N,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:v,relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[k,{begin:/\[/,end:/\]/,relevance:0,contains:[k]}]}]},TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_TITLE_MODE:{scope:"title",begin:y,relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})});function R(e,n){"."===e.input[e.index-1]&&n.ignoreMatch()}function D(e,n){void 0!==e.className&&(e.scope=e.className,delete e.className)}function I(e,n){n&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,void 0===e.relevance&&(e.relevance=0))}function L(e,n){Array.isArray(e.illegal)&&(e.illegal=p(...e.illegal))}function B(e,n){if(e.match){if(e.begin||e.end)throw Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function $(e,n){void 0===e.relevance&&(e.relevance=1)}const z=(e,n)=>{if(!e.beforeMatch)return;if(e.starts)throw Error("beforeMatch cannot be used with starts");const t=Object.assign({},e);Object.keys(e).forEach(n=>{delete e[n]}),e.keywords=t.keywords,e.begin=m(t.beforeMatch,g(t.begin)),e.starts={relevance:0,contains:[Object.assign(t,{endsParent:!0})]},e.relevance=0,delete t.beforeMatch},F=["of","and","for","in","not","or","if","then","parent","list","value"];function U(e,n,t="keyword"){const a=Object.create(null);return"string"==typeof e?i(t,e.split(" ")):Array.isArray(e)?i(t,e):Object.keys(e).forEach(t=>{Object.assign(a,U(e[t],n,t))}),a;function i(e,t){n&&(t=t.map(e=>e.toLowerCase())),t.forEach(n=>{const t=n.split("|");a[t[0]]=[e,j(t[0],t[1])]})}}function j(e,n){return n?Number(n):(e=>F.includes(e.toLowerCase()))(e)?0:1}const P={},K=e=>{console.error(e)},H=(e,...n)=>{console.log("WARN: "+e,...n)},q=(e,n)=>{P[`${e}/${n}`]||(console.log(`Deprecated as of ${e}. ${n}`),P[`${e}/${n}`]=!0)},Z=Error();function G(e,n,{key:t}){let a=0;const i=e[t],r={},s={};for(let e=1;e<=n.length;e++)s[e+a]=i[e],r[e+a]=!0,a+=_(n[e-1]);e[t]=s,e[t]._emit=r,e[t]._multi=!0}function W(e){(e=>{e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope}),(e=>{if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw K("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),Z;if("object"!=typeof e.beginScope||null===e.beginScope)throw K("beginScope must be object"),Z;G(e,e.begin,{key:"beginScope"}),e.begin=f(e.begin,{joinWith:""})}})(e),(e=>{if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw K("skip, excludeEnd, returnEnd not compatible with endScope: {}"),Z;if("object"!=typeof e.endScope||null===e.endScope)throw K("endScope must be object"),Z;G(e,e.end,{key:"endScope"}),e.end=f(e.end,{joinWith:""})}})(e)}function Q(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=_(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(f(e,{joinWith:"|"}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),a=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,a)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;let t=n.exec(e);if(this.resumingScanAtSamePosition())if(t&&t.index===this.lastIndex);else{const n=this.getMatcher(0);n.lastIndex=this.lastIndex+1,t=n.exec(e)}return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&this.considerAll()),t}}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=r(e.classNameAliases||{}),function t(i,s){const o=i;if(i.isCompiled)return o;[D,B,W,z].forEach(e=>e(i,s)),e.compilerExtensions.forEach(e=>e(i,s)),i.__beforeBegin=null,[I,L,$].forEach(e=>e(i,s)),i.isCompiled=!0;let l=null;return"object"==typeof i.keywords&&i.keywords.$pattern&&(i.keywords=Object.assign({},i.keywords),l=i.keywords.$pattern,delete i.keywords.$pattern),l=l||/\w+/,i.keywords&&(i.keywords=U(i.keywords,e.case_insensitive)),o.keywordPatternRe=n(l,!0),s&&(i.begin||(i.begin=/\B|\b/),o.beginRe=n(o.begin),i.end||i.endsWithParent||(i.end=/\B|\b/),i.end&&(o.endRe=n(o.end)),o.terminatorEnd=d(o.end)||"",i.endsWithParent&&s.terminatorEnd&&(o.terminatorEnd+=(i.end?"|":"")+s.terminatorEnd)),i.illegal&&(o.illegalRe=n(i.illegal)),i.contains||(i.contains=[]),i.contains=[].concat(...i.contains.map(e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(n=>r(e,{variants:null},n))),e.cachedVariants?e.cachedVariants:X(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e))("self"===e?i:e))),i.contains.forEach(e=>{t(e,o)}),i.starts&&t(i.starts,s),o.matcher=(e=>{const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminatorEnd&&n.addRule(e.terminatorEnd,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n})(o),o}(e)}function X(e){return!!e&&(e.endsWithParent||X(e.starts))}class V extends Error{constructor(e,n){super(e),this.name="HTMLInjectionError",this.html=n}}const J=i,Y=r,ee=Symbol("nomatch");var ne=(e=>{const n=Object.create(null),i=Object.create(null),r=[];let s=!0;const o="Could not find the language '{}', did you forget to load/include a language module?",l={disableAutodetect:!0,name:"Plain text",contains:[]};let d={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:c};function _(e){return d.noHighlightRe.test(e)}function h(e,n,t){let a="",i="";"object"==typeof n?(a=e,t=n.ignoreIllegals,i=n.language):(q("10.7.0","highlight(lang, code, ...args) has been deprecated."),q("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),i=e,a=n),void 0===t&&(t=!0);const r={code:a,language:i};x("before:highlight",r);const s=r.result?r.result:f(r.language,r.code,t);return s.code=r.code,x("after:highlight",s),s}function f(e,t,i,r){const l=Object.create(null);function c(){if(!O.keywords)return void M.addText(S);let e=0;O.keywordPatternRe.lastIndex=0;let n=O.keywordPatternRe.exec(S),t="";for(;n;){t+=S.substring(e,n.index);const i=w.case_insensitive?n[0].toLowerCase():n[0],r=(a=i,O.keywords[a]);if(r){const[e,a]=r;if(M.addText(t),t="",l[i]=(l[i]||0)+1,l[i]<=7&&(A+=a),e.startsWith("_"))t+=n[0];else{const t=w.classNameAliases[e]||e;M.addKeyword(n[0],t)}}else t+=n[0];e=O.keywordPatternRe.lastIndex,n=O.keywordPatternRe.exec(S)}var a;t+=S.substr(e),M.addText(t)}function g(){null!=O.subLanguage?(()=>{if(""===S)return;let e=null;if("string"==typeof O.subLanguage){if(!n[O.subLanguage])return void M.addText(S);e=f(O.subLanguage,S,!0,x[O.subLanguage]),x[O.subLanguage]=e._top}else e=E(S,O.subLanguage.length?O.subLanguage:null);O.relevance>0&&(A+=e.relevance),M.addSublanguage(e._emitter,e.language)})():c(),S=""}function u(e,n){let t=1;const a=n.length-1;for(;t<=a;){if(!e._emit[t]){t++;continue}const a=w.classNameAliases[e[t]]||e[t],i=n[t];a?M.addKeyword(i,a):(S=i,c(),S=""),t++}}function b(e,n){return e.scope&&"string"==typeof e.scope&&M.openNode(w.classNameAliases[e.scope]||e.scope),e.beginScope&&(e.beginScope._wrap?(M.addKeyword(S,w.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),S=""):e.beginScope._multi&&(u(e.beginScope,n),S="")),O=Object.create(e,{parent:{value:O}}),O}function m(e,n,t){let i=((e,n)=>{const t=e&&e.exec(n);return t&&0===t.index})(e.endRe,t);if(i){if(e["on:end"]){const t=new a(e);e["on:end"](n,t),t.isMatchIgnored&&(i=!1)}if(i){for(;e.endsParent&&e.parent;)e=e.parent;return e}}if(e.endsWithParent)return m(e.parent,n,t)}function p(e){return 0===O.matcher.regexIndex?(S+=e[0],1):(R=!0,0)}function _(e){const n=e[0],a=t.substr(e.index),i=m(O,e,a);if(!i)return ee;const r=O;O.endScope&&O.endScope._wrap?(g(),M.addKeyword(n,O.endScope._wrap)):O.endScope&&O.endScope._multi?(g(),u(O.endScope,e)):r.skip?S+=n:(r.returnEnd||r.excludeEnd||(S+=n),g(),r.excludeEnd&&(S=n));do{O.scope&&M.closeNode(),O.skip||O.subLanguage||(A+=O.relevance),O=O.parent}while(O!==i.parent);return i.starts&&b(i.starts,e),r.returnEnd?0:n.length}let h={};function y(n,r){const o=r&&r[0];if(S+=n,null==o)return g(),0;if("begin"===h.type&&"end"===r.type&&h.index===r.index&&""===o){if(S+=t.slice(r.index,r.index+1),!s){const n=Error(`0 width match regex (${e})`);throw n.languageName=e,n.badRule=h.rule,n}return 1}if(h=r,"begin"===r.type)return(e=>{const n=e[0],t=e.rule,i=new a(t),r=[t.__beforeBegin,t["on:begin"]];for(const t of r)if(t&&(t(e,i),i.isMatchIgnored))return p(n);return t.skip?S+=n:(t.excludeBegin&&(S+=n),g(),t.returnBegin||t.excludeBegin||(S=n)),b(t,e),t.returnBegin?0:n.length})(r);if("illegal"===r.type&&!i){const e=Error('Illegal lexeme "'+o+'" for mode "'+(O.scope||"")+'"');throw e.mode=O,e}if("end"===r.type){const e=_(r);if(e!==ee)return e}if("illegal"===r.type&&""===o)return 1;if(T>1e5&&T>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return S+=o,o.length}const w=v(e);if(!w)throw K(o.replace("{}",e)),Error('Unknown language: "'+e+'"');const N=Q(w);let k="",O=r||N;const x={},M=new d.__emitter(d);(()=>{const e=[];for(let n=O;n!==w;n=n.parent)n.scope&&e.unshift(n.scope);e.forEach(e=>M.openNode(e))})();let S="",A=0,C=0,T=0,R=!1;try{for(O.matcher.considerAll();;){T++,R?R=!1:O.matcher.considerAll(),O.matcher.lastIndex=C;const e=O.matcher.exec(t);if(!e)break;const n=y(t.substring(C,e.index),e);C=e.index+n}return y(t.substr(C)),M.closeAllNodes(),M.finalize(),k=M.toHTML(),{language:e,value:k,relevance:A,illegal:!1,_emitter:M,_top:O}}catch(n){if(n.message&&n.message.includes("Illegal"))return{language:e,value:J(t),illegal:!0,relevance:0,_illegalBy:{message:n.message,index:C,context:t.slice(C-100,C+100),mode:n.mode,resultSoFar:k},_emitter:M};if(s)return{language:e,value:J(t),illegal:!1,relevance:0,errorRaised:n,_emitter:M,_top:O};throw n}}function E(e,t){t=t||d.languages||Object.keys(n);const a=(e=>{const n={value:J(e),illegal:!1,relevance:0,_top:l,_emitter:new d.__emitter(d)};return n._emitter.addText(e),n})(e),i=t.filter(v).filter(O).map(n=>f(n,e,!1));i.unshift(a);const r=i.sort((e,n)=>{if(e.relevance!==n.relevance)return n.relevance-e.relevance;if(e.language&&n.language){if(v(e.language).supersetOf===n.language)return 1;if(v(n.language).supersetOf===e.language)return-1}return 0}),[s,o]=r,c=s;return c.secondBest=o,c}function y(e){let n=null;const t=(e=>{let n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=d.languageDetectRe.exec(n);if(t){const n=v(t[1]);return n||(H(o.replace("{}",t[1])),H("Falling back to no-highlight mode for this block.",e)),n?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>_(e)||v(e))})(e);if(_(t))return;if(x("before:highlightElement",{el:e,language:t}),e.children.length>0&&(d.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(e)),d.throwUnescapedHTML))throw new V("One of your code blocks includes unescaped HTML.",e.innerHTML);n=e;const a=n.textContent,r=t?h(a,{language:t,ignoreIllegals:!0}):E(a);e.innerHTML=r.value,((e,n,t)=>{const a=n&&i[n]||t;e.classList.add("hljs"),e.classList.add("language-"+a)})(e,t,r.language),e.result={language:r.language,re:r.relevance,relevance:r.relevance},r.secondBest&&(e.secondBest={language:r.secondBest.language,relevance:r.secondBest.relevance}),x("after:highlightElement",{el:e,result:r,text:a})}let w=!1;function N(){"loading"!==document.readyState?document.querySelectorAll(d.cssSelector).forEach(y):w=!0}function v(e){return e=(e||"").toLowerCase(),n[e]||n[i[e]]}function k(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{i[e.toLowerCase()]=n})}function O(e){const n=v(e);return n&&!n.disableAutodetect}function x(e,n){const t=e;r.forEach(e=>{e[t]&&e[t](n)})}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",()=>{w&&N()},!1),Object.assign(e,{highlight:h,highlightAuto:E,highlightAll:N,highlightElement:y,highlightBlock:e=>(q("10.7.0","highlightBlock will be removed entirely in v12.0"),q("10.7.0","Please use highlightElement now."),y(e)),configure:e=>{d=Y(d,e)},initHighlighting:()=>{N(),q("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")},initHighlightingOnLoad:()=>{N(),q("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")},registerLanguage:(t,a)=>{let i=null;try{i=a(e)}catch(e){if(K("Language definition for '{}' could not be registered.".replace("{}",t)),!s)throw e;K(e),i=l}i.name||(i.name=t),n[t]=i,i.rawDefinition=a.bind(null,e),i.aliases&&k(i.aliases,{languageName:t})},unregisterLanguage:e=>{delete n[e];for(const n of Object.keys(i))i[n]===e&&delete i[n]},listLanguages:()=>Object.keys(n),getLanguage:v,registerAliases:k,autoDetection:O,inherit:Y,addPlugin:e=>{(e=>{e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=n=>{e["before:highlightBlock"](Object.assign({block:n.el},n))}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=n=>{e["after:highlightBlock"](Object.assign({block:n.el},n))})})(e),r.push(e)}}),e.debugMode=()=>{s=!1},e.safeMode=()=>{s=!0},e.versionString="11.5.0",e.regex={concat:m,lookahead:g,either:p,optional:b,anyNumberOfTimes:u};for(const e in T)"object"==typeof T[e]&&t(T[e]);return Object.assign(e,T),e})({});const te=e=>({IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z][A-Za-z0-9_-]*/}}),ae=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],ie=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],re=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],se=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],oe=["align-content","align-items","align-self","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","isolation","justify-content","left","letter-spacing","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","resize","rest","rest-after","rest-before","right","row-gap","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","speak","speak-as","src","tab-size","table-layout","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","z-index"].reverse(),le=re.concat(se);var ce="\\.([0-9](_*[0-9])*)",de="[0-9a-fA-F](_*[0-9a-fA-F])*",ge={className:"number",variants:[{begin:`(\\b([0-9](_*[0-9])*)((${ce})|\\.)?|(${ce}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:`\\b([0-9](_*[0-9])*)((${ce})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${ce})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{begin:`\\b0[xX]((${de})\\.?|(${de})?\\.(${de}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${de})[lL]?\\b`},{begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],relevance:0};function ue(e,n,t){return-1===t?"":e.replace(n,a=>ue(e,n,t-1))}const be="[A-Za-z$_][0-9A-Za-z$_]*",me=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],pe=["true","false","null","undefined","NaN","Infinity"],_e=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],he=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],fe=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],Ee=["arguments","this","super","console","window","document","localStorage","module","global"],ye=[].concat(fe,_e,he);function we(e){const n=e.regex,t=be,a={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{const t=e[0].length+e.index,a=e.input[t];if("<"===a||","===a)return void n.ignoreMatch();let i;">"===a&&(((e,{after:n})=>{const t="",O={match:[/const|var|let/,/\s+/,t,/\s*/,/=\s*/,/(async\s*)?/,n.lookahead(k)],keywords:"async",className:{1:"keyword",3:"title.function"},contains:[_]};return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:i,exports:{PARAMS_CONTAINS:p,CLASS_REFERENCE:f},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node",relevance:5}),{label:"use_strict",className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,c,d,g,u,o,f,{className:"attr",begin:t+n.lookahead(":"),relevance:0},O,{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",relevance:0,contains:[u,e.REGEXP_MODE,{className:"function",begin:k,returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:a.begin,"on:begin":a.isTrulyOpeningTag,end:a.end}],subLanguage:"xml",contains:[{begin:a.begin,end:a.end,skip:!0,contains:["self"]}]}]},E,{beginKeywords:"while if switch catch for"},{begin:"\\b(?!function)"+e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,label:"func.def",contains:[_,e.inherit(e.TITLE_MODE,{begin:t,className:"title.function"})]},{match:/\.\.\./,relevance:0},N,{match:"\\$"+t,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},contains:[_]},y,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},h,v,{match:/\$[(.]/}]}}const Ne=e=>m(/\b/,e,/\w$/.test(e)?/\b/:/\B/),ve=["Protocol","Type"].map(Ne),ke=["init","self"].map(Ne),Oe=["Any","Self"],xe=["actor","associatedtype","async","await",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","isolated","nonisolated","lazy","let","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","switch","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],Me=["false","nil","true"],Se=["assignment","associativity","higherThan","left","lowerThan","none","right"],Ae=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],Ce=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],Te=p(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),Re=p(Te,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),De=m(Te,Re,"*"),Ie=p(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/),Le=p(Ie,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),Be=m(Ie,Le,"*"),$e=m(/[A-Z]/,Le,"*"),ze=["autoclosure",m(/convention\(/,p("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",m(/objc\(/,Be,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","testable","UIApplicationMain","unknown","usableFromInline"],Fe=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"];var Ue=Object.freeze({__proto__:null,grmr_bash:e=>{const n=e.regex,t={},a={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{className:"variable",variants:[{begin:n.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]});const i={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},r={begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},s={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,t,i]};i.contains.push(s);const o={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t]},l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/,keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"],literal:["true","false"],built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"]},contains:[l,e.SHEBANG(),c,o,e.HASH_COMMENT_MODE,r,{match:/(\/[a-z._-]+)+/},s,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},t]}},grmr_c:e=>{const n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="[a-zA-Z_]\\w*::",i="(decltype\\(auto\\)|"+n.optional(a)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{match:/\batomic_[a-z]{3,6}\b/}]},s={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(s,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={className:"title",begin:n.optional(a)+e.IDENT_RE,relevance:0},d=n.optional(a)+e.IDENT_RE+"\\s*\\(",g={keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","struct","switch","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"],type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","const","static","complex","bool","imaginary"],literal:"true false NULL",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr"},u=[l,r,t,e.C_BLOCK_COMMENT_MODE,o,s],b={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:g,contains:u.concat([{begin:/\(/,end:/\)/,keywords:g,contains:u.concat(["self"]),relevance:0}]),relevance:0},m={begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)",keywords:g,relevance:0},{begin:d,returnBegin:!0,contains:[e.inherit(c,{className:"title.function"})],relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,s,o,r,{begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,s,o,r]}]},r,t,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C",aliases:["h"],keywords:g,disableAutodetect:!0,illegal:"=]/,contains:[{beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:l,strings:s,keywords:g}}},grmr_cpp:e=>{const n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="[a-zA-Z_]\\w*::",i="(?!struct)(decltype\\(auto\\)|"+n.optional(a)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={className:"type",begin:"\\b[a-z\\d_]*_t\\b"},s={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(s,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={className:"title",begin:n.optional(a)+e.IDENT_RE,relevance:0},d=n.optional(a)+e.IDENT_RE+"\\s*\\(",g={type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","switch","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"],_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]},u={className:"function.dispatch",relevance:0,keywords:{_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]},begin:n.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!switch)/,/(?!while)/,e.IDENT_RE,n.lookahead(/(<[^<>]+>|)\s*\(/))},b=[u,l,r,t,e.C_BLOCK_COMMENT_MODE,o,s],m={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:g,contains:b.concat([{begin:/\(/,end:/\)/,keywords:g,contains:b.concat(["self"]),relevance:0}]),relevance:0},p={className:"function",begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)",keywords:g,relevance:0},{begin:d,returnBegin:!0,contains:[c],relevance:0},{begin:/::/,relevance:0},{begin:/:/,endsWithParent:!0,contains:[s,o]},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,s,o,r,{begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,s,o,r]}]},r,t,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++",aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:g,illegal:"",keywords:g,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:g},{match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],className:{1:"keyword",3:"title.class"}}])}},grmr_csharp:e=>{const n={keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","switch","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]),built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"],literal:["default","false","null","true"]},t=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},i={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},r=e.inherit(i,{illegal:/\n/}),s={className:"subst",begin:/\{/,end:/\}/,keywords:n},o=e.inherit(s,{illegal:/\n/}),l={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},e.BACKSLASH_ESCAPE,o]},c={className:"string",begin:/\$@"/,end:'"',contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},s]},d=e.inherit(c,{illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},o]});s.contains=[c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],o.contains=[d,l,r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];const g={variants:[c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},u={begin:"<",end:">",contains:[{beginKeywords:"in out"},t]},b=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",m={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{keyword:"if else elif endif define undef warning error line region endregion pragma checksum"}},g,a,{beginKeywords:"class interface",relevance:0,end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},t,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+b+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial",relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,contains:[e.TITLE_MODE,u],relevance:0},{match:/\(\)/},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[g,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},m]}},grmr_css:e=>{const n=e.regex,t=te(e),a=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"},classNameAliases:{keyframePosition:"selector-tag"},contains:[t.BLOCK_COMMENT,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/},t.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},t.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{begin:":("+re.join("|")+")"},{begin:":(:)?("+se.join("|")+")"}]},t.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b"},{begin:/:/,end:/[;}{]/,contains:[t.BLOCK_COMMENT,t.HEXCOLOR,t.IMPORTANT,t.CSS_NUMBER_MODE,...a,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri"},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},t.FUNCTION_DISPATCH]},{begin:n.lookahead(/@/),end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute"},...a,t.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"\\b("+ae.join("|")+")\\b"}]}},grmr_diff:e=>{const n=e.regex;return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,match:n.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)},{className:"comment",variants:[{begin:n.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}},grmr_go:e=>{const n={keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","switch","type","var"],type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"],literal:["true","false","iota","nil"],built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"]};return{name:"Go",aliases:["golang"],keywords:n,illegal:"{const n=e.regex,t={className:"number",relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:e.NUMBER_RE}]},a=e.COMMENT();a.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const i={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},s={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},o={begin:/\[/,end:/\]/,contains:[a,r,i,s,t,"self"],relevance:0},l=n.either(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[a,{className:"section",begin:/\[+/,end:/\]+/},{begin:n.concat(l,"(\\s*\\.\\s*",l,")*",n.lookahead(/\s*=\s*[^#\s]/)),className:"attr",starts:{end:/$/,contains:[a,o,r,i,s,t]}}]}},grmr_java:e=>{const n=e.regex,t="[ร€-สธa-zA-Z_$][ร€-สธa-zA-Z_$0-9]*",a=t+ue("(?:<"+t+"~~~(?:\\s*,\\s*"+t+"~~~)*>)?",/~~~/g,2),i={keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","switch","continue","throws","protected","public","private","module","requires","exports","do","sealed"],literal:["false","true","null"],type:["char","boolean","long","float","int","byte","short","double"],built_in:["super","this"]},r={className:"meta",begin:"@"+t,contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},s={className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0};return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{begin:/import java\.[a-z]+\./,keywords:"import",relevance:2},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{begin:/"""/,end:/"""/,className:"string",contains:[e.BACKSLASH_ESCAPE]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,t],className:{1:"keyword",3:"title.class"}},{match:/non-sealed/,scope:"keyword"},{begin:[n.concat(/(?!else)/,t),/\s+/,t,/\s+/,/=/],className:{1:"type",3:"variable",5:"operator"}},{begin:[/record/,/\s+/,t],className:{1:"keyword",3:"title.class"},contains:[s,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"new throw return else",relevance:0},{begin:["(?:"+a+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,ge,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},ge,r]}},grmr_javascript:we,grmr_json:e=>({name:"JSON",contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{beginKeywords:"true false null"},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}),grmr_kotlin:e=>{const n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},t={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},a={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},i={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[i,a]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,i,a]}]};a.contains.push(r);const s={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},o={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(r,{className:"string"})]}]},l=ge,c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),d={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},g=d;return g.variants[1].contains=[d],d.variants[1].contains=[g],{name:"Kotlin",aliases:["kt","kts"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},t,s,o,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[d,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,s,o,r,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},s,o]},r,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},l]}},grmr_less:e=>{const n=te(e),t=le,a="([\\w-]+|@\\{[\\w-]+\\})",i=[],r=[],s=e=>({className:"string",begin:"~?"+e+".*?"+e}),o=(e,n,t)=>({className:e,begin:n,relevance:t}),l={$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},c={begin:"\\(",end:"\\)",contains:r,keywords:l,relevance:0};r.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s("'"),s('"'),n.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},n.HEXCOLOR,c,o("variable","@@?[\\w-]+",10),o("variable","@\\{[\\w-]+\\}"),o("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},n.IMPORTANT);const d=r.concat({begin:/\{/,end:/\}/,contains:i}),g={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(r)},u={begin:a+"\\s*:",returnBegin:!0,end:/[;}]/,relevance:0,contains:[{begin:/-(webkit|moz|ms|o)-/},n.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b",end:/(?=:)/,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:r}}]},b={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",keywords:l,returnEnd:!0,contains:r,relevance:0}},m={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:d}},p={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:a,end:/\{/}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,o("keyword","all\\b"),o("variable","@\\{[\\w-]+\\}"),{begin:"\\b("+ae.join("|")+")\\b",className:"selector-tag"},n.CSS_NUMBER_MODE,o("selector-tag",a,0),o("selector-id","#"+a),o("selector-class","\\."+a,0),o("selector-tag","&",0),n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",begin:":("+re.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+se.join("|")+")"},{begin:/\(/,end:/\)/,relevance:0,contains:d},{begin:"!important"},n.FUNCTION_DISPATCH]},_={begin:`[\\w-]+:(:)?(${t.join("|")})`,returnBegin:!0,contains:[p]};return i.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,m,_,u,p),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:i}},grmr_lua:e=>{const n="\\[=*\\[",t="\\]=*\\]",a={begin:n,end:t,contains:["self"]},i=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",t,{contains:[a],relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:i.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:i}].concat(i)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:n,end:t,contains:[a],relevance:5}])}},grmr_makefile:e=>{const n={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{const n=e.regex,t=n.concat(/[A-Z_]/,n.optional(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),a={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},i={begin:/\s/,contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},r=e.inherit(i,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:"string"}),o=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),l={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[i,o,s,r,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[i,r,o,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},a,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/,relevance:10,contains:[o]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[l],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[l],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:n.concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:t,relevance:0,starts:l}]},{className:"tag",begin:n.concat(/<\//,n.lookahead(n.concat(t,/>/))),contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}},grmr_markdown:e=>{const n={begin:/<\/?[A-Za-z_]/,end:">",subLanguage:"xml",relevance:0},t={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,relevance:2},{begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/),relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}]},a={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},i={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]},r=e.inherit(a,{contains:[]}),s=e.inherit(i,{contains:[]});a.contains.push(s),i.contains.push(r);let o=[n,t];return[a,i,r,s].forEach(e=>{e.contains=e.contains.concat(o)}),o=o.concat(a,i),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:o},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:o}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},a,i,{className:"quote",begin:"^>\\s+",contains:o,end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},t,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}},grmr_objectivec:e=>{const n=/[a-zA-Z@][a-zA-Z0-9_]*/,t={$pattern:n,keyword:["@interface","@class","@protocol","@implementation"]};return{name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"],keywords:{"variable.language":["this","super"],$pattern:n,keyword:["while","export","sizeof","typedef","const","struct","for","union","volatile","static","mutable","if","do","return","goto","enum","else","break","extern","asm","case","default","register","explicit","typename","switch","continue","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"],literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"],built_in:["dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"],type:["int","float","char","unsigned","signed","short","long","double","wchar_t","unichar","void","bool","BOOL","id|0","_Bool"]},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+t.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:t,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}},grmr_perl:e=>{const n=e.regex,t=/[dualxmsipngr]{0,12}/,a={$pattern:/[\w.]+/,keyword:"abs accept alarm and atan2 bind binmode bless break caller chdir chmod chomp chop chown chr chroot close closedir connect continue cos crypt dbmclose dbmopen defined delete die do dump each else elsif endgrent endhostent endnetent endprotoent endpwent endservent eof eval exec exists exit exp fcntl fileno flock for foreach fork format formline getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep gt hex if index int ioctl join keys kill last lc lcfirst length link listen local localtime log lstat lt ma map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct open opendir or ord our pack package pipe pop pos print printf prototype push q|0 qq quotemeta qw qx rand read readdir readline readlink readpipe recv redo ref rename require reset return reverse rewinddir rindex rmdir say scalar seek seekdir select semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat state study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unless unlink unpack unshift untie until use utime values vec wait waitpid wantarray warn when while write x|0 xor y|0"},i={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:a},r={begin:/->\{/,end:/\}/},s={variants:[{begin:/\$\d/},{begin:n.concat(/[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])")},{begin:/[$%@][^\s\w{]/,relevance:0}]},o=[e.BACKSLASH_ESCAPE,i,s],l=[/!/,/\//,/\|/,/\?/,/'/,/"/,/#/],c=(e,a,i="\\1")=>{const r="\\1"===i?i:n.concat(i,a);return n.concat(n.concat("(?:",e,")"),a,/(?:\\.|[^\\\/])*?/,r,/(?:\\.|[^\\\/])*?/,i,t)},d=(e,a,i)=>n.concat(n.concat("(?:",e,")"),a,/(?:\\.|[^\\\/])*?/,i,t),g=[s,e.HASH_COMMENT_MODE,e.COMMENT(/^=\w/,/=cut/,{endsWithParent:!0}),r,{className:"string",contains:o,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,relevance:0},{begin:"-?\\w+\\s*=>",relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",variants:[{begin:c("s|tr|y",n.either(...l,{capture:!0}))},{begin:c("s|tr|y","\\(","\\)")},{begin:c("s|tr|y","\\[","\\]")},{begin:c("s|tr|y","\\{","\\}")}],relevance:2},{className:"regexp",variants:[{begin:/(m|qr)\/\//,relevance:0},{begin:d("(?:m|qr)?",/\//,/\//)},{begin:d("m|qr",n.either(...l,{capture:!0}),/\1/)},{begin:d("m|qr",/\(/,/\)/)},{begin:d("m|qr",/\[/,/\]/)},{begin:d("m|qr",/\{/,/\}/)}]}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return i.contains=g,r.contains=g,{name:"Perl",aliases:["pl","pm"],keywords:a,contains:g}},grmr_php:e=>{const n=e.regex,t=/(?![A-Za-z0-9])(?![$])/,a=n.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,t),i=n.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,t),r={scope:"variable",match:"\\$+"+a},s={scope:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]},o=e.inherit(e.APOS_STRING_MODE,{illegal:null}),l="[ \t\n]",c={scope:"string",variants:[e.inherit(e.QUOTE_STRING_MODE,{illegal:null,contains:e.QUOTE_STRING_MODE.contains.concat(s)}),o,e.END_SAME_AS_BEGIN({begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/,contains:e.QUOTE_STRING_MODE.contains.concat(s)})]},d={scope:"number",variants:[{begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"}],relevance:0},g=["false","null","true"],u=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endswitch","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","switch","throw","trait","try","unset","use","var","void","while","xor","yield"],b=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],m={keyword:u,literal:(e=>{const n=[];return e.forEach(e=>{n.push(e),e.toLowerCase()===e?n.push(e.toUpperCase()):n.push(e.toLowerCase())}),n})(g),built_in:b},p=e=>e.map(e=>e.replace(/\|\d+$/,"")),_={variants:[{match:[/new/,n.concat(l,"+"),n.concat("(?!",p(b).join("\\b|"),"\\b)"),i],scope:{1:"keyword",4:"title.class"}}]},h=n.concat(a,"\\b(?!\\()"),f={variants:[{match:[n.concat(/::/,n.lookahead(/(?!class\b)/)),h],scope:{2:"variable.constant"}},{match:[/::/,/class/],scope:{2:"variable.language"}},{match:[i,n.concat(/::/,n.lookahead(/(?!class\b)/)),h],scope:{1:"title.class",3:"variable.constant"}},{match:[i,n.concat("::",n.lookahead(/(?!class\b)/))],scope:{1:"title.class"}},{match:[i,/::/,/class/],scope:{1:"title.class",3:"variable.language"}}]},E={scope:"attr",match:n.concat(a,n.lookahead(":"),n.lookahead(/(?!::)/))},y={relevance:0,begin:/\(/,end:/\)/,keywords:m,contains:[E,r,f,e.C_BLOCK_COMMENT_MODE,c,d,_]},w={relevance:0,match:[/\b/,n.concat("(?!fn\\b|function\\b|",p(u).join("\\b|"),"|",p(b).join("\\b|"),"\\b)"),a,n.concat(l,"*"),n.lookahead(/(?=\()/)],scope:{3:"title.function.invoke"},contains:[y]};y.contains.push(w);const N=[E,f,e.C_BLOCK_COMMENT_MODE,c,d,_];return{case_insensitive:!1,keywords:m,contains:[{begin:n.concat(/#\[\s*/,i),beginScope:"meta",end:/]/,endScope:"meta",keywords:{literal:g,keyword:["new","array"]},contains:[{begin:/\[/,end:/]/,keywords:{literal:g,keyword:["new","array"]},contains:["self",...N]},...N,{scope:"meta",match:i}]},e.HASH_COMMENT_MODE,e.COMMENT("//","$"),e.COMMENT("/\\*","\\*/",{contains:[{scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,keywords:"__halt_compiler",starts:{scope:"comment",end:e.MATCH_NOTHING_RE,contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},{scope:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?=/},{begin:/<\?/,relevance:.1},{begin:/\?>/}]},{scope:"variable.language",match:/\$this\b/},r,w,f,{match:[/const/,/\s/,a],scope:{1:"keyword",3:"variable.constant"}},_,{scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"},e.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:m,contains:["self",r,f,e.C_BLOCK_COMMENT_MODE,c,d]}]},{scope:"class",variants:[{beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait",illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/,contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{scope:"title.class"})]},{beginKeywords:"use",relevance:0,end:";",contains:[{match:/\b(as|const|function)\b/,scope:"keyword"},e.UNDERSCORE_TITLE_MODE]},c,d]}},grmr_php_template:e=>({name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},e.inherit(e.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}),grmr_plaintext:e=>({name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}),grmr_python:e=>{const n=e.regex,t=/[\p{XID_Start}_]\p{XID_Continue}*/u,a=["and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],i={$pattern:/[A-Za-z]\w+|__\w+__/,keyword:a,built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"],literal:["__debug__","Ellipsis","False","None","NotImplemented","True"],type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"]},r={className:"meta",begin:/^(>>>|\.\.\.) /},s={className:"subst",begin:/\{/,end:/\}/,keywords:i,illegal:/#/},o={begin:/\{\{/,relevance:0},l={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,r],relevance:10},{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,r],relevance:10},{begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,r,o,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,r,o,s]},{begin:/([uU]|[rR])'/,end:/'/,relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,o,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,o,s]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},c="[0-9](_?[0-9])*",d=`(\\b(${c}))?\\.(${c})|\\b(${c})\\.`,g="\\b|"+a.join("|"),u={className:"number",relevance:0,variants:[{begin:`(\\b(${c})|(${d}))[eE][+-]?(${c})[jJ]?(?=${g})`},{begin:`(${d})[jJ]?`},{begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${g})`},{begin:`\\b0[bB](_?[01])+[lL]?(?=${g})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${g})`},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${g})`},{begin:`\\b(${c})[jJ](?=${g})`}]},b={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:i,contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,contains:["self",r,u,l,e.HASH_COMMENT_MODE]}]};return s.contains=[l,u,r],{name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:i,illegal:/(<\/|->|\?)|=>/,contains:[r,u,{begin:/\bself\b/},{beginKeywords:"if",relevance:0},l,b,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[m]},{variants:[{match:[/\bclass/,/\s+/,t,/\s*/,/\(\s*/,t,/\s*\)/]},{match:[/\bclass/,/\s+/,t]}],scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[u,m,l]}]}},grmr_python_repl:e=>({aliases:["pycon"],contains:[{className:"meta.prompt",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}),grmr_r:e=>{const n=e.regex,t=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/,a=n.either(/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,/0[xX][0-9a-fA-F]+(?:[pP][+-]?\d+)?[Li]?/,/(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?[Li]?/),i=/[=!<>:]=|\|\||&&|:::?|<-|<<-|->>|->|\|>|[-+*\/?!$&|:<=>@^~]|\*\*/,r=n.either(/[()]/,/[{}]/,/\[\[/,/[[\]]/,/\\/,/,/);return{name:"R",keywords:{$pattern:t,keyword:"function if in break next repeat else for while",literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum switch tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm"},contains:[e.COMMENT(/#'/,/$/,{contains:[{scope:"doctag",match:/@examples/,starts:{end:n.lookahead(n.either(/\n^#'\s*(?=@[a-zA-Z]+)/,/\n^(?!#')/)),endsParent:!0}},{scope:"doctag",begin:"@param",end:/$/,contains:[{scope:"variable",variants:[{match:t},{match:/`(?:\\.|[^`\\])+`/}],endsParent:!0}]},{scope:"doctag",match:/@[a-zA-Z]+/},{scope:"keyword",match:/\\[a-zA-Z]+/}]}),e.HASH_COMMENT_MODE,{scope:"string",contains:[e.BACKSLASH_ESCAPE],variants:[e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\(/,end:/\)(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/,end:/\}(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"',relevance:0},{begin:"'",end:"'",relevance:0}]},{relevance:0,variants:[{scope:{1:"operator",2:"number"},match:[i,a]},{scope:{1:"operator",2:"number"},match:[/%[^%]*%/,a]},{scope:{1:"punctuation",2:"number"},match:[r,a]},{scope:{2:"number"},match:[/[^a-zA-Z0-9._]|^/,a]}]},{scope:{3:"operator"},match:[t,/\s+/,/<-/,/\s+/]},{scope:"operator",relevance:0,variants:[{match:i},{match:/%[^%]*%/}]},{scope:"punctuation",relevance:0,match:r},{begin:"`",end:"`",contains:[{begin:/\\./}]}]}},grmr_ruby:e=>{const n=e.regex,t="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",a=n.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),i=n.concat(a,/(::\w+)*/),r={"variable.constant":["__FILE__","__LINE__"],"variable.language":["self","super"],keyword:["alias","and","attr_accessor","attr_reader","attr_writer","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","include","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield"],built_in:["proc","lambda"],literal:["true","false","nil"]},s={className:"doctag",begin:"@[A-Za-z]+"},o={begin:"#<",end:">"},l=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^=begin","^=end",{contains:[s],relevance:10}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],c={className:"subst",begin:/#\{/,end:/\}/,keywords:r},d={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:n.concat(/<<[-~]?'?/,n.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)),contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},g="[0-9](_?[0-9])*",u={className:"number",relevance:0,variants:[{begin:`\\b([1-9](_?[0-9])*|0)(\\.(${g}))?([eE][+-]?(${g})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},b={variants:[{match:/\(\)/},{className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0,keywords:r}]},m=[d,{variants:[{match:[/class\s+/,i,/\s+<\s+/,i]},{match:[/class\s+/,i]}],scope:{2:"title.class",4:"title.class.inherited"},keywords:r},{relevance:0,match:[i,/\.new[ (]/],scope:{1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},{match:[/def/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[b]},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[d,{begin:t}],relevance:0},u,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|/,end:/\|/,excludeBegin:!0,excludeEnd:!0,relevance:0,keywords:r},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(o,l),relevance:0}].concat(o,l);c.contains=m,b.contains=m;const p=[{begin:/^\s*=>/,starts:{end:"$",contains:m}},{className:"meta.prompt",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])",starts:{end:"$",keywords:r,contains:m}}];return l.unshift(o),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:r,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(p).concat(l).concat(m)}},grmr_rust:e=>{const n=e.regex,t={className:"title.function.invoke",relevance:0,begin:n.concat(/\b/,/(?!let\b)/,e.IDENT_RE,n.lookahead(/\s*\(/))},a="([ui](8|16|32|64|128|size)|f(32|64))?",i=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","panic!","file!","format!","format_args!","include_bin!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"];return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"],keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","unsafe","unsized","use","virtual","where","while","yield"],literal:["true","false","Some","None","Ok","Err"],built_in:i},illegal:""},t]}},grmr_scss:e=>{const n=te(e),t=se,a=re,i="@[a-z-]+",r={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b",relevance:0};return{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n.CSS_NUMBER_MODE,{className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag",begin:"\\b("+ae.join("|")+")\\b",relevance:0},{className:"selector-pseudo",begin:":("+a.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+t.join("|")+")"},r,{begin:/\(/,end:/\)/,contains:[n.CSS_NUMBER_MODE]},n.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:/:/,end:/[;}{]/,contains:[n.BLOCK_COMMENT,r,n.HEXCOLOR,n.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.IMPORTANT]},{begin:"@(page|font-face)",keywords:{$pattern:i,keyword:"@page @font-face"}},{begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},contains:[{begin:i,className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute"},r,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.HEXCOLOR,n.CSS_NUMBER_MODE]},n.FUNCTION_DISPATCH]}},grmr_shell:e=>({name:"Shell Session",aliases:["console","shellsession"],contains:[{className:"meta.prompt",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}),grmr_sql:e=>{const n=e.regex,t=e.COMMENT("--","$"),a=["true","false","unknown"],i=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],r=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],o=r,l=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter(e=>!r.includes(e)),c={begin:n.concat(/\b/,n.either(...o),/\s*\(/),relevance:0,keywords:{built_in:o}};return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:n,when:t}={})=>{const a=t;return n=n||[],e.map(e=>e.match(/\|\d+$/)||n.includes(e)?e:a(e)?e+"|0":e)})(l,{when:e=>e.length<3}),literal:a,type:i,built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"]},contains:[{begin:n.either(...s),relevance:0,keywords:{$pattern:/[\w\.]+/,keyword:l.concat(s),literal:a,type:i}},{className:"type",begin:n.either("double precision","large object","with timezone","without timezone")},c,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{className:"operator",begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}},grmr_swift:e=>{const n={match:/\s+/,relevance:0},t=e.COMMENT("/\\*","\\*/",{contains:["self"]}),a=[e.C_LINE_COMMENT_MODE,t],i={match:[/\./,p(...ve,...ke)],className:{2:"keyword"}},r={match:m(/\./,p(...xe)),relevance:0},s=xe.filter(e=>"string"==typeof e).concat(["_|0"]),o={variants:[{className:"keyword",match:p(...xe.filter(e=>"string"!=typeof e).concat(Oe).map(Ne),...ke)}]},l={$pattern:p(/\b\w+/,/#\w+/),keyword:s.concat(Ae),literal:Me},c=[i,r,o],d=[{match:m(/\./,p(...Ce)),relevance:0},{className:"built_in",match:m(/\b/,p(...Ce),/(?=\()/)}],u={match:/->/,relevance:0},b=[u,{className:"operator",relevance:0,variants:[{match:De},{match:`\\.(\\.|${Re})+`}]}],_="([0-9a-fA-F]_*)+",h={className:"number",relevance:0,variants:[{match:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{match:`\\b0x(${_})(\\.(${_}))?([pP][+-]?(([0-9]_*)+))?\\b`},{match:/\b0o([0-7]_*)+\b/},{match:/\b0b([01]_*)+\b/}]},f=(e="")=>({className:"subst",variants:[{match:m(/\\/,e,/[0\\tnr"']/)},{match:m(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),E=(e="")=>({className:"subst",match:m(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),y=(e="")=>({className:"subst",label:"interpol",begin:m(/\\/,e,/\(/),end:/\)/}),w=(e="")=>({begin:m(e,/"""/),end:m(/"""/,e),contains:[f(e),E(e),y(e)]}),N=(e="")=>({begin:m(e,/"/),end:m(/"/,e),contains:[f(e),y(e)]}),v={className:"string",variants:[w(),w("#"),w("##"),w("###"),N(),N("#"),N("##"),N("###")]},k={match:m(/`/,Be,/`/)},O=[k,{className:"variable",match:/\$\d+/},{className:"variable",match:`\\$${Le}+`}],x=[{match:/(@|#(un)?)available/,className:"keyword",starts:{contains:[{begin:/\(/,end:/\)/,keywords:Fe,contains:[...b,h,v]}]}},{className:"keyword",match:m(/@/,p(...ze))},{className:"meta",match:m(/@/,Be)}],M={match:g(/\b[A-Z]/),relevance:0,contains:[{className:"type",match:m(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,Le,"+")},{className:"type",match:$e,relevance:0},{match:/[?!]+/,relevance:0},{match:/\.\.\./,relevance:0},{match:m(/\s+&\s+/,g($e)),relevance:0}]},S={begin://,keywords:l,contains:[...a,...c,...x,u,M]};M.contains.push(S);const A={begin:/\(/,end:/\)/,relevance:0,keywords:l,contains:["self",{match:m(Be,/\s*:/),keywords:"_|0",relevance:0},...a,...c,...d,...b,h,v,...O,...x,M]},C={begin://,contains:[...a,M]},T={begin:/\(/,end:/\)/,keywords:l,contains:[{begin:p(g(m(Be,/\s*:/)),g(m(Be,/\s+/,Be,/\s*:/))),end:/:/,relevance:0,contains:[{className:"keyword",match:/\b_\b/},{className:"params",match:Be}]},...a,...c,...b,h,v,...x,M,A],endsParent:!0,illegal:/["']/},R={match:[/func/,/\s+/,p(k.match,Be,De)],className:{1:"keyword",3:"title.function"},contains:[C,T,n],illegal:[/\[/,/%/]},D={match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"},contains:[C,T,n],illegal:/\[|%/},I={match:[/operator/,/\s+/,De],className:{1:"keyword",3:"title"}},L={begin:[/precedencegroup/,/\s+/,$e],className:{1:"keyword",3:"title"},contains:[M],keywords:[...Se,...Me],end:/}/};for(const e of v.variants){const n=e.contains.find(e=>"interpol"===e.label);n.keywords=l;const t=[...c,...d,...b,h,v,...O];n.contains=[...t,{begin:/\(/,end:/\)/,contains:["self",...t]}]}return{name:"Swift",keywords:l,contains:[...a,R,D,{beginKeywords:"struct protocol class extension enum actor",end:"\\{",excludeEnd:!0,keywords:l,contains:[e.inherit(e.TITLE_MODE,{className:"title.class",begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...c]},I,L,{beginKeywords:"import",end:/$/,contains:[...a],relevance:0},...c,...d,...b,h,v,...O,...x,M,A]}},grmr_typescript:e=>{const n=we(e),t=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],a={beginKeywords:"namespace",end:/\{/,excludeEnd:!0,contains:[n.exports.CLASS_REFERENCE]},i={beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:{keyword:"interface extends",built_in:t},contains:[n.exports.CLASS_REFERENCE]},r={$pattern:be,keyword:me.concat(["type","namespace","interface","public","private","protected","implements","declare","abstract","readonly","enum","override"]),literal:pe,built_in:ye.concat(t),"variable.language":Ee},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},o=(e,n,t)=>{const a=e.contains.findIndex(e=>e.label===n);if(-1===a)throw Error("can not find mode to replace");e.contains.splice(a,1,t)};return Object.assign(n.keywords,r),n.exports.PARAMS_CONTAINS.push(s),n.contains=n.contains.concat([s,a,i]),o(n,"shebang",e.SHEBANG()),o(n,"use_strict",{className:"meta",relevance:10,begin:/^\s*['"]use strict['"]/}),n.contains.find(e=>"func.def"===e.label).relevance=0,Object.assign(n,{name:"TypeScript",aliases:["ts","tsx"]}),n},grmr_vbnet:e=>{const n=e.regex,t=/\d{1,2}\/\d{1,2}\/\d{4}/,a=/\d{4}-\d{1,2}-\d{1,2}/,i=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,r=/\d{1,2}(:\d{1,2}){1,2}/,s={className:"literal",variants:[{begin:n.concat(/# */,n.either(a,t),/ *#/)},{begin:n.concat(/# */,r,/ *#/)},{begin:n.concat(/# */,i,/ *#/)},{begin:n.concat(/# */,n.either(a,t),/ +/,n.either(i,r),/ *#/)}]},o=e.COMMENT(/'''/,/$/,{contains:[{className:"doctag",begin:/<\/?/,end:/>/}]}),l=e.COMMENT(null,/$/,{variants:[{begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET",aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield",built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort",type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort",literal:"true false nothing"},illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/,end:/"/,illegal:/\n/,contains:[{begin:/""/}]},s,{className:"number",relevance:0,variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/},{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{className:"label",begin:/^\w+:/},o,l,{className:"meta",begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/,end:/$/,keywords:{keyword:"const disable else elseif enable end externalsource if region then"},contains:[l]}]}},grmr_yaml:e=>{const n="true false yes no null",t="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),r={end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},s={begin:/\{/,end:/\}/,contains:[r],illegal:"\\n",relevance:0},o={begin:"\\[",end:"\\]",contains:[r],illegal:"\\n",relevance:0},l=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+t},{className:"type",begin:"!<"+t+">"},{className:"type",begin:"!"+t},{className:"type",begin:"!!"+t},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},s,o,a],c=[...l];return c.pop(),c.push(i),r.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:l}}});const je=ne;for(const e of Object.keys(Ue)){const n=e.replace("grmr_","").replace("_","-");je.registerLanguage(n,Ue[e])}return je}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); +var hljs=function(){"use strict";var e={exports:{}};function n(e){return e instanceof Map?e.clear=e.delete=e.set=()=>{throw Error("map is read-only")}:e instanceof Set&&(e.add=e.clear=e.delete=()=>{throw Error("set is read-only")}),Object.freeze(e),Object.getOwnPropertyNames(e).forEach(t=>{var a=e[t];"object"!=typeof a||Object.isFrozen(a)||n(a)}),e}e.exports=n,e.exports.default=n;var t=e.exports;class a{constructor(e){void 0===e.data&&(e.data={}),this.data=e.data,this.isMatchIgnored=!1}ignoreMatch(){this.isMatchIgnored=!0}}function i(e){return e.replace(/&/g,"&").replace(//g,">").replace(/"/g,""").replace(/'/g,"'")}function r(e,...n){const t=Object.create(null);for(const n in e)t[n]=e[n];return n.forEach(e=>{for(const n in e)t[n]=e[n]}),t}const s=e=>!!e.kind;class o{constructor(e,n){this.buffer="",this.classPrefix=n.classPrefix,e.walk(this)}addText(e){this.buffer+=i(e)}openNode(e){if(!s(e))return;let n=e.kind;n=e.sublanguage?"language-"+n:((e,{prefix:n})=>{if(e.includes(".")){const t=e.split(".");return[`${n}${t.shift()}`,...t.map((e,n)=>`${e}${"_".repeat(n+1)}`)].join(" ")}return`${n}${e}`})(n,{prefix:this.classPrefix}),this.span(n)}closeNode(e){s(e)&&(this.buffer+="")}value(){return this.buffer}span(e){this.buffer+=``}}class l{constructor(){this.rootNode={children:[]},this.stack=[this.rootNode]}get top(){return this.stack[this.stack.length-1]}get root(){return this.rootNode}add(e){this.top.children.push(e)}openNode(e){const n={kind:e,children:[]};this.add(n),this.stack.push(n)}closeNode(){if(this.stack.length>1)return this.stack.pop()}closeAllNodes(){for(;this.closeNode(););}toJSON(){return JSON.stringify(this.rootNode,null,4)}walk(e){return this.constructor._walk(e,this.rootNode)}static _walk(e,n){return"string"==typeof n?e.addText(n):n.children&&(e.openNode(n),n.children.forEach(n=>this._walk(e,n)),e.closeNode(n)),e}static _collapse(e){"string"!=typeof e&&e.children&&(e.children.every(e=>"string"==typeof e)?e.children=[e.children.join("")]:e.children.forEach(e=>{l._collapse(e)}))}}class c extends l{constructor(e){super(),this.options=e}addKeyword(e,n){""!==e&&(this.openNode(n),this.addText(e),this.closeNode())}addText(e){""!==e&&this.add(e)}addSublanguage(e,n){const t=e.root;t.kind=n,t.sublanguage=!0,this.add(t)}toHTML(){return new o(this,this.options).value()}finalize(){return!0}}function d(e){return e?"string"==typeof e?e:e.source:null}function g(e){return m("(?=",e,")")}function u(e){return m("(?:",e,")*")}function b(e){return m("(?:",e,")?")}function m(...e){return e.map(e=>d(e)).join("")}function p(...e){const n=(e=>{const n=e[e.length-1];return"object"==typeof n&&n.constructor===Object?(e.splice(e.length-1,1),n):{}})(e);return"("+(n.capture?"":"?:")+e.map(e=>d(e)).join("|")+")"}function _(e){return RegExp(e.toString()+"|").exec("").length-1}const h=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./;function f(e,{joinWith:n}){let t=0;return e.map(e=>{t+=1;const n=t;let a=d(e),i="";for(;a.length>0;){const e=h.exec(a);if(!e){i+=a;break}i+=a.substring(0,e.index),a=a.substring(e.index+e[0].length),"\\"===e[0][0]&&e[1]?i+="\\"+(Number(e[1])+n):(i+=e[0],"("===e[0]&&t++)}return i}).map(e=>`(${e})`).join(n)}const E="[a-zA-Z]\\w*",y="[a-zA-Z_]\\w*",w="\\b\\d+(\\.\\d+)?",N="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",v="\\b(0b[01]+)",k={begin:"\\\\[\\s\\S]",relevance:0},O={scope:"string",begin:"'",end:"'",illegal:"\\n",contains:[k]},x={scope:"string",begin:'"',end:'"',illegal:"\\n",contains:[k]},M=(e,n,t={})=>{const a=r({scope:"comment",begin:e,end:n,contains:[]},t);a.contains.push({scope:"doctag",begin:"[ ]*(?=(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):)",end:/(TODO|FIXME|NOTE|BUG|OPTIMIZE|HACK|XXX):/,excludeBegin:!0,relevance:0});const i=p("I","a","is","so","us","to","at","if","in","it","on",/[A-Za-z]+['](d|ve|re|ll|t|s|n)/,/[A-Za-z]+[-][a-z]+/,/[A-Za-z][a-z]{2,}/);return a.contains.push({begin:m(/[ ]+/,"(",i,/[.]?[:]?([.][ ]|[ ])/,"){3}")}),a},S=M("//","$"),A=M("/\\*","\\*/"),C=M("#","$");var T=Object.freeze({__proto__:null,MATCH_NOTHING_RE:/\b\B/,IDENT_RE:E,UNDERSCORE_IDENT_RE:y,NUMBER_RE:w,C_NUMBER_RE:N,BINARY_NUMBER_RE:v,RE_STARTERS_RE:"!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",SHEBANG:(e={})=>{const n=/^#![ ]*\//;return e.binary&&(e.begin=m(n,/.*\b/,e.binary,/\b.*/)),r({scope:"meta",begin:n,end:/$/,relevance:0,"on:begin":(e,n)=>{0!==e.index&&n.ignoreMatch()}},e)},BACKSLASH_ESCAPE:k,APOS_STRING_MODE:O,QUOTE_STRING_MODE:x,PHRASAL_WORDS_MODE:{begin:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},COMMENT:M,C_LINE_COMMENT_MODE:S,C_BLOCK_COMMENT_MODE:A,HASH_COMMENT_MODE:C,NUMBER_MODE:{scope:"number",begin:w,relevance:0},C_NUMBER_MODE:{scope:"number",begin:N,relevance:0},BINARY_NUMBER_MODE:{scope:"number",begin:v,relevance:0},REGEXP_MODE:{begin:/(?=\/[^/\n]*\/)/,contains:[{scope:"regexp",begin:/\//,end:/\/[gimuy]*/,illegal:/\n/,contains:[k,{begin:/\[/,end:/\]/,relevance:0,contains:[k]}]}]},TITLE_MODE:{scope:"title",begin:E,relevance:0},UNDERSCORE_TITLE_MODE:{scope:"title",begin:y,relevance:0},METHOD_GUARD:{begin:"\\.\\s*[a-zA-Z_]\\w*",relevance:0},END_SAME_AS_BEGIN:e=>Object.assign(e,{"on:begin":(e,n)=>{n.data._beginMatch=e[1]},"on:end":(e,n)=>{n.data._beginMatch!==e[1]&&n.ignoreMatch()}})});function R(e,n){"."===e.input[e.index-1]&&n.ignoreMatch()}function D(e,n){void 0!==e.className&&(e.scope=e.className,delete e.className)}function I(e,n){n&&e.beginKeywords&&(e.begin="\\b("+e.beginKeywords.split(" ").join("|")+")(?!\\.)(?=\\b|\\s)",e.__beforeBegin=R,e.keywords=e.keywords||e.beginKeywords,delete e.beginKeywords,void 0===e.relevance&&(e.relevance=0))}function L(e,n){Array.isArray(e.illegal)&&(e.illegal=p(...e.illegal))}function B(e,n){if(e.match){if(e.begin||e.end)throw Error("begin & end are not supported with match");e.begin=e.match,delete e.match}}function $(e,n){void 0===e.relevance&&(e.relevance=1)}const z=(e,n)=>{if(!e.beforeMatch)return;if(e.starts)throw Error("beforeMatch cannot be used with starts");const t=Object.assign({},e);Object.keys(e).forEach(n=>{delete e[n]}),e.keywords=t.keywords,e.begin=m(t.beforeMatch,g(t.begin)),e.starts={relevance:0,contains:[Object.assign(t,{endsParent:!0})]},e.relevance=0,delete t.beforeMatch},F=["of","and","for","in","not","or","if","then","parent","list","value"];function U(e,n,t="keyword"){const a=Object.create(null);return"string"==typeof e?i(t,e.split(" ")):Array.isArray(e)?i(t,e):Object.keys(e).forEach(t=>{Object.assign(a,U(e[t],n,t))}),a;function i(e,t){n&&(t=t.map(e=>e.toLowerCase())),t.forEach(n=>{const t=n.split("|");a[t[0]]=[e,j(t[0],t[1])]})}}function j(e,n){return n?Number(n):(e=>F.includes(e.toLowerCase()))(e)?0:1}const P={},K=e=>{console.error(e)},H=(e,...n)=>{console.log("WARN: "+e,...n)},q=(e,n)=>{P[`${e}/${n}`]||(console.log(`Deprecated as of ${e}. ${n}`),P[`${e}/${n}`]=!0)},Z=Error();function G(e,n,{key:t}){let a=0;const i=e[t],r={},s={};for(let e=1;e<=n.length;e++)s[e+a]=i[e],r[e+a]=!0,a+=_(n[e-1]);e[t]=s,e[t]._emit=r,e[t]._multi=!0}function W(e){(e=>{e.scope&&"object"==typeof e.scope&&null!==e.scope&&(e.beginScope=e.scope,delete e.scope)})(e),"string"==typeof e.beginScope&&(e.beginScope={_wrap:e.beginScope}),"string"==typeof e.endScope&&(e.endScope={_wrap:e.endScope}),(e=>{if(Array.isArray(e.begin)){if(e.skip||e.excludeBegin||e.returnBegin)throw K("skip, excludeBegin, returnBegin not compatible with beginScope: {}"),Z;if("object"!=typeof e.beginScope||null===e.beginScope)throw K("beginScope must be object"),Z;G(e,e.begin,{key:"beginScope"}),e.begin=f(e.begin,{joinWith:""})}})(e),(e=>{if(Array.isArray(e.end)){if(e.skip||e.excludeEnd||e.returnEnd)throw K("skip, excludeEnd, returnEnd not compatible with endScope: {}"),Z;if("object"!=typeof e.endScope||null===e.endScope)throw K("endScope must be object"),Z;G(e,e.end,{key:"endScope"}),e.end=f(e.end,{joinWith:""})}})(e)}function Q(e){function n(n,t){return RegExp(d(n),"m"+(e.case_insensitive?"i":"")+(e.unicodeRegex?"u":"")+(t?"g":""))}class t{constructor(){this.matchIndexes={},this.regexes=[],this.matchAt=1,this.position=0}addRule(e,n){n.position=this.position++,this.matchIndexes[this.matchAt]=n,this.regexes.push([n,e]),this.matchAt+=_(e)+1}compile(){0===this.regexes.length&&(this.exec=()=>null);const e=this.regexes.map(e=>e[1]);this.matcherRe=n(f(e,{joinWith:"|"}),!0),this.lastIndex=0}exec(e){this.matcherRe.lastIndex=this.lastIndex;const n=this.matcherRe.exec(e);if(!n)return null;const t=n.findIndex((e,n)=>n>0&&void 0!==e),a=this.matchIndexes[t];return n.splice(0,t),Object.assign(n,a)}}class a{constructor(){this.rules=[],this.multiRegexes=[],this.count=0,this.lastIndex=0,this.regexIndex=0}getMatcher(e){if(this.multiRegexes[e])return this.multiRegexes[e];const n=new t;return this.rules.slice(e).forEach(([e,t])=>n.addRule(e,t)),n.compile(),this.multiRegexes[e]=n,n}resumingScanAtSamePosition(){return 0!==this.regexIndex}considerAll(){this.regexIndex=0}addRule(e,n){this.rules.push([e,n]),"begin"===n.type&&this.count++}exec(e){const n=this.getMatcher(this.regexIndex);n.lastIndex=this.lastIndex;let t=n.exec(e);if(this.resumingScanAtSamePosition())if(t&&t.index===this.lastIndex);else{const n=this.getMatcher(0);n.lastIndex=this.lastIndex+1,t=n.exec(e)}return t&&(this.regexIndex+=t.position+1,this.regexIndex===this.count&&this.considerAll()),t}}if(e.compilerExtensions||(e.compilerExtensions=[]),e.contains&&e.contains.includes("self"))throw Error("ERR: contains `self` is not supported at the top-level of a language. See documentation.");return e.classNameAliases=r(e.classNameAliases||{}),function t(i,s){const o=i;if(i.isCompiled)return o;[D,B,W,z].forEach(e=>e(i,s)),e.compilerExtensions.forEach(e=>e(i,s)),i.__beforeBegin=null,[I,L,$].forEach(e=>e(i,s)),i.isCompiled=!0;let l=null;return"object"==typeof i.keywords&&i.keywords.$pattern&&(i.keywords=Object.assign({},i.keywords),l=i.keywords.$pattern,delete i.keywords.$pattern),l=l||/\w+/,i.keywords&&(i.keywords=U(i.keywords,e.case_insensitive)),o.keywordPatternRe=n(l,!0),s&&(i.begin||(i.begin=/\B|\b/),o.beginRe=n(o.begin),i.end||i.endsWithParent||(i.end=/\B|\b/),i.end&&(o.endRe=n(o.end)),o.terminatorEnd=d(o.end)||"",i.endsWithParent&&s.terminatorEnd&&(o.terminatorEnd+=(i.end?"|":"")+s.terminatorEnd)),i.illegal&&(o.illegalRe=n(i.illegal)),i.contains||(i.contains=[]),i.contains=[].concat(...i.contains.map(e=>(e=>(e.variants&&!e.cachedVariants&&(e.cachedVariants=e.variants.map(n=>r(e,{variants:null},n))),e.cachedVariants?e.cachedVariants:X(e)?r(e,{starts:e.starts?r(e.starts):null}):Object.isFrozen(e)?r(e):e))("self"===e?i:e))),i.contains.forEach(e=>{t(e,o)}),i.starts&&t(i.starts,s),o.matcher=(e=>{const n=new a;return e.contains.forEach(e=>n.addRule(e.begin,{rule:e,type:"begin"})),e.terminatorEnd&&n.addRule(e.terminatorEnd,{type:"end"}),e.illegal&&n.addRule(e.illegal,{type:"illegal"}),n})(o),o}(e)}function X(e){return!!e&&(e.endsWithParent||X(e.starts))}class V extends Error{constructor(e,n){super(e),this.name="HTMLInjectionError",this.html=n}}const J=i,Y=r,ee=Symbol("nomatch");var ne=(e=>{const n=Object.create(null),i=Object.create(null),r=[];let s=!0;const o="Could not find the language '{}', did you forget to load/include a language module?",l={disableAutodetect:!0,name:"Plain text",contains:[]};let d={ignoreUnescapedHTML:!1,throwUnescapedHTML:!1,noHighlightRe:/^(no-?highlight)$/i,languageDetectRe:/\blang(?:uage)?-([\w-]+)\b/i,classPrefix:"hljs-",cssSelector:"pre code",languages:null,__emitter:c};function _(e){return d.noHighlightRe.test(e)}function h(e,n,t){let a="",i="";"object"==typeof n?(a=e,t=n.ignoreIllegals,i=n.language):(q("10.7.0","highlight(lang, code, ...args) has been deprecated."),q("10.7.0","Please use highlight(code, options) instead.\nhttps://github.com/highlightjs/highlight.js/issues/2277"),i=e,a=n),void 0===t&&(t=!0);const r={code:a,language:i};x("before:highlight",r);const s=r.result?r.result:f(r.language,r.code,t);return s.code=r.code,x("after:highlight",s),s}function f(e,t,i,r){const l=Object.create(null);function c(){if(!O.keywords)return void M.addText(S);let e=0;O.keywordPatternRe.lastIndex=0;let n=O.keywordPatternRe.exec(S),t="";for(;n;){t+=S.substring(e,n.index);const i=w.case_insensitive?n[0].toLowerCase():n[0],r=(a=i,O.keywords[a]);if(r){const[e,a]=r;if(M.addText(t),t="",l[i]=(l[i]||0)+1,l[i]<=7&&(A+=a),e.startsWith("_"))t+=n[0];else{const t=w.classNameAliases[e]||e;M.addKeyword(n[0],t)}}else t+=n[0];e=O.keywordPatternRe.lastIndex,n=O.keywordPatternRe.exec(S)}var a;t+=S.substr(e),M.addText(t)}function g(){null!=O.subLanguage?(()=>{if(""===S)return;let e=null;if("string"==typeof O.subLanguage){if(!n[O.subLanguage])return void M.addText(S);e=f(O.subLanguage,S,!0,x[O.subLanguage]),x[O.subLanguage]=e._top}else e=E(S,O.subLanguage.length?O.subLanguage:null);O.relevance>0&&(A+=e.relevance),M.addSublanguage(e._emitter,e.language)})():c(),S=""}function u(e,n){let t=1;const a=n.length-1;for(;t<=a;){if(!e._emit[t]){t++;continue}const a=w.classNameAliases[e[t]]||e[t],i=n[t];a?M.addKeyword(i,a):(S=i,c(),S=""),t++}}function b(e,n){return e.scope&&"string"==typeof e.scope&&M.openNode(w.classNameAliases[e.scope]||e.scope),e.beginScope&&(e.beginScope._wrap?(M.addKeyword(S,w.classNameAliases[e.beginScope._wrap]||e.beginScope._wrap),S=""):e.beginScope._multi&&(u(e.beginScope,n),S="")),O=Object.create(e,{parent:{value:O}}),O}function m(e,n,t){let i=((e,n)=>{const t=e&&e.exec(n);return t&&0===t.index})(e.endRe,t);if(i){if(e["on:end"]){const t=new a(e);e["on:end"](n,t),t.isMatchIgnored&&(i=!1)}if(i){for(;e.endsParent&&e.parent;)e=e.parent;return e}}if(e.endsWithParent)return m(e.parent,n,t)}function p(e){return 0===O.matcher.regexIndex?(S+=e[0],1):(R=!0,0)}function _(e){const n=e[0],a=t.substr(e.index),i=m(O,e,a);if(!i)return ee;const r=O;O.endScope&&O.endScope._wrap?(g(),M.addKeyword(n,O.endScope._wrap)):O.endScope&&O.endScope._multi?(g(),u(O.endScope,e)):r.skip?S+=n:(r.returnEnd||r.excludeEnd||(S+=n),g(),r.excludeEnd&&(S=n));do{O.scope&&M.closeNode(),O.skip||O.subLanguage||(A+=O.relevance),O=O.parent}while(O!==i.parent);return i.starts&&b(i.starts,e),r.returnEnd?0:n.length}let h={};function y(n,r){const o=r&&r[0];if(S+=n,null==o)return g(),0;if("begin"===h.type&&"end"===r.type&&h.index===r.index&&""===o){if(S+=t.slice(r.index,r.index+1),!s){const n=Error(`0 width match regex (${e})`);throw n.languageName=e,n.badRule=h.rule,n}return 1}if(h=r,"begin"===r.type)return(e=>{const n=e[0],t=e.rule,i=new a(t),r=[t.__beforeBegin,t["on:begin"]];for(const t of r)if(t&&(t(e,i),i.isMatchIgnored))return p(n);return t.skip?S+=n:(t.excludeBegin&&(S+=n),g(),t.returnBegin||t.excludeBegin||(S=n)),b(t,e),t.returnBegin?0:n.length})(r);if("illegal"===r.type&&!i){const e=Error('Illegal lexeme "'+o+'" for mode "'+(O.scope||"")+'"');throw e.mode=O,e}if("end"===r.type){const e=_(r);if(e!==ee)return e}if("illegal"===r.type&&""===o)return 1;if(T>1e5&&T>3*r.index)throw Error("potential infinite loop, way more iterations than matches");return S+=o,o.length}const w=v(e);if(!w)throw K(o.replace("{}",e)),Error('Unknown language: "'+e+'"');const N=Q(w);let k="",O=r||N;const x={},M=new d.__emitter(d);(()=>{const e=[];for(let n=O;n!==w;n=n.parent)n.scope&&e.unshift(n.scope);e.forEach(e=>M.openNode(e))})();let S="",A=0,C=0,T=0,R=!1;try{for(O.matcher.considerAll();;){T++,R?R=!1:O.matcher.considerAll(),O.matcher.lastIndex=C;const e=O.matcher.exec(t);if(!e)break;const n=y(t.substring(C,e.index),e);C=e.index+n}return y(t.substr(C)),M.closeAllNodes(),M.finalize(),k=M.toHTML(),{language:e,value:k,relevance:A,illegal:!1,_emitter:M,_top:O}}catch(n){if(n.message&&n.message.includes("Illegal"))return{language:e,value:J(t),illegal:!0,relevance:0,_illegalBy:{message:n.message,index:C,context:t.slice(C-100,C+100),mode:n.mode,resultSoFar:k},_emitter:M};if(s)return{language:e,value:J(t),illegal:!1,relevance:0,errorRaised:n,_emitter:M,_top:O};throw n}}function E(e,t){t=t||d.languages||Object.keys(n);const a=(e=>{const n={value:J(e),illegal:!1,relevance:0,_top:l,_emitter:new d.__emitter(d)};return n._emitter.addText(e),n})(e),i=t.filter(v).filter(O).map(n=>f(n,e,!1));i.unshift(a);const r=i.sort((e,n)=>{if(e.relevance!==n.relevance)return n.relevance-e.relevance;if(e.language&&n.language){if(v(e.language).supersetOf===n.language)return 1;if(v(n.language).supersetOf===e.language)return-1}return 0}),[s,o]=r,c=s;return c.secondBest=o,c}function y(e){let n=null;const t=(e=>{let n=e.className+" ";n+=e.parentNode?e.parentNode.className:"";const t=d.languageDetectRe.exec(n);if(t){const n=v(t[1]);return n||(H(o.replace("{}",t[1])),H("Falling back to no-highlight mode for this block.",e)),n?t[1]:"no-highlight"}return n.split(/\s+/).find(e=>_(e)||v(e))})(e);if(_(t))return;if(x("before:highlightElement",{el:e,language:t}),e.children.length>0&&(d.ignoreUnescapedHTML||(console.warn("One of your code blocks includes unescaped HTML. This is a potentially serious security risk."),console.warn("https://github.com/highlightjs/highlight.js/wiki/security"),console.warn("The element with unescaped HTML:"),console.warn(e)),d.throwUnescapedHTML))throw new V("One of your code blocks includes unescaped HTML.",e.innerHTML);n=e;const a=n.textContent,r=t?h(a,{language:t,ignoreIllegals:!0}):E(a);e.innerHTML=r.value,((e,n,t)=>{const a=n&&i[n]||t;e.classList.add("hljs"),e.classList.add("language-"+a)})(e,t,r.language),e.result={language:r.language,re:r.relevance,relevance:r.relevance},r.secondBest&&(e.secondBest={language:r.secondBest.language,relevance:r.secondBest.relevance}),x("after:highlightElement",{el:e,result:r,text:a})}let w=!1;function N(){"loading"!==document.readyState?document.querySelectorAll(d.cssSelector).forEach(y):w=!0}function v(e){return e=(e||"").toLowerCase(),n[e]||n[i[e]]}function k(e,{languageName:n}){"string"==typeof e&&(e=[e]),e.forEach(e=>{i[e.toLowerCase()]=n})}function O(e){const n=v(e);return n&&!n.disableAutodetect}function x(e,n){const t=e;r.forEach(e=>{e[t]&&e[t](n)})}"undefined"!=typeof window&&window.addEventListener&&window.addEventListener("DOMContentLoaded",()=>{w&&N()},!1),Object.assign(e,{highlight:h,highlightAuto:E,highlightAll:N,highlightElement:y,highlightBlock:e=>(q("10.7.0","highlightBlock will be removed entirely in v12.0"),q("10.7.0","Please use highlightElement now."),y(e)),configure:e=>{d=Y(d,e)},initHighlighting:()=>{N(),q("10.6.0","initHighlighting() deprecated. Use highlightAll() now.")},initHighlightingOnLoad:()=>{N(),q("10.6.0","initHighlightingOnLoad() deprecated. Use highlightAll() now.")},registerLanguage:(t,a)=>{let i=null;try{i=a(e)}catch(e){if(K("Language definition for '{}' could not be registered.".replace("{}",t)),!s)throw e;K(e),i=l}i.name||(i.name=t),n[t]=i,i.rawDefinition=a.bind(null,e),i.aliases&&k(i.aliases,{languageName:t})},unregisterLanguage:e=>{delete n[e];for(const n of Object.keys(i))i[n]===e&&delete i[n]},listLanguages:()=>Object.keys(n),getLanguage:v,registerAliases:k,autoDetection:O,inherit:Y,addPlugin:e=>{(e=>{e["before:highlightBlock"]&&!e["before:highlightElement"]&&(e["before:highlightElement"]=n=>{e["before:highlightBlock"](Object.assign({block:n.el},n))}),e["after:highlightBlock"]&&!e["after:highlightElement"]&&(e["after:highlightElement"]=n=>{e["after:highlightBlock"](Object.assign({block:n.el},n))})})(e),r.push(e)}}),e.debugMode=()=>{s=!1},e.safeMode=()=>{s=!0},e.versionString="11.5.0",e.regex={concat:m,lookahead:g,either:p,optional:b,anyNumberOfTimes:u};for(const e in T)"object"==typeof T[e]&&t(T[e]);return Object.assign(e,T),e})({});const te=e=>({IMPORTANT:{scope:"meta",begin:"!important"},BLOCK_COMMENT:e.C_BLOCK_COMMENT_MODE,HEXCOLOR:{scope:"number",begin:/#(([0-9a-fA-F]{3,4})|(([0-9a-fA-F]{2}){3,4}))\b/},FUNCTION_DISPATCH:{className:"built_in",begin:/[\w-]+(?=\()/},ATTRIBUTE_SELECTOR_MODE:{scope:"selector-attr",begin:/\[/,end:/\]/,illegal:"$",contains:[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},CSS_NUMBER_MODE:{scope:"number",begin:e.NUMBER_RE+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",relevance:0},CSS_VARIABLE:{className:"attr",begin:/--[A-Za-z][A-Za-z0-9_-]*/}}),ae=["a","abbr","address","article","aside","audio","b","blockquote","body","button","canvas","caption","cite","code","dd","del","details","dfn","div","dl","dt","em","fieldset","figcaption","figure","footer","form","h1","h2","h3","h4","h5","h6","header","hgroup","html","i","iframe","img","input","ins","kbd","label","legend","li","main","mark","menu","nav","object","ol","p","q","quote","samp","section","span","strong","summary","sup","table","tbody","td","textarea","tfoot","th","thead","time","tr","ul","var","video"],ie=["any-hover","any-pointer","aspect-ratio","color","color-gamut","color-index","device-aspect-ratio","device-height","device-width","display-mode","forced-colors","grid","height","hover","inverted-colors","monochrome","orientation","overflow-block","overflow-inline","pointer","prefers-color-scheme","prefers-contrast","prefers-reduced-motion","prefers-reduced-transparency","resolution","scan","scripting","update","width","min-width","max-width","min-height","max-height"],re=["active","any-link","blank","checked","current","default","defined","dir","disabled","drop","empty","enabled","first","first-child","first-of-type","fullscreen","future","focus","focus-visible","focus-within","has","host","host-context","hover","indeterminate","in-range","invalid","is","lang","last-child","last-of-type","left","link","local-link","not","nth-child","nth-col","nth-last-child","nth-last-col","nth-last-of-type","nth-of-type","only-child","only-of-type","optional","out-of-range","past","placeholder-shown","read-only","read-write","required","right","root","scope","target","target-within","user-invalid","valid","visited","where"],se=["after","backdrop","before","cue","cue-region","first-letter","first-line","grammar-error","marker","part","placeholder","selection","slotted","spelling-error"],oe=["align-content","align-items","align-self","all","animation","animation-delay","animation-direction","animation-duration","animation-fill-mode","animation-iteration-count","animation-name","animation-play-state","animation-timing-function","backface-visibility","background","background-attachment","background-blend-mode","background-clip","background-color","background-image","background-origin","background-position","background-repeat","background-size","block-size","border","border-block","border-block-color","border-block-end","border-block-end-color","border-block-end-style","border-block-end-width","border-block-start","border-block-start-color","border-block-start-style","border-block-start-width","border-block-style","border-block-width","border-bottom","border-bottom-color","border-bottom-left-radius","border-bottom-right-radius","border-bottom-style","border-bottom-width","border-collapse","border-color","border-image","border-image-outset","border-image-repeat","border-image-slice","border-image-source","border-image-width","border-inline","border-inline-color","border-inline-end","border-inline-end-color","border-inline-end-style","border-inline-end-width","border-inline-start","border-inline-start-color","border-inline-start-style","border-inline-start-width","border-inline-style","border-inline-width","border-left","border-left-color","border-left-style","border-left-width","border-radius","border-right","border-right-color","border-right-style","border-right-width","border-spacing","border-style","border-top","border-top-color","border-top-left-radius","border-top-right-radius","border-top-style","border-top-width","border-width","bottom","box-decoration-break","box-shadow","box-sizing","break-after","break-before","break-inside","caption-side","caret-color","clear","clip","clip-path","clip-rule","color","column-count","column-fill","column-gap","column-rule","column-rule-color","column-rule-style","column-rule-width","column-span","column-width","columns","contain","content","content-visibility","counter-increment","counter-reset","cue","cue-after","cue-before","cursor","direction","display","empty-cells","filter","flex","flex-basis","flex-direction","flex-flow","flex-grow","flex-shrink","flex-wrap","float","flow","font","font-display","font-family","font-feature-settings","font-kerning","font-language-override","font-size","font-size-adjust","font-smoothing","font-stretch","font-style","font-synthesis","font-variant","font-variant-caps","font-variant-east-asian","font-variant-ligatures","font-variant-numeric","font-variant-position","font-variation-settings","font-weight","gap","glyph-orientation-vertical","grid","grid-area","grid-auto-columns","grid-auto-flow","grid-auto-rows","grid-column","grid-column-end","grid-column-start","grid-gap","grid-row","grid-row-end","grid-row-start","grid-template","grid-template-areas","grid-template-columns","grid-template-rows","hanging-punctuation","height","hyphens","icon","image-orientation","image-rendering","image-resolution","ime-mode","inline-size","isolation","justify-content","left","letter-spacing","line-break","line-height","list-style","list-style-image","list-style-position","list-style-type","margin","margin-block","margin-block-end","margin-block-start","margin-bottom","margin-inline","margin-inline-end","margin-inline-start","margin-left","margin-right","margin-top","marks","mask","mask-border","mask-border-mode","mask-border-outset","mask-border-repeat","mask-border-slice","mask-border-source","mask-border-width","mask-clip","mask-composite","mask-image","mask-mode","mask-origin","mask-position","mask-repeat","mask-size","mask-type","max-block-size","max-height","max-inline-size","max-width","min-block-size","min-height","min-inline-size","min-width","mix-blend-mode","nav-down","nav-index","nav-left","nav-right","nav-up","none","normal","object-fit","object-position","opacity","order","orphans","outline","outline-color","outline-offset","outline-style","outline-width","overflow","overflow-wrap","overflow-x","overflow-y","padding","padding-block","padding-block-end","padding-block-start","padding-bottom","padding-inline","padding-inline-end","padding-inline-start","padding-left","padding-right","padding-top","page-break-after","page-break-before","page-break-inside","pause","pause-after","pause-before","perspective","perspective-origin","pointer-events","position","quotes","resize","rest","rest-after","rest-before","right","row-gap","scroll-margin","scroll-margin-block","scroll-margin-block-end","scroll-margin-block-start","scroll-margin-bottom","scroll-margin-inline","scroll-margin-inline-end","scroll-margin-inline-start","scroll-margin-left","scroll-margin-right","scroll-margin-top","scroll-padding","scroll-padding-block","scroll-padding-block-end","scroll-padding-block-start","scroll-padding-bottom","scroll-padding-inline","scroll-padding-inline-end","scroll-padding-inline-start","scroll-padding-left","scroll-padding-right","scroll-padding-top","scroll-snap-align","scroll-snap-stop","scroll-snap-type","scrollbar-color","scrollbar-gutter","scrollbar-width","shape-image-threshold","shape-margin","shape-outside","speak","speak-as","src","tab-size","table-layout","text-align","text-align-all","text-align-last","text-combine-upright","text-decoration","text-decoration-color","text-decoration-line","text-decoration-style","text-emphasis","text-emphasis-color","text-emphasis-position","text-emphasis-style","text-indent","text-justify","text-orientation","text-overflow","text-rendering","text-shadow","text-transform","text-underline-position","top","transform","transform-box","transform-origin","transform-style","transition","transition-delay","transition-duration","transition-property","transition-timing-function","unicode-bidi","vertical-align","visibility","voice-balance","voice-duration","voice-family","voice-pitch","voice-range","voice-rate","voice-stress","voice-volume","white-space","widows","width","will-change","word-break","word-spacing","word-wrap","writing-mode","z-index"].reverse(),le=re.concat(se);var ce="\\.([0-9](_*[0-9])*)",de="[0-9a-fA-F](_*[0-9a-fA-F])*",ge={className:"number",variants:[{begin:`(\\b([0-9](_*[0-9])*)((${ce})|\\.)?|(${ce}))[eE][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:`\\b([0-9](_*[0-9])*)((${ce})[fFdD]?\\b|\\.([fFdD]\\b)?)`},{begin:`(${ce})[fFdD]?\\b`},{begin:"\\b([0-9](_*[0-9])*)[fFdD]\\b"},{begin:`\\b0[xX]((${de})\\.?|(${de})?\\.(${de}))[pP][+-]?([0-9](_*[0-9])*)[fFdD]?\\b`},{begin:"\\b(0|[1-9](_*[0-9])*)[lL]?\\b"},{begin:`\\b0[xX](${de})[lL]?\\b`},{begin:"\\b0(_*[0-7])*[lL]?\\b"},{begin:"\\b0[bB][01](_*[01])*[lL]?\\b"}],relevance:0};function ue(e,n,t){return-1===t?"":e.replace(n,a=>ue(e,n,t-1))}const be="[A-Za-z$_][0-9A-Za-z$_]*",me=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","case","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],pe=["true","false","null","undefined","NaN","Infinity"],_e=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],he=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],fe=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],Ee=["arguments","this","super","console","window","document","localStorage","module","global"],ye=[].concat(fe,_e,he);function we(e){const n=e.regex,t=be,a={begin:/<[A-Za-z0-9\\._:-]+/,end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{const t=e[0].length+e.index,a=e.input[t];if("<"===a||","===a)return void n.ignoreMatch();let i;">"===a&&(((e,{after:n})=>{const t="",O={match:[/const|var|let/,/\s+/,t,/\s*/,/=\s*/,/(async\s*)?/,n.lookahead(k)],keywords:"async",className:{1:"keyword",3:"title.function"},contains:[_]};return{name:"Javascript",aliases:["js","jsx","mjs","cjs"],keywords:i,exports:{PARAMS_CONTAINS:p,CLASS_REFERENCE:f},illegal:/#(?![$_A-z])/,contains:[e.SHEBANG({label:"shebang",binary:"node",relevance:5}),{label:"use_strict",className:"meta",relevance:10,begin:/^\s*['"]use (strict|asm)['"]/},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,c,d,g,u,o,f,{className:"attr",begin:t+n.lookahead(":"),relevance:0},O,{begin:"("+e.RE_STARTERS_RE+"|\\b(case|return|throw)\\b)\\s*",keywords:"return throw case",relevance:0,contains:[u,e.REGEXP_MODE,{className:"function",begin:k,returnBegin:!0,end:"\\s*=>",contains:[{className:"params",variants:[{begin:e.UNDERSCORE_IDENT_RE,relevance:0},{className:null,begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,contains:p}]}]},{begin:/,/,relevance:0},{match:/\s+/,relevance:0},{variants:[{begin:"<>",end:""},{match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:a.begin,"on:begin":a.isTrulyOpeningTag,end:a.end}],subLanguage:"xml",contains:[{begin:a.begin,end:a.end,skip:!0,contains:["self"]}]}]},E,{beginKeywords:"while if case catch for"},{begin:"\\b(?!function)"+e.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{",returnBegin:!0,label:"func.def",contains:[_,e.inherit(e.TITLE_MODE,{begin:t,className:"title.function"})]},{match:/\.\.\./,relevance:0},N,{match:"\\$"+t,relevance:0},{match:[/\bconstructor(?=\s*\()/],className:{1:"title.function"},contains:[_]},y,{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},h,v,{match:/\$[(.]/}]}}const Ne=e=>m(/\b/,e,/\w$/.test(e)?/\b/:/\B/),ve=["Protocol","Type"].map(Ne),ke=["init","self"].map(Ne),Oe=["Any","Self"],xe=["actor","associatedtype","async","await",/as\?/,/as!/,"as","break","case","catch","class","continue","convenience","default","defer","deinit","didSet","do","dynamic","else","enum","extension","fallthrough",/fileprivate\(set\)/,"fileprivate","final","for","func","get","guard","if","import","indirect","infix",/init\?/,/init!/,"inout",/internal\(set\)/,"internal","in","is","isolated","nonisolated","lazy","let","mutating","nonmutating",/open\(set\)/,"open","operator","optional","override","postfix","precedencegroup","prefix",/private\(set\)/,"private","protocol",/public\(set\)/,"public","repeat","required","rethrows","return","set","some","static","struct","subscript","super","case","throws","throw",/try\?/,/try!/,"try","typealias",/unowned\(safe\)/,/unowned\(unsafe\)/,"unowned","var","weak","where","while","willSet"],Me=["false","nil","true"],Se=["assignment","associativity","higherThan","left","lowerThan","none","right"],Ae=["#colorLiteral","#column","#dsohandle","#else","#elseif","#endif","#error","#file","#fileID","#fileLiteral","#filePath","#function","#if","#imageLiteral","#keyPath","#line","#selector","#sourceLocation","#warn_unqualified_access","#warning"],Ce=["abs","all","any","assert","assertionFailure","debugPrint","dump","fatalError","getVaList","isKnownUniquelyReferenced","max","min","numericCast","pointwiseMax","pointwiseMin","precondition","preconditionFailure","print","readLine","repeatElement","sequence","stride","swap","swift_unboxFromSwiftValueWithType","transcode","type","unsafeBitCast","unsafeDowncast","withExtendedLifetime","withUnsafeMutablePointer","withUnsafePointer","withVaList","withoutActuallyEscaping","zip"],Te=p(/[/=\-+!*%<>&|^~?]/,/[\u00A1-\u00A7]/,/[\u00A9\u00AB]/,/[\u00AC\u00AE]/,/[\u00B0\u00B1]/,/[\u00B6\u00BB\u00BF\u00D7\u00F7]/,/[\u2016-\u2017]/,/[\u2020-\u2027]/,/[\u2030-\u203E]/,/[\u2041-\u2053]/,/[\u2055-\u205E]/,/[\u2190-\u23FF]/,/[\u2500-\u2775]/,/[\u2794-\u2BFF]/,/[\u2E00-\u2E7F]/,/[\u3001-\u3003]/,/[\u3008-\u3020]/,/[\u3030]/),Re=p(Te,/[\u0300-\u036F]/,/[\u1DC0-\u1DFF]/,/[\u20D0-\u20FF]/,/[\uFE00-\uFE0F]/,/[\uFE20-\uFE2F]/),De=m(Te,Re,"*"),Ie=p(/[a-zA-Z_]/,/[\u00A8\u00AA\u00AD\u00AF\u00B2-\u00B5\u00B7-\u00BA]/,/[\u00BC-\u00BE\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF]/,/[\u0100-\u02FF\u0370-\u167F\u1681-\u180D\u180F-\u1DBF]/,/[\u1E00-\u1FFF]/,/[\u200B-\u200D\u202A-\u202E\u203F-\u2040\u2054\u2060-\u206F]/,/[\u2070-\u20CF\u2100-\u218F\u2460-\u24FF\u2776-\u2793]/,/[\u2C00-\u2DFF\u2E80-\u2FFF]/,/[\u3004-\u3007\u3021-\u302F\u3031-\u303F\u3040-\uD7FF]/,/[\uF900-\uFD3D\uFD40-\uFDCF\uFDF0-\uFE1F\uFE30-\uFE44]/,/[\uFE47-\uFEFE\uFF00-\uFFFD]/),Le=p(Ie,/\d/,/[\u0300-\u036F\u1DC0-\u1DFF\u20D0-\u20FF\uFE20-\uFE2F]/),Be=m(Ie,Le,"*"),$e=m(/[A-Z]/,Le,"*"),ze=["autoclosure",m(/convention\(/,p("swift","block","c"),/\)/),"discardableResult","dynamicCallable","dynamicMemberLookup","escaping","frozen","GKInspectable","IBAction","IBDesignable","IBInspectable","IBOutlet","IBSegueAction","inlinable","main","nonobjc","NSApplicationMain","NSCopying","NSManaged",m(/objc\(/,Be,/\)/),"objc","objcMembers","propertyWrapper","requires_stored_property_inits","resultBuilder","testable","UIApplicationMain","unknown","usableFromInline"],Fe=["iOS","iOSApplicationExtension","macOS","macOSApplicationExtension","macCatalyst","macCatalystApplicationExtension","watchOS","watchOSApplicationExtension","tvOS","tvOSApplicationExtension","swift"];var Ue=Object.freeze({__proto__:null,grmr_bash:e=>{const n=e.regex,t={},a={begin:/\$\{/,end:/\}/,contains:["self",{begin:/:-/,contains:[t]}]};Object.assign(t,{className:"variable",variants:[{begin:n.concat(/\$[\w\d#@][\w\d_]*/,"(?![\\w\\d])(?![$])")},a]});const i={className:"subst",begin:/\$\(/,end:/\)/,contains:[e.BACKSLASH_ESCAPE]},r={begin:/<<-?\s*(?=\w+)/,starts:{contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,className:"string"})]}},s={className:"string",begin:/"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,t,i]};i.contains.push(s);const o={begin:/\$\(\(/,end:/\)\)/,contains:[{begin:/\d+#[0-9a-f]+/,className:"number"},e.NUMBER_MODE,t]},l=e.SHEBANG({binary:"(fish|bash|zsh|sh|csh|ksh|tcsh|dash|scsh)",relevance:10}),c={className:"function",begin:/\w[\w\d_]*\s*\(\s*\)\s*\{/,returnBegin:!0,contains:[e.inherit(e.TITLE_MODE,{begin:/\w[\w\d_]*/})],relevance:0};return{name:"Bash",aliases:["sh"],keywords:{$pattern:/\b[a-z][a-z0-9._-]+\b/,keyword:["if","then","else","elif","fi","for","while","in","do","done","case","esac","function"],literal:["true","false"],built_in:["break","cd","continue","eval","exec","exit","export","getopts","hash","pwd","readonly","return","shift","test","times","trap","umask","unset","alias","bind","builtin","caller","command","declare","echo","enable","help","let","local","logout","mapfile","printf","read","readarray","source","type","typeset","ulimit","unalias","set","shopt","autoload","bg","bindkey","bye","cap","chdir","clone","comparguments","compcall","compctl","compdescribe","compfiles","compgroups","compquote","comptags","comptry","compvalues","dirs","disable","disown","echotc","echoti","emulate","fc","fg","float","functions","getcap","getln","history","integer","jobs","kill","limit","log","noglob","popd","print","pushd","pushln","rehash","sched","setcap","setopt","stat","suspend","ttyctl","unfunction","unhash","unlimit","unsetopt","vared","wait","whence","where","which","zcompile","zformat","zftp","zle","zmodload","zparseopts","zprof","zpty","zregexparse","zsocket","zstyle","ztcp","chcon","chgrp","chown","chmod","cp","dd","df","dir","dircolors","ln","ls","mkdir","mkfifo","mknod","mktemp","mv","realpath","rm","rmdir","shred","sync","touch","truncate","vdir","b2sum","base32","base64","cat","cksum","comm","csplit","cut","expand","fmt","fold","head","join","md5sum","nl","numfmt","od","paste","ptx","pr","sha1sum","sha224sum","sha256sum","sha384sum","sha512sum","shuf","sort","split","sum","tac","tail","tr","tsort","unexpand","uniq","wc","arch","basename","chroot","date","dirname","du","echo","env","expr","factor","groups","hostid","id","link","logname","nice","nohup","nproc","pathchk","pinky","printenv","printf","pwd","readlink","runcon","seq","sleep","stat","stdbuf","stty","tee","test","timeout","tty","uname","unlink","uptime","users","who","whoami","yes"]},contains:[l,e.SHEBANG(),c,o,e.HASH_COMMENT_MODE,r,{match:/(\/[a-z._-]+)+/},s,{className:"",begin:/\\"/},{className:"string",begin:/'/,end:/'/},t]}},grmr_c:e=>{const n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="[a-zA-Z_]\\w*::",i="(decltype\\(auto\\)|"+n.optional(a)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={className:"type",variants:[{begin:"\\b[a-z\\d_]*_t\\b"},{match:/\batomic_[a-z]{3,6}\b/}]},s={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(s,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={className:"title",begin:n.optional(a)+e.IDENT_RE,relevance:0},d=n.optional(a)+e.IDENT_RE+"\\s*\\(",g={keyword:["asm","auto","break","case","continue","default","do","else","enum","extern","for","fortran","goto","if","inline","register","restrict","return","sizeof","struct","case","typedef","union","volatile","while","_Alignas","_Alignof","_Atomic","_Generic","_Noreturn","_Static_assert","_Thread_local","alignas","alignof","noreturn","static_assert","thread_local","_Pragma"],type:["float","double","signed","unsigned","int","short","long","char","void","_Bool","_Complex","_Imaginary","_Decimal32","_Decimal64","_Decimal128","const","static","complex","bool","imaginary"],literal:"true false NULL",built_in:"std string wstring cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set pair bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap priority_queue make_pair array shared_ptr abort terminate abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf future isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr"},u=[l,r,t,e.C_BLOCK_COMMENT_MODE,o,s],b={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:g,contains:u.concat([{begin:/\(/,end:/\)/,keywords:g,contains:u.concat(["self"]),relevance:0}]),relevance:0},m={begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)",keywords:g,relevance:0},{begin:d,returnBegin:!0,contains:[e.inherit(c,{className:"title.function"})],relevance:0},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,s,o,r,{begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,s,o,r]}]},r,t,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C",aliases:["h"],keywords:g,disableAutodetect:!0,illegal:"=]/,contains:[{beginKeywords:"final class struct"},e.TITLE_MODE]}]),exports:{preprocessor:l,strings:s,keywords:g}}},grmr_cpp:e=>{const n=e.regex,t=e.COMMENT("//","$",{contains:[{begin:/\\\n/}]}),a="[a-zA-Z_]\\w*::",i="(?!struct)(decltype\\(auto\\)|"+n.optional(a)+"[a-zA-Z_]\\w*"+n.optional("<[^<>]+>")+")",r={className:"type",begin:"\\b[a-z\\d_]*_t\\b"},s={className:"string",variants:[{begin:'(u8?|U|L)?"',end:'"',illegal:"\\n",contains:[e.BACKSLASH_ESCAPE]},{begin:"(u8?|U|L)?'(\\\\(x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4,8}|[0-7]{3}|\\S)|.)",end:"'",illegal:"."},e.END_SAME_AS_BEGIN({begin:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\(/,end:/\)([^()\\ ]{0,16})"/})]},o={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)((ll|LL|l|L)(u|U)?|(u|U)(ll|LL|l|L)?|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},l={className:"meta",begin:/#\s*[a-z]+\b/,end:/$/,keywords:{keyword:"if else elif endif define undef warning error line pragma _Pragma ifdef ifndef include"},contains:[{begin:/\\\n/,relevance:0},e.inherit(s,{className:"string"}),{className:"string",begin:/<.*?>/},t,e.C_BLOCK_COMMENT_MODE]},c={className:"title",begin:n.optional(a)+e.IDENT_RE,relevance:0},d=n.optional(a)+e.IDENT_RE+"\\s*\\(",g={type:["bool","char","char16_t","char32_t","char8_t","double","float","int","long","short","void","wchar_t","unsigned","signed","const","static"],keyword:["alignas","alignof","and","and_eq","asm","atomic_cancel","atomic_commit","atomic_noexcept","auto","bitand","bitor","break","case","catch","class","co_await","co_return","co_yield","compl","concept","const_cast|10","consteval","constexpr","constinit","continue","decltype","default","delete","do","dynamic_cast|10","else","enum","explicit","export","extern","false","final","for","friend","goto","if","import","inline","module","mutable","namespace","new","noexcept","not","not_eq","nullptr","operator","or","or_eq","override","private","protected","public","reflexpr","register","reinterpret_cast|10","requires","return","sizeof","static_assert","static_cast|10","struct","case","synchronized","template","this","thread_local","throw","transaction_safe","transaction_safe_dynamic","true","try","typedef","typeid","typename","union","using","virtual","volatile","while","xor","xor_eq"],literal:["NULL","false","nullopt","nullptr","true"],built_in:["_Pragma"],_type_hints:["any","auto_ptr","barrier","binary_semaphore","bitset","complex","condition_variable","condition_variable_any","counting_semaphore","deque","false_type","future","imaginary","initializer_list","istringstream","jthread","latch","lock_guard","multimap","multiset","mutex","optional","ostringstream","packaged_task","pair","promise","priority_queue","queue","recursive_mutex","recursive_timed_mutex","scoped_lock","set","shared_future","shared_lock","shared_mutex","shared_timed_mutex","shared_ptr","stack","string_view","stringstream","timed_mutex","thread","true_type","tuple","unique_lock","unique_ptr","unordered_map","unordered_multimap","unordered_multiset","unordered_set","variant","vector","weak_ptr","wstring","wstring_view"]},u={className:"function.dispatch",relevance:0,keywords:{_hint:["abort","abs","acos","apply","as_const","asin","atan","atan2","calloc","ceil","cerr","cin","clog","cos","cosh","cout","declval","endl","exchange","exit","exp","fabs","floor","fmod","forward","fprintf","fputs","free","frexp","fscanf","future","invoke","isalnum","isalpha","iscntrl","isdigit","isgraph","islower","isprint","ispunct","isspace","isupper","isxdigit","labs","launder","ldexp","log","log10","make_pair","make_shared","make_shared_for_overwrite","make_tuple","make_unique","malloc","memchr","memcmp","memcpy","memset","modf","move","pow","printf","putchar","puts","realloc","scanf","sin","sinh","snprintf","sprintf","sqrt","sscanf","std","stderr","stdin","stdout","strcat","strchr","strcmp","strcpy","strcspn","strlen","strncat","strncmp","strncpy","strpbrk","strrchr","strspn","strstr","swap","tan","tanh","terminate","to_underlying","tolower","toupper","vfprintf","visit","vprintf","vsprintf"]},begin:n.concat(/\b/,/(?!decltype)/,/(?!if)/,/(?!for)/,/(?!case)/,/(?!while)/,e.IDENT_RE,n.lookahead(/(<[^<>]+>|)\s*\(/))},b=[u,l,r,t,e.C_BLOCK_COMMENT_MODE,o,s],m={variants:[{begin:/=/,end:/;/},{begin:/\(/,end:/\)/},{beginKeywords:"new throw return else",end:/;/}],keywords:g,contains:b.concat([{begin:/\(/,end:/\)/,keywords:g,contains:b.concat(["self"]),relevance:0}]),relevance:0},p={className:"function",begin:"("+i+"[\\*&\\s]+)+"+d,returnBegin:!0,end:/[{;=]/,excludeEnd:!0,keywords:g,illegal:/[^\w\s\*&:<>.]/,contains:[{begin:"decltype\\(auto\\)",keywords:g,relevance:0},{begin:d,returnBegin:!0,contains:[c],relevance:0},{begin:/::/,relevance:0},{begin:/:/,endsWithParent:!0,contains:[s,o]},{relevance:0,match:/,/},{className:"params",begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:[t,e.C_BLOCK_COMMENT_MODE,s,o,r,{begin:/\(/,end:/\)/,keywords:g,relevance:0,contains:["self",t,e.C_BLOCK_COMMENT_MODE,s,o,r]}]},r,t,e.C_BLOCK_COMMENT_MODE,l]};return{name:"C++",aliases:["cc","c++","h++","hpp","hh","hxx","cxx"],keywords:g,illegal:"",keywords:g,contains:["self",r]},{begin:e.IDENT_RE+"::",keywords:g},{match:[/\b(?:enum(?:\s+(?:class|struct))?|class|struct|union)/,/\s+/,/\w+/],className:{1:"keyword",3:"title.class"}}])}},grmr_csharp:e=>{const n={keyword:["abstract","as","base","break","case","catch","class","const","continue","do","else","event","explicit","extern","finally","fixed","for","foreach","goto","if","implicit","in","interface","internal","is","lock","namespace","new","operator","out","override","params","private","protected","public","readonly","record","ref","return","sealed","sizeof","stackalloc","static","struct","case","this","throw","try","typeof","unchecked","unsafe","using","virtual","void","volatile","while"].concat(["add","alias","and","ascending","async","await","by","descending","equals","from","get","global","group","init","into","join","let","nameof","not","notnull","on","or","orderby","partial","remove","select","set","unmanaged","value|0","var","when","where","with","yield"]),built_in:["bool","byte","char","decimal","delegate","double","dynamic","enum","float","int","long","nint","nuint","object","sbyte","short","string","ulong","uint","ushort"],literal:["default","false","null","true"]},t=e.inherit(e.TITLE_MODE,{begin:"[a-zA-Z](\\.?\\w)*"}),a={className:"number",variants:[{begin:"\\b(0b[01']+)"},{begin:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{begin:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],relevance:0},i={className:"string",begin:'@"',end:'"',contains:[{begin:'""'}]},r=e.inherit(i,{illegal:/\n/}),s={className:"subst",begin:/\{/,end:/\}/,keywords:n},o=e.inherit(s,{illegal:/\n/}),l={className:"string",begin:/\$"/,end:'"',illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},e.BACKSLASH_ESCAPE,o]},c={className:"string",begin:/\$@"/,end:'"',contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},s]},d=e.inherit(c,{illegal:/\n/,contains:[{begin:/\{\{/},{begin:/\}\}/},{begin:'""'},o]});s.contains=[c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.C_BLOCK_COMMENT_MODE],o.contains=[d,l,r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,a,e.inherit(e.C_BLOCK_COMMENT_MODE,{illegal:/\n/})];const g={variants:[c,l,i,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},u={begin:"<",end:">",contains:[{beginKeywords:"in out"},t]},b=e.IDENT_RE+"(<"+e.IDENT_RE+"(\\s*,\\s*"+e.IDENT_RE+")*>)?(\\[\\])?",m={begin:"@"+e.IDENT_RE,relevance:0};return{name:"C#",aliases:["cs","c#"],keywords:n,illegal:/::/,contains:[e.COMMENT("///","$",{returnBegin:!0,contains:[{className:"doctag",variants:[{begin:"///",relevance:0},{begin:"\x3c!--|--\x3e"},{begin:""}]}]}),e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{className:"meta",begin:"#",end:"$",keywords:{keyword:"if else elif endif define undef warning error line region endregion pragma checksum"}},g,a,{beginKeywords:"class interface",relevance:0,end:/[{;=]/,illegal:/[^\s:,]/,contains:[{beginKeywords:"where class"},t,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"namespace",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"record",relevance:0,end:/[{;=]/,illegal:/[^\s:]/,contains:[t,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"meta",begin:"^\\s*\\[(?=[\\w])",excludeBegin:!0,end:"\\]",excludeEnd:!0,contains:[{className:"string",begin:/"/,end:/"/}]},{beginKeywords:"new return throw await else",relevance:0},{className:"function",begin:"("+b+"\\s+)+"+e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,end:/\s*[{;=]/,excludeEnd:!0,keywords:n,contains:[{beginKeywords:"public private protected static internal protected abstract async extern override unsafe virtual new sealed partial",relevance:0},{begin:e.IDENT_RE+"\\s*(<[^=]+>\\s*)?\\(",returnBegin:!0,contains:[e.TITLE_MODE,u],relevance:0},{match:/\(\)/},{className:"params",begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:n,relevance:0,contains:[g,a,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},m]}},grmr_css:e=>{const n=e.regex,t=te(e),a=[e.APOS_STRING_MODE,e.QUOTE_STRING_MODE];return{name:"CSS",case_insensitive:!0,illegal:/[=|'\$]/,keywords:{keyframePosition:"from to"},classNameAliases:{keyframePosition:"selector-tag"},contains:[t.BLOCK_COMMENT,{begin:/-(webkit|moz|ms|o)-(?=[a-z])/},t.CSS_NUMBER_MODE,{className:"selector-id",begin:/#[A-Za-z0-9_-]+/,relevance:0},{className:"selector-class",begin:"\\.[a-zA-Z-][a-zA-Z0-9_-]*",relevance:0},t.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",variants:[{begin:":("+re.join("|")+")"},{begin:":(:)?("+se.join("|")+")"}]},t.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b"},{begin:/:/,end:/[;}{]/,contains:[t.BLOCK_COMMENT,t.HEXCOLOR,t.IMPORTANT,t.CSS_NUMBER_MODE,...a,{begin:/(url|data-uri)\(/,end:/\)/,relevance:0,keywords:{built_in:"url data-uri"},contains:[{className:"string",begin:/[^)]/,endsWithParent:!0,excludeEnd:!0}]},t.FUNCTION_DISPATCH]},{begin:n.lookahead(/@/),end:"[{;]",relevance:0,illegal:/:/,contains:[{className:"keyword",begin:/@-?\w[\w]*(-\w+)*/},{begin:/\s/,endsWithParent:!0,excludeEnd:!0,relevance:0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},contains:[{begin:/[a-z-]+(?=:)/,className:"attribute"},...a,t.CSS_NUMBER_MODE]}]},{className:"selector-tag",begin:"\\b("+ae.join("|")+")\\b"}]}},grmr_diff:e=>{const n=e.regex;return{name:"Diff",aliases:["patch"],contains:[{className:"meta",relevance:10,match:n.either(/^@@ +-\d+,\d+ +\+\d+,\d+ +@@/,/^\*\*\* +\d+,\d+ +\*\*\*\*$/,/^--- +\d+,\d+ +----$/)},{className:"comment",variants:[{begin:n.either(/Index: /,/^index/,/={3,}/,/^-{3}/,/^\*{3} /,/^\+{3}/,/^diff --git/),end:/$/},{match:/^\*{15}$/}]},{className:"addition",begin:/^\+/,end:/$/},{className:"deletion",begin:/^-/,end:/$/},{className:"addition",begin:/^!/,end:/$/}]}},grmr_go:e=>{const n={keyword:["break","case","chan","const","continue","default","defer","else","fallthrough","for","func","go","goto","if","import","interface","map","package","range","return","select","struct","case","type","var"],type:["bool","byte","complex64","complex128","error","float32","float64","int8","int16","int32","int64","string","uint8","uint16","uint32","uint64","int","uint","uintptr","rune"],literal:["true","false","iota","nil"],built_in:["append","cap","close","complex","copy","imag","len","make","new","panic","print","println","real","recover","delete"]};return{name:"Go",aliases:["golang"],keywords:n,illegal:"{const n=e.regex,t={className:"number",relevance:0,variants:[{begin:/([+-]+)?[\d]+_[\d_]+/},{begin:e.NUMBER_RE}]},a=e.COMMENT();a.variants=[{begin:/;/,end:/$/},{begin:/#/,end:/$/}];const i={className:"variable",variants:[{begin:/\$[\w\d"][\w\d_]*/},{begin:/\$\{(.*?)\}/}]},r={className:"literal",begin:/\bon|off|true|false|yes|no\b/},s={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:"'''",end:"'''",relevance:10},{begin:'"""',end:'"""',relevance:10},{begin:'"',end:'"'},{begin:"'",end:"'"}]},o={begin:/\[/,end:/\]/,contains:[a,r,i,s,t,"self"],relevance:0},l=n.either(/[A-Za-z0-9_-]+/,/"(\\"|[^"])*"/,/'[^']*'/);return{name:"TOML, also INI",aliases:["toml"],case_insensitive:!0,illegal:/\S/,contains:[a,{className:"section",begin:/\[+/,end:/\]+/},{begin:n.concat(l,"(\\s*\\.\\s*",l,")*",n.lookahead(/\s*=\s*[^#\s]/)),className:"attr",starts:{end:/$/,contains:[a,o,r,i,s,t]}}]}},grmr_java:e=>{const n=e.regex,t="[ร€-สธa-zA-Z_$][ร€-สธa-zA-Z_$0-9]*",a=t+ue("(?:<"+t+"~~~(?:\\s*,\\s*"+t+"~~~)*>)?",/~~~/g,2),i={keyword:["synchronized","abstract","private","var","static","if","const ","for","while","strictfp","finally","protected","import","native","final","void","enum","else","break","transient","catch","instanceof","volatile","case","assert","package","default","public","try","case","continue","throws","protected","public","private","module","requires","exports","do","sealed"],literal:["false","true","null"],type:["char","boolean","long","float","int","byte","short","double"],built_in:["super","this"]},r={className:"meta",begin:"@"+t,contains:[{begin:/\(/,end:/\)/,contains:["self"]}]},s={className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[e.C_BLOCK_COMMENT_MODE],endsParent:!0};return{name:"Java",aliases:["jsp"],keywords:i,illegal:/<\/|#/,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{begin:/\w+@/,relevance:0},{className:"doctag",begin:"@[A-Za-z]+"}]}),{begin:/import java\.[a-z]+\./,keywords:"import",relevance:2},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,{begin:/"""/,end:/"""/,className:"string",contains:[e.BACKSLASH_ESCAPE]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{match:[/\b(?:class|interface|enum|extends|implements|new)/,/\s+/,t],className:{1:"keyword",3:"title.class"}},{match:/non-sealed/,scope:"keyword"},{begin:[n.concat(/(?!else)/,t),/\s+/,t,/\s+/,/=/],className:{1:"type",3:"variable",5:"operator"}},{begin:[/record/,/\s+/,t],className:{1:"keyword",3:"title.class"},contains:[s,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{beginKeywords:"new throw return else",relevance:0},{begin:["(?:"+a+"\\s+)",e.UNDERSCORE_IDENT_RE,/\s*(?=\()/],className:{2:"title.function"},keywords:i,contains:[{className:"params",begin:/\(/,end:/\)/,keywords:i,relevance:0,contains:[r,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,ge,e.C_BLOCK_COMMENT_MODE]},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},ge,r]}},grmr_javascript:we,grmr_json:e=>({name:"JSON",contains:[{className:"attr",begin:/"(\\.|[^\\"\r\n])*"(?=\s*:)/,relevance:1.01},{match:/[{}[\],:]/,className:"punctuation",relevance:0},e.QUOTE_STRING_MODE,{beginKeywords:"true false null"},e.C_NUMBER_MODE,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:"\\S"}),grmr_kotlin:e=>{const n={keyword:"abstract as val var vararg get set class object open private protected public noinline crossinline dynamic final enum if else do while for when throw try catch finally import package is in fun override companion reified inline lateinit init interface annotation data sealed internal infix operator out by constructor super tailrec where const inner suspend typealias external expect actual",built_in:"Byte Short Char Int Long Boolean Float Double Void Unit Nothing",literal:"true false null"},t={className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"@"},a={className:"subst",begin:/\$\{/,end:/\}/,contains:[e.C_NUMBER_MODE]},i={className:"variable",begin:"\\$"+e.UNDERSCORE_IDENT_RE},r={className:"string",variants:[{begin:'"""',end:'"""(?=[^"])',contains:[i,a]},{begin:"'",end:"'",illegal:/\n/,contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"',illegal:/\n/,contains:[e.BACKSLASH_ESCAPE,i,a]}]};a.contains.push(r);const s={className:"meta",begin:"@(?:file|property|field|get|set|receiver|param|setparam|delegate)\\s*:(?:\\s*"+e.UNDERSCORE_IDENT_RE+")?"},o={className:"meta",begin:"@"+e.UNDERSCORE_IDENT_RE,contains:[{begin:/\(/,end:/\)/,contains:[e.inherit(r,{className:"string"})]}]},l=ge,c=e.COMMENT("/\\*","\\*/",{contains:[e.C_BLOCK_COMMENT_MODE]}),d={variants:[{className:"type",begin:e.UNDERSCORE_IDENT_RE},{begin:/\(/,end:/\)/,contains:[]}]},g=d;return g.variants[1].contains=[d],d.variants[1].contains=[g],{name:"Kotlin",aliases:["kt","kts"],keywords:n,contains:[e.COMMENT("/\\*\\*","\\*/",{relevance:0,contains:[{className:"doctag",begin:"@[A-Za-z]+"}]}),e.C_LINE_COMMENT_MODE,c,{className:"keyword",begin:/\b(break|continue|return|this)\b/,starts:{contains:[{className:"symbol",begin:/@\w+/}]}},t,s,o,{className:"function",beginKeywords:"fun",end:"[(]|$",returnBegin:!0,excludeEnd:!0,keywords:n,relevance:5,contains:[{begin:e.UNDERSCORE_IDENT_RE+"\\s*\\(",returnBegin:!0,relevance:0,contains:[e.UNDERSCORE_TITLE_MODE]},{className:"type",begin://,keywords:"reified",relevance:0},{className:"params",begin:/\(/,end:/\)/,endsParent:!0,keywords:n,relevance:0,contains:[{begin:/:/,end:/[=,\/]/,endsWithParent:!0,contains:[d,e.C_LINE_COMMENT_MODE,c],relevance:0},e.C_LINE_COMMENT_MODE,c,s,o,r,e.C_NUMBER_MODE]},c]},{className:"class",beginKeywords:"class interface trait",end:/[:\{(]|$/,excludeEnd:!0,illegal:"extends implements",contains:[{beginKeywords:"public protected internal private constructor"},e.UNDERSCORE_TITLE_MODE,{className:"type",begin://,excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:/[,:]\s*/,end:/[<\(,]|$/,excludeBegin:!0,returnEnd:!0},s,o]},r,{className:"meta",begin:"^#!/usr/bin/env",end:"$",illegal:"\n"},l]}},grmr_less:e=>{const n=te(e),t=le,a="([\\w-]+|@\\{[\\w-]+\\})",i=[],r=[],s=e=>({className:"string",begin:"~?"+e+".*?"+e}),o=(e,n,t)=>({className:e,begin:n,relevance:t}),l={$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},c={begin:"\\(",end:"\\)",contains:r,keywords:l,relevance:0};r.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s("'"),s('"'),n.CSS_NUMBER_MODE,{begin:"(url|data-uri)\\(",starts:{className:"string",end:"[\\)\\n]",excludeEnd:!0}},n.HEXCOLOR,c,o("variable","@@?[\\w-]+",10),o("variable","@\\{[\\w-]+\\}"),o("built_in","~?`[^`]*?`"),{className:"attribute",begin:"[\\w-]+\\s*:",end:":",returnBegin:!0,excludeEnd:!0},n.IMPORTANT);const d=r.concat({begin:/\{/,end:/\}/,contains:i}),g={beginKeywords:"when",endsWithParent:!0,contains:[{beginKeywords:"and not"}].concat(r)},u={begin:a+"\\s*:",returnBegin:!0,end:/[;}]/,relevance:0,contains:[{begin:/-(webkit|moz|ms|o)-/},n.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b",end:/(?=:)/,starts:{endsWithParent:!0,illegal:"[<=$]",relevance:0,contains:r}}]},b={className:"keyword",begin:"@(import|media|charset|font-face|(-[a-z]+-)?keyframes|supports|document|namespace|page|viewport|host)\\b",starts:{end:"[;{}]",keywords:l,returnEnd:!0,contains:r,relevance:0}},m={className:"variable",variants:[{begin:"@[\\w-]+\\s*:",relevance:15},{begin:"@[\\w-]+"}],starts:{end:"[;}]",returnEnd:!0,contains:d}},p={variants:[{begin:"[\\.#:&\\[>]",end:"[;{}]"},{begin:a,end:/\{/}],returnBegin:!0,returnEnd:!0,illegal:"[<='$\"]",relevance:0,contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,g,o("keyword","all\\b"),o("variable","@\\{[\\w-]+\\}"),{begin:"\\b("+ae.join("|")+")\\b",className:"selector-tag"},n.CSS_NUMBER_MODE,o("selector-tag",a,0),o("selector-id","#"+a),o("selector-class","\\."+a,0),o("selector-tag","&",0),n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-pseudo",begin:":("+re.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+se.join("|")+")"},{begin:/\(/,end:/\)/,relevance:0,contains:d},{begin:"!important"},n.FUNCTION_DISPATCH]},_={begin:`[\\w-]+:(:)?(${t.join("|")})`,returnBegin:!0,contains:[p]};return i.push(e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,m,_,u,p),{name:"Less",case_insensitive:!0,illegal:"[=>'/<($\"]",contains:i}},grmr_lua:e=>{const n="\\[=*\\[",t="\\]=*\\]",a={begin:n,end:t,contains:["self"]},i=[e.COMMENT("--(?!\\[=*\\[)","$"),e.COMMENT("--\\[=*\\[",t,{contains:[a],relevance:10})];return{name:"Lua",keywords:{$pattern:e.UNDERSCORE_IDENT_RE,literal:"true false nil",keyword:"and break do else elseif end for goto if in local not or repeat return then until while",built_in:"_G _ENV _VERSION __index __newindex __mode __call __metatable __tostring __len __gc __add __sub __mul __div __mod __pow __concat __unm __eq __lt __le assert collectgarbage dofile error getfenv getmetatable ipairs load loadfile loadstring module next pairs pcall print rawequal rawget rawset require select setfenv setmetatable tonumber tostring type unpack xpcall arg self coroutine resume yield status wrap create running debug getupvalue debug sethook getmetatable gethook setmetatable setlocal traceback setfenv getinfo setupvalue getlocal getregistry getfenv io lines write close flush open output type read stderr stdin input stdout popen tmpfile math log max acos huge ldexp pi cos tanh pow deg tan cosh sinh random randomseed frexp ceil floor rad abs sqrt modf asin min mod fmod log10 atan2 exp sin atan os exit setlocale date getenv difftime remove time clock tmpname rename execute package preload loadlib loaded loaders cpath config path seeall string sub upper len gfind rep find match char dump gmatch reverse byte format gsub lower table setn insert getn foreachi maxn foreach concat sort remove"},contains:i.concat([{className:"function",beginKeywords:"function",end:"\\)",contains:[e.inherit(e.TITLE_MODE,{begin:"([_a-zA-Z]\\w*\\.)*([_a-zA-Z]\\w*:)?[_a-zA-Z]\\w*"}),{className:"params",begin:"\\(",endsWithParent:!0,contains:i}].concat(i)},e.C_NUMBER_MODE,e.APOS_STRING_MODE,e.QUOTE_STRING_MODE,{className:"string",begin:n,end:t,contains:[a],relevance:5}])}},grmr_makefile:e=>{const n={className:"variable",variants:[{begin:"\\$\\("+e.UNDERSCORE_IDENT_RE+"\\)",contains:[e.BACKSLASH_ESCAPE]},{begin:/\$[@%{const n=e.regex,t=n.concat(/[A-Z_]/,n.optional(/[A-Z0-9_.-]*:/),/[A-Z0-9_.-]*/),a={className:"symbol",begin:/&[a-z]+;|&#[0-9]+;|&#x[a-f0-9]+;/},i={begin:/\s/,contains:[{className:"keyword",begin:/#?[a-z_][a-z1-9_-]+/,illegal:/\n/}]},r=e.inherit(i,{begin:/\(/,end:/\)/}),s=e.inherit(e.APOS_STRING_MODE,{className:"string"}),o=e.inherit(e.QUOTE_STRING_MODE,{className:"string"}),l={endsWithParent:!0,illegal:/`]+/}]}]}]};return{name:"HTML, XML",aliases:["html","xhtml","rss","atom","xjb","xsd","xsl","plist","wsf","svg"],case_insensitive:!0,contains:[{className:"meta",begin://,relevance:10,contains:[i,o,s,r,{begin:/\[/,end:/\]/,contains:[{className:"meta",begin://,contains:[i,r,o,s]}]}]},e.COMMENT(//,{relevance:10}),{begin://,relevance:10},a,{className:"meta",end:/\?>/,variants:[{begin:/<\?xml/,relevance:10,contains:[o]},{begin:/<\?[a-z][a-z0-9]+/}]},{className:"tag",begin:/)/,end:/>/,keywords:{name:"style"},contains:[l],starts:{end:/<\/style>/,returnEnd:!0,subLanguage:["css","xml"]}},{className:"tag",begin:/)/,end:/>/,keywords:{name:"script"},contains:[l],starts:{end:/<\/script>/,returnEnd:!0,subLanguage:["javascript","handlebars","xml"]}},{className:"tag",begin:/<>|<\/>/},{className:"tag",begin:n.concat(//,/>/,/\s/)))),end:/\/?>/,contains:[{className:"name",begin:t,relevance:0,starts:l}]},{className:"tag",begin:n.concat(/<\//,n.lookahead(n.concat(t,/>/))),contains:[{className:"name",begin:t,relevance:0},{begin:/>/,relevance:0,endsParent:!0}]}]}},grmr_markdown:e=>{const n={begin:/<\/?[A-Za-z_]/,end:">",subLanguage:"xml",relevance:0},t={variants:[{begin:/\[.+?\]\[.*?\]/,relevance:0},{begin:/\[.+?\]\(((data|javascript|mailto):|(?:http|ftp)s?:\/\/).*?\)/,relevance:2},{begin:e.regex.concat(/\[.+?\]\(/,/[A-Za-z][A-Za-z0-9+.-]*/,/:\/\/.*?\)/),relevance:2},{begin:/\[.+?\]\([./?&#].*?\)/,relevance:1},{begin:/\[.*?\]\(.*?\)/,relevance:0}],returnBegin:!0,contains:[{match:/\[(?=\])/},{className:"string",relevance:0,begin:"\\[",end:"\\]",excludeBegin:!0,returnEnd:!0},{className:"link",relevance:0,begin:"\\]\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0},{className:"symbol",relevance:0,begin:"\\]\\[",end:"\\]",excludeBegin:!0,excludeEnd:!0}]},a={className:"strong",contains:[],variants:[{begin:/_{2}/,end:/_{2}/},{begin:/\*{2}/,end:/\*{2}/}]},i={className:"emphasis",contains:[],variants:[{begin:/\*(?!\*)/,end:/\*/},{begin:/_(?!_)/,end:/_/,relevance:0}]},r=e.inherit(a,{contains:[]}),s=e.inherit(i,{contains:[]});a.contains.push(s),i.contains.push(r);let o=[n,t];return[a,i,r,s].forEach(e=>{e.contains=e.contains.concat(o)}),o=o.concat(a,i),{name:"Markdown",aliases:["md","mkdown","mkd"],contains:[{className:"section",variants:[{begin:"^#{1,6}",end:"$",contains:o},{begin:"(?=^.+?\\n[=-]{2,}$)",contains:[{begin:"^[=-]*$"},{begin:"^",end:"\\n",contains:o}]}]},n,{className:"bullet",begin:"^[ \t]*([*+-]|(\\d+\\.))(?=\\s+)",end:"\\s+",excludeEnd:!0},a,i,{className:"quote",begin:"^>\\s+",contains:o,end:"$"},{className:"code",variants:[{begin:"(`{3,})[^`](.|\\n)*?\\1`*[ ]*"},{begin:"(~{3,})[^~](.|\\n)*?\\1~*[ ]*"},{begin:"```",end:"```+[ ]*$"},{begin:"~~~",end:"~~~+[ ]*$"},{begin:"`.+?`"},{begin:"(?=^( {4}|\\t))",contains:[{begin:"^( {4}|\\t)",end:"(\\n)$"}],relevance:0}]},{begin:"^[-\\*]{3,}",end:"$"},t,{begin:/^\[[^\n]+\]:/,returnBegin:!0,contains:[{className:"symbol",begin:/\[/,end:/\]/,excludeBegin:!0,excludeEnd:!0},{className:"link",begin:/:\s*/,end:/$/,excludeBegin:!0}]}]}},grmr_objectivec:e=>{const n=/[a-zA-Z@][a-zA-Z0-9_]*/,t={$pattern:n,keyword:["@interface","@class","@protocol","@implementation"]};return{name:"Objective-C",aliases:["mm","objc","obj-c","obj-c++","objective-c++"],keywords:{"variable.language":["this","super"],$pattern:n,keyword:["while","export","sizeof","typedef","const","struct","for","union","volatile","static","mutable","if","do","return","goto","enum","else","break","extern","asm","case","default","register","explicit","typename","case","continue","inline","readonly","assign","readwrite","self","@synchronized","id","typeof","nonatomic","IBOutlet","IBAction","strong","weak","copy","in","out","inout","bycopy","byref","oneway","__strong","__weak","__block","__autoreleasing","@private","@protected","@public","@try","@property","@end","@throw","@catch","@finally","@autoreleasepool","@synthesize","@dynamic","@selector","@optional","@required","@encode","@package","@import","@defs","@compatibility_alias","__bridge","__bridge_transfer","__bridge_retained","__bridge_retain","__covariant","__contravariant","__kindof","_Nonnull","_Nullable","_Null_unspecified","__FUNCTION__","__PRETTY_FUNCTION__","__attribute__","getter","setter","retain","unsafe_unretained","nonnull","nullable","null_unspecified","null_resettable","class","instancetype","NS_DESIGNATED_INITIALIZER","NS_UNAVAILABLE","NS_REQUIRES_SUPER","NS_RETURNS_INNER_POINTER","NS_INLINE","NS_AVAILABLE","NS_DEPRECATED","NS_ENUM","NS_OPTIONS","NS_SWIFT_UNAVAILABLE","NS_ASSUME_NONNULL_BEGIN","NS_ASSUME_NONNULL_END","NS_REFINED_FOR_SWIFT","NS_SWIFT_NAME","NS_SWIFT_NOTHROW","NS_DURING","NS_HANDLER","NS_ENDHANDLER","NS_VALUERETURN","NS_VOIDRETURN"],literal:["false","true","FALSE","TRUE","nil","YES","NO","NULL"],built_in:["dispatch_once_t","dispatch_queue_t","dispatch_sync","dispatch_async","dispatch_once"],type:["int","float","char","unsigned","signed","short","long","double","wchar_t","unichar","void","bool","BOOL","id|0","_Bool"]},illegal:"/,end:/$/,illegal:"\\n"},e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{className:"class",begin:"("+t.keyword.join("|")+")\\b",end:/(\{|$)/,excludeEnd:!0,keywords:t,contains:[e.UNDERSCORE_TITLE_MODE]},{begin:"\\."+e.UNDERSCORE_IDENT_RE,relevance:0}]}},grmr_perl:e=>{const n=e.regex,t=/[dualxmsipngr]{0,12}/,a={$pattern:/[\w.]+/,keyword:"abs accept alarm and atan2 bind binmode bless break caller chdir chmod chomp chop chown chr chroot close closedir connect continue cos crypt dbmclose dbmopen defined delete die do dump each else elsif endgrent endhostent endnetent endprotoent endpwent endservent eof eval exec exists exit exp fcntl fileno flock for foreach fork format formline getc getgrent getgrgid getgrnam gethostbyaddr gethostbyname gethostent getlogin getnetbyaddr getnetbyname getnetent getpeername getpgrp getpriority getprotobyname getprotobynumber getprotoent getpwent getpwnam getpwuid getservbyname getservbyport getservent getsockname getsockopt given glob gmtime goto grep gt hex if index int ioctl join keys kill last lc lcfirst length link listen local localtime log lstat lt ma map mkdir msgctl msgget msgrcv msgsnd my ne next no not oct open opendir or ord our pack package pipe pop pos print printf prototype push q|0 qq quotemeta qw qx rand read readdir readline readlink readpipe recv redo ref rename require reset return reverse rewinddir rindex rmdir say scalar seek seekdir select semctl semget semop send setgrent sethostent setnetent setpgrp setpriority setprotoent setpwent setservent setsockopt shift shmctl shmget shmread shmwrite shutdown sin sleep socket socketpair sort splice split sprintf sqrt srand stat state study sub substr symlink syscall sysopen sysread sysseek system syswrite tell telldir tie tied time times tr truncate uc ucfirst umask undef unless unlink unpack unshift untie until use utime values vec wait waitpid wantarray warn when while write x|0 xor y|0"},i={className:"subst",begin:"[$@]\\{",end:"\\}",keywords:a},r={begin:/->\{/,end:/\}/},s={variants:[{begin:/\$\d/},{begin:n.concat(/[$%@](\^\w\b|#\w+(::\w+)*|\{\w+\}|\w+(::\w*)*)/,"(?![A-Za-z])(?![@$%])")},{begin:/[$%@][^\s\w{]/,relevance:0}]},o=[e.BACKSLASH_ESCAPE,i,s],l=[/!/,/\//,/\|/,/\?/,/'/,/"/,/#/],c=(e,a,i="\\1")=>{const r="\\1"===i?i:n.concat(i,a);return n.concat(n.concat("(?:",e,")"),a,/(?:\\.|[^\\\/])*?/,r,/(?:\\.|[^\\\/])*?/,i,t)},d=(e,a,i)=>n.concat(n.concat("(?:",e,")"),a,/(?:\\.|[^\\\/])*?/,i,t),g=[s,e.HASH_COMMENT_MODE,e.COMMENT(/^=\w/,/=cut/,{endsWithParent:!0}),r,{className:"string",contains:o,variants:[{begin:"q[qwxr]?\\s*\\(",end:"\\)",relevance:5},{begin:"q[qwxr]?\\s*\\[",end:"\\]",relevance:5},{begin:"q[qwxr]?\\s*\\{",end:"\\}",relevance:5},{begin:"q[qwxr]?\\s*\\|",end:"\\|",relevance:5},{begin:"q[qwxr]?\\s*<",end:">",relevance:5},{begin:"qw\\s+q",end:"q",relevance:5},{begin:"'",end:"'",contains:[e.BACKSLASH_ESCAPE]},{begin:'"',end:'"'},{begin:"`",end:"`",contains:[e.BACKSLASH_ESCAPE]},{begin:/\{\w+\}/,relevance:0},{begin:"-?\\w+\\s*=>",relevance:0}]},{className:"number",begin:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",relevance:0},{begin:"(\\/\\/|"+e.RE_STARTERS_RE+"|\\b(split|return|print|reverse|grep)\\b)\\s*",keywords:"split return print reverse grep",relevance:0,contains:[e.HASH_COMMENT_MODE,{className:"regexp",variants:[{begin:c("s|tr|y",n.either(...l,{capture:!0}))},{begin:c("s|tr|y","\\(","\\)")},{begin:c("s|tr|y","\\[","\\]")},{begin:c("s|tr|y","\\{","\\}")}],relevance:2},{className:"regexp",variants:[{begin:/(m|qr)\/\//,relevance:0},{begin:d("(?:m|qr)?",/\//,/\//)},{begin:d("m|qr",n.either(...l,{capture:!0}),/\1/)},{begin:d("m|qr",/\(/,/\)/)},{begin:d("m|qr",/\[/,/\]/)},{begin:d("m|qr",/\{/,/\}/)}]}]},{className:"function",beginKeywords:"sub",end:"(\\s*\\(.*?\\))?[;{]",excludeEnd:!0,relevance:5,contains:[e.TITLE_MODE]},{begin:"-\\w\\b",relevance:0},{begin:"^__DATA__$",end:"^__END__$",subLanguage:"mojolicious",contains:[{begin:"^@@.*",end:"$",className:"comment"}]}];return i.contains=g,r.contains=g,{name:"Perl",aliases:["pl","pm"],keywords:a,contains:g}},grmr_php:e=>{const n=e.regex,t=/(?![A-Za-z0-9])(?![$])/,a=n.concat(/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/,t),i=n.concat(/(\\?[A-Z][a-z0-9_\x7f-\xff]+|\\?[A-Z]+(?=[A-Z][a-z0-9_\x7f-\xff])){1,}/,t),r={scope:"variable",match:"\\$+"+a},s={scope:"subst",variants:[{begin:/\$\w+/},{begin:/\{\$/,end:/\}/}]},o=e.inherit(e.APOS_STRING_MODE,{illegal:null}),l="[ \t\n]",c={scope:"string",variants:[e.inherit(e.QUOTE_STRING_MODE,{illegal:null,contains:e.QUOTE_STRING_MODE.contains.concat(s)}),o,e.END_SAME_AS_BEGIN({begin:/<<<[ \t]*(\w+)\n/,end:/[ \t]*(\w+)\b/,contains:e.QUOTE_STRING_MODE.contains.concat(s)})]},d={scope:"number",variants:[{begin:"\\b0[bB][01]+(?:_[01]+)*\\b"},{begin:"\\b0[oO][0-7]+(?:_[0-7]+)*\\b"},{begin:"\\b0[xX][\\da-fA-F]+(?:_[\\da-fA-F]+)*\\b"},{begin:"(?:\\b\\d+(?:_\\d+)*(\\.(?:\\d+(?:_\\d+)*))?|\\B\\.\\d+)(?:[eE][+-]?\\d+)?"}],relevance:0},g=["false","null","true"],u=["__CLASS__","__DIR__","__FILE__","__FUNCTION__","__COMPILER_HALT_OFFSET__","__LINE__","__METHOD__","__NAMESPACE__","__TRAIT__","die","echo","exit","include","include_once","print","require","require_once","array","abstract","and","as","binary","bool","boolean","break","callable","case","catch","class","clone","const","continue","declare","default","do","double","else","elseif","empty","enddeclare","endfor","endforeach","endif","endcase","endwhile","enum","eval","extends","final","finally","float","for","foreach","from","global","goto","if","implements","instanceof","insteadof","int","integer","interface","isset","iterable","list","match|0","mixed","new","never","object","or","private","protected","public","readonly","real","return","string","case","throw","trait","try","unset","use","var","void","while","xor","yield"],b=["Error|0","AppendIterator","ArgumentCountError","ArithmeticError","ArrayIterator","ArrayObject","AssertionError","BadFunctionCallException","BadMethodCallException","CachingIterator","CallbackFilterIterator","CompileError","Countable","DirectoryIterator","DivisionByZeroError","DomainException","EmptyIterator","ErrorException","Exception","FilesystemIterator","FilterIterator","GlobIterator","InfiniteIterator","InvalidArgumentException","IteratorIterator","LengthException","LimitIterator","LogicException","MultipleIterator","NoRewindIterator","OutOfBoundsException","OutOfRangeException","OuterIterator","OverflowException","ParentIterator","ParseError","RangeException","RecursiveArrayIterator","RecursiveCachingIterator","RecursiveCallbackFilterIterator","RecursiveDirectoryIterator","RecursiveFilterIterator","RecursiveIterator","RecursiveIteratorIterator","RecursiveRegexIterator","RecursiveTreeIterator","RegexIterator","RuntimeException","SeekableIterator","SplDoublyLinkedList","SplFileInfo","SplFileObject","SplFixedArray","SplHeap","SplMaxHeap","SplMinHeap","SplObjectStorage","SplObserver","SplPriorityQueue","SplQueue","SplStack","SplSubject","SplTempFileObject","TypeError","UnderflowException","UnexpectedValueException","UnhandledMatchError","ArrayAccess","BackedEnum","Closure","Fiber","Generator","Iterator","IteratorAggregate","Serializable","Stringable","Throwable","Traversable","UnitEnum","WeakReference","WeakMap","Directory","__PHP_Incomplete_Class","parent","php_user_filter","self","static","stdClass"],m={keyword:u,literal:(e=>{const n=[];return e.forEach(e=>{n.push(e),e.toLowerCase()===e?n.push(e.toUpperCase()):n.push(e.toLowerCase())}),n})(g),built_in:b},p=e=>e.map(e=>e.replace(/\|\d+$/,"")),_={variants:[{match:[/new/,n.concat(l,"+"),n.concat("(?!",p(b).join("\\b|"),"\\b)"),i],scope:{1:"keyword",4:"title.class"}}]},h=n.concat(a,"\\b(?!\\()"),f={variants:[{match:[n.concat(/::/,n.lookahead(/(?!class\b)/)),h],scope:{2:"variable.constant"}},{match:[/::/,/class/],scope:{2:"variable.language"}},{match:[i,n.concat(/::/,n.lookahead(/(?!class\b)/)),h],scope:{1:"title.class",3:"variable.constant"}},{match:[i,n.concat("::",n.lookahead(/(?!class\b)/))],scope:{1:"title.class"}},{match:[i,/::/,/class/],scope:{1:"title.class",3:"variable.language"}}]},E={scope:"attr",match:n.concat(a,n.lookahead(":"),n.lookahead(/(?!::)/))},y={relevance:0,begin:/\(/,end:/\)/,keywords:m,contains:[E,r,f,e.C_BLOCK_COMMENT_MODE,c,d,_]},w={relevance:0,match:[/\b/,n.concat("(?!fn\\b|function\\b|",p(u).join("\\b|"),"|",p(b).join("\\b|"),"\\b)"),a,n.concat(l,"*"),n.lookahead(/(?=\()/)],scope:{3:"title.function.invoke"},contains:[y]};y.contains.push(w);const N=[E,f,e.C_BLOCK_COMMENT_MODE,c,d,_];return{case_insensitive:!1,keywords:m,contains:[{begin:n.concat(/#\[\s*/,i),beginScope:"meta",end:/]/,endScope:"meta",keywords:{literal:g,keyword:["new","array"]},contains:[{begin:/\[/,end:/]/,keywords:{literal:g,keyword:["new","array"]},contains:["self",...N]},...N,{scope:"meta",match:i}]},e.HASH_COMMENT_MODE,e.COMMENT("//","$"),e.COMMENT("/\\*","\\*/",{contains:[{scope:"doctag",match:"@[A-Za-z]+"}]}),{match:/__halt_compiler\(\);/,keywords:"__halt_compiler",starts:{scope:"comment",end:e.MATCH_NOTHING_RE,contains:[{match:/\?>/,scope:"meta",endsParent:!0}]}},{scope:"meta",variants:[{begin:/<\?php/,relevance:10},{begin:/<\?=/},{begin:/<\?/,relevance:.1},{begin:/\?>/}]},{scope:"variable.language",match:/\$this\b/},r,w,f,{match:[/const/,/\s/,a],scope:{1:"keyword",3:"variable.constant"}},_,{scope:"function",relevance:0,beginKeywords:"fn function",end:/[;{]/,excludeEnd:!0,illegal:"[$%\\[]",contains:[{beginKeywords:"use"},e.UNDERSCORE_TITLE_MODE,{begin:"=>",endsParent:!0},{scope:"params",begin:"\\(",end:"\\)",excludeBegin:!0,excludeEnd:!0,keywords:m,contains:["self",r,f,e.C_BLOCK_COMMENT_MODE,c,d]}]},{scope:"class",variants:[{beginKeywords:"enum",illegal:/[($"]/},{beginKeywords:"class interface trait",illegal:/[:($"]/}],relevance:0,end:/\{/,excludeEnd:!0,contains:[{beginKeywords:"extends implements"},e.UNDERSCORE_TITLE_MODE]},{beginKeywords:"namespace",relevance:0,end:";",illegal:/[.']/,contains:[e.inherit(e.UNDERSCORE_TITLE_MODE,{scope:"title.class"})]},{beginKeywords:"use",relevance:0,end:";",contains:[{match:/\b(as|const|function)\b/,scope:"keyword"},e.UNDERSCORE_TITLE_MODE]},c,d]}},grmr_php_template:e=>({name:"PHP template",subLanguage:"xml",contains:[{begin:/<\?(php|=)?/,end:/\?>/,subLanguage:"php",contains:[{begin:"/\\*",end:"\\*/",skip:!0},{begin:'b"',end:'"',skip:!0},{begin:"b'",end:"'",skip:!0},e.inherit(e.APOS_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0}),e.inherit(e.QUOTE_STRING_MODE,{illegal:null,className:null,contains:null,skip:!0})]}]}),grmr_plaintext:e=>({name:"Plain text",aliases:["text","txt"],disableAutodetect:!0}),grmr_python:e=>{const n=e.regex,t=/[\p{XID_Start}_]\p{XID_Continue}*/u,a=["and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal|10","not","or","pass","raise","return","try","while","with","yield"],i={$pattern:/[A-Za-z]\w+|__\w+__/,keyword:a,built_in:["__import__","abs","all","any","ascii","bin","bool","breakpoint","bytearray","bytes","callable","chr","classmethod","compile","complex","delattr","dict","dir","divmod","enumerate","eval","exec","filter","float","format","frozenset","getattr","globals","hasattr","hash","help","hex","id","input","int","isinstance","issubclass","iter","len","list","locals","map","max","memoryview","min","next","object","oct","open","ord","pow","print","property","range","repr","reversed","round","set","setattr","slice","sorted","staticmethod","str","sum","super","tuple","type","vars","zip"],literal:["__debug__","Ellipsis","False","None","NotImplemented","True"],type:["Any","Callable","Coroutine","Dict","List","Literal","Generic","Optional","Sequence","Set","Tuple","Type","Union"]},r={className:"meta",begin:/^(>>>|\.\.\.) /},s={className:"subst",begin:/\{/,end:/\}/,keywords:i,illegal:/#/},o={begin:/\{\{/,relevance:0},l={className:"string",contains:[e.BACKSLASH_ESCAPE],variants:[{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,r],relevance:10},{begin:/([uU]|[bB]|[rR]|[bB][rR]|[rR][bB])?"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,r],relevance:10},{begin:/([fF][rR]|[rR][fF]|[fF])'''/,end:/'''/,contains:[e.BACKSLASH_ESCAPE,r,o,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"""/,end:/"""/,contains:[e.BACKSLASH_ESCAPE,r,o,s]},{begin:/([uU]|[rR])'/,end:/'/,relevance:10},{begin:/([uU]|[rR])"/,end:/"/,relevance:10},{begin:/([bB]|[bB][rR]|[rR][bB])'/,end:/'/},{begin:/([bB]|[bB][rR]|[rR][bB])"/,end:/"/},{begin:/([fF][rR]|[rR][fF]|[fF])'/,end:/'/,contains:[e.BACKSLASH_ESCAPE,o,s]},{begin:/([fF][rR]|[rR][fF]|[fF])"/,end:/"/,contains:[e.BACKSLASH_ESCAPE,o,s]},e.APOS_STRING_MODE,e.QUOTE_STRING_MODE]},c="[0-9](_?[0-9])*",d=`(\\b(${c}))?\\.(${c})|\\b(${c})\\.`,g="\\b|"+a.join("|"),u={className:"number",relevance:0,variants:[{begin:`(\\b(${c})|(${d}))[eE][+-]?(${c})[jJ]?(?=${g})`},{begin:`(${d})[jJ]?`},{begin:`\\b([1-9](_?[0-9])*|0+(_?0)*)[lLjJ]?(?=${g})`},{begin:`\\b0[bB](_?[01])+[lL]?(?=${g})`},{begin:`\\b0[oO](_?[0-7])+[lL]?(?=${g})`},{begin:`\\b0[xX](_?[0-9a-fA-F])+[lL]?(?=${g})`},{begin:`\\b(${c})[jJ](?=${g})`}]},b={className:"comment",begin:n.lookahead(/# type:/),end:/$/,keywords:i,contains:[{begin:/# type:/},{begin:/#/,end:/\b\B/,endsWithParent:!0}]},m={className:"params",variants:[{className:"",begin:/\(\s*\)/,skip:!0},{begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,keywords:i,contains:["self",r,u,l,e.HASH_COMMENT_MODE]}]};return s.contains=[l,u,r],{name:"Python",aliases:["py","gyp","ipython"],unicodeRegex:!0,keywords:i,illegal:/(<\/|->|\?)|=>/,contains:[r,u,{begin:/\bself\b/},{beginKeywords:"if",relevance:0},l,b,e.HASH_COMMENT_MODE,{match:[/\bdef/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[m]},{variants:[{match:[/\bclass/,/\s+/,t,/\s*/,/\(\s*/,t,/\s*\)/]},{match:[/\bclass/,/\s+/,t]}],scope:{1:"keyword",3:"title.class",6:"title.class.inherited"}},{className:"meta",begin:/^[\t ]*@/,end:/(?=#)|$/,contains:[u,m,l]}]}},grmr_python_repl:e=>({aliases:["pycon"],contains:[{className:"meta.prompt",starts:{end:/ |$/,starts:{end:"$",subLanguage:"python"}},variants:[{begin:/^>>>(?=[ ]|$)/},{begin:/^\.\.\.(?=[ ]|$)/}]}]}),grmr_r:e=>{const n=e.regex,t=/(?:(?:[a-zA-Z]|\.[._a-zA-Z])[._a-zA-Z0-9]*)|\.(?!\d)/,a=n.either(/0[xX][0-9a-fA-F]+\.[0-9a-fA-F]*[pP][+-]?\d+i?/,/0[xX][0-9a-fA-F]+(?:[pP][+-]?\d+)?[Li]?/,/(?:\d+(?:\.\d*)?|\.\d+)(?:[eE][+-]?\d+)?[Li]?/),i=/[=!<>:]=|\|\||&&|:::?|<-|<<-|->>|->|\|>|[-+*\/?!$&|:<=>@^~]|\*\*/,r=n.either(/[()]/,/[{}]/,/\[\[/,/[[\]]/,/\\/,/,/);return{name:"R",keywords:{$pattern:t,keyword:"function if in break next repeat else for while",literal:"NULL NA TRUE FALSE Inf NaN NA_integer_|10 NA_real_|10 NA_character_|10 NA_complex_|10",built_in:"LETTERS letters month.abb month.name pi T F abs acos acosh all any anyNA Arg as.call as.character as.complex as.double as.environment as.integer as.logical as.null.default as.numeric as.raw asin asinh atan atanh attr attributes baseenv browser c call ceiling class Conj cos cosh cospi cummax cummin cumprod cumsum digamma dim dimnames emptyenv exp expression floor forceAndCall gamma gc.time globalenv Im interactive invisible is.array is.atomic is.call is.character is.complex is.double is.environment is.expression is.finite is.function is.infinite is.integer is.language is.list is.logical is.matrix is.na is.name is.nan is.null is.numeric is.object is.pairlist is.raw is.recursive is.single is.symbol lazyLoadDBfetch length lgamma list log max min missing Mod names nargs nzchar oldClass on.exit pos.to.env proc.time prod quote range Re rep retracemem return round seq_along seq_len seq.int sign signif sin sinh sinpi sqrt standardGeneric substitute sum case tan tanh tanpi tracemem trigamma trunc unclass untracemem UseMethod xtfrm"},contains:[e.COMMENT(/#'/,/$/,{contains:[{scope:"doctag",match:/@examples/,starts:{end:n.lookahead(n.either(/\n^#'\s*(?=@[a-zA-Z]+)/,/\n^(?!#')/)),endsParent:!0}},{scope:"doctag",begin:"@param",end:/$/,contains:[{scope:"variable",variants:[{match:t},{match:/`(?:\\.|[^`\\])+`/}],endsParent:!0}]},{scope:"doctag",match:/@[a-zA-Z]+/},{scope:"keyword",match:/\\[a-zA-Z]+/}]}),e.HASH_COMMENT_MODE,{scope:"string",contains:[e.BACKSLASH_ESCAPE],variants:[e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\(/,end:/\)(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\{/,end:/\}(-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]"(-*)\[/,end:/\](-*)"/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\(/,end:/\)(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\{/,end:/\}(-*)'/}),e.END_SAME_AS_BEGIN({begin:/[rR]'(-*)\[/,end:/\](-*)'/}),{begin:'"',end:'"',relevance:0},{begin:"'",end:"'",relevance:0}]},{relevance:0,variants:[{scope:{1:"operator",2:"number"},match:[i,a]},{scope:{1:"operator",2:"number"},match:[/%[^%]*%/,a]},{scope:{1:"punctuation",2:"number"},match:[r,a]},{scope:{2:"number"},match:[/[^a-zA-Z0-9._]|^/,a]}]},{scope:{3:"operator"},match:[t,/\s+/,/<-/,/\s+/]},{scope:"operator",relevance:0,variants:[{match:i},{match:/%[^%]*%/}]},{scope:"punctuation",relevance:0,match:r},{begin:"`",end:"`",contains:[{begin:/\\./}]}]}},grmr_ruby:e=>{const n=e.regex,t="([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)",a=n.either(/\b([A-Z]+[a-z0-9]+)+/,/\b([A-Z]+[a-z0-9]+)+[A-Z]+/),i=n.concat(a,/(::\w+)*/),r={"variable.constant":["__FILE__","__LINE__"],"variable.language":["self","super"],keyword:["alias","and","attr_accessor","attr_reader","attr_writer","begin","BEGIN","break","case","class","defined","do","else","elsif","end","END","ensure","for","if","in","include","module","next","not","or","redo","require","rescue","retry","return","then","undef","unless","until","when","while","yield"],built_in:["proc","lambda"],literal:["true","false","nil"]},s={className:"doctag",begin:"@[A-Za-z]+"},o={begin:"#<",end:">"},l=[e.COMMENT("#","$",{contains:[s]}),e.COMMENT("^=begin","^=end",{contains:[s],relevance:10}),e.COMMENT("^__END__",e.MATCH_NOTHING_RE)],c={className:"subst",begin:/#\{/,end:/\}/,keywords:r},d={className:"string",contains:[e.BACKSLASH_ESCAPE,c],variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/`/,end:/`/},{begin:/%[qQwWx]?\(/,end:/\)/},{begin:/%[qQwWx]?\[/,end:/\]/},{begin:/%[qQwWx]?\{/,end:/\}/},{begin:/%[qQwWx]?/},{begin:/%[qQwWx]?\//,end:/\//},{begin:/%[qQwWx]?%/,end:/%/},{begin:/%[qQwWx]?-/,end:/-/},{begin:/%[qQwWx]?\|/,end:/\|/},{begin:/\B\?(\\\d{1,3})/},{begin:/\B\?(\\x[A-Fa-f0-9]{1,2})/},{begin:/\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/},{begin:/\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/},{begin:/\B\?\\(c|C-)[\x20-\x7e]/},{begin:/\B\?\\?\S/},{begin:n.concat(/<<[-~]?'?/,n.lookahead(/(\w+)(?=\W)[^\n]*\n(?:[^\n]*\n)*?\s*\1\b/)),contains:[e.END_SAME_AS_BEGIN({begin:/(\w+)/,end:/(\w+)/,contains:[e.BACKSLASH_ESCAPE,c]})]}]},g="[0-9](_?[0-9])*",u={className:"number",relevance:0,variants:[{begin:`\\b([1-9](_?[0-9])*|0)(\\.(${g}))?([eE][+-]?(${g})|r)?i?\\b`},{begin:"\\b0[dD][0-9](_?[0-9])*r?i?\\b"},{begin:"\\b0[bB][0-1](_?[0-1])*r?i?\\b"},{begin:"\\b0[oO][0-7](_?[0-7])*r?i?\\b"},{begin:"\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"},{begin:"\\b0(_?[0-7])+r?i?\\b"}]},b={variants:[{match:/\(\)/},{className:"params",begin:/\(/,end:/(?=\))/,excludeBegin:!0,endsParent:!0,keywords:r}]},m=[d,{variants:[{match:[/class\s+/,i,/\s+<\s+/,i]},{match:[/class\s+/,i]}],scope:{2:"title.class",4:"title.class.inherited"},keywords:r},{relevance:0,match:[i,/\.new[ (]/],scope:{1:"title.class"}},{relevance:0,match:/\b[A-Z][A-Z_0-9]+\b/,className:"variable.constant"},{match:[/def/,/\s+/,t],scope:{1:"keyword",3:"title.function"},contains:[b]},{begin:e.IDENT_RE+"::"},{className:"symbol",begin:e.UNDERSCORE_IDENT_RE+"(!|\\?)?:",relevance:0},{className:"symbol",begin:":(?!\\s)",contains:[d,{begin:t}],relevance:0},u,{className:"variable",begin:"(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])(?![A-Za-z])(?![@$?'])"},{className:"params",begin:/\|/,end:/\|/,excludeBegin:!0,excludeEnd:!0,relevance:0,keywords:r},{begin:"("+e.RE_STARTERS_RE+"|unless)\\s*",keywords:"unless",contains:[{className:"regexp",contains:[e.BACKSLASH_ESCAPE,c],illegal:/\n/,variants:[{begin:"/",end:"/[a-z]*"},{begin:/%r\{/,end:/\}[a-z]*/},{begin:"%r\\(",end:"\\)[a-z]*"},{begin:"%r!",end:"![a-z]*"},{begin:"%r\\[",end:"\\][a-z]*"}]}].concat(o,l),relevance:0}].concat(o,l);c.contains=m,b.contains=m;const p=[{begin:/^\s*=>/,starts:{end:"$",contains:m}},{className:"meta.prompt",begin:"^([>?]>|[\\w#]+\\(\\w+\\):\\d+:\\d+[>*]|(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>)(?=[ ])",starts:{end:"$",keywords:r,contains:m}}];return l.unshift(o),{name:"Ruby",aliases:["rb","gemspec","podspec","thor","irb"],keywords:r,illegal:/\/\*/,contains:[e.SHEBANG({binary:"ruby"})].concat(p).concat(l).concat(m)}},grmr_rust:e=>{const n=e.regex,t={className:"title.function.invoke",relevance:0,begin:n.concat(/\b/,/(?!let\b)/,e.IDENT_RE,n.lookahead(/\s*\(/))},a="([ui](8|16|32|64|128|size)|f(32|64))?",i=["drop ","Copy","Send","Sized","Sync","Drop","Fn","FnMut","FnOnce","ToOwned","Clone","Debug","PartialEq","PartialOrd","Eq","Ord","AsRef","AsMut","Into","From","Default","Iterator","Extend","IntoIterator","DoubleEndedIterator","ExactSizeIterator","SliceConcatExt","ToString","assert!","assert_eq!","bitflags!","bytes!","cfg!","col!","concat!","concat_idents!","debug_assert!","debug_assert_eq!","env!","panic!","file!","format!","format_args!","include_bin!","include_str!","line!","local_data_key!","module_path!","option_env!","print!","println!","select!","stringify!","try!","unimplemented!","unreachable!","vec!","write!","writeln!","macro_rules!","assert_ne!","debug_assert_ne!"];return{name:"Rust",aliases:["rs"],keywords:{$pattern:e.IDENT_RE+"!?",type:["i8","i16","i32","i64","i128","isize","u8","u16","u32","u64","u128","usize","f32","f64","str","char","bool","Box","Option","Result","String","Vec"],keyword:["abstract","as","async","await","become","box","break","const","continue","crate","do","dyn","else","enum","extern","false","final","fn","for","if","impl","in","let","loop","macro","match","mod","move","mut","override","priv","pub","ref","return","self","Self","static","struct","super","trait","true","try","type","typeof","unsafe","unsized","use","virtual","where","while","yield"],literal:["true","false","Some","None","Ok","Err"],built_in:i},illegal:""},t]}},grmr_scss:e=>{const n=te(e),t=se,a=re,i="@[a-z-]+",r={className:"variable",begin:"(\\$[a-zA-Z-][a-zA-Z0-9_-]*)\\b",relevance:0};return{name:"SCSS",case_insensitive:!0,illegal:"[=/|']",contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,n.CSS_NUMBER_MODE,{className:"selector-id",begin:"#[A-Za-z0-9_-]+",relevance:0},{className:"selector-class",begin:"\\.[A-Za-z0-9_-]+",relevance:0},n.ATTRIBUTE_SELECTOR_MODE,{className:"selector-tag",begin:"\\b("+ae.join("|")+")\\b",relevance:0},{className:"selector-pseudo",begin:":("+a.join("|")+")"},{className:"selector-pseudo",begin:":(:)?("+t.join("|")+")"},r,{begin:/\(/,end:/\)/,contains:[n.CSS_NUMBER_MODE]},n.CSS_VARIABLE,{className:"attribute",begin:"\\b("+oe.join("|")+")\\b"},{begin:"\\b(whitespace|wait|w-resize|visible|vertical-text|vertical-ideographic|uppercase|upper-roman|upper-alpha|underline|transparent|top|thin|thick|text|text-top|text-bottom|tb-rl|table-header-group|table-footer-group|sw-resize|super|strict|static|square|solid|small-caps|separate|se-resize|scroll|s-resize|rtl|row-resize|ridge|right|repeat|repeat-y|repeat-x|relative|progress|pointer|overline|outside|outset|oblique|nowrap|not-allowed|normal|none|nw-resize|no-repeat|no-drop|newspaper|ne-resize|n-resize|move|middle|medium|ltr|lr-tb|lowercase|lower-roman|lower-alpha|loose|list-item|line|line-through|line-edge|lighter|left|keep-all|justify|italic|inter-word|inter-ideograph|inside|inset|inline|inline-block|inherit|inactive|ideograph-space|ideograph-parenthesis|ideograph-numeric|ideograph-alpha|horizontal|hidden|help|hand|groove|fixed|ellipsis|e-resize|double|dotted|distribute|distribute-space|distribute-letter|distribute-all-lines|disc|disabled|default|decimal|dashed|crosshair|collapse|col-resize|circle|char|center|capitalize|break-word|break-all|bottom|both|bolder|bold|block|bidi-override|below|baseline|auto|always|all-scroll|absolute|table|table-cell)\\b"},{begin:/:/,end:/[;}{]/,contains:[n.BLOCK_COMMENT,r,n.HEXCOLOR,n.CSS_NUMBER_MODE,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.IMPORTANT]},{begin:"@(page|font-face)",keywords:{$pattern:i,keyword:"@page @font-face"}},{begin:"@",end:"[{;]",returnBegin:!0,keywords:{$pattern:/[a-z-]+/,keyword:"and or not only",attribute:ie.join(" ")},contains:[{begin:i,className:"keyword"},{begin:/[a-z-]+(?=:)/,className:"attribute"},r,e.QUOTE_STRING_MODE,e.APOS_STRING_MODE,n.HEXCOLOR,n.CSS_NUMBER_MODE]},n.FUNCTION_DISPATCH]}},grmr_shell:e=>({name:"Shell Session",aliases:["console","shellsession"],contains:[{className:"meta.prompt",begin:/^\s{0,3}[/~\w\d[\]()@-]*[>%$#][ ]?/,starts:{end:/[^\\](?=\s*$)/,subLanguage:"bash"}}]}),grmr_sql:e=>{const n=e.regex,t=e.COMMENT("--","$"),a=["true","false","unknown"],i=["bigint","binary","blob","boolean","char","character","clob","date","dec","decfloat","decimal","float","int","integer","interval","nchar","nclob","national","numeric","real","row","smallint","time","timestamp","varchar","varying","varbinary"],r=["abs","acos","array_agg","asin","atan","avg","cast","ceil","ceiling","coalesce","corr","cos","cosh","count","covar_pop","covar_samp","cume_dist","dense_rank","deref","element","exp","extract","first_value","floor","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","last_value","lead","listagg","ln","log","log10","lower","max","min","mod","nth_value","ntile","nullif","percent_rank","percentile_cont","percentile_disc","position","position_regex","power","rank","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","row_number","sin","sinh","sqrt","stddev_pop","stddev_samp","substring","substring_regex","sum","tan","tanh","translate","translate_regex","treat","trim","trim_array","unnest","upper","value_of","var_pop","var_samp","width_bucket"],s=["create table","insert into","primary key","foreign key","not null","alter table","add constraint","grouping sets","on overflow","character set","respect nulls","ignore nulls","nulls first","nulls last","depth first","breadth first"],o=r,l=["abs","acos","all","allocate","alter","and","any","are","array","array_agg","array_max_cardinality","as","asensitive","asin","asymmetric","at","atan","atomic","authorization","avg","begin","begin_frame","begin_partition","between","bigint","binary","blob","boolean","both","by","call","called","cardinality","cascaded","case","cast","ceil","ceiling","char","char_length","character","character_length","check","classifier","clob","close","coalesce","collate","collect","column","commit","condition","connect","constraint","contains","convert","copy","corr","corresponding","cos","cosh","count","covar_pop","covar_samp","create","cross","cube","cume_dist","current","current_catalog","current_date","current_default_transform_group","current_path","current_role","current_row","current_schema","current_time","current_timestamp","current_path","current_role","current_transform_group_for_type","current_user","cursor","cycle","date","day","deallocate","dec","decimal","decfloat","declare","default","define","delete","dense_rank","deref","describe","deterministic","disconnect","distinct","double","drop","dynamic","each","element","else","empty","end","end_frame","end_partition","end-exec","equals","escape","every","except","exec","execute","exists","exp","external","extract","false","fetch","filter","first_value","float","floor","for","foreign","frame_row","free","from","full","function","fusion","get","global","grant","group","grouping","groups","having","hold","hour","identity","in","indicator","initial","inner","inout","insensitive","insert","int","integer","intersect","intersection","interval","into","is","join","json_array","json_arrayagg","json_exists","json_object","json_objectagg","json_query","json_table","json_table_primitive","json_value","lag","language","large","last_value","lateral","lead","leading","left","like","like_regex","listagg","ln","local","localtime","localtimestamp","log","log10","lower","match","match_number","match_recognize","matches","max","member","merge","method","min","minute","mod","modifies","module","month","multiset","national","natural","nchar","nclob","new","no","none","normalize","not","nth_value","ntile","null","nullif","numeric","octet_length","occurrences_regex","of","offset","old","omit","on","one","only","open","or","order","out","outer","over","overlaps","overlay","parameter","partition","pattern","per","percent","percent_rank","percentile_cont","percentile_disc","period","portion","position","position_regex","power","precedes","precision","prepare","primary","procedure","ptf","range","rank","reads","real","recursive","ref","references","referencing","regr_avgx","regr_avgy","regr_count","regr_intercept","regr_r2","regr_slope","regr_sxx","regr_sxy","regr_syy","release","result","return","returns","revoke","right","rollback","rollup","row","row_number","rows","running","savepoint","scope","scroll","search","second","seek","select","sensitive","session_user","set","show","similar","sin","sinh","skip","smallint","some","specific","specifictype","sql","sqlexception","sqlstate","sqlwarning","sqrt","start","static","stddev_pop","stddev_samp","submultiset","subset","substring","substring_regex","succeeds","sum","symmetric","system","system_time","system_user","table","tablesample","tan","tanh","then","time","timestamp","timezone_hour","timezone_minute","to","trailing","translate","translate_regex","translation","treat","trigger","trim","trim_array","true","truncate","uescape","union","unique","unknown","unnest","update","upper","user","using","value","values","value_of","var_pop","var_samp","varbinary","varchar","varying","versioning","when","whenever","where","width_bucket","window","with","within","without","year","add","asc","collation","desc","final","first","last","view"].filter(e=>!r.includes(e)),c={begin:n.concat(/\b/,n.either(...o),/\s*\(/),relevance:0,keywords:{built_in:o}};return{name:"SQL",case_insensitive:!0,illegal:/[{}]|<\//,keywords:{$pattern:/\b[\w\.]+/,keyword:((e,{exceptions:n,when:t}={})=>{const a=t;return n=n||[],e.map(e=>e.match(/\|\d+$/)||n.includes(e)?e:a(e)?e+"|0":e)})(l,{when:e=>e.length<3}),literal:a,type:i,built_in:["current_catalog","current_date","current_default_transform_group","current_path","current_role","current_schema","current_transform_group_for_type","current_user","session_user","system_time","system_user","current_time","localtime","current_timestamp","localtimestamp"]},contains:[{begin:n.either(...s),relevance:0,keywords:{$pattern:/[\w\.]+/,keyword:l.concat(s),literal:a,type:i}},{className:"type",begin:n.either("double precision","large object","with timezone","without timezone")},c,{className:"variable",begin:/@[a-z0-9]+/},{className:"string",variants:[{begin:/'/,end:/'/,contains:[{begin:/''/}]}]},{begin:/"/,end:/"/,contains:[{begin:/""/}]},e.C_NUMBER_MODE,e.C_BLOCK_COMMENT_MODE,t,{className:"operator",begin:/[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/,relevance:0}]}},grmr_swift:e=>{const n={match:/\s+/,relevance:0},t=e.COMMENT("/\\*","\\*/",{contains:["self"]}),a=[e.C_LINE_COMMENT_MODE,t],i={match:[/\./,p(...ve,...ke)],className:{2:"keyword"}},r={match:m(/\./,p(...xe)),relevance:0},s=xe.filter(e=>"string"==typeof e).concat(["_|0"]),o={variants:[{className:"keyword",match:p(...xe.filter(e=>"string"!=typeof e).concat(Oe).map(Ne),...ke)}]},l={$pattern:p(/\b\w+/,/#\w+/),keyword:s.concat(Ae),literal:Me},c=[i,r,o],d=[{match:m(/\./,p(...Ce)),relevance:0},{className:"built_in",match:m(/\b/,p(...Ce),/(?=\()/)}],u={match:/->/,relevance:0},b=[u,{className:"operator",relevance:0,variants:[{match:De},{match:`\\.(\\.|${Re})+`}]}],_="([0-9a-fA-F]_*)+",h={className:"number",relevance:0,variants:[{match:"\\b(([0-9]_*)+)(\\.(([0-9]_*)+))?([eE][+-]?(([0-9]_*)+))?\\b"},{match:`\\b0x(${_})(\\.(${_}))?([pP][+-]?(([0-9]_*)+))?\\b`},{match:/\b0o([0-7]_*)+\b/},{match:/\b0b([01]_*)+\b/}]},f=(e="")=>({className:"subst",variants:[{match:m(/\\/,e,/[0\\tnr"']/)},{match:m(/\\/,e,/u\{[0-9a-fA-F]{1,8}\}/)}]}),E=(e="")=>({className:"subst",match:m(/\\/,e,/[\t ]*(?:[\r\n]|\r\n)/)}),y=(e="")=>({className:"subst",label:"interpol",begin:m(/\\/,e,/\(/),end:/\)/}),w=(e="")=>({begin:m(e,/"""/),end:m(/"""/,e),contains:[f(e),E(e),y(e)]}),N=(e="")=>({begin:m(e,/"/),end:m(/"/,e),contains:[f(e),y(e)]}),v={className:"string",variants:[w(),w("#"),w("##"),w("###"),N(),N("#"),N("##"),N("###")]},k={match:m(/`/,Be,/`/)},O=[k,{className:"variable",match:/\$\d+/},{className:"variable",match:`\\$${Le}+`}],x=[{match:/(@|#(un)?)available/,className:"keyword",starts:{contains:[{begin:/\(/,end:/\)/,keywords:Fe,contains:[...b,h,v]}]}},{className:"keyword",match:m(/@/,p(...ze))},{className:"meta",match:m(/@/,Be)}],M={match:g(/\b[A-Z]/),relevance:0,contains:[{className:"type",match:m(/(AV|CA|CF|CG|CI|CL|CM|CN|CT|MK|MP|MTK|MTL|NS|SCN|SK|UI|WK|XC)/,Le,"+")},{className:"type",match:$e,relevance:0},{match:/[?!]+/,relevance:0},{match:/\.\.\./,relevance:0},{match:m(/\s+&\s+/,g($e)),relevance:0}]},S={begin://,keywords:l,contains:[...a,...c,...x,u,M]};M.contains.push(S);const A={begin:/\(/,end:/\)/,relevance:0,keywords:l,contains:["self",{match:m(Be,/\s*:/),keywords:"_|0",relevance:0},...a,...c,...d,...b,h,v,...O,...x,M]},C={begin://,contains:[...a,M]},T={begin:/\(/,end:/\)/,keywords:l,contains:[{begin:p(g(m(Be,/\s*:/)),g(m(Be,/\s+/,Be,/\s*:/))),end:/:/,relevance:0,contains:[{className:"keyword",match:/\b_\b/},{className:"params",match:Be}]},...a,...c,...b,h,v,...x,M,A],endsParent:!0,illegal:/["']/},R={match:[/func/,/\s+/,p(k.match,Be,De)],className:{1:"keyword",3:"title.function"},contains:[C,T,n],illegal:[/\[/,/%/]},D={match:[/\b(?:subscript|init[?!]?)/,/\s*(?=[<(])/],className:{1:"keyword"},contains:[C,T,n],illegal:/\[|%/},I={match:[/operator/,/\s+/,De],className:{1:"keyword",3:"title"}},L={begin:[/precedencegroup/,/\s+/,$e],className:{1:"keyword",3:"title"},contains:[M],keywords:[...Se,...Me],end:/}/};for(const e of v.variants){const n=e.contains.find(e=>"interpol"===e.label);n.keywords=l;const t=[...c,...d,...b,h,v,...O];n.contains=[...t,{begin:/\(/,end:/\)/,contains:["self",...t]}]}return{name:"Swift",keywords:l,contains:[...a,R,D,{beginKeywords:"struct protocol class extension enum actor",end:"\\{",excludeEnd:!0,keywords:l,contains:[e.inherit(e.TITLE_MODE,{className:"title.class",begin:/[A-Za-z$_][\u00C0-\u02B80-9A-Za-z$_]*/}),...c]},I,L,{beginKeywords:"import",end:/$/,contains:[...a],relevance:0},...c,...d,...b,h,v,...O,...x,M,A]}},grmr_typescript:e=>{const n=we(e),t=["any","void","number","boolean","string","object","never","symbol","bigint","unknown"],a={beginKeywords:"namespace",end:/\{/,excludeEnd:!0,contains:[n.exports.CLASS_REFERENCE]},i={beginKeywords:"interface",end:/\{/,excludeEnd:!0,keywords:{keyword:"interface extends",built_in:t},contains:[n.exports.CLASS_REFERENCE]},r={$pattern:be,keyword:me.concat(["type","namespace","interface","public","private","protected","implements","declare","abstract","readonly","enum","override"]),literal:pe,built_in:ye.concat(t),"variable.language":Ee},s={className:"meta",begin:"@[A-Za-z$_][0-9A-Za-z$_]*"},o=(e,n,t)=>{const a=e.contains.findIndex(e=>e.label===n);if(-1===a)throw Error("can not find mode to replace");e.contains.splice(a,1,t)};return Object.assign(n.keywords,r),n.exports.PARAMS_CONTAINS.push(s),n.contains=n.contains.concat([s,a,i]),o(n,"shebang",e.SHEBANG()),o(n,"use_strict",{className:"meta",relevance:10,begin:/^\s*['"]use strict['"]/}),n.contains.find(e=>"func.def"===e.label).relevance=0,Object.assign(n,{name:"TypeScript",aliases:["ts","tsx"]}),n},grmr_vbnet:e=>{const n=e.regex,t=/\d{1,2}\/\d{1,2}\/\d{4}/,a=/\d{4}-\d{1,2}-\d{1,2}/,i=/(\d|1[012])(:\d+){0,2} *(AM|PM)/,r=/\d{1,2}(:\d{1,2}){1,2}/,s={className:"literal",variants:[{begin:n.concat(/# */,n.either(a,t),/ *#/)},{begin:n.concat(/# */,r,/ *#/)},{begin:n.concat(/# */,i,/ *#/)},{begin:n.concat(/# */,n.either(a,t),/ +/,n.either(i,r),/ *#/)}]},o=e.COMMENT(/'''/,/$/,{contains:[{className:"doctag",begin:/<\/?/,end:/>/}]}),l=e.COMMENT(null,/$/,{variants:[{begin:/'/},{begin:/([\t ]|^)REM(?=\s)/}]});return{name:"Visual Basic .NET",aliases:["vb"],case_insensitive:!0,classNameAliases:{label:"symbol"},keywords:{keyword:"addhandler alias aggregate ansi as async assembly auto binary by byref byval call case catch class compare const continue custom declare default delegate dim distinct do each equals else elseif end enum erase error event exit explicit finally for friend from function get global goto group handles if implements imports in inherits interface into iterator join key let lib loop me mid module mustinherit mustoverride mybase myclass namespace narrowing new next notinheritable notoverridable of off on operator option optional order overloads overridable overrides paramarray partial preserve private property protected public raiseevent readonly redim removehandler resume return select set shadows shared skip static step stop structure strict sub synclock take text then throw to try unicode until using when where while widening with withevents writeonly yield",built_in:"addressof and andalso await directcast gettype getxmlnamespace is isfalse isnot istrue like mod nameof new not or orelse trycast typeof xor cbool cbyte cchar cdate cdbl cdec cint clng cobj csbyte cshort csng cstr cuint culng cushort",type:"boolean byte char date decimal double integer long object sbyte short single string uinteger ulong ushort",literal:"true false nothing"},illegal:"//|\\{|\\}|endif|gosub|variant|wend|^\\$ ",contains:[{className:"string",begin:/"(""|[^/n])"C\b/},{className:"string",begin:/"/,end:/"/,illegal:/\n/,contains:[{begin:/""/}]},s,{className:"number",relevance:0,variants:[{begin:/\b\d[\d_]*((\.[\d_]+(E[+-]?[\d_]+)?)|(E[+-]?[\d_]+))[RFD@!#]?/},{begin:/\b\d[\d_]*((U?[SIL])|[%&])?/},{begin:/&H[\dA-F_]+((U?[SIL])|[%&])?/},{begin:/&O[0-7_]+((U?[SIL])|[%&])?/},{begin:/&B[01_]+((U?[SIL])|[%&])?/}]},{className:"label",begin:/^\w+:/},o,l,{className:"meta",begin:/[\t ]*#(const|disable|else|elseif|enable|end|externalsource|if|region)\b/,end:/$/,keywords:{keyword:"const disable else elseif enable end externalsource if region then"},contains:[l]}]}},grmr_yaml:e=>{const n="true false yes no null",t="[\\w#;/?:@&=+$,.~*'()[\\]]+",a={className:"string",relevance:0,variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/\S+/}],contains:[e.BACKSLASH_ESCAPE,{className:"template-variable",variants:[{begin:/\{\{/,end:/\}\}/},{begin:/%\{/,end:/\}/}]}]},i=e.inherit(a,{variants:[{begin:/'/,end:/'/},{begin:/"/,end:/"/},{begin:/[^\s,{}[\]]+/}]}),r={end:",",endsWithParent:!0,excludeEnd:!0,keywords:n,relevance:0},s={begin:/\{/,end:/\}/,contains:[r],illegal:"\\n",relevance:0},o={begin:"\\[",end:"\\]",contains:[r],illegal:"\\n",relevance:0},l=[{className:"attr",variants:[{begin:"\\w[\\w :\\/.-]*:(?=[ \t]|$)"},{begin:'"\\w[\\w :\\/.-]*":(?=[ \t]|$)'},{begin:"'\\w[\\w :\\/.-]*':(?=[ \t]|$)"}]},{className:"meta",begin:"^---\\s*$",relevance:10},{className:"string",begin:"[\\|>]([1-9]?[+-])?[ ]*\\n( +)[^ ][^\\n]*\\n(\\2[^\\n]+\\n?)*"},{begin:"<%[%=-]?",end:"[%-]?%>",subLanguage:"ruby",excludeBegin:!0,excludeEnd:!0,relevance:0},{className:"type",begin:"!\\w+!"+t},{className:"type",begin:"!<"+t+">"},{className:"type",begin:"!"+t},{className:"type",begin:"!!"+t},{className:"meta",begin:"&"+e.UNDERSCORE_IDENT_RE+"$"},{className:"meta",begin:"\\*"+e.UNDERSCORE_IDENT_RE+"$"},{className:"bullet",begin:"-(?=[ ]|$)",relevance:0},e.HASH_COMMENT_MODE,{beginKeywords:n,keywords:{literal:n}},{className:"number",begin:"\\b[0-9]{4}(-[0-9][0-9]){0,2}([Tt \\t][0-9][0-9]?(:[0-9][0-9]){2})?(\\.[0-9]*)?([ \\t])*(Z|[-+][0-9][0-9]?(:[0-9][0-9])?)?\\b"},{className:"number",begin:e.C_NUMBER_RE+"\\b",relevance:0},s,o,a],c=[...l];return c.pop(),c.push(i),r.contains=c,{name:"YAML",case_insensitive:!0,aliases:["yml"],contains:l}}});const je=ne;for(const e of Object.keys(Ue)){const n=e.replace("grmr_","").replace("_","-");je.registerLanguage(n,Ue[e])}return je}();"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs); diff --git a/playground/src/workbench/prql-syntax.js b/playground/src/workbench/prql-syntax.js index 6adce08b273c..8a589aed327c 100644 --- a/playground/src/workbench/prql-syntax.js +++ b/playground/src/workbench/prql-syntax.js @@ -13,7 +13,7 @@ const TRANSFORMS = [ "union", "window", ]; -const BUILTIN_FUNCTIONS = ["switch"]; // "in", "as" +const BUILTIN_FUNCTIONS = ["case"]; // "in", "as" const KEYWORDS = ["func", "let", "prql"]; const LITERALS = ["null", "true", "false"]; const OPERATORS = ["and", "or"]; // "not" diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index d23926e458f6..21f14994e112 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -72,7 +72,7 @@ pub enum ExprKind { TransformCall(TransformCall), SString(Vec), FString(Vec), - Switch(Vec), + Case(Vec), BuiltInFunction { name: String, args: Vec, @@ -573,8 +573,8 @@ impl Display for Expr { ExprKind::Literal(literal) => { write!(f, "{}", literal)?; } - ExprKind::Switch(cases) => { - f.write_str("switch [\n")?; + ExprKind::Case(cases) => { + f.write_str("case [\n")?; for case in cases { writeln!(f, " {} => {}", case.condition, case.value)?; } diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index 9d7664f80fe6..09fc02d71bd7 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -100,7 +100,7 @@ pub fn fold_expr_kind(fold: &mut T, expr_kind: ExprKind) -> .map(|x| fold.fold_interpolate_item(x)) .try_collect()?, ), - Switch(cases) => Switch(fold_cases(fold, cases)?), + Case(cases) => Case(fold_cases(fold, cases)?), FuncCall(func_call) => FuncCall(fold.fold_func_call(func_call)?), Closure(closure) => Closure(Box::new(fold.fold_closure(*closure)?)), diff --git a/prql-compiler/src/ast/rq/expr.rs b/prql-compiler/src/ast/rq/expr.rs index ba9f07a8bc40..d685459f268c 100644 --- a/prql-compiler/src/ast/rq/expr.rs +++ b/prql-compiler/src/ast/rq/expr.rs @@ -34,7 +34,7 @@ pub enum ExprKind { // TODO: convert this into built-in function FString(Vec>), - Switch(Vec>), + Case(Vec>), BuiltInFunction { name: String, diff --git a/prql-compiler/src/ast/rq/fold.rs b/prql-compiler/src/ast/rq/fold.rs index ca0920244f41..d0a35d89260a 100644 --- a/prql-compiler/src/ast/rq/fold.rs +++ b/prql-compiler/src/ast/rq/fold.rs @@ -223,7 +223,7 @@ pub fn fold_expr_kind(fold: &mut F, kind: ExprKind) -> Resul ExprKind::SString(items) => ExprKind::SString(fold_interpolate_items(fold, items)?), ExprKind::FString(items) => ExprKind::FString(fold_interpolate_items(fold, items)?), - ExprKind::Switch(cases) => ExprKind::Switch( + ExprKind::Case(cases) => ExprKind::Case( cases .into_iter() .map(|c| fold_switch_case(fold, c)) diff --git a/prql-compiler/src/parser/expr.rs b/prql-compiler/src/parser/expr.rs index 6a24915f7a44..07b16439fd59 100644 --- a/prql-compiler/src/parser/expr.rs +++ b/prql-compiler/src/parser/expr.rs @@ -72,7 +72,7 @@ pub fn expr() -> impl Parser> + Clone { } }); - let switch = keyword("switch") + let case = keyword("case") .ignore_then( func_call(expr.clone()) .then_ignore(just(Token::Arrow)) @@ -84,7 +84,7 @@ pub fn expr() -> impl Parser> + Clone { .then_ignore(new_line().repeated()) .delimited_by(ctrl('['), ctrl(']')), ) - .map(ExprKind::Switch); + .map(ExprKind::Case); let param = select! { Token::Param(id) => ExprKind::Param(id) }; @@ -94,7 +94,7 @@ pub fn expr() -> impl Parser> + Clone { pipeline, interpolation, ident_kind, - switch, + case, param, )) .map_with_span(into_expr) diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 2043ea8d9847..2d0af4523d7a 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -51,7 +51,7 @@ pub fn lexer() -> impl Parser)>, Error let ident = ident_part().map(Token::Ident); - let keyword = choice((just("func"), just("let"), just("switch"), just("prql"))) + let keyword = choice((just("func"), just("let"), just("case"), just("prql"))) .then_ignore(end_expr()) .map(|x| x.to_string()) .map(Token::Keyword); diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 247a881dbfd9..db7b880e3fb9 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -2188,13 +2188,13 @@ join s=salaries [==id] } #[test] - fn test_switch() { - assert_yaml_snapshot!(parse_expr(r#"switch [ + fn test_case() { + assert_yaml_snapshot!(parse_expr(r#"case [ nickname != null -> nickname, true -> null ]"#).unwrap(), @r###" --- - Switch: + Case: - condition: Binary: left: diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index 92f36d1c4428..1c688ac4589a 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -637,7 +637,7 @@ impl Lowerer { pl::ExprKind::FString(items) => { rq::ExprKind::FString(self.lower_interpolations(items)?) } - pl::ExprKind::Switch(cases) => rq::ExprKind::Switch( + pl::ExprKind::Case(cases) => rq::ExprKind::Case( cases .into_iter() .map(|case| -> Result<_> { diff --git a/prql-compiler/src/semantic/static_analysis.rs b/prql-compiler/src/semantic/static_analysis.rs index 4db3b93fd54d..081fff2b5821 100644 --- a/prql-compiler/src/semantic/static_analysis.rs +++ b/prql-compiler/src/semantic/static_analysis.rs @@ -131,7 +131,7 @@ fn eval(kind: ExprKind) -> ExprKind { } } - ExprKind::Switch(items) => { + ExprKind::Case(items) => { let mut res = Vec::with_capacity(items.len()); for item in items { if let ExprKind::Literal(Literal::Boolean(condition)) = item.condition.kind { @@ -160,7 +160,7 @@ fn eval(kind: ExprKind) -> ExprKind { } } - ExprKind::Switch(res) + ExprKind::Case(res) } k => k, diff --git a/prql-compiler/src/sql/anchor.rs b/prql-compiler/src/sql/anchor.rs index a81bcc37d63c..a96d52300714 100644 --- a/prql-compiler/src/sql/anchor.rs +++ b/prql-compiler/src/sql/anchor.rs @@ -463,7 +463,7 @@ pub fn infer_complexity(compute: &Compute) -> Complexity { pub fn infer_complexity_expr(expr: &Expr) -> Complexity { match &expr.kind { - rq::ExprKind::Switch(_) => Complexity::NonGroup, + rq::ExprKind::Case(_) => Complexity::NonGroup, rq::ExprKind::Binary { left, right, .. } => { Complexity::max(infer_complexity_expr(left), infer_complexity_expr(right)) } diff --git a/prql-compiler/src/sql/gen_expr.rs b/prql-compiler/src/sql/gen_expr.rs index 5f57a16670d7..797879487fe6 100644 --- a/prql-compiler/src/sql/gen_expr.rs +++ b/prql-compiler/src/sql/gen_expr.rs @@ -94,7 +94,7 @@ pub(super) fn translate_expr_kind(item: ExprKind, ctx: &mut Context) -> Result sql_ast::Expr::Identifier(sql_ast::Ident::new(format!("${id}"))), ExprKind::FString(f_string_items) => translate_fstring(f_string_items, ctx)?, ExprKind::Literal(l) => translate_literal(l, ctx)?, - ExprKind::Switch(mut cases) => { + ExprKind::Case(mut cases) => { let default = cases .last() .filter(|last| { diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 6d4dcb9b071d..68df47ae447f 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2665,11 +2665,11 @@ fn test_output_column_deduplication() { } #[test] -fn test_switch() { +fn test_case() { assert_display_snapshot!(compile( r###" from employees - derive display_name = switch [ + derive display_name = case [ nickname != null -> nickname, true -> f'{first_name} {last_name}' ] @@ -2689,7 +2689,7 @@ fn test_switch() { assert_display_snapshot!(compile( r###" from employees - derive display_name = switch [ + derive display_name = case [ nickname != null -> nickname, first_name != null -> f'{first_name} {last_name}' ] @@ -2710,7 +2710,7 @@ fn test_switch() { assert_display_snapshot!(compile( r###" from tracks - select category = switch [ + select category = case [ length > avg_length -> 'long' ] group category (aggregate count) @@ -2781,7 +2781,7 @@ fn test_static_analysis() { a3 = null ?? y, - a3 = switch [ + a3 = case [ false == true -> 1, 7 == 3 -> 2, 7 == y -> 3, diff --git a/prql-compiler/tests/integration/data/chinook/tracks.csv b/prql-compiler/tests/integration/data/chinook/tracks.csv index 60f177ca91b3..66246430590c 100644 --- a/prql-compiler/tests/integration/data/chinook/tracks.csv +++ b/prql-compiler/tests/integration/data/chinook/tracks.csv @@ -2677,7 +2677,7 @@ track_id,name,album_id,media_type_id,genre_id,composer,milliseconds,bytes,unit_p 2676,Intro,217,1,1,Jagger/Richards,49737,1618591,0.99 2677,You Got Me Rocking,217,1,1,Jagger/Richards,205766,6734385,0.99 2678,Gimmie Shelters,217,1,1,Jagger/Richards,382119,12528764,0.99 -2679,Flip The Switch,217,1,1,Jagger/Richards,252421,8336591,0.99 +2679,Flip The Case,217,1,1,Jagger/Richards,252421,8336591,0.99 2680,Memory Motel,217,1,1,Jagger/Richards,365844,11982431,0.99 2681,Corinna,217,1,1,Jesse Ed Davis III/Taj Mahal,257488,8449471,0.99 2682,Saint Of Me,217,1,1,Jagger/Richards,325694,10725160,0.99 diff --git a/prql-compiler/tests/integration/queries/switch.prql b/prql-compiler/tests/integration/queries/switch.prql index 19497776665a..284f61d6202b 100644 --- a/prql-compiler/tests/integration/queries/switch.prql +++ b/prql-compiler/tests/integration/queries/switch.prql @@ -1,6 +1,6 @@ from tracks sort milliseconds -select display = switch [ +select display = case [ composer != null -> composer, genre_id < 17 -> 'no composer', true -> f'unknown composer' diff --git a/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap b/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap index b53c9cc01eb9..2a9e5eec12b4 100644 --- a/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap +++ b/prql-compiler/tests/integration/snapshots/integration__tests__test@switch.prql.snap @@ -1,7 +1,7 @@ --- source: prql-compiler/tests/integration/main.rs expression: sqlite_out -input_file: prql-compiler/tests/integration/queries/switch.prql +input_file: prql-compiler/tests/integration/queries/case.prql --- display,milliseconds Samuel Rosa,1071 diff --git a/prql-lezer/src/prql.grammar b/prql-lezer/src/prql.grammar index 803e6e61a6c0..e599e2f47991 100644 --- a/prql-lezer/src/prql.grammar +++ b/prql-lezer/src/prql.grammar @@ -1,5 +1,5 @@ // TODO: -// - `switch` transform +// - `case` transform // - Do we want to highlight built-in transforms like `from` differently to // normal functions? // - A few small TODOs included below diff --git a/website/content/posts/2023-02-02-one-year/_index.md b/website/content/posts/2023-02-02-one-year/_index.md index 8ec6ef20c85e..c591feb5e7b3 100644 --- a/website/content/posts/2023-02-02-one-year/_index.md +++ b/website/content/posts/2023-02-02-one-year/_index.md @@ -31,7 +31,7 @@ Language design & development in the last year have been focused on these areas: - small quality-of-life language features (e.g. syntax for [f-strings, dates, coalesce operator](https://prql-lang.org/book/syntax.html), - [switch](https://github.com/PRQL/prql/issues/504)), + [case](https://github.com/PRQL/prql/issues/504)), PRQL is now in a state where it can greatly improve the developer experience for writing complex analytical queries, but it does require a bit of fiddling to set diff --git a/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js b/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js index 6c0869bc3b2d..be8801f6ab34 100644 --- a/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js +++ b/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js @@ -3,5 +3,5 @@ * Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=(t,e,i)=>{Object.keys(i).forEach((n=>{const s=i[n],r=e[n],a=r&&o(r)?"element":null==(l=r)?`${l}`:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(s).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}))},l=t=>!(!o(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",(()=>{p.forEach((t=>t()))})),p.push(e)):e()},_=t=>{"function"==typeof t&&t()},b=(e,i,n=!0)=>{if(!n)return void _(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),_(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},v=(t,e,i,n)=>{let s=t.indexOf(e);if(-1===s)return t[!i&&n?t.length-1:0];const o=t.length;return s+=i?1:-1,n&&(s=(s+o)%o),t[Math.max(0,Math.min(s,o-1))]},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,E=/::\d+$/,A={};let T=1;const O={mouseenter:"mouseover",mouseleave:"mouseout"},C=/^(mouseenter|mouseleave)/i,k=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function L(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function x(t){const e=L(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function D(t,e,i=null){const n=Object.keys(t);for(let s=0,o=n.length;sfunction(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};n?n=t(n):i=t(i)}const[o,r,a]=S(e,i,n),l=x(t),c=l[a]||(l[a]={}),h=D(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=L(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return s.delegateTarget=r,n.oneOff&&j.off(t,s.type,e,i),i.apply(r,[s]);return null}}(t,i,n):function(t,e){return function i(n){return n.delegateTarget=t,i.oneOff&&j.off(t,n.type,e),e.apply(t,[n])}}(t,i);u.delegationSelector=o?i:null,u.originalHandler=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function I(t,e,i,n,s){const o=D(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function P(t){return t=t.replace(w,""),O[t]||t}const j={on(t,e,i,n){N(t,e,i,n,!1)},one(t,e,i,n){N(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=x(t),c=e.startsWith(".");if(void 0!==o){if(!l||!l[r])return;return void I(t,l,r,o,s?i:null)}c&&Object.keys(l).forEach((i=>{!function(t,e,i,n){const s=e[i]||{};Object.keys(s).forEach((o=>{if(o.includes(n)){const n=s[o];I(t,e,i,n.originalHandler,n.delegationSelector)}}))}(t,l,i,e.slice(1))}));const h=l[r]||{};Object.keys(h).forEach((i=>{const n=i.replace(E,"");if(!a||e.includes(n)){const e=h[i];I(t,l,r,e.originalHandler,e.delegationSelector)}}))},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=f(),s=P(e),o=e!==s,r=k.has(s);let a,l=!0,c=!0,h=!1,d=null;return o&&n&&(a=n.Event(e,i),n(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),h=a.isDefaultPrevented()),r?(d=document.createEvent("HTMLEvents"),d.initEvent(s,l,!0)):d=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==i&&Object.keys(i).forEach((t=>{Object.defineProperty(d,t,{get:()=>i[t]})})),h&&d.preventDefault(),c&&t.dispatchEvent(d),d.defaultPrevented&&void 0!==a&&a.preventDefault(),d}},M=new Map,H={set(t,e,i){M.has(t)||M.set(t,new Map);const n=M.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>M.has(t)&&M.get(t).get(e)||null,remove(t,e){if(!M.has(t))return;const i=M.get(t);i.delete(e),0===i.size&&M.delete(t)}};class B{constructor(t){(t=r(t))&&(this._element=t,H.set(this._element,this.constructor.DATA_KEY,this))}dispose(){H.remove(this._element,this.constructor.DATA_KEY),j.off(this._element,this.constructor.EVENT_KEY),Object.getOwnPropertyNames(this).forEach((t=>{this[t]=null}))}_queueCallback(t,e,i=!0){b(t,e,i)}static getInstance(t){return H.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.1.3"}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}}const R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;j.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),c(this))return;const o=n(this)||this.closest(`.${s}`);t.getOrCreateInstance(o)[e]()}))};class W extends B{static get NAME(){return"alert"}close(){if(j.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),j.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=W.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(W,"close"),g(W);const $='[data-bs-toggle="button"]';class z extends B{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=z.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}function q(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function F(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}j.on(document,"click.bs.button.data-api",$,(t=>{t.preventDefault();const e=t.target.closest($);z.getOrCreateInstance(e).toggle()})),g(z);const U={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter((t=>t.startsWith("bs"))).forEach((i=>{let n=i.replace(/^bs/,"");n=n.charAt(0).toLowerCase()+n.slice(1,n.length),e[n]=q(t.dataset[i])})),e},getDataAttribute:(t,e)=>q(t.getAttribute(`data-bs-${F(e)}`)),offset(t){const e=t.getBoundingClientRect();return{top:e.top+window.pageYOffset,left:e.left+window.pageXOffset}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},V={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode;for(;n&&n.nodeType===Node.ELEMENT_NODE&&3!==n.nodeType;)n.matches(e)&&i.push(n),n=n.parentNode;return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(", ");return this.find(e,t).filter((t=>!c(t)&&l(t)))}},K="carousel",X={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},Y={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},Q="next",G="prev",Z="left",J="right",tt={ArrowLeft:J,ArrowRight:Z},et="slid.bs.carousel",it="active",nt=".active.carousel-item";class st extends B{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=V.findOne(".carousel-indicators",this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return X}static get NAME(){return K}next(){this._slide(Q)}nextWhenVisible(){!document.hidden&&l(this._element)&&this.next()}prev(){this._slide(G)}pause(t){t||(this._isPaused=!0),V.findOne(".carousel-item-next, .carousel-item-prev",this._element)&&(s(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=V.findOne(nt,this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void j.one(this._element,et,(()=>this.to(t)));if(e===t)return this.pause(),void this.cycle();const i=t>e?Q:G;this._slide(i,this._items[t])}_getConfig(t){return t={...X,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(K,t,Y),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=40)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?J:Z)}_addEventListeners(){this._config.keyboard&&j.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(j.on(this._element,"mouseenter.bs.carousel",(t=>this.pause(t))),j.on(this._element,"mouseleave.bs.carousel",(t=>this.cycle(t)))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>this._pointerEvent&&("pen"===t.pointerType||"touch"===t.pointerType),e=e=>{t(e)?this.touchStartX=e.clientX:this._pointerEvent||(this.touchStartX=e.touches[0].clientX)},i=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},n=e=>{t(e)&&(this.touchDeltaX=e.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((t=>this.cycle(t)),500+this._config.interval))};V.find(".carousel-item img",this._element).forEach((t=>{j.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()))})),this._pointerEvent?(j.on(this._element,"pointerdown.bs.carousel",(t=>e(t))),j.on(this._element,"pointerup.bs.carousel",(t=>n(t))),this._element.classList.add("pointer-event")):(j.on(this._element,"touchstart.bs.carousel",(t=>e(t))),j.on(this._element,"touchmove.bs.carousel",(t=>i(t))),j.on(this._element,"touchend.bs.carousel",(t=>n(t))))}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=tt[t.key];e&&(t.preventDefault(),this._slide(e))}_getItemIndex(t){return this._items=t&&t.parentNode?V.find(".carousel-item",t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const i=t===Q;return v(this._items,e,i,this._config.wrap)}_triggerSlideEvent(t,e){const i=this._getItemIndex(t),n=this._getItemIndex(V.findOne(nt,this._element));return j.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:n,to:i})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=V.findOne(".active",this._indicatorsElement);e.classList.remove(it),e.removeAttribute("aria-current");const i=V.find("[data-bs-target]",this._indicatorsElement);for(let e=0;e{j.trigger(this._element,et,{relatedTarget:o,direction:d,from:s,to:r})};if(this._element.classList.contains("slide")){o.classList.add(h),u(o),n.classList.add(c),o.classList.add(c);const t=()=>{o.classList.remove(c,h),o.classList.add(it),n.classList.remove(it,h,c),this._isSliding=!1,setTimeout(f,0)};this._queueCallback(t,n,!0)}else n.classList.remove(it),o.classList.add(it),this._isSliding=!1,f();a&&this.cycle()}_directionToOrder(t){return[J,Z].includes(t)?m()?t===Z?G:Q:t===Z?Q:G:t}_orderToDirection(t){return[Q,G].includes(t)?m()?t===G?Z:J:t===G?J:Z:t}static carouselInterface(t,e){const i=st.getOrCreateInstance(t,e);let{_config:n}=i;"object"==typeof e&&(n={...n,...e});const s="string"==typeof e?e:n.slide;if("number"==typeof e)i.to(e);else if("string"==typeof s){if(void 0===i[s])throw new TypeError(`No method named "${s}"`);i[s]()}else n.interval&&n.ride&&(i.pause(),i.cycle())}static jQueryInterface(t){return this.each((function(){st.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=n(this);if(!e||!e.classList.contains("carousel"))return;const i={...U.getDataAttributes(e),...U.getDataAttributes(this)},s=this.getAttribute("data-bs-slide-to");s&&(i.interval=!1),st.carouselInterface(e,i),s&&st.getInstance(e).to(s),t.preventDefault()}}j.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",st.dataApiClickHandler),j.on(window,"load.bs.carousel.data-api",(()=>{const t=V.find('[data-bs-ride="carousel"]');for(let e=0,i=t.length;et===this._element));null!==s&&o.length&&(this._selector=s,this._triggerArray.push(e))}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return rt}static get NAME(){return ot}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t,e=[];if(this._config.parent){const t=V.find(ut,this._config.parent);e=V.find(".collapse.show, .collapse.collapsing",this._config.parent).filter((e=>!t.includes(e)))}const i=V.findOne(this._selector);if(e.length){const n=e.find((t=>i!==t));if(t=n?pt.getInstance(n):null,t&&t._isTransitioning)return}if(j.trigger(this._element,"show.bs.collapse").defaultPrevented)return;e.forEach((e=>{i!==e&&pt.getOrCreateInstance(e,{toggle:!1}).hide(),t||H.set(e,"bs.collapse",null)}));const n=this._getDimension();this._element.classList.remove(ct),this._element.classList.add(ht),this._element.style[n]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const s=`scroll${n[0].toUpperCase()+n.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct,lt),this._element.style[n]="",j.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[n]=`${this._element[s]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(j.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,u(this._element),this._element.classList.add(ht),this._element.classList.remove(ct,lt);const e=this._triggerArray.length;for(let t=0;t{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct),j.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(lt)}_getConfig(t){return(t={...rt,...U.getDataAttributes(this._element),...t}).toggle=Boolean(t.toggle),t.parent=r(t.parent),a(ot,t,at),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=V.find(ut,this._config.parent);V.find(ft,this._config.parent).filter((e=>!t.includes(e))).forEach((t=>{const e=n(t);e&&this._addAriaAndCollapsedClass([t],this._isShown(e))}))}_addAriaAndCollapsedClass(t,e){t.length&&t.forEach((t=>{e?t.classList.remove(dt):t.classList.add(dt),t.setAttribute("aria-expanded",e)}))}static jQueryInterface(t){return this.each((function(){const e={};"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1);const i=pt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}j.on(document,"click.bs.collapse.data-api",ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=i(this);V.find(e).forEach((t=>{pt.getOrCreateInstance(t,{toggle:!1}).toggle()}))})),g(pt);var mt="top",gt="bottom",_t="right",bt="left",vt="auto",yt=[mt,gt,_t,bt],wt="start",Et="end",At="clippingParents",Tt="viewport",Ot="popper",Ct="reference",kt=yt.reduce((function(t,e){return t.concat([e+"-"+wt,e+"-"+Et])}),[]),Lt=[].concat(yt,[vt]).reduce((function(t,e){return t.concat([e,e+"-"+wt,e+"-"+Et])}),[]),xt="beforeRead",Dt="read",St="afterRead",Nt="beforeMain",It="main",Pt="afterMain",jt="beforeWrite",Mt="write",Ht="afterWrite",Bt=[xt,Dt,St,Nt,It,Pt,jt,Mt,Ht];function Rt(t){return t?(t.nodeName||"").toLowerCase():null}function Wt(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function $t(t){return t instanceof Wt(t).Element||t instanceof Element}function zt(t){return t instanceof Wt(t).HTMLElement||t instanceof HTMLElement}function qt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Wt(t).ShadowRoot||t instanceof ShadowRoot)}const Ft={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];zt(s)&&Rt(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});zt(n)&&Rt(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function Ut(t){return t.split("-")[0]}function Vt(t,e){var i=t.getBoundingClientRect();return{width:i.width/1,height:i.height/1,top:i.top/1,right:i.right/1,bottom:i.bottom/1,left:i.left/1,x:i.left/1,y:i.top/1}}function Kt(t){var e=Vt(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Xt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&qt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Yt(t){return Wt(t).getComputedStyle(t)}function Qt(t){return["table","td","th"].indexOf(Rt(t))>=0}function Gt(t){return(($t(t)?t.ownerDocument:t.document)||window.document).documentElement}function Zt(t){return"html"===Rt(t)?t:t.assignedSlot||t.parentNode||(qt(t)?t.host:null)||Gt(t)}function Jt(t){return zt(t)&&"fixed"!==Yt(t).position?t.offsetParent:null}function te(t){for(var e=Wt(t),i=Jt(t);i&&Qt(i)&&"static"===Yt(i).position;)i=Jt(i);return i&&("html"===Rt(i)||"body"===Rt(i)&&"static"===Yt(i).position)?e:i||function(t){var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&zt(t)&&"fixed"===Yt(t).position)return null;for(var i=Zt(t);zt(i)&&["html","body"].indexOf(Rt(i))<0;){var n=Yt(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function ee(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}var ie=Math.max,ne=Math.min,se=Math.round;function oe(t,e,i){return ie(t,ne(e,i))}function re(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ae(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const le={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=Ut(i.placement),l=ee(a),c=[bt,_t].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return re("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ae(t,yt))}(s.padding,i),d=Kt(o),u="y"===l?mt:bt,f="y"===l?gt:_t,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=te(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,E=oe(v,w,y),A=l;i.modifiersData[n]=((e={})[A]=E,e.centerOffset=E-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Xt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ce(t){return t.split("-")[1]}var he={top:"auto",right:"auto",bottom:"auto",left:"auto"};function de(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=!0===h?function(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:se(se(e*n)/n)||0,y:se(se(i*n)/n)||0}}(r):"function"==typeof h?h(r):r,u=d.x,f=void 0===u?0:u,p=d.y,m=void 0===p?0:p,g=r.hasOwnProperty("x"),_=r.hasOwnProperty("y"),b=bt,v=mt,y=window;if(c){var w=te(i),E="clientHeight",A="clientWidth";w===Wt(i)&&"static"!==Yt(w=Gt(i)).position&&"absolute"===a&&(E="scrollHeight",A="scrollWidth"),w=w,s!==mt&&(s!==bt&&s!==_t||o!==Et)||(v=gt,m-=w[E]-n.height,m*=l?1:-1),s!==bt&&(s!==mt&&s!==gt||o!==Et)||(b=_t,f-=w[A]-n.width,f*=l?1:-1)}var T,O=Object.assign({position:a},c&&he);return l?Object.assign({},O,((T={})[v]=_?"0":"",T[b]=g?"0":"",T.transform=(y.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",T)):Object.assign({},O,((e={})[v]=_?m+"px":"",e[b]=g?f+"px":"",e.transform="",e))}const ue={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:Ut(e.placement),variation:ce(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,de(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,de(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var fe={passive:!0};const pe={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Wt(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,fe)})),a&&l.addEventListener("resize",i.update,fe),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,fe)})),a&&l.removeEventListener("resize",i.update,fe)}},data:{}};var me={left:"right",right:"left",bottom:"top",top:"bottom"};function ge(t){return t.replace(/left|right|bottom|top/g,(function(t){return me[t]}))}var _e={start:"end",end:"start"};function be(t){return t.replace(/start|end/g,(function(t){return _e[t]}))}function ve(t){var e=Wt(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ye(t){return Vt(Gt(t)).left+ve(t).scrollLeft}function we(t){var e=Yt(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ee(t){return["html","body","#document"].indexOf(Rt(t))>=0?t.ownerDocument.body:zt(t)&&we(t)?t:Ee(Zt(t))}function Ae(t,e){var i;void 0===e&&(e=[]);var n=Ee(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Wt(n),r=s?[o].concat(o.visualViewport||[],we(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ae(Zt(r)))}function Te(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Oe(t,e){return e===Tt?Te(function(t){var e=Wt(t),i=Gt(t),n=e.visualViewport,s=i.clientWidth,o=i.clientHeight,r=0,a=0;return n&&(s=n.width,o=n.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=n.offsetLeft,a=n.offsetTop)),{width:s,height:o,x:r+ye(t),y:a}}(t)):zt(e)?function(t){var e=Vt(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Te(function(t){var e,i=Gt(t),n=ve(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ie(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ie(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+ye(t),l=-n.scrollTop;return"rtl"===Yt(s||i).direction&&(a+=ie(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Gt(t)))}function Ce(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?Ut(s):null,r=s?ce(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case mt:e={x:a,y:i.y-n.height};break;case gt:e={x:a,y:i.y+i.height};break;case _t:e={x:i.x+i.width,y:l};break;case bt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?ee(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case wt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Et:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ke(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.boundary,r=void 0===o?At:o,a=i.rootBoundary,l=void 0===a?Tt:a,c=i.elementContext,h=void 0===c?Ot:c,d=i.altBoundary,u=void 0!==d&&d,f=i.padding,p=void 0===f?0:f,m=re("number"!=typeof p?p:ae(p,yt)),g=h===Ot?Ct:Ot,_=t.rects.popper,b=t.elements[u?g:h],v=function(t,e,i){var n="clippingParents"===e?function(t){var e=Ae(Zt(t)),i=["absolute","fixed"].indexOf(Yt(t).position)>=0&&zt(t)?te(t):t;return $t(i)?e.filter((function(t){return $t(t)&&Xt(t,i)&&"body"!==Rt(t)})):[]}(t):[].concat(e),s=[].concat(n,[i]),o=s[0],r=s.reduce((function(e,i){var n=Oe(t,i);return e.top=ie(n.top,e.top),e.right=ne(n.right,e.right),e.bottom=ne(n.bottom,e.bottom),e.left=ie(n.left,e.left),e}),Oe(t,o));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}($t(b)?b:b.contextElement||Gt(t.elements.popper),r,l),y=Vt(t.elements.reference),w=Ce({reference:y,element:_,strategy:"absolute",placement:s}),E=Te(Object.assign({},_,w)),A=h===Ot?E:y,T={top:v.top-A.top+m.top,bottom:A.bottom-v.bottom+m.bottom,left:v.left-A.left+m.left,right:A.right-v.right+m.right},O=t.modifiersData.offset;if(h===Ot&&O){var C=O[s];Object.keys(T).forEach((function(t){var e=[_t,gt].indexOf(t)>=0?1:-1,i=[mt,gt].indexOf(t)>=0?"y":"x";T[t]+=C[i]*e}))}return T}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?Lt:l,h=ce(n),d=h?a?kt:kt.filter((function(t){return ce(t)===h})):yt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ke(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[Ut(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const xe={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=Ut(g),b=l||(_!==g&&p?function(t){if(Ut(t)===vt)return[];var e=ge(t);return[be(t),e,be(e)]}(g):[ge(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(Ut(i)===vt?Le(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,A=!0,T=v[0],O=0;O=0,D=x?"width":"height",S=ke(e,{placement:C,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),N=x?L?_t:bt:L?gt:mt;y[D]>w[D]&&(N=ge(N));var I=ge(N),P=[];if(o&&P.push(S[k]<=0),a&&P.push(S[N]<=0,S[I]<=0),P.every((function(t){return t}))){T=C,A=!1;break}E.set(C,P)}if(A)for(var j=function(t){var e=v.find((function(e){var i=E.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==j(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function De(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Se(t){return[mt,_t,gt,bt].some((function(e){return t[e]>=0}))}const Ne={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ke(e,{elementContext:"reference"}),a=ke(e,{altBoundary:!0}),l=De(r,n),c=De(a,s,o),h=Se(l),d=Se(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},Ie={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=Lt.reduce((function(t,i){return t[i]=function(t,e,i){var n=Ut(t),s=[bt,mt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[bt,_t].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Pe={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=Ce({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},je={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ke(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=Ut(e.placement),b=ce(e.placement),v=!b,y=ee(_),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,A=e.rects.reference,T=e.rects.popper,O="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,C={x:0,y:0};if(E){if(o||a){var k="y"===y?mt:bt,L="y"===y?gt:_t,x="y"===y?"height":"width",D=E[y],S=E[y]+g[k],N=E[y]-g[L],I=f?-T[x]/2:0,P=b===wt?A[x]:T[x],j=b===wt?-T[x]:-A[x],M=e.elements.arrow,H=f&&M?Kt(M):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},R=B[k],W=B[L],$=oe(0,A[x],H[x]),z=v?A[x]/2-I-$-R-O:P-$-R-O,q=v?-A[x]/2+I+$+W+O:j+$+W+O,F=e.elements.arrow&&te(e.elements.arrow),U=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,V=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,K=E[y]+z-V-U,X=E[y]+q-V;if(o){var Y=oe(f?ne(S,K):S,D,f?ie(N,X):N);E[y]=Y,C[y]=Y-D}if(a){var Q="x"===y?mt:bt,G="x"===y?gt:_t,Z=E[w],J=Z+g[Q],tt=Z-g[G],et=oe(f?ne(J,K):J,Z,f?ie(tt,X):tt);E[w]=et,C[w]=et-Z}}e.modifiersData[n]=C}},requiresIfExists:["offset"]};function Me(t,e,i){void 0===i&&(i=!1);var n=zt(e);zt(e)&&function(t){var e=t.getBoundingClientRect();e.width,t.offsetWidth,e.height,t.offsetHeight}(e);var s,o,r=Gt(e),a=Vt(t),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(n||!n&&!i)&&(("body"!==Rt(e)||we(r))&&(l=(s=e)!==Wt(s)&&zt(s)?{scrollLeft:(o=s).scrollLeft,scrollTop:o.scrollTop}:ve(s)),zt(e)?((c=Vt(e)).x+=e.clientLeft,c.y+=e.clientTop):r&&(c.x=ye(r))),{x:a.left+l.scrollLeft-c.x,y:a.top+l.scrollTop-c.y,width:a.width,height:a.height}}function He(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Be={placement:"bottom",modifiers:[],strategy:"absolute"};function Re(){for(var t=arguments.length,e=new Array(t),i=0;ij.on(t,"mouseover",d))),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(Je),this._element.classList.add(Je),j.trigger(this._element,"shown.bs.dropdown",t)}hide(){if(c(this._element)||!this._isShown(this._menu))return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){j.trigger(this._element,"hide.bs.dropdown",t).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._popper&&this._popper.destroy(),this._menu.classList.remove(Je),this._element.classList.remove(Je),this._element.setAttribute("aria-expanded","false"),U.removeDataAttribute(this._menu,"popper"),j.trigger(this._element,"hidden.bs.dropdown",t))}_getConfig(t){if(t={...this.constructor.Default,...U.getDataAttributes(this._element),...t},a(Ue,t,this.constructor.DefaultType),"object"==typeof t.reference&&!o(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${Ue.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(t){if(void 0===Fe)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=t:o(this._config.reference)?e=r(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const i=this._getPopperConfig(),n=i.modifiers.find((t=>"applyStyles"===t.name&&!1===t.enabled));this._popper=qe(e,this._menu,i),n&&U.setDataAttribute(this._menu,"popper","static")}_isShown(t=this._element){return t.classList.contains(Je)}_getMenuElement(){return V.next(this._element,ei)[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains("dropend"))return ri;if(t.classList.contains("dropstart"))return ai;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?ni:ii:e?oi:si}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=V.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(l);i.length&&v(i,e,t===Ye,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(t&&(2===t.button||"keyup"===t.type&&"Tab"!==t.key))return;const e=V.find(ti);for(let i=0,n=e.length;ie+t)),this._setElementAttributes(di,"paddingRight",(e=>e+t)),this._setElementAttributes(ui,"marginRight",(e=>e-t))}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t)[e];t.style[e]=`${i(Number.parseFloat(s))}px`}))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,"paddingRight"),this._resetElementAttributes(di,"paddingRight"),this._resetElementAttributes(ui,"marginRight")}_saveInitialAttribute(t,e){const i=t.style[e];i&&U.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=U.getDataAttribute(t,e);void 0===i?t.style.removeProperty(e):(U.removeDataAttribute(t,e),t.style[e]=i)}))}_applyManipulationCallback(t,e){o(t)?e(t):V.find(t,this._element).forEach(e)}isOverflowing(){return this.getWidth()>0}}const pi={className:"modal-backdrop",isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},mi={className:"string",isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"},gi="show",_i="mousedown.bs.backdrop";class bi{constructor(t){this._config=this._getConfig(t),this._isAppended=!1,this._element=null}show(t){this._config.isVisible?(this._append(),this._config.isAnimated&&u(this._getElement()),this._getElement().classList.add(gi),this._emulateAnimation((()=>{_(t)}))):_(t)}hide(t){this._config.isVisible?(this._getElement().classList.remove(gi),this._emulateAnimation((()=>{this.dispose(),_(t)}))):_(t)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_getConfig(t){return(t={...pi,..."object"==typeof t?t:{}}).rootElement=r(t.rootElement),a("backdrop",t,mi),t}_append(){this._isAppended||(this._config.rootElement.append(this._getElement()),j.on(this._getElement(),_i,(()=>{_(this._config.clickCallback)})),this._isAppended=!0)}dispose(){this._isAppended&&(j.off(this._element,_i),this._element.remove(),this._isAppended=!1)}_emulateAnimation(t){b(t,this._getElement(),this._config.isAnimated)}}const vi={trapElement:null,autofocus:!0},yi={trapElement:"element",autofocus:"boolean"},wi=".bs.focustrap",Ei="backward";class Ai{constructor(t){this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}activate(){const{trapElement:t,autofocus:e}=this._config;this._isActive||(e&&t.focus(),j.off(document,wi),j.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),j.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,j.off(document,wi))}_handleFocusin(t){const{target:e}=t,{trapElement:i}=this._config;if(e===document||e===i||i.contains(e))return;const n=V.focusableChildren(i);0===n.length?i.focus():this._lastTabNavDirection===Ei?n[n.length-1].focus():n[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?Ei:"forward")}_getConfig(t){return t={...vi,..."object"==typeof t?t:{}},a("focustrap",t,yi),t}}const Ti="modal",Oi="Escape",Ci={backdrop:!0,keyboard:!0,focus:!0},ki={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"},Li="hidden.bs.modal",xi="show.bs.modal",Di="resize.bs.modal",Si="click.dismiss.bs.modal",Ni="keydown.dismiss.bs.modal",Ii="mousedown.dismiss.bs.modal",Pi="modal-open",ji="show",Mi="modal-static";class Hi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._dialog=V.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollBar=new fi}static get Default(){return Ci}static get NAME(){return Ti}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||j.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isAnimated()&&(this._isTransitioning=!0),this._scrollBar.hide(),document.body.classList.add(Pi),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),j.on(this._dialog,Ii,(()=>{j.one(this._element,"mouseup.dismiss.bs.modal",(t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)}))})),this._showBackdrop((()=>this._showElement(t))))}hide(){if(!this._isShown||this._isTransitioning)return;if(j.trigger(this._element,"hide.bs.modal").defaultPrevented)return;this._isShown=!1;const t=this._isAnimated();t&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),this._focustrap.deactivate(),this._element.classList.remove(ji),j.off(this._element,Si),j.off(this._dialog,Ii),this._queueCallback((()=>this._hideModal()),this._element,t)}dispose(){[window,this._dialog].forEach((t=>j.off(t,".bs.modal"))),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new bi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_getConfig(t){return t={...Ci,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Ti,t,ki),t}_showElement(t){const e=this._isAnimated(),i=V.findOne(".modal-body",this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,i&&(i.scrollTop=0),e&&u(this._element),this._element.classList.add(ji),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,j.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,e)}_setEscapeEvent(){this._isShown?j.on(this._element,Ni,(t=>{this._config.keyboard&&t.key===Oi?(t.preventDefault(),this.hide()):this._config.keyboard||t.key!==Oi||this._triggerBackdropTransition()})):j.off(this._element,Ni)}_setResizeEvent(){this._isShown?j.on(window,Di,(()=>this._adjustDialog())):j.off(window,Di)}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(Pi),this._resetAdjustments(),this._scrollBar.reset(),j.trigger(this._element,Li)}))}_showBackdrop(t){j.on(this._element,Si,(t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&(!0===this._config.backdrop?this.hide():"static"===this._config.backdrop&&this._triggerBackdropTransition())})),this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(j.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const{classList:t,scrollHeight:e,style:i}=this._element,n=e>document.documentElement.clientHeight;!n&&"hidden"===i.overflowY||t.contains(Mi)||(n||(i.overflowY="hidden"),t.add(Mi),this._queueCallback((()=>{t.remove(Mi),n||this._queueCallback((()=>{i.overflowY=""}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;(!i&&t&&!m()||i&&!t&&m())&&(this._element.style.paddingLeft=`${e}px`),(i&&!t&&!m()||!i&&t&&m())&&(this._element.style.paddingRight=`${e}px`)}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}j.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=n(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),j.one(e,xi,(t=>{t.defaultPrevented||j.one(e,Li,(()=>{l(this)&&this.focus()}))}));const i=V.findOne(".modal.show");i&&Hi.getInstance(i).hide(),Hi.getOrCreateInstance(e).toggle(this)})),R(Hi),g(Hi);const Bi="offcanvas",Ri={backdrop:!0,keyboard:!0,scroll:!1},Wi={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"},$i="show",zi=".offcanvas.show",qi="hidden.bs.offcanvas";class Fi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get NAME(){return Bi}static get Default(){return Ri}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||j.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._element.style.visibility="visible",this._backdrop.show(),this._config.scroll||(new fi).hide(),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add($i),this._queueCallback((()=>{this._config.scroll||this._focustrap.activate(),j.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(j.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.remove($i),this._backdrop.hide(),this._queueCallback((()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new fi).reset(),j.trigger(this._element,qi)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_getConfig(t){return t={...Ri,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Bi,t,Wi),t}_initializeBackDrop(){return new bi({className:"offcanvas-backdrop",isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_addEventListeners(){j.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{this._config.keyboard&&"Escape"===t.key&&this.hide()}))}static jQueryInterface(t){return this.each((function(){const e=Fi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}j.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=n(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this))return;j.one(e,qi,(()=>{l(this)&&this.focus()}));const i=V.findOne(zi);i&&i!==e&&Fi.getInstance(i).hide(),Fi.getOrCreateInstance(e).toggle(this)})),j.on(window,"load.bs.offcanvas.data-api",(()=>V.find(zi).forEach((t=>Fi.getOrCreateInstance(t).show())))),R(Fi),g(Fi);const Ui=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Vi=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,Ki=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Xi=(t,e)=>{const i=t.nodeName.toLowerCase();if(e.includes(i))return!Ui.has(i)||Boolean(Vi.test(t.nodeValue)||Ki.test(t.nodeValue));const n=e.filter((t=>t instanceof RegExp));for(let t=0,e=n.length;t{Xi(t,r)||i.removeAttribute(t.nodeName)}))}return n.body.innerHTML}const Qi="tooltip",Gi=new Set(["sanitize","allowList","sanitizeFn"]),Zi={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},Ji={AUTO:"auto",TOP:"top",RIGHT:m()?"left":"right",BOTTOM:"bottom",LEFT:m()?"right":"left"},tn={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},en={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},nn="fade",sn="show",on="show",rn="out",an=".tooltip-inner",ln=".modal",cn="hide.bs.modal",hn="hover",dn="focus";class un extends B{constructor(t,e){if(void 0===Fe)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this._config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return tn}static get NAME(){return Qi}static get Event(){return en}static get DefaultType(){return Zi}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains(sn))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),j.off(this._element.closest(ln),cn,this._hideModalHandler),this.tip&&this.tip.remove(),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const t=j.trigger(this._element,this.constructor.Event.SHOW),e=h(this._element),i=null===e?this._element.ownerDocument.documentElement.contains(this._element):e.contains(this._element);if(t.defaultPrevented||!i)return;"tooltip"===this.constructor.NAME&&this.tip&&this.getTitle()!==this.tip.querySelector(an).innerHTML&&(this._disposePopper(),this.tip.remove(),this.tip=null);const n=this.getTipElement(),s=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME);n.setAttribute("id",s),this._element.setAttribute("aria-describedby",s),this._config.animation&&n.classList.add(nn);const o="function"==typeof this._config.placement?this._config.placement.call(this,n,this._element):this._config.placement,r=this._getAttachment(o);this._addAttachmentClass(r);const{container:a}=this._config;H.set(n,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(a.append(n),j.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=qe(this._element,n,this._getPopperConfig(r)),n.classList.add(sn);const l=this._resolvePossibleFunction(this._config.customClass);l&&n.classList.add(...l.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>{j.on(t,"mouseover",d)}));const c=this.tip.classList.contains(nn);this._queueCallback((()=>{const t=this._hoverState;this._hoverState=null,j.trigger(this._element,this.constructor.Event.SHOWN),t===rn&&this._leave(null,this)}),this.tip,c)}hide(){if(!this._popper)return;const t=this.getTipElement();if(j.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented)return;t.classList.remove(sn),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1;const e=this.tip.classList.contains(nn);this._queueCallback((()=>{this._isWithActiveTrigger()||(this._hoverState!==on&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),j.trigger(this._element,this.constructor.Event.HIDDEN),this._disposePopper())}),this.tip,e),this._hoverState=""}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");t.innerHTML=this._config.template;const e=t.children[0];return this.setContent(e),e.classList.remove(nn,sn),this.tip=e,this.tip}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),an)}_sanitizeAndSetContent(t,e,i){const n=V.findOne(i,t);e||!n?this.setElementContent(n,e):n.remove()}setElementContent(t,e){if(null!==t)return o(e)?(e=r(e),void(this._config.html?e.parentNode!==t&&(t.innerHTML="",t.append(e)):t.textContent=e.textContent)):void(this._config.html?(this._config.sanitize&&(e=Yi(e,this._config.allowList,this._config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){const t=this._element.getAttribute("data-bs-original-title")||this._config.title;return this._resolvePossibleFunction(t)}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){return e||this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(t)}`)}_getAttachment(t){return Ji[t.toUpperCase()]}_setListeners(){this._config.trigger.split(" ").forEach((t=>{if("click"===t)j.on(this._element,this.constructor.Event.CLICK,this._config.selector,(t=>this.toggle(t)));else if("manual"!==t){const e=t===hn?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,i=t===hn?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;j.on(this._element,e,this._config.selector,(t=>this._enter(t))),j.on(this._element,i,this._config.selector,(t=>this._leave(t)))}})),this._hideModalHandler=()=>{this._element&&this.hide()},j.on(this._element.closest(ln),cn,this._hideModalHandler),this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?dn:hn]=!0),e.getTipElement().classList.contains(sn)||e._hoverState===on?e._hoverState=on:(clearTimeout(e._timeout),e._hoverState=on,e._config.delay&&e._config.delay.show?e._timeout=setTimeout((()=>{e._hoverState===on&&e.show()}),e._config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?dn:hn]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=rn,e._config.delay&&e._config.delay.hide?e._timeout=setTimeout((()=>{e._hoverState===rn&&e.hide()}),e._config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=U.getDataAttributes(this._element);return Object.keys(e).forEach((t=>{Gi.has(t)&&delete e[t]})),(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),a(Qi,t,this.constructor.DefaultType),t.sanitize&&(t.template=Yi(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`,"g"),i=t.getAttribute("class").match(e);null!==i&&i.length>0&&i.map((t=>t.trim())).forEach((e=>t.classList.remove(e)))}_getBasicClassPrefix(){return"bs-tooltip"}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null)}static jQueryInterface(t){return this.each((function(){const e=un.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(un);const fn={...un.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},pn={...un.DefaultType,content:"(string|element|function)"},mn={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"};class gn extends un{static get Default(){return fn}static get NAME(){return"popover"}static get Event(){return mn}static get DefaultType(){return pn}isWithContent(){return this.getTitle()||this._getContent()}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),".popover-header"),this._sanitizeAndSetContent(t,this._getContent(),".popover-body")}_getContent(){return this._resolvePossibleFunction(this._config.content)}_getBasicClassPrefix(){return"bs-popover"}static jQueryInterface(t){return this.each((function(){const e=gn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(gn);const _n="scrollspy",bn={offset:10,method:"auto",target:""},vn={offset:"number",method:"string",target:"(string|element)"},yn="active",wn=".nav-link, .list-group-item, .dropdown-item",En="position";class An extends B{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,j.on(this._scrollElement,"scroll.bs.scrollspy",(()=>this._process())),this.refresh(),this._process()}static get Default(){return bn}static get NAME(){return _n}refresh(){const t=this._scrollElement===this._scrollElement.window?"offset":En,e="auto"===this._config.method?t:this._config.method,n=e===En?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),V.find(wn,this._config.target).map((t=>{const s=i(t),o=s?V.findOne(s):null;if(o){const t=o.getBoundingClientRect();if(t.width||t.height)return[U[e](o).top+n,s]}return null})).filter((t=>t)).sort(((t,e)=>t[0]-e[0])).forEach((t=>{this._offsets.push(t[0]),this._targets.push(t[1])}))}dispose(){j.off(this._scrollElement,".bs.scrollspy"),super.dispose()}_getConfig(t){return(t={...bn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}}).target=r(t.target)||document.documentElement,a(_n,t,vn),t}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),i=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=i){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`)),i=V.findOne(e.join(","),this._config.target);i.classList.add(yn),i.classList.contains("dropdown-item")?V.findOne(".dropdown-toggle",i.closest(".dropdown")).classList.add(yn):V.parents(i,".nav, .list-group").forEach((t=>{V.prev(t,".nav-link, .list-group-item").forEach((t=>t.classList.add(yn))),V.prev(t,".nav-item").forEach((t=>{V.children(t,".nav-link").forEach((t=>t.classList.add(yn)))}))})),j.trigger(this._scrollElement,"activate.bs.scrollspy",{relatedTarget:t})}_clear(){V.find(wn,this._config.target).filter((t=>t.classList.contains(yn))).forEach((t=>t.classList.remove(yn)))}static jQueryInterface(t){return this.each((function(){const e=An.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(window,"load.bs.scrollspy.data-api",(()=>{V.find('[data-bs-spy="scroll"]').forEach((t=>new An(t)))})),g(An);const Tn="active",On="fade",Cn="show",kn=".active",Ln=":scope > li > .active";class xn extends B{static get NAME(){return"tab"}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains(Tn))return;let t;const e=n(this._element),i=this._element.closest(".nav, .list-group");if(i){const e="UL"===i.nodeName||"OL"===i.nodeName?Ln:kn;t=V.find(e,i),t=t[t.length-1]}const s=t?j.trigger(t,"hide.bs.tab",{relatedTarget:this._element}):null;if(j.trigger(this._element,"show.bs.tab",{relatedTarget:t}).defaultPrevented||null!==s&&s.defaultPrevented)return;this._activate(this._element,i);const o=()=>{j.trigger(t,"hidden.bs.tab",{relatedTarget:this._element}),j.trigger(this._element,"shown.bs.tab",{relatedTarget:t})};e?this._activate(e,e.parentNode,o):o()}_activate(t,e,i){const n=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?V.children(e,kn):V.find(Ln,e))[0],s=i&&n&&n.classList.contains(On),o=()=>this._transitionComplete(t,n,i);n&&s?(n.classList.remove(Cn),this._queueCallback(o,t,!0)):o()}_transitionComplete(t,e,i){if(e){e.classList.remove(Tn);const t=V.findOne(":scope > .dropdown-menu .active",e.parentNode);t&&t.classList.remove(Tn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add(Tn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),u(t),t.classList.contains(On)&&t.classList.add(Cn);let n=t.parentNode;if(n&&"LI"===n.nodeName&&(n=n.parentNode),n&&n.classList.contains("dropdown-menu")){const e=t.closest(".dropdown");e&&V.find(".dropdown-toggle",e).forEach((t=>t.classList.add(Tn))),t.setAttribute("aria-expanded",!0)}i&&i()}static jQueryInterface(t){return this.each((function(){const e=xn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this)||xn.getOrCreateInstance(this).show()})),g(xn);const Dn="toast",Sn="hide",Nn="show",In="showing",Pn={animation:"boolean",autohide:"boolean",delay:"number"},jn={animation:!0,autohide:!0,delay:5e3};class Mn extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get DefaultType(){return Pn}static get Default(){return jn}static get NAME(){return Dn}show(){j.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Sn),u(this._element),this._element.classList.add(Nn),this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.remove(In),j.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this._element.classList.contains(Nn)&&(j.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.add(Sn),this._element.classList.remove(In),this._element.classList.remove(Nn),j.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this._element.classList.contains(Nn)&&this._element.classList.remove(Nn),super.dispose()}_getConfig(t){return t={...jn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},a(Dn,t,this.constructor.DefaultType),t}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){j.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),j.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Mn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(Mn),g(Mn),{Alert:W,Button:z,Carousel:st,Collapse:pt,Dropdown:hi,Modal:Hi,Offcanvas:Fi,Popover:gn,ScrollSpy:An,Tab:xn,Toast:Mn,Tooltip:un}})); +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t="transitionend",e=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return e},i=t=>{const i=e(t);return i&&document.querySelector(i)?i:null},n=t=>{const i=e(t);return i?document.querySelector(i):null},s=e=>{e.dispatchEvent(new Event(t))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(t):null,a=(t,e,i)=>{Object.keys(i).forEach((n=>{const s=i[n],r=e[n],a=r&&o(r)?"element":null==(l=r)?`${l}`:{}.toString.call(l).match(/\s([a-z]+)/i)[1].toLowerCase();var l;if(!new RegExp(s).test(a))throw new TypeError(`${t.toUpperCase()}: Option "${n}" provided type "${a}" but expected type "${s}".`)}))},l=t=>!(!o(t)||0===t.getClientRects().length)&&"visible"===getComputedStyle(t).getPropertyValue("visibility"),c=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),h=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?h(t.parentNode):null},d=()=>{},u=t=>{t.offsetHeight},f=()=>{const{jQuery:t}=window;return t&&!document.body.hasAttribute("data-bs-no-jquery")?t:null},p=[],m=()=>"rtl"===document.documentElement.dir,g=t=>{var e;e=()=>{const e=f();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(p.length||document.addEventListener("DOMContentLoaded",(()=>{p.forEach((t=>t()))})),p.push(e)):e()},_=t=>{"function"==typeof t&&t()},b=(e,i,n=!0)=>{if(!n)return void _(e);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(i)+5;let r=!1;const a=({target:n})=>{n===i&&(r=!0,i.removeEventListener(t,a),_(e))};i.addEventListener(t,a),setTimeout((()=>{r||s(i)}),o)},v=(t,e,i,n)=>{let s=t.indexOf(e);if(-1===s)return t[!i&&n?t.length-1:0];const o=t.length;return s+=i?1:-1,n&&(s=(s+o)%o),t[Math.max(0,Math.min(s,o-1))]},y=/[^.]*(?=\..*)\.|.*/,w=/\..*/,E=/::\d+$/,A={};let T=1;const O={mouseenter:"mouseover",mouseleave:"mouseout"},C=/^(mouseenter|mouseleave)/i,k=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function L(t,e){return e&&`${e}::${T++}`||t.uidEvent||T++}function x(t){const e=L(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function D(t,e,i=null){const n=Object.keys(t);for(let s=0,o=n.length;sfunction(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};n?n=t(n):i=t(i)}const[o,r,a]=S(e,i,n),l=x(t),c=l[a]||(l[a]={}),h=D(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=L(r,e.replace(y,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(let a=o.length;a--;)if(o[a]===r)return s.delegateTarget=r,n.oneOff&&j.off(t,s.type,e,i),i.apply(r,[s]);return null}}(t,i,n):function(t,e){return function i(n){return n.delegateTarget=t,i.oneOff&&j.off(t,n.type,e),e.apply(t,[n])}}(t,i);u.delegationSelector=o?i:null,u.originalHandler=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function I(t,e,i,n,s){const o=D(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function P(t){return t=t.replace(w,""),O[t]||t}const j={on(t,e,i,n){N(t,e,i,n,!1)},one(t,e,i,n){N(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=S(e,i,n),a=r!==e,l=x(t),c=e.startsWith(".");if(void 0!==o){if(!l||!l[r])return;return void I(t,l,r,o,s?i:null)}c&&Object.keys(l).forEach((i=>{!function(t,e,i,n){const s=e[i]||{};Object.keys(s).forEach((o=>{if(o.includes(n)){const n=s[o];I(t,e,i,n.originalHandler,n.delegationSelector)}}))}(t,l,i,e.slice(1))}));const h=l[r]||{};Object.keys(h).forEach((i=>{const n=i.replace(E,"");if(!a||e.includes(n)){const e=h[i];I(t,l,r,e.originalHandler,e.delegationSelector)}}))},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=f(),s=P(e),o=e!==s,r=k.has(s);let a,l=!0,c=!0,h=!1,d=null;return o&&n&&(a=n.Event(e,i),n(t).trigger(a),l=!a.isPropagationStopped(),c=!a.isImmediatePropagationStopped(),h=a.isDefaultPrevented()),r?(d=document.createEvent("HTMLEvents"),d.initEvent(s,l,!0)):d=new CustomEvent(e,{bubbles:l,cancelable:!0}),void 0!==i&&Object.keys(i).forEach((t=>{Object.defineProperty(d,t,{get:()=>i[t]})})),h&&d.preventDefault(),c&&t.dispatchEvent(d),d.defaultPrevented&&void 0!==a&&a.preventDefault(),d}},M=new Map,H={set(t,e,i){M.has(t)||M.set(t,new Map);const n=M.get(t);n.has(e)||0===n.size?n.set(e,i):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(n.keys())[0]}.`)},get:(t,e)=>M.has(t)&&M.get(t).get(e)||null,remove(t,e){if(!M.has(t))return;const i=M.get(t);i.delete(e),0===i.size&&M.delete(t)}};class B{constructor(t){(t=r(t))&&(this._element=t,H.set(this._element,this.constructor.DATA_KEY,this))}dispose(){H.remove(this._element,this.constructor.DATA_KEY),j.off(this._element,this.constructor.EVENT_KEY),Object.getOwnPropertyNames(this).forEach((t=>{this[t]=null}))}_queueCallback(t,e,i=!0){b(t,e,i)}static getInstance(t){return H.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.1.3"}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}}const R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,s=t.NAME;j.on(document,i,`[data-bs-dismiss="${s}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),c(this))return;const o=n(this)||this.closest(`.${s}`);t.getOrCreateInstance(o)[e]()}))};class W extends B{static get NAME(){return"alert"}close(){if(j.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),j.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=W.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(W,"close"),g(W);const $='[data-bs-toggle="button"]';class z extends B{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=z.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}function q(t){return"true"===t||"false"!==t&&(t===Number(t).toString()?Number(t):""===t||"null"===t?null:t)}function F(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}j.on(document,"click.bs.button.data-api",$,(t=>{t.preventDefault();const e=t.target.closest($);z.getOrCreateInstance(e).toggle()})),g(z);const U={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={};return Object.keys(t.dataset).filter((t=>t.startsWith("bs"))).forEach((i=>{let n=i.replace(/^bs/,"");n=n.charAt(0).toLowerCase()+n.slice(1,n.length),e[n]=q(t.dataset[i])})),e},getDataAttribute:(t,e)=>q(t.getAttribute(`data-bs-${F(e)}`)),offset(t){const e=t.getBoundingClientRect();return{top:e.top+window.pageYOffset,left:e.left+window.pageXOffset}},position:t=>({top:t.offsetTop,left:t.offsetLeft})},V={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode;for(;n&&n.nodeType===Node.ELEMENT_NODE&&3!==n.nodeType;)n.matches(e)&&i.push(n),n=n.parentNode;return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(", ");return this.find(e,t).filter((t=>!c(t)&&l(t)))}},K="carousel",X={interval:5e3,keyboard:!0,slide:!1,pause:"hover",wrap:!0,touch:!0},Y={interval:"(number|boolean)",keyboard:"boolean",slide:"(boolean|string)",pause:"(string|boolean)",wrap:"boolean",touch:"boolean"},Q="next",G="prev",Z="left",J="right",tt={ArrowLeft:J,ArrowRight:Z},et="slid.bs.carousel",it="active",nt=".active.carousel-item";class st extends B{constructor(t,e){super(t),this._items=null,this._interval=null,this._activeElement=null,this._isPaused=!1,this._isSliding=!1,this.touchTimeout=null,this.touchStartX=0,this.touchDeltaX=0,this._config=this._getConfig(e),this._indicatorsElement=V.findOne(".carousel-indicators",this._element),this._touchSupported="ontouchstart"in document.documentElement||navigator.maxTouchPoints>0,this._pointerEvent=Boolean(window.PointerEvent),this._addEventListeners()}static get Default(){return X}static get NAME(){return K}next(){this._slide(Q)}nextWhenVisible(){!document.hidden&&l(this._element)&&this.next()}prev(){this._slide(G)}pause(t){t||(this._isPaused=!0),V.findOne(".carousel-item-next, .carousel-item-prev",this._element)&&(s(this._element),this.cycle(!0)),clearInterval(this._interval),this._interval=null}cycle(t){t||(this._isPaused=!1),this._interval&&(clearInterval(this._interval),this._interval=null),this._config&&this._config.interval&&!this._isPaused&&(this._updateInterval(),this._interval=setInterval((document.visibilityState?this.nextWhenVisible:this.next).bind(this),this._config.interval))}to(t){this._activeElement=V.findOne(nt,this._element);const e=this._getItemIndex(this._activeElement);if(t>this._items.length-1||t<0)return;if(this._isSliding)return void j.one(this._element,et,(()=>this.to(t)));if(e===t)return this.pause(),void this.cycle();const i=t>e?Q:G;this._slide(i,this._items[t])}_getConfig(t){return t={...X,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(K,t,Y),t}_handleSwipe(){const t=Math.abs(this.touchDeltaX);if(t<=40)return;const e=t/this.touchDeltaX;this.touchDeltaX=0,e&&this._slide(e>0?J:Z)}_addEventListeners(){this._config.keyboard&&j.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(j.on(this._element,"mouseenter.bs.carousel",(t=>this.pause(t))),j.on(this._element,"mouseleave.bs.carousel",(t=>this.cycle(t)))),this._config.touch&&this._touchSupported&&this._addTouchEventListeners()}_addTouchEventListeners(){const t=t=>this._pointerEvent&&("pen"===t.pointerType||"touch"===t.pointerType),e=e=>{t(e)?this.touchStartX=e.clientX:this._pointerEvent||(this.touchStartX=e.touches[0].clientX)},i=t=>{this.touchDeltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this.touchStartX},n=e=>{t(e)&&(this.touchDeltaX=e.clientX-this.touchStartX),this._handleSwipe(),"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((t=>this.cycle(t)),500+this._config.interval))};V.find(".carousel-item img",this._element).forEach((t=>{j.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()))})),this._pointerEvent?(j.on(this._element,"pointerdown.bs.carousel",(t=>e(t))),j.on(this._element,"pointerup.bs.carousel",(t=>n(t))),this._element.classList.add("pointer-event")):(j.on(this._element,"touchstart.bs.carousel",(t=>e(t))),j.on(this._element,"touchmove.bs.carousel",(t=>i(t))),j.on(this._element,"touchend.bs.carousel",(t=>n(t))))}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=tt[t.key];e&&(t.preventDefault(),this._slide(e))}_getItemIndex(t){return this._items=t&&t.parentNode?V.find(".carousel-item",t.parentNode):[],this._items.indexOf(t)}_getItemByOrder(t,e){const i=t===Q;return v(this._items,e,i,this._config.wrap)}_triggerSlideEvent(t,e){const i=this._getItemIndex(t),n=this._getItemIndex(V.findOne(nt,this._element));return j.trigger(this._element,"slide.bs.carousel",{relatedTarget:t,direction:e,from:n,to:i})}_setActiveIndicatorElement(t){if(this._indicatorsElement){const e=V.findOne(".active",this._indicatorsElement);e.classList.remove(it),e.removeAttribute("aria-current");const i=V.find("[data-bs-target]",this._indicatorsElement);for(let e=0;e{j.trigger(this._element,et,{relatedTarget:o,direction:d,from:s,to:r})};if(this._element.classList.contains("slide")){o.classList.add(h),u(o),n.classList.add(c),o.classList.add(c);const t=()=>{o.classList.remove(c,h),o.classList.add(it),n.classList.remove(it,h,c),this._isSliding=!1,setTimeout(f,0)};this._queueCallback(t,n,!0)}else n.classList.remove(it),o.classList.add(it),this._isSliding=!1,f();a&&this.cycle()}_directionToOrder(t){return[J,Z].includes(t)?m()?t===Z?G:Q:t===Z?Q:G:t}_orderToDirection(t){return[Q,G].includes(t)?m()?t===G?Z:J:t===G?J:Z:t}static carouselInterface(t,e){const i=st.getOrCreateInstance(t,e);let{_config:n}=i;"object"==typeof e&&(n={...n,...e});const s="string"==typeof e?e:n.slide;if("number"==typeof e)i.to(e);else if("string"==typeof s){if(void 0===i[s])throw new TypeError(`No method named "${s}"`);i[s]()}else n.interval&&n.ride&&(i.pause(),i.cycle())}static jQueryInterface(t){return this.each((function(){st.carouselInterface(this,t)}))}static dataApiClickHandler(t){const e=n(this);if(!e||!e.classList.contains("carousel"))return;const i={...U.getDataAttributes(e),...U.getDataAttributes(this)},s=this.getAttribute("data-bs-slide-to");s&&(i.interval=!1),st.carouselInterface(e,i),s&&st.getInstance(e).to(s),t.preventDefault()}}j.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",st.dataApiClickHandler),j.on(window,"load.bs.carousel.data-api",(()=>{const t=V.find('[data-bs-ride="carousel"]');for(let e=0,i=t.length;et===this._element));null!==s&&o.length&&(this._selector=s,this._triggerArray.push(e))}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return rt}static get NAME(){return ot}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t,e=[];if(this._config.parent){const t=V.find(ut,this._config.parent);e=V.find(".collapse.show, .collapse.collapsing",this._config.parent).filter((e=>!t.includes(e)))}const i=V.findOne(this._selector);if(e.length){const n=e.find((t=>i!==t));if(t=n?pt.getInstance(n):null,t&&t._isTransitioning)return}if(j.trigger(this._element,"show.bs.collapse").defaultPrevented)return;e.forEach((e=>{i!==e&&pt.getOrCreateInstance(e,{toggle:!1}).hide(),t||H.set(e,"bs.collapse",null)}));const n=this._getDimension();this._element.classList.remove(ct),this._element.classList.add(ht),this._element.style[n]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const s=`scroll${n[0].toUpperCase()+n.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct,lt),this._element.style[n]="",j.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[n]=`${this._element[s]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(j.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,u(this._element),this._element.classList.add(ht),this._element.classList.remove(ct,lt);const e=this._triggerArray.length;for(let t=0;t{this._isTransitioning=!1,this._element.classList.remove(ht),this._element.classList.add(ct),j.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(lt)}_getConfig(t){return(t={...rt,...U.getDataAttributes(this._element),...t}).toggle=Boolean(t.toggle),t.parent=r(t.parent),a(ot,t,at),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=V.find(ut,this._config.parent);V.find(ft,this._config.parent).filter((e=>!t.includes(e))).forEach((t=>{const e=n(t);e&&this._addAriaAndCollapsedClass([t],this._isShown(e))}))}_addAriaAndCollapsedClass(t,e){t.length&&t.forEach((t=>{e?t.classList.remove(dt):t.classList.add(dt),t.setAttribute("aria-expanded",e)}))}static jQueryInterface(t){return this.each((function(){const e={};"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1);const i=pt.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}j.on(document,"click.bs.collapse.data-api",ft,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();const e=i(this);V.find(e).forEach((t=>{pt.getOrCreateInstance(t,{toggle:!1}).toggle()}))})),g(pt);var mt="top",gt="bottom",_t="right",bt="left",vt="auto",yt=[mt,gt,_t,bt],wt="start",Et="end",At="clippingParents",Tt="viewport",Ot="popper",Ct="reference",kt=yt.reduce((function(t,e){return t.concat([e+"-"+wt,e+"-"+Et])}),[]),Lt=[].concat(yt,[vt]).reduce((function(t,e){return t.concat([e,e+"-"+wt,e+"-"+Et])}),[]),xt="beforeRead",Dt="read",St="afterRead",Nt="beforeMain",It="main",Pt="afterMain",jt="beforeWrite",Mt="write",Ht="afterWrite",Bt=[xt,Dt,St,Nt,It,Pt,jt,Mt,Ht];function Rt(t){return t?(t.nodeName||"").toLowerCase():null}function Wt(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function $t(t){return t instanceof Wt(t).Element||t instanceof Element}function zt(t){return t instanceof Wt(t).HTMLElement||t instanceof HTMLElement}function qt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof Wt(t).ShadowRoot||t instanceof ShadowRoot)}const Ft={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];zt(s)&&Rt(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});zt(n)&&Rt(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function Ut(t){return t.split("-")[0]}function Vt(t,e){var i=t.getBoundingClientRect();return{width:i.width/1,height:i.height/1,top:i.top/1,right:i.right/1,bottom:i.bottom/1,left:i.left/1,x:i.left/1,y:i.top/1}}function Kt(t){var e=Vt(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Xt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&qt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Yt(t){return Wt(t).getComputedStyle(t)}function Qt(t){return["table","td","th"].indexOf(Rt(t))>=0}function Gt(t){return(($t(t)?t.ownerDocument:t.document)||window.document).documentElement}function Zt(t){return"html"===Rt(t)?t:t.assignedSlot||t.parentNode||(qt(t)?t.host:null)||Gt(t)}function Jt(t){return zt(t)&&"fixed"!==Yt(t).position?t.offsetParent:null}function te(t){for(var e=Wt(t),i=Jt(t);i&&Qt(i)&&"static"===Yt(i).position;)i=Jt(i);return i&&("html"===Rt(i)||"body"===Rt(i)&&"static"===Yt(i).position)?e:i||function(t){var e=-1!==navigator.userAgent.toLowerCase().indexOf("firefox");if(-1!==navigator.userAgent.indexOf("Trident")&&zt(t)&&"fixed"===Yt(t).position)return null;for(var i=Zt(t);zt(i)&&["html","body"].indexOf(Rt(i))<0;){var n=Yt(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function ee(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}var ie=Math.max,ne=Math.min,se=Math.round;function oe(t,e,i){return ie(t,ne(e,i))}function re(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function ae(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const le={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=Ut(i.placement),l=ee(a),c=[bt,_t].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return re("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:ae(t,yt))}(s.padding,i),d=Kt(o),u="y"===l?mt:bt,f="y"===l?gt:_t,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=te(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,E=oe(v,w,y),A=l;i.modifiersData[n]=((e={})[A]=E,e.centerOffset=E-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Xt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function ce(t){return t.split("-")[1]}var he={top:"auto",right:"auto",bottom:"auto",left:"auto"};function de(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=!0===h?function(t){var e=t.x,i=t.y,n=window.devicePixelRatio||1;return{x:se(se(e*n)/n)||0,y:se(se(i*n)/n)||0}}(r):"function"==typeof h?h(r):r,u=d.x,f=void 0===u?0:u,p=d.y,m=void 0===p?0:p,g=r.hasOwnProperty("x"),_=r.hasOwnProperty("y"),b=bt,v=mt,y=window;if(c){var w=te(i),E="clientHeight",A="clientWidth";w===Wt(i)&&"static"!==Yt(w=Gt(i)).position&&"absolute"===a&&(E="scrollHeight",A="scrollWidth"),w=w,s!==mt&&(s!==bt&&s!==_t||o!==Et)||(v=gt,m-=w[E]-n.height,m*=l?1:-1),s!==bt&&(s!==mt&&s!==gt||o!==Et)||(b=_t,f-=w[A]-n.width,f*=l?1:-1)}var T,O=Object.assign({position:a},c&&he);return l?Object.assign({},O,((T={})[v]=_?"0":"",T[b]=g?"0":"",T.transform=(y.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",T)):Object.assign({},O,((e={})[v]=_?m+"px":"",e[b]=g?f+"px":"",e.transform="",e))}const ue={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:Ut(e.placement),variation:ce(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,de(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,de(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var fe={passive:!0};const pe={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=Wt(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,fe)})),a&&l.addEventListener("resize",i.update,fe),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,fe)})),a&&l.removeEventListener("resize",i.update,fe)}},data:{}};var me={left:"right",right:"left",bottom:"top",top:"bottom"};function ge(t){return t.replace(/left|right|bottom|top/g,(function(t){return me[t]}))}var _e={start:"end",end:"start"};function be(t){return t.replace(/start|end/g,(function(t){return _e[t]}))}function ve(t){var e=Wt(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ye(t){return Vt(Gt(t)).left+ve(t).scrollLeft}function we(t){var e=Yt(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ee(t){return["html","body","#document"].indexOf(Rt(t))>=0?t.ownerDocument.body:zt(t)&&we(t)?t:Ee(Zt(t))}function Ae(t,e){var i;void 0===e&&(e=[]);var n=Ee(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=Wt(n),r=s?[o].concat(o.visualViewport||[],we(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Ae(Zt(r)))}function Te(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Oe(t,e){return e===Tt?Te(function(t){var e=Wt(t),i=Gt(t),n=e.visualViewport,s=i.clientWidth,o=i.clientHeight,r=0,a=0;return n&&(s=n.width,o=n.height,/^((?!chrome|android).)*safari/i.test(navigator.userAgent)||(r=n.offsetLeft,a=n.offsetTop)),{width:s,height:o,x:r+ye(t),y:a}}(t)):zt(e)?function(t){var e=Vt(t);return e.top=e.top+t.clientTop,e.left=e.left+t.clientLeft,e.bottom=e.top+t.clientHeight,e.right=e.left+t.clientWidth,e.width=t.clientWidth,e.height=t.clientHeight,e.x=e.left,e.y=e.top,e}(e):Te(function(t){var e,i=Gt(t),n=ve(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=ie(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=ie(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+ye(t),l=-n.scrollTop;return"rtl"===Yt(s||i).direction&&(a+=ie(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(Gt(t)))}function Ce(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?Ut(s):null,r=s?ce(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;case(o){case mt:e={x:a,y:i.y-n.height};break;case gt:e={x:a,y:i.y+i.height};break;case _t:e={x:i.x+i.width,y:l};break;case bt:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?ee(o):null;if(null!=c){var h="y"===c?"height":"width";case(r){case wt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case Et:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ke(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.boundary,r=void 0===o?At:o,a=i.rootBoundary,l=void 0===a?Tt:a,c=i.elementContext,h=void 0===c?Ot:c,d=i.altBoundary,u=void 0!==d&&d,f=i.padding,p=void 0===f?0:f,m=re("number"!=typeof p?p:ae(p,yt)),g=h===Ot?Ct:Ot,_=t.rects.popper,b=t.elements[u?g:h],v=function(t,e,i){var n="clippingParents"===e?function(t){var e=Ae(Zt(t)),i=["absolute","fixed"].indexOf(Yt(t).position)>=0&&zt(t)?te(t):t;return $t(i)?e.filter((function(t){return $t(t)&&Xt(t,i)&&"body"!==Rt(t)})):[]}(t):[].concat(e),s=[].concat(n,[i]),o=s[0],r=s.reduce((function(e,i){var n=Oe(t,i);return e.top=ie(n.top,e.top),e.right=ne(n.right,e.right),e.bottom=ne(n.bottom,e.bottom),e.left=ie(n.left,e.left),e}),Oe(t,o));return r.width=r.right-r.left,r.height=r.bottom-r.top,r.x=r.left,r.y=r.top,r}($t(b)?b:b.contextElement||Gt(t.elements.popper),r,l),y=Vt(t.elements.reference),w=Ce({reference:y,element:_,strategy:"absolute",placement:s}),E=Te(Object.assign({},_,w)),A=h===Ot?E:y,T={top:v.top-A.top+m.top,bottom:A.bottom-v.bottom+m.bottom,left:v.left-A.left+m.left,right:A.right-v.right+m.right},O=t.modifiersData.offset;if(h===Ot&&O){var C=O[s];Object.keys(T).forEach((function(t){var e=[_t,gt].indexOf(t)>=0?1:-1,i=[mt,gt].indexOf(t)>=0?"y":"x";T[t]+=C[i]*e}))}return T}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?Lt:l,h=ce(n),d=h?a?kt:kt.filter((function(t){return ce(t)===h})):yt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ke(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[Ut(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const xe={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=Ut(g),b=l||(_!==g&&p?function(t){if(Ut(t)===vt)return[];var e=ge(t);return[be(t),e,be(e)]}(g):[ge(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(Ut(i)===vt?Le(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,E=new Map,A=!0,T=v[0],O=0;O=0,D=x?"width":"height",S=ke(e,{placement:C,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),N=x?L?_t:bt:L?gt:mt;y[D]>w[D]&&(N=ge(N));var I=ge(N),P=[];if(o&&P.push(S[k]<=0),a&&P.push(S[N]<=0,S[I]<=0),P.every((function(t){return t}))){T=C,A=!1;break}E.set(C,P)}if(A)for(var j=function(t){var e=v.find((function(e){var i=E.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},M=p?3:1;M>0&&"break"!==j(M);M--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function De(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Se(t){return[mt,_t,gt,bt].some((function(e){return t[e]>=0}))}const Ne={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ke(e,{elementContext:"reference"}),a=ke(e,{altBoundary:!0}),l=De(r,n),c=De(a,s,o),h=Se(l),d=Se(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},Ie={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=Lt.reduce((function(t,i){return t[i]=function(t,e,i){var n=Ut(t),s=[bt,mt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[bt,_t].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Pe={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=Ce({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},je={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ke(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=Ut(e.placement),b=ce(e.placement),v=!b,y=ee(_),w="x"===y?"y":"x",E=e.modifiersData.popperOffsets,A=e.rects.reference,T=e.rects.popper,O="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,C={x:0,y:0};if(E){if(o||a){var k="y"===y?mt:bt,L="y"===y?gt:_t,x="y"===y?"height":"width",D=E[y],S=E[y]+g[k],N=E[y]-g[L],I=f?-T[x]/2:0,P=b===wt?A[x]:T[x],j=b===wt?-T[x]:-A[x],M=e.elements.arrow,H=f&&M?Kt(M):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},R=B[k],W=B[L],$=oe(0,A[x],H[x]),z=v?A[x]/2-I-$-R-O:P-$-R-O,q=v?-A[x]/2+I+$+W+O:j+$+W+O,F=e.elements.arrow&&te(e.elements.arrow),U=F?"y"===y?F.clientTop||0:F.clientLeft||0:0,V=e.modifiersData.offset?e.modifiersData.offset[e.placement][y]:0,K=E[y]+z-V-U,X=E[y]+q-V;if(o){var Y=oe(f?ne(S,K):S,D,f?ie(N,X):N);E[y]=Y,C[y]=Y-D}if(a){var Q="x"===y?mt:bt,G="x"===y?gt:_t,Z=E[w],J=Z+g[Q],tt=Z-g[G],et=oe(f?ne(J,K):J,Z,f?ie(tt,X):tt);E[w]=et,C[w]=et-Z}}e.modifiersData[n]=C}},requiresIfExists:["offset"]};function Me(t,e,i){void 0===i&&(i=!1);var n=zt(e);zt(e)&&function(t){var e=t.getBoundingClientRect();e.width,t.offsetWidth,e.height,t.offsetHeight}(e);var s,o,r=Gt(e),a=Vt(t),l={scrollLeft:0,scrollTop:0},c={x:0,y:0};return(n||!n&&!i)&&(("body"!==Rt(e)||we(r))&&(l=(s=e)!==Wt(s)&&zt(s)?{scrollLeft:(o=s).scrollLeft,scrollTop:o.scrollTop}:ve(s)),zt(e)?((c=Vt(e)).x+=e.clientLeft,c.y+=e.clientTop):r&&(c.x=ye(r))),{x:a.left+l.scrollLeft-c.x,y:a.top+l.scrollTop-c.y,width:a.width,height:a.height}}function He(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var Be={placement:"bottom",modifiers:[],strategy:"absolute"};function Re(){for(var t=arguments.length,e=new Array(t),i=0;ij.on(t,"mouseover",d))),this._element.focus(),this._element.setAttribute("aria-expanded",!0),this._menu.classList.add(Je),this._element.classList.add(Je),j.trigger(this._element,"shown.bs.dropdown",t)}hide(){if(c(this._element)||!this._isShown(this._menu))return;const t={relatedTarget:this._element};this._completeHide(t)}dispose(){this._popper&&this._popper.destroy(),super.dispose()}update(){this._inNavbar=this._detectNavbar(),this._popper&&this._popper.update()}_completeHide(t){j.trigger(this._element,"hide.bs.dropdown",t).defaultPrevented||("ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._popper&&this._popper.destroy(),this._menu.classList.remove(Je),this._element.classList.remove(Je),this._element.setAttribute("aria-expanded","false"),U.removeDataAttribute(this._menu,"popper"),j.trigger(this._element,"hidden.bs.dropdown",t))}_getConfig(t){if(t={...this.constructor.Default,...U.getDataAttributes(this._element),...t},a(Ue,t,this.constructor.DefaultType),"object"==typeof t.reference&&!o(t.reference)&&"function"!=typeof t.reference.getBoundingClientRect)throw new TypeError(`${Ue.toUpperCase()}: Option "reference" provided type "object" without a required "getBoundingClientRect" method.`);return t}_createPopper(t){if(void 0===Fe)throw new TypeError("Bootstrap's dropdowns require Popper (https://popper.js.org)");let e=this._element;"parent"===this._config.reference?e=t:o(this._config.reference)?e=r(this._config.reference):"object"==typeof this._config.reference&&(e=this._config.reference);const i=this._getPopperConfig(),n=i.modifiers.find((t=>"applyStyles"===t.name&&!1===t.enabled));this._popper=qe(e,this._menu,i),n&&U.setDataAttribute(this._menu,"popper","static")}_isShown(t=this._element){return t.classList.contains(Je)}_getMenuElement(){return V.next(this._element,ei)[0]}_getPlacement(){const t=this._element.parentNode;if(t.classList.contains("dropend"))return ri;if(t.classList.contains("dropstart"))return ai;const e="end"===getComputedStyle(this._menu).getPropertyValue("--bs-position").trim();return t.classList.contains("dropup")?e?ni:ii:e?oi:si}_detectNavbar(){return null!==this._element.closest(".navbar")}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return"static"===this._config.display&&(t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,..."function"==typeof this._config.popperConfig?this._config.popperConfig(t):this._config.popperConfig}}_selectMenuItem({key:t,target:e}){const i=V.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter(l);i.length&&v(i,e,t===Ye,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(t&&(2===t.button||"keyup"===t.type&&"Tab"!==t.key))return;const e=V.find(ti);for(let i=0,n=e.length;ie+t)),this._setElementAttributes(di,"paddingRight",(e=>e+t)),this._setElementAttributes(ui,"marginRight",(e=>e-t))}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t)[e];t.style[e]=`${i(Number.parseFloat(s))}px`}))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,"paddingRight"),this._resetElementAttributes(di,"paddingRight"),this._resetElementAttributes(ui,"marginRight")}_saveInitialAttribute(t,e){const i=t.style[e];i&&U.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=U.getDataAttribute(t,e);void 0===i?t.style.removeProperty(e):(U.removeDataAttribute(t,e),t.style[e]=i)}))}_applyManipulationCallback(t,e){o(t)?e(t):V.find(t,this._element).forEach(e)}isOverflowing(){return this.getWidth()>0}}const pi={className:"modal-backdrop",isVisible:!0,isAnimated:!1,rootElement:"body",clickCallback:null},mi={className:"string",isVisible:"boolean",isAnimated:"boolean",rootElement:"(element|string)",clickCallback:"(function|null)"},gi="show",_i="mousedown.bs.backdrop";class bi{constructor(t){this._config=this._getConfig(t),this._isAppended=!1,this._element=null}show(t){this._config.isVisible?(this._append(),this._config.isAnimated&&u(this._getElement()),this._getElement().classList.add(gi),this._emulateAnimation((()=>{_(t)}))):_(t)}hide(t){this._config.isVisible?(this._getElement().classList.remove(gi),this._emulateAnimation((()=>{this.dispose(),_(t)}))):_(t)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_getConfig(t){return(t={...pi,..."object"==typeof t?t:{}}).rootElement=r(t.rootElement),a("backdrop",t,mi),t}_append(){this._isAppended||(this._config.rootElement.append(this._getElement()),j.on(this._getElement(),_i,(()=>{_(this._config.clickCallback)})),this._isAppended=!0)}dispose(){this._isAppended&&(j.off(this._element,_i),this._element.remove(),this._isAppended=!1)}_emulateAnimation(t){b(t,this._getElement(),this._config.isAnimated)}}const vi={trapElement:null,autofocus:!0},yi={trapElement:"element",autofocus:"boolean"},wi=".bs.focustrap",Ei="backward";class Ai{constructor(t){this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}activate(){const{trapElement:t,autofocus:e}=this._config;this._isActive||(e&&t.focus(),j.off(document,wi),j.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),j.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,j.off(document,wi))}_handleFocusin(t){const{target:e}=t,{trapElement:i}=this._config;if(e===document||e===i||i.contains(e))return;const n=V.focusableChildren(i);0===n.length?i.focus():this._lastTabNavDirection===Ei?n[n.length-1].focus():n[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?Ei:"forward")}_getConfig(t){return t={...vi,..."object"==typeof t?t:{}},a("focustrap",t,yi),t}}const Ti="modal",Oi="Escape",Ci={backdrop:!0,keyboard:!0,focus:!0},ki={backdrop:"(boolean|string)",keyboard:"boolean",focus:"boolean"},Li="hidden.bs.modal",xi="show.bs.modal",Di="resize.bs.modal",Si="click.dismiss.bs.modal",Ni="keydown.dismiss.bs.modal",Ii="mousedown.dismiss.bs.modal",Pi="modal-open",ji="show",Mi="modal-static";class Hi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._dialog=V.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._ignoreBackdropClick=!1,this._isTransitioning=!1,this._scrollBar=new fi}static get Default(){return Ci}static get NAME(){return Ti}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||j.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isAnimated()&&(this._isTransitioning=!0),this._scrollBar.hide(),document.body.classList.add(Pi),this._adjustDialog(),this._setEscapeEvent(),this._setResizeEvent(),j.on(this._dialog,Ii,(()=>{j.one(this._element,"mouseup.dismiss.bs.modal",(t=>{t.target===this._element&&(this._ignoreBackdropClick=!0)}))})),this._showBackdrop((()=>this._showElement(t))))}hide(){if(!this._isShown||this._isTransitioning)return;if(j.trigger(this._element,"hide.bs.modal").defaultPrevented)return;this._isShown=!1;const t=this._isAnimated();t&&(this._isTransitioning=!0),this._setEscapeEvent(),this._setResizeEvent(),this._focustrap.deactivate(),this._element.classList.remove(ji),j.off(this._element,Si),j.off(this._dialog,Ii),this._queueCallback((()=>this._hideModal()),this._element,t)}dispose(){[window,this._dialog].forEach((t=>j.off(t,".bs.modal"))),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new bi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_getConfig(t){return t={...Ci,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Ti,t,ki),t}_showElement(t){const e=this._isAnimated(),i=V.findOne(".modal-body",this._dialog);this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0,i&&(i.scrollTop=0),e&&u(this._element),this._element.classList.add(ji),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,j.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,e)}_setEscapeEvent(){this._isShown?j.on(this._element,Ni,(t=>{this._config.keyboard&&t.key===Oi?(t.preventDefault(),this.hide()):this._config.keyboard||t.key!==Oi||this._triggerBackdropTransition()})):j.off(this._element,Ni)}_setResizeEvent(){this._isShown?j.on(window,Di,(()=>this._adjustDialog())):j.off(window,Di)}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(Pi),this._resetAdjustments(),this._scrollBar.reset(),j.trigger(this._element,Li)}))}_showBackdrop(t){j.on(this._element,Si,(t=>{this._ignoreBackdropClick?this._ignoreBackdropClick=!1:t.target===t.currentTarget&&(!0===this._config.backdrop?this.hide():"static"===this._config.backdrop&&this._triggerBackdropTransition())})),this._backdrop.show(t)}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(j.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const{classList:t,scrollHeight:e,style:i}=this._element,n=e>document.documentElement.clientHeight;!n&&"hidden"===i.overflowY||t.contains(Mi)||(n||(i.overflowY="hidden"),t.add(Mi),this._queueCallback((()=>{t.remove(Mi),n||this._queueCallback((()=>{i.overflowY=""}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;(!i&&t&&!m()||i&&!t&&m())&&(this._element.style.paddingLeft=`${e}px`),(i&&!t&&!m()||!i&&t&&m())&&(this._element.style.paddingRight=`${e}px`)}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Hi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}j.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=n(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),j.one(e,xi,(t=>{t.defaultPrevented||j.one(e,Li,(()=>{l(this)&&this.focus()}))}));const i=V.findOne(".modal.show");i&&Hi.getInstance(i).hide(),Hi.getOrCreateInstance(e).toggle(this)})),R(Hi),g(Hi);const Bi="offcanvas",Ri={backdrop:!0,keyboard:!0,scroll:!1},Wi={backdrop:"boolean",keyboard:"boolean",scroll:"boolean"},$i="show",zi=".offcanvas.show",qi="hidden.bs.offcanvas";class Fi extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get NAME(){return Bi}static get Default(){return Ri}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||j.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._element.style.visibility="visible",this._backdrop.show(),this._config.scroll||(new fi).hide(),this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add($i),this._queueCallback((()=>{this._config.scroll||this._focustrap.activate(),j.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(j.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.remove($i),this._backdrop.hide(),this._queueCallback((()=>{this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._element.style.visibility="hidden",this._config.scroll||(new fi).reset(),j.trigger(this._element,qi)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_getConfig(t){return t={...Ri,...U.getDataAttributes(this._element),..."object"==typeof t?t:{}},a(Bi,t,Wi),t}_initializeBackDrop(){return new bi({className:"offcanvas-backdrop",isVisible:this._config.backdrop,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:()=>this.hide()})}_initializeFocusTrap(){return new Ai({trapElement:this._element})}_addEventListeners(){j.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{this._config.keyboard&&"Escape"===t.key&&this.hide()}))}static jQueryInterface(t){return this.each((function(){const e=Fi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}j.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=n(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this))return;j.one(e,qi,(()=>{l(this)&&this.focus()}));const i=V.findOne(zi);i&&i!==e&&Fi.getInstance(i).hide(),Fi.getOrCreateInstance(e).toggle(this)})),j.on(window,"load.bs.offcanvas.data-api",(()=>V.find(zi).forEach((t=>Fi.getOrCreateInstance(t).show())))),R(Fi),g(Fi);const Ui=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Vi=/^(?:(?:https?|mailto|ftp|tel|file|sms):|[^#&/:?]*(?:[#/?]|$))/i,Ki=/^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[\d+/a-z]+=*$/i,Xi=(t,e)=>{const i=t.nodeName.toLowerCase();if(e.includes(i))return!Ui.has(i)||Boolean(Vi.test(t.nodeValue)||Ki.test(t.nodeValue));const n=e.filter((t=>t instanceof RegExp));for(let t=0,e=n.length;t{Xi(t,r)||i.removeAttribute(t.nodeName)}))}return n.body.innerHTML}const Qi="tooltip",Gi=new Set(["sanitize","allowList","sanitizeFn"]),Zi={animation:"boolean",template:"string",title:"(string|element|function)",trigger:"string",delay:"(number|object)",html:"boolean",selector:"(string|boolean)",placement:"(string|function)",offset:"(array|string|function)",container:"(string|element|boolean)",fallbackPlacements:"array",boundary:"(string|element)",customClass:"(string|function)",sanitize:"boolean",sanitizeFn:"(null|function)",allowList:"object",popperConfig:"(null|object|function)"},Ji={AUTO:"auto",TOP:"top",RIGHT:m()?"left":"right",BOTTOM:"bottom",LEFT:m()?"right":"left"},tn={animation:!0,template:'',trigger:"hover focus",title:"",delay:0,html:!1,selector:!1,placement:"top",offset:[0,0],container:!1,fallbackPlacements:["top","right","bottom","left"],boundary:"clippingParents",customClass:"",sanitize:!0,sanitizeFn:null,allowList:{"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},popperConfig:null},en={HIDE:"hide.bs.tooltip",HIDDEN:"hidden.bs.tooltip",SHOW:"show.bs.tooltip",SHOWN:"shown.bs.tooltip",INSERTED:"inserted.bs.tooltip",CLICK:"click.bs.tooltip",FOCUSIN:"focusin.bs.tooltip",FOCUSOUT:"focusout.bs.tooltip",MOUSEENTER:"mouseenter.bs.tooltip",MOUSELEAVE:"mouseleave.bs.tooltip"},nn="fade",sn="show",on="show",rn="out",an=".tooltip-inner",ln=".modal",cn="hide.bs.modal",hn="hover",dn="focus";class un extends B{constructor(t,e){if(void 0===Fe)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t),this._isEnabled=!0,this._timeout=0,this._hoverState="",this._activeTrigger={},this._popper=null,this._config=this._getConfig(e),this.tip=null,this._setListeners()}static get Default(){return tn}static get NAME(){return Qi}static get Event(){return en}static get DefaultType(){return Zi}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(t){if(this._isEnabled)if(t){const e=this._initializeOnDelegatedTarget(t);e._activeTrigger.click=!e._activeTrigger.click,e._isWithActiveTrigger()?e._enter(null,e):e._leave(null,e)}else{if(this.getTipElement().classList.contains(sn))return void this._leave(null,this);this._enter(null,this)}}dispose(){clearTimeout(this._timeout),j.off(this._element.closest(ln),cn,this._hideModalHandler),this.tip&&this.tip.remove(),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this.isWithContent()||!this._isEnabled)return;const t=j.trigger(this._element,this.constructor.Event.SHOW),e=h(this._element),i=null===e?this._element.ownerDocument.documentElement.contains(this._element):e.contains(this._element);if(t.defaultPrevented||!i)return;"tooltip"===this.constructor.NAME&&this.tip&&this.getTitle()!==this.tip.querySelector(an).innerHTML&&(this._disposePopper(),this.tip.remove(),this.tip=null);const n=this.getTipElement(),s=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME);n.setAttribute("id",s),this._element.setAttribute("aria-describedby",s),this._config.animation&&n.classList.add(nn);const o="function"==typeof this._config.placement?this._config.placement.call(this,n,this._element):this._config.placement,r=this._getAttachment(o);this._addAttachmentClass(r);const{container:a}=this._config;H.set(n,this.constructor.DATA_KEY,this),this._element.ownerDocument.documentElement.contains(this.tip)||(a.append(n),j.trigger(this._element,this.constructor.Event.INSERTED)),this._popper?this._popper.update():this._popper=qe(this._element,n,this._getPopperConfig(r)),n.classList.add(sn);const l=this._resolvePossibleFunction(this._config.customClass);l&&n.classList.add(...l.split(" ")),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>{j.on(t,"mouseover",d)}));const c=this.tip.classList.contains(nn);this._queueCallback((()=>{const t=this._hoverState;this._hoverState=null,j.trigger(this._element,this.constructor.Event.SHOWN),t===rn&&this._leave(null,this)}),this.tip,c)}hide(){if(!this._popper)return;const t=this.getTipElement();if(j.trigger(this._element,this.constructor.Event.HIDE).defaultPrevented)return;t.classList.remove(sn),"ontouchstart"in document.documentElement&&[].concat(...document.body.children).forEach((t=>j.off(t,"mouseover",d))),this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1;const e=this.tip.classList.contains(nn);this._queueCallback((()=>{this._isWithActiveTrigger()||(this._hoverState!==on&&t.remove(),this._cleanTipClass(),this._element.removeAttribute("aria-describedby"),j.trigger(this._element,this.constructor.Event.HIDDEN),this._disposePopper())}),this.tip,e),this._hoverState=""}update(){null!==this._popper&&this._popper.update()}isWithContent(){return Boolean(this.getTitle())}getTipElement(){if(this.tip)return this.tip;const t=document.createElement("div");t.innerHTML=this._config.template;const e=t.children[0];return this.setContent(e),e.classList.remove(nn,sn),this.tip=e,this.tip}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),an)}_sanitizeAndSetContent(t,e,i){const n=V.findOne(i,t);e||!n?this.setElementContent(n,e):n.remove()}setElementContent(t,e){if(null!==t)return o(e)?(e=r(e),void(this._config.html?e.parentNode!==t&&(t.innerHTML="",t.append(e)):t.textContent=e.textContent)):void(this._config.html?(this._config.sanitize&&(e=Yi(e,this._config.allowList,this._config.sanitizeFn)),t.innerHTML=e):t.textContent=e)}getTitle(){const t=this._element.getAttribute("data-bs-original-title")||this._config.title;return this._resolvePossibleFunction(t)}updateAttachment(t){return"right"===t?"end":"left"===t?"start":t}_initializeOnDelegatedTarget(t,e){return e||this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return"function"==typeof t?t.call(this._element):t}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"onChange",enabled:!0,phase:"afterWrite",fn:t=>this._handlePopperPlacementChange(t)}],onFirstUpdate:t=>{t.options.placement!==t.placement&&this._handlePopperPlacementChange(t)}};return{...e,..."function"==typeof this._config.popperConfig?this._config.popperConfig(e):this._config.popperConfig}}_addAttachmentClass(t){this.getTipElement().classList.add(`${this._getBasicClassPrefix()}-${this.updateAttachment(t)}`)}_getAttachment(t){return Ji[t.toUpperCase()]}_setListeners(){this._config.trigger.split(" ").forEach((t=>{if("click"===t)j.on(this._element,this.constructor.Event.CLICK,this._config.selector,(t=>this.toggle(t)));else if("manual"!==t){const e=t===hn?this.constructor.Event.MOUSEENTER:this.constructor.Event.FOCUSIN,i=t===hn?this.constructor.Event.MOUSELEAVE:this.constructor.Event.FOCUSOUT;j.on(this._element,e,this._config.selector,(t=>this._enter(t))),j.on(this._element,i,this._config.selector,(t=>this._leave(t)))}})),this._hideModalHandler=()=>{this._element&&this.hide()},j.on(this._element.closest(ln),cn,this._hideModalHandler),this._config.selector?this._config={...this._config,trigger:"manual",selector:""}:this._fixTitle()}_fixTitle(){const t=this._element.getAttribute("title"),e=typeof this._element.getAttribute("data-bs-original-title");(t||"string"!==e)&&(this._element.setAttribute("data-bs-original-title",t||""),!t||this._element.getAttribute("aria-label")||this._element.textContent||this._element.setAttribute("aria-label",t),this._element.setAttribute("title",""))}_enter(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusin"===t.type?dn:hn]=!0),e.getTipElement().classList.contains(sn)||e._hoverState===on?e._hoverState=on:(clearTimeout(e._timeout),e._hoverState=on,e._config.delay&&e._config.delay.show?e._timeout=setTimeout((()=>{e._hoverState===on&&e.show()}),e._config.delay.show):e.show())}_leave(t,e){e=this._initializeOnDelegatedTarget(t,e),t&&(e._activeTrigger["focusout"===t.type?dn:hn]=e._element.contains(t.relatedTarget)),e._isWithActiveTrigger()||(clearTimeout(e._timeout),e._hoverState=rn,e._config.delay&&e._config.delay.hide?e._timeout=setTimeout((()=>{e._hoverState===rn&&e.hide()}),e._config.delay.hide):e.hide())}_isWithActiveTrigger(){for(const t in this._activeTrigger)if(this._activeTrigger[t])return!0;return!1}_getConfig(t){const e=U.getDataAttributes(this._element);return Object.keys(e).forEach((t=>{Gi.has(t)&&delete e[t]})),(t={...this.constructor.Default,...e,..."object"==typeof t&&t?t:{}}).container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),a(Qi,t,this.constructor.DefaultType),t.sanitize&&(t.template=Yi(t.template,t.allowList,t.sanitizeFn)),t}_getDelegateConfig(){const t={};for(const e in this._config)this.constructor.Default[e]!==this._config[e]&&(t[e]=this._config[e]);return t}_cleanTipClass(){const t=this.getTipElement(),e=new RegExp(`(^|\\s)${this._getBasicClassPrefix()}\\S+`,"g"),i=t.getAttribute("class").match(e);null!==i&&i.length>0&&i.map((t=>t.trim())).forEach((e=>t.classList.remove(e)))}_getBasicClassPrefix(){return"bs-tooltip"}_handlePopperPlacementChange(t){const{state:e}=t;e&&(this.tip=e.elements.popper,this._cleanTipClass(),this._addAttachmentClass(this._getAttachment(e.placement)))}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null)}static jQueryInterface(t){return this.each((function(){const e=un.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(un);const fn={...un.Default,placement:"right",offset:[0,8],trigger:"click",content:"",template:''},pn={...un.DefaultType,content:"(string|element|function)"},mn={HIDE:"hide.bs.popover",HIDDEN:"hidden.bs.popover",SHOW:"show.bs.popover",SHOWN:"shown.bs.popover",INSERTED:"inserted.bs.popover",CLICK:"click.bs.popover",FOCUSIN:"focusin.bs.popover",FOCUSOUT:"focusout.bs.popover",MOUSEENTER:"mouseenter.bs.popover",MOUSELEAVE:"mouseleave.bs.popover"};class gn extends un{static get Default(){return fn}static get NAME(){return"popover"}static get Event(){return mn}static get DefaultType(){return pn}isWithContent(){return this.getTitle()||this._getContent()}setContent(t){this._sanitizeAndSetContent(t,this.getTitle(),".popover-header"),this._sanitizeAndSetContent(t,this._getContent(),".popover-body")}_getContent(){return this._resolvePossibleFunction(this._config.content)}_getBasicClassPrefix(){return"bs-popover"}static jQueryInterface(t){return this.each((function(){const e=gn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}g(gn);const _n="scrollspy",bn={offset:10,method:"auto",target:""},vn={offset:"number",method:"string",target:"(string|element)"},yn="active",wn=".nav-link, .list-group-item, .dropdown-item",En="position";class An extends B{constructor(t,e){super(t),this._scrollElement="BODY"===this._element.tagName?window:this._element,this._config=this._getConfig(e),this._offsets=[],this._targets=[],this._activeTarget=null,this._scrollHeight=0,j.on(this._scrollElement,"scroll.bs.scrollspy",(()=>this._process())),this.refresh(),this._process()}static get Default(){return bn}static get NAME(){return _n}refresh(){const t=this._scrollElement===this._scrollElement.window?"offset":En,e="auto"===this._config.method?t:this._config.method,n=e===En?this._getScrollTop():0;this._offsets=[],this._targets=[],this._scrollHeight=this._getScrollHeight(),V.find(wn,this._config.target).map((t=>{const s=i(t),o=s?V.findOne(s):null;if(o){const t=o.getBoundingClientRect();if(t.width||t.height)return[U[e](o).top+n,s]}return null})).filter((t=>t)).sort(((t,e)=>t[0]-e[0])).forEach((t=>{this._offsets.push(t[0]),this._targets.push(t[1])}))}dispose(){j.off(this._scrollElement,".bs.scrollspy"),super.dispose()}_getConfig(t){return(t={...bn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}}).target=r(t.target)||document.documentElement,a(_n,t,vn),t}_getScrollTop(){return this._scrollElement===window?this._scrollElement.pageYOffset:this._scrollElement.scrollTop}_getScrollHeight(){return this._scrollElement.scrollHeight||Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)}_getOffsetHeight(){return this._scrollElement===window?window.innerHeight:this._scrollElement.getBoundingClientRect().height}_process(){const t=this._getScrollTop()+this._config.offset,e=this._getScrollHeight(),i=this._config.offset+e-this._getOffsetHeight();if(this._scrollHeight!==e&&this.refresh(),t>=i){const t=this._targets[this._targets.length-1];this._activeTarget!==t&&this._activate(t)}else{if(this._activeTarget&&t0)return this._activeTarget=null,void this._clear();for(let e=this._offsets.length;e--;)this._activeTarget!==this._targets[e]&&t>=this._offsets[e]&&(void 0===this._offsets[e+1]||t`${e}[data-bs-target="${t}"],${e}[href="${t}"]`)),i=V.findOne(e.join(","),this._config.target);i.classList.add(yn),i.classList.contains("dropdown-item")?V.findOne(".dropdown-toggle",i.closest(".dropdown")).classList.add(yn):V.parents(i,".nav, .list-group").forEach((t=>{V.prev(t,".nav-link, .list-group-item").forEach((t=>t.classList.add(yn))),V.prev(t,".nav-item").forEach((t=>{V.children(t,".nav-link").forEach((t=>t.classList.add(yn)))}))})),j.trigger(this._scrollElement,"activate.bs.scrollspy",{relatedTarget:t})}_clear(){V.find(wn,this._config.target).filter((t=>t.classList.contains(yn))).forEach((t=>t.classList.remove(yn)))}static jQueryInterface(t){return this.each((function(){const e=An.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(window,"load.bs.scrollspy.data-api",(()=>{V.find('[data-bs-spy="scroll"]').forEach((t=>new An(t)))})),g(An);const Tn="active",On="fade",Cn="show",kn=".active",Ln=":scope > li > .active";class xn extends B{static get NAME(){return"tab"}show(){if(this._element.parentNode&&this._element.parentNode.nodeType===Node.ELEMENT_NODE&&this._element.classList.contains(Tn))return;let t;const e=n(this._element),i=this._element.closest(".nav, .list-group");if(i){const e="UL"===i.nodeName||"OL"===i.nodeName?Ln:kn;t=V.find(e,i),t=t[t.length-1]}const s=t?j.trigger(t,"hide.bs.tab",{relatedTarget:this._element}):null;if(j.trigger(this._element,"show.bs.tab",{relatedTarget:t}).defaultPrevented||null!==s&&s.defaultPrevented)return;this._activate(this._element,i);const o=()=>{j.trigger(t,"hidden.bs.tab",{relatedTarget:this._element}),j.trigger(this._element,"shown.bs.tab",{relatedTarget:t})};e?this._activate(e,e.parentNode,o):o()}_activate(t,e,i){const n=(!e||"UL"!==e.nodeName&&"OL"!==e.nodeName?V.children(e,kn):V.find(Ln,e))[0],s=i&&n&&n.classList.contains(On),o=()=>this._transitionComplete(t,n,i);n&&s?(n.classList.remove(Cn),this._queueCallback(o,t,!0)):o()}_transitionComplete(t,e,i){if(e){e.classList.remove(Tn);const t=V.findOne(":scope > .dropdown-menu .active",e.parentNode);t&&t.classList.remove(Tn),"tab"===e.getAttribute("role")&&e.setAttribute("aria-selected",!1)}t.classList.add(Tn),"tab"===t.getAttribute("role")&&t.setAttribute("aria-selected",!0),u(t),t.classList.contains(On)&&t.classList.add(Cn);let n=t.parentNode;if(n&&"LI"===n.nodeName&&(n=n.parentNode),n&&n.classList.contains("dropdown-menu")){const e=t.closest(".dropdown");e&&V.find(".dropdown-toggle",e).forEach((t=>t.classList.add(Tn))),t.setAttribute("aria-expanded",!0)}i&&i()}static jQueryInterface(t){return this.each((function(){const e=xn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}j.on(document,"click.bs.tab.data-api",'[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),c(this)||xn.getOrCreateInstance(this).show()})),g(xn);const Dn="toast",Sn="hide",Nn="show",In="showing",Pn={animation:"boolean",autohide:"boolean",delay:"number"},jn={animation:!0,autohide:!0,delay:5e3};class Mn extends B{constructor(t,e){super(t),this._config=this._getConfig(e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get DefaultType(){return Pn}static get Default(){return jn}static get NAME(){return Dn}show(){j.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(Sn),u(this._element),this._element.classList.add(Nn),this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.remove(In),j.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this._element.classList.contains(Nn)&&(j.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(In),this._queueCallback((()=>{this._element.classList.add(Sn),this._element.classList.remove(In),this._element.classList.remove(Nn),j.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this._element.classList.contains(Nn)&&this._element.classList.remove(Nn),super.dispose()}_getConfig(t){return t={...jn,...U.getDataAttributes(this._element),..."object"==typeof t&&t?t:{}},a(Dn,t,this.constructor.DefaultType),t}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){case(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){j.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),j.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),j.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Mn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(Mn),g(Mn),{Alert:W,Button:z,Carousel:st,Collapse:pt,Dropdown:hi,Modal:Hi,Offcanvas:Fi,Popover:gn,ScrollSpy:An,Tab:xn,Toast:Mn,Tooltip:un}})); //# sourceMappingURL=bootstrap.bundle.min.js.map diff --git a/website/themes/prql-theme/static/plugins/highlight/highlight.min.js b/website/themes/prql-theme/static/plugins/highlight/highlight.min.js index 4bb7f08157d4..9c9d11726b67 100644 --- a/website/themes/prql-theme/static/plugins/highlight/highlight.min.js +++ b/website/themes/prql-theme/static/plugins/highlight/highlight.min.js @@ -304,7 +304,7 @@ anyNumberOfTimes:u};for(const t in A)"object"==typeof A[t]&&e.exports(A[t]) ;return Object.assign(t,A),t})({});return te}() ;"object"==typeof exports&&"undefined"!=typeof module&&(module.exports=hljs);/*! `javascript` grammar compiled for Highlight.js 11.7.0 */ (()=>{var e=(()=>{"use strict" -;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","switch","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) +;const e="[A-Za-z$_][0-9A-Za-z$_]*",n=["as","in","of","if","for","while","finally","var","new","function","do","return","void","else","break","catch","instanceof","with","throw","case","default","try","case","continue","typeof","delete","let","yield","const","class","debugger","async","await","static","import","from","export","extends"],a=["true","false","null","undefined","NaN","Infinity"],t=["Object","Function","Boolean","Symbol","Math","Date","Number","BigInt","String","RegExp","Array","Float32Array","Float64Array","Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Int32Array","Uint16Array","Uint32Array","BigInt64Array","BigUint64Array","Set","Map","WeakSet","WeakMap","ArrayBuffer","SharedArrayBuffer","Atomics","DataView","JSON","Promise","Generator","GeneratorFunction","AsyncFunction","Reflect","Proxy","Intl","WebAssembly"],s=["Error","EvalError","InternalError","RangeError","ReferenceError","SyntaxError","TypeError","URIError"],r=["setInterval","setTimeout","clearInterval","clearTimeout","require","exports","eval","isFinite","isNaN","parseFloat","parseInt","decodeURI","decodeURIComponent","encodeURI","encodeURIComponent","escape","unescape"],c=["arguments","this","super","console","window","document","localStorage","module","global"],i=[].concat(r,t,s) ;return o=>{const l=o.regex,b=e,d={begin:/<[A-Za-z0-9\\._:-]+/, end:/\/[A-Za-z0-9\\._:-]+>|\/>/,isTrulyOpeningTag:(e,n)=>{ const a=e[0].length+e.index,t=e.input[a] @@ -372,7 +372,7 @@ relevance:0},{variants:[{begin:"<>",end:""},{ match:/<[A-Za-z0-9\\._:-]+\s*\/>/},{begin:d.begin, "on:begin":d.isTrulyOpeningTag,end:d.end}],subLanguage:"xml",contains:[{ begin:d.begin,end:d.end,skip:!0,contains:["self"]}]}]},O,{ -beginKeywords:"while if switch catch for"},{ +beginKeywords:"while if case catch for"},{ begin:"\\b(?!function)"+o.UNDERSCORE_IDENT_RE+"\\([^()]*(\\([^()]*(\\([^()]*\\)[^()]*)*\\)[^()]*)*\\)\\s*\\{", returnBegin:!0,label:"func.def",contains:[S,o.inherit(o.TITLE_MODE,{begin:b, className:"title.function"})]},{match:/\.\.\./,relevance:0},x,{match:"\\$"+b, diff --git a/website/themes/prql-theme/static/plugins/highlight/prql.js b/website/themes/prql-theme/static/plugins/highlight/prql.js index ed51a6923d3c..c5bb78a9a230 100644 --- a/website/themes/prql-theme/static/plugins/highlight/prql.js +++ b/website/themes/prql-theme/static/plugins/highlight/prql.js @@ -23,7 +23,7 @@ formatting = function (hljs) { "union", "window", ]; - const BUILTIN_FUNCTIONS = ["switch", "in", "as"]; + const BUILTIN_FUNCTIONS = ["case", "in", "as"]; const KEYWORDS = ["func", "let", "prql"]; return { name: "PRQL", From 080b74776f9aeb6870d10e49cd0913ace4193c72 Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Wed, 8 Mar 2023 07:09:30 +0900 Subject: [PATCH 114/184] build: add basic devcontainer.json (for Rust, JavaScript, Python) (#1893) * chore: add devcontainer config file * build: add base devcontainer definition and build workflow file * First cut, very low-quality draft for Dev Containers I have written about 98% of what I know. Let's all contribute to strengthen this document. Thanks. * Remove "will" in favor of direct action words. It's almost always better to write documentation saying "thing X _does_ action Y" instead of "thing X will do action Y". * Update using-dev-container.md * Update using-dev-container.md * Final editorial tweak for first-cut description * Update to reflect @eitsupi's comments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * docs: some updates about VS Code Dev Containers * docs: update title and add note * docs: add a link to containers.dev * docs: formatting lists * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * build: use only Dockerfile for base pre-built image * ci: update workflow to use docker/build-push-action * chore: autoformatting * build: fix workflow trigger * chore: fix path * fix: fix GHA syntax * fix: fix typo * ci: use docker/metadata-action to prepare tags * build: use pre-built image as devcontainer base image * build: remove task for devcontainer setup for now * chore: sync vscode extensions in devcontainer.json * docs: some document update and install zsh completion * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * docs: add the page about devcontainers to the book * build: set postCreateCommand * chore: fix version of go-task Dev Container Feature * docs: remove superfluous comment --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: Rich Brown Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .devcontainer/devcontainer.json | 33 +++++++++++++++++++ book/src/SUMMARY.md | 1 + book/src/contributing/dev-container.md | 45 ++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 .devcontainer/devcontainer.json create mode 100644 book/src/contributing/dev-container.md diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000000..8af2eec50d0e --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,33 @@ +// Dev Container for Rust, website, prql-js and prql-python +{ + "image": "ghcr.io/prql/prql-devcontainer-base:latest", + "features": { + "ghcr.io/devcontainers/features/hugo:1": {}, + "ghcr.io/devcontainers/features/python:1": {}, + "ghcr.io/devcontainers/features/node:1": {}, + "ghcr.io/eitsupi/devcontainer-features/go-task:1": {} + }, + "customizations": { + "vscode": { + "extensions": [ + // Keep in sync with Taskfile.yml + "prql-lang.prql-vscode", + "rust-lang.rust-analyzer", + "mitsuhiko.insta", + "esbenp.prettier-vscode", + "budparr.language-hugo-vscode" + ] + } + }, + "mounts": [ + { + "source": "devcontainer-cargo-cache", + "target": "/usr/local/cargo", + "type": "volume" + } + ], + "postCreateCommand": { + "install-maturin": "task install-maturin", + "install-npm-dependencies": "task install-npm-dependencies" + } +} diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index d8dea5cd6719..db5d7a8d3e5b 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -73,6 +73,7 @@ - [Development](./contributing/development.md) - [Using Docker](./contributing/using-docker.md) + - [Develop in Dev Containers](./contributing/dev-container.md) - [Internals](./internals/README.md) diff --git a/book/src/contributing/dev-container.md b/book/src/contributing/dev-container.md new file mode 100644 index 000000000000..7157a67b5975 --- /dev/null +++ b/book/src/contributing/dev-container.md @@ -0,0 +1,45 @@ +# Develop in Dev Containers + +```admonish note +Currently the Dev Container included in this repository only supports the `amd64` platform. +``` + +[Dev Containers](https://containers.dev/) are a way to package a number of +"developer tools" (compilers, bundlers, package managers, loaders, etc.) into a +single object. This is helpful when many people want to contribute to a project: +each person only has to install the (single) Dev Container on their own machine +to start working. By definition, the Dev Container has a consistent set of tools +that are known to work together. This avoids a fuss with finding the proper +versions of each of the build tools. + +To use a Dev Container on your local computer with VS Code, you must install the +[VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +and its system requirements. + +## How you use it + +While there are a variety of tools that support Dev Containers, the focus here +is on developing with VS Code in a container by +[GitHub Codespaces](https://docs.github.com/en/codespaces/overview) or +[VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). + +Please refer to the documents for general instructions on how to use these +tools. + +## Using PRQL in a Dev Container + +[Task](https://taskfile.dev/) is installed in the container for quick access to +tasks defined on the `Taskfiles.yml`. + +Here are some useful commands available in the container. + +- `task -l` lists all the available tasks. +- `task run-book` starts an `mdbook` server. As you edit the files of the + Language Book (in the `book` directory), `mdbook` rebuilds those pages. + (Port 3000) +- `task run-website` starts a `hugo` server. As you edit the files (in the + `website` directory), `hugo` rebuilds those pages. (Port 1313) +- `task run-playground` starts a Node server to build the Playground. As you + edit the files (in the `playground` directory), the server rebuilds those + pages. (Port 3000) +- `task WHAT ELSE?` _Provide explanation of other useful commands._ From 1adc4cb6c5f261714c50b763c2400f2f72fef120 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:10:27 -0800 Subject: [PATCH 115/184] docs: Wordsmith #1893 (#2045) * docs: Wordsmith #1893 --- book/src/SUMMARY.md | 4 ++-- ...r.md => developing-with-dev-containers.md} | 23 ++++++++----------- ...ng-docker.md => developing-with-docker.md} | 2 +- 3 files changed, 12 insertions(+), 17 deletions(-) rename book/src/contributing/{dev-container.md => developing-with-dev-containers.md} (71%) rename book/src/contributing/{using-docker.md => developing-with-docker.md} (99%) diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md index db5d7a8d3e5b..62c5d04bf13e 100644 --- a/book/src/SUMMARY.md +++ b/book/src/SUMMARY.md @@ -72,8 +72,8 @@ - [Contributing to PRQL](./contributing/README.md) - [Development](./contributing/development.md) - - [Using Docker](./contributing/using-docker.md) - - [Develop in Dev Containers](./contributing/dev-container.md) + - [Developing with Docker](./contributing/developing-with-docker.md) + - [Developing with Dev Containers](./contributing/developing-with-dev-containers.md) - [Internals](./internals/README.md) diff --git a/book/src/contributing/dev-container.md b/book/src/contributing/developing-with-dev-containers.md similarity index 71% rename from book/src/contributing/dev-container.md rename to book/src/contributing/developing-with-dev-containers.md index 7157a67b5975..534dbaa8139c 100644 --- a/book/src/contributing/dev-container.md +++ b/book/src/contributing/developing-with-dev-containers.md @@ -1,30 +1,25 @@ -# Develop in Dev Containers +# Developing with Dev Containers ```admonish note Currently the Dev Container included in this repository only supports the `amd64` platform. ``` [Dev Containers](https://containers.dev/) are a way to package a number of -"developer tools" (compilers, bundlers, package managers, loaders, etc.) into a +developer tools (compilers, bundlers, package managers, loaders, etc.) into a single object. This is helpful when many people want to contribute to a project: -each person only has to install the (single) Dev Container on their own machine -to start working. By definition, the Dev Container has a consistent set of tools -that are known to work together. This avoids a fuss with finding the proper -versions of each of the build tools. - -To use a Dev Container on your local computer with VS Code, you must install the -[VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) -and its system requirements. - -## How you use it +each person only has to install the Dev Container on their own machine to start +working. By definition, the Dev Container has a consistent set of tools that are +known to work together. This avoids a fuss with finding the proper version of +each of the build tools. While there are a variety of tools that support Dev Containers, the focus here is on developing with VS Code in a container by [GitHub Codespaces](https://docs.github.com/en/codespaces/overview) or [VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers). -Please refer to the documents for general instructions on how to use these -tools. +To use a Dev Container on a local computer with VS Code, install the +[VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) +and its system requirements. Then refer to the links above to get started. ## Using PRQL in a Dev Container diff --git a/book/src/contributing/using-docker.md b/book/src/contributing/developing-with-docker.md similarity index 99% rename from book/src/contributing/using-docker.md rename to book/src/contributing/developing-with-docker.md index ee8a1ce789fe..80977a29ceba 100644 --- a/book/src/contributing/using-docker.md +++ b/book/src/contributing/developing-with-docker.md @@ -1,4 +1,4 @@ -# Using the Dockerfile +# Developing with Docker The `Dockerfile` in this repo builds a Docker image that has current versions of our Rust development tools. This can be the lowest-effort way of setting up a From b1c80c530a24f11487e5c25a9aa1e9c2cdd7ccb2 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:22:49 -0800 Subject: [PATCH 116/184] docs: Move task docs out of devcontainers (#2046) These are good docs, but there's no reason for them to be here. They'd be good in the Taskfile, or very open to other suggestions While I _really_ appreciate docs that we write (CC @richbhanover), it's important that they're focused, concise, and close to the code that they document -- because they also need to be maintained, and the project takes on that responsibility. I really don't want to lose folks' generosity and ideas, but I'm going to start being a bit firmer on these sorts of things, because we're already starting to see some stale docs (#2044). There are other ways of writing things that have fewer guarantees of continued support -- blog posts, gists, etc. --- .../developing-with-dev-containers.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/book/src/contributing/developing-with-dev-containers.md b/book/src/contributing/developing-with-dev-containers.md index 534dbaa8139c..d595961af25d 100644 --- a/book/src/contributing/developing-with-dev-containers.md +++ b/book/src/contributing/developing-with-dev-containers.md @@ -20,21 +20,3 @@ is on developing with VS Code in a container by To use a Dev Container on a local computer with VS Code, install the [VS Code Dev Containers extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) and its system requirements. Then refer to the links above to get started. - -## Using PRQL in a Dev Container - -[Task](https://taskfile.dev/) is installed in the container for quick access to -tasks defined on the `Taskfiles.yml`. - -Here are some useful commands available in the container. - -- `task -l` lists all the available tasks. -- `task run-book` starts an `mdbook` server. As you edit the files of the - Language Book (in the `book` directory), `mdbook` rebuilds those pages. - (Port 3000) -- `task run-website` starts a `hugo` server. As you edit the files (in the - `website` directory), `hugo` rebuilds those pages. (Port 1313) -- `task run-playground` starts a Node server to build the Playground. As you - edit the files (in the `playground` directory), the server rebuilds those - pages. (Port 3000) -- `task WHAT ELSE?` _Provide explanation of other useful commands._ From cba6e12d4842cf1a0b8aa2c84750a24b1d5b0817 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 15:48:29 -0800 Subject: [PATCH 117/184] chore: Fix footnote in a doc (#2047) --- book/src/contributing/development.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index 1d8e6666c362..b4bf4ed7b1f4 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -427,6 +427,3 @@ Currently we release in a semi-automated way: ``` We may make this more automated in future; e.g. automatic changelog creation. - -[^wrap]: -[^perms]: From fb06418c4a32c554ad8d7ce7b562dacb11f21ff0 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 19:26:27 -0800 Subject: [PATCH 118/184] todo (#2049) * chore: Add TODO to devcontainer.yaml CC @eitsupi * chore: Add todo to devcontainer.yaml re workflows (Zero rush, this is not a request to do something right now, just want to ensure that this isn't copied for the next workflow we write) --- .github/workflows/devcontainer.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/devcontainer.yaml b/.github/workflows/devcontainer.yaml index 86392d342c7c..28c9cf330822 100644 --- a/.github/workflows/devcontainer.yaml +++ b/.github/workflows/devcontainer.yaml @@ -1,6 +1,10 @@ name: devcontainer on: + # TODO: adopt our standard hierarchy for these, as per + # https://github.com/PRQL/prql/pull/1893#discussion_r1125736478, possibly only + # publishing on releases or on the `web` branch (which possibly should be + # renamed back to `stable` if we use it more for this) push: paths: - .devcontainer/base-image/Dockerfile From 9ece779383ee8ff40cdbc82491059f51f3d59629 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 19:45:37 -0800 Subject: [PATCH 119/184] docs: Add some guidance on writing docs (#2050) --- book/src/contributing/development.md | 34 +++++++++++++++++++++++++--- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index b4bf4ed7b1f4..19177e242073 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -162,7 +162,7 @@ change! - This means PRs almost always need a test to demonstrate incremental progress. - If a change breaks functionality without breaking tests, our tests were - insufficient. + probably insufficient. - If a change breaks existing tests (for example, changing an external API), that indicates we should be careful about merging a change, including soliciting others' views. @@ -183,8 +183,36 @@ change! with our expectations, or there isn't as much consensus on a decision as we had hoped. It's very easy to revert code and then re-revert when we've resolved the issue; it's a sign of moving quickly. Other options which resolve - the build immediately are also fine, such as commenting out an incorrect test - or adding a quick fix for the underlying issue. + issues immediately are also fine, such as commenting out an incorrect test or + adding a quick fix for the underlying issue. + +## Docs + +We're very keen on contributions to improve our documentation. + +This includes our docs in the book, on the website, in our code, or in a Readme. +We also appreciate issues pointing out that our documentation was confusing, +incorrect, or stale โ€” if it's confusing for you, it's probably confusing for +others. + +Some principles for ensuring our docs remain maintainable: + +- Docs should be as close as possible to the code. Doctests are ideal on this + dimension โ€” they're literally very close to the code and they can't drift + apart since they're tested on every commit. Or, for example, it's better to + add text to a `--help` message, rather than write a paragraph in the Redame + explaining the CLI. +- We should have some visualization of how to maintain docs when we add them. + Docs have a habit of falling out of date โ€” the folks reading them are often + different from those writing them, they're sparse from the code, generally not + possible to test, and are rarely the by-product of other contributions. Docs + that are concise & specific are easier to maintain. +- Docs should be specifically relevant to PRQL; anything else we can instead + link to. + +If something doesn't fit into one of these categories, there are still lots of +ways of getting the word out there โ€” a blog post / gist / etc. Let us know and +we're happy to link to it / tweet it. ## Components of PRQL From 5deac57d5817b0a9329af3d4101e300001c119c7 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 21:14:27 -0800 Subject: [PATCH 120/184] chore: Fix typo (#2051) --- book/src/contributing/development.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index 19177e242073..b005e1b64dfe 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -200,7 +200,7 @@ Some principles for ensuring our docs remain maintainable: - Docs should be as close as possible to the code. Doctests are ideal on this dimension โ€” they're literally very close to the code and they can't drift apart since they're tested on every commit. Or, for example, it's better to - add text to a `--help` message, rather than write a paragraph in the Redame + add text to a `--help` message, rather than write a paragraph in the Readme explaining the CLI. - We should have some visualization of how to maintain docs when we add them. Docs have a habit of falling out of date โ€” the folks reading them are often From 25f47f997872c0dbc46d688afefe5235fe3eee09 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Tue, 7 Mar 2023 23:05:57 -0800 Subject: [PATCH 121/184] chore: Add Changelog for 0.6.0 (#2053) --- CHANGELOG.md | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc752c79d360..5bd0d557d13b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,25 @@ # PRQL Changelog -## 0.5.3 โ€” [unreleased] +## 0.6.0 โ€” 2022-03-07 + +0.6.0 introduces `loop` as an experimental feature, which compiles to +`WITH RECURSIVE`, renames `switch` to `case`, and introduces a rewritten parser, +giving us the ability to dramatically improve error messages. + +There are a few cases of breaking changes, including switching `switch` to +`case`, in case that's confusing. There are also some minor parsing changes +outlined below. + +This release has 108 commits from 11 contributors. Selected changes: **Features**: -- `loop`, which translates to `WITH RECURSIVE` (#1642, @aljazerzen) +- Add an experimental `loop` language feature, which translates to + `WITH RECURSIVE` (#1642, @aljazerzen) +- Rename the experimental `switch` function to `case` given it more closely + matches the traditional semantics of `case`. (@max-sixty, #2036) +- Change the `case` syntax to use `=>` instead of `->` to distinguish it from + function syntax. - Convert parser from pest to Chumsky (@aljazerzen, #1818) - Improved error messages, and the potential to make even better in the future. Many of these improvements come from error recovery. @@ -28,8 +43,6 @@ `@2020-01-01T13:19:55-0800` (@max-sixty, #1991). - Add `std.upper` and `std.lower` functions for changing string casing (@Jelenkee, #2019). -- Rename the experimental `switch` to `case` given it more closely matches the - traditional semantics of `case`. (@max-sixty, #2036) **Fixes**: @@ -43,8 +56,6 @@ - Error messages for invalid queries are displayed in the book (@max-sixty, #2015) -**Web**: - **Integrations**: - [prql-php] Added PHP bindings. (@vanillajonathan, #1860) @@ -57,11 +68,14 @@ **Internal changes**: -- Test that the code our nascent autoformatter generates can be compiled into - SQL. Examples where it can't are now labeled. (@max-sixty, #2016) +- Test that the output of our nascent autoformatter can be successfully compiled + into SQL. Failing examples are now clearly labeled. (@max-sixty, #2016) **New Contributors**: +- @linux-china, with #1971 +- @Jelenkee, with #2019 + ## 0.5.2 โ€” 2022-02-18 0.5.2 is a tiny release to fix an build issue in yesterday's `prql-js` 0.5.1 From da173c39bb1c3af90ac8681bec9bd5295c379432 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 00:48:16 -0800 Subject: [PATCH 122/184] feat!: Re-revert switch syntax change (#2040) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Re-revert switch syntax change . * . * Add symbol to three grammars --------- Co-authored-by: Aljaลพ Mur Erลพen --- book/highlight-prql.js | 2 +- book/src/language-features/case.md | 10 ++++----- book/tests/prql/language-features/case-0.prql | 4 ++-- book/tests/prql/language-features/case-1.prql | 6 ++--- book/tests/snapshot.rs | 1 + ...shot__@language-features__case-0.prql.snap | 2 +- ...shot__@language-features__case-1.prql.snap | 2 +- playground/src/workbench/prql-syntax.js | 2 ++ prql-compiler/src/parser/expr.rs | 2 +- prql-compiler/src/parser/lexer.rs | 4 +++- prql-compiler/src/parser/mod.rs | 4 ++-- prql-compiler/src/test.rs | 22 +++++++++---------- prql-compiler/tests/integration/main.rs | 4 +++- .../tests/integration/queries/switch.prql | 6 ++--- prql-lezer/src/prql.grammar | 6 +++-- .../static/plugins/highlight/prql.js | 2 +- 16 files changed, 44 insertions(+), 35 deletions(-) diff --git a/book/highlight-prql.js b/book/highlight-prql.js index 2f3e7136fdda..36f704dbe5bb 100644 --- a/book/highlight-prql.js +++ b/book/highlight-prql.js @@ -164,7 +164,7 @@ formatting = function (hljs) { { scope: "operator", match: - /(>)|(<)|(==)|(\+)|(\-)|(\/)|(\*)|(!=)|(<=)|(>=)|(\band\b)|(\bor\b)/, + /(>)|(<)|(==)|(\+)|(\-)|(\/)|(\*)|(!=)|(->)|(=>)|(<=)|(>=)|(\band\b)|(\bor\b)/, relevance: 10, }, { diff --git a/book/src/language-features/case.md b/book/src/language-features/case.md index a836e84b1b2b..f91768d21952 100644 --- a/book/src/language-features/case.md +++ b/book/src/language-features/case.md @@ -9,8 +9,8 @@ PRQL uses `case` for both SQL's `CASE` and `IF` statements. Here's an example: ```prql_no_fmt from employees derive distance = case [ - city == "Calgary" -> 0, - city == "Edmonton" -> 300, + city == "Calgary" => 0, + city == "Edmonton" => 300, ] ``` @@ -20,8 +20,8 @@ If no condition is met, the value takes a `null` value. To set a default, use a ```prql_no_fmt from employees derive distance = case [ - city == "Calgary" -> 0, - city == "Edmonton" -> 300, - true -> "Unknown", + city == "Calgary" => 0, + city == "Edmonton" => 300, + true => "Unknown", ] ``` diff --git a/book/tests/prql/language-features/case-0.prql b/book/tests/prql/language-features/case-0.prql index 0845b3bf8fc7..6e6f269a5bed 100644 --- a/book/tests/prql/language-features/case-0.prql +++ b/book/tests/prql/language-features/case-0.prql @@ -2,6 +2,6 @@ from employees derive distance = case [ - city == "Calgary" -> 0, - city == "Edmonton" -> 300, + city == "Calgary" => 0, + city == "Edmonton" => 300, ] diff --git a/book/tests/prql/language-features/case-1.prql b/book/tests/prql/language-features/case-1.prql index 5a97534e00b1..78ad16893e76 100644 --- a/book/tests/prql/language-features/case-1.prql +++ b/book/tests/prql/language-features/case-1.prql @@ -2,7 +2,7 @@ from employees derive distance = case [ - city == "Calgary" -> 0, - city == "Edmonton" -> 300, - true -> "Unknown", + city == "Calgary" => 0, + city == "Edmonton" => 300, + true => "Unknown", ] diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index c742bf3caa4d..97ebb89e75ad 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -190,6 +190,7 @@ fn test_prql_examples() { glob!("prql/**/*.prql", |path| { let prql = fs::read_to_string(path).unwrap(); + // TODO: I don't think we use this and can remove it? if prql.contains("skip_test") { return; } diff --git a/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap index c1b47f0b82e5..70a17264d893 100644 --- a/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n]\n" +expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" => 0,\n city == \"Edmonton\" => 300,\n]\n" input_file: book/tests/prql/language-features/case-0.prql --- SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap index 816c9244da9b..391cb2489d75 100644 --- a/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" -> 0,\n city == \"Edmonton\" -> 300,\n true -> \"Unknown\",\n]\n" +expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" => 0,\n city == \"Edmonton\" => 300,\n true => \"Unknown\",\n]\n" input_file: book/tests/prql/language-features/case-1.prql --- SELECT diff --git a/playground/src/workbench/prql-syntax.js b/playground/src/workbench/prql-syntax.js index 8a589aed327c..c835de0c9ffa 100644 --- a/playground/src/workbench/prql-syntax.js +++ b/playground/src/workbench/prql-syntax.js @@ -39,6 +39,8 @@ const def = { "-", "==", "!=", + "->", + "=>", ">", "<", ">=", diff --git a/prql-compiler/src/parser/expr.rs b/prql-compiler/src/parser/expr.rs index 07b16439fd59..f45e28f1c231 100644 --- a/prql-compiler/src/parser/expr.rs +++ b/prql-compiler/src/parser/expr.rs @@ -75,7 +75,7 @@ pub fn expr() -> impl Parser> + Clone { let case = keyword("case") .ignore_then( func_call(expr.clone()) - .then_ignore(just(Token::Arrow)) + .then_ignore(just(Token::ArrowDouble)) .then(func_call(expr)) .map(|(condition, value)| SwitchCase { condition, value }) .padded_by(new_line().repeated()) diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 2d0af4523d7a..8ed26a1f748f 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -20,7 +20,9 @@ pub enum Token { /// single-char control tokens Control(char), - Arrow, // -> + // TODO: rename to ArrowThin + Arrow, // -> + // TODO: rename to ArrowFat ArrowDouble, // => Eq, // == Ne, // != diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index db7b880e3fb9..219ea1e34cea 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -2190,8 +2190,8 @@ join s=salaries [==id] #[test] fn test_case() { assert_yaml_snapshot!(parse_expr(r#"case [ - nickname != null -> nickname, - true -> null + nickname != null => nickname, + true => null ]"#).unwrap(), @r###" --- Case: diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 68df47ae447f..62022adb1eb1 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2670,8 +2670,8 @@ fn test_case() { r###" from employees derive display_name = case [ - nickname != null -> nickname, - true -> f'{first_name} {last_name}' + nickname != null => nickname, + true => f'{first_name} {last_name}' ] "###).unwrap(), @r###" @@ -2690,8 +2690,8 @@ fn test_case() { r###" from employees derive display_name = case [ - nickname != null -> nickname, - first_name != null -> f'{first_name} {last_name}' + nickname != null => nickname, + first_name != null => f'{first_name} {last_name}' ] "###).unwrap(), @r###" @@ -2711,7 +2711,7 @@ fn test_case() { r###" from tracks select category = case [ - length > avg_length -> 'long' + length > avg_length => 'long' ] group category (aggregate count) "###).unwrap(), @@ -2782,12 +2782,12 @@ fn test_static_analysis() { a3 = null ?? y, a3 = case [ - false == true -> 1, - 7 == 3 -> 2, - 7 == y -> 3, - 7.3 == 7.3 -> 4, - z -> 5, - true -> 6 + false == true => 1, + 7 == 3 => 2, + 7 == y => 3, + 7.3 == 7.3 => 4, + z => 5, + true => 6 ] ] "###).unwrap(), diff --git a/prql-compiler/tests/integration/main.rs b/prql-compiler/tests/integration/main.rs index 6ead5ffe1ded..666d005862cd 100644 --- a/prql-compiler/tests/integration/main.rs +++ b/prql-compiler/tests/integration/main.rs @@ -34,7 +34,9 @@ mod tests { let opts = Options::default() .with_target(Target::Sql(Some(Dialect::SQLite))) .no_format(); - let sql = prql_compiler::compile(&prql, &opts).unwrap(); + let sql = prql_compiler::compile(&prql, &opts) + .unwrap_or_else(|e| panic!("Failed to compile\n\n{prql}\n\n{e}")); + let sqlite_out = sqlite::query_csv(&sqlite_conn, &sql); // save both csv files as same snapshot diff --git a/prql-compiler/tests/integration/queries/switch.prql b/prql-compiler/tests/integration/queries/switch.prql index 284f61d6202b..7214c48fc708 100644 --- a/prql-compiler/tests/integration/queries/switch.prql +++ b/prql-compiler/tests/integration/queries/switch.prql @@ -1,8 +1,8 @@ from tracks sort milliseconds select display = case [ - composer != null -> composer, - genre_id < 17 -> 'no composer', - true -> f'unknown composer' + composer != null => composer, + genre_id < 17 => 'no composer', + true => f'unknown composer' ] take 10 diff --git a/prql-lezer/src/prql.grammar b/prql-lezer/src/prql.grammar index e599e2f47991..6aea78ea786f 100644 --- a/prql-lezer/src/prql.grammar +++ b/prql-lezer/src/prql.grammar @@ -19,7 +19,7 @@ pipe { "|" | ~ambig_newline newline } List { "[" newline? list_item (("," newline? ) list_item)* ","? newline? "]" } -list_item { Assign_call | expr_call } +list_item { Assign_call | expr_call | Case_branch } expr_call { Expr | Func_call } // Ideally we would force a space after `Ident` to prevent an invalid s-string @@ -37,6 +37,7 @@ Expr { !term term (( Op_bin) term)* } Named_arg { ident_part ":" Expr } Assign { ident_part "=" Expr } Assign_call { ident_part "=" expr_call } +Case_branch { Expr "=>" Expr } Nested_pipeline { "(" newline* Pipeline ~ambig_newline newline? ")" } @@ -46,7 +47,8 @@ Nested_pipeline { "(" newline* Pipeline ~ambig_newline newline? ")" } // It's outside tokens because otherwise it conflicts with Ident Ident { ident_part ( "." ident_part)* } -// I don't think it's possible to have `Op_bin` & `Op_unary` as tokens โ€” that would mean `-` can't be both unary & bin. +// I don't think it's possible to have `Op_bin` & `Op_unary` as tokens โ€” that +// would mean `-` can't be both unary & bin. Op_bin { Op_bin_only | Op_unary } @tokens { diff --git a/website/themes/prql-theme/static/plugins/highlight/prql.js b/website/themes/prql-theme/static/plugins/highlight/prql.js index c5bb78a9a230..37632c50d1ea 100644 --- a/website/themes/prql-theme/static/plugins/highlight/prql.js +++ b/website/themes/prql-theme/static/plugins/highlight/prql.js @@ -152,7 +152,7 @@ formatting = function (hljs) { { scope: "operator", match: - /(>)|(<)|(==)|(\+)|(\-)|(\/)|(\*)|(!=)|(<=)|(>=)|(\band\b)|(\bor\b)/, + /(>)|(<)|(==)|(\+)|(\-)|(\/)|(\*)|(!=)|(->)|(=>)|(<=)|(>=)|(\band\b)|(\bor\b)/, relevance: 10, }, { From 4ad2374ae644209f5947e3cf2c1c14a3a6d357d0 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 00:54:38 -0800 Subject: [PATCH 123/184] chore: Bump versions to 0.6.0 (#2054) * chore: Bump versions to 0.6.0 * chore: Add Changelog for 0.6.0 (#2053) * Don't snapshot the current version --- Cargo.lock | 20 +++++------ Cargo.toml | 2 +- book/src/language-features/target.md | 2 +- .../prql/language-features/target-2.prql | 2 +- book/tests/snapshot.rs | 2 +- ...ot__@language-features__target-2.prql.snap | 3 +- playground/package-lock.json | 2 +- prql-compiler/prql-compiler-macros/Cargo.toml | 2 +- prql-compiler/prqlc/Cargo.toml | 2 +- prql-compiler/src/semantic/mod.rs | 34 ------------------- prql-elixir/native/prql/Cargo.toml | 2 +- prql-js/package-lock.json | 4 +-- prql-js/package.json | 2 +- 13 files changed, 23 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b6d5897963b0..1ad62a73ec12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "compile-files" -version = "0.5.2" +version = "0.6.0" dependencies = [ "prql-compiler", ] @@ -1606,7 +1606,7 @@ dependencies = [ [[package]] name = "mdbook-prql" -version = "0.5.2" +version = "0.6.0" dependencies = [ "anyhow", "clap 4.1.6", @@ -2109,7 +2109,7 @@ dependencies = [ [[package]] name = "prql" -version = "0.5.2" +version = "0.6.0" dependencies = [ "prql-compiler", "rustler", @@ -2117,7 +2117,7 @@ dependencies = [ [[package]] name = "prql-compiler" -version = "0.5.2" +version = "0.6.0" dependencies = [ "anyhow", "ariadne", @@ -2148,7 +2148,7 @@ dependencies = [ [[package]] name = "prql-compiler-macros" -version = "0.5.2" +version = "0.6.0" dependencies = [ "prql-compiler", "syn", @@ -2156,7 +2156,7 @@ dependencies = [ [[package]] name = "prql-java" -version = "0.5.2" +version = "0.6.0" dependencies = [ "jni", "prql-compiler", @@ -2164,7 +2164,7 @@ dependencies = [ [[package]] name = "prql-js" -version = "0.5.2" +version = "0.6.0" dependencies = [ "console_error_panic_hook", "prql-compiler", @@ -2174,7 +2174,7 @@ dependencies = [ [[package]] name = "prql-lib" -version = "0.5.2" +version = "0.6.0" dependencies = [ "libc", "prql-compiler", @@ -2183,7 +2183,7 @@ dependencies = [ [[package]] name = "prql-python" -version = "0.5.2" +version = "0.6.0" dependencies = [ "insta", "prql-compiler", @@ -2193,7 +2193,7 @@ dependencies = [ [[package]] name = "prqlc" -version = "0.5.2" +version = "0.6.0" dependencies = [ "anyhow", "ariadne", diff --git a/Cargo.toml b/Cargo.toml index 04b449a500f7..866a4a93dc95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ edition = "2021" license = "Apache-2.0" repository = "https://github.com/PRQL/prql" rust-version = "1.65.0" -version = "0.5.2" +version = "0.6.0" [profile.release.package.prql-js] # Tell `rust-js` to optimize for small code size. diff --git a/book/src/language-features/target.md b/book/src/language-features/target.md index 979d9434f4c9..c3cd4f255b33 100644 --- a/book/src/language-features/target.md +++ b/book/src/language-features/target.md @@ -48,7 +48,7 @@ very welcome. PRQL allows specifying a version of the language in the PRQL header, like: ```prql_no_fmt -prql version:"0.5" +prql version:"0.6" from employees ``` diff --git a/book/tests/prql/language-features/target-2.prql b/book/tests/prql/language-features/target-2.prql index 06bf38542363..dd5bf36ff497 100644 --- a/book/tests/prql/language-features/target-2.prql +++ b/book/tests/prql/language-features/target-2.prql @@ -1,5 +1,5 @@ # Can't yet format & compile -prql version:"0.5" +prql version:"0.6" from employees diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 97ebb89e75ad..86c4f9346762 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -178,7 +178,7 @@ Some book snapshots were not consistent with the queries in the book: {snapshots_updated} -The snapshots have now been updated. Subsequent runs of this test should now pass."### +The snapshots have now been updated. Subsequent runs of this test should now pass.\n\n"### )); } Ok(()) diff --git a/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap index 87aa49f8fbb7..4326599ef89f 100644 --- a/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap @@ -1,9 +1,10 @@ --- source: book/tests/snapshot.rs -expression: "prql version:\"0.4\"\n\nfrom employees\n" +expression: "# Can't yet format & compile\n\nprql version:\"0.6\"\n\nfrom employees\n" input_file: book/tests/prql/language-features/target-2.prql --- SELECT * FROM employees + diff --git a/playground/package-lock.json b/playground/package-lock.json index 3cae1d7b48db..365eef31083a 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -28,7 +28,7 @@ } }, "../prql-js": { - "version": "0.5.2", + "version": "0.6.0", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/prql-compiler/prql-compiler-macros/Cargo.toml b/prql-compiler/prql-compiler-macros/Cargo.toml index 2244c503b04d..d80e788df0ae 100644 --- a/prql-compiler/prql-compiler-macros/Cargo.toml +++ b/prql-compiler/prql-compiler-macros/Cargo.toml @@ -14,7 +14,7 @@ proc_macro = true test = false [dependencies] -prql-compiler = {path = "..", default-features = false, version = "0.5.2"} +prql-compiler = {path = "..", default-features = false, version = "0.6.0" } # Was getting build errors with more recent versions; can remove pin if it # successfully builds. syn = "=1.0.107" diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 40b0ced399be..522f9776aa84 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -19,7 +19,7 @@ env_logger = {version = "0.10.0", features = ["color"]} itertools = "0.10.3" minijinja = {version = "0.30.4", features = ["unstable_machinery"]} notify = "^5.1.0" -prql-compiler = {path = '..', version = "0.5.2"} +prql-compiler = {path = '..', version = "0.6.0" } regex = {version = "1.7.1", features = ["std", "unicode"]} serde = "^1" serde_json = "1.0.81" diff --git a/prql-compiler/src/semantic/mod.rs b/prql-compiler/src/semantic/mod.rs index 91e172cd341d..c0a5d72b3339 100644 --- a/prql-compiler/src/semantic/mod.rs +++ b/prql-compiler/src/semantic/mod.rs @@ -169,40 +169,6 @@ mod test { - Wildcard "### ); - assert_yaml_snapshot!(parse_and_resolve(r###" - prql target:sql.bigquery version:"0.5" - - from employees - "###).unwrap(), @r###" - --- - def: - version: ^0.5 - other: - target: sql.bigquery - tables: - - id: 0 - name: ~ - relation: - kind: - ExternRef: - LocalTable: employees - columns: - - Wildcard - relation: - kind: - Pipeline: - - From: - source: 0 - columns: - - - Wildcard - - 0 - name: employees - - Select: - - 0 - columns: - - Wildcard - "### ); - assert!(parse_and_resolve( r###" prql target:sql.bigquery version:foo diff --git a/prql-elixir/native/prql/Cargo.toml b/prql-elixir/native/prql/Cargo.toml index a39a9eee25db..5c900b50e5be 100644 --- a/prql-elixir/native/prql/Cargo.toml +++ b/prql-elixir/native/prql/Cargo.toml @@ -16,7 +16,7 @@ name = "prql" path = "src/lib.rs" [dependencies] -prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.5.2"} +prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.6.0" } # See Readme for details on Mac [target.'cfg(not(any(target_family="wasm", target_os = "macos")))'.dependencies] diff --git a/prql-js/package-lock.json b/prql-js/package-lock.json index 82d80abcb852..7e5cbb4f9287 100644 --- a/prql-js/package-lock.json +++ b/prql-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "prql-js", - "version": "0.5.2", + "version": "0.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prql-js", - "version": "0.5.2", + "version": "0.6.0", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/prql-js/package.json b/prql-js/package.json index 9e25e8fed74f..43876e7d3daf 100644 --- a/prql-js/package.json +++ b/prql-js/package.json @@ -24,5 +24,5 @@ "test": "mocha tests" }, "types": "dist/node/prql_js.d.ts", - "version": "0.5.2" + "version": "0.6.0" } From 60b7b0750c1c7095c2c21cdb55cdc8e23724526a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 01:17:20 -0800 Subject: [PATCH 124/184] devops: Avoid triggering rebuilds on `snap.new` files (#2056) Notes in the gitignore file --- .gitignore | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 711ac9dd9583..17ef3a036aa3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,10 +6,10 @@ target* lcov.info -**/.vscode/settings.json -**/.vscode/launch.json -**/.vscode/tasks.json -**/.idea +.vscode/settings.json +.vscode/launch.json +.vscode/tasks.json +.idea /*.prql _*.prql @@ -25,4 +25,5 @@ _*.prql # created, which we don't want. That said, if ignoring them causes confusion # (e.g. folks look at their git status to assess whether there are pending # snapshots), we can adjust. -**/*.pending-snap +*.pending-snap +*.snap.new From fc8a92be7f0ae4617d82923abf19699f12a523ca Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Thu, 9 Mar 2023 03:52:10 +0900 Subject: [PATCH 125/184] docs: add changelog item about devcontainers (#2059) * docs: add changelog item about devcontainers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bd0d557d13b..1e9292db3db2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,9 @@ This release has 108 commits from 11 contributors. Selected changes: - Test that the output of our nascent autoformatter can be successfully compiled into SQL. Failing examples are now clearly labeled. (@max-sixty, #2016) +- Definition files have been added to configure + [Dev Containers](https://containers.dev/) for Rust development environment. + (@eitsupi, #1893, #2025, #2028) **New Contributors**: From fef04efec69125084545599bcded4fcab94c313f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 11:09:10 -0800 Subject: [PATCH 126/184] devops: Replace version number in example each release (#2055) * chore: Bump versions to 0.6.0 * chore: Add Changelog for 0.6.0 (#2053) * Don't snapshot the current version * devops: Replace version number in example each release This currently causes a failure on each minor release; now automatic * I think a small cargo release bug? * Use full version number --- book/src/language-features/target.md | 2 +- book/tests/prql/language-features/target-2.prql | 2 +- prql-compiler/Cargo.toml | 8 ++++++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/book/src/language-features/target.md b/book/src/language-features/target.md index c3cd4f255b33..aef5fc914274 100644 --- a/book/src/language-features/target.md +++ b/book/src/language-features/target.md @@ -48,7 +48,7 @@ very welcome. PRQL allows specifying a version of the language in the PRQL header, like: ```prql_no_fmt -prql version:"0.6" +prql version:"0.6.0" from employees ``` diff --git a/book/tests/prql/language-features/target-2.prql b/book/tests/prql/language-features/target-2.prql index dd5bf36ff497..0b724ad34437 100644 --- a/book/tests/prql/language-features/target-2.prql +++ b/book/tests/prql/language-features/target-2.prql @@ -1,5 +1,5 @@ # Can't yet format & compile -prql version:"0.6" +prql version:"0.6.0" from employees diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index c8ba776d9e0b..0bcf64871e0d 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -56,3 +56,11 @@ duckdb = {version = "0.7.0", features = ["bundled", "chrono"]} [[bench]] harness = false name = "bench" + +# Putting this in the workspace root causes it to refer to the path relative +# to `prql-compiler`? We can place it there when that's fixed. +[[package.metadata.release.pre-release-replacements]] +exactly = 1 +file = "../book/src/language-features/target.md" +replace = 'prql version:"{{version}}"' +search = 'prql version:"[\d.]+"' From 983895327cabfde69be6589a26696bc95abf81f8 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 22:29:48 -0800 Subject: [PATCH 127/184] chore: Update changelog re experimental `loop` (#2063) ...better to underpromise --- CHANGELOG.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e9292db3db2..4d11db1829bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,11 @@ # PRQL Changelog -## 0.6.0 โ€” 2022-03-07 +## 0.6.0 โ€” 2022-03-08 -0.6.0 introduces `loop` as an experimental feature, which compiles to -`WITH RECURSIVE`, renames `switch` to `case`, and introduces a rewritten parser, -giving us the ability to dramatically improve error messages. +0.6.0 introduces a rewritten parser, giving us the ability to dramatically +improve error messages, renames `switch` to `case` and includes lots of minor +improvements and fixes. It also introduces `loop`, which compiles to +`WITH RECURSIVE`, as a highly experimental feature. There are a few cases of breaking changes, including switching `switch` to `case`, in case that's confusing. There are also some minor parsing changes @@ -14,8 +15,9 @@ This release has 108 commits from 11 contributors. Selected changes: **Features**: -- Add an experimental `loop` language feature, which translates to - `WITH RECURSIVE` (#1642, @aljazerzen) +- Add a (highly experimental) `loop` language feature, which translates to + `WITH RECURSIVE`. We expect changes and refinements in upcoming releases. + (#1642, @aljazerzen) - Rename the experimental `switch` function to `case` given it more closely matches the traditional semantics of `case`. (@max-sixty, #2036) - Change the `case` syntax to use `=>` instead of `->` to distinguish it from From f9753566e3f4a8fb422a423be37eb332f6bf692d Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Wed, 8 Mar 2023 22:41:48 -0800 Subject: [PATCH 128/184] chore: Add changelog template for 0.6.1 (#2064) * chore: Bump versions to 0.6.0 * chore: Add changelog template for 0.6.1 --- CHANGELOG.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d11db1829bc..d42e02820d82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # PRQL Changelog +## 0.6.1 โ€” [unreleased] + +**Features**: + +**Fixes**: + +**Documentation**: + +**Web**: + +**Integrations**: + +**Internal changes**: + +**New Contributors**: + ## 0.6.0 โ€” 2022-03-08 0.6.0 introduces a rewritten parser, giving us the ability to dramatically From 107f3d71a56805c59fa217090d3d213a50711f8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 9 Mar 2023 09:26:23 +0100 Subject: [PATCH 129/184] refactor: update C API to return Result (#2039) * refactor: update C API * provide result_destroy * add MessageKind * php bindings * disable dotnet and elixir workflows --------- Co-authored-by: Jonathan --- .github/workflows/test-dotnet.yaml | 10 +- .github/workflows/test-elixir.yaml | 8 +- .github/workflows/test-php.yaml | 12 +- prql-compiler/src/error.rs | 2 +- prql-lib/examples/minimal-c/Makefile | 3 + prql-lib/examples/minimal-c/main.c | 64 ++++--- prql-lib/libprql_lib.h | 108 ++++++++++- prql-lib/src/lib.rs | 220 +++++++++++++++++++--- prql-php/.gitignore | 3 +- prql-php/README.md | 52 ++++- prql-php/build.sh | 6 + prql-php/composer.json | 3 +- prql-php/composer.lock | 50 ++++- prql-php/src/Compiler.php | 272 +++++++++++++++++---------- prql-php/src/Message.php | 40 ++++ prql-php/src/MessageKind.php | 15 ++ prql-php/src/Options.php | 15 +- prql-php/src/Result.php | 18 ++ prql-php/src/SourceLocation.php | 16 ++ prql-php/src/Span.php | 15 ++ prql-php/tests/CompilerTest.php | 50 +++-- 21 files changed, 772 insertions(+), 210 deletions(-) create mode 100644 prql-php/build.sh create mode 100644 prql-php/src/Message.php create mode 100644 prql-php/src/MessageKind.php create mode 100644 prql-php/src/Result.php create mode 100644 prql-php/src/SourceLocation.php create mode 100644 prql-php/src/Span.php diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml index 402f9a7046f9..849ce5c1f44c 100644 --- a/.github/workflows/test-dotnet.yaml +++ b/.github/workflows/test-dotnet.yaml @@ -1,11 +1,11 @@ name: test-dotnet on: - pull_request: - paths: - - "prql-dotnet/**" - - "prql-lib/**" - - ".github/workflows/test-dotnet.yaml" + # pull_request: + # paths: + # - "prql-dotnet/**" + # - "prql-lib/**" + # - ".github/workflows/test-dotnet.yaml" workflow_call: concurrency: diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index 89b0b34097ac..cc8d37470ca7 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -1,10 +1,10 @@ name: test-elixir on: - pull_request: - paths: - - "prql-elixir/**" - - ".github/workflows/test-elixir.yaml" + # pull_request: + # paths: + # - "prql-elixir/**" + # - ".github/workflows/test-elixir.yaml" workflow_call: concurrency: diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml index 608b5d20e114..14ea0fb88983 100644 --- a/.github/workflows/test-php.yaml +++ b/.github/workflows/test-php.yaml @@ -25,21 +25,13 @@ jobs: - uses: actions-rs/toolchain@v1 with: toolchain: stable - - run: cargo build - working-directory: prql-lib - - run: | - mv ../target/debug/libprql_lib.so ../prql-php/src/libprql_lib.so - ls -l ../target/debug/ - uname -a - ls -lR ../prql-php/ - working-directory: prql-lib + - run: sh build.sh + working-directory: prql-php - name: ๐Ÿ“ฆ Install dependencies using Composer uses: php-actions/composer@v6 with: args: --working-dir=prql-php php_extensions: FFI - name: ๐Ÿงช Run tests using PHPUnit - # TODO: enable when aligned with https://github.com/PRQL/prql/pull/1941 - if: false run: vendor/bin/phpunit tests working-directory: prql-php diff --git a/prql-compiler/src/error.rs b/prql-compiler/src/error.rs index 5ba0ece52685..aa656e45fe71 100644 --- a/prql-compiler/src/error.rs +++ b/prql-compiler/src/error.rs @@ -83,7 +83,7 @@ impl Error { #[derive(Clone, Serialize)] pub struct ErrorMessage { - /// Plain text of the error + /// Machine-readable identifier of the error pub code: Option, /// Plain text of the error pub reason: String, diff --git a/prql-lib/examples/minimal-c/Makefile b/prql-lib/examples/minimal-c/Makefile index e1ceb0b6c435..a9b34dad60bb 100644 --- a/prql-lib/examples/minimal-c/Makefile +++ b/prql-lib/examples/minimal-c/Makefile @@ -12,3 +12,6 @@ build: main.c build-prql run: build ./main.out + +valgrind: build + valgrind ./main.out diff --git a/prql-lib/examples/minimal-c/main.c b/prql-lib/examples/minimal-c/main.c index 62d57dbc78a5..e61638c67842 100644 --- a/prql-lib/examples/minimal-c/main.c +++ b/prql-lib/examples/minimal-c/main.c @@ -2,46 +2,64 @@ #include +void print_result(CompileResult res) { + printf("---- [ Compiled with %ld errors ]----\n", res.messages_len); + for (int i = 0; i < res.messages_len; i++) { + Message const* e = &res.messages[i]; + if (e->display != NULL) { + printf("%s", *e->display); + } else if (e->code != NULL) { + printf("[%s] Error: %s\n", *e->code, e->reason); + } else { + printf("Error: %s", e->reason); + } + } + if (*res.output == '\0') { + printf("Output: \n\n"); + } else { + printf("Output:\n%s\n\n", res.output); + } +} + int main() { char *prql_query; prql_query = "from albums | select [album_id, title] | take 3"; - - int res; - char res_buffer[256]; + CompileResult res; + CompileResult res2; // default compile option - res = compile(prql_query, NULL, res_buffer); - printf("%s\n\n", res_buffer); + res = compile(prql_query, NULL); + print_result(res); + result_destroy(res); // custom compile options Options opts; opts.format = false; opts.signature_comment = false; opts.target = "sql.mssql"; - res = compile(prql_query, &opts, res_buffer); - printf("%s\n\n", res_buffer); + res = compile(prql_query, &opts); + print_result(res); + result_destroy(res); // error handling - res = compile("from album | select [album_id] | select [title]", NULL, res_buffer); - if (res == 0) { - printf("success\n\n"); - } - if (res < 0) { - printf("error with code %d!\n%s\n\n", res, res_buffer); - } + res = compile("from album | select [album_id] | select [title]", NULL); + print_result(res); + result_destroy(res); - // intermediate results - char* pl_buffer = (char*) malloc(sizeof(char) * 512); - char* rq_buffer = (char*) malloc(sizeof(char) * 512); + // error handling + res = compile("let a = (from album)", NULL); + print_result(res); + result_destroy(res); - res = prql_to_pl(prql_query, pl_buffer); - printf("PL JSON: %s\n\n", pl_buffer); + // intermediate results + res = prql_to_pl(prql_query); + print_result(res); - res = pl_to_rq(pl_buffer, rq_buffer); - printf("RQ JSON: %s\n\n", rq_buffer); + res2 = pl_to_rq(res.output); + result_destroy(res); - free(pl_buffer); - free(rq_buffer); + print_result(res2); + result_destroy(res2); return 0; } diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h index 7e9ca050049c..a4a0ce492d77 100644 --- a/prql-lib/libprql_lib.h +++ b/prql-lib/libprql_lib.h @@ -3,6 +3,80 @@ #include #include +/** + * Compile message kind. Currently only Error is implemented. + */ +typedef enum MessageKind { + Error, + Warning, + Lint, +} MessageKind; + +/** + * Identifier of a location in source. + * Contains offsets in terms of chars. + */ +typedef struct Span { + size_t start; + size_t end; +} Span; + +/** + * Location within a source file. + */ +typedef struct SourceLocation { + size_t start_line; + size_t start_col; + size_t end_line; + size_t end_col; +} SourceLocation; + +/** + * Compile result message. + * + * Calling code is responsible for freeing all memory allocated + * for fields as well as strings. + */ +typedef struct Message { + /** + * Message kind. Currently only Error is implemented. + */ + enum MessageKind kind; + /** + * Machine-readable identifier of the error + */ + const int8_t *const *code; + /** + * Plain text of the error + */ + const int8_t *reason; + /** + * A list of suggestions of how to fix the error + */ + const int8_t *const *hint; + /** + * Character offset of error origin within a source file + */ + const struct Span *span; + /** + * Annotated code, containing cause and hints. + */ + const int8_t *const *display; + /** + * Line and column number of error origin within a source file + */ + const struct SourceLocation *location; +} Message; + +/** + * Result of compilation. + */ +typedef struct CompileResult { + const int8_t *output; + const struct Message *messages; + size_t messages_len; +} CompileResult; + /** * Compilation options */ @@ -39,9 +113,11 @@ typedef struct Options { * * # Safety * - * This function assumes zero-terminated strings and sufficiently large output buffers. + * This function assumes zero-terminated input strings. + * Calling code is responsible for freeing memory allocated for `CompileResult` + * by calling `result_destroy`. */ -int compile(const char *prql_query, const struct Options *options, char *out); +struct CompileResult compile(const char *prql_query, const struct Options *options); /** * Build PL AST from a PRQL string. PL in documented in the @@ -53,9 +129,11 @@ int compile(const char *prql_query, const struct Options *options, char *out); * * # Safety * - * This function assumes zero-terminated strings and sufficiently large output buffers. + * This function assumes zero-terminated input strings. + * Calling code is responsible for freeing memory allocated for `CompileResult` + * by calling `result_destroy`. */ -int prql_to_pl(const char *prql_query, char *out); +struct CompileResult prql_to_pl(const char *prql_query); /** * Finds variable references, validates functions calls, determines frames and converts PL to RQ. @@ -68,9 +146,11 @@ int prql_to_pl(const char *prql_query, char *out); * * # Safety * - * This function assumes zero-terminated strings and sufficiently large output buffers. + * This function assumes zero-terminated input strings. + * Calling code is responsible for freeing memory allocated for `CompileResult` + * by calling `result_destroy`. */ -int pl_to_rq(const char *pl_json, char *out); +struct CompileResult pl_to_rq(const char *pl_json); /** * Convert RQ AST into an SQL string. RQ is documented in the @@ -82,6 +162,18 @@ int pl_to_rq(const char *pl_json, char *out); * * # Safety * - * This function assumes zero-terminated strings and sufficiently large output buffers. + * This function assumes zero-terminated input strings. + * Calling code is responsible for freeing memory allocated for `CompileResult` + * by calling `result_destroy`. + */ +struct CompileResult rq_to_sql(const char *rq_json, const struct Options *options); + +/** + * Destroy a `CompileResult` once you are done with it. + * + * # Safety + * + * This function expects to be called exactly once after the call of any the functions + * that return CompileResult. No fields should be freed manually. */ -int rq_to_sql(const char *rq_json, char *out); +void result_destroy(struct CompileResult res); diff --git a/prql-lib/src/lib.rs b/prql-lib/src/lib.rs index 7c7e39f5eef8..6ab3f3f01fed 100644 --- a/prql-lib/src/lib.rs +++ b/prql-lib/src/lib.rs @@ -2,7 +2,7 @@ extern crate libc; -use libc::{c_char, c_int}; +use libc::{c_char, size_t}; use prql_compiler::ErrorMessages; use prql_compiler::Target; use std::ffi::CStr; @@ -18,13 +18,14 @@ use std::str::FromStr; /// /// # Safety /// -/// This function assumes zero-terminated strings and sufficiently large output buffers. +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. #[no_mangle] pub unsafe extern "C" fn compile( prql_query: *const c_char, options: *const Options, - out: *mut c_char, -) -> c_int { +) -> CompileResult { let prql_query: String = c_str_to_string(prql_query); let options = options.as_ref().map(convert_options).transpose(); @@ -38,7 +39,7 @@ pub unsafe extern "C" fn compile( }) .map_err(|e| e.composed("", &prql_query, false)); - result_into_c_str(result, out) + result_into_c_str(result) } /// Build PL AST from a PRQL string. PL in documented in the @@ -50,15 +51,17 @@ pub unsafe extern "C" fn compile( /// /// # Safety /// -/// This function assumes zero-terminated strings and sufficiently large output buffers. +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. #[no_mangle] -pub unsafe extern "C" fn prql_to_pl(prql_query: *const c_char, out: *mut c_char) -> c_int { +pub unsafe extern "C" fn prql_to_pl(prql_query: *const c_char) -> CompileResult { let prql_query: String = c_str_to_string(prql_query); let result = Ok(prql_query.as_str()) .and_then(prql_compiler::prql_to_pl) .and_then(prql_compiler::json::from_pl); - result_into_c_str(result, out) + result_into_c_str(result) } /// Finds variable references, validates functions calls, determines frames and converts PL to RQ. @@ -71,16 +74,18 @@ pub unsafe extern "C" fn prql_to_pl(prql_query: *const c_char, out: *mut c_char) /// /// # Safety /// -/// This function assumes zero-terminated strings and sufficiently large output buffers. +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. #[no_mangle] -pub unsafe extern "C" fn pl_to_rq(pl_json: *const c_char, out: *mut c_char) -> c_int { +pub unsafe extern "C" fn pl_to_rq(pl_json: *const c_char) -> CompileResult { let pl_json: String = c_str_to_string(pl_json); let result = Ok(pl_json.as_str()) .and_then(prql_compiler::json::to_pl) .and_then(prql_compiler::pl_to_rq) .and_then(prql_compiler::json::from_rq); - result_into_c_str(result, out) + result_into_c_str(result) } /// Convert RQ AST into an SQL string. RQ is documented in the @@ -92,15 +97,24 @@ pub unsafe extern "C" fn pl_to_rq(pl_json: *const c_char, out: *mut c_char) -> c /// /// # Safety /// -/// This function assumes zero-terminated strings and sufficiently large output buffers. +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. #[no_mangle] -pub unsafe extern "C" fn rq_to_sql(rq_json: *const c_char, out: *mut c_char) -> c_int { +pub unsafe extern "C" fn rq_to_sql( + rq_json: *const c_char, + options: *const Options, +) -> CompileResult { let rq_json: String = c_str_to_string(rq_json); - let result = Ok(rq_json.as_str()) - .and_then(prql_compiler::json::to_rq) - .and_then(|x| prql_compiler::rq_to_sql(x, &prql_compiler::Options::default())); - result_into_c_str(result, out) + let options = options.as_ref().map(convert_options).transpose(); + + let result = options.and_then(|options| { + Ok(rq_json.as_str()) + .and_then(prql_compiler::json::to_rq) + .and_then(|x| prql_compiler::rq_to_sql(x, &options.unwrap_or_default())) + }); + result_into_c_str(result) } /// Compilation options @@ -124,22 +138,166 @@ pub struct Options { pub signature_comment: bool, } -unsafe fn result_into_c_str(result: Result, out: *mut c_char) -> i32 { - let (is_err, string) = match result { - Ok(string) => (false, string), - Err(err) => (true, err.to_string()), - }; +/// Result of compilation. +#[repr(C)] +pub struct CompileResult { + pub output: *const i8, + pub messages: *const Message, + pub messages_len: size_t, +} + +/// Compile message kind. Currently only Error is implemented. +#[repr(C)] +pub enum MessageKind { + Error, + Warning, + Lint, +} + +/// Compile result message. +/// +/// Calling code is responsible for freeing all memory allocated +/// for fields as well as strings. +// Make sure to keep in sync with prql_compiler::ErrorMessage +#[repr(C)] +pub struct Message { + /// Message kind. Currently only Error is implemented. + pub kind: MessageKind, + /// Machine-readable identifier of the error + pub code: *const *const i8, + /// Plain text of the error + pub reason: *const i8, + /// A list of suggestions of how to fix the error + pub hint: *const *const i8, + /// Character offset of error origin within a source file + pub span: *const Span, + + /// Annotated code, containing cause and hints. + pub display: *const *const i8, + /// Line and column number of error origin within a source file + pub location: *const SourceLocation, +} + +/// Identifier of a location in source. +/// Contains offsets in terms of chars. +// Make sure to keep in sync with prql_compiler::Span +#[repr(C)] +pub struct Span { + pub start: size_t, + pub end: size_t, +} - let copy_len = string.bytes().len(); - let c_str = CString::new(string).unwrap(); +/// Location within a source file. +// Make sure to keep in sync with prql_compiler::SourceLocation +#[repr(C)] +pub struct SourceLocation { + pub start_line: size_t, + pub start_col: size_t, + + pub end_line: size_t, + pub end_col: size_t, +} - out.copy_from(c_str.as_ptr(), copy_len); - let end_of_string_ptr = out.add(copy_len); - *end_of_string_ptr = 0; +/// Destroy a `CompileResult` once you are done with it. +/// +/// # Safety +/// +/// This function expects to be called exactly once after the call of any the functions +/// that return CompileResult. No fields should be freed manually. +#[no_mangle] +pub unsafe extern "C" fn result_destroy(res: CompileResult) { + // This is required because we are allocating memory for + // strings, vectors and options. + // For strings and vectors this is required, but options may be + // able to live entirely within the struct, instead of the heap. + + for i in 0..res.messages_len { + let e = &*res.messages.add(i); + + if !e.code.is_null() { + drop(CString::from_raw(*e.code as *mut i8)); + drop(Box::from_raw(e.code as *mut *const i8)); + } + drop(CString::from_raw(e.reason as *mut i8)); + if !e.hint.is_null() { + drop(CString::from_raw(*e.hint as *mut i8)); + drop(Box::from_raw(e.hint as *mut *const i8)); + } + if !e.span.is_null() { + drop(Box::from_raw(e.span as *mut Span)); + } + if !e.display.is_null() { + drop(CString::from_raw(*e.display as *mut i8)); + drop(Box::from_raw(e.display as *mut *const i8)); + } + if !e.location.is_null() { + drop(Box::from_raw(e.location as *mut SourceLocation)); + } + } + drop(Vec::from_raw_parts( + res.messages as *mut i8, + res.messages_len, + res.messages_len, + )); + drop(CString::from_raw(res.output as *mut i8)); +} + +unsafe fn result_into_c_str(result: Result) -> CompileResult { + match result { + Ok(output) => CompileResult { + output: convert_string(output), + messages: ::std::ptr::null_mut(), + messages_len: 0, + }, + Err(err) => { + let mut errors = Vec::with_capacity(err.inner.len()); + errors.extend(err.inner.into_iter().map(|e| Message { + kind: MessageKind::Error, + code: option_to_ptr(e.code.map(convert_string)), + reason: convert_string(e.reason), + hint: option_to_ptr(e.hint.map(convert_string)), + span: option_to_ptr(e.span.map(convert_span)), + display: option_to_ptr(e.display.map(convert_string)), + location: option_to_ptr(e.location.map(convert_source_location)), + })); + CompileResult { + output: CString::default().into_raw(), + messages_len: errors.len(), + messages: errors.leak().as_ptr(), + } + } + } +} + +/// Allocates the value on the heap and returns a pointer to it. +/// If the input is None, it returns null pointer. +fn option_to_ptr(o: Option) -> *const T { + match o { + Some(x) => { + let b = Box::new(x); + Box::into_raw(b) + } + None => ::std::ptr::null(), + } +} + +fn convert_string(x: String) -> *const i8 { + CString::new(x).unwrap_or_default().into_raw() +} + +fn convert_span(x: prql_compiler::Span) -> Span { + Span { + start: x.start, + end: x.end, + } +} - match is_err { - true => -1, - false => 0, +fn convert_source_location(x: prql_compiler::SourceLocation) -> SourceLocation { + SourceLocation { + start_line: x.start.0, + start_col: x.start.1, + end_line: x.end.0, + end_col: x.end.1, } } @@ -149,7 +307,7 @@ unsafe fn c_str_to_string(c_str: *const c_char) -> String { } fn convert_options(o: &Options) -> Result { - let target = if o.target.is_null() { + let target = if !o.target.is_null() { Some(unsafe { c_str_to_string(o.target) }) } else { None diff --git a/prql-php/.gitignore b/prql-php/.gitignore index 61ead86667ca..4c802cd562b2 100644 --- a/prql-php/.gitignore +++ b/prql-php/.gitignore @@ -1 +1,2 @@ -/vendor +vendor/ +lib/ diff --git a/prql-php/README.md b/prql-php/README.md index 3b417479a4c4..66e283dcd7b5 100644 --- a/prql-php/README.md +++ b/prql-php/README.md @@ -1,9 +1,9 @@ # prql-php -`prql-php` offers PHP bindings through FFI. +`prql-php` offers PHP bindings to `prql-compiler` crate through FFI. -It provides the `Compiler` class which contains the `toJson` and `toSql` -methods. +It provides the `Compiler` class which contains `compile`, `prqlToPL`, `plToRQ` +and `rqToSQL` functions. It's still at an early stage, and isn't published to Composer. Contributions are welcome. @@ -21,5 +21,49 @@ enabled. Set `ffi.enable` in your php.ini configuration file to `"true"`. use Prql\Compiler\Compiler; $prql = new Compiler(); -$result = $prql->toSql("from employees"); +$result = $prql->compile("from employees"); + +echo($result->output); +``` + +## Development + +### Environment + +A way to establish a dev environment with PHP, the ext-ffi extension and +Composer is to use a [nix flake](https://github.com/loophp/nix-shell). After +installing nix, enable experimental flakes feature: + +``` +mkdir -p ~/.config/nix +echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf +``` + +Now you can spawn a shell from `prql-php/`: + +``` +nix shell github:loophp/nix-shell#env-php81 --impure +``` + +This will pull-in ext-ffi extension, because it's declared in `composer.json`. + +### Building + +There is a `build.sh` script that: + +- runs cargo to build `libprql_lib`, +- copies `libprql_lib.so` into `lib`, +- copies `libprql_lib.h` into `lib`. + +### Tests + +``` +sh build.sh +./vendor/bin/phpunit tests +``` + +### Code style + +``` +./vendor/bin/phpcs --standard=PSR12 src tests ``` diff --git a/prql-php/build.sh b/prql-php/build.sh new file mode 100644 index 000000000000..bbb545bbd312 --- /dev/null +++ b/prql-php/build.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +cargo build -p prql-lib --release + +mkdir -p lib +cp ../target/release/libprql_lib.so ../prql-lib/libprql_lib.h lib diff --git a/prql-php/composer.json b/prql-php/composer.json index 7fad323e451e..e224fe1ca46f 100644 --- a/prql-php/composer.json +++ b/prql-php/composer.json @@ -32,6 +32,7 @@ "ext-ffi": "*" }, "require-dev": { - "phpunit/phpunit": "^10" + "phpunit/phpunit": "^10", + "squizlabs/php_codesniffer": "^3.7" } } diff --git a/prql-php/composer.lock b/prql-php/composer.lock index bb8cb1d27700..d1c8a284c6c4 100644 --- a/prql-php/composer.lock +++ b/prql-php/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a4068cec0f3425baf61d7b880f827bea", + "content-hash": "6463be3ca6ff9224f299805a4a534a78", "packages": [], "packages-dev": [ { @@ -1411,6 +1411,54 @@ ], "time": "2023-02-07T11:34:05+00:00" }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.7.2", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/ed8e00df0a83aa96acf703f8c2979ff33341f879", + "reference": "ed8e00df0a83aa96acf703f8c2979ff33341f879", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" + }, + "bin": ["bin/phpcs", "bin/phpcbf"], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": ["BSD-3-Clause"], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/squizlabs/PHP_CodeSniffer", + "keywords": ["phpcs", "standards", "static analysis"], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, + "time": "2023-02-22T23:07:41+00:00" + }, { "name": "theseer/tokenizer", "version": "1.2.1", diff --git a/prql-php/src/Compiler.php b/prql-php/src/Compiler.php index baa470c4fa29..f27847dd77e8 100644 --- a/prql-php/src/Compiler.php +++ b/prql-php/src/Compiler.php @@ -9,11 +9,12 @@ * PHP version 8.0 * * @api - * @package Prql\Compiler + * * @author PRQL * @copyright 2023 PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 - * @link https://prql-lang.org/ + * + * @see https://prql-lang.org/ */ declare(strict_types=1); @@ -21,167 +22,248 @@ namespace Prql\Compiler; /** - * The PRQL compiler transpiles PRQL queries. - * - * @package Prql\Compiler * @author PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 - * @link https://prql-lang.org/ + * + * @see https://prql-lang.org/ */ final class Compiler { - private \FFI $_libprql; + private \FFI $ffi; /** * Initializes a new instance of the Compiler. * - * @param ?string|null $lib_path Path to the libprql library. + * @param ?string|null $lib_path path to the libprql library */ - function __construct(?string $lib_path = null) + public function __construct(?string $lib_path = null) { - $library = $lib_path; - if ($lib_path === null) { - $library = __DIR__; + $lib_path = __DIR__.'/../lib'; } - if (PHP_OS_FAMILY === "Windows") { - $library .= "\libprql_lib.dll"; - } elseif (PHP_OS_FAMILY === "Darwin") { - $library .= "/libprql_lib.dylib"; + $header = $lib_path.'/libprql_lib.h'; + + if (PHP_OS_FAMILY === 'Windows') { + $library = $lib_path."\libprql_lib.dll"; + } elseif (PHP_OS_FAMILY === 'Darwin') { + $library = $lib_path.'/libprql_lib.dylib'; } else { - $library .= "/libprql_lib.so"; + $library = $lib_path.'/libprql_lib.so'; } - $this->_libprql = \FFI::cdef( - " - typedef struct Options { - bool format; - char *target; - bool signature_comment; - } Options; - - int compile(const char *prql_query, const struct Options *options, char *out); - int prql_to_pl(const char *prql_query, char *out); - int pl_to_rq(const char *pl_json, char *out); - int rq_to_sql(const char *rq_json, char *out); - ", $library - ); + $header_source = file_get_contents($header, false, null, 0, 1024 * 1024); + + if ($header_source === false) { + throw new \InvalidArgumentException('Cannot load header file.'); + } + + $this->ffi = \FFI::cdef($header_source, $library); } /** * Compile a PRQL string into a SQL string. * - * @param string $prql_query A PRQL query. - * @param Options|null $options PRQL compiler options. + * @param string $prql_query a PRQL query + * @param Options|null $options compile options * - * @return string SQL query. - * @throws \InvalidArgumentException If no query is given or the query canno - * be compiled. - * @api - * @todo FIX THIS. THIS DOES NOT WORK! - * @ignore Ignore this function until fixed. + * @return Result compilation result containing SQL query + * + * @throws \InvalidArgumentException on NULL input */ - function compile(string $prql_query, ?Options $options = null): string + public function compile(string $prql_query, ?Options $options = null): Result { if (!$prql_query) { - throw new \InvalidArgumentException("No query given."); + throw new \InvalidArgumentException('No query given.'); } - if ($options === null) { - $options = new Options(); - } - - $ffi_options = $this->_libprql->new("struct Options"); - $ffi_options->format = $options->format; - $ffi_options->signature_comment = $options->signature_comment; + $ffi_options = $this->optionsInit($options); - if (isset($options->target)) { - $target_len = strlen($options->target); - $ffi_options->target = \FFI::new("char[$target_len]", false); - \FFI::memcpy($ffi_options->target, $options->target, $target_len); - \FFI::free($ffi_options->target); - } - - $out = str_pad("", 1024); - if ($this->_libprql->compile($prql_query, \FFI::addr($ffi_options), $out) !== 0) { - throw new \InvalidArgumentException("Could not compile query."); - } + $res = $this->ffi->compile($prql_query, \FFI::addr($ffi_options)); - unset($ffi_options); + $this->optionsDestroy($ffi_options); - return trim($out); + return $this->convertResult($res); } /** * Compile a PRQL string into PL. * - * @param string $prql_query A PRQL query. + * @param string $prql_query PRQL query + * + * @return Result compilation result containing PL serialized as JSON + * + * @throws \InvalidArgumentException on NULL input * - * @return string Pipelined Language (PL) JSON string. - * @throws \InvalidArgumentException If no query is given or the query cannot - * be compiled. * @api */ - function prqlToPL(string $prql_query): string + public function prqlToPL(string $prql_query): Result { if (!$prql_query) { - throw new \InvalidArgumentException("No query given."); + throw new \InvalidArgumentException('No query given.'); } - $out = str_pad("", 1024); - if ($this->_libprql->prql_to_pl($prql_query, $out) !== 0) { - throw new \InvalidArgumentException("Could not compile query."); - } + $res = $this->ffi->prql_to_pl($prql_query); - return trim($out); + return $this->convertResult($res); } /** * Converts PL to RQ. * - * @param string $pl_json PL in JSON format. + * @param string $pl_json PL serialized as JSON + * + * @return Result compilation result containing RQ serialized as JSON + * + * @throws \InvalidArgumentException on NULL input * - * @return string RQ string. - * @throws \InvalidArgumentException If no query is given or the query cannot - * be compiled. * @api */ - function plToRQ(string $pl_json): string + public function plToRQ(string $pl_json): Result { - if (!$prql_query) { - throw new \InvalidArgumentException("No query given."); + if (!$pl_json) { + throw new \InvalidArgumentException('No query given.'); } - $out = str_pad("", 1024); - if ($this->_libprql->pl_to_rq($pl_json, $out) !== 0) { - throw new \InvalidArgumentException("Could not convert PL."); - } + $res = $this->ffi->pl_to_rq($pl_json); - return trim($out); + return $this->convertResult($res); } /** * Converts RQ to SQL. * - * @param string $rq_json PL in JSON format. + * @param string $rq_json RQ serialized as JSON + * @param Options|null $options compile options + * + * @return Result compilation result containing SQL query + * + * @throws \InvalidArgumentException on NULL input * - * @return string SQL string. - * @throws \InvalidArgumentException If no query is given or the query cannot - * be compiled. * @api */ - function rQToSql(string $rq_json): string + public function rqToSQL(string $rq_json, ?Options $options = null): Result { - if (!$prql_query) { - throw new \InvalidArgumentException("No query given."); + if (!$rq_json) { + throw new \InvalidArgumentException('No query given.'); } - $out = str_pad("", 1024); - if ($this->_libprql->rq_to_sql($rq_json, $out) !== 0) { - throw new \InvalidArgumentException("Could not convert RQ."); + $ffi_options = $this->optionsInit($options); + + $res = $this->ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); + + $this->optionsDestroy($ffi_options); + + return $this->convertResult($res); + } + + private function optionsInit(?Options $options = null) + { + if ($options === null) { + $options = new Options(); } - return trim($out); + $ffi_options = $this->ffi->new('struct Options'); + $ffi_options->format = $options->format; + $ffi_options->signature_comment = $options->signature_comment; + + if (isset($options->target)) { + $len = strlen($options->target) + 1; + $ffi_options->target = \FFI::new("char[$len]", false); + \FFI::memcpy($ffi_options->target, $options->target, $len - 1); + } + + return $ffi_options; + } + + private function optionsDestroy($ffi_options) + { + if (!\FFI::isNull($ffi_options->target)) { + \FFI::free($ffi_options->target); + } + unset($ffi_options); + } + + private function convertResult($ffi_res): Result + { + $res = new Result(); + + // convert string + $res->output = $this->convertString($ffi_res->output); + + $res->messages = []; + for ($i = 0; $i < $ffi_res->messages_len; ++$i) { + $res->messages[$i] = $this->convertMessage($ffi_res->messages[$i]); + } + + // free the ffi_result + $this->ffi->result_destroy($ffi_res); + + return $res; + } + + private function convertMessage($ffi_msg): Message + { + $msg = new Message(); + + // I'm using numbers here, I cannot find a way to refer to MessageKind.Error + if ($ffi_msg->kind == 0) { + $msg->kind = MessageKind::Error; + } elseif ($ffi_msg->kind == 1) { + $msg->kind = MessageKind::Warning; + } elseif ($ffi_msg->kind == 2) { + $msg->kind = MessageKind::Lint; + } + + $msg->code = $this->convertNullableString($ffi_msg->code); + $msg->reason = $this->convertString($ffi_msg->reason); + $msg->span = $this->convertSpan($ffi_msg->span); + $msg->hint = $this->convertNullableString($ffi_msg->hint); + + $msg->display = $this->convertNullableString($ffi_msg->display); + $msg->location = $this->convertLocation($ffi_msg->location); + + return $msg; + } + + private function convertSpan($ffi_ptr): ?Span + { + if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { + return null; + } + $span = new Span(); + $span->start = $ffi_ptr[0]->start; + $span->end = $ffi_ptr[0]->end; + + return $span; + } + + private function convertLocation($ffi_ptr): ?SourceLocation + { + if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { + return null; + } + + $location = new SourceLocation(); + $location->start_line = $ffi_ptr[0]->start_line; + $location->start_col = $ffi_ptr[0]->start_col; + $location->end_line = $ffi_ptr[0]->end_line; + $location->end_col = $ffi_ptr[0]->end_col; + + return $location; + } + + private function convertNullableString($ffi_ptr): ?string + { + if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { + return null; + } + // dereference + return $this->convertString($ffi_ptr[0]); + } + + private function convertString($ffi_ptr): string + { + return \FFI::string(\FFI::cast(\FFI::type('char*'), $ffi_ptr)); } } diff --git a/prql-php/src/Message.php b/prql-php/src/Message.php new file mode 100644 index 000000000000..9029fb7fd889 --- /dev/null +++ b/prql-php/src/Message.php @@ -0,0 +1,40 @@ + + */ + public array $messages; +} diff --git a/prql-php/src/SourceLocation.php b/prql-php/src/SourceLocation.php new file mode 100644 index 000000000000..15af1545ac65 --- /dev/null +++ b/prql-php/src/SourceLocation.php @@ -0,0 +1,16 @@ +assertFileExists("src/libprql_lib.so"); + $this->assertFileExists("lib/libprql_lib.so"); } - public function testPrqlLibraryLoads(): void + public function testPrqlHeaderFileExists(): void { - $code = "int prql_to_pl(const char *prql_query, char *out);"; - $ffi = FFI::cdef($code, "src/libprql_lib.so"); - $this->assertInstanceOf(FFI::class, $ffi); + $this->assertFileExists("lib/libprql_lib.h"); } - public function testInvalidQueryThrows(): void + public function testInvalidQuery(): void { - $this->expectException(\InvalidArgumentException::class); - $prql = new Compiler(); - $prql->compile("invalid"); + $res = $prql->compile("invalid"); + + $this->assertCount(1, $res->messages); } public function testCompileWorks(): void @@ -39,18 +41,34 @@ public function testCompileWorks(): void $options->target = "sql.mssql"; $prql = new Compiler(); - $expected = "SELECT * FROM employees"; - $actual = $prql->compile("from employees", $options); + $actual = $prql->compile("from employees | take 10", $options); + $this->assertCount(0, $actual->messages); - $this->assertEquals($expected, $actual); + $this->assertEquals("SELECT TOP (10) * FROM employees", $actual->output); } - public function testPrqlToPLWorks(): void + public function testOtherFunctions(): void { $prql = new Compiler(); - $pl = $prql->prqlToPL("from employees"); + $query = " + let a = (from employees | take 10) + + from a | select [first_name] + "; + + $pl = $prql->prqlToPL($query); + $this->assertCount(0, $pl->messages); + + $rq = $prql->plToRQ($pl->output); + $this->assertCount(0, $rq->messages); + + $via_json = $prql->rqToSQL($rq->output); + $this->assertCount(0, $via_json->messages); + + $direct = $prql->compile($query); + $this->assertCount(0, $direct->messages); - $this->assertNotNull($pl); + $this->assertEquals($via_json, $direct); } } From 31baef45cfced37f8c6439dc7232065dc79a8ff5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 9 Mar 2023 13:32:38 +0100 Subject: [PATCH 130/184] refactor!: prepare for type system (#2067) --- book/src/language-features/ranges.md | 4 +- book/src/transforms/take.md | 2 +- .../prql/language-features/ranges-0.prql | 2 +- .../prql/language-features/ranges-1.prql | 2 +- book/tests/prql/transforms/take-1.prql | 2 +- ...ot__@language-features__ranges-0.prql.snap | 5 +- ...ot__@language-features__ranges-1.prql.snap | 5 +- .../snapshot__@transforms__take-1.prql.snap | 5 +- prql-compiler/src/ast/pl/expr.rs | 18 +- prql-compiler/src/ast/pl/fold.rs | 28 ++- prql-compiler/src/ast/pl/stmt.rs | 19 +- prql-compiler/src/ast/pl/types.rs | 189 ++++++++++-------- prql-compiler/src/parser/expr.rs | 4 +- prql-compiler/src/parser/lexer.rs | 14 +- prql-compiler/src/parser/stmt.rs | 66 +++--- prql-compiler/src/semantic/context.rs | 34 +++- prql-compiler/src/semantic/lowering.rs | 9 +- prql-compiler/src/semantic/resolver.rs | 111 +++++++--- ...c__resolver__test__frames_and_names-2.snap | 4 +- ...c__resolver__test__frames_and_names-3.snap | 10 +- ...tic__resolver__test__frames_and_names.snap | 10 +- ...semantic__resolver__test__functions_1.snap | 13 +- ...tic__resolver__test__functions_nested.snap | 28 +-- ..._resolver__test__functions_pipeline-2.snap | 23 ++- ...c__resolver__test__functions_pipeline.snap | 9 +- ..._semantic__resolver__test__named_args.snap | 28 +-- ...semantic__resolver__test__variables_1.snap | 26 +-- prql-compiler/src/semantic/std.prql | 35 +++- prql-compiler/src/semantic/transforms.rs | 35 ++-- prql-compiler/src/semantic/type_resolver.rs | 94 +++++++-- prql-compiler/src/sql/std_impl.prql | 20 +- prql-compiler/src/test.rs | 4 +- 32 files changed, 534 insertions(+), 324 deletions(-) diff --git a/book/src/language-features/ranges.md b/book/src/language-features/ranges.md index 4c3d674c9e75..fb4efbd3c953 100644 --- a/book/src/language-features/ranges.md +++ b/book/src/language-features/ranges.md @@ -8,7 +8,7 @@ including dates: ```prql from events -filter (date | in @1776-07-04..@1787-09-17) +filter (created_at | in @1776-07-04..@1787-09-17) filter (magnitude | in 50..100) derive is_northern = (latitude | in 0..) ``` @@ -20,7 +20,7 @@ in `take`: ```prql from orders -sort [-value, date] +sort [-value, created_at] take 101..110 ``` diff --git a/book/src/transforms/take.md b/book/src/transforms/take.md index c12493a7e3e9..2a908e4ed64b 100644 --- a/book/src/transforms/take.md +++ b/book/src/transforms/take.md @@ -18,6 +18,6 @@ take 10 ```prql from orders -sort [-value, date] +sort [-value, created_at] take 101..110 ``` diff --git a/book/tests/prql/language-features/ranges-0.prql b/book/tests/prql/language-features/ranges-0.prql index d200b9b61999..e3eea68afafb 100644 --- a/book/tests/prql/language-features/ranges-0.prql +++ b/book/tests/prql/language-features/ranges-0.prql @@ -1,4 +1,4 @@ from events -filter (date | in @1776-07-04..@1787-09-17) +filter (created_at | in @1776-07-04..@1787-09-17) filter (magnitude | in 50..100) derive is_northern = (latitude | in 0..) diff --git a/book/tests/prql/language-features/ranges-1.prql b/book/tests/prql/language-features/ranges-1.prql index f6939b843a7c..fcf59ae0e31c 100644 --- a/book/tests/prql/language-features/ranges-1.prql +++ b/book/tests/prql/language-features/ranges-1.prql @@ -1,3 +1,3 @@ from orders -sort [-value, date] +sort [-value, created_at] take 101..110 diff --git a/book/tests/prql/transforms/take-1.prql b/book/tests/prql/transforms/take-1.prql index f6939b843a7c..fcf59ae0e31c 100644 --- a/book/tests/prql/transforms/take-1.prql +++ b/book/tests/prql/transforms/take-1.prql @@ -1,3 +1,3 @@ from orders -sort [-value, date] +sort [-value, created_at] take 101..110 diff --git a/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap index 79caec12df4b..f3d6e9a9f02c 100644 --- a/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from events\nfilter (date | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" +expression: "from events\nfilter (created_at | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" input_file: book/tests/prql/language-features/ranges-0.prql --- SELECT @@ -9,5 +9,6 @@ SELECT FROM events WHERE - date BETWEEN DATE '1776-07-04' AND DATE '1787-09-17' + created_at BETWEEN DATE '1776-07-04' AND DATE '1787-09-17' AND magnitude BETWEEN 50 AND 100 + diff --git a/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap index 69b3698f9352..7c8542dfe016 100644 --- a/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap +++ b/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" +expression: "from orders\nsort [-value, created_at]\ntake 101..110\n" input_file: book/tests/prql/language-features/ranges-1.prql --- SELECT @@ -9,6 +9,7 @@ FROM orders ORDER BY value DESC, - date + created_at LIMIT 10 OFFSET 100 + diff --git a/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap index 0e739ad8c893..8693c9d3c8ff 100644 --- a/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap +++ b/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap @@ -1,6 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from orders\nsort [-value, date]\ntake 101..110\n" +expression: "from orders\nsort [-value, created_at]\ntake 101..110\n" input_file: book/tests/prql/transforms/take-1.prql --- SELECT @@ -9,6 +9,7 @@ FROM orders ORDER BY value DESC, - date + created_at LIMIT 10 OFFSET 100 + diff --git a/prql-compiler/src/ast/pl/expr.rs b/prql-compiler/src/ast/pl/expr.rs index 21f14994e112..fc98216c51fa 100644 --- a/prql-compiler/src/ast/pl/expr.rs +++ b/prql-compiler/src/ast/pl/expr.rs @@ -77,6 +77,7 @@ pub enum ExprKind { name: String, args: Vec, }, + Set(SetExpr), /// a placeholder for values provided after query is compiled Param(String), @@ -176,8 +177,8 @@ pub struct Closure { pub body_ty: Option, pub args: Vec, - pub params: Vec, - pub named_params: Vec, + pub params: Vec, + pub named_params: Vec, pub env: HashMap, } @@ -190,6 +191,16 @@ impl Closure { } } +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct ClosureParam { + pub name: String, + + #[serde(skip_serializing_if = "Option::is_none")] + pub ty: Option, + + pub default_value: Option, +} + #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub struct WindowFrame> { pub kind: WindowKind, @@ -583,6 +594,9 @@ impl Display for Expr { ExprKind::BuiltInFunction { .. } => { f.write_str("")?; } + ExprKind::Set(_) => { + writeln!(f, "")?; + } ExprKind::Param(id) => { writeln!(f, "${id}")?; } diff --git a/prql-compiler/src/ast/pl/fold.rs b/prql-compiler/src/ast/pl/fold.rs index 09fc02d71bd7..75bb3c2cf27c 100644 --- a/prql-compiler/src/ast/pl/fold.rs +++ b/prql-compiler/src/ast/pl/fold.rs @@ -36,10 +36,16 @@ pub trait AstFold { fn fold_exprs(&mut self, exprs: Vec) -> Result> { exprs.into_iter().map(|node| self.fold_expr(node)).collect() } - fn fold_var_def(&mut self, table: VarDef) -> Result { + fn fold_var_def(&mut self, var_def: VarDef) -> Result { Ok(VarDef { - name: table.name, - value: Box::new(self.fold_expr(*table.value)?), + name: var_def.name, + value: Box::new(self.fold_expr(*var_def.value)?), + }) + } + fn fold_type_def(&mut self, ty_def: TypeDef) -> Result { + Ok(TypeDef { + name: ty_def.name, + value: ty_def.value.map(|x| self.fold_expr(x)).transpose()?, }) } fn fold_pipeline(&mut self, pipeline: Pipeline) -> Result { @@ -61,7 +67,7 @@ pub trait AstFold { fold_interpolate_item(self, sstring_item) } fn fold_type(&mut self, t: Ty) -> Result { - fold_type(self, t) + Ok(t) } fn fold_window(&mut self, window: WindowFrame) -> Result { fold_window(self, window) @@ -113,7 +119,7 @@ pub fn fold_expr_kind(fold: &mut T, expr_kind: ExprKind) -> Param(id) => Param(id), // None of these capture variables, so we don't need to fold them. - Literal(_) => expr_kind, + Literal(_) | Set(_) => expr_kind, }) } @@ -122,6 +128,7 @@ pub fn fold_stmt_kind(fold: &mut T, stmt_kind: StmtKind) -> Ok(match stmt_kind { FuncDef(func) => FuncDef(fold.fold_func_def(func)?), VarDef(var_def) => VarDef(fold.fold_var_def(var_def)?), + TypeDef(type_def) => TypeDef(fold.fold_type_def(type_def)?), Main(expr) => Main(Box::new(fold.fold_expr(*expr)?)), QueryDef(_) => stmt_kind, }) @@ -314,14 +321,3 @@ pub fn fold_func_param( }) .try_collect() } - -pub fn fold_type(fold: &mut T, t: Ty) -> Result { - Ok(match t { - Ty::Literal(_) => t, - Ty::Parameterized(t, p) => { - Ty::Parameterized(Box::new(fold.fold_type(*t)?), Box::new(fold.fold_type(*p)?)) - } - Ty::AnyOf(ts) => Ty::AnyOf(ts.into_iter().map(|t| fold_type(fold, t)).try_collect()?), - _ => t, - }) -} diff --git a/prql-compiler/src/ast/pl/stmt.rs b/prql-compiler/src/ast/pl/stmt.rs index 05c43066a00b..11f2c5124b77 100644 --- a/prql-compiler/src/ast/pl/stmt.rs +++ b/prql-compiler/src/ast/pl/stmt.rs @@ -27,6 +27,7 @@ pub enum StmtKind { QueryDef(QueryDef), FuncDef(FuncDef), VarDef(VarDef), + TypeDef(TypeDef), Main(Box), } @@ -44,15 +45,16 @@ pub struct FuncDef { pub positional_params: Vec, // ident pub named_params: Vec, // named expr pub body: Box, - pub return_ty: Option, + pub return_ty: Option, } #[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] pub struct FuncParam { pub name: String, + /// Parsed expression that will be resolved to a type #[serde(skip_serializing_if = "Option::is_none")] - pub ty: Option, + pub ty_expr: Option, pub default_value: Option, } @@ -63,6 +65,12 @@ pub struct VarDef { pub value: Box, } +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +pub struct TypeDef { + pub name: String, + pub value: Option, +} + impl From for Stmt { fn from(kind: StmtKind) -> Self { Stmt { @@ -127,6 +135,13 @@ impl Display for StmtKind { } }; } + StmtKind::TypeDef(ty_def) => { + if let Some(value) = &ty_def.value { + write!(f, "type {} = {value}\n\n", ty_def.name)?; + } else { + write!(f, "type {}\n\n", ty_def.name)?; + } + } } Ok(()) } diff --git a/prql-compiler/src/ast/pl/types.rs b/prql-compiler/src/ast/pl/types.rs index cb1463940c7b..622b3117020a 100644 --- a/prql-compiler/src/ast/pl/types.rs +++ b/prql-compiler/src/ast/pl/types.rs @@ -1,20 +1,49 @@ -use std::cmp::Ordering; use std::fmt::{Debug, Display, Formatter, Result, Write}; use enum_as_inner::EnumAsInner; use serde::{Deserialize, Serialize}; -use super::Frame; +use super::{Frame, Literal}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] +pub enum SetExpr { + /// Set of a built-in primitive type + Primitive(TyLit), + + /// Set that contains only a literal value + Singleton(Literal), + + /// Union of sets (sum) + Union(Vec<(Option, SetExpr)>), + + /// Set of tuples (product) + Tuple(Vec), + + /// Set of arrays + Array(Box), + + /// Set of sets. + /// Used for exprs that can be converted to SetExpr and then used as a Ty. + Set, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub enum TupleElement { + Single(Option, SetExpr), + Wildcard, +} #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, EnumAsInner)] pub enum Ty { - Empty, - Literal(TyLit), - Named(String), - Parameterized(Box, Box), - AnyOf(Vec), + /// Value is an element of this [SetExpr] + SetExpr(SetExpr), + + /// Value is a function described by [TyFunc] + // TODO: convert into [Ty::Domain]. Function(TyFunc), + /// Special type for relations. + // TODO: convert into [Ty::Domain]. Table(Frame), /// Means that we have no information about the type of the variable and @@ -26,20 +55,23 @@ pub enum Ty { Debug, Clone, Serialize, Deserialize, PartialEq, Eq, strum::EnumString, strum::Display, )] pub enum TyLit { + // TODO: convert to a named expression #[strum(to_string = "list")] List, + // TODO: convert to a named expression #[strum(to_string = "column")] Column, + // TODO: convert to a named expression #[strum(to_string = "scalar")] Scalar, - #[strum(to_string = "integer")] - Integer, + #[strum(to_string = "int")] + Int, #[strum(to_string = "float")] Float, #[strum(to_string = "bool")] Bool, - #[strum(to_string = "string")] - String, + #[strum(to_string = "text")] + Text, #[strum(to_string = "date")] Date, #[strum(to_string = "time")] @@ -56,109 +88,90 @@ pub struct TyFunc { } impl Ty { - pub const fn column() -> Ty { - Ty::Literal(TyLit::Column) - } -} + pub fn is_superset_of(&self, subset: &Ty) -> bool { + match (self, subset) { + // Not handled here. See type_resolver. + (Ty::Infer, _) | (_, Ty::Infer) => false, -impl From for Ty { - fn from(lit: TyLit) -> Self { - Ty::Literal(lit) - } -} + (Ty::SetExpr(left), Ty::SetExpr(right)) => left.is_superset_of(right), + + (Ty::Table(_), Ty::Table(_)) => true, -impl Default for Ty { - fn default() -> Self { - Ty::Infer + (l, r) => l == r, + } } } -/// Implements a partial ordering or types: -/// - higher up are types that include many others (AnyOf, Any) and -/// - on the bottom are the atomic types (bool, string). -impl PartialOrd for Ty { - fn partial_cmp(&self, other: &Self) -> Option { - match (self, other) { - // Not handled here. See type_resolver. - (Ty::Infer, _) | (_, Ty::Infer) => None, +impl SetExpr { + fn is_superset_of(&self, subset: &SetExpr) -> bool { + match (self, subset) { + // TODO: convert these to array + (SetExpr::Primitive(TyLit::Column), SetExpr::Primitive(TyLit::Column)) => true, + (SetExpr::Primitive(TyLit::Column), SetExpr::Primitive(_)) => true, + (SetExpr::Primitive(_), SetExpr::Primitive(TyLit::Column)) => false, - (Ty::Literal(TyLit::Column), Ty::Literal(TyLit::Column)) => Some(Ordering::Equal), - (Ty::Literal(TyLit::Column), Ty::Literal(_)) => Some(Ordering::Greater), - (Ty::Literal(_), Ty::Literal(TyLit::Column)) => Some(Ordering::Less), + (SetExpr::Primitive(l0), SetExpr::Primitive(r0)) => l0 == r0, + (SetExpr::Union(many), one) => many.iter().any(|(_, any)| any.is_superset_of(one)), + (one, SetExpr::Union(many)) => many.iter().all(|(_, each)| one.is_superset_of(each)), - (Ty::Literal(l0), Ty::Literal(r0)) => { - if l0 == r0 { - Some(Ordering::Equal) - } else { - None - } - } - (Ty::AnyOf(many), one) => { - if many.iter().any(|m| m >= one) { - Some(Ordering::Greater) - } else { - None - } - } - (one, Ty::AnyOf(many)) => { - if many.iter().any(|m| m >= one) { - Some(Ordering::Less) - } else { - None - } - } - (Ty::Parameterized(l_ty, l_param), Ty::Parameterized(r_ty, r_param)) => { - if l_ty == r_ty && l_param == r_param { - Some(Ordering::Equal) - } else { - None - } - } - (Ty::Parameterized(l_ty, _), r_ty) if **l_ty == *r_ty => Some(Ordering::Equal), - (l_ty, Ty::Parameterized(r_ty, _)) if *l_ty == **r_ty => Some(Ordering::Equal), + (l, r) => l == r, + } + } +} - (Ty::Table(_), Ty::Table(_)) => Some(Ordering::Equal), +impl Display for Ty { + fn fmt(&self, f: &mut Formatter<'_>) -> Result { + match &self { + Ty::SetExpr(lit) => write!(f, "{:}", lit), + Ty::Table(frame) => write!(f, "table<{frame}>"), + Ty::Infer => write!(f, "infer"), + Ty::Function(func) => { + write!(f, "func")?; - (l, r) => { - if l == r { - Some(Ordering::Equal) - } else { - None + for t in &func.args { + write!(f, " {t}")?; } + write!(f, " -> {}", func.return_ty)?; + Ok(()) } } } } -impl Display for Ty { +impl Display for SetExpr { fn fmt(&self, f: &mut Formatter<'_>) -> Result { match &self { - Ty::Empty => write!(f, "()"), - Ty::Literal(lit) => write!(f, "{:}", lit), - Ty::Named(name) => write!(f, "{:}", name), - Ty::Parameterized(t, param) => { - write!(f, "{t}<{}>", param) - } - Ty::AnyOf(ts) => { - for (i, t) in ts.iter().enumerate() { - write!(f, "{t}")?; + SetExpr::Primitive(lit) => write!(f, "{:}", lit), + SetExpr::Union(ts) => { + for (i, (_, e)) in ts.iter().enumerate() { + write!(f, "{e}")?; if i < ts.len() - 1 { f.write_char('|')?; } } Ok(()) } - Ty::Table(frame) => write!(f, "table<{frame}>"), - Ty::Infer => write!(f, "infer"), - Ty::Function(func) => { - write!(f, "func")?; - - for t in &func.args { - write!(f, " {t}")?; + SetExpr::Singleton(lit) => write!(f, "{:}", lit), + SetExpr::Tuple(elements) => { + write!(f, "[")?; + for e in elements { + match e { + TupleElement::Wildcard => { + write!(f, "*")?; + } + TupleElement::Single(name, expr) => { + if let Some(name) = name { + write!(f, "{name} = ")? + } + write!(f, "{expr}")? + } + } + write!(f, ",")? } - write!(f, " -> {}", func.return_ty)?; Ok(()) } + SetExpr::Set => write!(f, "set"), + SetExpr::Array(_) => todo!(), } } } diff --git a/prql-compiler/src/parser/expr.rs b/prql-compiler/src/parser/expr.rs index f45e28f1c231..27840e0d26a4 100644 --- a/prql-compiler/src/parser/expr.rs +++ b/prql-compiler/src/parser/expr.rs @@ -195,7 +195,7 @@ where .labelled("pipeline") } -fn binary_op_parser<'a, Term, Op>( +pub fn binary_op_parser<'a, Term, Op>( term: Term, op: Op, ) -> impl Parser> + 'a @@ -307,7 +307,7 @@ fn operator_compare() -> impl Parser> { fn operator_and() -> impl Parser> { just(Token::And).to(BinOp::And) } -fn operator_or() -> impl Parser> { +pub fn operator_or() -> impl Parser> { just(Token::Or).to(BinOp::Or) } fn operator_coalesce() -> impl Parser> { diff --git a/prql-compiler/src/parser/lexer.rs b/prql-compiler/src/parser/lexer.rs index 8ed26a1f748f..ed787d4dcf14 100644 --- a/prql-compiler/src/parser/lexer.rs +++ b/prql-compiler/src/parser/lexer.rs @@ -53,10 +53,16 @@ pub fn lexer() -> impl Parser)>, Error let ident = ident_part().map(Token::Ident); - let keyword = choice((just("func"), just("let"), just("case"), just("prql"))) - .then_ignore(end_expr()) - .map(|x| x.to_string()) - .map(Token::Keyword); + let keyword = choice(( + just("func"), + just("let"), + just("case"), + just("prql"), + just("type"), + )) + .then_ignore(end_expr()) + .map(|x| x.to_string()) + .map(Token::Keyword); let literal = literal().map(Token::Literal); diff --git a/prql-compiler/src/parser/stmt.rs b/prql-compiler/src/parser/stmt.rs index 3006cfbe0c1f..393be2596b34 100644 --- a/prql-compiler/src/parser/stmt.rs +++ b/prql-compiler/src/parser/stmt.rs @@ -1,4 +1,4 @@ -use std::{collections::HashMap, str::FromStr}; +use std::collections::HashMap; use chumsky::prelude::*; use semver::VersionReq; @@ -13,8 +13,8 @@ pub fn source() -> impl Parser, Error = Simple> { query_def() .or_not() .chain::( - var_def() - .or(function_def()) + choice((type_def(), var_def(), function_def())) + .map_with_span(into_stmt) .separated_by(new_line().repeated()) .allow_leading() .allow_trailing(), @@ -70,18 +70,26 @@ fn query_def() -> impl Parser> { .labelled("query header") } -fn var_def() -> impl Parser> { +fn var_def() -> impl Parser> { keyword("let") .ignore_then(ident_part()) .then_ignore(ctrl('=')) .then(expr_call().map(Box::new)) .map(|(name, value)| VarDef { name, value }) .map(StmtKind::VarDef) - .map_with_span(into_stmt) .labelled("variable definition") } -fn function_def() -> impl Parser> { +fn type_def() -> impl Parser> { + keyword("type") + .ignore_then(ident_part()) + .then(ctrl('=').ignore_then(expr_call()).or_not()) + .map(|(name, value)| TypeDef { name, value }) + .map(StmtKind::TypeDef) + .labelled("type definition") +} + +fn function_def() -> impl Parser> { keyword("func") .ignore_then( // func name @@ -100,9 +108,9 @@ fn function_def() -> impl Parser> { .map(|(((name, return_ty), params), body)| { let (pos, nam) = params .into_iter() - .map(|((name, ty), default_value)| FuncParam { + .map(|((name, ty_expr), default_value)| FuncParam { name, - ty, + ty_expr, default_value, }) .partition(|p| p.default_value.is_none()); @@ -116,39 +124,17 @@ fn function_def() -> impl Parser> { } }) .map(StmtKind::FuncDef) - .map_with_span(into_stmt) .labelled("function definition") } -pub fn type_expr() -> impl Parser> { - recursive(|type_expr| { - let type_term = ident_part().then(type_expr.or_not()).map(|(name, param)| { - let ty = match TyLit::from_str(&name) { - Ok(t) => Ty::from(t), - Err(_) if name == "table" => Ty::Table(Frame::default()), - Err(_) => { - eprintln!("named type: {}", name); - Ty::Named(name.to_string()) - } - }; - - if let Some(param) = param { - Ty::Parameterized(Box::new(ty), Box::new(param)) - } else { - ty - } - }); - - type_term - .separated_by(ctrl('|')) - .delimited_by(ctrl('<'), ctrl('>')) - .map(|mut terms| { - if terms.len() == 1 { - terms.remove(0) - } else { - Ty::AnyOf(terms) - } - }) - }) - .labelled("type expression") +pub fn type_expr() -> impl Parser> { + let literal = select! { Token::Literal(lit) => ExprKind::Literal(lit) }; + + let ident = ident().map(ExprKind::Ident); + + let term = literal.or(ident).map_with_span(into_expr); + + binary_op_parser(term, operator_or()) + .delimited_by(ctrl('<'), ctrl('>')) + .labelled("type expression") } diff --git a/prql-compiler/src/semantic/context.rs b/prql-compiler/src/semantic/context.rs index a49fa788fbf3..06854632f614 100644 --- a/prql-compiler/src/semantic/context.rs +++ b/prql-compiler/src/semantic/context.rs @@ -135,7 +135,16 @@ impl Context { let expr = TableExpr::RelationVar(value); DeclKind::TableDecl(TableDecl { columns, expr }) } - Some(_) => DeclKind::Expr(var_def.value), + Some(_) => { + let mut value = var_def.value; + + // TODO: check that declaring module is std + if let Some(kind) = get_stdlib_decl(name.as_str()) { + value.kind = kind; + } + + DeclKind::Expr(value) + } None => { return Err( Error::new_simple("Cannot infer type. Type annotations needed.") @@ -368,6 +377,29 @@ impl Context { } } +fn get_stdlib_decl(name: &str) -> Option { + let ty_lit = match name { + "int" => TyLit::Int, + "float" => TyLit::Float, + "bool" => TyLit::Bool, + "text" => TyLit::Text, + "date" => TyLit::Date, + "time" => TyLit::Time, + "timestamp" => TyLit::Timestamp, + "table" => { + // TODO: this is just a dummy that gets intercepted when resolving types + return Some(ExprKind::Set(SetExpr::Array(Box::new(SetExpr::Singleton( + Literal::Null, + ))))); + } + "column" => TyLit::Column, + "list" => TyLit::List, + "scalar" => TyLit::Scalar, + _ => return None, + }; + Some(ExprKind::Set(SetExpr::Primitive(ty_lit))) +} + impl Default for DeclKind { fn default() -> Self { DeclKind::Module(Module::default()) diff --git a/prql-compiler/src/semantic/lowering.rs b/prql-compiler/src/semantic/lowering.rs index 1c688ac4589a..aac2ab09f7b0 100644 --- a/prql-compiler/src/semantic/lowering.rs +++ b/prql-compiler/src/semantic/lowering.rs @@ -32,13 +32,15 @@ pub fn lower_ast_to_ir(statements: Vec, context: Context) -> Result query_def = Some(def), - pl::StmtKind::Main(expr) => { + QueryDef(def) => query_def = Some(def), + Main(expr) => { let relation = l.lower_relation(*expr)?; main_pipeline = Some(relation); } - pl::StmtKind::FuncDef(_) | pl::StmtKind::VarDef(_) => {} + FuncDef(_) | VarDef(_) | TypeDef(_) => {} } } @@ -660,6 +662,7 @@ impl Lowerer { | pl::ExprKind::List(_) | pl::ExprKind::Closure(_) | pl::ExprKind::Pipeline(_) + | pl::ExprKind::Set(_) | pl::ExprKind::TransformCall(_) => { log::debug!("cannot lower {ast:?}"); return Err(Error::new(Reason::Unexpected { diff --git a/prql-compiler/src/semantic/resolver.rs b/prql-compiler/src/semantic/resolver.rs index f15003f4e3c5..e1dd506409c8 100644 --- a/prql-compiler/src/semantic/resolver.rs +++ b/prql-compiler/src/semantic/resolver.rs @@ -16,7 +16,7 @@ use super::context::{Context, Decl, DeclKind}; use super::module::{Module, NS_FRAME, NS_FRAME_RIGHT, NS_PARAM}; use super::reporting::debug_call_tree; use super::transforms::{self, Flattener}; -use super::type_resolver::{resolve_type, type_of_closure, validate_type}; +use super::type_resolver::{self, infer_type, type_of_closure, validate_type}; /// Runs semantic analysis on the query, using current state. /// @@ -69,11 +69,20 @@ impl AstFold for Resolver { } StmtKind::VarDef(var_def) => { let var_def = self.fold_var_def(var_def)?; + self.context.declare_var(var_def, stmt.id, stmt.span)?; + continue; + } + StmtKind::TypeDef(ty_def) => { let var_def = VarDef { - value: Box::new(Flattener::fold(*var_def.value)), - ..var_def + name: ty_def.name, + value: Box::new(ty_def.value.unwrap_or_else(|| { + let mut e = Expr::null(); + e.ty = Some(Ty::SetExpr(SetExpr::Set)); + e + })), }; + let var_def = self.fold_var_def(var_def)?; self.context.declare_var(var_def, stmt.id, stmt.span)?; continue; } @@ -88,6 +97,13 @@ impl AstFold for Resolver { Ok(res) } + fn fold_var_def(&mut self, var_def: VarDef) -> Result { + Ok(VarDef { + name: var_def.name, + value: Box::new(Flattener::fold(self.fold_expr(*var_def.value)?)), + }) + } + fn fold_expr(&mut self, node: Expr) -> Result { if node.id.is_some() && !matches!(node.kind, ExprKind::Closure(_)) { return Ok(node); @@ -114,7 +130,7 @@ impl AstFold for Resolver { match &entry.kind { // convert ident to function without args DeclKind::FuncDef(func_def) => { - let closure = closure_of_func_def(func_def, fq_ident); + let closure = self.closure_of_func_def(func_def.clone(), fq_ident)?; if self.in_func_call_name { Expr::from(ExprKind::Closure(Box::new(closure))) @@ -290,7 +306,7 @@ impl AstFold for Resolver { r.span = r.span.or(span); if r.ty.is_none() { - r.ty = Some(resolve_type(&r, &self.context)?); + r.ty = Some(infer_type(&r, &self.context)?); } if let Some(Ty::Table(frame)) = &mut r.ty { if let Some(alias) = r.alias.take() { @@ -302,21 +318,6 @@ impl AstFold for Resolver { } } -fn closure_of_func_def(func_def: &FuncDef, fq_ident: Ident) -> Closure { - Closure { - name: Some(fq_ident), - body: func_def.body.clone(), - body_ty: func_def.return_ty.clone(), - - params: func_def.positional_params.clone(), - named_params: func_def.named_params.clone(), - - args: vec![], - - env: HashMap::default(), - } -} - impl Resolver { fn resolve_pipeline(&mut self, Pipeline { mut exprs }: Pipeline) -> Result { let mut value = exprs.remove(0); @@ -362,7 +363,7 @@ impl Resolver { body_ty: None, args: vec![], - params: vec![FuncParam { + params: vec![ClosureParam { name: closure_param.to_string(), default_value: None, ty: None, @@ -445,7 +446,11 @@ impl Resolver { let closure = self.resolve_function_args(closure)?; // evaluate - let needs_window = Some(Ty::column()) <= closure.body_ty; + let needs_window = (closure.body_ty) + .as_ref() + .map(|ty| ty.is_superset_of(&Ty::SetExpr(SetExpr::Primitive(TyLit::Column)))) + .unwrap_or_default(); + let mut res = match self.cast_built_in_function(closure)? { // this function call is a built-in function Ok(transform) => transform, @@ -603,12 +608,11 @@ impl Resolver { log::debug!("resolved arg to {}", arg.kind.as_ref()); // add table's frame into scope - if let Some(Ty::Table(frame)) = &arg.ty { - if is_last { - self.context.root_mod.insert_frame(frame, NS_FRAME); - } else { - self.context.root_mod.insert_frame(frame, NS_FRAME_RIGHT); - } + let frame = arg.ty.as_ref().unwrap().as_table().unwrap(); + if is_last { + self.context.root_mod.insert_frame(frame, NS_FRAME); + } else { + self.context.root_mod.insert_frame(frame, NS_FRAME_RIGHT); } closure.args[index] = arg; @@ -655,7 +659,7 @@ impl Resolver { fn fold_and_type_check( &mut self, arg: Expr, - param: &FuncParam, + param: &ClosureParam, func_name: &Option, ) -> Result { let mut arg = self.fold_within_namespace(arg, ¶m.name)?; @@ -738,6 +742,53 @@ impl Resolver { except, })) } + + fn closure_of_func_def(&mut self, func_def: FuncDef, fq_ident: Ident) -> Result { + let body_ty = self.fold_type_expr(func_def.return_ty)?; + + Ok(Closure { + name: Some(fq_ident), + body: func_def.body, + body_ty, + + params: self.fold_func_params(&func_def.positional_params)?, + named_params: self.fold_func_params(&func_def.named_params)?, + + args: vec![], + + env: HashMap::default(), + }) + } + + fn fold_func_params(&mut self, func_params: &[FuncParam]) -> Result> { + let mut params = Vec::with_capacity(func_params.len()); + for p in func_params.iter().cloned() { + params.push(ClosureParam { + name: p.name, + ty: self.fold_type_expr(p.ty_expr)?, + default_value: p.default_value, + }) + } + Ok(params) + } + + fn fold_type_expr(&mut self, expr: Option) -> Result> { + Ok(match expr { + Some(expr) => { + let expr = self.fold_expr(expr)?; + + let set_expr = type_resolver::coerce_to_set(expr, &self.context)?; + + // TODO: workaround + if let SetExpr::Array(_) = set_expr { + return Ok(Some(Ty::Table(Frame::default()))); + } + + Some(Ty::SetExpr(set_expr)) + } + None => None, + }) + } } fn env_of_closure(closure: Closure) -> (Module, Expr) { @@ -772,7 +823,7 @@ mod test { } fn resolve_type(query: &str) -> Result { - Ok(parse_and_resolve(query)?.ty.unwrap_or_default()) + Ok(parse_and_resolve(query)?.ty.unwrap_or(Ty::Infer)) } fn resolve_derive(query: &str) -> Result> { diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-2.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-2.snap index 9aaf81765509..a118b1d2ee1d 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-2.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-2.snap @@ -11,12 +11,12 @@ Table: input_name: customers except: [] inputs: - - id: 4 + - id: 6 name: table_1 table: - default_db - table_1 - - id: 8 + - id: 13 name: customers table: - default_db diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-3.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-3.snap index d6ad7c7d27bb..3063f2c406f6 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-3.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names-3.snap @@ -8,23 +8,23 @@ Table: name: - e - emp_no - expr_id: 17 + expr_id: 24 - Single: name: - e - gender - expr_id: 18 + expr_id: 25 - Single: name: - emp_salary - expr_id: 26 + expr_id: 36 inputs: - - id: 4 + - id: 6 name: e table: - default_db - employees - - id: 11 + - id: 18 name: salaries table: - default_db diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names.snap index e528472dda2c..e54c8881a653 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__frames_and_names.snap @@ -8,22 +8,22 @@ Table: name: - orders - customer_no - expr_id: 11 + expr_id: 18 - Single: name: - orders - gross - expr_id: 12 + expr_id: 19 - Single: name: - orders - tax - expr_id: 13 + expr_id: 20 - Single: name: ~ - expr_id: 14 + expr_id: 21 inputs: - - id: 4 + - id: 6 name: orders table: - default_db diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_1.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_1.snap index f31194a7aa5d..c8780eb17a9a 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_1.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_1.snap @@ -2,26 +2,27 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n func subtract a b -> a - b\n\n from employees\n derive [\n net_salary = subtract gross_salary tax\n ]\n \"#).unwrap()" --- -- id: 13 +- id: 18 Binary: left: - id: 11 + id: 16 Ident: - _frame - employees - gross_salary - target_id: 5 + target_id: 7 ty: Infer op: Sub right: - id: 12 + id: 17 Ident: - _frame - employees - tax - target_id: 5 + target_id: 7 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column alias: net_salary diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap index 7f629f209879..75477a3642f6 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_nested.snap @@ -2,55 +2,57 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n func lag_day x -> s\"lag_day_todo({x})\"\n func ret x dividend_return -> x / (lag_day x) - 1 + dividend_return\n\n from a\n derive (ret b c)\n \"#).unwrap()" --- -- id: 14 +- id: 19 Binary: left: - id: 15 + id: 20 Binary: left: - id: 16 + id: 21 Binary: left: - id: 12 + id: 17 Ident: - _frame - a - b - target_id: 6 + target_id: 8 ty: Infer op: Div right: - id: 21 + id: 26 SString: - String: lag_day_todo( - Expr: - id: 12 + id: 17 Ident: - _frame - a - b - target_id: 6 + target_id: 8 ty: Infer - String: ) ty: Infer ty: Infer op: Sub right: - id: 23 + id: 28 Literal: Integer: 1 ty: - Literal: Integer + SetExpr: + Primitive: Int ty: Infer op: Add right: - id: 13 + id: 18 Ident: - _frame - a - c - target_id: 6 + target_id: 8 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline-2.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline-2.snap index 1638ac3cfafa..ea54921c5edc 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline-2.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline-2.snap @@ -2,40 +2,43 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n func plus_one x -> x + 1\n func plus x y -> x + y\n\n from a\n derive [b = (sum foo | plus_one | plus 2)]\n \"#).unwrap()" --- -- id: 23 +- id: 31 Binary: left: - id: 17 + id: 25 Literal: Integer: 2 ty: - Literal: Integer + SetExpr: + Primitive: Int op: Add right: - id: 20 + id: 28 Binary: left: - id: 11 + id: 16 BuiltInFunction: name: std.sum args: - - id: 13 + - id: 21 Ident: - _frame - a - foo - target_id: 6 + target_id: 8 ty: Infer ty: Infer op: Add right: - id: 22 + id: 30 Literal: Integer: 1 ty: - Literal: Integer + SetExpr: + Primitive: Int ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column alias: b diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline.snap index 1ea6487bb964..335d1d89e686 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__functions_pipeline.snap @@ -2,18 +2,19 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n from a\n derive one = (foo | sum)\n \"#).unwrap()" --- -- id: 10 +- id: 15 BuiltInFunction: name: std.sum args: - - id: 9 + - id: 14 Ident: - _frame - a - foo - target_id: 4 + target_id: 6 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column alias: one diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__named_args.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__named_args.snap index d66d43bc57bc..5afd102820a2 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__named_args.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__named_args.snap @@ -2,44 +2,48 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n func add x to:1 -> x + to\n\n from foo_table\n derive [\n added = add bar to:3,\n added_default = add bar\n ]\n \"#).unwrap()" --- -- id: 13 +- id: 18 Binary: left: - id: 12 + id: 17 Ident: - _frame - foo_table - bar - target_id: 5 + target_id: 7 ty: Infer op: Add right: - id: 11 + id: 16 Literal: Integer: 3 ty: - Literal: Integer + SetExpr: + Primitive: Int ty: - Literal: Column + SetExpr: + Primitive: Column alias: added -- id: 20 +- id: 25 Binary: left: - id: 19 + id: 24 Ident: - _frame - foo_table - bar - target_id: 5 + target_id: 7 ty: Infer op: Add right: - id: 18 + id: 23 Literal: Integer: 1 ty: - Literal: Integer + SetExpr: + Primitive: Int ty: - Literal: Column + SetExpr: + Primitive: Column alias: added_default diff --git a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__variables_1.snap b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__variables_1.snap index ade0148c53ad..ea39d81c2bbc 100644 --- a/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__variables_1.snap +++ b/prql-compiler/src/semantic/snapshots/prql_compiler__semantic__resolver__test__variables_1.snap @@ -2,47 +2,49 @@ source: prql-compiler/src/semantic/resolver.rs expression: "resolve_derive(r#\"\n from employees\n derive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n ]\n \"#).unwrap()" --- -- id: 8 +- id: 13 Binary: left: - id: 9 + id: 14 Ident: - _frame - employees - salary - target_id: 4 + target_id: 6 ty: Infer op: Add right: - id: 10 + id: 15 Ident: - _frame - employees - payroll_tax - target_id: 4 + target_id: 6 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column alias: gross_salary -- id: 11 +- id: 16 Binary: left: - id: 12 + id: 17 Ident: - _frame - gross_salary - target_id: 8 + target_id: 13 ty: Infer op: Add right: - id: 13 + id: 18 Ident: - _frame - employees - benefits_cost - target_id: 4 + target_id: 6 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column alias: gross_cost diff --git a/prql-compiler/src/semantic/std.prql b/prql-compiler/src/semantic/std.prql index 51027e667c4b..2e8042ecb27b 100644 --- a/prql-compiler/src/semantic/std.prql +++ b/prql-compiler/src/semantic/std.prql @@ -1,14 +1,14 @@ # Aggregate Functions -func min column -> null -func max column -> null -func sum column -> null -func avg column -> null -func stddev column -> null -func average column -> null -func count non_null:s"*" -> null +func min column -> null +func max column -> null +func sum column -> null +func avg column -> null +func stddev column -> null +func average column -> null +func count non_null:s"*" -> null # TODO: Possibly make this into `count distinct:true` (or like `distinct:` as an # abbreviation of that?) -func count_distinct column -> null +func count_distinct column -> null # Window functions func lag offset column -> null @@ -58,8 +58,21 @@ func _eq a -> null func _is_null a -> _param.a == null # Misc -func from_text
text `noresolve.format`:csv -> null +func from_text
input `noresolve.format`:csv -> null # String functions -func lower column -> null -func upper column -> null +func lower column -> null +func upper column -> null + +# type primitives +type int +type float +type bool +type text +type date +type time +type timestamp +type table +type column +type list +type scalar diff --git a/prql-compiler/src/semantic/transforms.rs b/prql-compiler/src/semantic/transforms.rs index 661ddc1de351..f400456636ac 100644 --- a/prql-compiler/src/semantic/transforms.rs +++ b/prql-compiler/src/semantic/transforms.rs @@ -469,7 +469,7 @@ fn fold_by_simulating_eval( body_ty: None, args: vec![], - params: vec![FuncParam { + params: vec![ClosureParam { name: param_id.to_string(), ty: None, default_value: None, @@ -1078,7 +1078,7 @@ mod tests { let query = parse( " from c_invoice - group date (aggregate average amount) + group issued_at (aggregate average amount) ", ) .unwrap(); @@ -1089,7 +1089,7 @@ mod tests { let query = parse( " from c_invoice - group date ( + group issued_at ( aggregate (average amount) ) ", @@ -1099,10 +1099,10 @@ mod tests { assert_yaml_snapshot!(result, @r###" --- - Main: - id: 18 + id: 28 TransformCall: input: - id: 4 + id: 6 Ident: - default_db - c_invoice @@ -1113,7 +1113,7 @@ mod tests { input_name: c_invoice except: [] inputs: - - id: 4 + - id: 6 name: c_invoice table: - default_db @@ -1121,26 +1121,27 @@ mod tests { kind: Aggregate: assigns: - - id: 15 + - id: 22 BuiltInFunction: name: std.average args: - - id: 17 + - id: 27 Ident: - _frame - c_invoice - amount - target_id: 4 + target_id: 6 ty: Infer ty: - Literal: Column + SetExpr: + Primitive: Column partition: - - id: 8 + - id: 12 Ident: - _frame - c_invoice - - date - target_id: 4 + - issued_at + target_id: 6 ty: Infer ty: Table: @@ -1148,13 +1149,13 @@ mod tests { - Single: name: - c_invoice - - date - expr_id: 8 + - issued_at + expr_id: 12 - Single: name: ~ - expr_id: 15 + expr_id: 22 inputs: - - id: 4 + - id: 6 name: c_invoice table: - default_db diff --git a/prql-compiler/src/semantic/type_resolver.rs b/prql-compiler/src/semantic/type_resolver.rs index e8c45fa0e0a3..229faacfb131 100644 --- a/prql-compiler/src/semantic/type_resolver.rs +++ b/prql-compiler/src/semantic/type_resolver.rs @@ -1,4 +1,3 @@ -use std::cmp::Ordering; use std::collections::HashSet; use anyhow::Result; @@ -8,7 +7,75 @@ use crate::error::{Error, Reason, WithErrorInfo}; use super::Context; -pub fn resolve_type(node: &Expr, context: &Context) -> Result { +/// Takes a resolved [Expr] and evaluates it a set expression that can be used to construct a type. +pub fn coerce_to_set(expr: Expr, context: &Context) -> Result { + coerce_to_named_set(expr, context).map(|(_, s)| s) +} + +fn coerce_to_named_set(expr: Expr, context: &Context) -> Result<(Option, SetExpr), Error> { + let name = expr.alias; + let expr = coerce_kind_to_set(expr.kind, context).map_err(|e| e.with_span(expr.span))?; + + Ok((name, expr)) +} + +fn coerce_kind_to_set(expr: ExprKind, context: &Context) -> Result { + // primitives + if let ExprKind::Set(set_expr) = expr { + return Ok(set_expr); + } + + // singletons + if let ExprKind::Literal(lit) = expr { + return Ok(SetExpr::Singleton(lit)); + } + + // tuples + if let ExprKind::List(elements) = expr { + let mut set_elements = Vec::with_capacity(elements.len()); + + for e in elements { + let (name, set) = coerce_to_named_set(e, context)?; + + set_elements.push(TupleElement::Single(name, set)); + } + + return Ok(SetExpr::Tuple(set_elements)); + } + + // unions + if let ExprKind::Binary { + left, + op: BinOp::Or, + right, + } = expr + { + let left = coerce_to_named_set(*left, context)?; + let right = coerce_to_named_set(*right, context)?; + + // flatten nested unions + let mut options = Vec::with_capacity(2); + if let SetExpr::Union(parts) = left.1 { + options.extend(parts); + } else { + options.push(left); + } + if let SetExpr::Union(parts) = right.1 { + options.extend(parts); + } else { + options.push(right); + } + + return Ok(SetExpr::Union(options)); + } + + Err(Error::new_simple(format!( + "not a set expression: {}", + Expr::from(expr) + ))) +} + +pub fn infer_type(node: &Expr, context: &Context) -> Result { if let Some(ty) = &node.ty { return Ok(ty.clone()); } @@ -16,13 +83,13 @@ pub fn resolve_type(node: &Expr, context: &Context) -> Result { Ok(match &node.kind { ExprKind::Literal(ref literal) => match literal { Literal::Null => Ty::Infer, - Literal::Integer(_) => TyLit::Integer.into(), - Literal::Float(_) => TyLit::Float.into(), - Literal::Boolean(_) => TyLit::Bool.into(), - Literal::String(_) => TyLit::String.into(), - Literal::Date(_) => TyLit::Date.into(), - Literal::Time(_) => TyLit::Time.into(), - Literal::Timestamp(_) => TyLit::Timestamp.into(), + Literal::Integer(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Int)), + Literal::Float(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Float)), + Literal::Boolean(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Bool)), + Literal::String(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Text)), + Literal::Date(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Date)), + Literal::Time(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Time)), + Literal::Timestamp(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Timestamp)), Literal::ValueAndUnit(_) => Ty::Infer, // TODO Literal::Relation(_) => unreachable!(), }, @@ -30,11 +97,11 @@ pub fn resolve_type(node: &Expr, context: &Context) -> Result { ExprKind::Ident(_) | ExprKind::Pipeline(_) | ExprKind::FuncCall(_) => Ty::Infer, ExprKind::SString(_) => Ty::Infer, - ExprKind::FString(_) => TyLit::String.into(), + ExprKind::FString(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::Text)), ExprKind::Range(_) => Ty::Infer, // TODO ExprKind::TransformCall(call) => Ty::Table(call.infer_type(context)?), - ExprKind::List(_) => Ty::Literal(TyLit::List), + ExprKind::List(_) => Ty::SetExpr(SetExpr::Primitive(TyLit::List)), _ => Ty::Infer, }) @@ -94,10 +161,7 @@ where }); } - let expected_is_above = matches!( - expected.partial_cmp(&found_ty), - Some(Ordering::Equal | Ordering::Greater) - ); + let expected_is_above = expected.is_superset_of(&found_ty); if !expected_is_above { let e = Err(Error::new(Reason::Expected { who: who(), diff --git a/prql-compiler/src/sql/std_impl.prql b/prql-compiler/src/sql/std_impl.prql index 0545e05ebef4..1d781067d0ff 100644 --- a/prql-compiler/src/sql/std_impl.prql +++ b/prql-compiler/src/sql/std_impl.prql @@ -1,13 +1,13 @@ -func min column -> s"MIN({column})" -func max column -> s"MAX({column})" -func sum column -> s"SUM({column})" -func avg column -> s"AVG({column})" -func stddev column -> s"STDDEV({column})" -func average column -> s"AVG({column})" -func count non_null:s"*" -> s"COUNT({non_null})" +func min column -> s"MIN({column})" +func max column -> s"MAX({column})" +func sum column -> s"SUM({column})" +func avg column -> s"AVG({column})" +func stddev column -> s"STDDEV({column})" +func average column -> s"AVG({column})" +func count non_null:s"*" -> s"COUNT({non_null})" # TODO: Possibly make this into `count distinct:true` (or like `distinct:` as an # abbreviation of that?) -func count_distinct column -> s"COUNT(DISTINCT {column})" +func count_distinct column -> s"COUNT(DISTINCT {column})" # Window functions func lag offset column -> s"LAG({column}, {offset})" @@ -23,5 +23,5 @@ func round n_digits column -> s"ROUND({column}, {n_digits})" func as `noresolve.type` column -> s"CAST({column} AS {type})" # String functions -func lower column -> s"LOWER({column})" -func upper column -> s"UPPER({column})" +func lower column -> s"LOWER({column})" +func upper column -> s"UPPER({column})" diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 62022adb1eb1..7993544a68bc 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -2232,7 +2232,7 @@ fn test_double_aggregate() { let query = r###" from numbers - group [type] ( + group [`type`] ( aggregate [ total_amt = sum amount, max amount @@ -2308,7 +2308,7 @@ fn test_inline_tables() { assert_display_snapshot!(compile(r###" ( from employees - select [emp_id, name, surname, type, amount] + select [emp_id, name, surname, `type`, amount] ) join s = (from salaries | select [emp_id, salary]) [==emp_id] "###).unwrap(), From 9d0e6fdc37c3075c6623f0b21d8f1e4ce79ae15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alja=C5=BE=20Mur=20Er=C5=BEen?= Date: Thu, 9 Mar 2023 13:50:41 +0100 Subject: [PATCH 131/184] build: disable dotnet tests in test-all (#2068) --- .github/workflows/test-all.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 69658da969e6..18c85e4a3a9c 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -48,8 +48,8 @@ jobs: test-elixir: uses: ./.github/workflows/test-elixir.yaml - test-dotnet: - uses: ./.github/workflows/test-dotnet.yaml + # test-dotnet: + # uses: ./.github/workflows/test-dotnet.yaml test-lib: uses: ./.github/workflows/test-lib.yaml From c23a2579140af437bf3c3dd97b2c99fec03897f2 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 17:25:04 -0800 Subject: [PATCH 132/184] chore: Rename snap secret name (#2072) Addresses some of #2065 --- .github/workflows/release.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index add1048a8405..d473626ed494 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -91,7 +91,8 @@ jobs: - name: ๐Ÿ†™ Publish Snap uses: snapcore/action-publish@v1 env: - SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.STORE_LOGIN }} + SNAPCRAFT_STORE_CREDENTIALS: + ${{ secrets.SNAPCRAFT_STORE_CREDENTIALS }} with: snap: ${{ steps.build.outputs.snap }} release: edge From 58a6fb66144a5ec378a9b56478fa2ba527abbf7f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:10:07 -0800 Subject: [PATCH 133/184] docs: Lengthen expected workflow time (#2074) docs: Lenthen expected workflow time Unfortunately as the repo has grown, it takes longer now. GHA cache also seems much slower to pull now; that takes a full minute. --- book/src/contributing/development.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/contributing/development.md b/book/src/contributing/development.md index b005e1b64dfe..360d3e73be8d 100644 --- a/book/src/contributing/development.md +++ b/book/src/contributing/development.md @@ -345,7 +345,7 @@ inconsistent in watchexec. Let's revert back if it gets solved. - **[GitHub Actions on every commit](https://github.com/PRQL/prql/blob/main/.github/workflows/pull-request.yaml)** โ€” we run the tests described up to this point on every commit to a pull - request. These are designed to run in under two minutes, and we should be + request. These are designed to run in under five minutes, and we should be reassessing their scope if they grow beyond that. Once these pass, a pull request can be merged. From d07839dde8df12be3c9bd2be9b54d394a2a21dea Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 21:10:19 -0800 Subject: [PATCH 134/184] ci: Add color to CI cargo output (#2073) * chore: Rename snap secret name Addresses some of #2065 * ci: Add color to CI cargo output --- .github/workflows/test-rust.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index 0ac9ed479b11..5fc6b9e0d7eb 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -9,6 +9,9 @@ on: target_option: type: string +env: + CARGO_TERM_COLOR: always + jobs: test: runs-on: ${{ inputs.os }} From b181c9deaeed65d87b3611f2d722c6bbd65dc5c3 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:16:08 -0800 Subject: [PATCH 135/184] ci: Fix GHPages deploment (#2075) Not sure what changed, but it wasn't working. This more closely replicates the example GH pages example workflow. It works on `web` branch. --- .github/workflows/publish-web.yaml | 37 +++++++++++++++++++----------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index ba17deef1ae5..8a5c94e964f0 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -6,23 +6,23 @@ on: # Called by pull-request when specifically requested workflow_call: +# Grant GITHUB_TOKEN the permissions required to make a Pages deployment +permissions: + pages: write + id-token: write + jobs: - publish-web: + build-web: runs-on: ubuntu-latest # Skip running workflow on forks if: github.repository_owner == 'prql' - # Grant GITHUB_TOKEN the permissions required to make a Pages deployment - permissions: - pages: write - id-token: write - - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - steps: + - name: Setup Pages + id: pages + uses: actions/configure-pages@v1 + - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 @@ -50,17 +50,26 @@ jobs: - uses: arduino/setup-task@v1 with: repo-token: "${{ secrets.GITHUB_TOKEN }}" + - name: ๐Ÿ•ท๏ธ Build website run: task build-web - - name: Prepare tar for upload - uses: actions/upload-pages-artifact@v1.0.7 + - uses: actions/upload-pages-artifact@v1.0.7 with: path: website/public/ + deploy-web: + needs: build-web + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + steps: - name: Deploy to GitHub Pages - # Even if called by another workflow, don't try and actually publish if - # on a fork (it'll fail the workflow even if it otherwise builds successfully) + # TDOO: is this repetitive for the `if: github.repository_owner == 'prql'` check above? + # # Even if called by another workflow, don't try and actually publish if + # # on a fork (it'll fail the workflow even if it otherwise builds successfully) if: "!github.event.pull_request.head.repo.fork" id: deployment uses: actions/deploy-pages@v1.2.4 From f0fb6e892cf25760ee07ef0a49c42600e2aa9455 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 22:24:40 -0800 Subject: [PATCH 136/184] ci: Adjust logic to skip publish on forks (#2076) --- .github/workflows/publish-web.yaml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index 8a5c94e964f0..0fac00860f8b 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -15,8 +15,11 @@ jobs: build-web: runs-on: ubuntu-latest - # Skip running workflow on forks - if: github.repository_owner == 'prql' + # Commenting out as I think it's duplicative with the check below; TODO: + # delete assuming everything works OK. + # + # # Skip running workflow on forks + # if: github.repository_owner == 'prql' steps: - name: Setup Pages @@ -65,11 +68,11 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} + # Don't attempt to publish if on a fork (it'll fail the workflow even if it + # otherwise builds successfully) + if: "!github.event.pull_request.head.repo.fork" + steps: - name: Deploy to GitHub Pages - # TDOO: is this repetitive for the `if: github.repository_owner == 'prql'` check above? - # # Even if called by another workflow, don't try and actually publish if - # # on a fork (it'll fail the workflow even if it otherwise builds successfully) - if: "!github.event.pull_request.head.repo.fork" id: deployment uses: actions/deploy-pages@v1.2.4 From 34042cd7c7d7ef78ffcc69bacdf90786e832f0af Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Thu, 9 Mar 2023 23:26:09 -0800 Subject: [PATCH 137/184] ci: Adjust logic to skip publish on forks v2 (#2077) * ci: Adjust logic to skip publish on forks v2 --- .github/workflows/publish-web.yaml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index 0fac00860f8b..e32274ffb244 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -15,11 +15,9 @@ jobs: build-web: runs-on: ubuntu-latest - # Commenting out as I think it's duplicative with the check below; TODO: - # delete assuming everything works OK. - # - # # Skip running workflow on forks - # if: github.repository_owner == 'prql' + # Skip running workflow on forks. This still runs on PRs, but then below we + # disable it from attempting to publish. + if: github.repository_owner == 'prql' steps: - name: Setup Pages @@ -68,8 +66,7 @@ jobs: name: github-pages url: ${{ steps.deployment.outputs.page_url }} - # Don't attempt to publish if on a fork (it'll fail the workflow even if it - # otherwise builds successfully) + # Don't attempt to publish if on a fork, including a PR. if: "!github.event.pull_request.head.repo.fork" steps: From 016575dbd56d1293879712ba65e5f64c09e8b678 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 00:52:20 -0800 Subject: [PATCH 138/184] docs: Add a new policy for bindings support (#2062) * docs: Add a new policy for bindings support * . --- book/src/bindings/README.md | 40 ++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/book/src/bindings/README.md b/book/src/bindings/README.md index 216ac63f40aa..e2125ccc2db3 100644 --- a/book/src/bindings/README.md +++ b/book/src/bindings/README.md @@ -2,11 +2,45 @@ PRQL has bindings for many languages. These include: -- [Java](./java.md) +We have three tiers of bindings: + +- Supported +- Unsupported +- Nascent + +## Supported + +Supported bindings require: + +- A maintainer. +- Implementations of the + [core compile functions](https://docs.rs/prql-compiler/latest/prql_compiler/#functions). +- Test coverage for these functions. +- A published package to the language's standard package repository. +- A script in `Taskfile.yml` to bootstrap a development environment. +- Any dev tools, such as a linter & formatter, in pre-commit or MegaLinter. + - [JavaScript](./javascript.md) -- [.NET](./net.md) -- [PHP](./php.md) - [Python](./python.md) - [R](./r.md) - [Rust](./rust.md) + +Most of these are in the main PRQL repo, and we gate any changes to the +compiler's API on compatible changes to the bindings. + +## Unsupported + +Unsupported bindings work, but don't fulfil all of the above criteria. We don't +gate changes to the compiler's API. If they stop working, we'll demote them to +nascent. + +- [Java](./java.md) - [Elixir](./elixir.md) +- `prql-lib`, the C bindings + +## Nascent + +Nascent bindings are in development, and may not yet fully work. + +- [.NET](./net.md) +- [PHP](./php.md) From f01d857585d2625f1f92959777957a1309a7aad4 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 01:37:36 -0800 Subject: [PATCH 139/184] internal: Derive `Debug` for `Context` (#2080) --- prql-compiler/src/sql/context.rs | 2 +- prql-compiler/src/sql/dialect.rs | 12 ++++++++++-- prql-compiler/src/sql/mod.rs | 3 ++- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/prql-compiler/src/sql/context.rs b/prql-compiler/src/sql/context.rs index b9b38e1ae2bf..9c58e3cd156e 100644 --- a/prql-compiler/src/sql/context.rs +++ b/prql-compiler/src/sql/context.rs @@ -17,7 +17,7 @@ use crate::utils::{IdGenerator, NameGenerator}; use super::preprocess::{SqlRelation, SqlTransform}; -#[derive(Default)] +#[derive(Default, Debug)] pub struct AnchorContext { pub(super) column_decls: HashMap, pub(super) column_names: HashMap, diff --git a/prql-compiler/src/sql/dialect.rs b/prql-compiler/src/sql/dialect.rs index 64bbeb08e766..71903dcbb6b8 100644 --- a/prql-compiler/src/sql/dialect.rs +++ b/prql-compiler/src/sql/dialect.rs @@ -94,15 +94,23 @@ impl Default for Dialect { } } +#[derive(Debug)] pub struct GenericDialect; +#[derive(Debug)] pub struct SQLiteDialect; +#[derive(Debug)] pub struct MySqlDialect; +#[derive(Debug)] pub struct MsSqlDialect; +#[derive(Debug)] pub struct BigQueryDialect; +#[derive(Debug)] pub struct ClickHouseDialect; - +#[derive(Debug)] pub struct SnowflakeDialect; +#[derive(Debug)] pub struct DuckDbDialect; +#[derive(Debug)] pub struct PostgresDialect; pub(super) enum ColumnExclude { @@ -110,7 +118,7 @@ pub(super) enum ColumnExclude { Except, } -pub(super) trait DialectHandler: Any { +pub(super) trait DialectHandler: Any + Debug { fn use_top(&self) -> bool { false } diff --git a/prql-compiler/src/sql/mod.rs b/prql-compiler/src/sql/mod.rs index 64f6cd53de3a..231a27e26b73 100644 --- a/prql-compiler/src/sql/mod.rs +++ b/prql-compiler/src/sql/mod.rs @@ -56,6 +56,7 @@ pub fn compile(query: Query, options: &Options) -> Result { Ok(sql) } +#[derive(Debug)] struct Context { pub dialect: Box, pub anchor: AnchorContext, @@ -69,7 +70,7 @@ struct Context { pub ctes: Vec, } -#[derive(Clone)] +#[derive(Clone, Debug)] struct QueryOpts { /// When true, column references will not include table names prefixes. pub omit_ident_prefix: bool, From 325af820bbb56adb4d892da08f6680fd177aaab2 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 09:40:13 -0800 Subject: [PATCH 140/184] chore: Add lang to loop pseudocode (#2083) * internal: Derive `Debug` for `Context` * chore: Add lang to loop pseudocode --- book/src/language-features/standard-library/loop.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/language-features/standard-library/loop.md b/book/src/language-features/standard-library/loop.md index 97f462a8b5cc..061ec312a932 100644 --- a/book/src/language-features/standard-library/loop.md +++ b/book/src/language-features/standard-library/loop.md @@ -12,7 +12,7 @@ relation and all intermediate relations. This behavior could be expressed with following pseudo-code: -``` +```python def loop(step, initial): result = [] current = initial From b6866cc156a94db40fcdc07b7d9e6ab496e27e1a Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 09:43:55 -0800 Subject: [PATCH 141/184] build: Bump rust version delta to 3 (#2084) * internal: Derive `Debug` for `Context` * build: Bump rust version delta to 3 I think this should be the final change (but we can do a couple more if needed fer debian etc) --- .github/workflows/nightly.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index a08c5f23f99c..386bcf5b4ad1 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -54,8 +54,7 @@ jobs: - uses: a-kenji/update-rust-toolchain@main with: # Discussion in #1561 - # Move this up until 3, so the next upgrade is at 1.66 once 1.69 is released. - minor-version-delta: 2 + minor-version-delta: 3 toolchain-path: "./rust-toolchain.toml" pr-title: "build: Update rust toolchain version" From 48cbda3da1621ca8b29eecbcace2cf9ccd72e959 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 10:15:08 -0800 Subject: [PATCH 142/184] chore: bump actions/configure-pages from 1 to 3 (#2087) Bumps [actions/configure-pages](https://github.com/actions/configure-pages) from 1 to 3. - [Release notes](https://github.com/actions/configure-pages/releases) - [Commits](https://github.com/actions/configure-pages/compare/v1...v3) --- updated-dependencies: - dependency-name: actions/configure-pages dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-web.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index e32274ffb244..455695be2820 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -22,7 +22,7 @@ jobs: steps: - name: Setup Pages id: pages - uses: actions/configure-pages@v1 + uses: actions/configure-pages@v3 - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 From 6e1646cfa30b014bd73cfab17b12892ed06cb410 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 10:17:52 -0800 Subject: [PATCH 143/184] chore: bump web-vitals from 3.1.0 to 3.3.0 in /playground (#2086) Bumps [web-vitals](https://github.com/GoogleChrome/web-vitals) from 3.1.0 to 3.3.0. - [Release notes](https://github.com/GoogleChrome/web-vitals/releases) - [Changelog](https://github.com/GoogleChrome/web-vitals/blob/main/CHANGELOG.md) - [Commits](https://github.com/GoogleChrome/web-vitals/compare/v3.1.0...v3.3.0) --- updated-dependencies: - dependency-name: web-vitals dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- playground/package-lock.json | 14 +++++++------- playground/package.json | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/playground/package-lock.json b/playground/package-lock.json index 365eef31083a..96cd41b6b656 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -20,7 +20,7 @@ "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", "wasm-react-scripts": "5.0.3", - "web-vitals": "^3.1.0", + "web-vitals": "^3.3.0", "yaml": "^2.2.1" }, "devDependencies": { @@ -17050,9 +17050,9 @@ } }, "node_modules/web-vitals": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.1.0.tgz", - "integrity": "sha512-zCeQ+bOjWjJbXv5ZL0r8Py3XP2doCQMZXNKlBGfUjPAVZWokApdeF/kFlK1peuKlCt8sL9TFkKzyXE9/cmNJQA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.0.tgz", + "integrity": "sha512-GZsEmJBNclIpViS/7QVOTr7Kbt4BgLeR7kQ5zCCtJVuiWsA+K6xTXaoEXssvl8yYFICEyNmA2Nr+vgBYTnS4bA==" }, "node_modules/webidl-conversions": { "version": "6.1.0", @@ -30223,9 +30223,9 @@ } }, "web-vitals": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.1.0.tgz", - "integrity": "sha512-zCeQ+bOjWjJbXv5ZL0r8Py3XP2doCQMZXNKlBGfUjPAVZWokApdeF/kFlK1peuKlCt8sL9TFkKzyXE9/cmNJQA==" + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/web-vitals/-/web-vitals-3.3.0.tgz", + "integrity": "sha512-GZsEmJBNclIpViS/7QVOTr7Kbt4BgLeR7kQ5zCCtJVuiWsA+K6xTXaoEXssvl8yYFICEyNmA2Nr+vgBYTnS4bA==" }, "webidl-conversions": { "version": "6.1.0", diff --git a/playground/package.json b/playground/package.json index 379af98d2616..eef71f294594 100644 --- a/playground/package.json +++ b/playground/package.json @@ -23,7 +23,7 @@ "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", "wasm-react-scripts": "5.0.3", - "web-vitals": "^3.1.0", + "web-vitals": "^3.3.0", "yaml": "^2.2.1" }, "devDependencies": { From c985d735f493053072d57e7f39547b315b29e8e1 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 11:41:29 -0800 Subject: [PATCH 144/184] refactor: Unify duplicated logic in book tests (#2090) It's not some super elegant abstraction, but pulls the complicated match into a function --- book/src/lib.rs | 102 ++++++++++++++++++++++------------------- book/tests/snapshot.rs | 15 +++--- 2 files changed, 63 insertions(+), 54 deletions(-) diff --git a/book/src/lib.rs b/book/src/lib.rs index dc85ee7aa710..4197a12530c5 100644 --- a/book/src/lib.rs +++ b/book/src/lib.rs @@ -96,58 +96,68 @@ impl Preprocessor for ComparisonPreprocessor { } } +pub fn code_block_lang<'a>(event: &'a Event) -> Option<&'a str> { + if let Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) = event { + Some(lang.as_ref()) + } else { + None + } +} + fn replace_examples(text: &str) -> Result { let mut parser = Parser::new_ext(text, Options::all()); let mut cmark_acc = vec![]; while let Some(event) = parser.next() { - match event.clone() { - // Duplicative repetitive logic here and in - // [snapshot.rs/collect_book_examples]; could we unify? - Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) - if lang.starts_with("prql") => - { - let Some(Event::Text(text)) = parser.next() - else { - bail!("Expected text after PRQL code block") - }; - let prql = text.to_string(); - let options = prql_compiler::Options::default().no_signature(); - let result = &compile(&prql, &options); - match lang.to_string().as_str() { - "prql" | "prql_no_fmt" => cmark_acc.push(Event::Html( - table_of_comparison( - &prql, - result - .clone() - .unwrap_or_else(|_| { - panic!("{}", format!("Query raised an error: {prql}")) - }) - .as_str(), - ) - .into(), - )), - "prql_error" => cmark_acc.push(Event::Html( - table_of_error( - &prql, - result - .clone() - .expect_err( - &format!("Query was labeled to raise an error, but succeeded.\n {prql}").to_string(), + if let Some(lang) = code_block_lang(&event) { + let Some(Event::Text(text)) = parser.next() + else { + bail!("Expected text within code block") + }; + let prql = text.to_string(); + let options = prql_compiler::Options::default().no_signature(); + let result = compile(&prql, &options); + + match lang { + "prql" | "prql_no_fmt" => cmark_acc.push(Event::Html( + table_of_comparison( + &prql, + result + .unwrap_or_else(|_| { + panic!("{}", format!("Query raised an error:\n\n {prql}\n\n")) + }) + .as_str(), + ) + .into(), + )), + "prql_error" => cmark_acc.push(Event::Html( + table_of_error( + &prql, + result + .expect_err( + &format!( + "Query was labeled to raise an error, but succeeded.\n {prql}\n\n" ) - .to_string() - .as_str(), - ) - .into(), - )), - "prql_no_test" => {} - _ => bail!("Unknown code block language: {}", lang), - }; - - // Skip ending tag - parser.next(); - } - _ => cmark_acc.push(event.to_owned()), + .to_string(), + ) + .to_string() + .as_str(), + ) + .into(), + )), + "prql_no_test" => {} + _ => { + if lang.starts_with("prql") { + bail!("Unknown code block language: {}", lang) + } else { + cmark_acc.push(event.to_owned()) + } + } + }; + // Skip ending tag + parser.next(); + } else { + cmark_acc.push(event.to_owned()) } } let mut buf = String::new(); diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 86c4f9346762..956012669ef0 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -22,6 +22,7 @@ use globset::Glob; use insta::{assert_snapshot, glob}; use itertools::Itertools; use log::warn; +use mdbook_prql::code_block_lang; use prql_compiler::*; use std::path::{Path, PathBuf}; use std::{collections::HashMap, fs}; @@ -52,7 +53,7 @@ const ROOT_EXAMPLES_PATH: &str = "tests/prql"; /// Collect all the PRQL examples in the book, as a map of . #[cfg(not(target_family = "windows"))] fn collect_book_examples() -> Result> { - use pulldown_cmark::{CodeBlockKind, Event, Parser, Tag}; + use pulldown_cmark::{Event, Parser}; let glob = Glob::new("**/*.md")?.compile_matcher(); let examples_in_book: HashMap = WalkDir::new(Path::new("./src/")) .into_iter() @@ -69,22 +70,20 @@ fn collect_book_examples() -> Result> { let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; while let Some(event) = parser.next() { - match event.clone() { + match code_block_lang(&event) { // At the start of a PRQL code block, push the _next_ item. // Note that on windows, we only get the next _line_, and so // this is disabled on windows. // https://github.com/PRQL/prql/issues/356 - Event::Start(Tag::CodeBlock(CodeBlockKind::Fenced(lang))) - if lang.starts_with("prql") => - { + Some(lang) if lang.starts_with("prql") => { let Some(Event::Text(text)) = parser.next() else { bail!("Expected text after PRQL code block") }; - if lang == "prql".into() { + if lang == "prql" { prql_blocks.push(text.to_string()); - } else if lang == "prql_error".into() { + } else if lang == "prql_error" { prql_blocks.push(format!("# Error expected\n\n{text}")); - } else if lang == "prql_no_fmt".into() { + } else if lang == "prql_no_fmt" { prql_blocks.push(format!("# Can't yet format & compile\n\n{text}")); } } From 9e97826136022e285e1fe305c7281fd9950a944f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 11:42:44 -0800 Subject: [PATCH 145/184] devops: Broaden bacon watches (#2091) * devops: Broaden bacon watches * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- bacon.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bacon.toml b/bacon.toml index 5361e3781741..8b65fac4e6d6 100644 --- a/bacon.toml +++ b/bacon.toml @@ -5,14 +5,18 @@ default_job = "check" # PRQL additions [jobs.test-fast] command = ['cargo', 'insta', 'test', '--accept', "--color=always", "-p=prql-compiler", "--lib"] +watch = ["tests", "benches", "examples"] + [jobs.test] command = ['cargo', 'insta', 'test', '--accept', "--color=always", "--unreferenced=auto"] +watch = ["tests", "benches", "examples"] # Standard tasks [jobs.check] command = ["cargo", "check", "--color", "always"] need_stdout = false +watch = ["tests", "benches", "examples"] [jobs.check-all] command = ["cargo", "check", "--all-targets", "--color", "always"] From ad6e1413504c6a2063aea3c288b230c4a1329edc Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 12:22:13 -0800 Subject: [PATCH 146/184] ci: Don't run `cargo audit` on PRs (#2092) Details inline --- .github/workflows/nightly.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 386bcf5b4ad1..63c883cea5d3 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -12,6 +12,10 @@ on: jobs: cargo-audit: runs-on: ubuntu-latest + # We can't read PRQL repo security events on forks, which causes this to + # incorrectly fail. So we disable. If we wanted to run checks on PRs, we + # could move this to `pull-request-target`. + if: "!github.event.pull_request.head.repo.fork" permissions: actions: read contents: read From 9882089509bdb271614de7d381e8a38205053b9c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 10 Mar 2023 20:33:22 +0000 Subject: [PATCH 147/184] chore: bump actions/deploy-pages from 1.2.4 to 1.2.5 (#2088) Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 1.2.4 to 1.2.5. - [Release notes](https://github.com/actions/deploy-pages/releases) - [Commits](https://github.com/actions/deploy-pages/compare/v1.2.4...v1.2.5) --- updated-dependencies: - dependency-name: actions/deploy-pages dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/publish-web.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index 455695be2820..e4cb273bdaba 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -72,4 +72,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v1.2.4 + uses: actions/deploy-pages@v1.2.5 From 25aa804e91d61a340e5b376dfbb88707a90d710c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 15:41:56 -0800 Subject: [PATCH 148/184] devops: Add a GitHub issue template for bug reports (#2094) * devops: Add a GitHub issue template for bug reports * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * . * . --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/bug_report.yaml | 62 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yaml | 1 + .github/ISSUE_TEMPLATE/feature_request.yaml | 8 +++ 3 files changed, 71 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yaml create mode 100644 .github/ISSUE_TEMPLATE/config.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yaml diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml new file mode 100644 index 000000000000..08196cce0f0d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -0,0 +1,62 @@ +name: ๐Ÿ› Bug report +description: File a bug report to help us improve +labels: [bug] +body: + - type: textarea + id: what-happened + attributes: + label: What happened? + description: | + Thanks for reporting a bug! Feel free to add any initial context here. + + - type: textarea + id: prql-input + attributes: + label: PRQL input + description: | + A minimal, self-contained example that demonstrates the issue. + + This will be automatically formatted into code, so no need for markdown backticks. + render: elm + validations: + required: true + + - type: textarea + id: output + attributes: + label: SQL output + description: | + The SQL that PRQL currently compiles to. Feel free to use the [playground](https://prql-lang.org/playground/) to generate the SQL. + + This will be automatically formatted into code, so no need for markdown backticks. + render: SQL + validations: + required: true + + - type: textarea + id: expected-output + attributes: + label: Expected SQL output + + description: + Optional; no need to write out if it's obvious from the context + render: SQL + + - type: checkboxes + id: mvce-checkboxes + attributes: + label: MVCE confirmation + description: | + Please confirm that the bug report is minimal and doesn't exist already: + + - **Minimal example** โ€” the example is as focused as reasonably possible to demonstrate the underlying issue in PRQL. For example, it's not possible to exclude any line and still observe the bug. + + - **New issue** โ€” a search of GitHub Issues suggests this is not a duplicate. + options: + - label: Minimal example + - label: New issue + + - type: textarea + id: extra + attributes: + label: Anything else? diff --git a/.github/ISSUE_TEMPLATE/config.yaml b/.github/ISSUE_TEMPLATE/config.yaml new file mode 100644 index 000000000000..0086358db1eb --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yaml @@ -0,0 +1 @@ +blank_issues_enabled: true diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml new file mode 100644 index 000000000000..9cb8dbd82079 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -0,0 +1,8 @@ +name: Something else +description: Anything that's not a bug report +labels: [bug] +body: + - type: textarea + id: what-happened + attributes: + label: What's up? From 9157c04ee8c659cc00d5c8da37d6d70d91c406eb Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 15:58:38 -0800 Subject: [PATCH 149/184] chore: Fix clippy windows issue (#2095) --- book/tests/snapshot.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index 956012669ef0..c5cc989b02a6 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -22,7 +22,6 @@ use globset::Glob; use insta::{assert_snapshot, glob}; use itertools::Itertools; use log::warn; -use mdbook_prql::code_block_lang; use prql_compiler::*; use std::path::{Path, PathBuf}; use std::{collections::HashMap, fs}; @@ -70,7 +69,7 @@ fn collect_book_examples() -> Result> { let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; while let Some(event) = parser.next() { - match code_block_lang(&event) { + match mdbook_prql::code_block_lang(&event) { // At the start of a PRQL code block, push the _next_ item. // Note that on windows, we only get the next _line_, and so // this is disabled on windows. From eebaae18e9394447afe65306e7fc51238c96f4e7 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:01:30 -0800 Subject: [PATCH 150/184] ci: Don't run toolchain update on forks (#2098) --- .github/workflows/nightly.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/nightly.yaml b/.github/workflows/nightly.yaml index 63c883cea5d3..47b83bb8f061 100644 --- a/.github/workflows/nightly.yaml +++ b/.github/workflows/nightly.yaml @@ -52,6 +52,8 @@ jobs: update-rust-toolchain: runs-on: ubuntu-latest + # Don't run on forks; will attempt to create a PR into the fork... + if: "!github.event.pull_request.head.repo.fork" steps: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 From 5bd9a1472589f083361e673d868993e43112cc15 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 16:01:57 -0800 Subject: [PATCH 151/184] chore: Update comments in book tests (#2097) --- book/tests/snapshot.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index c5cc989b02a6..d12910afd363 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -34,12 +34,14 @@ use walkdir::WalkDir; /// - Compiles them to SQL, comparing to a snapshot. Insta raises an error if /// there's a diff. /// -/// Then, when the book is built, the PRQL code block in the book is replaced -/// with a comparison table. +/// This mirrors the process in [replace_examples], which inserts a +/// comparison table of SQL into the book, and so serves as a snapshot test of +/// those examples. fn test_examples() -> Result<()> { - // Note that on Windows, markdown is read differently, and so we don't write - // on Windows (we write from the same place we read as a workaround). ref - // https://github.com/PRQL/prql/issues/356 + // Note that on Windows, markdown is read differently, and so we don't yet + // write on Windows (we write from the same place we read as a workaround, + // and would welcome a fix). + // ref https://github.com/PRQL/prql/issues/356 write_prql_examples(collect_book_examples()?)?; test_prql_examples(); @@ -60,12 +62,9 @@ fn collect_book_examples() -> Result> { .filter(|x| glob.is_match(x.path())) .flat_map(|dir_entry| { let text = fs::read_to_string(dir_entry.path())?; - // TODO: Duplicative logic here and in [lib.rs/replace_examples]; - // could we unify? + // TODO: Still slightly duplicative logic here and in + // [lib.rs/replace_examples], but not sure how to avoid it. // - // Could we have a function that takes text and returns a - // Vec, where expected is whether it - // should succeed or fail? let mut parser = Parser::new(&text); let mut prql_blocks = vec![]; while let Some(event) = parser.next() { @@ -165,6 +164,7 @@ fn write_prql_examples(examples: HashMap) -> Result<()> { }) }); + // TODO: Not actually sure we want this; not consistent with `cargo insta --accept`. if !snapshots_updated.is_empty() { let snapshots_updated = snapshots_updated .iter() From ecf6abe4fe0c2c7d29b11d79181ad3929d5080b6 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sat, 11 Mar 2023 01:03:32 +0100 Subject: [PATCH 152/184] chore: PHP - fix lints and docs (#2096) * Update Compiler.php * Document PHP code --- prql-php/src/Compiler.php | 82 +++++++++++++++++---------------- prql-php/src/MessageKind.php | 9 ++++ prql-php/src/Options.php | 4 +- prql-php/src/Result.php | 3 ++ prql-php/src/SourceLocation.php | 15 ++++++ prql-php/src/Span.php | 7 +++ 6 files changed, 78 insertions(+), 42 deletions(-) diff --git a/prql-php/src/Compiler.php b/prql-php/src/Compiler.php index f27847dd77e8..88fc770362f6 100644 --- a/prql-php/src/Compiler.php +++ b/prql-php/src/Compiler.php @@ -14,7 +14,7 @@ * @copyright 2023 PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 * - * @see https://prql-lang.org/ + * @link https://prql-lang.org/ */ declare(strict_types=1); @@ -22,14 +22,16 @@ namespace Prql\Compiler; /** + * PRQL Compiler. + * * @author PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 * - * @see https://prql-lang.org/ + * @link https://prql-lang.org/ */ final class Compiler { - private \FFI $ffi; + private \FFI $_ffi; /** * Initializes a new instance of the Compiler. @@ -39,17 +41,17 @@ final class Compiler public function __construct(?string $lib_path = null) { if ($lib_path === null) { - $lib_path = __DIR__.'/../lib'; + $lib_path = __DIR__ . '/../lib'; } - $header = $lib_path.'/libprql_lib.h'; + $header = $lib_path . '/libprql_lib.h'; if (PHP_OS_FAMILY === 'Windows') { - $library = $lib_path."\libprql_lib.dll"; + $library = $lib_path . "\libprql_lib.dll"; } elseif (PHP_OS_FAMILY === 'Darwin') { - $library = $lib_path.'/libprql_lib.dylib'; + $library = $lib_path . '/libprql_lib.dylib'; } else { - $library = $lib_path.'/libprql_lib.so'; + $library = $lib_path . '/libprql_lib.so'; } $header_source = file_get_contents($header, false, null, 0, 1024 * 1024); @@ -58,7 +60,7 @@ public function __construct(?string $lib_path = null) throw new \InvalidArgumentException('Cannot load header file.'); } - $this->ffi = \FFI::cdef($header_source, $library); + $this->_ffi = \FFI::cdef($header_source, $library); } /** @@ -77,13 +79,13 @@ public function compile(string $prql_query, ?Options $options = null): Result throw new \InvalidArgumentException('No query given.'); } - $ffi_options = $this->optionsInit($options); + $ffi_options = $this->_optionsInit($options); - $res = $this->ffi->compile($prql_query, \FFI::addr($ffi_options)); + $res = $this->_ffi->compile($prql_query, \FFI::addr($ffi_options)); - $this->optionsDestroy($ffi_options); + $this->_optionsDestroy($ffi_options); - return $this->convertResult($res); + return $this->_convertResult($res); } /** @@ -103,9 +105,9 @@ public function prqlToPL(string $prql_query): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->ffi->prql_to_pl($prql_query); + $res = $this->_ffi->prql_to_pl($prql_query); - return $this->convertResult($res); + return $this->_convertResult($res); } /** @@ -125,9 +127,9 @@ public function plToRQ(string $pl_json): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->ffi->pl_to_rq($pl_json); + $res = $this->_ffi->pl_to_rq($pl_json); - return $this->convertResult($res); + return $this->_convertResult($res); } /** @@ -148,22 +150,22 @@ public function rqToSQL(string $rq_json, ?Options $options = null): Result throw new \InvalidArgumentException('No query given.'); } - $ffi_options = $this->optionsInit($options); + $ffi_options = $this->_optionsInit($options); - $res = $this->ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); + $res = $this->_ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); - $this->optionsDestroy($ffi_options); + $this->_optionsDestroy($ffi_options); - return $this->convertResult($res); + return $this->_convertResult($res); } - private function optionsInit(?Options $options = null) + private function _optionsInit(?Options $options = null) { if ($options === null) { $options = new Options(); } - $ffi_options = $this->ffi->new('struct Options'); + $ffi_options = $this->_ffi->new('struct Options'); $ffi_options->format = $options->format; $ffi_options->signature_comment = $options->signature_comment; @@ -176,7 +178,7 @@ private function optionsInit(?Options $options = null) return $ffi_options; } - private function optionsDestroy($ffi_options) + private function _optionsDestroy($ffi_options) { if (!\FFI::isNull($ffi_options->target)) { \FFI::free($ffi_options->target); @@ -184,25 +186,25 @@ private function optionsDestroy($ffi_options) unset($ffi_options); } - private function convertResult($ffi_res): Result + private function _convertResult($ffi_res): Result { $res = new Result(); // convert string - $res->output = $this->convertString($ffi_res->output); + $res->output = $this->_convertString($ffi_res->output); $res->messages = []; for ($i = 0; $i < $ffi_res->messages_len; ++$i) { - $res->messages[$i] = $this->convertMessage($ffi_res->messages[$i]); + $res->messages[$i] = $this->_convertMessage($ffi_res->messages[$i]); } // free the ffi_result - $this->ffi->result_destroy($ffi_res); + $this->_ffi->result_destroy($ffi_res); return $res; } - private function convertMessage($ffi_msg): Message + private function _convertMessage($ffi_msg): Message { $msg = new Message(); @@ -215,18 +217,18 @@ private function convertMessage($ffi_msg): Message $msg->kind = MessageKind::Lint; } - $msg->code = $this->convertNullableString($ffi_msg->code); - $msg->reason = $this->convertString($ffi_msg->reason); - $msg->span = $this->convertSpan($ffi_msg->span); - $msg->hint = $this->convertNullableString($ffi_msg->hint); + $msg->code = $this->_convertNullableString($ffi_msg->code); + $msg->reason = $this->_convertString($ffi_msg->reason); + $msg->span = $this->_convertSpan($ffi_msg->span); + $msg->hint = $this->_convertNullableString($ffi_msg->hint); - $msg->display = $this->convertNullableString($ffi_msg->display); - $msg->location = $this->convertLocation($ffi_msg->location); + $msg->display = $this->_convertNullableString($ffi_msg->display); + $msg->location = $this->_convertLocation($ffi_msg->location); return $msg; } - private function convertSpan($ffi_ptr): ?Span + private function _convertSpan($ffi_ptr): ?Span { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; @@ -238,7 +240,7 @@ private function convertSpan($ffi_ptr): ?Span return $span; } - private function convertLocation($ffi_ptr): ?SourceLocation + private function _convertLocation($ffi_ptr): ?SourceLocation { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; @@ -253,16 +255,16 @@ private function convertLocation($ffi_ptr): ?SourceLocation return $location; } - private function convertNullableString($ffi_ptr): ?string + private function _convertNullableString($ffi_ptr): ?string { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; } // dereference - return $this->convertString($ffi_ptr[0]); + return $this->_convertString($ffi_ptr[0]); } - private function convertString($ffi_ptr): string + private function _convertString($ffi_ptr): string { return \FFI::string(\FFI::cast(\FFI::type('char*'), $ffi_ptr)); } diff --git a/prql-php/src/MessageKind.php b/prql-php/src/MessageKind.php index 27236b2c3fee..8140b16d02d2 100644 --- a/prql-php/src/MessageKind.php +++ b/prql-php/src/MessageKind.php @@ -9,7 +9,16 @@ */ enum MessageKind { + /** + * Error message. + */ case Error; + /** + * Warning message. + */ case Warning; + /** + * Lint message. + */ case Lint; } diff --git a/prql-php/src/Options.php b/prql-php/src/Options.php index 0c5e20182164..bb14f4b5ee54 100644 --- a/prql-php/src/Options.php +++ b/prql-php/src/Options.php @@ -14,7 +14,7 @@ * @copyright 2023 PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 * - * @see https://prql-lang.org/ + * @see https://prql-lang.org/ */ declare(strict_types=1); @@ -27,7 +27,7 @@ * @author PRQL * @license https://spdx.org/licenses/Apache-2.0.html Apache License 2.0 * - * @see https://prql-lang.org/ + * @see https://prql-lang.org/ */ final class Options { diff --git a/prql-php/src/Result.php b/prql-php/src/Result.php index ba20a56cda84..2ed3f8cce747 100644 --- a/prql-php/src/Result.php +++ b/prql-php/src/Result.php @@ -9,6 +9,9 @@ */ final class Result { + /** + * @var string + */ public string $output; /** diff --git a/prql-php/src/SourceLocation.php b/prql-php/src/SourceLocation.php index 15af1545ac65..e051549cb493 100644 --- a/prql-php/src/SourceLocation.php +++ b/prql-php/src/SourceLocation.php @@ -9,8 +9,23 @@ */ final class SourceLocation { + /** + * Start line. + */ public int $start_line; + + /** + * Start column. + */ public int $start_col; + + /** + * End line. + */ public int $end_line; + + /** + * End column. + */ public int $end_col; } diff --git a/prql-php/src/Span.php b/prql-php/src/Span.php index 21f92e2fdc09..d0f5e2874068 100644 --- a/prql-php/src/Span.php +++ b/prql-php/src/Span.php @@ -10,6 +10,13 @@ */ final class Span { + /** + * Start offset. + */ public int $start; + + /** + * End offset. + */ public int $end; } From 74c00fd70308967244c83a1abcaf821f39c8aad7 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 17:49:33 -0800 Subject: [PATCH 153/184] chore(ci): Bump cache keys (#2099) Currently we've run out of cache space and are going to start churning soon. `prql-lib` is taking up 1.3GB; going to try bumping that and seeing if it still needs that much. --- .github/workflows/test-lib.yaml | 5 +++-- .github/workflows/test-rust.yaml | 13 +++++++------ prql-lib/examples/minimal-c/Makefile | 1 + 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml index 7bd0f8d36c19..d307cb7ef1e6 100644 --- a/.github/workflows/test-lib.yaml +++ b/.github/workflows/test-lib.yaml @@ -14,7 +14,7 @@ concurrency: cancel-in-progress: true jobs: - test: + test-lib: runs-on: ubuntu-latest steps: - name: ๐Ÿ“‚ Checkout code @@ -22,12 +22,13 @@ jobs: - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 with: - key: ${{ inputs.target_option }} + key: 0.6.0-${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - name: Build uses: richb-hanover/cargo@v1.1.0 with: command: build + # Currently requires a release build; would be useful to allow a debug build. args: --release -p prql-lib - name: Run basic C example working-directory: prql-lib/examples/minimal-c diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index 5fc6b9e0d7eb..08e2e64dab8a 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -13,7 +13,7 @@ env: CARGO_TERM_COLOR: always jobs: - test: + test-rust: runs-on: ${{ inputs.os }} steps: - name: ๐Ÿ“‚ Checkout code @@ -25,8 +25,7 @@ jobs: # reset the cache. If necessary, we could do this on each release and # have this update automatically (there's no variable that contains # the current version unfortunately, though). - prefix-key: "0.5.2" - key: ${{ inputs.target_option }} + key: 0.6.0-${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - uses: baptiste0928/cargo-install@next with: @@ -54,9 +53,11 @@ jobs: - uses: baptiste0928/cargo-install@next with: crate: cargo-insta - # Only check unreferenced snapshots on the default target tests on ubuntu (maybe - # there's a nicer approach where we can parameterize one step rather than - # have two different ones; we welcome a change to simplify this) + # Only check unreferenced snapshots on the default target tests on ubuntu + # + # (Maybe there's a nicer approach where we can parameterize one step + # rather than have two different ones? We welcome a change to simplify + # this.) - name: ๐Ÿ“‹ Test uses: richb-hanover/cargo@v1.1.0 if: diff --git a/prql-lib/examples/minimal-c/Makefile b/prql-lib/examples/minimal-c/Makefile index a9b34dad60bb..cf56b87285db 100644 --- a/prql-lib/examples/minimal-c/Makefile +++ b/prql-lib/examples/minimal-c/Makefile @@ -3,6 +3,7 @@ PRQL_PROJECT=../../.. build-prql: cargo build -p prql-lib --release +# TODO: would be helpful to allow running with a debug build too. build: main.c build-prql gcc main.c -o main.out \ -I${PRQL_PROJECT}/prql-lib \ From 5ce4a5fa3279f0d80c1bfb2858460599c97381d2 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 18:16:45 -0800 Subject: [PATCH 154/184] chore: Clarify test job names (#2100) --- .github/workflows/test-rust.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index 08e2e64dab8a..1f809579a358 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -58,7 +58,7 @@ jobs: # (Maybe there's a nicer approach where we can parameterize one step # rather than have two different ones? We welcome a change to simplify # this.) - - name: ๐Ÿ“‹ Test + - name: ๐Ÿ“‹ Test default uses: richb-hanover/cargo@v1.1.0 if: ${{ (inputs.target_option != '--target=wasm32-unknown-unknown' && @@ -66,7 +66,7 @@ jobs: with: command: insta args: test --unreferenced=auto ${{ inputs.target_option }} - - name: ๐Ÿ“‹ Test + - name: ๐Ÿ“‹ Test wasm uses: richb-hanover/cargo@v1.1.0 if: ${{ ! (inputs.target_option != '--target=wasm32-unknown-unknown' && From ed1e896ecbb1c5e18f0f1286639118e3a77b0100 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Fri, 10 Mar 2023 19:12:30 -0800 Subject: [PATCH 155/184] docs: Add link from book to docs.rs (#2101) * docs: Add link from book to docs.rs --- book/src/internals/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/book/src/internals/README.md b/book/src/internals/README.md index 38571d2be4ac..dadf1de088ae 100644 --- a/book/src/internals/README.md +++ b/book/src/internals/README.md @@ -6,3 +6,7 @@ their meaning. It's intended for advanced users and compiler contributors. - [Name resolving](./name-resolving.md) - [Functions](./functional-lang.md) - [Syntax highlighting](./syntax-highlighting.md) + +It's also worth checking out the +[`prql-compiler` docs](https://docs.rs/prql-compiler/latest/prql_compiler/) for +more details on its API. From c2cedaa3b43184d82014c5ee9f98c9a5fe70f3bd Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Sat, 11 Mar 2023 20:51:35 +0900 Subject: [PATCH 156/184] build: update MegaLinter configs for PHP (#2069) * chore: set PHP_PHPCS_ARGUMENTS * chore: set PHP_PHPSTAN_FILTER_REGEX_EXCLUDE * chore: temporarily enable linting for all codes * build: disable PSR12.Operators.OperatorSpacing * Revert "chore: temporarily enable linting for all codes" This reverts commit 48aa0b48f5ee07116e9bbe75cbfac36e06f2b64f. * build: disable psalm for now * build: enable errors from phpcs and phpstan * Revert "Revert "chore: temporarily enable linting for all codes"" This reverts commit 035a69060864ace4558ff20797e8aa376445c8cd. * format: use list style * format: spacing around `.` Co-authored-by: Jonathan * ci: trying phpstan target the sub dir * Revert "Revert "Revert "chore: temporarily enable linting for all codes""" This reverts commit 3727c472444576858146c985edbafefe221fea10. * chore: temp add a comment for to trigger megalinter for php * Revert "ci: trying phpstan target the sub dir" This reverts commit 1b46136a9347c2161d5a56931a3a01617566873e. * ci: disable phpstan for now * chore: prql-php in PSR-12 coding standard (#2106) * Revert "chore: temp add a comment for to trigger megalinter for php" This reverts commit d154741bfba4738d6da34997907f4674c391027d. --------- Co-authored-by: Jonathan --- .mega-linter.yaml | 7 ++-- prql-php/src/Compiler.php | 68 ++++++++++++++++++++------------------- 2 files changed, 39 insertions(+), 36 deletions(-) diff --git a/.mega-linter.yaml b/.mega-linter.yaml index 680a2e9edbe4..4235b513c9cd 100644 --- a/.mega-linter.yaml +++ b/.mega-linter.yaml @@ -9,6 +9,8 @@ DISABLE: DISABLE_LINTERS: - SPELL_CSPELL - CSS_STYLELINT + - PHP_PSALM + - PHP_PHPSTAN # Disabled for now as we couldn't figure out how to prevent false positives. #2069 DISABLE_ERRORS_LINTERS: - COPYPASTE_JSCPD - REPOSITORY_TRIVY @@ -26,9 +28,8 @@ DISABLE_ERRORS_LINTERS: - JSON_JSONLINT - MAKEFILE_CHECKMAKE - MARKDOWN_MARKDOWN_LINK_CHECK - - PHP_PHPCS - - PHP_PHPSTAN - - PHP_PSALM - SPELL_MISSPELL - SQL_TSQLLINT - YAML_V8R +PHP_PHPCS_ARGUMENTS: + - --standard=PSR12 diff --git a/prql-php/src/Compiler.php b/prql-php/src/Compiler.php index 88fc770362f6..3888f174ae90 100644 --- a/prql-php/src/Compiler.php +++ b/prql-php/src/Compiler.php @@ -31,7 +31,7 @@ */ final class Compiler { - private \FFI $_ffi; + private \FFI $ffi; /** * Initializes a new instance of the Compiler. @@ -60,7 +60,7 @@ public function __construct(?string $lib_path = null) throw new \InvalidArgumentException('Cannot load header file.'); } - $this->_ffi = \FFI::cdef($header_source, $library); + $this->ffi = \FFI::cdef($header_source, $library); } /** @@ -79,13 +79,13 @@ public function compile(string $prql_query, ?Options $options = null): Result throw new \InvalidArgumentException('No query given.'); } - $ffi_options = $this->_optionsInit($options); + $ffi_options = $this->optionsInit($options); - $res = $this->_ffi->compile($prql_query, \FFI::addr($ffi_options)); + $res = $this->ffi->compile($prql_query, \FFI::addr($ffi_options)); - $this->_optionsDestroy($ffi_options); + $this->optionsDestroy($ffi_options); - return $this->_convertResult($res); + return $this->convertResult($res); } /** @@ -105,9 +105,9 @@ public function prqlToPL(string $prql_query): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->_ffi->prql_to_pl($prql_query); + $res = $this->ffi->prql_to_pl($prql_query); - return $this->_convertResult($res); + return $this->convertResult($res); } /** @@ -127,9 +127,9 @@ public function plToRQ(string $pl_json): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->_ffi->pl_to_rq($pl_json); + $res = $this->ffi->pl_to_rq($pl_json); - return $this->_convertResult($res); + return $this->convertResult($res); } /** @@ -150,22 +150,22 @@ public function rqToSQL(string $rq_json, ?Options $options = null): Result throw new \InvalidArgumentException('No query given.'); } - $ffi_options = $this->_optionsInit($options); + $ffi_options = $this->optionsInit($options); - $res = $this->_ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); + $res = $this->ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); - $this->_optionsDestroy($ffi_options); + $this->optionsDestroy($ffi_options); - return $this->_convertResult($res); + return $this->convertResult($res); } - private function _optionsInit(?Options $options = null) + private function optionsInit(?Options $options = null) { if ($options === null) { $options = new Options(); } - $ffi_options = $this->_ffi->new('struct Options'); + $ffi_options = $this->ffi->new('struct Options'); $ffi_options->format = $options->format; $ffi_options->signature_comment = $options->signature_comment; @@ -178,33 +178,34 @@ private function _optionsInit(?Options $options = null) return $ffi_options; } - private function _optionsDestroy($ffi_options) + private function optionsDestroy($ffi_options) { if (!\FFI::isNull($ffi_options->target)) { \FFI::free($ffi_options->target); } + unset($ffi_options); } - private function _convertResult($ffi_res): Result + private function convertResult($ffi_res): Result { $res = new Result(); // convert string - $res->output = $this->_convertString($ffi_res->output); + $res->output = $this->convertString($ffi_res->output); $res->messages = []; for ($i = 0; $i < $ffi_res->messages_len; ++$i) { - $res->messages[$i] = $this->_convertMessage($ffi_res->messages[$i]); + $res->messages[$i] = $this->convertMessage($ffi_res->messages[$i]); } // free the ffi_result - $this->_ffi->result_destroy($ffi_res); + $this->ffi->result_destroy($ffi_res); return $res; } - private function _convertMessage($ffi_msg): Message + private function convertMessage($ffi_msg): Message { $msg = new Message(); @@ -217,22 +218,23 @@ private function _convertMessage($ffi_msg): Message $msg->kind = MessageKind::Lint; } - $msg->code = $this->_convertNullableString($ffi_msg->code); - $msg->reason = $this->_convertString($ffi_msg->reason); - $msg->span = $this->_convertSpan($ffi_msg->span); - $msg->hint = $this->_convertNullableString($ffi_msg->hint); + $msg->code = $this->convertNullableString($ffi_msg->code); + $msg->reason = $this->convertString($ffi_msg->reason); + $msg->span = $this->convertSpan($ffi_msg->span); + $msg->hint = $this->convertNullableString($ffi_msg->hint); - $msg->display = $this->_convertNullableString($ffi_msg->display); - $msg->location = $this->_convertLocation($ffi_msg->location); + $msg->display = $this->convertNullableString($ffi_msg->display); + $msg->location = $this->convertLocation($ffi_msg->location); return $msg; } - private function _convertSpan($ffi_ptr): ?Span + private function convertSpan($ffi_ptr): ?Span { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; } + $span = new Span(); $span->start = $ffi_ptr[0]->start; $span->end = $ffi_ptr[0]->end; @@ -240,7 +242,7 @@ private function _convertSpan($ffi_ptr): ?Span return $span; } - private function _convertLocation($ffi_ptr): ?SourceLocation + private function convertLocation($ffi_ptr): ?SourceLocation { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; @@ -255,16 +257,16 @@ private function _convertLocation($ffi_ptr): ?SourceLocation return $location; } - private function _convertNullableString($ffi_ptr): ?string + private function convertNullableString($ffi_ptr): ?string { if (is_null($ffi_ptr) || \FFI::isNull($ffi_ptr)) { return null; } // dereference - return $this->_convertString($ffi_ptr[0]); + return $this->convertString($ffi_ptr[0]); } - private function _convertString($ffi_ptr): string + private function convertString($ffi_ptr): string { return \FFI::string(\FFI::cast(\FFI::type('char*'), $ffi_ptr)); } From ec68c915920b3fb133d51063cec012489c53362a Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sat, 11 Mar 2023 19:42:46 +0100 Subject: [PATCH 157/184] chore(prql-php): Add comment and define to header file (#2107) * Update cbindgen.toml * Update libprql_lib.h * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- prql-lib/cbindgen.toml | 11 +++++++++++ prql-lib/libprql_lib.h | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/prql-lib/cbindgen.toml b/prql-lib/cbindgen.toml index 08094f28fc2c..73fbadea44a7 100644 --- a/prql-lib/cbindgen.toml +++ b/prql-lib/cbindgen.toml @@ -1 +1,12 @@ language = "C" + +header = '''/* + * PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement + * + * License: Apache-2.0 + * Website: https://prql-lang.org/ + */''' + +autogen_warning = "/* This file is autogenerated. Do not modify this file manually. */" + +after_includes = '#define FFI_SCOPE "PRQL"' diff --git a/prql-lib/libprql_lib.h b/prql-lib/libprql_lib.h index a4a0ce492d77..e8c5f7f38993 100644 --- a/prql-lib/libprql_lib.h +++ b/prql-lib/libprql_lib.h @@ -1,7 +1,17 @@ +/* + * PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement + * + * License: Apache-2.0 + * Website: https://prql-lang.org/ + */ + +/* This file is autogenerated. Do not modify this file manually. */ + #include #include #include #include +#define FFI_SCOPE "PRQL" /** * Compile message kind. Currently only Error is implemented. From 33061501ffefd918222d56e73caba8e6213bffdd Mon Sep 17 00:00:00 2001 From: Jelenkee <59470612+Jelenkee@users.noreply.github.com> Date: Sat, 11 Mar 2023 20:01:19 +0100 Subject: [PATCH 158/184] test: Remove writing of test files to disk (#2105) * -fixed reading of markdown files on windows -removed writing of snapshots to disk * -removed include_str * update snapshot * -fixed formatting * -fixed clippy * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * dang it * -replaced snapshots --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- book/tests/prql/examples/cte-0.prql | 18 --- book/tests/prql/examples/employees-0.prql | 11 -- book/tests/prql/examples/employees-1.prql | 16 --- book/tests/prql/examples/employees-2.prql | 21 ---- book/tests/prql/examples/employees-3.prql | 13 --- .../prql/examples/list-equivalence-0.prql | 2 - .../prql/examples/list-equivalence-1.prql | 2 - .../prql/examples/list-equivalence-2.prql | 5 - .../prql/examples/list-equivalence-3.prql | 3 - book/tests/prql/examples/misc-0.prql | 15 --- book/tests/prql/examples/misc-1.prql | 7 -- book/tests/prql/examples/variables-1.prql | 15 --- .../prql/internals/functional-lang-0.prql | 3 - .../prql/internals/functional-lang-1.prql | 1 - .../prql/internals/functional-lang-2.prql | 1 - .../prql/internals/functional-lang-3.prql | 1 - .../prql/internals/name-resolving-0.prql | 2 - .../prql/internals/name-resolving-1.prql | 4 - book/tests/prql/introduction-0.prql | 18 --- book/tests/prql/language-features/case-0.prql | 7 -- book/tests/prql/language-features/case-1.prql | 8 -- .../prql/language-features/coalesce-0.prql | 2 - .../language-features/dates-and-times-0.prql | 2 - .../language-features/dates-and-times-1.prql | 2 - .../language-features/dates-and-times-2.prql | 2 - .../language-features/dates-and-times-3.prql | 2 - .../prql/language-features/distinct-0.prql | 5 - .../prql/language-features/distinct-1.prql | 3 - .../prql/language-features/distinct-2.prql | 6 - .../prql/language-features/f-strings-0.prql | 2 - .../prql/language-features/f-strings-1.prql | 2 - book/tests/prql/language-features/null-0.prql | 3 - .../prql/language-features/ranges-0.prql | 4 - .../prql/language-features/ranges-1.prql | 3 - .../prql/language-features/s-strings-0.prql | 2 - .../prql/language-features/s-strings-1.prql | 2 - .../prql/language-features/s-strings-2.prql | 7 -- .../prql/language-features/s-strings-3.prql | 2 - .../prql/language-features/s-strings-4.prql | 6 - .../prql/language-features/s-strings-5.prql | 5 - .../prql/language-features/s-strings-6.prql | 5 - .../standard-library/README-0.prql | 6 - .../standard-library/from-text-0.prql | 9 -- .../standard-library/from-text-1.prql | 10 -- .../standard-library/from-text-2.prql | 16 --- .../standard-library/loop-0.prql | 7 -- .../prql/language-features/strings-0.prql | 2 - .../prql/language-features/strings-1.prql | 2 - .../prql/language-features/strings-2.prql | 2 - .../prql/language-features/strings-3.prql | 2 - .../prql/language-features/strings-4.prql | 2 - .../prql/language-features/strings-5.prql | 4 - .../prql/language-features/target-0.prql | 5 - .../prql/language-features/target-1.prql | 7 -- .../prql/language-features/target-2.prql | 5 - book/tests/prql/queries/functions-0.prql | 6 - book/tests/prql/queries/functions-1.prql | 7 -- book/tests/prql/queries/functions-2.prql | 7 -- book/tests/prql/queries/functions-3.prql | 4 - book/tests/prql/queries/functions-4.prql | 5 - book/tests/prql/queries/functions-5.prql | 9 -- book/tests/prql/queries/pipelines-0.prql | 1 - book/tests/prql/queries/pipelines-1.prql | 2 - book/tests/prql/queries/pipelines-2.prql | 6 - book/tests/prql/queries/variables-0.prql | 8 -- book/tests/prql/queries/variables-1.prql | 9 -- book/tests/prql/syntax-0.prql | 3 - book/tests/prql/syntax-1.prql | 1 - book/tests/prql/syntax-10.prql | 3 - book/tests/prql/syntax-11.prql | 3 - book/tests/prql/syntax-12.prql | 1 - book/tests/prql/syntax-13.prql | 3 - book/tests/prql/syntax-14.prql | 1 - book/tests/prql/syntax-15.prql | 2 - book/tests/prql/syntax-16.prql | 5 - book/tests/prql/syntax-17.prql | 3 - book/tests/prql/syntax-2.prql | 10 -- book/tests/prql/syntax-3.prql | 2 - book/tests/prql/syntax-4.prql | 2 - book/tests/prql/syntax-5.prql | 6 - book/tests/prql/syntax-6.prql | 28 ----- book/tests/prql/syntax-7.prql | 4 - book/tests/prql/syntax-8.prql | 7 -- book/tests/prql/syntax-9.prql | 3 - book/tests/prql/transforms/aggregate-0.prql | 5 - book/tests/prql/transforms/aggregate-1.prql | 7 -- book/tests/prql/transforms/aggregate-2.prql | 2 - book/tests/prql/transforms/append-0.prql | 2 - book/tests/prql/transforms/append-1.prql | 2 - book/tests/prql/transforms/append-2.prql | 2 - book/tests/prql/transforms/derive-0.prql | 2 - book/tests/prql/transforms/derive-1.prql | 5 - book/tests/prql/transforms/filter-0.prql | 2 - book/tests/prql/transforms/filter-1.prql | 2 - book/tests/prql/transforms/filter-2.prql | 2 - book/tests/prql/transforms/from-0.prql | 1 - book/tests/prql/transforms/from-1.prql | 2 - book/tests/prql/transforms/group-0.prql | 7 -- book/tests/prql/transforms/group-1.prql | 3 - book/tests/prql/transforms/group-2.prql | 5 - book/tests/prql/transforms/join-0.prql | 2 - book/tests/prql/transforms/join-1.prql | 2 - book/tests/prql/transforms/join-2.prql | 2 - book/tests/prql/transforms/select-0.prql | 2 - book/tests/prql/transforms/select-1.prql | 5 - book/tests/prql/transforms/select-2.prql | 2 - book/tests/prql/transforms/select-3.prql | 2 - book/tests/prql/transforms/select-4.prql | 5 - book/tests/prql/transforms/select-5.prql | 5 - book/tests/prql/transforms/select-6.prql | 5 - book/tests/prql/transforms/sort-0.prql | 2 - book/tests/prql/transforms/sort-1.prql | 2 - book/tests/prql/transforms/sort-2.prql | 2 - book/tests/prql/transforms/sort-3.prql | 2 - book/tests/prql/transforms/sort-4.prql | 3 - book/tests/prql/transforms/sort-5.prql | 3 - book/tests/prql/transforms/take-0.prql | 2 - book/tests/prql/transforms/take-1.prql | 3 - book/tests/prql/transforms/window-0.prql | 7 -- book/tests/prql/transforms/window-1.prql | 11 -- book/tests/prql/transforms/window-2.prql | 3 - book/tests/prql/transforms/window-3.prql | 5 - book/tests/prql/transforms/window-4.prql | 2 - book/tests/snapshot.rs | 109 +++--------------- ..._@language-features__s-strings-4.prql.snap | 10 -- ...t__@language-features__strings-5.prql.snap | 11 -- ...ot__@language-features__target-1.prql.snap | 11 -- ...ot__@language-features__target-2.prql.snap | 10 -- .../snapshot__@queries__functions-0.prql.snap | 10 -- .../snapshot__@queries__functions-1.prql.snap | 11 -- .../snapshot__@queries__functions-2.prql.snap | 11 -- .../snapshot__@queries__functions-4.prql.snap | 11 -- .../snapshots/snapshot__@syntax-6.prql.snap | 20 ---- .../snapshot__@transforms__select-4.prql.snap | 11 -- .../snapshot__@transforms__select-5.prql.snap | 10 -- .../snapshot__@transforms__select-6.prql.snap | 9 -- ...t__tests__prql__examples__cte-0.prql.snap} | 3 +- ...ts__prql__examples__employees-0.prql.snap} | 1 - ...ts__prql__examples__employees-1.prql.snap} | 1 - ...ts__prql__examples__employees-2.prql.snap} | 1 - ...ts__prql__examples__employees-3.prql.snap} | 3 +- ...l__examples__list-equivalence-0.prql.snap} | 2 +- ...l__examples__list-equivalence-1.prql.snap} | 2 +- ...l__examples__list-equivalence-2.prql.snap} | 2 +- ...l__examples__list-equivalence-3.prql.snap} | 2 +- ...__tests__prql__examples__misc-0.prql.snap} | 1 - ...__tests__prql__examples__misc-1.prql.snap} | 2 +- ...ts__prql__examples__variables-0.prql.snap} | 1 - ...ts__prql__examples__variables-1.prql.snap} | 1 - ...l__internals__functional-lang-0.prql.snap} | 2 +- ...l__internals__functional-lang-1.prql.snap} | 2 +- ...l__internals__functional-lang-2.prql.snap} | 2 +- ...l__internals__functional-lang-3.prql.snap} | 2 +- ...ql__internals__name-resolving-0.prql.snap} | 2 +- ...ql__internals__name-resolving-1.prql.snap} | 2 +- ...ot__tests__prql__introduction-0.prql.snap} | 1 - ...prql__language-features__case-0.prql.snap} | 1 - ...prql__language-features__case-1.prql.snap} | 1 - ...__language-features__coalesce-0.prql.snap} | 2 +- ...age-features__dates-and-times-0.prql.snap} | 2 +- ...age-features__dates-and-times-1.prql.snap} | 2 +- ...age-features__dates-and-times-2.prql.snap} | 1 - ...age-features__dates-and-times-3.prql.snap} | 2 +- ...__language-features__distinct-0.prql.snap} | 2 +- ...__language-features__distinct-1.prql.snap} | 2 +- ...__language-features__distinct-2.prql.snap} | 1 - ..._language-features__f-strings-0.prql.snap} | 2 +- ..._language-features__f-strings-1.prql.snap} | 2 +- ...prql__language-features__null-0.prql.snap} | 2 +- ...ql__language-features__ranges-0.prql.snap} | 1 - ...ql__language-features__ranges-1.prql.snap} | 1 - ..._language-features__s-strings-0.prql.snap} | 2 +- ..._language-features__s-strings-1.prql.snap} | 2 +- ..._language-features__s-strings-2.prql.snap} | 2 +- ..._language-features__s-strings-3.prql.snap} | 1 - ...__language-features__s-strings-4.prql.snap | 10 ++ ..._language-features__s-strings-5.prql.snap} | 2 +- ..._language-features__s-strings-6.prql.snap} | 2 +- ...res__standard-library__README-0.prql.snap} | 1 - ...__standard-library__from-text-0.prql.snap} | 1 - ...__standard-library__from-text-1.prql.snap} | 1 - ...__standard-library__from-text-2.prql.snap} | 1 - ...tures__standard-library__loop-0.prql.snap} | 1 - ...l__language-features__strings-0.prql.snap} | 2 +- ...l__language-features__strings-1.prql.snap} | 2 +- ...l__language-features__strings-2.prql.snap} | 2 +- ...l__language-features__strings-3.prql.snap} | 2 +- ...l__language-features__strings-4.prql.snap} | 2 +- ...ql__language-features__strings-5.prql.snap | 10 ++ ...ql__language-features__target-0.prql.snap} | 2 +- ...rql__language-features__target-1.prql.snap | 11 ++ ...rql__language-features__target-2.prql.snap | 9 ++ ...ests__prql__queries__functions-0.prql.snap | 10 ++ ...ests__prql__queries__functions-1.prql.snap | 11 ++ ...ests__prql__queries__functions-2.prql.snap | 11 ++ ...sts__prql__queries__functions-3.prql.snap} | 2 +- ...ests__prql__queries__functions-4.prql.snap | 10 ++ ...sts__prql__queries__functions-5.prql.snap} | 1 - ...sts__prql__queries__pipelines-0.prql.snap} | 2 +- ...sts__prql__queries__pipelines-1.prql.snap} | 2 +- ...sts__prql__queries__pipelines-2.prql.snap} | 1 - ...sts__prql__queries__variables-0.prql.snap} | 1 - ...sts__prql__queries__variables-1.prql.snap} | 1 - ...snapshot__tests__prql__syntax-0.prql.snap} | 2 +- ...snapshot__tests__prql__syntax-1.prql.snap} | 2 +- ...napshot__tests__prql__syntax-10.prql.snap} | 1 - ...napshot__tests__prql__syntax-11.prql.snap} | 1 - ...napshot__tests__prql__syntax-12.prql.snap} | 1 - ...napshot__tests__prql__syntax-13.prql.snap} | 1 - ...napshot__tests__prql__syntax-14.prql.snap} | 1 - ...napshot__tests__prql__syntax-15.prql.snap} | 1 - ...napshot__tests__prql__syntax-16.prql.snap} | 1 - ...napshot__tests__prql__syntax-17.prql.snap} | 1 - ...snapshot__tests__prql__syntax-2.prql.snap} | 2 +- ...snapshot__tests__prql__syntax-3.prql.snap} | 2 +- ...snapshot__tests__prql__syntax-4.prql.snap} | 2 +- ...snapshot__tests__prql__syntax-5.prql.snap} | 1 - .../snapshot__tests__prql__syntax-6.prql.snap | 20 ++++ ...snapshot__tests__prql__syntax-7.prql.snap} | 1 - ...snapshot__tests__prql__syntax-8.prql.snap} | 1 - ...snapshot__tests__prql__syntax-9.prql.snap} | 1 - ...__prql__transforms__aggregate-0.prql.snap} | 2 +- ...__prql__transforms__aggregate-1.prql.snap} | 2 +- ...__prql__transforms__aggregate-2.prql.snap} | 2 +- ...sts__prql__transforms__append-0.prql.snap} | 2 +- ...sts__prql__transforms__append-1.prql.snap} | 2 +- ...sts__prql__transforms__append-2.prql.snap} | 2 +- ...sts__prql__transforms__derive-0.prql.snap} | 2 +- ...sts__prql__transforms__derive-1.prql.snap} | 2 +- ...sts__prql__transforms__filter-0.prql.snap} | 2 +- ...sts__prql__transforms__filter-1.prql.snap} | 2 +- ...sts__prql__transforms__filter-2.prql.snap} | 2 +- ...tests__prql__transforms__from-0.prql.snap} | 2 +- ...tests__prql__transforms__from-1.prql.snap} | 2 +- ...ests__prql__transforms__group-0.prql.snap} | 2 +- ...ests__prql__transforms__group-1.prql.snap} | 2 +- ...ests__prql__transforms__group-2.prql.snap} | 1 - ...tests__prql__transforms__join-0.prql.snap} | 2 +- ...tests__prql__transforms__join-1.prql.snap} | 2 +- ...tests__prql__transforms__join-2.prql.snap} | 2 +- ...sts__prql__transforms__select-0.prql.snap} | 2 +- ...sts__prql__transforms__select-1.prql.snap} | 2 +- ...sts__prql__transforms__select-2.prql.snap} | 2 +- ...sts__prql__transforms__select-3.prql.snap} | 2 +- ...ests__prql__transforms__select-4.prql.snap | 11 ++ ...ests__prql__transforms__select-5.prql.snap | 10 ++ ...ests__prql__transforms__select-6.prql.snap | 9 ++ ...tests__prql__transforms__sort-0.prql.snap} | 2 +- ...tests__prql__transforms__sort-1.prql.snap} | 2 +- ...tests__prql__transforms__sort-2.prql.snap} | 2 +- ...tests__prql__transforms__sort-3.prql.snap} | 1 - ...tests__prql__transforms__sort-4.prql.snap} | 2 +- ...tests__prql__transforms__sort-5.prql.snap} | 1 - ...tests__prql__transforms__take-0.prql.snap} | 2 +- ...tests__prql__transforms__take-1.prql.snap} | 1 - ...sts__prql__transforms__window-0.prql.snap} | 2 +- ...sts__prql__transforms__window-1.prql.snap} | 2 +- ...sts__prql__transforms__window-2.prql.snap} | 2 +- ...sts__prql__transforms__window-3.prql.snap} | 2 +- ...sts__prql__transforms__window-4.prql.snap} | 1 - prql-compiler/benches/bench.rs | 2 +- .../compile-files/queries/variables.prql | 0 prql-compiler/src/parser/mod.rs | 20 +--- ...er__parser__test__pipeline_parse_tree.snap | 2 +- 264 files changed, 222 insertions(+), 964 deletions(-) delete mode 100644 book/tests/prql/examples/cte-0.prql delete mode 100644 book/tests/prql/examples/employees-0.prql delete mode 100644 book/tests/prql/examples/employees-1.prql delete mode 100644 book/tests/prql/examples/employees-2.prql delete mode 100644 book/tests/prql/examples/employees-3.prql delete mode 100644 book/tests/prql/examples/list-equivalence-0.prql delete mode 100644 book/tests/prql/examples/list-equivalence-1.prql delete mode 100644 book/tests/prql/examples/list-equivalence-2.prql delete mode 100644 book/tests/prql/examples/list-equivalence-3.prql delete mode 100644 book/tests/prql/examples/misc-0.prql delete mode 100644 book/tests/prql/examples/misc-1.prql delete mode 100644 book/tests/prql/examples/variables-1.prql delete mode 100644 book/tests/prql/internals/functional-lang-0.prql delete mode 100644 book/tests/prql/internals/functional-lang-1.prql delete mode 100644 book/tests/prql/internals/functional-lang-2.prql delete mode 100644 book/tests/prql/internals/functional-lang-3.prql delete mode 100644 book/tests/prql/internals/name-resolving-0.prql delete mode 100644 book/tests/prql/internals/name-resolving-1.prql delete mode 100644 book/tests/prql/introduction-0.prql delete mode 100644 book/tests/prql/language-features/case-0.prql delete mode 100644 book/tests/prql/language-features/case-1.prql delete mode 100644 book/tests/prql/language-features/coalesce-0.prql delete mode 100644 book/tests/prql/language-features/dates-and-times-0.prql delete mode 100644 book/tests/prql/language-features/dates-and-times-1.prql delete mode 100644 book/tests/prql/language-features/dates-and-times-2.prql delete mode 100644 book/tests/prql/language-features/dates-and-times-3.prql delete mode 100644 book/tests/prql/language-features/distinct-0.prql delete mode 100644 book/tests/prql/language-features/distinct-1.prql delete mode 100644 book/tests/prql/language-features/distinct-2.prql delete mode 100644 book/tests/prql/language-features/f-strings-0.prql delete mode 100644 book/tests/prql/language-features/f-strings-1.prql delete mode 100644 book/tests/prql/language-features/null-0.prql delete mode 100644 book/tests/prql/language-features/ranges-0.prql delete mode 100644 book/tests/prql/language-features/ranges-1.prql delete mode 100644 book/tests/prql/language-features/s-strings-0.prql delete mode 100644 book/tests/prql/language-features/s-strings-1.prql delete mode 100644 book/tests/prql/language-features/s-strings-2.prql delete mode 100644 book/tests/prql/language-features/s-strings-3.prql delete mode 100644 book/tests/prql/language-features/s-strings-4.prql delete mode 100644 book/tests/prql/language-features/s-strings-5.prql delete mode 100644 book/tests/prql/language-features/s-strings-6.prql delete mode 100644 book/tests/prql/language-features/standard-library/README-0.prql delete mode 100644 book/tests/prql/language-features/standard-library/from-text-0.prql delete mode 100644 book/tests/prql/language-features/standard-library/from-text-1.prql delete mode 100644 book/tests/prql/language-features/standard-library/from-text-2.prql delete mode 100644 book/tests/prql/language-features/standard-library/loop-0.prql delete mode 100644 book/tests/prql/language-features/strings-0.prql delete mode 100644 book/tests/prql/language-features/strings-1.prql delete mode 100644 book/tests/prql/language-features/strings-2.prql delete mode 100644 book/tests/prql/language-features/strings-3.prql delete mode 100644 book/tests/prql/language-features/strings-4.prql delete mode 100644 book/tests/prql/language-features/strings-5.prql delete mode 100644 book/tests/prql/language-features/target-0.prql delete mode 100644 book/tests/prql/language-features/target-1.prql delete mode 100644 book/tests/prql/language-features/target-2.prql delete mode 100644 book/tests/prql/queries/functions-0.prql delete mode 100644 book/tests/prql/queries/functions-1.prql delete mode 100644 book/tests/prql/queries/functions-2.prql delete mode 100644 book/tests/prql/queries/functions-3.prql delete mode 100644 book/tests/prql/queries/functions-4.prql delete mode 100644 book/tests/prql/queries/functions-5.prql delete mode 100644 book/tests/prql/queries/pipelines-0.prql delete mode 100644 book/tests/prql/queries/pipelines-1.prql delete mode 100644 book/tests/prql/queries/pipelines-2.prql delete mode 100644 book/tests/prql/queries/variables-0.prql delete mode 100644 book/tests/prql/queries/variables-1.prql delete mode 100644 book/tests/prql/syntax-0.prql delete mode 100644 book/tests/prql/syntax-1.prql delete mode 100644 book/tests/prql/syntax-10.prql delete mode 100644 book/tests/prql/syntax-11.prql delete mode 100644 book/tests/prql/syntax-12.prql delete mode 100644 book/tests/prql/syntax-13.prql delete mode 100644 book/tests/prql/syntax-14.prql delete mode 100644 book/tests/prql/syntax-15.prql delete mode 100644 book/tests/prql/syntax-16.prql delete mode 100644 book/tests/prql/syntax-17.prql delete mode 100644 book/tests/prql/syntax-2.prql delete mode 100644 book/tests/prql/syntax-3.prql delete mode 100644 book/tests/prql/syntax-4.prql delete mode 100644 book/tests/prql/syntax-5.prql delete mode 100644 book/tests/prql/syntax-6.prql delete mode 100644 book/tests/prql/syntax-7.prql delete mode 100644 book/tests/prql/syntax-8.prql delete mode 100644 book/tests/prql/syntax-9.prql delete mode 100644 book/tests/prql/transforms/aggregate-0.prql delete mode 100644 book/tests/prql/transforms/aggregate-1.prql delete mode 100644 book/tests/prql/transforms/aggregate-2.prql delete mode 100644 book/tests/prql/transforms/append-0.prql delete mode 100644 book/tests/prql/transforms/append-1.prql delete mode 100644 book/tests/prql/transforms/append-2.prql delete mode 100644 book/tests/prql/transforms/derive-0.prql delete mode 100644 book/tests/prql/transforms/derive-1.prql delete mode 100644 book/tests/prql/transforms/filter-0.prql delete mode 100644 book/tests/prql/transforms/filter-1.prql delete mode 100644 book/tests/prql/transforms/filter-2.prql delete mode 100644 book/tests/prql/transforms/from-0.prql delete mode 100644 book/tests/prql/transforms/from-1.prql delete mode 100644 book/tests/prql/transforms/group-0.prql delete mode 100644 book/tests/prql/transforms/group-1.prql delete mode 100644 book/tests/prql/transforms/group-2.prql delete mode 100644 book/tests/prql/transforms/join-0.prql delete mode 100644 book/tests/prql/transforms/join-1.prql delete mode 100644 book/tests/prql/transforms/join-2.prql delete mode 100644 book/tests/prql/transforms/select-0.prql delete mode 100644 book/tests/prql/transforms/select-1.prql delete mode 100644 book/tests/prql/transforms/select-2.prql delete mode 100644 book/tests/prql/transforms/select-3.prql delete mode 100644 book/tests/prql/transforms/select-4.prql delete mode 100644 book/tests/prql/transforms/select-5.prql delete mode 100644 book/tests/prql/transforms/select-6.prql delete mode 100644 book/tests/prql/transforms/sort-0.prql delete mode 100644 book/tests/prql/transforms/sort-1.prql delete mode 100644 book/tests/prql/transforms/sort-2.prql delete mode 100644 book/tests/prql/transforms/sort-3.prql delete mode 100644 book/tests/prql/transforms/sort-4.prql delete mode 100644 book/tests/prql/transforms/sort-5.prql delete mode 100644 book/tests/prql/transforms/take-0.prql delete mode 100644 book/tests/prql/transforms/take-1.prql delete mode 100644 book/tests/prql/transforms/window-0.prql delete mode 100644 book/tests/prql/transforms/window-1.prql delete mode 100644 book/tests/prql/transforms/window-2.prql delete mode 100644 book/tests/prql/transforms/window-3.prql delete mode 100644 book/tests/prql/transforms/window-4.prql delete mode 100644 book/tests/snapshots/snapshot__@language-features__s-strings-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@language-features__target-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@language-features__target-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@queries__functions-0.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@queries__functions-1.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@queries__functions-2.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@queries__functions-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@syntax-6.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@transforms__select-4.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@transforms__select-5.prql.snap delete mode 100644 book/tests/snapshots/snapshot__@transforms__select-6.prql.snap rename book/tests/snapshots/{snapshot__@examples__cte-0.prql.snap => snapshot__tests__prql__examples__cte-0.prql.snap} (56%) rename book/tests/snapshots/{snapshot__@examples__employees-0.prql.snap => snapshot__tests__prql__examples__employees-0.prql.snap} (94%) rename book/tests/snapshots/{snapshot__@examples__employees-1.prql.snap => snapshot__tests__prql__examples__employees-1.prql.snap} (95%) rename book/tests/snapshots/{snapshot__@examples__employees-2.prql.snap => snapshot__tests__prql__examples__employees-2.prql.snap} (96%) rename book/tests/snapshots/{snapshot__@examples__employees-3.prql.snap => snapshot__tests__prql__examples__employees-3.prql.snap} (56%) rename book/tests/snapshots/{snapshot__@examples__list-equivalence-0.prql.snap => snapshot__tests__prql__examples__list-equivalence-0.prql.snap} (65%) rename book/tests/snapshots/{snapshot__@examples__list-equivalence-1.prql.snap => snapshot__tests__prql__examples__list-equivalence-1.prql.snap} (66%) rename book/tests/snapshots/{snapshot__@transforms__derive-1.prql.snap => snapshot__tests__prql__examples__list-equivalence-2.prql.snap} (84%) rename book/tests/snapshots/{snapshot__@examples__list-equivalence-3.prql.snap => snapshot__tests__prql__examples__list-equivalence-3.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@examples__misc-0.prql.snap => snapshot__tests__prql__examples__misc-0.prql.snap} (96%) rename book/tests/snapshots/{snapshot__@examples__misc-1.prql.snap => snapshot__tests__prql__examples__misc-1.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@examples__variables-0.prql.snap => snapshot__tests__prql__examples__variables-0.prql.snap} (95%) rename book/tests/snapshots/{snapshot__@examples__variables-1.prql.snap => snapshot__tests__prql__examples__variables-1.prql.snap} (94%) rename book/tests/snapshots/{snapshot__@internals__functional-lang-0.prql.snap => snapshot__tests__prql__internals__functional-lang-0.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@internals__functional-lang-1.prql.snap => snapshot__tests__prql__internals__functional-lang-1.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@internals__functional-lang-2.prql.snap => snapshot__tests__prql__internals__functional-lang-2.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@internals__functional-lang-3.prql.snap => snapshot__tests__prql__internals__functional-lang-3.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@syntax-4.prql.snap => snapshot__tests__prql__internals__name-resolving-0.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@internals__name-resolving-1.prql.snap => snapshot__tests__prql__internals__name-resolving-1.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@introduction-0.prql.snap => snapshot__tests__prql__introduction-0.prql.snap} (97%) rename book/tests/snapshots/{snapshot__@language-features__case-0.prql.snap => snapshot__tests__prql__language-features__case-0.prql.snap} (85%) rename book/tests/snapshots/{snapshot__@language-features__case-1.prql.snap => snapshot__tests__prql__language-features__case-1.prql.snap} (86%) rename book/tests/snapshots/{snapshot__@language-features__coalesce-0.prql.snap => snapshot__tests__prql__language-features__coalesce-0.prql.snap} (68%) rename book/tests/snapshots/{snapshot__@language-features__dates-and-times-0.prql.snap => snapshot__tests__prql__language-features__dates-and-times-0.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@language-features__dates-and-times-1.prql.snap => snapshot__tests__prql__language-features__dates-and-times-1.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@language-features__dates-and-times-2.prql.snap => snapshot__tests__prql__language-features__dates-and-times-2.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@language-features__dates-and-times-3.prql.snap => snapshot__tests__prql__language-features__dates-and-times-3.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@language-features__distinct-0.prql.snap => snapshot__tests__prql__language-features__distinct-0.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@language-features__distinct-1.prql.snap => snapshot__tests__prql__language-features__distinct-1.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@language-features__distinct-2.prql.snap => snapshot__tests__prql__language-features__distinct-2.prql.snap} (85%) rename book/tests/snapshots/{snapshot__@language-features__f-strings-0.prql.snap => snapshot__tests__prql__language-features__f-strings-0.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@language-features__f-strings-1.prql.snap => snapshot__tests__prql__language-features__f-strings-1.prql.snap} (79%) rename book/tests/snapshots/{snapshot__@language-features__null-0.prql.snap => snapshot__tests__prql__language-features__null-0.prql.snap} (78%) rename book/tests/snapshots/{snapshot__@language-features__ranges-0.prql.snap => snapshot__tests__prql__language-features__ranges-0.prql.snap} (85%) rename book/tests/snapshots/{snapshot__@transforms__take-1.prql.snap => snapshot__tests__prql__language-features__ranges-1.prql.snap} (79%) rename book/tests/snapshots/{snapshot__@language-features__s-strings-0.prql.snap => snapshot__tests__prql__language-features__s-strings-0.prql.snap} (70%) rename book/tests/snapshots/{snapshot__@language-features__s-strings-1.prql.snap => snapshot__tests__prql__language-features__s-strings-1.prql.snap} (68%) rename book/tests/snapshots/{snapshot__@language-features__s-strings-2.prql.snap => snapshot__tests__prql__language-features__s-strings-2.prql.snap} (85%) rename book/tests/snapshots/{snapshot__@language-features__s-strings-3.prql.snap => snapshot__tests__prql__language-features__s-strings-3.prql.snap} (87%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap rename book/tests/snapshots/{snapshot__@language-features__s-strings-5.prql.snap => snapshot__tests__prql__language-features__s-strings-5.prql.snap} (80%) rename book/tests/snapshots/{snapshot__@language-features__s-strings-6.prql.snap => snapshot__tests__prql__language-features__s-strings-6.prql.snap} (81%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__README-0.prql.snap => snapshot__tests__prql__language-features__standard-library__README-0.prql.snap} (84%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-0.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-1.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__from-text-2.prql.snap => snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap} (91%) rename book/tests/snapshots/{snapshot__@language-features__standard-library__loop-0.prql.snap => snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap} (86%) rename book/tests/snapshots/{snapshot__@language-features__strings-0.prql.snap => snapshot__tests__prql__language-features__strings-0.prql.snap} (69%) rename book/tests/snapshots/{snapshot__@language-features__strings-1.prql.snap => snapshot__tests__prql__language-features__strings-1.prql.snap} (69%) rename book/tests/snapshots/{snapshot__@language-features__strings-2.prql.snap => snapshot__tests__prql__language-features__strings-2.prql.snap} (70%) rename book/tests/snapshots/{snapshot__@language-features__strings-3.prql.snap => snapshot__tests__prql__language-features__strings-3.prql.snap} (73%) rename book/tests/snapshots/{snapshot__@language-features__strings-4.prql.snap => snapshot__tests__prql__language-features__strings-4.prql.snap} (75%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap rename book/tests/snapshots/{snapshot__@language-features__target-0.prql.snap => snapshot__tests__prql__language-features__target-0.prql.snap} (74%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap rename book/tests/snapshots/{snapshot__@queries__functions-3.prql.snap => snapshot__tests__prql__queries__functions-3.prql.snap} (81%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap rename book/tests/snapshots/{snapshot__@queries__functions-5.prql.snap => snapshot__tests__prql__queries__functions-5.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@transforms__from-0.prql.snap => snapshot__tests__prql__queries__pipelines-0.prql.snap} (65%) rename book/tests/snapshots/{snapshot__@queries__pipelines-1.prql.snap => snapshot__tests__prql__queries__pipelines-1.prql.snap} (77%) rename book/tests/snapshots/{snapshot__@queries__pipelines-2.prql.snap => snapshot__tests__prql__queries__pipelines-2.prql.snap} (90%) rename book/tests/snapshots/{snapshot__@queries__variables-0.prql.snap => snapshot__tests__prql__queries__variables-0.prql.snap} (88%) rename book/tests/snapshots/{snapshot__@queries__variables-1.prql.snap => snapshot__tests__prql__queries__variables-1.prql.snap} (88%) rename book/tests/snapshots/{snapshot__@syntax-0.prql.snap => snapshot__tests__prql__syntax-0.prql.snap} (83%) rename book/tests/snapshots/{snapshot__@syntax-1.prql.snap => snapshot__tests__prql__syntax-1.prql.snap} (83%) rename book/tests/snapshots/{snapshot__@syntax-10.prql.snap => snapshot__tests__prql__syntax-10.prql.snap} (78%) rename book/tests/snapshots/{snapshot__@syntax-11.prql.snap => snapshot__tests__prql__syntax-11.prql.snap} (78%) rename book/tests/snapshots/{snapshot__@syntax-12.prql.snap => snapshot__tests__prql__syntax-12.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@syntax-13.prql.snap => snapshot__tests__prql__syntax-13.prql.snap} (89%) rename book/tests/snapshots/{snapshot__@syntax-14.prql.snap => snapshot__tests__prql__syntax-14.prql.snap} (71%) rename book/tests/snapshots/{snapshot__@syntax-15.prql.snap => snapshot__tests__prql__syntax-15.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@syntax-16.prql.snap => snapshot__tests__prql__syntax-16.prql.snap} (81%) rename book/tests/snapshots/{snapshot__@syntax-17.prql.snap => snapshot__tests__prql__syntax-17.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@syntax-2.prql.snap => snapshot__tests__prql__syntax-2.prql.snap} (85%) rename book/tests/snapshots/{snapshot__@syntax-3.prql.snap => snapshot__tests__prql__syntax-3.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@transforms__select-2.prql.snap => snapshot__tests__prql__syntax-4.prql.snap} (70%) rename book/tests/snapshots/{snapshot__@syntax-5.prql.snap => snapshot__tests__prql__syntax-5.prql.snap} (89%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap rename book/tests/snapshots/{snapshot__@syntax-7.prql.snap => snapshot__tests__prql__syntax-7.prql.snap} (89%) rename book/tests/snapshots/{snapshot__@syntax-8.prql.snap => snapshot__tests__prql__syntax-8.prql.snap} (86%) rename book/tests/snapshots/{snapshot__@syntax-9.prql.snap => snapshot__tests__prql__syntax-9.prql.snap} (79%) rename book/tests/snapshots/{snapshot__@transforms__aggregate-0.prql.snap => snapshot__tests__prql__transforms__aggregate-0.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@transforms__group-0.prql.snap => snapshot__tests__prql__transforms__aggregate-1.prql.snap} (83%) rename book/tests/snapshots/{snapshot__@transforms__aggregate-2.prql.snap => snapshot__tests__prql__transforms__aggregate-2.prql.snap} (74%) rename book/tests/snapshots/{snapshot__@transforms__append-0.prql.snap => snapshot__tests__prql__transforms__append-0.prql.snap} (75%) rename book/tests/snapshots/{snapshot__@transforms__append-1.prql.snap => snapshot__tests__prql__transforms__append-1.prql.snap} (76%) rename book/tests/snapshots/{snapshot__@transforms__append-2.prql.snap => snapshot__tests__prql__transforms__append-2.prql.snap} (77%) rename book/tests/snapshots/{snapshot__@transforms__derive-0.prql.snap => snapshot__tests__prql__transforms__derive-0.prql.snap} (77%) rename book/tests/snapshots/{snapshot__@examples__list-equivalence-2.prql.snap => snapshot__tests__prql__transforms__derive-1.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@transforms__filter-0.prql.snap => snapshot__tests__prql__transforms__filter-0.prql.snap} (71%) rename book/tests/snapshots/{snapshot__@transforms__filter-1.prql.snap => snapshot__tests__prql__transforms__filter-1.prql.snap} (77%) rename book/tests/snapshots/{snapshot__@transforms__filter-2.prql.snap => snapshot__tests__prql__transforms__filter-2.prql.snap} (74%) rename book/tests/snapshots/{snapshot__@queries__pipelines-0.prql.snap => snapshot__tests__prql__transforms__from-0.prql.snap} (64%) rename book/tests/snapshots/{snapshot__@transforms__from-1.prql.snap => snapshot__tests__prql__transforms__from-1.prql.snap} (72%) rename book/tests/snapshots/{snapshot__@transforms__aggregate-1.prql.snap => snapshot__tests__prql__transforms__group-0.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@transforms__group-1.prql.snap => snapshot__tests__prql__transforms__group-1.prql.snap} (74%) rename book/tests/snapshots/{snapshot__@transforms__group-2.prql.snap => snapshot__tests__prql__transforms__group-2.prql.snap} (87%) rename book/tests/snapshots/{snapshot__@transforms__join-0.prql.snap => snapshot__tests__prql__transforms__join-0.prql.snap} (83%) rename book/tests/snapshots/{snapshot__@transforms__join-1.prql.snap => snapshot__tests__prql__transforms__join-1.prql.snap} (81%) rename book/tests/snapshots/{snapshot__@transforms__join-2.prql.snap => snapshot__tests__prql__transforms__join-2.prql.snap} (80%) rename book/tests/snapshots/{snapshot__@transforms__select-0.prql.snap => snapshot__tests__prql__transforms__select-0.prql.snap} (77%) rename book/tests/snapshots/{snapshot__@transforms__select-1.prql.snap => snapshot__tests__prql__transforms__select-1.prql.snap} (83%) rename book/tests/snapshots/{snapshot__@internals__name-resolving-0.prql.snap => snapshot__tests__prql__transforms__select-2.prql.snap} (67%) rename book/tests/snapshots/{snapshot__@transforms__select-3.prql.snap => snapshot__tests__prql__transforms__select-3.prql.snap} (75%) create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap create mode 100644 book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap rename book/tests/snapshots/{snapshot__@transforms__sort-0.prql.snap => snapshot__tests__prql__transforms__sort-0.prql.snap} (70%) rename book/tests/snapshots/{snapshot__@transforms__sort-1.prql.snap => snapshot__tests__prql__transforms__sort-1.prql.snap} (71%) rename book/tests/snapshots/{snapshot__@transforms__sort-2.prql.snap => snapshot__tests__prql__transforms__sort-2.prql.snap} (76%) rename book/tests/snapshots/{snapshot__@transforms__sort-3.prql.snap => snapshot__tests__prql__transforms__sort-3.prql.snap} (79%) rename book/tests/snapshots/{snapshot__@transforms__sort-4.prql.snap => snapshot__tests__prql__transforms__sort-4.prql.snap} (81%) rename book/tests/snapshots/{snapshot__@transforms__sort-5.prql.snap => snapshot__tests__prql__transforms__sort-5.prql.snap} (86%) rename book/tests/snapshots/{snapshot__@transforms__take-0.prql.snap => snapshot__tests__prql__transforms__take-0.prql.snap} (69%) rename book/tests/snapshots/{snapshot__@language-features__ranges-1.prql.snap => snapshot__tests__prql__transforms__take-1.prql.snap} (76%) rename book/tests/snapshots/{snapshot__@transforms__window-0.prql.snap => snapshot__tests__prql__transforms__window-0.prql.snap} (86%) rename book/tests/snapshots/{snapshot__@transforms__window-1.prql.snap => snapshot__tests__prql__transforms__window-1.prql.snap} (91%) rename book/tests/snapshots/{snapshot__@transforms__window-2.prql.snap => snapshot__tests__prql__transforms__window-2.prql.snap} (82%) rename book/tests/snapshots/{snapshot__@transforms__window-3.prql.snap => snapshot__tests__prql__transforms__window-3.prql.snap} (84%) rename book/tests/snapshots/{snapshot__@transforms__window-4.prql.snap => snapshot__tests__prql__transforms__window-4.prql.snap} (83%) rename book/tests/prql/examples/variables-0.prql => prql-compiler/examples/compile-files/queries/variables.prql (100%) diff --git a/book/tests/prql/examples/cte-0.prql b/book/tests/prql/examples/cte-0.prql deleted file mode 100644 index e1f990d5a366..000000000000 --- a/book/tests/prql/examples/cte-0.prql +++ /dev/null @@ -1,18 +0,0 @@ -# Can't yet format & compile - -let newest_employees = ( - from employees - sort tenure - take 50 -) - -let average_salaries = ( - from salaries - group country ( - aggregate average_country_salary = (average salary) - ) -) - -from newest_employees -join average_salaries [==country] -select [name, salary, average_country_salary] diff --git a/book/tests/prql/examples/employees-0.prql b/book/tests/prql/examples/employees-0.prql deleted file mode 100644 index 78e6ad12a5d6..000000000000 --- a/book/tests/prql/examples/employees-0.prql +++ /dev/null @@ -1,11 +0,0 @@ -from salaries -group [emp_no] ( - aggregate [emp_salary = average salary] -) -join t=titles [==emp_no] -join dept_emp side:left [==emp_no] -group [dept_emp.dept_no, t.title] ( - aggregate [avg_salary = average emp_salary] -) -join departments [==dept_no] -select [dept_name, title, avg_salary] diff --git a/book/tests/prql/examples/employees-1.prql b/book/tests/prql/examples/employees-1.prql deleted file mode 100644 index a568c2949aa9..000000000000 --- a/book/tests/prql/examples/employees-1.prql +++ /dev/null @@ -1,16 +0,0 @@ -from e=employees -join salaries [==emp_no] -group [e.emp_no, e.gender] ( - aggregate [ - emp_salary = average salaries.salary - ] -) -join de=dept_emp [==emp_no] side:left -group [de.dept_no, gender] ( - aggregate [ - salary_avg = average emp_salary, - salary_sd = stddev emp_salary, - ] -) -join departments [==dept_no] -select [dept_name, gender, salary_avg, salary_sd] diff --git a/book/tests/prql/examples/employees-2.prql b/book/tests/prql/examples/employees-2.prql deleted file mode 100644 index 6164d8077a4a..000000000000 --- a/book/tests/prql/examples/employees-2.prql +++ /dev/null @@ -1,21 +0,0 @@ -from e=employees -join salaries [==emp_no] -group [e.emp_no, e.gender] ( - aggregate [ - emp_salary = average salaries.salary - ] -) -join de=dept_emp [==emp_no] -join dm=dept_manager [ - (dm.dept_no == de.dept_no) and s"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)" -] -group [dm.emp_no, gender] ( - aggregate [ - salary_avg = average emp_salary, - salary_sd = stddev emp_salary - ] -) -derive mng_no = emp_no -join managers=employees [==emp_no] -derive mng_name = s"managers.first_name || ' ' || managers.last_name" -select [mng_name, managers.gender, salary_avg, salary_sd] diff --git a/book/tests/prql/examples/employees-3.prql b/book/tests/prql/examples/employees-3.prql deleted file mode 100644 index 41950b3019cb..000000000000 --- a/book/tests/prql/examples/employees-3.prql +++ /dev/null @@ -1,13 +0,0 @@ -# Can't yet format & compile - -from de=dept_emp -join s=salaries side:left [ - (s.emp_no == de.emp_no), - s"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})" -] -group [de.emp_no, de.dept_no] ( - aggregate salary = (average s.salary) -) -join employees [==emp_no] -join titles [==emp_no] -select [dept_no, salary, employees.gender, titles.title] diff --git a/book/tests/prql/examples/list-equivalence-0.prql b/book/tests/prql/examples/list-equivalence-0.prql deleted file mode 100644 index ce126ab4c459..000000000000 --- a/book/tests/prql/examples/list-equivalence-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select salary diff --git a/book/tests/prql/examples/list-equivalence-1.prql b/book/tests/prql/examples/list-equivalence-1.prql deleted file mode 100644 index 3b89f4256948..000000000000 --- a/book/tests/prql/examples/list-equivalence-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select [salary] diff --git a/book/tests/prql/examples/list-equivalence-2.prql b/book/tests/prql/examples/list-equivalence-2.prql deleted file mode 100644 index f49937a6bfc6..000000000000 --- a/book/tests/prql/examples/list-equivalence-2.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost -] diff --git a/book/tests/prql/examples/list-equivalence-3.prql b/book/tests/prql/examples/list-equivalence-3.prql deleted file mode 100644 index f539c32d0469..000000000000 --- a/book/tests/prql/examples/list-equivalence-3.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -derive gross_salary = salary + payroll_tax -derive gross_cost = gross_salary + benefits_cost diff --git a/book/tests/prql/examples/misc-0.prql b/book/tests/prql/examples/misc-0.prql deleted file mode 100644 index e29792bf8486..000000000000 --- a/book/tests/prql/examples/misc-0.prql +++ /dev/null @@ -1,15 +0,0 @@ -# TODO: this table should have a column `part` with values 1..5, -# but such data declaration is not yet supported, see #286 -let parts = ( - from seq_1_to_5 -) - -from pl=prospect_lists_prospects -filter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e' -join a=accounts [a.id == pl.related_id] -join er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1'] -join ea=email_addresses [ea.id == er.email_address_id] -select ea.email_address -derive prefix = s"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')" -derive stub = s"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)" -select [email_address, stub] diff --git a/book/tests/prql/examples/misc-1.prql b/book/tests/prql/examples/misc-1.prql deleted file mode 100644 index 7fc71d21985a..000000000000 --- a/book/tests/prql/examples/misc-1.prql +++ /dev/null @@ -1,7 +0,0 @@ -from club_ratings -filter rating != null -# TODO: this is real ugly. `average rating` should not require parenthesis -# TODO: why cannot we put comments in group's pipeline? -group year ( - derive [rating_norm = rating - (average rating) / (stddev rating)] -) diff --git a/book/tests/prql/examples/variables-1.prql b/book/tests/prql/examples/variables-1.prql deleted file mode 100644 index e0a4b962bb21..000000000000 --- a/book/tests/prql/examples/variables-1.prql +++ /dev/null @@ -1,15 +0,0 @@ -from employees -group [emp_no] ( - aggregate [ - emp_salary = average salary # average salary resolves to "AVG(salary)" (from stdlib) - ] -) -join titles [==emp_no] -group [title] ( - aggregate [ - avg_salary = average emp_salary - ] -) -select salary_k = avg_salary / 1000 # avg_salary should resolve to "AVG(emp_salary)" -take 10 # induces new SELECT -derive salary = salary_k * 1000 # salary_k should not resolve to "avg_salary / 1000" diff --git a/book/tests/prql/internals/functional-lang-0.prql b/book/tests/prql/internals/functional-lang-0.prql deleted file mode 100644 index 4b2a2780ffbd..000000000000 --- a/book/tests/prql/internals/functional-lang-0.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -filter age > 50 -sort name diff --git a/book/tests/prql/internals/functional-lang-1.prql b/book/tests/prql/internals/functional-lang-1.prql deleted file mode 100644 index b73c3e233564..000000000000 --- a/book/tests/prql/internals/functional-lang-1.prql +++ /dev/null @@ -1 +0,0 @@ -from employees | filter age > 50 | sort name diff --git a/book/tests/prql/internals/functional-lang-2.prql b/book/tests/prql/internals/functional-lang-2.prql deleted file mode 100644 index d2277f25634f..000000000000 --- a/book/tests/prql/internals/functional-lang-2.prql +++ /dev/null @@ -1 +0,0 @@ -filter age > 50 (from employees) | sort name diff --git a/book/tests/prql/internals/functional-lang-3.prql b/book/tests/prql/internals/functional-lang-3.prql deleted file mode 100644 index 40177f3353f9..000000000000 --- a/book/tests/prql/internals/functional-lang-3.prql +++ /dev/null @@ -1 +0,0 @@ -sort name (filter age > 50 (from employees)) diff --git a/book/tests/prql/internals/name-resolving-0.prql b/book/tests/prql/internals/name-resolving-0.prql deleted file mode 100644 index ec44dd3366e8..000000000000 --- a/book/tests/prql/internals/name-resolving-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select first_name diff --git a/book/tests/prql/internals/name-resolving-1.prql b/book/tests/prql/internals/name-resolving-1.prql deleted file mode 100644 index 9a0ec0db2a53..000000000000 --- a/book/tests/prql/internals/name-resolving-1.prql +++ /dev/null @@ -1,4 +0,0 @@ -from employees -derive [first_name, dept_id] -join d=departments [==dept_id] -select [first_name, d.title] diff --git a/book/tests/prql/introduction-0.prql b/book/tests/prql/introduction-0.prql deleted file mode 100644 index 9a6969d51382..000000000000 --- a/book/tests/prql/introduction-0.prql +++ /dev/null @@ -1,18 +0,0 @@ -from employees -filter start_date > @2021-01-01 # Clear date syntax -derive [ # `derive` adds columns / variables - gross_salary = salary + (tax ?? 0), # Terse coalesce - gross_cost = gross_salary + benefits_cost, # Variables can use other variables -] -filter gross_cost > 0 -group [title, country] ( # `group` runs a pipeline over each group - aggregate [ # `aggregate` reduces each group to a value - average gross_salary, - sum_gross_cost = sum gross_cost, # `=` sets a column name - ] -) -filter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING` -derive id = f"{title}_{country}" # F-strings like Python -derive country_code = s"LEFT(country, 2)" # S-strings allow using SQL as an escape hatch -sort [sum_gross_cost, -country] # `-country` means descending order -take 1..20 # Range expressions (also valid here as `take 20`) diff --git a/book/tests/prql/language-features/case-0.prql b/book/tests/prql/language-features/case-0.prql deleted file mode 100644 index 6e6f269a5bed..000000000000 --- a/book/tests/prql/language-features/case-0.prql +++ /dev/null @@ -1,7 +0,0 @@ -# Can't yet format & compile - -from employees -derive distance = case [ - city == "Calgary" => 0, - city == "Edmonton" => 300, -] diff --git a/book/tests/prql/language-features/case-1.prql b/book/tests/prql/language-features/case-1.prql deleted file mode 100644 index 78ad16893e76..000000000000 --- a/book/tests/prql/language-features/case-1.prql +++ /dev/null @@ -1,8 +0,0 @@ -# Can't yet format & compile - -from employees -derive distance = case [ - city == "Calgary" => 0, - city == "Edmonton" => 300, - true => "Unknown", -] diff --git a/book/tests/prql/language-features/coalesce-0.prql b/book/tests/prql/language-features/coalesce-0.prql deleted file mode 100644 index 86640dac1782..000000000000 --- a/book/tests/prql/language-features/coalesce-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from orders -derive amount ?? 0 diff --git a/book/tests/prql/language-features/dates-and-times-0.prql b/book/tests/prql/language-features/dates-and-times-0.prql deleted file mode 100644 index 9bc1efe5bcae..000000000000 --- a/book/tests/prql/language-features/dates-and-times-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -derive age_at_year_end = (@2022-12-31 - dob) diff --git a/book/tests/prql/language-features/dates-and-times-1.prql b/book/tests/prql/language-features/dates-and-times-1.prql deleted file mode 100644 index 83107818e462..000000000000 --- a/book/tests/prql/language-features/dates-and-times-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from orders -derive should_have_shipped_today = (order_time < @08:30) diff --git a/book/tests/prql/language-features/dates-and-times-2.prql b/book/tests/prql/language-features/dates-and-times-2.prql deleted file mode 100644 index 9efc7883716b..000000000000 --- a/book/tests/prql/language-features/dates-and-times-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from commits -derive first_prql_commit = @2020-01-01T13:19:55-08:00 diff --git a/book/tests/prql/language-features/dates-and-times-3.prql b/book/tests/prql/language-features/dates-and-times-3.prql deleted file mode 100644 index a22537d03c8e..000000000000 --- a/book/tests/prql/language-features/dates-and-times-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from projects -derive first_check_in = start + 10days diff --git a/book/tests/prql/language-features/distinct-0.prql b/book/tests/prql/language-features/distinct-0.prql deleted file mode 100644 index ed8a37d174b7..000000000000 --- a/book/tests/prql/language-features/distinct-0.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -select department -group department ( - take 1 -) diff --git a/book/tests/prql/language-features/distinct-1.prql b/book/tests/prql/language-features/distinct-1.prql deleted file mode 100644 index 70764167a1ab..000000000000 --- a/book/tests/prql/language-features/distinct-1.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -select department -group department (take 1) diff --git a/book/tests/prql/language-features/distinct-2.prql b/book/tests/prql/language-features/distinct-2.prql deleted file mode 100644 index f224527e39e3..000000000000 --- a/book/tests/prql/language-features/distinct-2.prql +++ /dev/null @@ -1,6 +0,0 @@ -# youngest employee from each department -from employees -group department ( - sort age - take 1 -) diff --git a/book/tests/prql/language-features/f-strings-0.prql b/book/tests/prql/language-features/f-strings-0.prql deleted file mode 100644 index 5916b81e2865..000000000000 --- a/book/tests/prql/language-features/f-strings-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select full_name = f"{first_name} {last_name}" diff --git a/book/tests/prql/language-features/f-strings-1.prql b/book/tests/prql/language-features/f-strings-1.prql deleted file mode 100644 index 6e8e37a471a0..000000000000 --- a/book/tests/prql/language-features/f-strings-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from web -select url = f"http{tls}://www.{domain}.{tld}/{page}" diff --git a/book/tests/prql/language-features/null-0.prql b/book/tests/prql/language-features/null-0.prql deleted file mode 100644 index 59e730264398..000000000000 --- a/book/tests/prql/language-features/null-0.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -filter first_name == null -filter null != last_name diff --git a/book/tests/prql/language-features/ranges-0.prql b/book/tests/prql/language-features/ranges-0.prql deleted file mode 100644 index e3eea68afafb..000000000000 --- a/book/tests/prql/language-features/ranges-0.prql +++ /dev/null @@ -1,4 +0,0 @@ -from events -filter (created_at | in @1776-07-04..@1787-09-17) -filter (magnitude | in 50..100) -derive is_northern = (latitude | in 0..) diff --git a/book/tests/prql/language-features/ranges-1.prql b/book/tests/prql/language-features/ranges-1.prql deleted file mode 100644 index fcf59ae0e31c..000000000000 --- a/book/tests/prql/language-features/ranges-1.prql +++ /dev/null @@ -1,3 +0,0 @@ -from orders -sort [-value, created_at] -take 101..110 diff --git a/book/tests/prql/language-features/s-strings-0.prql b/book/tests/prql/language-features/s-strings-0.prql deleted file mode 100644 index 58aeda7a72fc..000000000000 --- a/book/tests/prql/language-features/s-strings-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select db_version = s"version()" diff --git a/book/tests/prql/language-features/s-strings-1.prql b/book/tests/prql/language-features/s-strings-1.prql deleted file mode 100644 index 00a434b7d91c..000000000000 --- a/book/tests/prql/language-features/s-strings-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -aggregate [average salary] diff --git a/book/tests/prql/language-features/s-strings-2.prql b/book/tests/prql/language-features/s-strings-2.prql deleted file mode 100644 index 60f8731d9746..000000000000 --- a/book/tests/prql/language-features/s-strings-2.prql +++ /dev/null @@ -1,7 +0,0 @@ -from de=dept_emp -join s=salaries side:left [ - (s.emp_no == de.emp_no), - s"""({s.from_date}, {s.to_date}) - OVERLAPS - ({de.from_date}, {de.to_date})""" -] diff --git a/book/tests/prql/language-features/s-strings-3.prql b/book/tests/prql/language-features/s-strings-3.prql deleted file mode 100644 index bca882d48c32..000000000000 --- a/book/tests/prql/language-features/s-strings-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from s"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC" -join s = s"SELECT * FROM salaries" [==id] diff --git a/book/tests/prql/language-features/s-strings-4.prql b/book/tests/prql/language-features/s-strings-4.prql deleted file mode 100644 index 39a20f5bae9a..000000000000 --- a/book/tests/prql/language-features/s-strings-4.prql +++ /dev/null @@ -1,6 +0,0 @@ -# Can't yet format & compile - -from employees -derive [ - has_valid_title = s"regexp_contains(title, '([a-z0-9]*-){{2,}}')" -] diff --git a/book/tests/prql/language-features/s-strings-5.prql b/book/tests/prql/language-features/s-strings-5.prql deleted file mode 100644 index 58a535b9d514..000000000000 --- a/book/tests/prql/language-features/s-strings-5.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -derive [ - gross_salary = salary + benefits, - daily_rate = s"{gross_salary} / 365" -] diff --git a/book/tests/prql/language-features/s-strings-6.prql b/book/tests/prql/language-features/s-strings-6.prql deleted file mode 100644 index e8ba3a5b3cf2..000000000000 --- a/book/tests/prql/language-features/s-strings-6.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -derive [ - gross_salary = salary + benefits, - daily_rate = s"({gross_salary}) / 365" -] diff --git a/book/tests/prql/language-features/standard-library/README-0.prql b/book/tests/prql/language-features/standard-library/README-0.prql deleted file mode 100644 index 1a362939ebc3..000000000000 --- a/book/tests/prql/language-features/standard-library/README-0.prql +++ /dev/null @@ -1,6 +0,0 @@ -from employees -derive [ - gross_salary = (salary + payroll_tax | as int), - gross_salary_rounded = (gross_salary | round 0), - time = s"NOW()", # an s-string, given no `now` function exists in PRQL -] diff --git a/book/tests/prql/language-features/standard-library/from-text-0.prql b/book/tests/prql/language-features/standard-library/from-text-0.prql deleted file mode 100644 index cc3dd3464e80..000000000000 --- a/book/tests/prql/language-features/standard-library/from-text-0.prql +++ /dev/null @@ -1,9 +0,0 @@ -from_text """ -a,b,c -1,2,3 -4,5,6 -""" -derive [ - d = b + c, - answer = 20 * 2 + 2, -] diff --git a/book/tests/prql/language-features/standard-library/from-text-1.prql b/book/tests/prql/language-features/standard-library/from-text-1.prql deleted file mode 100644 index 588486d405c0..000000000000 --- a/book/tests/prql/language-features/standard-library/from-text-1.prql +++ /dev/null @@ -1,10 +0,0 @@ -let temp_format_lookup = from_text format:csv """ -country_code,format -uk,C -us,F -lr,F -de,C -""" - -from temperatures -join temp_format_lookup [==country_code] diff --git a/book/tests/prql/language-features/standard-library/from-text-2.prql b/book/tests/prql/language-features/standard-library/from-text-2.prql deleted file mode 100644 index be9c55da39b9..000000000000 --- a/book/tests/prql/language-features/standard-library/from-text-2.prql +++ /dev/null @@ -1,16 +0,0 @@ -let x = from_text format:json """{ - "columns": ["a", "b", "c"], - "data": [ - [1, "x", false], - [4, "y", null] - ] -}""" - -let y = from_text format:json """ - [ - {"a": 1, "m": "5"}, - {"a": 4, "n": "6"} - ] -""" - -from x | join y [==a] diff --git a/book/tests/prql/language-features/standard-library/loop-0.prql b/book/tests/prql/language-features/standard-library/loop-0.prql deleted file mode 100644 index 5dccfdba14ae..000000000000 --- a/book/tests/prql/language-features/standard-library/loop-0.prql +++ /dev/null @@ -1,7 +0,0 @@ -from_text format:json '[{"n": 1 }]' -loop ( - filter n<4 - select n = n+1 -) - -# returns [1, 2, 3, 4] diff --git a/book/tests/prql/language-features/strings-0.prql b/book/tests/prql/language-features/strings-0.prql deleted file mode 100644 index 294ce2444927..000000000000 --- a/book/tests/prql/language-features/strings-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select x = "hello world" diff --git a/book/tests/prql/language-features/strings-1.prql b/book/tests/prql/language-features/strings-1.prql deleted file mode 100644 index 3591aa871e1b..000000000000 --- a/book/tests/prql/language-features/strings-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select x = 'hello world' diff --git a/book/tests/prql/language-features/strings-2.prql b/book/tests/prql/language-features/strings-2.prql deleted file mode 100644 index d91760c6bcd4..000000000000 --- a/book/tests/prql/language-features/strings-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select x = '"hello world"' diff --git a/book/tests/prql/language-features/strings-3.prql b/book/tests/prql/language-features/strings-3.prql deleted file mode 100644 index be93bbf93a6a..000000000000 --- a/book/tests/prql/language-features/strings-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select x = """I said "hello world"!""" diff --git a/book/tests/prql/language-features/strings-4.prql b/book/tests/prql/language-features/strings-4.prql deleted file mode 100644 index 92d3be607db4..000000000000 --- a/book/tests/prql/language-features/strings-4.prql +++ /dev/null @@ -1,2 +0,0 @@ -from my_table -select x = """""I said """hello world"""!""""" diff --git a/book/tests/prql/language-features/strings-5.prql b/book/tests/prql/language-features/strings-5.prql deleted file mode 100644 index 190823141edf..000000000000 --- a/book/tests/prql/language-features/strings-5.prql +++ /dev/null @@ -1,4 +0,0 @@ -# Can't yet format & compile - -from my_table -select x = "\t\tline ends here\n \\ " diff --git a/book/tests/prql/language-features/target-0.prql b/book/tests/prql/language-features/target-0.prql deleted file mode 100644 index 21e54d9840c3..000000000000 --- a/book/tests/prql/language-features/target-0.prql +++ /dev/null @@ -1,5 +0,0 @@ -prql target:sql.postgres - -from employees -sort age -take 10 diff --git a/book/tests/prql/language-features/target-1.prql b/book/tests/prql/language-features/target-1.prql deleted file mode 100644 index 58ed8531c0e5..000000000000 --- a/book/tests/prql/language-features/target-1.prql +++ /dev/null @@ -1,7 +0,0 @@ -# Can't yet format & compile - -prql target:sql.mssql - -from employees -sort age -take 10 diff --git a/book/tests/prql/language-features/target-2.prql b/book/tests/prql/language-features/target-2.prql deleted file mode 100644 index 0b724ad34437..000000000000 --- a/book/tests/prql/language-features/target-2.prql +++ /dev/null @@ -1,5 +0,0 @@ -# Can't yet format & compile - -prql version:"0.6.0" - -from employees diff --git a/book/tests/prql/queries/functions-0.prql b/book/tests/prql/queries/functions-0.prql deleted file mode 100644 index f859ceaa151e..000000000000 --- a/book/tests/prql/queries/functions-0.prql +++ /dev/null @@ -1,6 +0,0 @@ -# Can't yet format & compile - -func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 - -from cities -derive temp_c = (fahrenheit_to_celsius temp_f) diff --git a/book/tests/prql/queries/functions-1.prql b/book/tests/prql/queries/functions-1.prql deleted file mode 100644 index a03bbcd3ac0d..000000000000 --- a/book/tests/prql/queries/functions-1.prql +++ /dev/null @@ -1,7 +0,0 @@ -func interp low:0 high x -> (x - low) / (high - low) - -from students -derive [ - sat_proportion_1 = (interp 1600 sat_score), - sat_proportion_2 = (interp low:0 1600 sat_score), -] diff --git a/book/tests/prql/queries/functions-2.prql b/book/tests/prql/queries/functions-2.prql deleted file mode 100644 index 7fe11cbe86bc..000000000000 --- a/book/tests/prql/queries/functions-2.prql +++ /dev/null @@ -1,7 +0,0 @@ -func interp low:0 high x -> (x - low) / (high - low) - -from students -derive [ - sat_proportion_1 = (sat_score | interp 1600), - sat_proportion_2 = (sat_score | interp low:0 1600), -] diff --git a/book/tests/prql/queries/functions-3.prql b/book/tests/prql/queries/functions-3.prql deleted file mode 100644 index fc9447867a1c..000000000000 --- a/book/tests/prql/queries/functions-3.prql +++ /dev/null @@ -1,4 +0,0 @@ -func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 - -from cities -derive temp_c = (temp_f | fahrenheit_to_celsius) diff --git a/book/tests/prql/queries/functions-4.prql b/book/tests/prql/queries/functions-4.prql deleted file mode 100644 index fc6ded8dc043..000000000000 --- a/book/tests/prql/queries/functions-4.prql +++ /dev/null @@ -1,5 +0,0 @@ -func fahrenheit_to_celsius temp -> (temp - 32) / 1.8 -func interp low:0 high x -> (x - low) / (high - low) - -from kettles -derive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100) diff --git a/book/tests/prql/queries/functions-5.prql b/book/tests/prql/queries/functions-5.prql deleted file mode 100644 index 7875927c0806..000000000000 --- a/book/tests/prql/queries/functions-5.prql +++ /dev/null @@ -1,9 +0,0 @@ -func cost_share cost -> cost / cost_total - -from costs -select [materials, labor, overhead, cost_total] -derive [ - materials_share = (cost_share materials), - labor_share = (cost_share labor), - overhead_share = (cost_share overhead), -] diff --git a/book/tests/prql/queries/pipelines-0.prql b/book/tests/prql/queries/pipelines-0.prql deleted file mode 100644 index 782143755f3b..000000000000 --- a/book/tests/prql/queries/pipelines-0.prql +++ /dev/null @@ -1 +0,0 @@ -from employees diff --git a/book/tests/prql/queries/pipelines-1.prql b/book/tests/prql/queries/pipelines-1.prql deleted file mode 100644 index c3b39d069fa8..000000000000 --- a/book/tests/prql/queries/pipelines-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -derive gross_salary = (salary + payroll_tax) diff --git a/book/tests/prql/queries/pipelines-2.prql b/book/tests/prql/queries/pipelines-2.prql deleted file mode 100644 index dee17ddc0e63..000000000000 --- a/book/tests/prql/queries/pipelines-2.prql +++ /dev/null @@ -1,6 +0,0 @@ -from e = employees -derive gross_salary = (salary + payroll_tax) -sort gross_salary -take 10 -join d = department [==dept_no] -select [e.name, gross_salary, d.name] diff --git a/book/tests/prql/queries/variables-0.prql b/book/tests/prql/queries/variables-0.prql deleted file mode 100644 index f130b7179c73..000000000000 --- a/book/tests/prql/queries/variables-0.prql +++ /dev/null @@ -1,8 +0,0 @@ -let top_50 = ( - from employees - sort salary - take 50 - aggregate [total_salary = sum salary] -) - -from top_50 # Starts a new pipeline diff --git a/book/tests/prql/queries/variables-1.prql b/book/tests/prql/queries/variables-1.prql deleted file mode 100644 index 320c82b3ddd9..000000000000 --- a/book/tests/prql/queries/variables-1.prql +++ /dev/null @@ -1,9 +0,0 @@ -let grouping = s""" - SELECT SUM(a) - FROM tbl - GROUP BY - GROUPING SETS - ((b, c, d), (d), (b, d)) -""" - -from grouping diff --git a/book/tests/prql/syntax-0.prql b/book/tests/prql/syntax-0.prql deleted file mode 100644 index d8b0ec6dd72e..000000000000 --- a/book/tests/prql/syntax-0.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -filter department == "Product" -select [first_name, last_name] diff --git a/book/tests/prql/syntax-1.prql b/book/tests/prql/syntax-1.prql deleted file mode 100644 index f28aaf723a02..000000000000 --- a/book/tests/prql/syntax-1.prql +++ /dev/null @@ -1 +0,0 @@ -from employees | filter department == "Product" | select [first_name, last_name] diff --git a/book/tests/prql/syntax-10.prql b/book/tests/prql/syntax-10.prql deleted file mode 100644 index d768dedf3f09..000000000000 --- a/book/tests/prql/syntax-10.prql +++ /dev/null @@ -1,3 +0,0 @@ -prql target:sql.mysql -from employees -select `first name` diff --git a/book/tests/prql/syntax-11.prql b/book/tests/prql/syntax-11.prql deleted file mode 100644 index b2ebba1b6488..000000000000 --- a/book/tests/prql/syntax-11.prql +++ /dev/null @@ -1,3 +0,0 @@ -prql target:sql.postgres -from employees -select `first name` diff --git a/book/tests/prql/syntax-12.prql b/book/tests/prql/syntax-12.prql deleted file mode 100644 index e855d0393136..000000000000 --- a/book/tests/prql/syntax-12.prql +++ /dev/null @@ -1 +0,0 @@ -from `dir/*.parquet` diff --git a/book/tests/prql/syntax-13.prql b/book/tests/prql/syntax-13.prql deleted file mode 100644 index a634b9554275..000000000000 --- a/book/tests/prql/syntax-13.prql +++ /dev/null @@ -1,3 +0,0 @@ -prql target:sql.bigquery -from `project-foo.dataset.table` -join `project-bar.dataset.table` [==col_bax] diff --git a/book/tests/prql/syntax-14.prql b/book/tests/prql/syntax-14.prql deleted file mode 100644 index a9ccfe89ed66..000000000000 --- a/book/tests/prql/syntax-14.prql +++ /dev/null @@ -1 +0,0 @@ -from `music.albums` diff --git a/book/tests/prql/syntax-15.prql b/book/tests/prql/syntax-15.prql deleted file mode 100644 index 15be2cb62f61..000000000000 --- a/book/tests/prql/syntax-15.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -filter id == $1 diff --git a/book/tests/prql/syntax-16.prql b/book/tests/prql/syntax-16.prql deleted file mode 100644 index 290e626cf825..000000000000 --- a/book/tests/prql/syntax-16.prql +++ /dev/null @@ -1,5 +0,0 @@ -from numbers -select [ - small = 1.000_000_1, - big = 5_000_000, -] diff --git a/book/tests/prql/syntax-17.prql b/book/tests/prql/syntax-17.prql deleted file mode 100644 index 029a0ea82464..000000000000 --- a/book/tests/prql/syntax-17.prql +++ /dev/null @@ -1,3 +0,0 @@ -std.from my_table -std.select [from = my_table.a, take = my_table.b] -std.take 3 diff --git a/book/tests/prql/syntax-2.prql b/book/tests/prql/syntax-2.prql deleted file mode 100644 index 738ad9c85a11..000000000000 --- a/book/tests/prql/syntax-2.prql +++ /dev/null @@ -1,10 +0,0 @@ -from numbers -derive [x = 1, y = 2] -derive [ - a = x, - b = y -] -derive [ - c = a, - d = b, -] diff --git a/book/tests/prql/syntax-3.prql b/book/tests/prql/syntax-3.prql deleted file mode 100644 index 7badae90b98a..000000000000 --- a/book/tests/prql/syntax-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select [first_name] diff --git a/book/tests/prql/syntax-4.prql b/book/tests/prql/syntax-4.prql deleted file mode 100644 index ec44dd3366e8..000000000000 --- a/book/tests/prql/syntax-4.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select first_name diff --git a/book/tests/prql/syntax-5.prql b/book/tests/prql/syntax-5.prql deleted file mode 100644 index 79e709893b7c..000000000000 --- a/book/tests/prql/syntax-5.prql +++ /dev/null @@ -1,6 +0,0 @@ -from foo -select [ - circumference = diameter * 3.14159, - color, -] -filter circumference > 10 and color != "red" diff --git a/book/tests/prql/syntax-6.prql b/book/tests/prql/syntax-6.prql deleted file mode 100644 index ac2acdcd7a08..000000000000 --- a/book/tests/prql/syntax-6.prql +++ /dev/null @@ -1,28 +0,0 @@ -# Can't yet format & compile - -from employees -# Requires parentheses, because it's contains a pipe -derive is_proximate = (distance | in 0..20) -# Requires parentheses, because it's a function call -derive total_distance = (sum distance) -# `??` doesn't require parentheses, as it's not a function call -derive min_capped_distance = (min distance ?? 5) -# No parentheses needed, because no function call -derive travel_time = distance / 40 -# No inner parentheses needed around `1+1` because no function call -derive distance_rounded_2_dp = (round 1+1 distance) -derive [ - # Requires parentheses, because it contains a pipe - is_far = (distance | in 100..), - # The left value of the range requires parentheses, - # because of the minus sign - is_negative = (distance | in (-100..0)), - # ...this is equivalent - is_negative = (distance | in (-100)..0), - # Doesn't require parentheses, because it's in a list (confusing, see footnote)! - average_distance = average distance, -] -# Requires parentheses because of the minus sign -sort (-distance) -# A list is fine too -sort [-distance] diff --git a/book/tests/prql/syntax-7.prql b/book/tests/prql/syntax-7.prql deleted file mode 100644 index a7ee0af913aa..000000000000 --- a/book/tests/prql/syntax-7.prql +++ /dev/null @@ -1,4 +0,0 @@ -# Error expected - -from employees -derive total_distance = sum distance diff --git a/book/tests/prql/syntax-8.prql b/book/tests/prql/syntax-8.prql deleted file mode 100644 index f655f4637971..000000000000 --- a/book/tests/prql/syntax-8.prql +++ /dev/null @@ -1,7 +0,0 @@ -from employees -group [title, country] ( - aggregate [ - average salary, - ct = count - ] -) diff --git a/book/tests/prql/syntax-9.prql b/book/tests/prql/syntax-9.prql deleted file mode 100644 index 7ee340a4259a..000000000000 --- a/book/tests/prql/syntax-9.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees # Comment 1 -# Comment 2 -aggregate [average salary] diff --git a/book/tests/prql/transforms/aggregate-0.prql b/book/tests/prql/transforms/aggregate-0.prql deleted file mode 100644 index 12e9ff298a1a..000000000000 --- a/book/tests/prql/transforms/aggregate-0.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -aggregate [ - average salary, - ct = count -] diff --git a/book/tests/prql/transforms/aggregate-1.prql b/book/tests/prql/transforms/aggregate-1.prql deleted file mode 100644 index f655f4637971..000000000000 --- a/book/tests/prql/transforms/aggregate-1.prql +++ /dev/null @@ -1,7 +0,0 @@ -from employees -group [title, country] ( - aggregate [ - average salary, - ct = count - ] -) diff --git a/book/tests/prql/transforms/aggregate-2.prql b/book/tests/prql/transforms/aggregate-2.prql deleted file mode 100644 index d3276634b6af..000000000000 --- a/book/tests/prql/transforms/aggregate-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -derive [avg_sal = average salary] diff --git a/book/tests/prql/transforms/append-0.prql b/book/tests/prql/transforms/append-0.prql deleted file mode 100644 index ecadad3ed3d0..000000000000 --- a/book/tests/prql/transforms/append-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees_1 -append employees_2 diff --git a/book/tests/prql/transforms/append-1.prql b/book/tests/prql/transforms/append-1.prql deleted file mode 100644 index 427597e3dbad..000000000000 --- a/book/tests/prql/transforms/append-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees_1 -remove employees_2 diff --git a/book/tests/prql/transforms/append-2.prql b/book/tests/prql/transforms/append-2.prql deleted file mode 100644 index 08c142df97fe..000000000000 --- a/book/tests/prql/transforms/append-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees_1 -intersect employees_2 diff --git a/book/tests/prql/transforms/derive-0.prql b/book/tests/prql/transforms/derive-0.prql deleted file mode 100644 index 0ca92150a0a9..000000000000 --- a/book/tests/prql/transforms/derive-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -derive gross_salary = salary + payroll_tax diff --git a/book/tests/prql/transforms/derive-1.prql b/book/tests/prql/transforms/derive-1.prql deleted file mode 100644 index f49937a6bfc6..000000000000 --- a/book/tests/prql/transforms/derive-1.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -derive [ - gross_salary = salary + payroll_tax, - gross_cost = gross_salary + benefits_cost -] diff --git a/book/tests/prql/transforms/filter-0.prql b/book/tests/prql/transforms/filter-0.prql deleted file mode 100644 index 6ecce44d63af..000000000000 --- a/book/tests/prql/transforms/filter-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -filter age > 25 diff --git a/book/tests/prql/transforms/filter-1.prql b/book/tests/prql/transforms/filter-1.prql deleted file mode 100644 index 60ca713cdfe8..000000000000 --- a/book/tests/prql/transforms/filter-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -filter (age > 25 or department != "IT") diff --git a/book/tests/prql/transforms/filter-2.prql b/book/tests/prql/transforms/filter-2.prql deleted file mode 100644 index fe81ad79a5fb..000000000000 --- a/book/tests/prql/transforms/filter-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -filter (age | in 25..40) diff --git a/book/tests/prql/transforms/from-0.prql b/book/tests/prql/transforms/from-0.prql deleted file mode 100644 index 782143755f3b..000000000000 --- a/book/tests/prql/transforms/from-0.prql +++ /dev/null @@ -1 +0,0 @@ -from employees diff --git a/book/tests/prql/transforms/from-1.prql b/book/tests/prql/transforms/from-1.prql deleted file mode 100644 index f9ec0ba68c54..000000000000 --- a/book/tests/prql/transforms/from-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from e = employees -select e.first_name diff --git a/book/tests/prql/transforms/group-0.prql b/book/tests/prql/transforms/group-0.prql deleted file mode 100644 index f655f4637971..000000000000 --- a/book/tests/prql/transforms/group-0.prql +++ /dev/null @@ -1,7 +0,0 @@ -from employees -group [title, country] ( - aggregate [ - average salary, - ct = count - ] -) diff --git a/book/tests/prql/transforms/group-1.prql b/book/tests/prql/transforms/group-1.prql deleted file mode 100644 index 1d1d99b09ba3..000000000000 --- a/book/tests/prql/transforms/group-1.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -sort join_date -take 1 diff --git a/book/tests/prql/transforms/group-2.prql b/book/tests/prql/transforms/group-2.prql deleted file mode 100644 index 47024bedc68e..000000000000 --- a/book/tests/prql/transforms/group-2.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -group role ( - sort join_date # taken from above - take 1 -) diff --git a/book/tests/prql/transforms/join-0.prql b/book/tests/prql/transforms/join-0.prql deleted file mode 100644 index df05df8dbed5..000000000000 --- a/book/tests/prql/transforms/join-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -join side:left positions [employees.id==positions.employee_id] diff --git a/book/tests/prql/transforms/join-1.prql b/book/tests/prql/transforms/join-1.prql deleted file mode 100644 index e074ffd3e034..000000000000 --- a/book/tests/prql/transforms/join-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -join side:left p=positions [employees.id==p.employee_id] diff --git a/book/tests/prql/transforms/join-2.prql b/book/tests/prql/transforms/join-2.prql deleted file mode 100644 index 37c18f95467b..000000000000 --- a/book/tests/prql/transforms/join-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -join positions [==emp_no] diff --git a/book/tests/prql/transforms/select-0.prql b/book/tests/prql/transforms/select-0.prql deleted file mode 100644 index 69ff35c8a5b6..000000000000 --- a/book/tests/prql/transforms/select-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select name = f"{first_name} {last_name}" diff --git a/book/tests/prql/transforms/select-1.prql b/book/tests/prql/transforms/select-1.prql deleted file mode 100644 index 346904e522e0..000000000000 --- a/book/tests/prql/transforms/select-1.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -select [ - name = f"{first_name} {last_name}", - age_eoy = dob - @2022-12-31, -] diff --git a/book/tests/prql/transforms/select-2.prql b/book/tests/prql/transforms/select-2.prql deleted file mode 100644 index ec44dd3366e8..000000000000 --- a/book/tests/prql/transforms/select-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -select first_name diff --git a/book/tests/prql/transforms/select-3.prql b/book/tests/prql/transforms/select-3.prql deleted file mode 100644 index d0f3f99260cb..000000000000 --- a/book/tests/prql/transforms/select-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from e=employees -select [e.first_name, e.last_name] diff --git a/book/tests/prql/transforms/select-4.prql b/book/tests/prql/transforms/select-4.prql deleted file mode 100644 index 5d89bfe51b61..000000000000 --- a/book/tests/prql/transforms/select-4.prql +++ /dev/null @@ -1,5 +0,0 @@ -# Can't yet format & compile - -prql target:sql.bigquery -from tracks -select ![milliseconds,bytes] diff --git a/book/tests/prql/transforms/select-5.prql b/book/tests/prql/transforms/select-5.prql deleted file mode 100644 index 6296e2abd6e7..000000000000 --- a/book/tests/prql/transforms/select-5.prql +++ /dev/null @@ -1,5 +0,0 @@ -# Can't yet format & compile - -from tracks -select [track_id, title, composer, bytes] -select ![title, composer] diff --git a/book/tests/prql/transforms/select-6.prql b/book/tests/prql/transforms/select-6.prql deleted file mode 100644 index 0f5a238d4098..000000000000 --- a/book/tests/prql/transforms/select-6.prql +++ /dev/null @@ -1,5 +0,0 @@ -# Can't yet format & compile - -from artists -derive nick = name -select ![artists.*] diff --git a/book/tests/prql/transforms/sort-0.prql b/book/tests/prql/transforms/sort-0.prql deleted file mode 100644 index e019af01c2eb..000000000000 --- a/book/tests/prql/transforms/sort-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -sort age diff --git a/book/tests/prql/transforms/sort-1.prql b/book/tests/prql/transforms/sort-1.prql deleted file mode 100644 index a5b15d8d0fbf..000000000000 --- a/book/tests/prql/transforms/sort-1.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -sort [-age] diff --git a/book/tests/prql/transforms/sort-2.prql b/book/tests/prql/transforms/sort-2.prql deleted file mode 100644 index 7809593be39c..000000000000 --- a/book/tests/prql/transforms/sort-2.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -sort [age, -tenure, +salary] diff --git a/book/tests/prql/transforms/sort-3.prql b/book/tests/prql/transforms/sort-3.prql deleted file mode 100644 index c4c9bbd5e7a4..000000000000 --- a/book/tests/prql/transforms/sort-3.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -sort [s"substr({first_name}, 2, 5)"] diff --git a/book/tests/prql/transforms/sort-4.prql b/book/tests/prql/transforms/sort-4.prql deleted file mode 100644 index 7f4df2d22a48..000000000000 --- a/book/tests/prql/transforms/sort-4.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -sort tenure -derive name = f"{first_name} {last_name}" diff --git a/book/tests/prql/transforms/sort-5.prql b/book/tests/prql/transforms/sort-5.prql deleted file mode 100644 index 812dcdc7bdbe..000000000000 --- a/book/tests/prql/transforms/sort-5.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -sort tenure -join locations [==employee_id] diff --git a/book/tests/prql/transforms/take-0.prql b/book/tests/prql/transforms/take-0.prql deleted file mode 100644 index 63d11c6b23f7..000000000000 --- a/book/tests/prql/transforms/take-0.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -take 10 diff --git a/book/tests/prql/transforms/take-1.prql b/book/tests/prql/transforms/take-1.prql deleted file mode 100644 index fcf59ae0e31c..000000000000 --- a/book/tests/prql/transforms/take-1.prql +++ /dev/null @@ -1,3 +0,0 @@ -from orders -sort [-value, created_at] -take 101..110 diff --git a/book/tests/prql/transforms/window-0.prql b/book/tests/prql/transforms/window-0.prql deleted file mode 100644 index 6259783650c6..000000000000 --- a/book/tests/prql/transforms/window-0.prql +++ /dev/null @@ -1,7 +0,0 @@ -from employees -group employee_id ( - sort month - window rolling:12 ( - derive [trail_12_m_comp = sum paycheck] - ) -) diff --git a/book/tests/prql/transforms/window-1.prql b/book/tests/prql/transforms/window-1.prql deleted file mode 100644 index 551a99f49293..000000000000 --- a/book/tests/prql/transforms/window-1.prql +++ /dev/null @@ -1,11 +0,0 @@ -from orders -sort day -window rows:-3..3 ( - derive [centered_weekly_average = average value] -) -group [order_month] ( - sort day - window expanding:true ( - derive [monthly_running_total = sum value] - ) -) diff --git a/book/tests/prql/transforms/window-2.prql b/book/tests/prql/transforms/window-2.prql deleted file mode 100644 index 0093d51081cf..000000000000 --- a/book/tests/prql/transforms/window-2.prql +++ /dev/null @@ -1,3 +0,0 @@ -from employees -sort age -derive rnk = rank diff --git a/book/tests/prql/transforms/window-3.prql b/book/tests/prql/transforms/window-3.prql deleted file mode 100644 index ed779ac389a2..000000000000 --- a/book/tests/prql/transforms/window-3.prql +++ /dev/null @@ -1,5 +0,0 @@ -from employees -group department ( - sort age - derive rnk = rank -) diff --git a/book/tests/prql/transforms/window-4.prql b/book/tests/prql/transforms/window-4.prql deleted file mode 100644 index a28ee16df128..000000000000 --- a/book/tests/prql/transforms/window-4.prql +++ /dev/null @@ -1,2 +0,0 @@ -from employees -filter salary < (average salary) diff --git a/book/tests/snapshot.rs b/book/tests/snapshot.rs index d12910afd363..19060db0454f 100644 --- a/book/tests/snapshot.rs +++ b/book/tests/snapshot.rs @@ -17,11 +17,9 @@ // us. They introduce a bunch of non-rust dependencies, which is not ideal, but // passable. They don't let us customize our formatting (e.g. in a table). // -use anyhow::{bail, Error, Result}; +use anyhow::{bail, Result}; use globset::Glob; -use insta::{assert_snapshot, glob}; -use itertools::Itertools; -use log::warn; +use insta::assert_snapshot; use prql_compiler::*; use std::path::{Path, PathBuf}; use std::{collections::HashMap, fs}; @@ -38,12 +36,6 @@ use walkdir::WalkDir; /// comparison table of SQL into the book, and so serves as a snapshot test of /// those examples. fn test_examples() -> Result<()> { - // Note that on Windows, markdown is read differently, and so we don't yet - // write on Windows (we write from the same place we read as a workaround, - // and would welcome a fix). - // ref https://github.com/PRQL/prql/issues/356 - - write_prql_examples(collect_book_examples()?)?; test_prql_examples(); Ok(()) @@ -52,7 +44,6 @@ fn test_examples() -> Result<()> { const ROOT_EXAMPLES_PATH: &str = "tests/prql"; /// Collect all the PRQL examples in the book, as a map of . -#[cfg(not(target_family = "windows"))] fn collect_book_examples() -> Result> { use pulldown_cmark::{Event, Parser}; let glob = Glob::new("**/*.md")?.compile_matcher(); @@ -69,14 +60,14 @@ fn collect_book_examples() -> Result> { let mut prql_blocks = vec![]; while let Some(event) = parser.next() { match mdbook_prql::code_block_lang(&event) { - // At the start of a PRQL code block, push the _next_ item. - // Note that on windows, we only get the next _line_, and so - // this is disabled on windows. - // https://github.com/PRQL/prql/issues/356 Some(lang) if lang.starts_with("prql") => { - let Some(Event::Text(text)) = parser.next() else { - bail!("Expected text after PRQL code block") - }; + let mut text = String::new(); + while let Some(Event::Text(line)) = parser.next() { + text.push_str(line.to_string().as_str()); + } + if text.is_empty() { + bail!("Expected text after PRQL code block"); + } if lang == "prql" { prql_blocks.push(text.to_string()); } else if lang == "prql_error" { @@ -112,82 +103,12 @@ fn collect_book_examples() -> Result> { Ok(examples_in_book) } -/// Collect examples which we've already written to disk, as a map of . -fn collect_snapshot_examples() -> Result> { - let glob = Glob::new("**/*.prql")?.compile_matcher(); - let existing_examples = WalkDir::new(Path::new(ROOT_EXAMPLES_PATH)) - .into_iter() - .flatten() - .filter(|x| glob.is_match(x.path())) - .map(|x| Ok::<_, Error>((x.clone().into_path(), fs::read_to_string(x.path())?))) - .try_collect()?; - - Ok(existing_examples) -} - -// On Windows, we grab them from the written files, because of the markdown issue. -#[cfg(target_family = "windows")] -fn collect_book_examples() -> Result> { - collect_snapshot_examples() -} - -/// Write the passed examples as snapshots to the `tests/prql` path, one in each file. -// We could alternatively have used something like -// https://github.com/earldouglas/codedown, but it's not much code, and it -// requires no dependencies. -fn write_prql_examples(examples: HashMap) -> Result<()> { - // If we have to modify any files, raise an error at the end, so it fails in CI. - let mut snapshots_updated = vec![]; - - let mut existing_snapshots: HashMap<_, _> = collect_snapshot_examples()?; - // Write any new snapshots, or update any that have changed - examples.iter().try_for_each(|(prql_path, example)| { - if existing_snapshots - .remove(prql_path) - .map(|existing| existing != *example) - .unwrap_or(true) - { - snapshots_updated.push(prql_path); - fs::create_dir_all(Path::new(prql_path).parent().unwrap())?; - fs::write(prql_path, example)?; - } - - Ok::<(), anyhow::Error>(()) - })?; - - // If there are any files left in `existing_snapshots`, we remove them, - // since they don't reference anything (like - // `--delete-unreferenced-snapshots` in insta). - existing_snapshots.iter().for_each(|(path, _)| { - trash::delete(path).unwrap_or_else(|e| { - warn!("Failed to delete unreferenced example: {}", e); - }) - }); - - // TODO: Not actually sure we want this; not consistent with `cargo insta --accept`. - if !snapshots_updated.is_empty() { - let snapshots_updated = snapshots_updated - .iter() - .map(|x| format!(" - {}", x.to_str().unwrap())) - .join("\n"); - bail!(format!( - r###" -Some book snapshots were not consistent with the queries in the book: - -{snapshots_updated} - -The snapshots have now been updated. Subsequent runs of this test should now pass.\n\n"### - )); - } - Ok(()) -} - /// Snapshot the SQL output of each example. fn test_prql_examples() { let opts = Options::default().no_signature(); - glob!("prql/**/*.prql", |path| { - let prql = fs::read_to_string(path).unwrap(); + let examples = collect_book_examples().unwrap(); + for (path, prql) in examples { // TODO: I don't think we use this and can remove it? if prql.contains("skip_test") { return; @@ -195,12 +116,8 @@ fn test_prql_examples() { // Whether it's a success or a failure, get the string. let sql = compile(&prql, &opts).unwrap_or_else(|e| e.to_string()); - // `glob!` gives us the file path in the test name anyway, so we pass an - // empty name. We pass `&prql` so the prql is in the snapshot (albeit in - // a single line, and, in the rare case that the SQL doesn't change, the - // PRQL only updates on running cargo insta with `--force-update-snapshots`). - assert_snapshot!("", &sql, &prql); - }); + assert_snapshot!(path.to_str().unwrap(), &sql, &prql); + } } /// Test that the formatted result (the `Display` result) of each example can be diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__@language-features__s-strings-4.prql.snap deleted file mode 100644 index 1c28726ce165..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-4.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" -input_file: book/tests/prql/language-features/s-strings-4.prql ---- -SELECT - *, - regexp_contains(title, '([a-z0-9]*-){2,}') AS has_valid_title -FROM - employees diff --git a/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap b/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap deleted file mode 100644 index 1e5ef589937a..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__strings-5.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from my_table\nselect x = \"\\t\\tline ends here\\n \\\\ \"\n" -input_file: book/tests/prql/language-features/strings-5.prql ---- -SELECT - ' line ends here - \ ' AS x -FROM - my_table - diff --git a/book/tests/snapshots/snapshot__@language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__@language-features__target-1.prql.snap deleted file mode 100644 index 83b87715b88d..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__target-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" -input_file: book/tests/prql/language-features/target-1.prql ---- -SELECT - TOP (10) * -FROM - employees -ORDER BY - age diff --git a/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap deleted file mode 100644 index 4326599ef89f..000000000000 --- a/book/tests/snapshots/snapshot__@language-features__target-2.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "# Can't yet format & compile\n\nprql version:\"0.6\"\n\nfrom employees\n" -input_file: book/tests/prql/language-features/target-2.prql ---- -SELECT - * -FROM - employees - diff --git a/book/tests/snapshots/snapshot__@queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-0.prql.snap deleted file mode 100644 index 332c716ae9d9..000000000000 --- a/book/tests/snapshots/snapshot__@queries__functions-0.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" -input_file: book/tests/prql/queries/functions-0.prql ---- -SELECT - *, - (temp_f - 32) / 1.8 AS temp_c -FROM - cities diff --git a/book/tests/snapshots/snapshot__@queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-1.prql.snap deleted file mode 100644 index 0aaeb32b5b0d..000000000000 --- a/book/tests/snapshots/snapshot__@queries__functions-1.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp lower:0 1600 sat_score),\n]\n" -input_file: book/tests/prql/queries/functions-1.prql ---- -SELECT - *, - (sat_score - 0) / 1600 AS sat_proportion_1, - (sat_score - 0) / 1600 AS sat_proportion_2 -FROM - students diff --git a/book/tests/snapshots/snapshot__@queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-2.prql.snap deleted file mode 100644 index 273eb16a4244..000000000000 --- a/book/tests/snapshots/snapshot__@queries__functions-2.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp lower:0 1600),\n]\n" -input_file: book/tests/prql/queries/functions-2.prql ---- -SELECT - *, - (sat_score - 0) / 1600 AS sat_proportion_1, - (sat_score - 0) / 1600 AS sat_proportion_2 -FROM - students diff --git a/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap deleted file mode 100644 index 98117ed8ee3a..000000000000 --- a/book/tests/snapshots/snapshot__@queries__functions-4.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp lower:0 higher x -> (x - lower) / (higher - lower)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" -input_file: book/tests/prql/queries/functions-4.prql ---- -SELECT - *, - ((temp_c - 32) / 1.8 - 0) / 100 AS boiling_proportion -FROM - kettles - diff --git a/book/tests/snapshots/snapshot__@syntax-6.prql.snap b/book/tests/snapshots/snapshot__@syntax-6.prql.snap deleted file mode 100644 index 916f3d4cbe85..000000000000 --- a/book/tests/snapshots/snapshot__@syntax-6.prql.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" -input_file: book/tests/prql/syntax-6.prql ---- -SELECT - *, - distance BETWEEN 0 AND 20 AS is_proximate, - SUM(distance) OVER () AS total_distance, - MIN(COALESCE(distance, 5)) OVER () AS min_capped_distance, - distance / 40 AS travel_time, - ROUND(distance, 2) AS distance_rounded_2_dp, - distance >= 100 AS is_far, - distance BETWEEN -100 AND 0, - distance BETWEEN -100 AND 0 AS is_negative, - AVG(distance) OVER () AS average_distance -FROM - employees -ORDER BY - distance DESC diff --git a/book/tests/snapshots/snapshot__@transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__@transforms__select-4.prql.snap deleted file mode 100644 index 3419030604ce..000000000000 --- a/book/tests/snapshots/snapshot__@transforms__select-4.prql.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "prql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" -input_file: book/tests/prql/transforms/select-4.prql ---- -SELECT - * -EXCEPT - (milliseconds, bytes) -FROM - tracks diff --git a/book/tests/snapshots/snapshot__@transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__@transforms__select-5.prql.snap deleted file mode 100644 index 33337b07109a..000000000000 --- a/book/tests/snapshots/snapshot__@transforms__select-5.prql.snap +++ /dev/null @@ -1,10 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" -input_file: book/tests/prql/transforms/select-5.prql ---- -SELECT - track_id, - bytes -FROM - tracks diff --git a/book/tests/snapshots/snapshot__@transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__@transforms__select-6.prql.snap deleted file mode 100644 index 7aa04a75c903..000000000000 --- a/book/tests/snapshots/snapshot__@transforms__select-6.prql.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: book/tests/snapshot.rs -expression: "from artists\nderive nick = name\nselect ![artists.*]\n" -input_file: book/tests/prql/transforms/select-6.prql ---- -SELECT - name AS nick -FROM - artists diff --git a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap similarity index 56% rename from book/tests/snapshots/snapshot__@examples__cte-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap index 36a99fd31e3f..f71d66ed6d20 100644 --- a/book/tests/snapshots/snapshot__@examples__cte-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "let newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" -input_file: book/tests/prql/examples/cte-0.prql +expression: "# Can't yet format & compile\n\nlet newest_employees = (\n from employees\n sort tenure\n take 50\n)\n\nlet average_salaries = (\n from salaries\n group country (\n aggregate average_country_salary = (average salary)\n )\n)\n\nfrom newest_employees\njoin average_salaries [==country]\nselect [name, salary, average_country_salary]\n" --- WITH newest_employees AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap similarity index 94% rename from book/tests/snapshots/snapshot__@examples__employees-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap index 47650f37675d..8732d541bc3a 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from salaries\ngroup [emp_no] (\n aggregate [emp_salary = average salary]\n)\njoin t=titles [==emp_no]\njoin dept_emp side:left [==emp_no]\ngroup [dept_emp.dept_no, t.title] (\n aggregate [avg_salary = average emp_salary]\n)\njoin departments [==dept_no]\nselect [dept_name, title, avg_salary]\n" -input_file: book/tests/prql/examples/employees-0.prql --- WITH table_3 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap similarity index 95% rename from book/tests/snapshots/snapshot__@examples__employees-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap index 88f00f10486c..7a7a20d9d486 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no] side:left\ngroup [de.dept_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary,\n ]\n)\njoin departments [==dept_no]\nselect [dept_name, gender, salary_avg, salary_sd]\n" -input_file: book/tests/prql/examples/employees-1.prql --- WITH table_3 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap similarity index 96% rename from book/tests/snapshots/snapshot__@examples__employees-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap index 612ece4db0c6..606c82c45116 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from e=employees\njoin salaries [==emp_no]\ngroup [e.emp_no, e.gender] (\n aggregate [\n emp_salary = average salaries.salary\n ]\n)\njoin de=dept_emp [==emp_no]\njoin dm=dept_manager [\n (dm.dept_no == de.dept_no) and s\"(de.from_date, de.to_date) OVERLAPS (dm.from_date, dm.to_date)\"\n]\ngroup [dm.emp_no, gender] (\n aggregate [\n salary_avg = average emp_salary,\n salary_sd = stddev emp_salary\n ]\n)\nderive mng_no = emp_no\njoin managers=employees [==emp_no]\nderive mng_name = s\"managers.first_name || ' ' || managers.last_name\"\nselect [mng_name, managers.gender, salary_avg, salary_sd]\n" -input_file: book/tests/prql/examples/employees-2.prql --- WITH table_3 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap similarity index 56% rename from book/tests/snapshots/snapshot__@examples__employees-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap index 68c457076ef7..f98020d2457a 100644 --- a/book/tests/snapshots/snapshot__@examples__employees-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs -expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" -input_file: book/tests/prql/examples/employees-3.prql +expression: "# Can't yet format & compile\n\nfrom de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"({s.from_date}, {s.to_date}) OVERLAPS ({de.from_date}, {de.to_date})\"\n]\ngroup [de.emp_no, de.dept_no] (\n aggregate salary = (average s.salary)\n)\njoin employees [==emp_no]\njoin titles [==emp_no]\nselect [dept_no, salary, employees.gender, titles.title]\n" --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__list-equivalence-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap similarity index 65% rename from book/tests/snapshots/snapshot__@examples__list-equivalence-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap index 9d105a9ac969..917f7babe1eb 100644 --- a/book/tests/snapshots/snapshot__@examples__list-equivalence-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect salary\n" -input_file: book/tests/prql/examples/list-equivalence-0.prql --- SELECT salary FROM employees + diff --git a/book/tests/snapshots/snapshot__@examples__list-equivalence-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap similarity index 66% rename from book/tests/snapshots/snapshot__@examples__list-equivalence-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap index 7659c80e47e0..65309b667121 100644 --- a/book/tests/snapshots/snapshot__@examples__list-equivalence-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect [salary]\n" -input_file: book/tests/prql/examples/list-equivalence-1.prql --- SELECT salary FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__derive-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@transforms__derive-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap index bd3e6b7781ac..b99c1d44b18a 100644 --- a/book/tests/snapshots/snapshot__@transforms__derive-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" -input_file: book/tests/prql/transforms/derive-1.prql --- SELECT *, @@ -9,3 +8,4 @@ SELECT salary + payroll_tax + benefits_cost AS gross_cost FROM employees + diff --git a/book/tests/snapshots/snapshot__@examples__list-equivalence-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@examples__list-equivalence-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap index 211db678219b..3503ac3ba3bc 100644 --- a/book/tests/snapshots/snapshot__@examples__list-equivalence-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive gross_salary = salary + payroll_tax\nderive gross_cost = gross_salary + benefits_cost\n" -input_file: book/tests/prql/examples/list-equivalence-3.prql --- SELECT *, @@ -9,3 +8,4 @@ SELECT salary + payroll_tax + benefits_cost AS gross_cost FROM employees + diff --git a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap similarity index 96% rename from book/tests/snapshots/snapshot__@examples__misc-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap index 676b3103af9c..795e18eb21ee 100644 --- a/book/tests/snapshots/snapshot__@examples__misc-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "# TODO: this table should have a column `part` with values 1..5,\n# but such data declaration is not yet supported, see #286\nlet parts = (\n from seq_1_to_5\n)\n\nfrom pl=prospect_lists_prospects\nfilter prospect_list_id == 'cc675eee-8bd1-237f-be5e-622ba511d65e'\njoin a=accounts [a.id == pl.related_id]\njoin er=email_addr_bean_rel [er.bean_id == a.id and er.primary_address == '1']\njoin ea=email_addresses [ea.id == er.email_address_id]\nselect ea.email_address\nderive prefix = s\"regexp_replace(SUBSTRING_INDEX({email_address}, '@', 1), '[.0-9-_:]+', '.')\"\nderive stub = s\"SUBSTRING_INDEX(SUBSTRING_INDEX({prefix}, '.', part), '.', -1)\"\nselect [email_address, stub]\n" -input_file: book/tests/prql/examples/misc-0.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__misc-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@examples__misc-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap index 692a81d2c3ee..bf33decb9e96 100644 --- a/book/tests/snapshots/snapshot__@examples__misc-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from club_ratings\nfilter rating != null\n# TODO: this is real ugly. `average rating` should not require parenthesis\n# TODO: why cannot we put comments in group's pipeline?\ngroup year (\n derive [rating_norm = rating - (average rating) / (stddev rating)]\n)\n" -input_file: book/tests/prql/examples/misc-1.prql --- SELECT *, @@ -10,3 +9,4 @@ FROM club_ratings WHERE rating IS NOT NULL + diff --git a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap similarity index 95% rename from book/tests/snapshots/snapshot__@examples__variables-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap index 69e10cb2c16d..9991d13535ad 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter country == \"USA\" # Each line transforms the previous result.\nderive [ # This adds columns / variables.\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost # Variables can use other variables.\n]\nfilter gross_cost > 0\ngroup [title, country] ( # For each group use a nested pipeline\n aggregate [ # Aggregate each group to a single row\n average salary,\n average gross_salary,\n sum salary,\n sum gross_salary,\n average gross_cost,\n sum_gross_cost = sum gross_cost,\n ct = count,\n ]\n)\nsort sum_gross_cost\nfilter ct > 200\ntake 20\n" -input_file: book/tests/prql/examples/variables-0.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap similarity index 94% rename from book/tests/snapshots/snapshot__@examples__variables-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap index 77b68ee0c7d1..e6ba77039637 100644 --- a/book/tests/snapshots/snapshot__@examples__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup [emp_no] (\n aggregate [\n emp_salary = average salary # average salary resolves to \"AVG(salary)\" (from stdlib)\n ]\n)\njoin titles [==emp_no]\ngroup [title] (\n aggregate [\n avg_salary = average emp_salary\n ]\n)\nselect salary_k = avg_salary / 1000 # avg_salary should resolve to \"AVG(emp_salary)\"\ntake 10 # induces new SELECT\nderive salary = salary_k * 1000 # salary_k should not resolve to \"avg_salary / 1000\"\n" -input_file: book/tests/prql/examples/variables-1.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@internals__functional-lang-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@internals__functional-lang-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap index ad5671afca07..99428ff3ef14 100644 --- a/book/tests/snapshots/snapshot__@internals__functional-lang-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter age > 50\nsort name\n" -input_file: book/tests/prql/internals/functional-lang-0.prql --- SELECT * @@ -11,3 +10,4 @@ WHERE age > 50 ORDER BY name + diff --git a/book/tests/snapshots/snapshot__@internals__functional-lang-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@internals__functional-lang-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap index 5757f55e1b85..392cd3e8ac16 100644 --- a/book/tests/snapshots/snapshot__@internals__functional-lang-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees | filter age > 50 | sort name\n" -input_file: book/tests/prql/internals/functional-lang-1.prql --- SELECT * @@ -11,3 +10,4 @@ WHERE age > 50 ORDER BY name + diff --git a/book/tests/snapshots/snapshot__@internals__functional-lang-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@internals__functional-lang-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap index 03421c4e7de6..42c319e1cee7 100644 --- a/book/tests/snapshots/snapshot__@internals__functional-lang-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "filter age > 50 (from employees) | sort name\n" -input_file: book/tests/prql/internals/functional-lang-2.prql --- SELECT * @@ -11,3 +10,4 @@ WHERE age > 50 ORDER BY name + diff --git a/book/tests/snapshots/snapshot__@internals__functional-lang-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@internals__functional-lang-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap index 08c9e99fcc9e..0e124447b84b 100644 --- a/book/tests/snapshots/snapshot__@internals__functional-lang-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "sort name (filter age > 50 (from employees))\n" -input_file: book/tests/prql/internals/functional-lang-3.prql --- SELECT * @@ -11,3 +10,4 @@ WHERE age > 50 ORDER BY name + diff --git a/book/tests/snapshots/snapshot__@syntax-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@syntax-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap index ddc00aa96ddf..9621e1555906 100644 --- a/book/tests/snapshots/snapshot__@syntax-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect first_name\n" -input_file: book/tests/prql/syntax-4.prql --- SELECT first_name FROM employees + diff --git a/book/tests/snapshots/snapshot__@internals__name-resolving-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@internals__name-resolving-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap index b9193ffa8f59..f5a7aa7115c1 100644 --- a/book/tests/snapshots/snapshot__@internals__name-resolving-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [first_name, dept_id]\njoin d=departments [==dept_id]\nselect [first_name, d.title]\n" -input_file: book/tests/prql/internals/name-resolving-1.prql --- SELECT employees.first_name, @@ -9,3 +8,4 @@ SELECT FROM employees JOIN departments AS d ON employees.dept_id = d.dept_id + diff --git a/book/tests/snapshots/snapshot__@introduction-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap similarity index 97% rename from book/tests/snapshots/snapshot__@introduction-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap index 2cfecfb1a71d..1519f4a7ce9f 100644 --- a/book/tests/snapshots/snapshot__@introduction-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter start_date > @2021-01-01 # Clear date syntax\nderive [ # `derive` adds columns / variables\n gross_salary = salary + (tax ?? 0), # Terse coalesce\n gross_cost = gross_salary + benefits_cost, # Variables can use other variables\n]\nfilter gross_cost > 0\ngroup [title, country] ( # `group` runs a pipeline over each group\n aggregate [ # `aggregate` reduces each group to a value\n average gross_salary,\n sum_gross_cost = sum gross_cost, # `=` sets a column name\n ]\n)\nfilter sum_gross_cost > 100_000 # `filter` replaces both of SQL's `WHERE` & `HAVING`\nderive id = f\"{title}_{country}\" # F-strings like Python\nderive country_code = s\"LEFT(country, 2)\" # S-strings allow using SQL as an escape hatch\nsort [sum_gross_cost, -country] # `-country` means descending order\ntake 1..20 # Range expressions (also valid here as `take 20`)\n" -input_file: book/tests/prql/introduction-0.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap similarity index 85% rename from book/tests/snapshots/snapshot__@language-features__case-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap index 70a17264d893..3ec06a4f67a0 100644 --- a/book/tests/snapshots/snapshot__@language-features__case-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" => 0,\n city == \"Edmonton\" => 300,\n]\n" -input_file: book/tests/prql/language-features/case-0.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap similarity index 86% rename from book/tests/snapshots/snapshot__@language-features__case-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap index 391cb2489d75..9dab9677a80a 100644 --- a/book/tests/snapshots/snapshot__@language-features__case-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "# Can't yet format & compile\n\nfrom employees\nderive distance = case [\n city == \"Calgary\" => 0,\n city == \"Edmonton\" => 300,\n true => \"Unknown\",\n]\n" -input_file: book/tests/prql/language-features/case-1.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@language-features__coalesce-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap similarity index 68% rename from book/tests/snapshots/snapshot__@language-features__coalesce-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap index 6daa5339b530..5503518b55c7 100644 --- a/book/tests/snapshots/snapshot__@language-features__coalesce-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from orders\nderive amount ?? 0\n" -input_file: book/tests/prql/language-features/coalesce-0.prql --- SELECT *, COALESCE(amount, 0) FROM orders + diff --git a/book/tests/snapshots/snapshot__@language-features__dates-and-times-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@language-features__dates-and-times-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap index 340f30bf1f57..033ee31ffdd0 100644 --- a/book/tests/snapshots/snapshot__@language-features__dates-and-times-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive age_at_year_end = (@2022-12-31 - dob)\n" -input_file: book/tests/prql/language-features/dates-and-times-0.prql --- SELECT *, DATE '2022-12-31' - dob AS age_at_year_end FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__dates-and-times-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@language-features__dates-and-times-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap index 2c2f18a79a1e..37e1970cb15b 100644 --- a/book/tests/snapshots/snapshot__@language-features__dates-and-times-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from orders\nderive should_have_shipped_today = (order_time < @08:30)\n" -input_file: book/tests/prql/language-features/dates-and-times-1.prql --- SELECT *, order_time < TIME '08:30' AS should_have_shipped_today FROM orders + diff --git a/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap index 55668e17d93e..d67550773cb6 100644 --- a/book/tests/snapshots/snapshot__@language-features__dates-and-times-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from commits\nderive first_prql_commit = @2020-01-01T13:19:55-08:00\n" -input_file: book/tests/prql/language-features/dates-and-times-2.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@language-features__dates-and-times-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@language-features__dates-and-times-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap index a3a25183480b..8b39bb21363a 100644 --- a/book/tests/snapshots/snapshot__@language-features__dates-and-times-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from projects\nderive first_check_in = start + 10days\n" -input_file: book/tests/prql/language-features/dates-and-times-3.prql --- SELECT *, start + INTERVAL 10 DAY AS first_check_in FROM projects + diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@language-features__distinct-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap index 5e3488b70da3..582111718d00 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect department\ngroup department (\n take 1\n)\n" -input_file: book/tests/prql/language-features/distinct-0.prql --- SELECT DISTINCT department FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@language-features__distinct-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap index 15a58a07f008..ed2b6e9f87b9 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect department\ngroup department (take 1)\n" -input_file: book/tests/prql/language-features/distinct-1.prql --- SELECT DISTINCT department FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap similarity index 85% rename from book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap index 693c04dcf449..ec9e32e03e2c 100644 --- a/book/tests/snapshots/snapshot__@language-features__distinct-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "# youngest employee from each department\nfrom employees\ngroup department (\n sort age\n take 1\n)\n" -input_file: book/tests/prql/language-features/distinct-2.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__f-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@language-features__f-strings-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap index 051d83e14d1a..f1bfda0e4a6e 100644 --- a/book/tests/snapshots/snapshot__@language-features__f-strings-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect full_name = f\"{first_name} {last_name}\"\n" -input_file: book/tests/prql/language-features/f-strings-0.prql --- SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__f-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap similarity index 79% rename from book/tests/snapshots/snapshot__@language-features__f-strings-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap index ff9e275ebaf9..84324ae55337 100644 --- a/book/tests/snapshots/snapshot__@language-features__f-strings-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from web\nselect url = f\"http{tls}://www.{domain}.{tld}/{page}\"\n" -input_file: book/tests/prql/language-features/f-strings-1.prql --- SELECT CONCAT( @@ -16,3 +15,4 @@ SELECT ) AS url FROM web + diff --git a/book/tests/snapshots/snapshot__@language-features__null-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap similarity index 78% rename from book/tests/snapshots/snapshot__@language-features__null-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap index 7db4048fec29..04239f880972 100644 --- a/book/tests/snapshots/snapshot__@language-features__null-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter first_name == null\nfilter null != last_name\n" -input_file: book/tests/prql/language-features/null-0.prql --- SELECT * @@ -10,3 +9,4 @@ FROM WHERE first_name IS NULL AND last_name IS NOT NULL + diff --git a/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap similarity index 85% rename from book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap index f3d6e9a9f02c..468a1475016a 100644 --- a/book/tests/snapshots/snapshot__@language-features__ranges-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from events\nfilter (created_at | in @1776-07-04..@1787-09-17)\nfilter (magnitude | in 50..100)\nderive is_northern = (latitude | in 0..)\n" -input_file: book/tests/prql/language-features/ranges-0.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap similarity index 79% rename from book/tests/snapshots/snapshot__@transforms__take-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap index 8693c9d3c8ff..3d0c33aa0b0e 100644 --- a/book/tests/snapshots/snapshot__@transforms__take-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from orders\nsort [-value, created_at]\ntake 101..110\n" -input_file: book/tests/prql/transforms/take-1.prql --- SELECT * diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap similarity index 70% rename from book/tests/snapshots/snapshot__@language-features__s-strings-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap index 305be40f0809..b37f802598a4 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect db_version = s\"version()\"\n" -input_file: book/tests/prql/language-features/s-strings-0.prql --- SELECT version() AS db_version FROM my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap similarity index 68% rename from book/tests/snapshots/snapshot__@language-features__s-strings-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap index 79a6ff83ecef..68274ddf6d00 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\naggregate [average salary]\n" -input_file: book/tests/prql/language-features/s-strings-1.prql --- SELECT AVG(salary) FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap similarity index 85% rename from book/tests/snapshots/snapshot__@language-features__s-strings-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap index 5aad5f54eaf3..46b2693ffa99 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from de=dept_emp\njoin s=salaries side:left [\n (s.emp_no == de.emp_no),\n s\"\"\"({s.from_date}, {s.to_date})\n OVERLAPS\n ({de.from_date}, {de.to_date})\"\"\"\n]\n" -input_file: book/tests/prql/language-features/s-strings-2.prql --- SELECT de.*, @@ -10,3 +9,4 @@ FROM dept_emp AS de LEFT JOIN salaries AS s ON s.emp_no = de.emp_no AND (s.from_date, s.to_date) OVERLAPS (de.from_date, de.to_date) + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap similarity index 87% rename from book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap index 3d97e867fc17..93099ceca1a6 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from s\"SELECT DISTINCT ON first_name, id, age FROM employees ORDER BY age ASC\"\njoin s = s\"SELECT * FROM salaries\" [==id]\n" -input_file: book/tests/prql/language-features/s-strings-3.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap new file mode 100644 index 000000000000..90310f1f64a8 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom employees\nderive [\n has_valid_title = s\"regexp_contains(title, '([a-z0-9]*-){{2,}}')\"\n]\n" +--- +SELECT + *, + regexp_contains(title, '([a-z0-9]*-){2,}') AS has_valid_title +FROM + employees + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap similarity index 80% rename from book/tests/snapshots/snapshot__@language-features__s-strings-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap index 978a638e672c..fb3adff9254d 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"{gross_salary} / 365\"\n]\n" -input_file: book/tests/prql/language-features/s-strings-5.prql --- SELECT *, @@ -9,3 +8,4 @@ SELECT salary + benefits / 365 AS daily_rate FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__s-strings-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap similarity index 81% rename from book/tests/snapshots/snapshot__@language-features__s-strings-6.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap index 46bcfcd6e40a..40fbc41c342c 100644 --- a/book/tests/snapshots/snapshot__@language-features__s-strings-6.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = salary + benefits,\n daily_rate = s\"({gross_salary}) / 365\"\n]\n" -input_file: book/tests/prql/language-features/s-strings-6.prql --- SELECT *, @@ -9,3 +8,4 @@ SELECT (salary + benefits) / 365 AS daily_rate FROM employees + diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap index b3a371283e07..ecdb8feb1703 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__README-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = (salary + payroll_tax | as int),\n gross_salary_rounded = (gross_salary | round 0),\n time = s\"NOW()\", # an s-string, given no `now` function exists in PRQL\n]\n" -input_file: book/tests/prql/language-features/standard-library/README-0.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap index 904a45d549da..3e0b263aa879 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from_text \"\"\"\na,b,c\n1,2,3\n4,5,6\n\"\"\"\nderive [\n d = b + c,\n answer = 20 * 2 + 2,\n]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-0.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap index 670e58dfc204..112dba19d2e7 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "let temp_format_lookup = from_text format:csv \"\"\"\ncountry_code,format\nuk,C\nus,F\nlr,F\nde,C\n\"\"\"\n\nfrom temperatures\njoin temp_format_lookup [==country_code]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-1.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap similarity index 91% rename from book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap index becf706977bb..2a06e6465d95 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__from-text-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "let x = from_text format:json \"\"\"{\n \"columns\": [\"a\", \"b\", \"c\"],\n \"data\": [\n [1, \"x\", false],\n [4, \"y\", null]\n ]\n}\"\"\"\n\nlet y = from_text format:json \"\"\"\n [\n {\"a\": 1, \"m\": \"5\"},\n {\"a\": 4, \"n\": \"6\"}\n ]\n\"\"\"\n\nfrom x | join y [==a]\n" -input_file: book/tests/prql/language-features/standard-library/from-text-2.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap similarity index 86% rename from book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap index 5515357a6c0c..8f697534e2e8 100644 --- a/book/tests/snapshots/snapshot__@language-features__standard-library__loop-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from_text format:json '[{\"n\": 1 }]'\nloop (\n filter n<4\n select n = n+1\n)\n\n# returns [1, 2, 3, 4]\n" -input_file: book/tests/prql/language-features/standard-library/loop-0.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@language-features__strings-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap similarity index 69% rename from book/tests/snapshots/snapshot__@language-features__strings-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap index 7ef0767b367b..8e27a7bae79f 100644 --- a/book/tests/snapshots/snapshot__@language-features__strings-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect x = \"hello world\"\n" -input_file: book/tests/prql/language-features/strings-0.prql --- SELECT 'hello world' AS x FROM my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__strings-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap similarity index 69% rename from book/tests/snapshots/snapshot__@language-features__strings-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap index dc23e42969d7..4ef9ca322260 100644 --- a/book/tests/snapshots/snapshot__@language-features__strings-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect x = 'hello world'\n" -input_file: book/tests/prql/language-features/strings-1.prql --- SELECT 'hello world' AS x FROM my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__strings-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap similarity index 70% rename from book/tests/snapshots/snapshot__@language-features__strings-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap index 648630dd4c11..dcb4881cfd6b 100644 --- a/book/tests/snapshots/snapshot__@language-features__strings-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect x = '\"hello world\"'\n" -input_file: book/tests/prql/language-features/strings-2.prql --- SELECT '"hello world"' AS x FROM my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__strings-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap similarity index 73% rename from book/tests/snapshots/snapshot__@language-features__strings-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap index 9a8356d373ce..e49aa3eecd10 100644 --- a/book/tests/snapshots/snapshot__@language-features__strings-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect x = \"\"\"I said \"hello world\"!\"\"\"\n" -input_file: book/tests/prql/language-features/strings-3.prql --- SELECT 'I said "hello world"!' AS x FROM my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__strings-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@language-features__strings-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap index 25f04f7996c7..e6297e16c531 100644 --- a/book/tests/snapshots/snapshot__@language-features__strings-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from my_table\nselect x = \"\"\"\"\"I said \"\"\"hello world\"\"\"!\"\"\"\"\"\n" -input_file: book/tests/prql/language-features/strings-4.prql --- SELECT 'I said """hello world"""!' AS x FROM my_table + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap new file mode 100644 index 000000000000..b28334b03be5 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom my_table\nselect x = \"\\t\\tline ends here\\n \\\\ \"\n" +--- +SELECT + ' line ends here + \ ' AS x +FROM + my_table + diff --git a/book/tests/snapshots/snapshot__@language-features__target-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap similarity index 74% rename from book/tests/snapshots/snapshot__@language-features__target-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap index cab9b249fc4e..31eb52b4b0e7 100644 --- a/book/tests/snapshots/snapshot__@language-features__target-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" -input_file: book/tests/prql/language-features/target-0.prql --- SELECT * @@ -11,3 +10,4 @@ ORDER BY age LIMIT 10 + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap new file mode 100644 index 000000000000..1319313f929f --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nprql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" +--- +SELECT + TOP (10) * +FROM + employees +ORDER BY + age + diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap new file mode 100644 index 000000000000..36f4e8f260f1 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nprql version:\"0.6.0\"\n\nfrom employees\n" +--- +SELECT + * +FROM + employees + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap new file mode 100644 index 000000000000..233a443272ed --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfunc fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (fahrenheit_to_celsius temp_f)\n" +--- +SELECT + *, + (temp_f - 32) / 1.8 AS temp_c +FROM + cities + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap new file mode 100644 index 000000000000..d0d37fc7950c --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (interp 1600 sat_score),\n sat_proportion_2 = (interp low:0 1600 sat_score),\n]\n" +--- +SELECT + *, + (sat_score - 0) / 1600 AS sat_proportion_1, + (sat_score - 0) / 1600 AS sat_proportion_2 +FROM + students + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap new file mode 100644 index 000000000000..03a3eca6f2fd --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "func interp low:0 high x -> (x - low) / (high - low)\n\nfrom students\nderive [\n sat_proportion_1 = (sat_score | interp 1600),\n sat_proportion_2 = (sat_score | interp low:0 1600),\n]\n" +--- +SELECT + *, + (sat_score - 0) / 1600 AS sat_proportion_1, + (sat_score - 0) / 1600 AS sat_proportion_2 +FROM + students + diff --git a/book/tests/snapshots/snapshot__@queries__functions-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap similarity index 81% rename from book/tests/snapshots/snapshot__@queries__functions-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap index 65115fa5932e..263a8b82b296 100644 --- a/book/tests/snapshots/snapshot__@queries__functions-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\n\nfrom cities\nderive temp_c = (temp_f | fahrenheit_to_celsius)\n" -input_file: book/tests/prql/queries/functions-3.prql --- SELECT *, (temp_f - 32) / 1.8 AS temp_c FROM cities + diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap new file mode 100644 index 000000000000..ac68df1425bc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "func fahrenheit_to_celsius temp -> (temp - 32) / 1.8\nfunc interp low:0 high x -> (x - low) / (high - low)\n\nfrom kettles\nderive boiling_proportion = (temp_c | fahrenheit_to_celsius | interp 100)\n" +--- +SELECT + *, + ((temp_c - 32) / 1.8 - 0) / 100 AS boiling_proportion +FROM + kettles + diff --git a/book/tests/snapshots/snapshot__@queries__functions-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@queries__functions-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap index 043fb613eb3f..05ce9c885a1c 100644 --- a/book/tests/snapshots/snapshot__@queries__functions-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "func cost_share cost -> cost / cost_total\n\nfrom costs\nselect [materials, labor, overhead, cost_total]\nderive [\n materials_share = (cost_share materials),\n labor_share = (cost_share labor),\n overhead_share = (cost_share overhead),\n]\n" -input_file: book/tests/prql/queries/functions-5.prql --- SELECT materials, diff --git a/book/tests/snapshots/snapshot__@transforms__from-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap similarity index 65% rename from book/tests/snapshots/snapshot__@transforms__from-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap index efa18103e60b..ef73243f301a 100644 --- a/book/tests/snapshots/snapshot__@transforms__from-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\n" -input_file: book/tests/prql/transforms/from-0.prql --- SELECT * FROM employees + diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap similarity index 77% rename from book/tests/snapshots/snapshot__@queries__pipelines-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap index 6daec46c4b39..9711846bf22b 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive gross_salary = (salary + payroll_tax)\n" -input_file: book/tests/prql/queries/pipelines-1.prql --- SELECT *, salary + payroll_tax AS gross_salary FROM employees + diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap similarity index 90% rename from book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap index 8a7e0fd99bc5..ca1e515fde69 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from e = employees\nderive gross_salary = (salary + payroll_tax)\nsort gross_salary\ntake 10\njoin d = department [==dept_no]\nselect [e.name, gross_salary, d.name]\n" -input_file: book/tests/prql/queries/pipelines-2.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap similarity index 88% rename from book/tests/snapshots/snapshot__@queries__variables-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap index ca97469b4749..378a0b651fca 100644 --- a/book/tests/snapshots/snapshot__@queries__variables-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "let top_50 = (\n from employees\n sort salary\n take 50\n aggregate [total_salary = sum salary]\n)\n\nfrom top_50 # Starts a new pipeline\n" -input_file: book/tests/prql/queries/variables-0.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@queries__variables-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap similarity index 88% rename from book/tests/snapshots/snapshot__@queries__variables-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap index 143fdae66f49..5a56be225071 100644 --- a/book/tests/snapshots/snapshot__@queries__variables-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "let grouping = s\"\"\"\n SELECT SUM(a)\n FROM tbl\n GROUP BY\n GROUPING SETS\n ((b, c, d), (d), (b, d))\n\"\"\"\n\nfrom grouping\n" -input_file: book/tests/prql/queries/variables-1.prql --- WITH table_0 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@syntax-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@syntax-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap index bc4245d27e99..ff6897edf956 100644 --- a/book/tests/snapshots/snapshot__@syntax-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter department == \"Product\"\nselect [first_name, last_name]\n" -input_file: book/tests/prql/syntax-0.prql --- SELECT first_name, @@ -10,3 +9,4 @@ FROM employees WHERE department = 'Product' + diff --git a/book/tests/snapshots/snapshot__@syntax-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@syntax-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap index 25db89b07dac..7684886350f9 100644 --- a/book/tests/snapshots/snapshot__@syntax-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees | filter department == \"Product\" | select [first_name, last_name]\n" -input_file: book/tests/prql/syntax-1.prql --- SELECT first_name, @@ -10,3 +9,4 @@ FROM employees WHERE department = 'Product' + diff --git a/book/tests/snapshots/snapshot__@syntax-10.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap similarity index 78% rename from book/tests/snapshots/snapshot__@syntax-10.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap index 1b4420bac18f..142f58a54334 100644 --- a/book/tests/snapshots/snapshot__@syntax-10.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "prql target:sql.mysql\nfrom employees\nselect `first name`\n" -input_file: book/tests/prql/syntax-10.prql --- SELECT `first name` diff --git a/book/tests/snapshots/snapshot__@syntax-11.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap similarity index 78% rename from book/tests/snapshots/snapshot__@syntax-11.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap index 3e60cedc7a74..cc696fab2ab0 100644 --- a/book/tests/snapshots/snapshot__@syntax-11.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "prql target:sql.postgres\nfrom employees\nselect `first name`\n" -input_file: book/tests/prql/syntax-11.prql --- SELECT "first name" diff --git a/book/tests/snapshots/snapshot__@syntax-12.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@syntax-12.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap index 7372f8f76f8a..afd329815111 100644 --- a/book/tests/snapshots/snapshot__@syntax-12.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from `dir/*.parquet`\n" -input_file: book/tests/prql/syntax-12.prql --- SELECT * diff --git a/book/tests/snapshots/snapshot__@syntax-13.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap similarity index 89% rename from book/tests/snapshots/snapshot__@syntax-13.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap index 9f4f882ffaca..0d3be609df1c 100644 --- a/book/tests/snapshots/snapshot__@syntax-13.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "prql target:sql.bigquery\nfrom `project-foo.dataset.table`\njoin `project-bar.dataset.table` [==col_bax]\n" -input_file: book/tests/prql/syntax-13.prql --- SELECT `project-foo.dataset.table`.*, diff --git a/book/tests/snapshots/snapshot__@syntax-14.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap similarity index 71% rename from book/tests/snapshots/snapshot__@syntax-14.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap index cc5fe4f92a62..dd305dbdadf6 100644 --- a/book/tests/snapshots/snapshot__@syntax-14.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from `music.albums`\n" -input_file: book/tests/prql/syntax-14.prql --- SELECT * diff --git a/book/tests/snapshots/snapshot__@syntax-15.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@syntax-15.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap index 0ee085bcefeb..4f7d34ea2e79 100644 --- a/book/tests/snapshots/snapshot__@syntax-15.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter id == $1\n" -input_file: book/tests/prql/syntax-15.prql --- SELECT * diff --git a/book/tests/snapshots/snapshot__@syntax-16.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap similarity index 81% rename from book/tests/snapshots/snapshot__@syntax-16.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap index 5bae6263183d..e20d96b994cb 100644 --- a/book/tests/snapshots/snapshot__@syntax-16.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from numbers\nselect [\n small = 1.000_000_1,\n big = 5_000_000,\n]\n" -input_file: book/tests/prql/syntax-16.prql --- SELECT 1.0000001 AS small, diff --git a/book/tests/snapshots/snapshot__@syntax-17.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@syntax-17.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap index a944999d43cd..da5f149207ad 100644 --- a/book/tests/snapshots/snapshot__@syntax-17.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "std.from my_table\nstd.select [from = my_table.a, take = my_table.b]\nstd.take 3\n" -input_file: book/tests/prql/syntax-17.prql --- SELECT a AS "from", diff --git a/book/tests/snapshots/snapshot__@syntax-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap similarity index 85% rename from book/tests/snapshots/snapshot__@syntax-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap index c30a9bccb908..034438f6196e 100644 --- a/book/tests/snapshots/snapshot__@syntax-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from numbers\nderive [x = 1, y = 2]\nderive [\n a = x,\n b = y\n]\nderive [\n c = a,\n d = b,\n]\n" -input_file: book/tests/prql/syntax-2.prql --- SELECT *, @@ -13,3 +12,4 @@ SELECT 2 AS d FROM numbers + diff --git a/book/tests/snapshots/snapshot__@syntax-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@syntax-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap index 9927316e1bc0..b24a1679b7c9 100644 --- a/book/tests/snapshots/snapshot__@syntax-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect [first_name]\n" -input_file: book/tests/prql/syntax-3.prql --- SELECT first_name FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__select-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap similarity index 70% rename from book/tests/snapshots/snapshot__@transforms__select-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap index e2ca00c69505..9621e1555906 100644 --- a/book/tests/snapshots/snapshot__@transforms__select-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect first_name\n" -input_file: book/tests/prql/transforms/select-2.prql --- SELECT first_name FROM employees + diff --git a/book/tests/snapshots/snapshot__@syntax-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap similarity index 89% rename from book/tests/snapshots/snapshot__@syntax-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap index 9095768d6603..7fe2bb668def 100644 --- a/book/tests/snapshots/snapshot__@syntax-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from foo\nselect [\n circumference = diameter * 3.14159,\n color,\n]\nfilter circumference > 10 and color != \"red\"\n" -input_file: book/tests/prql/syntax-5.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap new file mode 100644 index 000000000000..56a6f70b79a0 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap @@ -0,0 +1,20 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom employees\n# Requires parentheses, because it's contains a pipe\nderive is_proximate = (distance | in 0..20)\n# Requires parentheses, because it's a function call\nderive total_distance = (sum distance)\n# `??` doesn't require parentheses, as it's not a function call\nderive min_capped_distance = (min distance ?? 5)\n# No parentheses needed, because no function call\nderive travel_time = distance / 40\n# No inner parentheses needed around `1+1` because no function call\nderive distance_rounded_2_dp = (round 1+1 distance)\nderive [\n # Requires parentheses, because it contains a pipe\n is_far = (distance | in 100..),\n # The left value of the range requires parentheses,\n # because of the minus sign\n is_negative = (distance | in (-100..0)),\n # ...this is equivalent\n is_negative = (distance | in (-100)..0),\n # Doesn't require parentheses, because it's in a list (confusing, see footnote)!\n average_distance = average distance,\n]\n# Requires parentheses because of the minus sign\nsort (-distance)\n# A list is fine too\nsort [-distance]\n" +--- +SELECT + *, + distance BETWEEN 0 AND 20 AS is_proximate, + SUM(distance) OVER () AS total_distance, + MIN(COALESCE(distance, 5)) OVER () AS min_capped_distance, + distance / 40 AS travel_time, + ROUND(distance, 2) AS distance_rounded_2_dp, + distance >= 100 AS is_far, + distance BETWEEN -100 AND 0, + distance BETWEEN -100 AND 0 AS is_negative, + AVG(distance) OVER () AS average_distance +FROM + employees +ORDER BY + distance DESC + diff --git a/book/tests/snapshots/snapshot__@syntax-7.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap similarity index 89% rename from book/tests/snapshots/snapshot__@syntax-7.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap index d52ff256c269..d796d80ca8d8 100644 --- a/book/tests/snapshots/snapshot__@syntax-7.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "# Error expected\n\nfrom employees\nderive total_distance = sum distance\n" -input_file: book/tests/prql/syntax-7.prql --- Error: โ•ญโ”€[:4:29] diff --git a/book/tests/snapshots/snapshot__@syntax-8.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap similarity index 86% rename from book/tests/snapshots/snapshot__@syntax-8.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap index 9e7c1486e2a5..eda9f5af0327 100644 --- a/book/tests/snapshots/snapshot__@syntax-8.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" -input_file: book/tests/prql/syntax-8.prql --- SELECT title, diff --git a/book/tests/snapshots/snapshot__@syntax-9.prql.snap b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap similarity index 79% rename from book/tests/snapshots/snapshot__@syntax-9.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap index 08fc131cabca..86e0b07ded9c 100644 --- a/book/tests/snapshots/snapshot__@syntax-9.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees # Comment 1\n# Comment 2\naggregate [average salary]\n" -input_file: book/tests/prql/syntax-9.prql --- SELECT AVG(salary) diff --git a/book/tests/snapshots/snapshot__@transforms__aggregate-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@transforms__aggregate-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap index 3e9550e9528f..f8d6249f2964 100644 --- a/book/tests/snapshots/snapshot__@transforms__aggregate-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\naggregate [\n average salary,\n ct = count\n]\n" -input_file: book/tests/prql/transforms/aggregate-0.prql --- SELECT AVG(salary), COUNT(*) AS ct FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__group-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@transforms__group-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap index 1ce5fa06bce4..eda9f5af0327 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" -input_file: book/tests/prql/transforms/group-0.prql --- SELECT title, @@ -13,3 +12,4 @@ FROM GROUP BY title, country + diff --git a/book/tests/snapshots/snapshot__@transforms__aggregate-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap similarity index 74% rename from book/tests/snapshots/snapshot__@transforms__aggregate-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap index 9cd168662d59..1be9f1cc15df 100644 --- a/book/tests/snapshots/snapshot__@transforms__aggregate-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [avg_sal = average salary]\n" -input_file: book/tests/prql/transforms/aggregate-2.prql --- SELECT *, AVG(salary) OVER () AS avg_sal FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__append-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@transforms__append-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap index e082d762a2a6..0c40c37cfd24 100644 --- a/book/tests/snapshots/snapshot__@transforms__append-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees_1\nappend employees_2\n" -input_file: book/tests/prql/transforms/append-0.prql --- SELECT * @@ -13,3 +12,4 @@ SELECT * FROM employees_2 + diff --git a/book/tests/snapshots/snapshot__@transforms__append-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__@transforms__append-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap index 45a979b98908..06806c9b0b78 100644 --- a/book/tests/snapshots/snapshot__@transforms__append-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees_1\nremove employees_2\n" -input_file: book/tests/prql/transforms/append-1.prql --- SELECT * @@ -13,3 +12,4 @@ SELECT * FROM employees_2 AS b + diff --git a/book/tests/snapshots/snapshot__@transforms__append-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap similarity index 77% rename from book/tests/snapshots/snapshot__@transforms__append-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap index f0fe1a1555f9..9b8906ab950f 100644 --- a/book/tests/snapshots/snapshot__@transforms__append-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees_1\nintersect employees_2\n" -input_file: book/tests/prql/transforms/append-2.prql --- SELECT * @@ -13,3 +12,4 @@ SELECT * FROM employees_2 AS b + diff --git a/book/tests/snapshots/snapshot__@transforms__derive-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap similarity index 77% rename from book/tests/snapshots/snapshot__@transforms__derive-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap index 452801423ae4..7d9fe604e6e7 100644 --- a/book/tests/snapshots/snapshot__@transforms__derive-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive gross_salary = salary + payroll_tax\n" -input_file: book/tests/prql/transforms/derive-0.prql --- SELECT *, salary + payroll_tax AS gross_salary FROM employees + diff --git a/book/tests/snapshots/snapshot__@examples__list-equivalence-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@examples__list-equivalence-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap index 5662e8a95ef6..b99c1d44b18a 100644 --- a/book/tests/snapshots/snapshot__@examples__list-equivalence-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nderive [\n gross_salary = salary + payroll_tax,\n gross_cost = gross_salary + benefits_cost\n]\n" -input_file: book/tests/prql/examples/list-equivalence-2.prql --- SELECT *, @@ -9,3 +8,4 @@ SELECT salary + payroll_tax + benefits_cost AS gross_cost FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__filter-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap similarity index 71% rename from book/tests/snapshots/snapshot__@transforms__filter-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap index be2a38821ec6..5d75ef6cf24c 100644 --- a/book/tests/snapshots/snapshot__@transforms__filter-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter age > 25\n" -input_file: book/tests/prql/transforms/filter-0.prql --- SELECT * @@ -9,3 +8,4 @@ FROM employees WHERE age > 25 + diff --git a/book/tests/snapshots/snapshot__@transforms__filter-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap similarity index 77% rename from book/tests/snapshots/snapshot__@transforms__filter-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap index 86f72be77cd1..6696a54facce 100644 --- a/book/tests/snapshots/snapshot__@transforms__filter-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter (age > 25 or department != \"IT\")\n" -input_file: book/tests/prql/transforms/filter-1.prql --- SELECT * @@ -10,3 +9,4 @@ FROM WHERE age > 25 OR department <> 'IT' + diff --git a/book/tests/snapshots/snapshot__@transforms__filter-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap similarity index 74% rename from book/tests/snapshots/snapshot__@transforms__filter-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap index c5dda610f1bc..f90f4c01e310 100644 --- a/book/tests/snapshots/snapshot__@transforms__filter-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter (age | in 25..40)\n" -input_file: book/tests/prql/transforms/filter-2.prql --- SELECT * @@ -9,3 +8,4 @@ FROM employees WHERE age BETWEEN 25 AND 40 + diff --git a/book/tests/snapshots/snapshot__@queries__pipelines-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap similarity index 64% rename from book/tests/snapshots/snapshot__@queries__pipelines-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap index 0d1764763376..ef73243f301a 100644 --- a/book/tests/snapshots/snapshot__@queries__pipelines-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\n" -input_file: book/tests/prql/queries/pipelines-0.prql --- SELECT * FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__from-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap similarity index 72% rename from book/tests/snapshots/snapshot__@transforms__from-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap index f865a3f558d7..31af40868d65 100644 --- a/book/tests/snapshots/snapshot__@transforms__from-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from e = employees\nselect e.first_name\n" -input_file: book/tests/prql/transforms/from-1.prql --- SELECT first_name FROM employees AS e + diff --git a/book/tests/snapshots/snapshot__@transforms__aggregate-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@transforms__aggregate-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap index b0ed3d496abb..eda9f5af0327 100644 --- a/book/tests/snapshots/snapshot__@transforms__aggregate-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup [title, country] (\n aggregate [\n average salary,\n ct = count\n ]\n)\n" -input_file: book/tests/prql/transforms/aggregate-1.prql --- SELECT title, @@ -13,3 +12,4 @@ FROM GROUP BY title, country + diff --git a/book/tests/snapshots/snapshot__@transforms__group-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap similarity index 74% rename from book/tests/snapshots/snapshot__@transforms__group-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap index 4e6ea09db0db..325ee4f4b76e 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort join_date\ntake 1\n" -input_file: book/tests/prql/transforms/group-1.prql --- SELECT * @@ -11,3 +10,4 @@ ORDER BY join_date LIMIT 1 + diff --git a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap similarity index 87% rename from book/tests/snapshots/snapshot__@transforms__group-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap index 03289443cc04..a25e11fedceb 100644 --- a/book/tests/snapshots/snapshot__@transforms__group-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup role (\n sort join_date # taken from above\n take 1\n)\n" -input_file: book/tests/prql/transforms/group-2.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@transforms__join-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@transforms__join-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap index b5e14abc2d70..455f56a1eb72 100644 --- a/book/tests/snapshots/snapshot__@transforms__join-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\njoin side:left positions [employees.id==positions.employee_id]\n" -input_file: book/tests/prql/transforms/join-0.prql --- SELECT employees.*, @@ -9,3 +8,4 @@ SELECT FROM employees LEFT JOIN positions ON employees.id = positions.employee_id + diff --git a/book/tests/snapshots/snapshot__@transforms__join-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap similarity index 81% rename from book/tests/snapshots/snapshot__@transforms__join-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap index 4415ba7cafcb..b4c86487a35d 100644 --- a/book/tests/snapshots/snapshot__@transforms__join-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\njoin side:left p=positions [employees.id==p.employee_id]\n" -input_file: book/tests/prql/transforms/join-1.prql --- SELECT employees.*, @@ -9,3 +8,4 @@ SELECT FROM employees LEFT JOIN positions AS p ON employees.id = p.employee_id + diff --git a/book/tests/snapshots/snapshot__@transforms__join-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap similarity index 80% rename from book/tests/snapshots/snapshot__@transforms__join-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap index 8a9c3bf8c180..fe00d3aab1cf 100644 --- a/book/tests/snapshots/snapshot__@transforms__join-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\njoin positions [==emp_no]\n" -input_file: book/tests/prql/transforms/join-2.prql --- SELECT employees.*, @@ -9,3 +8,4 @@ SELECT FROM employees JOIN positions ON employees.emp_no = positions.emp_no + diff --git a/book/tests/snapshots/snapshot__@transforms__select-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap similarity index 77% rename from book/tests/snapshots/snapshot__@transforms__select-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap index 1247bb79dcbc..480e714b0ffe 100644 --- a/book/tests/snapshots/snapshot__@transforms__select-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect name = f\"{first_name} {last_name}\"\n" -input_file: book/tests/prql/transforms/select-0.prql --- SELECT CONCAT(first_name, ' ', last_name) AS name FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__select-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@transforms__select-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap index ba5a1e89bb47..69d637694b3f 100644 --- a/book/tests/snapshots/snapshot__@transforms__select-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect [\n name = f\"{first_name} {last_name}\",\n age_eoy = dob - @2022-12-31,\n]\n" -input_file: book/tests/prql/transforms/select-1.prql --- SELECT CONCAT(first_name, ' ', last_name) AS name, dob - DATE '2022-12-31' AS age_eoy FROM employees + diff --git a/book/tests/snapshots/snapshot__@internals__name-resolving-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap similarity index 67% rename from book/tests/snapshots/snapshot__@internals__name-resolving-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap index 8343f6242c89..9621e1555906 100644 --- a/book/tests/snapshots/snapshot__@internals__name-resolving-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap @@ -1,9 +1,9 @@ --- source: book/tests/snapshot.rs expression: "from employees\nselect first_name\n" -input_file: book/tests/prql/internals/name-resolving-0.prql --- SELECT first_name FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__select-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap similarity index 75% rename from book/tests/snapshots/snapshot__@transforms__select-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap index d016d5f07e32..659d581346a5 100644 --- a/book/tests/snapshots/snapshot__@transforms__select-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap @@ -1,10 +1,10 @@ --- source: book/tests/snapshot.rs expression: "from e=employees\nselect [e.first_name, e.last_name]\n" -input_file: book/tests/prql/transforms/select-3.prql --- SELECT first_name, last_name FROM employees AS e + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap new file mode 100644 index 000000000000..31ea529b998a --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap @@ -0,0 +1,11 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nprql target:sql.bigquery\nfrom tracks\nselect ![milliseconds,bytes]\n" +--- +SELECT + * +EXCEPT + (milliseconds, bytes) +FROM + tracks + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap new file mode 100644 index 000000000000..019026c050fa --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap @@ -0,0 +1,10 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom tracks\nselect [track_id, title, composer, bytes]\nselect ![title, composer]\n" +--- +SELECT + track_id, + bytes +FROM + tracks + diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap new file mode 100644 index 000000000000..2640271d11dc --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap @@ -0,0 +1,9 @@ +--- +source: book/tests/snapshot.rs +expression: "# Can't yet format & compile\n\nfrom artists\nderive nick = name\nselect ![artists.*]\n" +--- +SELECT + name AS nick +FROM + artists + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap similarity index 70% rename from book/tests/snapshots/snapshot__@transforms__sort-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap index fd9d4e99f2e9..25f7e08c2d90 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort age\n" -input_file: book/tests/prql/transforms/sort-0.prql --- SELECT * @@ -9,3 +8,4 @@ FROM employees ORDER BY age + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap similarity index 71% rename from book/tests/snapshots/snapshot__@transforms__sort-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap index 25afb720d44e..084bfc47f8f6 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort [-age]\n" -input_file: book/tests/prql/transforms/sort-1.prql --- SELECT * @@ -9,3 +8,4 @@ FROM employees ORDER BY age DESC + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__@transforms__sort-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap index 11975c45e9d6..b22c7b0de187 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort [age, -tenure, +salary]\n" -input_file: book/tests/prql/transforms/sort-2.prql --- SELECT * @@ -11,3 +10,4 @@ ORDER BY age, tenure DESC, salary + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap similarity index 79% rename from book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap index fb7acd653ec6..d1b930a965a2 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort [s\"substr({first_name}, 2, 5)\"]\n" -input_file: book/tests/prql/transforms/sort-3.prql --- SELECT *, diff --git a/book/tests/snapshots/snapshot__@transforms__sort-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap similarity index 81% rename from book/tests/snapshots/snapshot__@transforms__sort-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap index 63bf1bd5a668..802b2a250f26 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort tenure\nderive name = f\"{first_name} {last_name}\"\n" -input_file: book/tests/prql/transforms/sort-4.prql --- SELECT *, @@ -10,3 +9,4 @@ FROM employees ORDER BY tenure + diff --git a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap similarity index 86% rename from book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap index b969c19b2a4d..b01e3c7e4a87 100644 --- a/book/tests/snapshots/snapshot__@transforms__sort-5.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort tenure\njoin locations [==employee_id]\n" -input_file: book/tests/prql/transforms/sort-5.prql --- WITH table_1 AS ( SELECT diff --git a/book/tests/snapshots/snapshot__@transforms__take-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap similarity index 69% rename from book/tests/snapshots/snapshot__@transforms__take-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap index 8f2ff2547ca5..01ea3a5179e1 100644 --- a/book/tests/snapshots/snapshot__@transforms__take-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ntake 10\n" -input_file: book/tests/prql/transforms/take-0.prql --- SELECT * @@ -9,3 +8,4 @@ FROM employees LIMIT 10 + diff --git a/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap similarity index 76% rename from book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap index 7c8542dfe016..3d0c33aa0b0e 100644 --- a/book/tests/snapshots/snapshot__@language-features__ranges-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from orders\nsort [-value, created_at]\ntake 101..110\n" -input_file: book/tests/prql/language-features/ranges-1.prql --- SELECT * diff --git a/book/tests/snapshots/snapshot__@transforms__window-0.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap similarity index 86% rename from book/tests/snapshots/snapshot__@transforms__window-0.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap index ce88b096a0dd..8e596631305e 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-0.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup employee_id (\n sort month\n window rolling:12 (\n derive [trail_12_m_comp = sum paycheck]\n )\n)\n" -input_file: book/tests/prql/transforms/window-0.prql --- SELECT *, @@ -12,3 +11,4 @@ SELECT ) AS trail_12_m_comp FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__window-1.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap similarity index 91% rename from book/tests/snapshots/snapshot__@transforms__window-1.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap index c89b2c172602..2d48f3d23922 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-1.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from orders\nsort day\nwindow rows:-3..3 (\n derive [centered_weekly_average = average value]\n)\ngroup [order_month] (\n sort day\n window expanding:true (\n derive [monthly_running_total = sum value]\n )\n)\n" -input_file: book/tests/prql/transforms/window-1.prql --- SELECT *, @@ -16,3 +15,4 @@ SELECT ) AS monthly_running_total FROM orders + diff --git a/book/tests/snapshots/snapshot__@transforms__window-2.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__@transforms__window-2.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap index b99ff3b65568..a4a8a7c5c0c3 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-2.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nsort age\nderive rnk = rank\n" -input_file: book/tests/prql/transforms/window-2.prql --- SELECT *, @@ -13,3 +12,4 @@ FROM employees ORDER BY age + diff --git a/book/tests/snapshots/snapshot__@transforms__window-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap similarity index 84% rename from book/tests/snapshots/snapshot__@transforms__window-3.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap index 4e5e3cc14c09..b48b206027fc 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-3.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\ngroup department (\n sort age\n derive rnk = rank\n)\n" -input_file: book/tests/prql/transforms/window-3.prql --- SELECT *, @@ -12,3 +11,4 @@ SELECT ) AS rnk FROM employees + diff --git a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap similarity index 83% rename from book/tests/snapshots/snapshot__@transforms__window-4.prql.snap rename to book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap index 0dcf1866c987..f1c96b857e54 100644 --- a/book/tests/snapshots/snapshot__@transforms__window-4.prql.snap +++ b/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap @@ -1,7 +1,6 @@ --- source: book/tests/snapshot.rs expression: "from employees\nfilter salary < (average salary)\n" -input_file: book/tests/prql/transforms/window-4.prql --- WITH table_1 AS ( SELECT diff --git a/prql-compiler/benches/bench.rs b/prql-compiler/benches/bench.rs index bda16db184c0..a0ec550d6fb5 100644 --- a/prql-compiler/benches/bench.rs +++ b/prql-compiler/benches/bench.rs @@ -16,7 +16,7 @@ cfg_if::cfg_if! { use criterion::{criterion_group, criterion_main, Criterion}; use prql_compiler::*; - const CONTENT: &str = include_str!("../../book/tests/prql/examples/variables-0.prql"); + const CONTENT: &str = include_str!("../examples/compile-files/queries/variables.prql"); fn compile_query() -> Result { compile(CONTENT, &Options::default()) } diff --git a/book/tests/prql/examples/variables-0.prql b/prql-compiler/examples/compile-files/queries/variables.prql similarity index 100% rename from book/tests/prql/examples/variables-0.prql rename to prql-compiler/examples/compile-files/queries/variables.prql diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 219ea1e34cea..6f4e0f27ad76 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -201,23 +201,9 @@ mod test { #[test] fn test_pipeline_parse_tree() { - assert_yaml_snapshot!(parse( - // It's useful to have canonical examples rather than copy-pasting - // everything, so we reference the prql file here. But a downside of - // this implementation is: if there's an error in extracting the - // example from the docs into the file specified here, this test - // won't compile. Because `cargo insta test --accept` on the - // workspace โ€” which extracts the example โ€” requires compiling this, - // we can get stuck. - // - // Breaking out of that requires running this `cargo insta test - // --accept` within `book`, and then running it on the workspace. - // `task test-all` does this. - // - // If we change this, it would great if we can retain having - // examples tested in the docs. - include_str!("../../../book/tests/prql/examples/variables-0.prql"), - ) + assert_yaml_snapshot!(parse(include_str!( + "../../examples/compile-files/queries/variables.prql" + )) .unwrap()); } diff --git a/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap b/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap index d973041eff4d..16a11bf1858f 100644 --- a/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap +++ b/prql-compiler/src/parser/snapshots/prql_compiler__parser__test__pipeline_parse_tree.snap @@ -1,6 +1,6 @@ --- source: prql-compiler/src/parser/mod.rs -expression: "parse(&include_str!(\"../../../book/tests/prql/examples/variables-0.prql\")).unwrap()" +expression: "parse(include_str!(\"../../examples/compile-files/queries/variables.prql\")).unwrap()" --- - Main: Pipeline: From f328d7ade24a5bb8c258194f256dd080a3dea22c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 11 Mar 2023 11:30:36 -0800 Subject: [PATCH 159/184] web: Remove underline from logo (#2093) Ref https://github.com/PRQL/prql/pull/1667. Even if we want it for the headings, it's not the logo. We could replace the logo with an image of the text (which we have available) if we want to be strict about text links having underline? --- website/themes/prql-theme/static/style.css | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/website/themes/prql-theme/static/style.css b/website/themes/prql-theme/static/style.css index 14458343e251..77fe18979bfa 100644 --- a/website/themes/prql-theme/static/style.css +++ b/website/themes/prql-theme/static/style.css @@ -155,8 +155,9 @@ pre ::-webkit-scrollbar-thumb:hover { border-bottom: 1px solid rgba(0, 0, 0, 0.125); } -#header .logo img { +#header .logo { max-height: 50px; + text-decoration: none; } #header .logo h1 { From 12a488a94d0868333ca6253c468c58d5dcc24055 Mon Sep 17 00:00:00 2001 From: eitsupi <50911393+eitsupi@users.noreply.github.com> Date: Sun, 12 Mar 2023 08:33:18 +0900 Subject: [PATCH 160/184] fix: ensure use chumsky 0.9.2 or later (#2110) * fix: bump chumsky to 0.9.2 * docs: update changelog * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 3 +++ prql-compiler/Cargo.toml | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d42e02820d82..6a242e94d894 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ **Fixes**: +- The version specification of the dependent Chumsky was bumped from `0.9.0` to + `0.9.2`. `0.9.0` has a bug that causes an infinite loop. (@eitsupi, #2110) + **Documentation**: **Web**: diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index 0bcf64871e0d..15fee828a11e 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -32,9 +32,9 @@ strum_macros = "0.24.0" # Chumsky issues in wasm (though we only see it when compiling on MacOS) [target.'cfg(not(target_family="wasm"))'.dependencies] -chumsky = "0.9.0" +chumsky = "0.9.2" [target.'cfg(target_family="wasm")'.dependencies] -chumsky = {version = "0.9.0", features = ["ahash", "std"], default-features = false} +chumsky = {version = "0.9.2", features = ["ahash", "std"], default-features = false} [dev-dependencies] cfg-if = "1.0" From 29b37828132bbeea11d5e9d8cb18f74decd47a7c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 11 Mar 2023 15:50:53 -0800 Subject: [PATCH 161/184] fix: Don't use `DISTINCT` where group & select cols don't match (#2109) * fix: Don't use `DISTINCT` where group & select cols don't match --- CHANGELOG.md | 3 ++ book/src/language-features/distinct.md | 8 +++ ...l__language-features__distinct-3.prql.snap | 18 +++++++ prql-compiler/src/ast/rq/ids.rs | 2 +- prql-compiler/src/sql/preprocess.rs | 17 +++++-- prql-compiler/src/test.rs | 51 +++++++++++++++++-- 6 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a242e94d894..c4c3974c2841 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,9 @@ **Fixes**: +- No longer incorrectly compile to `DISTINCT` when a `take 1` refers to a + different set of columns than are in the `group`. (@max-sixty, with thanks to + @cottrell, #2109) - The version specification of the dependent Chumsky was bumped from `0.9.0` to `0.9.2`. `0.9.0` has a bug that causes an infinite loop. (@eitsupi, #2110) diff --git a/book/src/language-features/distinct.md b/book/src/language-features/distinct.md index 598360aa0ab9..4a05bd81235f 100644 --- a/book/src/language-features/distinct.md +++ b/book/src/language-features/distinct.md @@ -34,6 +34,14 @@ group department ( ) ``` +Note that we can't always compile to `DISTINCT`; when the columns in the `group` +aren't all the available columns, we need to use a window function: + +```prql +from employees +group [first_name, last_name] (take 1) +``` + ## Roadmap When using Postgres dialect, we are planning to compile: diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap new file mode 100644 index 000000000000..9bb590d55652 --- /dev/null +++ b/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap @@ -0,0 +1,18 @@ +--- +source: book/tests/snapshot.rs +expression: "from employees\ngroup [first_name, last_name] (take 1)\n" +--- +WITH table_1 AS ( + SELECT + *, + ROW_NUMBER() OVER (PARTITION BY first_name, last_name) AS _expr_0 + FROM + employees +) +SELECT + * +FROM + table_1 AS table_0 +WHERE + _expr_0 <= 1 + diff --git a/prql-compiler/src/ast/rq/ids.rs b/prql-compiler/src/ast/rq/ids.rs index ecd27fb7245d..faced8329f5d 100644 --- a/prql-compiler/src/ast/rq/ids.rs +++ b/prql-compiler/src/ast/rq/ids.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; /// Column id -#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Ord, PartialOrd)] pub struct CId(usize); impl CId { diff --git a/prql-compiler/src/sql/preprocess.rs b/prql-compiler/src/sql/preprocess.rs index 035f6858dd30..d194f5b269d6 100644 --- a/prql-compiler/src/sql/preprocess.rs +++ b/prql-compiler/src/sql/preprocess.rs @@ -99,6 +99,12 @@ pub(super) fn wrap(pipe: Vec) -> Vec { .collect() } +fn vecs_contain_same_elements(a: &[T], b: &[T]) -> bool { + let a: HashSet<&T, RandomState> = a.iter().collect(); + let b: HashSet<&T, RandomState> = b.iter().collect(); + a == b +} + /// Creates [SqlTransform::Distinct] from [Transform::Take] pub(super) fn distinct( pipeline: Vec, @@ -108,7 +114,7 @@ pub(super) fn distinct( use Transform::*; let mut res = Vec::new(); - for transform in pipeline { + for transform in pipeline.clone() { match transform { Super(Take(rq::Take { ref partition, .. })) if partition.is_empty() => { res.push(transform); @@ -126,8 +132,13 @@ pub(super) fn distinct( let take_only_first = range_int.start.unwrap_or(1) == 1 && matches!(range_int.end, Some(1)); - if take_only_first && sort.is_empty() { - // TODO: use distinct only if `by == all columns in frame` + + // Check whether the columns within the partition are the same + // as the columns in the table; otherwise we can't use DISTINCT. + let columns_in_frame = AnchorContext::determine_select_columns(&pipeline.clone()); + let matching_columns = vecs_contain_same_elements(&columns_in_frame, &partition); + + if take_only_first && sort.is_empty() && matching_columns { res.push(Distinct); continue; } diff --git a/prql-compiler/src/test.rs b/prql-compiler/src/test.rs index 7993544a68bc..b1c9384dce31 100644 --- a/prql-compiler/src/test.rs +++ b/prql-compiler/src/test.rs @@ -1357,18 +1357,34 @@ fn test_distinct() { employees "###); - // TODO: this should not use DISTINCT but ROW_NUMBER and WHERE, because we want - // row distinct only over first_name and last_name. + // We want distinct only over first_name and last_name, so we can't use a + // `DISTINCT *` here. assert_display_snapshot!((compile(r###" from employees group [first_name, last_name] (take 1) "###).unwrap()), @r###" + WITH table_1 AS ( + SELECT + *, + ROW_NUMBER() OVER (PARTITION BY first_name, last_name) AS _expr_0 + FROM + employees + ) SELECT - DISTINCT * + * FROM - employees + table_1 AS table_0 + WHERE + _expr_0 <= 1 "###); + // Check that a different order doesn't stop distinct from being used. + assert!(compile( + "from employees | select [first_name, last_name] | group [last_name, first_name] (take 1)" + ) + .unwrap() + .contains("DISTINCT")); + // head assert_display_snapshot!((compile(r###" from employees @@ -1434,6 +1450,33 @@ fn test_distinct() { WHERE _expr_0 = 4 "###); + + assert_display_snapshot!(compile(" + from invoices + select [billing_country, billing_city] + group [billing_city] ( + take 1 + ) + sort billing_city + ").unwrap(), @r###" + WITH table_1 AS ( + SELECT + billing_country, + billing_city, + ROW_NUMBER() OVER (PARTITION BY billing_city) AS _expr_0 + FROM + invoices + ) + SELECT + billing_country, + billing_city + FROM + table_1 AS table_0 + WHERE + _expr_0 <= 1 + ORDER BY + billing_city + "###); } #[test] From bac3bb8d1b39d2436eaabf627949c0b64659bb80 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:01:06 +0000 Subject: [PATCH 162/184] chore: bump sqlparser from 0.31.0 to 0.32.0 (#2031) * chore: bump sqlparser from 0.31.0 to 0.32.0 Bumps [sqlparser](https://github.com/sqlparser-rs/sqlparser-rs) from 0.31.0 to 0.32.0. - [Release notes](https://github.com/sqlparser-rs/sqlparser-rs/releases) - [Changelog](https://github.com/sqlparser-rs/sqlparser-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/sqlparser-rs/sqlparser-rs/compare/v0.31.0...v0.32.0) --- updated-dependencies: - dependency-name: sqlparser dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Co-authored-by: Maximilian Roos --- Cargo.lock | 4 ++-- prql-compiler/Cargo.toml | 2 +- prql-compiler/src/sql/gen_query.rs | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ad62a73ec12..cf52072cab03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2720,9 +2720,9 @@ dependencies = [ [[package]] name = "sqlparser" -version = "0.31.0" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f064eb7b163863163c29801910f763c6bfb563b8a8ca4c54193da4c1eea57547" +checksum = "0366f270dbabb5cc2e4c88427dc4c08bba144f81e32fbd459a013f26a4d16aa0" dependencies = [ "log", "serde", diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index 15fee828a11e..b28ada516f55 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -26,7 +26,7 @@ semver = {version = "1.0.14", features = ["serde"]} serde = {version = "1.0.137", features = ["derive"]} serde_json = "1.0.81" sqlformat = "0.2.0" -sqlparser = {version = "0.31.0", features = ["serde"]} +sqlparser = {version = "0.32.0", features = ["serde"]} strum = {version = "0.24.0", features = ["std", "derive"]}# for converting enum variants to string strum_macros = "0.24.0" diff --git a/prql-compiler/src/sql/gen_query.rs b/prql-compiler/src/sql/gen_query.rs index dfbf066f07d5..d9ec1e302f32 100644 --- a/prql-compiler/src/sql/gen_query.rs +++ b/prql-compiler/src/sql/gen_query.rs @@ -167,7 +167,6 @@ fn table_factor_of_table_ref(table_ref: TableRef, ctx: &mut Context) -> Result, ctx: &mut Context) -> Result Date: Sat, 11 Mar 2023 16:37:04 -0800 Subject: [PATCH 163/184] ci: Ensure we don't cache dependencies of binaries (#2113) This moves the Cache step to _after_ the `cargo install` steps --- .github/workflows/publish-web.yaml | 10 +++++----- .github/workflows/pull-request.yaml | 8 ++++---- .github/workflows/test-all.yaml | 2 ++ .github/workflows/test-rust.yaml | 14 +++++++------- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index e4cb273bdaba..b4b8cfebd245 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -31,11 +31,6 @@ jobs: - name: Setup hugo uses: peaceiris/actions-hugo@v2.6.0 - # Book setup, duplicated from `pull-request.yaml` - - name: ๐Ÿ’ฐ Cache - uses: Swatinem/rust-cache@v2 - with: - save-if: ${{ github.ref == 'refs/heads/web' }} - uses: baptiste0928/cargo-install@next with: crate: mdbook @@ -45,6 +40,11 @@ jobs: - uses: baptiste0928/cargo-install@next with: crate: mdbook-admonish + # Book setup, duplicated from `pull-request.yaml` + - name: ๐Ÿ’ฐ Cache + uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/web' }} - uses: ./.github/actions/build-prql-js diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index c00a026f61f2..989026c8bd07 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -42,10 +42,6 @@ jobs: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 # Duplicated in `publish-web.yaml` - - name: ๐Ÿ’ฐ Cache - uses: Swatinem/rust-cache@v2 - with: - save-if: ${{ github.ref == 'refs/heads/main' }} - uses: baptiste0928/cargo-install@next with: crate: mdbook @@ -55,6 +51,10 @@ jobs: - uses: baptiste0928/cargo-install@next with: crate: mdbook-admonish + - name: ๐Ÿ’ฐ Cache + uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} - name: ๐Ÿ”จ Build run: mdbook build working-directory: book/ diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 18c85e4a3a9c..88e58cbc5d63 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -66,6 +66,8 @@ jobs: uses: actions/checkout@v3 - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 + with: + save-if: ${{ github.ref == 'refs/heads/main' }} - name: Run cargo-tarpaulin uses: actions-rs/tarpaulin@v0.1 with: diff --git a/.github/workflows/test-rust.yaml b/.github/workflows/test-rust.yaml index 1f809579a358..1ca2a4743354 100644 --- a/.github/workflows/test-rust.yaml +++ b/.github/workflows/test-rust.yaml @@ -18,6 +18,13 @@ jobs: steps: - name: ๐Ÿ“‚ Checkout code uses: actions/checkout@v3 + - uses: baptiste0928/cargo-install@next + with: + crate: wasm-bindgen-cli + if: inputs.target_option == '--target=wasm32-unknown-unknown' + - uses: baptiste0928/cargo-install@next + with: + crate: cargo-insta - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 with: @@ -27,10 +34,6 @@ jobs: # the current version unfortunately, though). key: 0.6.0-${{ inputs.target_option }} save-if: ${{ github.ref == 'refs/heads/main' }} - - uses: baptiste0928/cargo-install@next - with: - crate: wasm-bindgen-cli - if: inputs.target_option == '--target=wasm32-unknown-unknown' - name: ๐Ÿ“Ž Clippy uses: richb-hanover/cargo@v1.1.0 with: @@ -50,9 +53,6 @@ jobs: with: command: test args: ${{ inputs.target_option }} --no-run --locked - - uses: baptiste0928/cargo-install@next - with: - crate: cargo-insta # Only check unreferenced snapshots on the default target tests on ubuntu # # (Maybe there's a nicer approach where we can parameterize one step From 59854900ffd2478d51c8fc569fc1304f7ac5cf59 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 12 Mar 2023 01:51:44 +0100 Subject: [PATCH 164/184] docs: Add .rpm to changelog (#2114) Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c3974c2841..599c04d04e5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,8 @@ This release has 108 commits from 11 contributors. Selected changes: - [prql-lib] Added C header file. (@vanillajonathan, #1879) - Added a workflow building a `.deb` on each release. (Note that it's not yet published on each release). (@vanillajonathan, #1883) +- Added a workflow building a `.rpm` on each release. (Note that it's not yet + published on each release). (@vanillajonathan, #1918) - Added a workflow building a Snap package on each release. (@vanillajonathan, #1881) From 329d2431a795cdd65240ee97bbcec96f3b3ac839 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sat, 11 Mar 2023 17:55:10 -0800 Subject: [PATCH 165/184] internal: Remove some remnants of `pest` (#2116) --- .github/workflows/publish-web.yaml | 2 +- Taskfile.yml | 8 - book/src/internals/compiler-architecture.md | 2 +- prql-compiler/src/parser/mod.rs | 4 - prql-elixir/native/prql/Cargo.lock | 695 -------------------- 5 files changed, 2 insertions(+), 709 deletions(-) delete mode 100644 prql-elixir/native/prql/Cargo.lock diff --git a/.github/workflows/publish-web.yaml b/.github/workflows/publish-web.yaml index b4b8cfebd245..1260325e0760 100644 --- a/.github/workflows/publish-web.yaml +++ b/.github/workflows/publish-web.yaml @@ -31,6 +31,7 @@ jobs: - name: Setup hugo uses: peaceiris/actions-hugo@v2.6.0 + # Book setup, duplicated from `pull-request.yaml` - uses: baptiste0928/cargo-install@next with: crate: mdbook @@ -40,7 +41,6 @@ jobs: - uses: baptiste0928/cargo-install@next with: crate: mdbook-admonish - # Book setup, duplicated from `pull-request.yaml` - name: ๐Ÿ’ฐ Cache uses: Swatinem/rust-cache@v2 with: diff --git a/Taskfile.yml b/Taskfile.yml index 6ea88606fff2..afc603520ff6 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -185,15 +185,8 @@ tasks: # - "**/*.md" # - "**/*.toml" # - "**/*.lock" - # - "**/*.pest" # - "**/*.snap" cmds: - # We run this `snapshot` first for the reasons given in - # `parser::test_parse_pipeline_parse_tree`. Ideally we would a) retain - # examples in the documentation (inc. tested), b) not rely on falliable - # tests to extract them, which include compiling prql-compiler, c) not - # fail other compilation steps if they can't be extracted. - - cargo insta test --accept -p mdbook-prql --test snapshot # Only delete unreferenced snapshots on the default target โ€” lots are # excluded under wasm. Note that this will also over-delete on Windows. # Note that we need to pass the target explicitly to manage @@ -224,7 +217,6 @@ tasks: # by `--accept` and task not interrupting existing runs, so all files go # to `.snap`s which match the generated output?). - "prql-compiler/**/*.rs" - - "prql-compiler/**/*.pest" - "prql-compiler/**/*.snap" cmds: - cargo insta test --accept -p prql-compiler --lib -- --quiet diff --git a/book/src/internals/compiler-architecture.md b/book/src/internals/compiler-architecture.md index b7702d3a222f..3679719f0a2f 100644 --- a/book/src/internals/compiler-architecture.md +++ b/book/src/internals/compiler-architecture.md @@ -4,7 +4,7 @@ Compiler works in the following stages: 1. Lexing & parsing - split PRQL text into tokens, build parse tree and convert into our AST (Abstract Syntax Tree, see `ast` module). Parsing is done using - PEST parser (`prql.pest`), AST is constructed in `parser.rs`. + the chumsky parser, AST is constructed in `parser.rs`. 2. Semantic analysis - resolves names (identifiers), extracts declarations, determines frames (columns of the table in each step). It declares `Context` diff --git a/prql-compiler/src/parser/mod.rs b/prql-compiler/src/parser/mod.rs index 6f4e0f27ad76..429c5fdd3b30 100644 --- a/prql-compiler/src/parser/mod.rs +++ b/prql-compiler/src/parser/mod.rs @@ -1,7 +1,3 @@ -//! This module contains the parser, which is responsible for converting a tree -//! of pest pairs into a tree of AST Items. It has a small function to call into -//! pest to get the parse tree / concrete syntax tree, and then a large -//! function for turning that into PRQL AST. mod expr; mod interpolation; mod lexer; diff --git a/prql-elixir/native/prql/Cargo.lock b/prql-elixir/native/prql/Cargo.lock deleted file mode 100644 index af9fef0a93fd..000000000000 --- a/prql-elixir/native/prql/Cargo.lock +++ /dev/null @@ -1,695 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217" -dependencies = [ - "const-random", -] - -[[package]] -name = "aho-corasick" -version = "0.7.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" -dependencies = [ - "backtrace", -] - -[[package]] -name = "ariadne" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1cb2a2046bea8ce5e875551f5772024882de0b540c7f93dfc5d6cf1ca8b030c" -dependencies = [ - "yansi", -] - -[[package]] -name = "backtrace" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "block-buffer" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" -dependencies = [ - "generic-array", -] - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "cc" -version = "1.0.78" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chumsky" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d02796e4586c6c41aeb68eae9bfb4558a522c35f1430c14b40136c3706e09e4" -dependencies = [ - "ahash", -] - -[[package]] -name = "const-random" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368a7a772ead6ce7e1de82bfb04c485f3db8ec744f72925af5735e29a22cc18e" -dependencies = [ - "const-random-macro", - "proc-macro-hack", -] - -[[package]] -name = "const-random-macro" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d7d6ab3c3a2282db210df5f02c4dab6e0a7057af0fb7ebd4070f30fe05c0ddb" -dependencies = [ - "getrandom", - "once_cell", - "proc-macro-hack", - "tiny-keccak", -] - -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "digest" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" -dependencies = [ - "block-buffer", - "crypto-common", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "enum-as-inner" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9720bba047d567ffc8a3cba48bf19126600e249ab7f128e9233e6376976a116" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "gimli" -version = "0.27.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" - -[[package]] -name = "heck" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.139" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "nom" -version = "7.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "object" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" - -[[package]] -name = "pest" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" -dependencies = [ - "thiserror", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pest_meta" -version = "2.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065" -dependencies = [ - "once_cell", - "pest", - "sha1", -] - -[[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" - -[[package]] -name = "proc-macro2" -version = "1.0.49" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "prql" -version = "0.1.0" -dependencies = [ - "prql-compiler", - "rustler", -] - -[[package]] -name = "prql-compiler" -version = "0.4.2" -dependencies = [ - "anyhow", - "ariadne", - "chumsky", - "csv", - "enum-as-inner", - "itertools", - "lazy_static", - "log", - "once_cell", - "pest", - "pest_derive", - "regex", - "semver", - "serde", - "serde_json", - "sqlformat", - "sqlparser", - "strum", - "strum_macros", -] - -[[package]] -name = "quote" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "regex" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] -name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "rustc-demangle" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" - -[[package]] -name = "rustler" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61e8ddf75de20513455d7b6f17241a595abbb01b53a6340cecc798a1b13422d" -dependencies = [ - "lazy_static", - "rustler_codegen", - "rustler_sys", -] - -[[package]] -name = "rustler_codegen" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa2e45c0165272070f80ce93bcd7dd5407a3c84a1ef73ab9900e00f00ef3d36" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "rustler_sys" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff26a42e62d538f82913dd34f60105ecfdffbdb25abdc3c3580b0c622285332" -dependencies = [ - "regex", - "unreachable", -] - -[[package]] -name = "rustversion" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" - -[[package]] -name = "ryu" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" - -[[package]] -name = "semver" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" -dependencies = [ - "serde", -] - -[[package]] -name = "serde" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.152" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.91" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" -dependencies = [ - "itoa 1.0.5", - "ryu", - "serde", -] - -[[package]] -name = "sha1" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest", -] - -[[package]] -name = "sqlformat" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87e292b4291f154971a43c3774364e2cbcaec599d3f5bf6fa9d122885dbc38a" -dependencies = [ - "itertools", - "nom", - "unicode_categories", -] - -[[package]] -name = "sqlparser" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67dc6ef36edb658196c3fef0464a80b53dbbc194a904e81f9bd4190f9ecc5b" -dependencies = [ - "log", - "serde", -] - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn", -] - -[[package]] -name = "syn" -version = "1.0.107" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "thiserror" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.38" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "ucd-trie" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" - -[[package]] -name = "unicode-ident" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" - -[[package]] -name = "unicode_categories" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" - -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" From 3a50d91d764440a98c73605a702259c5331ac2a3 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:02:27 -0800 Subject: [PATCH 166/184] refactor: Place all web into `web` path (#2117) * refactor: Place all web into `web` path Part of #2029 --- .github/workflows/pull-request.yaml | 2 +- .gitignore | 2 +- .prettierignore | 11 +++++------ Cargo.toml | 2 +- Taskfile.yml | 9 +++++---- _typos.toml | 6 +++--- book/src/bindings/elixir.md | 1 - book/src/bindings/javascript.md | 1 - book/src/bindings/net.md | 1 - book/src/bindings/php.md | 1 - book/src/bindings/rust.md | 1 - {book => web/book}/.gitignore | 0 {book => web/book}/Cargo.toml | 2 +- {book => web/book}/README.md | 0 {book => web/book}/book.toml | 0 {book => web/book}/comparison-table.css | 0 {book => web/book}/highlight-prql.js | 0 {book => web/book}/mdbook-admonish.css | 0 {book => web/book}/src/SUMMARY.md | 0 {book => web/book}/src/bindings/README.md | 0 web/book/src/bindings/dotnet.md | 1 + web/book/src/bindings/elixir.md | 1 + {book => web/book}/src/bindings/java.md | 0 web/book/src/bindings/javascript.md | 1 + web/book/src/bindings/php.md | 1 + {book => web/book}/src/bindings/python.md | 0 {book => web/book}/src/bindings/r.md | 0 web/book/src/bindings/rust.md | 1 + {book => web/book}/src/contributing/README.md | 0 .../developing-with-dev-containers.md | 0 .../src/contributing/developing-with-docker.md | 0 .../book}/src/contributing/development.md | 0 .../src/contributing/fortnightly-dev-call.ics | 0 {book => web/book}/src/examples/README.md | 0 {book => web/book}/src/examples/cte.md | 0 {book => web/book}/src/examples/employees.md | 0 .../book}/src/examples/list-equivalence.md | 0 {book => web/book}/src/examples/misc.md | 0 {book => web/book}/src/examples/variables.md | 0 {book => web/book}/src/integrations/README.md | 0 {book => web/book}/src/integrations/dbt.md | 0 {book => web/book}/src/integrations/jupyter.md | 0 {book => web/book}/src/integrations/prefect.md | 0 {book => web/book}/src/integrations/rill.md | 0 {book => web/book}/src/integrations/vscode.md | 0 {book => web/book}/src/internals/README.md | 0 .../book}/src/internals/compiler-architecture.md | 0 .../book}/src/internals/functional-lang.md | 0 .../book}/src/internals/language-design.md | 0 .../book}/src/internals/name-resolving.md | 0 .../book}/src/internals/syntax-highlighting.md | 0 {book => web/book}/src/introduction.md | 0 .../book}/src/language-features/README.md | 0 {book => web/book}/src/language-features/case.md | 0 .../book}/src/language-features/coalesce.md | 0 .../src/language-features/dates-and-times.md | 0 .../book}/src/language-features/distinct.md | 0 .../book}/src/language-features/f-strings.md | 0 {book => web/book}/src/language-features/null.md | 0 .../book}/src/language-features/ranges.md | 0 .../book}/src/language-features/regex.md | 0 .../book}/src/language-features/s-strings.md | 0 .../language-features/standard-library/README.md | 2 +- .../standard-library/from-text.md | 0 .../language-features/standard-library/loop.md | 0 .../book}/src/language-features/strings.md | 0 .../book}/src/language-features/target.md | 0 {book => web/book}/src/lib.rs | 0 {book => web/book}/src/main.rs | 0 {book => web/book}/src/queries/README.md | 0 {book => web/book}/src/queries/functions.md | 0 {book => web/book}/src/queries/pipelines.md | 0 {book => web/book}/src/queries/variables.md | 0 {book => web/book}/src/syntax.md | 0 {book => web/book}/src/transforms/README.md | 0 {book => web/book}/src/transforms/aggregate.md | 0 {book => web/book}/src/transforms/append.md | 0 {book => web/book}/src/transforms/derive.md | 0 {book => web/book}/src/transforms/filter.md | 0 {book => web/book}/src/transforms/from.md | 0 {book => web/book}/src/transforms/from_text.md | 0 {book => web/book}/src/transforms/group.md | 0 {book => web/book}/src/transforms/join.md | 0 {book => web/book}/src/transforms/select.md | 0 {book => web/book}/src/transforms/sort.md | 0 {book => web/book}/src/transforms/take.md | 0 {book => web/book}/src/transforms/window.md | 0 {book => web/book}/tests/snapshot.rs | 0 ...pshot__tests__prql__examples__cte-0.prql.snap | 0 ..._tests__prql__examples__employees-0.prql.snap | 0 ..._tests__prql__examples__employees-1.prql.snap | 0 ..._tests__prql__examples__employees-2.prql.snap | 0 ..._tests__prql__examples__employees-3.prql.snap | 0 ..._prql__examples__list-equivalence-0.prql.snap | 0 ..._prql__examples__list-equivalence-1.prql.snap | 0 ..._prql__examples__list-equivalence-2.prql.snap | 0 ..._prql__examples__list-equivalence-3.prql.snap | 0 ...shot__tests__prql__examples__misc-0.prql.snap | 0 ...shot__tests__prql__examples__misc-1.prql.snap | 0 ..._tests__prql__examples__variables-0.prql.snap | 0 ..._tests__prql__examples__variables-1.prql.snap | 0 ..._prql__internals__functional-lang-0.prql.snap | 0 ..._prql__internals__functional-lang-1.prql.snap | 0 ..._prql__internals__functional-lang-2.prql.snap | 0 ..._prql__internals__functional-lang-3.prql.snap | 0 ...__prql__internals__name-resolving-0.prql.snap | 0 ...__prql__internals__name-resolving-1.prql.snap | 0 ...apshot__tests__prql__introduction-0.prql.snap | 0 ...ts__prql__language-features__case-0.prql.snap | 0 ...ts__prql__language-features__case-1.prql.snap | 0 ...prql__language-features__coalesce-0.prql.snap | 0 ...anguage-features__dates-and-times-0.prql.snap | 0 ...anguage-features__dates-and-times-1.prql.snap | 0 ...anguage-features__dates-and-times-2.prql.snap | 0 ...anguage-features__dates-and-times-3.prql.snap | 0 ...prql__language-features__distinct-0.prql.snap | 0 ...prql__language-features__distinct-1.prql.snap | 0 ...prql__language-features__distinct-2.prql.snap | 0 ...prql__language-features__distinct-3.prql.snap | 0 ...rql__language-features__f-strings-0.prql.snap | 0 ...rql__language-features__f-strings-1.prql.snap | 0 ...ts__prql__language-features__null-0.prql.snap | 0 ...__prql__language-features__ranges-0.prql.snap | 0 ...__prql__language-features__ranges-1.prql.snap | 0 ...rql__language-features__s-strings-0.prql.snap | 0 ...rql__language-features__s-strings-1.prql.snap | 0 ...rql__language-features__s-strings-2.prql.snap | 0 ...rql__language-features__s-strings-3.prql.snap | 0 ...rql__language-features__s-strings-4.prql.snap | 0 ...rql__language-features__s-strings-5.prql.snap | 0 ...rql__language-features__s-strings-6.prql.snap | 0 ...eatures__standard-library__README-0.prql.snap | 0 ...ures__standard-library__from-text-0.prql.snap | 0 ...ures__standard-library__from-text-1.prql.snap | 0 ...ures__standard-library__from-text-2.prql.snap | 0 ...-features__standard-library__loop-0.prql.snap | 0 ..._prql__language-features__strings-0.prql.snap | 0 ..._prql__language-features__strings-1.prql.snap | 0 ..._prql__language-features__strings-2.prql.snap | 0 ..._prql__language-features__strings-3.prql.snap | 0 ..._prql__language-features__strings-4.prql.snap | 0 ..._prql__language-features__strings-5.prql.snap | 0 ...__prql__language-features__target-0.prql.snap | 2 +- ...__prql__language-features__target-1.prql.snap | 2 +- ...__prql__language-features__target-2.prql.snap | 2 +- ...__tests__prql__queries__functions-0.prql.snap | 0 ...__tests__prql__queries__functions-1.prql.snap | 0 ...__tests__prql__queries__functions-2.prql.snap | 0 ...__tests__prql__queries__functions-3.prql.snap | 0 ...__tests__prql__queries__functions-4.prql.snap | 0 ...__tests__prql__queries__functions-5.prql.snap | 0 ...__tests__prql__queries__pipelines-0.prql.snap | 0 ...__tests__prql__queries__pipelines-1.prql.snap | 0 ...__tests__prql__queries__pipelines-2.prql.snap | 0 ...__tests__prql__queries__variables-0.prql.snap | 0 ...__tests__prql__queries__variables-1.prql.snap | 0 .../snapshot__tests__prql__syntax-0.prql.snap | 0 .../snapshot__tests__prql__syntax-1.prql.snap | 0 .../snapshot__tests__prql__syntax-10.prql.snap | 0 .../snapshot__tests__prql__syntax-11.prql.snap | 0 .../snapshot__tests__prql__syntax-12.prql.snap | 0 .../snapshot__tests__prql__syntax-13.prql.snap | 0 .../snapshot__tests__prql__syntax-14.prql.snap | 0 .../snapshot__tests__prql__syntax-15.prql.snap | 0 .../snapshot__tests__prql__syntax-16.prql.snap | 0 .../snapshot__tests__prql__syntax-17.prql.snap | 0 .../snapshot__tests__prql__syntax-2.prql.snap | 0 .../snapshot__tests__prql__syntax-3.prql.snap | 0 .../snapshot__tests__prql__syntax-4.prql.snap | 0 .../snapshot__tests__prql__syntax-5.prql.snap | 0 .../snapshot__tests__prql__syntax-6.prql.snap | 0 .../snapshot__tests__prql__syntax-7.prql.snap | 0 .../snapshot__tests__prql__syntax-8.prql.snap | 0 .../snapshot__tests__prql__syntax-9.prql.snap | 0 ...ests__prql__transforms__aggregate-0.prql.snap | 0 ...ests__prql__transforms__aggregate-1.prql.snap | 0 ...ests__prql__transforms__aggregate-2.prql.snap | 0 ...__tests__prql__transforms__append-0.prql.snap | 0 ...__tests__prql__transforms__append-1.prql.snap | 0 ...__tests__prql__transforms__append-2.prql.snap | 0 ...__tests__prql__transforms__derive-0.prql.snap | 0 ...__tests__prql__transforms__derive-1.prql.snap | 0 ...__tests__prql__transforms__filter-0.prql.snap | 0 ...__tests__prql__transforms__filter-1.prql.snap | 0 ...__tests__prql__transforms__filter-2.prql.snap | 0 ...ot__tests__prql__transforms__from-0.prql.snap | 0 ...ot__tests__prql__transforms__from-1.prql.snap | 0 ...t__tests__prql__transforms__group-0.prql.snap | 0 ...t__tests__prql__transforms__group-1.prql.snap | 0 ...t__tests__prql__transforms__group-2.prql.snap | 0 ...ot__tests__prql__transforms__join-0.prql.snap | 0 ...ot__tests__prql__transforms__join-1.prql.snap | 0 ...ot__tests__prql__transforms__join-2.prql.snap | 0 ...__tests__prql__transforms__select-0.prql.snap | 0 ...__tests__prql__transforms__select-1.prql.snap | 0 ...__tests__prql__transforms__select-2.prql.snap | 0 ...__tests__prql__transforms__select-3.prql.snap | 0 ...__tests__prql__transforms__select-4.prql.snap | 0 ...__tests__prql__transforms__select-5.prql.snap | 0 ...__tests__prql__transforms__select-6.prql.snap | 0 ...ot__tests__prql__transforms__sort-0.prql.snap | 0 ...ot__tests__prql__transforms__sort-1.prql.snap | 0 ...ot__tests__prql__transforms__sort-2.prql.snap | 0 ...ot__tests__prql__transforms__sort-3.prql.snap | 0 ...ot__tests__prql__transforms__sort-4.prql.snap | 0 ...ot__tests__prql__transforms__sort-5.prql.snap | 0 ...ot__tests__prql__transforms__take-0.prql.snap | 0 ...ot__tests__prql__transforms__take-1.prql.snap | 0 ...__tests__prql__transforms__window-0.prql.snap | 0 ...__tests__prql__transforms__window-1.prql.snap | 0 ...__tests__prql__transforms__window-2.prql.snap | 0 ...__tests__prql__transforms__window-3.prql.snap | 0 ...__tests__prql__transforms__window-4.prql.snap | 0 {book => web/book}/theme/highlight.js | 0 {playground => web/playground}/.gitignore | 0 {playground => web/playground}/README.md | 0 {playground => web/playground}/package-lock.json | 15 ++++++++++++--- {playground => web/playground}/package.json | 4 ++-- .../playground}/public/favicon.ico | Bin {playground => web/playground}/public/index.html | 0 .../playground}/public/manifest.json | 0 {playground => web/playground}/public/robots.txt | 0 {playground => web/playground}/src/app/App.css | 0 {playground => web/playground}/src/app/App.js | 0 {playground => web/playground}/src/examples.js | 0 {playground => web/playground}/src/highlight.css | 0 {playground => web/playground}/src/index.css | 0 {playground => web/playground}/src/index.js | 0 .../playground}/src/output/Output.css | 0 .../playground}/src/output/Output.js | 0 .../playground}/src/reportWebVitals.js | 0 {playground => web/playground}/src/setupTests.js | 0 .../playground}/src/sidebar/Sidebar.css | 0 .../playground}/src/sidebar/Sidebar.js | 0 .../playground}/src/workbench/Workbench.css | 0 .../playground}/src/workbench/Workbench.js | 0 .../playground}/src/workbench/duckdb.js | 0 .../playground}/src/workbench/monaco-theme.json | 0 .../playground}/src/workbench/prql-syntax.js | 0 {website => web/website}/.gitignore | 0 {website => web/website}/README.md | 0 {website => web/website}/archetypes/default.md | 0 {website => web/website}/config.yml | 0 {website => web/website}/content/_index.md | 0 .../website}/content/book_integrated.html | 0 {website => web/website}/content/faq.md | 0 {website => web/website}/content/playground.html | 0 .../content/posts/2022-05-19-examples.md | 0 .../posts/2023-01-07-functional-relations.md | 0 .../content/posts/2023-01-27-prql-query.md | 0 .../2023-01-28-format-pretty-reports/_index.md | 0 .../query_result.png | Bin .../posts/2023-02-02-one-year/7cpDySb.png | Bin .../posts/2023-02-02-one-year/FQ9QSOo.png | Bin .../posts/2023-02-02-one-year/GXLvoXn.png | Bin .../posts/2023-02-02-one-year/URpCf29.png | Bin .../content/posts/2023-02-02-one-year/_index.md | 0 .../posts/2023-02-02-one-year/ncVXken.png | Bin {website => web/website}/content/roadmap.md | 0 {website => web/website}/static/CNAME | 0 .../website}/static/img/apple-touch-icon.png | Bin .../website}/static/img/favicon-16x16.png | Bin .../website}/static/img/favicon-32x32.png | Bin {website => web/website}/static/img/favicon.ico | Bin {website => web/website}/static/img/icon.svg | 0 .../themes/prql-theme/archetypes/default.md | 0 .../website}/themes/prql-theme/layouts/404.html | 0 .../layouts/_default/_markup/render-link.html | 0 .../prql-theme/layouts/_default/article.html | 0 .../prql-theme/layouts/_default/baseof.html | 0 .../prql-theme/layouts/_default/big_iframe.html | 0 .../themes/prql-theme/layouts/_default/home.html | 0 .../themes/prql-theme/layouts/_default/list.html | 0 .../prql-theme/layouts/_default/single.html | 0 .../prql-theme/layouts/partials/footer.html | 0 .../themes/prql-theme/layouts/partials/head.html | 0 .../prql-theme/layouts/partials/header.html | 0 .../layouts/partials/section-cards.html | 0 .../layouts/partials/section-comments.html | 0 .../prql-theme/layouts/shortcodes/columns.html | 0 .../prql-theme/layouts/shortcodes/faq.html | 0 .../prql-theme/layouts/shortcodes/link.html | 0 .../prql-theme/static/apple-touch-icon.png | Bin .../themes/prql-theme/static/favicon-16x16.png | Bin .../themes/prql-theme/static/favicon-32x32.png | Bin .../themes/prql-theme/static/favicon.ico | Bin .../themes/prql-theme/static/fonts/boxicons.eot | Bin .../prql-theme/static/fonts/boxicons.min.css | 0 .../themes/prql-theme/static/fonts/boxicons.ttf | Bin .../themes/prql-theme/static/fonts/boxicons.woff | Bin .../prql-theme/static/fonts/boxicons.woff2 | Bin .../static/fonts/inter-extra-bold.woff2 | Bin .../static/fonts/inter-extra-nold.woff | Bin .../website}/themes/prql-theme/static/icon.svg | 0 .../website}/themes/prql-theme/static/main.js | 0 .../plugins/bootstrap/bootstrap.bundle.min.js | 0 .../static/plugins/bootstrap/bootstrap.min.css | 0 .../static/plugins/highlight/highlight.css | 0 .../static/plugins/highlight/highlight.min.js | 0 .../prql-theme/static/plugins/highlight/prql.js | 0 .../website}/themes/prql-theme/static/style.css | 0 .../website}/themes/prql-theme/theme.toml | 0 302 files changed, 40 insertions(+), 31 deletions(-) delete mode 100644 book/src/bindings/elixir.md delete mode 100644 book/src/bindings/javascript.md delete mode 100644 book/src/bindings/net.md delete mode 100644 book/src/bindings/php.md delete mode 100644 book/src/bindings/rust.md rename {book => web/book}/.gitignore (100%) rename {book => web/book}/Cargo.toml (93%) rename {book => web/book}/README.md (100%) rename {book => web/book}/book.toml (100%) rename {book => web/book}/comparison-table.css (100%) rename {book => web/book}/highlight-prql.js (100%) rename {book => web/book}/mdbook-admonish.css (100%) rename {book => web/book}/src/SUMMARY.md (100%) rename {book => web/book}/src/bindings/README.md (100%) create mode 100644 web/book/src/bindings/dotnet.md create mode 100644 web/book/src/bindings/elixir.md rename {book => web/book}/src/bindings/java.md (100%) create mode 100644 web/book/src/bindings/javascript.md create mode 100644 web/book/src/bindings/php.md rename {book => web/book}/src/bindings/python.md (100%) rename {book => web/book}/src/bindings/r.md (100%) create mode 100644 web/book/src/bindings/rust.md rename {book => web/book}/src/contributing/README.md (100%) rename {book => web/book}/src/contributing/developing-with-dev-containers.md (100%) rename {book => web/book}/src/contributing/developing-with-docker.md (100%) rename {book => web/book}/src/contributing/development.md (100%) rename {book => web/book}/src/contributing/fortnightly-dev-call.ics (100%) rename {book => web/book}/src/examples/README.md (100%) rename {book => web/book}/src/examples/cte.md (100%) rename {book => web/book}/src/examples/employees.md (100%) rename {book => web/book}/src/examples/list-equivalence.md (100%) rename {book => web/book}/src/examples/misc.md (100%) rename {book => web/book}/src/examples/variables.md (100%) rename {book => web/book}/src/integrations/README.md (100%) rename {book => web/book}/src/integrations/dbt.md (100%) rename {book => web/book}/src/integrations/jupyter.md (100%) rename {book => web/book}/src/integrations/prefect.md (100%) rename {book => web/book}/src/integrations/rill.md (100%) rename {book => web/book}/src/integrations/vscode.md (100%) rename {book => web/book}/src/internals/README.md (100%) rename {book => web/book}/src/internals/compiler-architecture.md (100%) rename {book => web/book}/src/internals/functional-lang.md (100%) rename {book => web/book}/src/internals/language-design.md (100%) rename {book => web/book}/src/internals/name-resolving.md (100%) rename {book => web/book}/src/internals/syntax-highlighting.md (100%) rename {book => web/book}/src/introduction.md (100%) rename {book => web/book}/src/language-features/README.md (100%) rename {book => web/book}/src/language-features/case.md (100%) rename {book => web/book}/src/language-features/coalesce.md (100%) rename {book => web/book}/src/language-features/dates-and-times.md (100%) rename {book => web/book}/src/language-features/distinct.md (100%) rename {book => web/book}/src/language-features/f-strings.md (100%) rename {book => web/book}/src/language-features/null.md (100%) rename {book => web/book}/src/language-features/ranges.md (100%) rename {book => web/book}/src/language-features/regex.md (100%) rename {book => web/book}/src/language-features/s-strings.md (100%) rename {book => web/book}/src/language-features/standard-library/README.md (94%) rename {book => web/book}/src/language-features/standard-library/from-text.md (100%) rename {book => web/book}/src/language-features/standard-library/loop.md (100%) rename {book => web/book}/src/language-features/strings.md (100%) rename {book => web/book}/src/language-features/target.md (100%) rename {book => web/book}/src/lib.rs (100%) rename {book => web/book}/src/main.rs (100%) rename {book => web/book}/src/queries/README.md (100%) rename {book => web/book}/src/queries/functions.md (100%) rename {book => web/book}/src/queries/pipelines.md (100%) rename {book => web/book}/src/queries/variables.md (100%) rename {book => web/book}/src/syntax.md (100%) rename {book => web/book}/src/transforms/README.md (100%) rename {book => web/book}/src/transforms/aggregate.md (100%) rename {book => web/book}/src/transforms/append.md (100%) rename {book => web/book}/src/transforms/derive.md (100%) rename {book => web/book}/src/transforms/filter.md (100%) rename {book => web/book}/src/transforms/from.md (100%) rename {book => web/book}/src/transforms/from_text.md (100%) rename {book => web/book}/src/transforms/group.md (100%) rename {book => web/book}/src/transforms/join.md (100%) rename {book => web/book}/src/transforms/select.md (100%) rename {book => web/book}/src/transforms/sort.md (100%) rename {book => web/book}/src/transforms/take.md (100%) rename {book => web/book}/src/transforms/window.md (100%) rename {book => web/book}/tests/snapshot.rs (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap (80%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap (82%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap (78%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap (100%) rename {book => web/book}/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap (100%) rename {book => web/book}/theme/highlight.js (100%) rename {playground => web/playground}/.gitignore (100%) rename {playground => web/playground}/README.md (100%) rename {playground => web/playground}/package-lock.json (99%) rename {playground => web/playground}/package.json (87%) rename {playground => web/playground}/public/favicon.ico (100%) rename {playground => web/playground}/public/index.html (100%) rename {playground => web/playground}/public/manifest.json (100%) rename {playground => web/playground}/public/robots.txt (100%) rename {playground => web/playground}/src/app/App.css (100%) rename {playground => web/playground}/src/app/App.js (100%) rename {playground => web/playground}/src/examples.js (100%) rename {playground => web/playground}/src/highlight.css (100%) rename {playground => web/playground}/src/index.css (100%) rename {playground => web/playground}/src/index.js (100%) rename {playground => web/playground}/src/output/Output.css (100%) rename {playground => web/playground}/src/output/Output.js (100%) rename {playground => web/playground}/src/reportWebVitals.js (100%) rename {playground => web/playground}/src/setupTests.js (100%) rename {playground => web/playground}/src/sidebar/Sidebar.css (100%) rename {playground => web/playground}/src/sidebar/Sidebar.js (100%) rename {playground => web/playground}/src/workbench/Workbench.css (100%) rename {playground => web/playground}/src/workbench/Workbench.js (100%) rename {playground => web/playground}/src/workbench/duckdb.js (100%) rename {playground => web/playground}/src/workbench/monaco-theme.json (100%) rename {playground => web/playground}/src/workbench/prql-syntax.js (100%) rename {website => web/website}/.gitignore (100%) rename {website => web/website}/README.md (100%) rename {website => web/website}/archetypes/default.md (100%) rename {website => web/website}/config.yml (100%) rename {website => web/website}/content/_index.md (100%) rename {website => web/website}/content/book_integrated.html (100%) rename {website => web/website}/content/faq.md (100%) rename {website => web/website}/content/playground.html (100%) rename {website => web/website}/content/posts/2022-05-19-examples.md (100%) rename {website => web/website}/content/posts/2023-01-07-functional-relations.md (100%) rename {website => web/website}/content/posts/2023-01-27-prql-query.md (100%) rename {website => web/website}/content/posts/2023-01-28-format-pretty-reports/_index.md (100%) rename {website => web/website}/content/posts/2023-01-28-format-pretty-reports/query_result.png (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/7cpDySb.png (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/FQ9QSOo.png (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/GXLvoXn.png (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/URpCf29.png (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/_index.md (100%) rename {website => web/website}/content/posts/2023-02-02-one-year/ncVXken.png (100%) rename {website => web/website}/content/roadmap.md (100%) rename {website => web/website}/static/CNAME (100%) rename {website => web/website}/static/img/apple-touch-icon.png (100%) rename {website => web/website}/static/img/favicon-16x16.png (100%) rename {website => web/website}/static/img/favicon-32x32.png (100%) rename {website => web/website}/static/img/favicon.ico (100%) rename {website => web/website}/static/img/icon.svg (100%) rename {website => web/website}/themes/prql-theme/archetypes/default.md (100%) rename {website => web/website}/themes/prql-theme/layouts/404.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/_markup/render-link.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/article.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/baseof.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/big_iframe.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/home.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/list.html (100%) rename {website => web/website}/themes/prql-theme/layouts/_default/single.html (100%) rename {website => web/website}/themes/prql-theme/layouts/partials/footer.html (100%) rename {website => web/website}/themes/prql-theme/layouts/partials/head.html (100%) rename {website => web/website}/themes/prql-theme/layouts/partials/header.html (100%) rename {website => web/website}/themes/prql-theme/layouts/partials/section-cards.html (100%) rename {website => web/website}/themes/prql-theme/layouts/partials/section-comments.html (100%) rename {website => web/website}/themes/prql-theme/layouts/shortcodes/columns.html (100%) rename {website => web/website}/themes/prql-theme/layouts/shortcodes/faq.html (100%) rename {website => web/website}/themes/prql-theme/layouts/shortcodes/link.html (100%) rename {website => web/website}/themes/prql-theme/static/apple-touch-icon.png (100%) rename {website => web/website}/themes/prql-theme/static/favicon-16x16.png (100%) rename {website => web/website}/themes/prql-theme/static/favicon-32x32.png (100%) rename {website => web/website}/themes/prql-theme/static/favicon.ico (100%) rename {website => web/website}/themes/prql-theme/static/fonts/boxicons.eot (100%) rename {website => web/website}/themes/prql-theme/static/fonts/boxicons.min.css (100%) rename {website => web/website}/themes/prql-theme/static/fonts/boxicons.ttf (100%) rename {website => web/website}/themes/prql-theme/static/fonts/boxicons.woff (100%) rename {website => web/website}/themes/prql-theme/static/fonts/boxicons.woff2 (100%) rename {website => web/website}/themes/prql-theme/static/fonts/inter-extra-bold.woff2 (100%) rename {website => web/website}/themes/prql-theme/static/fonts/inter-extra-nold.woff (100%) rename {website => web/website}/themes/prql-theme/static/icon.svg (100%) rename {website => web/website}/themes/prql-theme/static/main.js (100%) rename {website => web/website}/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js (100%) rename {website => web/website}/themes/prql-theme/static/plugins/bootstrap/bootstrap.min.css (100%) rename {website => web/website}/themes/prql-theme/static/plugins/highlight/highlight.css (100%) rename {website => web/website}/themes/prql-theme/static/plugins/highlight/highlight.min.js (100%) rename {website => web/website}/themes/prql-theme/static/plugins/highlight/prql.js (100%) rename {website => web/website}/themes/prql-theme/static/style.css (100%) rename {website => web/website}/themes/prql-theme/theme.toml (100%) diff --git a/.github/workflows/pull-request.yaml b/.github/workflows/pull-request.yaml index 989026c8bd07..0b34fb0e0ef8 100644 --- a/.github/workflows/pull-request.yaml +++ b/.github/workflows/pull-request.yaml @@ -57,7 +57,7 @@ jobs: save-if: ${{ github.ref == 'refs/heads/main' }} - name: ๐Ÿ”จ Build run: mdbook build - working-directory: book/ + working-directory: web/book/ # Run Mac & Windows & bindings' other tests on a `pr-test-all` label or a `!` # (meanting a breaking change) in the PR title. (We also run on other diff --git a/.gitignore b/.gitignore index 17ef3a036aa3..702287897cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,7 @@ .DS_Store dist -target* +target*/ *.out lcov.info diff --git a/.prettierignore b/.prettierignore index ca7368fe76a4..e8fe196147ea 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,10 +1,9 @@ *.min.* -/book/theme/highlight.js +/web/book/theme/highlight.js # TODO: move these into content out of layouts -/website/themes/prql-theme/layouts/partials/codes/ - -/website/themes/prql-theme/layouts/_default/_markup/render-link.html +/web/website/themes/prql-theme/layouts/partials/codes/ +/web/website/themes/prql-theme/layouts/_default/_markup/render-link.html # Ideally prettier would allow blanket gitignores, https://github.com/prettier/prettier/issues/8048 @@ -14,5 +13,5 @@ target/ .mypy_cache **/build **/dist -/book/book -/website/public +/web/book/book +/web/website/public diff --git a/Cargo.toml b/Cargo.toml index 866a4a93dc95..a660c89e844b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ members = [ "prql-lib", "prql-js", "prql-python", - "book", + "web/book", "prql-elixir/native/prql", ] # Note we don't have a `default-members = ["prql-compiler"]`, since that causes diff --git a/Taskfile.yml b/Taskfile.yml index afc603520ff6..ccce977c79f6 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -194,7 +194,7 @@ tasks: - cargo insta test --accept --unreferenced=auto - cargo insta test --accept --target=wasm32-unknown-unknown # We build the book too, because that acts as a test - - cd book && mdbook build + - cd web/book && mdbook build test-rust-fast: desc: Test prql-compiler's unit tests. @@ -223,6 +223,7 @@ tasks: build-web: desc: Build the website, including the book & playground. + dir: web cmds: - cd website && hugo --minify - cd book && mdbook build @@ -259,19 +260,19 @@ tasks: run-website: desc: Build & serve the static website. - dir: website + dir: web/website cmds: - hugo server run-book: desc: Build & serve the book. - dir: book + dir: web/book cmds: - mdbook serve --port=3000 run-playground: desc: Build & serve the playground. - dir: playground + dir: web/playground cmds: # Must set `install-links=false` in the playground's `npm install` to # install prql-js as the regular dependency, instead of creating a diff --git a/_typos.toml b/_typos.toml index 2038bb357644..85153656cd55 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,9 +1,9 @@ [files] extend-exclude = [ - "book/theme/highlight.js", + "web/book/theme/highlight.js", "prql-compiler/tests/integration/data/", - "website/themes/prql-theme/static/plugins/bootstrap", - "website/themes/prql-theme/static/plugins/highlight/highlight.min.js", + "web/website/themes/prql-theme/static/plugins/bootstrap", + "web/website/themes/prql-theme/static/plugins/highlight/highlight.min.js", ] [default.extend-words] diff --git a/book/src/bindings/elixir.md b/book/src/bindings/elixir.md deleted file mode 100644 index c2874dcf8a07..000000000000 --- a/book/src/bindings/elixir.md +++ /dev/null @@ -1 +0,0 @@ -{{#include ../../../prql-elixir/README.md}} diff --git a/book/src/bindings/javascript.md b/book/src/bindings/javascript.md deleted file mode 100644 index ea88f1817685..000000000000 --- a/book/src/bindings/javascript.md +++ /dev/null @@ -1 +0,0 @@ -{{#include ../../../prql-js/README.md}} diff --git a/book/src/bindings/net.md b/book/src/bindings/net.md deleted file mode 100644 index a1cdb27aa1e3..000000000000 --- a/book/src/bindings/net.md +++ /dev/null @@ -1 +0,0 @@ -{{#include ../../../prql-net/README.md}} diff --git a/book/src/bindings/php.md b/book/src/bindings/php.md deleted file mode 100644 index e168db425270..000000000000 --- a/book/src/bindings/php.md +++ /dev/null @@ -1 +0,0 @@ -{{#include ../../../prql-php/README.md}} diff --git a/book/src/bindings/rust.md b/book/src/bindings/rust.md deleted file mode 100644 index b9511f4fd427..000000000000 --- a/book/src/bindings/rust.md +++ /dev/null @@ -1 +0,0 @@ -{{#include ../../../prql-compiler/README.md}} diff --git a/book/.gitignore b/web/book/.gitignore similarity index 100% rename from book/.gitignore rename to web/book/.gitignore diff --git a/book/Cargo.toml b/web/book/Cargo.toml similarity index 93% rename from book/Cargo.toml rename to web/book/Cargo.toml index 171876dd6ee3..d209d8cb3e1a 100644 --- a/book/Cargo.toml +++ b/web/book/Cargo.toml @@ -19,7 +19,7 @@ test = false anyhow = "1.0.57" globset = "0.4.8" itertools = "0.10.3" -prql-compiler = {path = "../prql-compiler", default-features = false} +prql-compiler = {path = "../../prql-compiler", default-features = false} pulldown-cmark = "0.9.1" pulldown-cmark-to-cmark = "10.0.1" semver = "1.0.9" diff --git a/book/README.md b/web/book/README.md similarity index 100% rename from book/README.md rename to web/book/README.md diff --git a/book/book.toml b/web/book/book.toml similarity index 100% rename from book/book.toml rename to web/book/book.toml diff --git a/book/comparison-table.css b/web/book/comparison-table.css similarity index 100% rename from book/comparison-table.css rename to web/book/comparison-table.css diff --git a/book/highlight-prql.js b/web/book/highlight-prql.js similarity index 100% rename from book/highlight-prql.js rename to web/book/highlight-prql.js diff --git a/book/mdbook-admonish.css b/web/book/mdbook-admonish.css similarity index 100% rename from book/mdbook-admonish.css rename to web/book/mdbook-admonish.css diff --git a/book/src/SUMMARY.md b/web/book/src/SUMMARY.md similarity index 100% rename from book/src/SUMMARY.md rename to web/book/src/SUMMARY.md diff --git a/book/src/bindings/README.md b/web/book/src/bindings/README.md similarity index 100% rename from book/src/bindings/README.md rename to web/book/src/bindings/README.md diff --git a/web/book/src/bindings/dotnet.md b/web/book/src/bindings/dotnet.md new file mode 100644 index 000000000000..44724dc1320e --- /dev/null +++ b/web/book/src/bindings/dotnet.md @@ -0,0 +1 @@ +{{#include ../../../../prql-dotnet/README.md}} diff --git a/web/book/src/bindings/elixir.md b/web/book/src/bindings/elixir.md new file mode 100644 index 000000000000..b59bf72d885c --- /dev/null +++ b/web/book/src/bindings/elixir.md @@ -0,0 +1 @@ +{{#include ../../../../prql-elixir/README.md}} diff --git a/book/src/bindings/java.md b/web/book/src/bindings/java.md similarity index 100% rename from book/src/bindings/java.md rename to web/book/src/bindings/java.md diff --git a/web/book/src/bindings/javascript.md b/web/book/src/bindings/javascript.md new file mode 100644 index 000000000000..50b53cfd3090 --- /dev/null +++ b/web/book/src/bindings/javascript.md @@ -0,0 +1 @@ +{{#include ../../../../prql-js/README.md}} diff --git a/web/book/src/bindings/php.md b/web/book/src/bindings/php.md new file mode 100644 index 000000000000..69bc83459d10 --- /dev/null +++ b/web/book/src/bindings/php.md @@ -0,0 +1 @@ +{{#include ../../../../prql-php/README.md}} diff --git a/book/src/bindings/python.md b/web/book/src/bindings/python.md similarity index 100% rename from book/src/bindings/python.md rename to web/book/src/bindings/python.md diff --git a/book/src/bindings/r.md b/web/book/src/bindings/r.md similarity index 100% rename from book/src/bindings/r.md rename to web/book/src/bindings/r.md diff --git a/web/book/src/bindings/rust.md b/web/book/src/bindings/rust.md new file mode 100644 index 000000000000..cc99cc895889 --- /dev/null +++ b/web/book/src/bindings/rust.md @@ -0,0 +1 @@ +{{#include ../../../../prql-compiler/README.md}} diff --git a/book/src/contributing/README.md b/web/book/src/contributing/README.md similarity index 100% rename from book/src/contributing/README.md rename to web/book/src/contributing/README.md diff --git a/book/src/contributing/developing-with-dev-containers.md b/web/book/src/contributing/developing-with-dev-containers.md similarity index 100% rename from book/src/contributing/developing-with-dev-containers.md rename to web/book/src/contributing/developing-with-dev-containers.md diff --git a/book/src/contributing/developing-with-docker.md b/web/book/src/contributing/developing-with-docker.md similarity index 100% rename from book/src/contributing/developing-with-docker.md rename to web/book/src/contributing/developing-with-docker.md diff --git a/book/src/contributing/development.md b/web/book/src/contributing/development.md similarity index 100% rename from book/src/contributing/development.md rename to web/book/src/contributing/development.md diff --git a/book/src/contributing/fortnightly-dev-call.ics b/web/book/src/contributing/fortnightly-dev-call.ics similarity index 100% rename from book/src/contributing/fortnightly-dev-call.ics rename to web/book/src/contributing/fortnightly-dev-call.ics diff --git a/book/src/examples/README.md b/web/book/src/examples/README.md similarity index 100% rename from book/src/examples/README.md rename to web/book/src/examples/README.md diff --git a/book/src/examples/cte.md b/web/book/src/examples/cte.md similarity index 100% rename from book/src/examples/cte.md rename to web/book/src/examples/cte.md diff --git a/book/src/examples/employees.md b/web/book/src/examples/employees.md similarity index 100% rename from book/src/examples/employees.md rename to web/book/src/examples/employees.md diff --git a/book/src/examples/list-equivalence.md b/web/book/src/examples/list-equivalence.md similarity index 100% rename from book/src/examples/list-equivalence.md rename to web/book/src/examples/list-equivalence.md diff --git a/book/src/examples/misc.md b/web/book/src/examples/misc.md similarity index 100% rename from book/src/examples/misc.md rename to web/book/src/examples/misc.md diff --git a/book/src/examples/variables.md b/web/book/src/examples/variables.md similarity index 100% rename from book/src/examples/variables.md rename to web/book/src/examples/variables.md diff --git a/book/src/integrations/README.md b/web/book/src/integrations/README.md similarity index 100% rename from book/src/integrations/README.md rename to web/book/src/integrations/README.md diff --git a/book/src/integrations/dbt.md b/web/book/src/integrations/dbt.md similarity index 100% rename from book/src/integrations/dbt.md rename to web/book/src/integrations/dbt.md diff --git a/book/src/integrations/jupyter.md b/web/book/src/integrations/jupyter.md similarity index 100% rename from book/src/integrations/jupyter.md rename to web/book/src/integrations/jupyter.md diff --git a/book/src/integrations/prefect.md b/web/book/src/integrations/prefect.md similarity index 100% rename from book/src/integrations/prefect.md rename to web/book/src/integrations/prefect.md diff --git a/book/src/integrations/rill.md b/web/book/src/integrations/rill.md similarity index 100% rename from book/src/integrations/rill.md rename to web/book/src/integrations/rill.md diff --git a/book/src/integrations/vscode.md b/web/book/src/integrations/vscode.md similarity index 100% rename from book/src/integrations/vscode.md rename to web/book/src/integrations/vscode.md diff --git a/book/src/internals/README.md b/web/book/src/internals/README.md similarity index 100% rename from book/src/internals/README.md rename to web/book/src/internals/README.md diff --git a/book/src/internals/compiler-architecture.md b/web/book/src/internals/compiler-architecture.md similarity index 100% rename from book/src/internals/compiler-architecture.md rename to web/book/src/internals/compiler-architecture.md diff --git a/book/src/internals/functional-lang.md b/web/book/src/internals/functional-lang.md similarity index 100% rename from book/src/internals/functional-lang.md rename to web/book/src/internals/functional-lang.md diff --git a/book/src/internals/language-design.md b/web/book/src/internals/language-design.md similarity index 100% rename from book/src/internals/language-design.md rename to web/book/src/internals/language-design.md diff --git a/book/src/internals/name-resolving.md b/web/book/src/internals/name-resolving.md similarity index 100% rename from book/src/internals/name-resolving.md rename to web/book/src/internals/name-resolving.md diff --git a/book/src/internals/syntax-highlighting.md b/web/book/src/internals/syntax-highlighting.md similarity index 100% rename from book/src/internals/syntax-highlighting.md rename to web/book/src/internals/syntax-highlighting.md diff --git a/book/src/introduction.md b/web/book/src/introduction.md similarity index 100% rename from book/src/introduction.md rename to web/book/src/introduction.md diff --git a/book/src/language-features/README.md b/web/book/src/language-features/README.md similarity index 100% rename from book/src/language-features/README.md rename to web/book/src/language-features/README.md diff --git a/book/src/language-features/case.md b/web/book/src/language-features/case.md similarity index 100% rename from book/src/language-features/case.md rename to web/book/src/language-features/case.md diff --git a/book/src/language-features/coalesce.md b/web/book/src/language-features/coalesce.md similarity index 100% rename from book/src/language-features/coalesce.md rename to web/book/src/language-features/coalesce.md diff --git a/book/src/language-features/dates-and-times.md b/web/book/src/language-features/dates-and-times.md similarity index 100% rename from book/src/language-features/dates-and-times.md rename to web/book/src/language-features/dates-and-times.md diff --git a/book/src/language-features/distinct.md b/web/book/src/language-features/distinct.md similarity index 100% rename from book/src/language-features/distinct.md rename to web/book/src/language-features/distinct.md diff --git a/book/src/language-features/f-strings.md b/web/book/src/language-features/f-strings.md similarity index 100% rename from book/src/language-features/f-strings.md rename to web/book/src/language-features/f-strings.md diff --git a/book/src/language-features/null.md b/web/book/src/language-features/null.md similarity index 100% rename from book/src/language-features/null.md rename to web/book/src/language-features/null.md diff --git a/book/src/language-features/ranges.md b/web/book/src/language-features/ranges.md similarity index 100% rename from book/src/language-features/ranges.md rename to web/book/src/language-features/ranges.md diff --git a/book/src/language-features/regex.md b/web/book/src/language-features/regex.md similarity index 100% rename from book/src/language-features/regex.md rename to web/book/src/language-features/regex.md diff --git a/book/src/language-features/s-strings.md b/web/book/src/language-features/s-strings.md similarity index 100% rename from book/src/language-features/s-strings.md rename to web/book/src/language-features/s-strings.md diff --git a/book/src/language-features/standard-library/README.md b/web/book/src/language-features/standard-library/README.md similarity index 94% rename from book/src/language-features/standard-library/README.md rename to web/book/src/language-features/standard-library/README.md index d4dbec6dbf5f..5d8f602afcd5 100644 --- a/book/src/language-features/standard-library/README.md +++ b/web/book/src/language-features/standard-library/README.md @@ -17,7 +17,7 @@ Here's the source of the current [PRQL `std`](https://github.com/PRQL/prql/blob/main/prql-compiler/src/semantic/std.prql): ```prql_no_test -{{#include ../../../../prql-compiler/src/semantic/std.prql}} +{{#include ../../../../../prql-compiler/src/semantic/std.prql}} ``` And a couple of examples: diff --git a/book/src/language-features/standard-library/from-text.md b/web/book/src/language-features/standard-library/from-text.md similarity index 100% rename from book/src/language-features/standard-library/from-text.md rename to web/book/src/language-features/standard-library/from-text.md diff --git a/book/src/language-features/standard-library/loop.md b/web/book/src/language-features/standard-library/loop.md similarity index 100% rename from book/src/language-features/standard-library/loop.md rename to web/book/src/language-features/standard-library/loop.md diff --git a/book/src/language-features/strings.md b/web/book/src/language-features/strings.md similarity index 100% rename from book/src/language-features/strings.md rename to web/book/src/language-features/strings.md diff --git a/book/src/language-features/target.md b/web/book/src/language-features/target.md similarity index 100% rename from book/src/language-features/target.md rename to web/book/src/language-features/target.md diff --git a/book/src/lib.rs b/web/book/src/lib.rs similarity index 100% rename from book/src/lib.rs rename to web/book/src/lib.rs diff --git a/book/src/main.rs b/web/book/src/main.rs similarity index 100% rename from book/src/main.rs rename to web/book/src/main.rs diff --git a/book/src/queries/README.md b/web/book/src/queries/README.md similarity index 100% rename from book/src/queries/README.md rename to web/book/src/queries/README.md diff --git a/book/src/queries/functions.md b/web/book/src/queries/functions.md similarity index 100% rename from book/src/queries/functions.md rename to web/book/src/queries/functions.md diff --git a/book/src/queries/pipelines.md b/web/book/src/queries/pipelines.md similarity index 100% rename from book/src/queries/pipelines.md rename to web/book/src/queries/pipelines.md diff --git a/book/src/queries/variables.md b/web/book/src/queries/variables.md similarity index 100% rename from book/src/queries/variables.md rename to web/book/src/queries/variables.md diff --git a/book/src/syntax.md b/web/book/src/syntax.md similarity index 100% rename from book/src/syntax.md rename to web/book/src/syntax.md diff --git a/book/src/transforms/README.md b/web/book/src/transforms/README.md similarity index 100% rename from book/src/transforms/README.md rename to web/book/src/transforms/README.md diff --git a/book/src/transforms/aggregate.md b/web/book/src/transforms/aggregate.md similarity index 100% rename from book/src/transforms/aggregate.md rename to web/book/src/transforms/aggregate.md diff --git a/book/src/transforms/append.md b/web/book/src/transforms/append.md similarity index 100% rename from book/src/transforms/append.md rename to web/book/src/transforms/append.md diff --git a/book/src/transforms/derive.md b/web/book/src/transforms/derive.md similarity index 100% rename from book/src/transforms/derive.md rename to web/book/src/transforms/derive.md diff --git a/book/src/transforms/filter.md b/web/book/src/transforms/filter.md similarity index 100% rename from book/src/transforms/filter.md rename to web/book/src/transforms/filter.md diff --git a/book/src/transforms/from.md b/web/book/src/transforms/from.md similarity index 100% rename from book/src/transforms/from.md rename to web/book/src/transforms/from.md diff --git a/book/src/transforms/from_text.md b/web/book/src/transforms/from_text.md similarity index 100% rename from book/src/transforms/from_text.md rename to web/book/src/transforms/from_text.md diff --git a/book/src/transforms/group.md b/web/book/src/transforms/group.md similarity index 100% rename from book/src/transforms/group.md rename to web/book/src/transforms/group.md diff --git a/book/src/transforms/join.md b/web/book/src/transforms/join.md similarity index 100% rename from book/src/transforms/join.md rename to web/book/src/transforms/join.md diff --git a/book/src/transforms/select.md b/web/book/src/transforms/select.md similarity index 100% rename from book/src/transforms/select.md rename to web/book/src/transforms/select.md diff --git a/book/src/transforms/sort.md b/web/book/src/transforms/sort.md similarity index 100% rename from book/src/transforms/sort.md rename to web/book/src/transforms/sort.md diff --git a/book/src/transforms/take.md b/web/book/src/transforms/take.md similarity index 100% rename from book/src/transforms/take.md rename to web/book/src/transforms/take.md diff --git a/book/src/transforms/window.md b/web/book/src/transforms/window.md similarity index 100% rename from book/src/transforms/window.md rename to web/book/src/transforms/window.md diff --git a/book/tests/snapshot.rs b/web/book/tests/snapshot.rs similarity index 100% rename from book/tests/snapshot.rs rename to web/book/tests/snapshot.rs diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__cte-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__employees-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__employees-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__employees-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__employees-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__list-equivalence-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__misc-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__misc-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__variables-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__examples__variables-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__functional-lang-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__internals__name-resolving-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__introduction-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__case-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__case-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__coalesce-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__dates-and-times-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__distinct-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__f-strings-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__null-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__ranges-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__s-strings-6.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__README-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__from-text-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__standard-library__loop-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__strings-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap similarity index 80% rename from book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap index 31eb52b4b0e7..b0923a3791ed 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap +++ b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-0.prql.snap @@ -1,5 +1,5 @@ --- -source: book/tests/snapshot.rs +source: web/book/tests/snapshot.rs expression: "prql target:sql.postgres\n\nfrom employees\nsort age\ntake 10\n" --- SELECT diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap similarity index 82% rename from book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap index 1319313f929f..d6e4b0820e63 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap +++ b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-1.prql.snap @@ -1,5 +1,5 @@ --- -source: book/tests/snapshot.rs +source: web/book/tests/snapshot.rs expression: "# Can't yet format & compile\n\nprql target:sql.mssql\n\nfrom employees\nsort age\ntake 10\n" --- SELECT diff --git a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap similarity index 78% rename from book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap index 36f4e8f260f1..ea2581281aed 100644 --- a/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap +++ b/web/book/tests/snapshots/snapshot__tests__prql__language-features__target-2.prql.snap @@ -1,5 +1,5 @@ --- -source: book/tests/snapshot.rs +source: web/book/tests/snapshot.rs expression: "# Can't yet format & compile\n\nprql version:\"0.6.0\"\n\nfrom employees\n" --- SELECT diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__functions-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__pipelines-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__variables-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__queries__variables-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-10.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-11.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-12.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-13.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-14.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-15.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-16.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-17.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-6.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-7.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-8.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__syntax-9.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__aggregate-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__append-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__append-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__append-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__derive-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__derive-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__filter-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__from-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__from-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__group-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__group-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__group-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__join-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__join-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__join-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__select-6.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-4.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__sort-5.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__take-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__take-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__window-0.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__window-1.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__window-2.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__window-3.prql.snap diff --git a/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap b/web/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap similarity index 100% rename from book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap rename to web/book/tests/snapshots/snapshot__tests__prql__transforms__window-4.prql.snap diff --git a/book/theme/highlight.js b/web/book/theme/highlight.js similarity index 100% rename from book/theme/highlight.js rename to web/book/theme/highlight.js diff --git a/playground/.gitignore b/web/playground/.gitignore similarity index 100% rename from playground/.gitignore rename to web/playground/.gitignore diff --git a/playground/README.md b/web/playground/README.md similarity index 100% rename from playground/README.md rename to web/playground/README.md diff --git a/playground/package-lock.json b/web/playground/package-lock.json similarity index 99% rename from playground/package-lock.json rename to web/playground/package-lock.json index 96cd41b6b656..53760bfc1007 100644 --- a/playground/package-lock.json +++ b/web/playground/package-lock.json @@ -15,7 +15,7 @@ "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "monaco-editor": "^0.36.0", - "prql-js": "file:../prql-js", + "prql-js": "file:../../prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", @@ -27,8 +27,17 @@ "npm-watch": "^0.11.0" } }, + "../../prql-js": { + "version": "0.6.0", + "license": "Apache-2.0", + "devDependencies": { + "chai": "^4.3.6", + "mocha": "^10.0.0" + } + }, "../prql-js": { "version": "0.6.0", + "extraneous": true, "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", @@ -14608,7 +14617,7 @@ } }, "node_modules/prql-js": { - "resolved": "../prql-js", + "resolved": "../../prql-js", "link": true }, "node_modules/prr": { @@ -28411,7 +28420,7 @@ } }, "prql-js": { - "version": "file:../prql-js", + "version": "file:../../prql-js", "requires": { "chai": "^4.3.6", "mocha": "^10.0.0" diff --git a/playground/package.json b/web/playground/package.json similarity index 87% rename from playground/package.json rename to web/playground/package.json index eef71f294594..777415fba84d 100644 --- a/playground/package.json +++ b/web/playground/package.json @@ -18,7 +18,7 @@ "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "monaco-editor": "^0.36.0", - "prql-js": "file:../prql-js", + "prql-js": "file:../../prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", @@ -41,7 +41,7 @@ "scripts": { "build": "react-scripts build", "eject": "react-scripts eject", - "preinstall": "cp -r ../prql-compiler/tests/integration/data public && cd ../prql-js && npm run build:bundler", + "preinstall": "cp -r ../../prql-compiler/tests/integration/data public && cd ../../prql-js && npm run build:bundler", "start": "react-scripts start", "test": "react-scripts test" }, diff --git a/playground/public/favicon.ico b/web/playground/public/favicon.ico similarity index 100% rename from playground/public/favicon.ico rename to web/playground/public/favicon.ico diff --git a/playground/public/index.html b/web/playground/public/index.html similarity index 100% rename from playground/public/index.html rename to web/playground/public/index.html diff --git a/playground/public/manifest.json b/web/playground/public/manifest.json similarity index 100% rename from playground/public/manifest.json rename to web/playground/public/manifest.json diff --git a/playground/public/robots.txt b/web/playground/public/robots.txt similarity index 100% rename from playground/public/robots.txt rename to web/playground/public/robots.txt diff --git a/playground/src/app/App.css b/web/playground/src/app/App.css similarity index 100% rename from playground/src/app/App.css rename to web/playground/src/app/App.css diff --git a/playground/src/app/App.js b/web/playground/src/app/App.js similarity index 100% rename from playground/src/app/App.js rename to web/playground/src/app/App.js diff --git a/playground/src/examples.js b/web/playground/src/examples.js similarity index 100% rename from playground/src/examples.js rename to web/playground/src/examples.js diff --git a/playground/src/highlight.css b/web/playground/src/highlight.css similarity index 100% rename from playground/src/highlight.css rename to web/playground/src/highlight.css diff --git a/playground/src/index.css b/web/playground/src/index.css similarity index 100% rename from playground/src/index.css rename to web/playground/src/index.css diff --git a/playground/src/index.js b/web/playground/src/index.js similarity index 100% rename from playground/src/index.js rename to web/playground/src/index.js diff --git a/playground/src/output/Output.css b/web/playground/src/output/Output.css similarity index 100% rename from playground/src/output/Output.css rename to web/playground/src/output/Output.css diff --git a/playground/src/output/Output.js b/web/playground/src/output/Output.js similarity index 100% rename from playground/src/output/Output.js rename to web/playground/src/output/Output.js diff --git a/playground/src/reportWebVitals.js b/web/playground/src/reportWebVitals.js similarity index 100% rename from playground/src/reportWebVitals.js rename to web/playground/src/reportWebVitals.js diff --git a/playground/src/setupTests.js b/web/playground/src/setupTests.js similarity index 100% rename from playground/src/setupTests.js rename to web/playground/src/setupTests.js diff --git a/playground/src/sidebar/Sidebar.css b/web/playground/src/sidebar/Sidebar.css similarity index 100% rename from playground/src/sidebar/Sidebar.css rename to web/playground/src/sidebar/Sidebar.css diff --git a/playground/src/sidebar/Sidebar.js b/web/playground/src/sidebar/Sidebar.js similarity index 100% rename from playground/src/sidebar/Sidebar.js rename to web/playground/src/sidebar/Sidebar.js diff --git a/playground/src/workbench/Workbench.css b/web/playground/src/workbench/Workbench.css similarity index 100% rename from playground/src/workbench/Workbench.css rename to web/playground/src/workbench/Workbench.css diff --git a/playground/src/workbench/Workbench.js b/web/playground/src/workbench/Workbench.js similarity index 100% rename from playground/src/workbench/Workbench.js rename to web/playground/src/workbench/Workbench.js diff --git a/playground/src/workbench/duckdb.js b/web/playground/src/workbench/duckdb.js similarity index 100% rename from playground/src/workbench/duckdb.js rename to web/playground/src/workbench/duckdb.js diff --git a/playground/src/workbench/monaco-theme.json b/web/playground/src/workbench/monaco-theme.json similarity index 100% rename from playground/src/workbench/monaco-theme.json rename to web/playground/src/workbench/monaco-theme.json diff --git a/playground/src/workbench/prql-syntax.js b/web/playground/src/workbench/prql-syntax.js similarity index 100% rename from playground/src/workbench/prql-syntax.js rename to web/playground/src/workbench/prql-syntax.js diff --git a/website/.gitignore b/web/website/.gitignore similarity index 100% rename from website/.gitignore rename to web/website/.gitignore diff --git a/website/README.md b/web/website/README.md similarity index 100% rename from website/README.md rename to web/website/README.md diff --git a/website/archetypes/default.md b/web/website/archetypes/default.md similarity index 100% rename from website/archetypes/default.md rename to web/website/archetypes/default.md diff --git a/website/config.yml b/web/website/config.yml similarity index 100% rename from website/config.yml rename to web/website/config.yml diff --git a/website/content/_index.md b/web/website/content/_index.md similarity index 100% rename from website/content/_index.md rename to web/website/content/_index.md diff --git a/website/content/book_integrated.html b/web/website/content/book_integrated.html similarity index 100% rename from website/content/book_integrated.html rename to web/website/content/book_integrated.html diff --git a/website/content/faq.md b/web/website/content/faq.md similarity index 100% rename from website/content/faq.md rename to web/website/content/faq.md diff --git a/website/content/playground.html b/web/website/content/playground.html similarity index 100% rename from website/content/playground.html rename to web/website/content/playground.html diff --git a/website/content/posts/2022-05-19-examples.md b/web/website/content/posts/2022-05-19-examples.md similarity index 100% rename from website/content/posts/2022-05-19-examples.md rename to web/website/content/posts/2022-05-19-examples.md diff --git a/website/content/posts/2023-01-07-functional-relations.md b/web/website/content/posts/2023-01-07-functional-relations.md similarity index 100% rename from website/content/posts/2023-01-07-functional-relations.md rename to web/website/content/posts/2023-01-07-functional-relations.md diff --git a/website/content/posts/2023-01-27-prql-query.md b/web/website/content/posts/2023-01-27-prql-query.md similarity index 100% rename from website/content/posts/2023-01-27-prql-query.md rename to web/website/content/posts/2023-01-27-prql-query.md diff --git a/website/content/posts/2023-01-28-format-pretty-reports/_index.md b/web/website/content/posts/2023-01-28-format-pretty-reports/_index.md similarity index 100% rename from website/content/posts/2023-01-28-format-pretty-reports/_index.md rename to web/website/content/posts/2023-01-28-format-pretty-reports/_index.md diff --git a/website/content/posts/2023-01-28-format-pretty-reports/query_result.png b/web/website/content/posts/2023-01-28-format-pretty-reports/query_result.png similarity index 100% rename from website/content/posts/2023-01-28-format-pretty-reports/query_result.png rename to web/website/content/posts/2023-01-28-format-pretty-reports/query_result.png diff --git a/website/content/posts/2023-02-02-one-year/7cpDySb.png b/web/website/content/posts/2023-02-02-one-year/7cpDySb.png similarity index 100% rename from website/content/posts/2023-02-02-one-year/7cpDySb.png rename to web/website/content/posts/2023-02-02-one-year/7cpDySb.png diff --git a/website/content/posts/2023-02-02-one-year/FQ9QSOo.png b/web/website/content/posts/2023-02-02-one-year/FQ9QSOo.png similarity index 100% rename from website/content/posts/2023-02-02-one-year/FQ9QSOo.png rename to web/website/content/posts/2023-02-02-one-year/FQ9QSOo.png diff --git a/website/content/posts/2023-02-02-one-year/GXLvoXn.png b/web/website/content/posts/2023-02-02-one-year/GXLvoXn.png similarity index 100% rename from website/content/posts/2023-02-02-one-year/GXLvoXn.png rename to web/website/content/posts/2023-02-02-one-year/GXLvoXn.png diff --git a/website/content/posts/2023-02-02-one-year/URpCf29.png b/web/website/content/posts/2023-02-02-one-year/URpCf29.png similarity index 100% rename from website/content/posts/2023-02-02-one-year/URpCf29.png rename to web/website/content/posts/2023-02-02-one-year/URpCf29.png diff --git a/website/content/posts/2023-02-02-one-year/_index.md b/web/website/content/posts/2023-02-02-one-year/_index.md similarity index 100% rename from website/content/posts/2023-02-02-one-year/_index.md rename to web/website/content/posts/2023-02-02-one-year/_index.md diff --git a/website/content/posts/2023-02-02-one-year/ncVXken.png b/web/website/content/posts/2023-02-02-one-year/ncVXken.png similarity index 100% rename from website/content/posts/2023-02-02-one-year/ncVXken.png rename to web/website/content/posts/2023-02-02-one-year/ncVXken.png diff --git a/website/content/roadmap.md b/web/website/content/roadmap.md similarity index 100% rename from website/content/roadmap.md rename to web/website/content/roadmap.md diff --git a/website/static/CNAME b/web/website/static/CNAME similarity index 100% rename from website/static/CNAME rename to web/website/static/CNAME diff --git a/website/static/img/apple-touch-icon.png b/web/website/static/img/apple-touch-icon.png similarity index 100% rename from website/static/img/apple-touch-icon.png rename to web/website/static/img/apple-touch-icon.png diff --git a/website/static/img/favicon-16x16.png b/web/website/static/img/favicon-16x16.png similarity index 100% rename from website/static/img/favicon-16x16.png rename to web/website/static/img/favicon-16x16.png diff --git a/website/static/img/favicon-32x32.png b/web/website/static/img/favicon-32x32.png similarity index 100% rename from website/static/img/favicon-32x32.png rename to web/website/static/img/favicon-32x32.png diff --git a/website/static/img/favicon.ico b/web/website/static/img/favicon.ico similarity index 100% rename from website/static/img/favicon.ico rename to web/website/static/img/favicon.ico diff --git a/website/static/img/icon.svg b/web/website/static/img/icon.svg similarity index 100% rename from website/static/img/icon.svg rename to web/website/static/img/icon.svg diff --git a/website/themes/prql-theme/archetypes/default.md b/web/website/themes/prql-theme/archetypes/default.md similarity index 100% rename from website/themes/prql-theme/archetypes/default.md rename to web/website/themes/prql-theme/archetypes/default.md diff --git a/website/themes/prql-theme/layouts/404.html b/web/website/themes/prql-theme/layouts/404.html similarity index 100% rename from website/themes/prql-theme/layouts/404.html rename to web/website/themes/prql-theme/layouts/404.html diff --git a/website/themes/prql-theme/layouts/_default/_markup/render-link.html b/web/website/themes/prql-theme/layouts/_default/_markup/render-link.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/_markup/render-link.html rename to web/website/themes/prql-theme/layouts/_default/_markup/render-link.html diff --git a/website/themes/prql-theme/layouts/_default/article.html b/web/website/themes/prql-theme/layouts/_default/article.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/article.html rename to web/website/themes/prql-theme/layouts/_default/article.html diff --git a/website/themes/prql-theme/layouts/_default/baseof.html b/web/website/themes/prql-theme/layouts/_default/baseof.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/baseof.html rename to web/website/themes/prql-theme/layouts/_default/baseof.html diff --git a/website/themes/prql-theme/layouts/_default/big_iframe.html b/web/website/themes/prql-theme/layouts/_default/big_iframe.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/big_iframe.html rename to web/website/themes/prql-theme/layouts/_default/big_iframe.html diff --git a/website/themes/prql-theme/layouts/_default/home.html b/web/website/themes/prql-theme/layouts/_default/home.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/home.html rename to web/website/themes/prql-theme/layouts/_default/home.html diff --git a/website/themes/prql-theme/layouts/_default/list.html b/web/website/themes/prql-theme/layouts/_default/list.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/list.html rename to web/website/themes/prql-theme/layouts/_default/list.html diff --git a/website/themes/prql-theme/layouts/_default/single.html b/web/website/themes/prql-theme/layouts/_default/single.html similarity index 100% rename from website/themes/prql-theme/layouts/_default/single.html rename to web/website/themes/prql-theme/layouts/_default/single.html diff --git a/website/themes/prql-theme/layouts/partials/footer.html b/web/website/themes/prql-theme/layouts/partials/footer.html similarity index 100% rename from website/themes/prql-theme/layouts/partials/footer.html rename to web/website/themes/prql-theme/layouts/partials/footer.html diff --git a/website/themes/prql-theme/layouts/partials/head.html b/web/website/themes/prql-theme/layouts/partials/head.html similarity index 100% rename from website/themes/prql-theme/layouts/partials/head.html rename to web/website/themes/prql-theme/layouts/partials/head.html diff --git a/website/themes/prql-theme/layouts/partials/header.html b/web/website/themes/prql-theme/layouts/partials/header.html similarity index 100% rename from website/themes/prql-theme/layouts/partials/header.html rename to web/website/themes/prql-theme/layouts/partials/header.html diff --git a/website/themes/prql-theme/layouts/partials/section-cards.html b/web/website/themes/prql-theme/layouts/partials/section-cards.html similarity index 100% rename from website/themes/prql-theme/layouts/partials/section-cards.html rename to web/website/themes/prql-theme/layouts/partials/section-cards.html diff --git a/website/themes/prql-theme/layouts/partials/section-comments.html b/web/website/themes/prql-theme/layouts/partials/section-comments.html similarity index 100% rename from website/themes/prql-theme/layouts/partials/section-comments.html rename to web/website/themes/prql-theme/layouts/partials/section-comments.html diff --git a/website/themes/prql-theme/layouts/shortcodes/columns.html b/web/website/themes/prql-theme/layouts/shortcodes/columns.html similarity index 100% rename from website/themes/prql-theme/layouts/shortcodes/columns.html rename to web/website/themes/prql-theme/layouts/shortcodes/columns.html diff --git a/website/themes/prql-theme/layouts/shortcodes/faq.html b/web/website/themes/prql-theme/layouts/shortcodes/faq.html similarity index 100% rename from website/themes/prql-theme/layouts/shortcodes/faq.html rename to web/website/themes/prql-theme/layouts/shortcodes/faq.html diff --git a/website/themes/prql-theme/layouts/shortcodes/link.html b/web/website/themes/prql-theme/layouts/shortcodes/link.html similarity index 100% rename from website/themes/prql-theme/layouts/shortcodes/link.html rename to web/website/themes/prql-theme/layouts/shortcodes/link.html diff --git a/website/themes/prql-theme/static/apple-touch-icon.png b/web/website/themes/prql-theme/static/apple-touch-icon.png similarity index 100% rename from website/themes/prql-theme/static/apple-touch-icon.png rename to web/website/themes/prql-theme/static/apple-touch-icon.png diff --git a/website/themes/prql-theme/static/favicon-16x16.png b/web/website/themes/prql-theme/static/favicon-16x16.png similarity index 100% rename from website/themes/prql-theme/static/favicon-16x16.png rename to web/website/themes/prql-theme/static/favicon-16x16.png diff --git a/website/themes/prql-theme/static/favicon-32x32.png b/web/website/themes/prql-theme/static/favicon-32x32.png similarity index 100% rename from website/themes/prql-theme/static/favicon-32x32.png rename to web/website/themes/prql-theme/static/favicon-32x32.png diff --git a/website/themes/prql-theme/static/favicon.ico b/web/website/themes/prql-theme/static/favicon.ico similarity index 100% rename from website/themes/prql-theme/static/favicon.ico rename to web/website/themes/prql-theme/static/favicon.ico diff --git a/website/themes/prql-theme/static/fonts/boxicons.eot b/web/website/themes/prql-theme/static/fonts/boxicons.eot similarity index 100% rename from website/themes/prql-theme/static/fonts/boxicons.eot rename to web/website/themes/prql-theme/static/fonts/boxicons.eot diff --git a/website/themes/prql-theme/static/fonts/boxicons.min.css b/web/website/themes/prql-theme/static/fonts/boxicons.min.css similarity index 100% rename from website/themes/prql-theme/static/fonts/boxicons.min.css rename to web/website/themes/prql-theme/static/fonts/boxicons.min.css diff --git a/website/themes/prql-theme/static/fonts/boxicons.ttf b/web/website/themes/prql-theme/static/fonts/boxicons.ttf similarity index 100% rename from website/themes/prql-theme/static/fonts/boxicons.ttf rename to web/website/themes/prql-theme/static/fonts/boxicons.ttf diff --git a/website/themes/prql-theme/static/fonts/boxicons.woff b/web/website/themes/prql-theme/static/fonts/boxicons.woff similarity index 100% rename from website/themes/prql-theme/static/fonts/boxicons.woff rename to web/website/themes/prql-theme/static/fonts/boxicons.woff diff --git a/website/themes/prql-theme/static/fonts/boxicons.woff2 b/web/website/themes/prql-theme/static/fonts/boxicons.woff2 similarity index 100% rename from website/themes/prql-theme/static/fonts/boxicons.woff2 rename to web/website/themes/prql-theme/static/fonts/boxicons.woff2 diff --git a/website/themes/prql-theme/static/fonts/inter-extra-bold.woff2 b/web/website/themes/prql-theme/static/fonts/inter-extra-bold.woff2 similarity index 100% rename from website/themes/prql-theme/static/fonts/inter-extra-bold.woff2 rename to web/website/themes/prql-theme/static/fonts/inter-extra-bold.woff2 diff --git a/website/themes/prql-theme/static/fonts/inter-extra-nold.woff b/web/website/themes/prql-theme/static/fonts/inter-extra-nold.woff similarity index 100% rename from website/themes/prql-theme/static/fonts/inter-extra-nold.woff rename to web/website/themes/prql-theme/static/fonts/inter-extra-nold.woff diff --git a/website/themes/prql-theme/static/icon.svg b/web/website/themes/prql-theme/static/icon.svg similarity index 100% rename from website/themes/prql-theme/static/icon.svg rename to web/website/themes/prql-theme/static/icon.svg diff --git a/website/themes/prql-theme/static/main.js b/web/website/themes/prql-theme/static/main.js similarity index 100% rename from website/themes/prql-theme/static/main.js rename to web/website/themes/prql-theme/static/main.js diff --git a/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js b/web/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js similarity index 100% rename from website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js rename to web/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.bundle.min.js diff --git a/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.min.css b/web/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.min.css similarity index 100% rename from website/themes/prql-theme/static/plugins/bootstrap/bootstrap.min.css rename to web/website/themes/prql-theme/static/plugins/bootstrap/bootstrap.min.css diff --git a/website/themes/prql-theme/static/plugins/highlight/highlight.css b/web/website/themes/prql-theme/static/plugins/highlight/highlight.css similarity index 100% rename from website/themes/prql-theme/static/plugins/highlight/highlight.css rename to web/website/themes/prql-theme/static/plugins/highlight/highlight.css diff --git a/website/themes/prql-theme/static/plugins/highlight/highlight.min.js b/web/website/themes/prql-theme/static/plugins/highlight/highlight.min.js similarity index 100% rename from website/themes/prql-theme/static/plugins/highlight/highlight.min.js rename to web/website/themes/prql-theme/static/plugins/highlight/highlight.min.js diff --git a/website/themes/prql-theme/static/plugins/highlight/prql.js b/web/website/themes/prql-theme/static/plugins/highlight/prql.js similarity index 100% rename from website/themes/prql-theme/static/plugins/highlight/prql.js rename to web/website/themes/prql-theme/static/plugins/highlight/prql.js diff --git a/website/themes/prql-theme/static/style.css b/web/website/themes/prql-theme/static/style.css similarity index 100% rename from website/themes/prql-theme/static/style.css rename to web/website/themes/prql-theme/static/style.css diff --git a/website/themes/prql-theme/theme.toml b/web/website/themes/prql-theme/theme.toml similarity index 100% rename from website/themes/prql-theme/theme.toml rename to web/website/themes/prql-theme/theme.toml From 28ae5ab10d6465e432ac762d57898ac4fa476008 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:13:32 -0800 Subject: [PATCH 167/184] chore: Remove old code comments in book tests (#2118) --- web/book/tests/snapshot.rs | 50 ++++++++------------------------------ 1 file changed, 10 insertions(+), 40 deletions(-) diff --git a/web/book/tests/snapshot.rs b/web/book/tests/snapshot.rs index 19060db0454f..ddb8e7f5579c 100644 --- a/web/book/tests/snapshot.rs +++ b/web/book/tests/snapshot.rs @@ -1,22 +1,4 @@ #![cfg(not(target_family = "wasm"))] -// -// Thoughts on the overall code: -// -// Overall, this is overengineered โ€”ย it's complicated and took a long time to -// write. The intention is good โ€” have a version of the SQL that's committed -// into the repo, and join our tests with our docs. But it feels like overly -// custom code for quite a general problem, even if our preferences are slightly -// different from the general case. -// -// Having an API for being able to read snapshots -// (https://github.com/mitsuhiko/insta/issues/353) would significantly reduce the need for -// custom code; -// -// Possibly we should be using something like pandoc / -// https://github.com/gpoore/codebraid / which would run the transformation for -// us. They introduce a bunch of non-rust dependencies, which is not ideal, but -// passable. They don't let us customize our formatting (e.g. in a table). -// use anyhow::{bail, Result}; use globset::Glob; use insta::assert_snapshot; @@ -27,18 +9,23 @@ use walkdir::WalkDir; #[test] /// This test: -/// - Extracts PRQL code blocks into files in the `examples` path, skipping -/// where the matching example is already present. +/// - Extracts PRQL code blocks from the book /// - Compiles them to SQL, comparing to a snapshot. Insta raises an error if /// there's a diff. /// /// This mirrors the process in [replace_examples], which inserts a /// comparison table of SQL into the book, and so serves as a snapshot test of /// those examples. -fn test_examples() -> Result<()> { - test_prql_examples(); +/// Snapshot the SQL output of each example. +fn test_prql_examples() { + let opts = Options::default().no_signature(); + let examples = collect_book_examples().unwrap(); - Ok(()) + for (path, prql) in examples { + // Whether it's a success or a failure, get the string. + let sql = compile(&prql, &opts).unwrap_or_else(|e| e.to_string()); + assert_snapshot!(path.to_str().unwrap(), &sql, &prql); + } } const ROOT_EXAMPLES_PATH: &str = "tests/prql"; @@ -103,23 +90,6 @@ fn collect_book_examples() -> Result> { Ok(examples_in_book) } -/// Snapshot the SQL output of each example. -fn test_prql_examples() { - let opts = Options::default().no_signature(); - let examples = collect_book_examples().unwrap(); - - for (path, prql) in examples { - // TODO: I don't think we use this and can remove it? - if prql.contains("skip_test") { - return; - } - - // Whether it's a success or a failure, get the string. - let sql = compile(&prql, &opts).unwrap_or_else(|e| e.to_string()); - assert_snapshot!(path.to_str().unwrap(), &sql, &prql); - } -} - /// Test that the formatted result (the `Display` result) of each example can be /// compiled. // From c0c023a0c0587754c96ef7f48c9b077686e8e31f Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:24:56 -0800 Subject: [PATCH 168/184] chore: Fix python test (#2120) --- prql-python/python/tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prql-python/python/tests/conftest.py b/prql-python/python/tests/conftest.py index 9bfb40dab01f..195af308a287 100644 --- a/prql-python/python/tests/conftest.py +++ b/prql-python/python/tests/conftest.py @@ -5,7 +5,7 @@ @pytest.fixture() def example_queries(): - website_path = "../website/content/_index.md" + website_path = "../web/website/content/_index.md" with open(website_path, "r") as f: website = f.read() website_yaml = yaml.safe_load(website.replace("---", "")) From b59570af751bb5817f3c400c5554ed25ee10f427 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 00:25:05 -0800 Subject: [PATCH 169/184] chore: bump minimatch and recursive-readdir in /web/playground (#2119) Bumps [minimatch](https://github.com/isaacs/minimatch) and [recursive-readdir](https://github.com/jergason/recursive-readdir). These dependencies needed to be updated together. Updates `minimatch` from 3.0.4 to 3.1.2 - [Release notes](https://github.com/isaacs/minimatch/releases) - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v3.0.4...v3.1.2) Updates `recursive-readdir` from 2.2.2 to 2.2.3 - [Release notes](https://github.com/jergason/recursive-readdir/releases) - [Changelog](https://github.com/jergason/recursive-readdir/blob/master/CHANGELOG.md) - [Commits](https://github.com/jergason/recursive-readdir/commits/v2.2.3) --- updated-dependencies: - dependency-name: minimatch dependency-type: indirect - dependency-name: recursive-readdir dependency-type: indirect ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- web/playground/package-lock.json | 39 ++++++++------------------------ 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/web/playground/package-lock.json b/web/playground/package-lock.json index 53760bfc1007..b37f5e564fec 100644 --- a/web/playground/package-lock.json +++ b/web/playground/package-lock.json @@ -14929,25 +14929,14 @@ } }, "node_modules/recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", - "dependencies": { - "minimatch": "3.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/recursive-readdir/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dependencies": { - "brace-expansion": "^1.1.7" + "minimatch": "^3.0.5" }, "engines": { - "node": "*" + "node": ">=6.0.0" } }, "node_modules/redent": { @@ -28658,21 +28647,11 @@ } }, "recursive-readdir": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", - "integrity": "sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", + "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "requires": { - "minimatch": "3.0.4" - }, - "dependencies": { - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "requires": { - "brace-expansion": "^1.1.7" - } - } + "minimatch": "^3.0.5" } }, "redent": { From b0080a53103dadbbea024032b32c9f386ae77d6e Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 01:41:44 -0800 Subject: [PATCH 170/184] refactor: Move all bindings code to `bindings` path (#2121) * refactor: Move all bindings code to `bindings` path --- .github/actions/build-prql-js/action.yaml | 2 +- .github/actions/build-prql-python/action.yaml | 6 +++--- .github/workflows/release.yaml | 2 +- .github/workflows/test-dotnet.yaml | 2 +- .github/workflows/test-elixir.yaml | 2 +- .github/workflows/test-java.yaml | 2 +- .github/workflows/test-js.yaml | 2 +- .github/workflows/test-lib.yaml | 2 +- .github/workflows/test-php.yaml | 6 +++--- .github/workflows/test-python.yaml | 2 +- Cargo.toml | 10 +++++----- {prql-dotnet => bindings/prql-dotnet}/.gitignore | 0 .../prql-dotnet}/PrqlCompiler.Tests/CompilerTest.cs | 0 .../PrqlCompiler.Tests/PrqlCompiler.Tests.csproj | 0 .../prql-dotnet}/PrqlCompiler.Tests/Usings.cs | 0 .../prql-dotnet}/PrqlCompiler/PrqlCompiler.cs | 0 .../prql-dotnet}/PrqlCompiler/PrqlCompiler.csproj | 0 .../PrqlCompiler/PrqlCompilerOptions.cs | 0 {prql-dotnet => bindings/prql-dotnet}/README.md | 0 {prql-dotnet => bindings/prql-dotnet}/prql-net.sln | 0 .../prql-elixir}/.formatter.exs | 0 {prql-elixir => bindings/prql-elixir}/.gitignore | 0 {prql-elixir => bindings/prql-elixir}/README.md | 0 {prql-elixir => bindings/prql-elixir}/lib/prql.ex | 0 .../prql-elixir}/lib/prql/errors.ex | 0 .../prql-elixir}/lib/prql/native.ex | 0 {prql-elixir => bindings/prql-elixir}/mix.exs | 0 {prql-elixir => bindings/prql-elixir}/mix.lock | 0 .../prql-elixir}/native/prql/.cargo/config.toml | 0 .../prql-elixir}/native/prql/Cargo.toml | 2 +- .../prql-elixir}/native/prql/README.md | 0 .../prql-elixir}/native/prql/src/lib.rs | 0 .../prql-elixir}/test/prql_test.exs | 0 .../prql-elixir}/test/test_helper.exs | 0 {prql-java => bindings/prql-java}/.gitignore | 0 {prql-java => bindings/prql-java}/Cargo.toml | 2 +- {prql-java => bindings/prql-java}/DEVELOPMENT.md | 0 {prql-java => bindings/prql-java}/README.md | 0 {prql-java => bindings/prql-java}/cross.sh | 0 .../prql-java}/java/.mvn/wrapper/maven-wrapper.jar | Bin .../java/.mvn/wrapper/maven-wrapper.properties | 0 {prql-java => bindings/prql-java}/java/build.sh | 9 +++++---- {prql-java => bindings/prql-java}/java/mvnw | 0 {prql-java => bindings/prql-java}/java/mvnw.cmd | 0 {prql-java => bindings/prql-java}/java/pom.xml | 0 .../src/main/java/org/prql/prql4j/Environment.java | 0 .../java/org/prql/prql4j/NativeLibraryLoader.java | 0 .../src/main/java/org/prql/prql4j/PrqlCompiler.java | 0 .../prql-java}/java/src/main/resources/.gitkeep | 0 .../test/java/org/prql/prql4j/PrqlCompilerTest.java | 0 .../prql-java}/java/src/test/resources/.gitkeep | 0 {prql-java => bindings/prql-java}/src/lib.rs | 0 {prql-js => bindings/prql-js}/Cargo.toml | 2 +- {prql-js => bindings/prql-js}/README.md | 0 {prql-js => bindings/prql-js}/package-lock.json | 0 {prql-js => bindings/prql-js}/package.json | 0 {prql-js => bindings/prql-js}/src/lib.rs | 0 {prql-js => bindings/prql-js}/src/utils.rs | 0 {prql-js => bindings/prql-js}/tests/test_all.js | 0 {prql-lib => bindings/prql-lib}/Cargo.toml | 2 +- {prql-lib => bindings/prql-lib}/README.md | 0 {prql-lib => bindings/prql-lib}/cbindgen.toml | 0 .../prql-lib}/examples/minimal-c/Makefile | 4 ++-- .../prql-lib}/examples/minimal-c/README.md | 0 .../prql-lib}/examples/minimal-c/main.c | 0 {prql-lib => bindings/prql-lib}/libprql_lib.h | 0 {prql-lib => bindings/prql-lib}/src/lib.rs | 0 {prql-php => bindings/prql-php}/.gitignore | 0 {prql-php => bindings/prql-php}/README.md | 0 bindings/prql-php/build.sh | 8 ++++++++ {prql-php => bindings/prql-php}/composer.json | 0 {prql-php => bindings/prql-php}/composer.lock | 0 {prql-php => bindings/prql-php}/src/Compiler.php | 0 {prql-php => bindings/prql-php}/src/Message.php | 0 {prql-php => bindings/prql-php}/src/MessageKind.php | 0 {prql-php => bindings/prql-php}/src/Options.php | 0 {prql-php => bindings/prql-php}/src/Result.php | 0 .../prql-php}/src/SourceLocation.php | 0 {prql-php => bindings/prql-php}/src/Span.php | 0 .../prql-php}/tests/CompilerTest.php | 0 {prql-python => bindings/prql-python}/.gitignore | 0 {prql-python => bindings/prql-python}/Cargo.toml | 2 +- {prql-python => bindings/prql-python}/README.md | 0 {prql-python => bindings/prql-python}/build.rs | 0 {prql-python => bindings/prql-python}/noxfile.py | 2 +- .../prql-python}/pyproject.toml | 0 .../prql-python}/python/tests/conftest.py | 2 +- .../prql-python}/python/tests/test_all.py | 0 .../python/tests/test_website_queries.py | 0 .../prql-python}/requirements.txt | 0 {prql-python => bindings/prql-python}/src/lib.rs | 0 prql-php/build.sh | 6 ------ web/book/src/bindings/dotnet.md | 2 +- web/book/src/bindings/elixir.md | 2 +- web/book/src/bindings/javascript.md | 2 +- web/book/src/bindings/php.md | 2 +- 96 files changed, 45 insertions(+), 42 deletions(-) rename {prql-dotnet => bindings/prql-dotnet}/.gitignore (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler.Tests/CompilerTest.cs (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler.Tests/Usings.cs (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler/PrqlCompiler.cs (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler/PrqlCompiler.csproj (100%) rename {prql-dotnet => bindings/prql-dotnet}/PrqlCompiler/PrqlCompilerOptions.cs (100%) rename {prql-dotnet => bindings/prql-dotnet}/README.md (100%) rename {prql-dotnet => bindings/prql-dotnet}/prql-net.sln (100%) rename {prql-elixir => bindings/prql-elixir}/.formatter.exs (100%) rename {prql-elixir => bindings/prql-elixir}/.gitignore (100%) rename {prql-elixir => bindings/prql-elixir}/README.md (100%) rename {prql-elixir => bindings/prql-elixir}/lib/prql.ex (100%) rename {prql-elixir => bindings/prql-elixir}/lib/prql/errors.ex (100%) rename {prql-elixir => bindings/prql-elixir}/lib/prql/native.ex (100%) rename {prql-elixir => bindings/prql-elixir}/mix.exs (100%) rename {prql-elixir => bindings/prql-elixir}/mix.lock (100%) rename {prql-elixir => bindings/prql-elixir}/native/prql/.cargo/config.toml (100%) rename {prql-elixir => bindings/prql-elixir}/native/prql/Cargo.toml (83%) rename {prql-elixir => bindings/prql-elixir}/native/prql/README.md (100%) rename {prql-elixir => bindings/prql-elixir}/native/prql/src/lib.rs (100%) rename {prql-elixir => bindings/prql-elixir}/test/prql_test.exs (100%) rename {prql-elixir => bindings/prql-elixir}/test/test_helper.exs (100%) rename {prql-java => bindings/prql-java}/.gitignore (100%) rename {prql-java => bindings/prql-java}/Cargo.toml (82%) rename {prql-java => bindings/prql-java}/DEVELOPMENT.md (100%) rename {prql-java => bindings/prql-java}/README.md (100%) rename {prql-java => bindings/prql-java}/cross.sh (100%) rename {prql-java => bindings/prql-java}/java/.mvn/wrapper/maven-wrapper.jar (100%) rename {prql-java => bindings/prql-java}/java/.mvn/wrapper/maven-wrapper.properties (100%) rename {prql-java => bindings/prql-java}/java/build.sh (80%) rename {prql-java => bindings/prql-java}/java/mvnw (100%) rename {prql-java => bindings/prql-java}/java/mvnw.cmd (100%) rename {prql-java => bindings/prql-java}/java/pom.xml (100%) rename {prql-java => bindings/prql-java}/java/src/main/java/org/prql/prql4j/Environment.java (100%) rename {prql-java => bindings/prql-java}/java/src/main/java/org/prql/prql4j/NativeLibraryLoader.java (100%) rename {prql-java => bindings/prql-java}/java/src/main/java/org/prql/prql4j/PrqlCompiler.java (100%) rename {prql-java => bindings/prql-java}/java/src/main/resources/.gitkeep (100%) rename {prql-java => bindings/prql-java}/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java (100%) rename {prql-java => bindings/prql-java}/java/src/test/resources/.gitkeep (100%) rename {prql-java => bindings/prql-java}/src/lib.rs (100%) rename {prql-js => bindings/prql-js}/Cargo.toml (96%) rename {prql-js => bindings/prql-js}/README.md (100%) rename {prql-js => bindings/prql-js}/package-lock.json (100%) rename {prql-js => bindings/prql-js}/package.json (100%) rename {prql-js => bindings/prql-js}/src/lib.rs (100%) rename {prql-js => bindings/prql-js}/src/utils.rs (100%) rename {prql-js => bindings/prql-js}/tests/test_all.js (100%) rename {prql-lib => bindings/prql-lib}/Cargo.toml (83%) rename {prql-lib => bindings/prql-lib}/README.md (100%) rename {prql-lib => bindings/prql-lib}/cbindgen.toml (100%) rename {prql-lib => bindings/prql-lib}/examples/minimal-c/Makefile (82%) rename {prql-lib => bindings/prql-lib}/examples/minimal-c/README.md (100%) rename {prql-lib => bindings/prql-lib}/examples/minimal-c/main.c (100%) rename {prql-lib => bindings/prql-lib}/libprql_lib.h (100%) rename {prql-lib => bindings/prql-lib}/src/lib.rs (100%) rename {prql-php => bindings/prql-php}/.gitignore (100%) rename {prql-php => bindings/prql-php}/README.md (100%) create mode 100644 bindings/prql-php/build.sh rename {prql-php => bindings/prql-php}/composer.json (100%) rename {prql-php => bindings/prql-php}/composer.lock (100%) rename {prql-php => bindings/prql-php}/src/Compiler.php (100%) rename {prql-php => bindings/prql-php}/src/Message.php (100%) rename {prql-php => bindings/prql-php}/src/MessageKind.php (100%) rename {prql-php => bindings/prql-php}/src/Options.php (100%) rename {prql-php => bindings/prql-php}/src/Result.php (100%) rename {prql-php => bindings/prql-php}/src/SourceLocation.php (100%) rename {prql-php => bindings/prql-php}/src/Span.php (100%) rename {prql-php => bindings/prql-php}/tests/CompilerTest.php (100%) rename {prql-python => bindings/prql-python}/.gitignore (100%) rename {prql-python => bindings/prql-python}/Cargo.toml (88%) rename {prql-python => bindings/prql-python}/README.md (100%) rename {prql-python => bindings/prql-python}/build.rs (100%) rename {prql-python => bindings/prql-python}/noxfile.py (86%) rename {prql-python => bindings/prql-python}/pyproject.toml (100%) rename {prql-python => bindings/prql-python}/python/tests/conftest.py (83%) rename {prql-python => bindings/prql-python}/python/tests/test_all.py (100%) rename {prql-python => bindings/prql-python}/python/tests/test_website_queries.py (100%) rename {prql-python => bindings/prql-python}/requirements.txt (100%) rename {prql-python => bindings/prql-python}/src/lib.rs (100%) delete mode 100644 prql-php/build.sh diff --git a/.github/actions/build-prql-js/action.yaml b/.github/actions/build-prql-js/action.yaml index 804ed072502e..556bc9170997 100644 --- a/.github/actions/build-prql-js/action.yaml +++ b/.github/actions/build-prql-js/action.yaml @@ -19,4 +19,4 @@ runs: - name: Run wasm-pack for node, bundler, & web run: npm run build shell: bash - working-directory: prql-js/ + working-directory: bindings/prql-js/ diff --git a/.github/actions/build-prql-python/action.yaml b/.github/actions/build-prql-python/action.yaml index 4fd788076a98..995e59f642e0 100644 --- a/.github/actions/build-prql-python/action.yaml +++ b/.github/actions/build-prql-python/action.yaml @@ -15,17 +15,17 @@ runs: with: manylinux: auto command: build - args: --release -o dist -m prql-python/Cargo.toml + args: --release -o dist -m bindings/prql-python/Cargo.toml - uses: messense/maturin-action@v1 if: runner.os == 'Windows' with: command: build - args: --release -o dist -m prql-python/Cargo.toml + args: --release -o dist -m bindings/prql-python/Cargo.toml - uses: messense/maturin-action@v1 if: runner.os == 'macOS' with: command: build - args: --release -o dist --universal2 -m prql-python/Cargo.toml + args: --release -o dist --universal2 -m bindings/prql-python/Cargo.toml - name: Upload wheels uses: actions/upload-artifact@v3 with: diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index d473626ed494..3a9b51b47422 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -130,7 +130,7 @@ jobs: - uses: ./.github/actions/build-prql-js - name: Publish package on npm run: npm publish - working-directory: prql-js/ + working-directory: bindings/prql-js/ env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml index 849ce5c1f44c..197135d9c0ec 100644 --- a/.github/workflows/test-dotnet.yaml +++ b/.github/workflows/test-dotnet.yaml @@ -21,7 +21,7 @@ jobs: uses: actions/checkout@v3 - name: ๐Ÿ— Build prql-lib run: cargo build - working-directory: prql-lib + working-directory: bindings/prql-lib - name: ๐Ÿ”ง Setup dotnet uses: actions/setup-dotnet@v3 with: diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index cc8d37470ca7..c682f2506dc5 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -13,7 +13,7 @@ concurrency: defaults: run: - working-directory: prql-elixir + working-directory: bindings/prql-elixir env: MIX_ENV: test diff --git a/.github/workflows/test-java.yaml b/.github/workflows/test-java.yaml index ed3a8754510f..d8e5cb3562ac 100644 --- a/.github/workflows/test-java.yaml +++ b/.github/workflows/test-java.yaml @@ -22,5 +22,5 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - name: Maven test - working-directory: prql-java/java/ + working-directory: bindings/prql-java/java/ run: ./mvnw test diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index b018d0e9414b..bca7583911a4 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -23,4 +23,4 @@ jobs: uses: actions/checkout@v3 - uses: ./.github/actions/build-prql-js - run: npm cit - working-directory: prql-js + working-directory: bindings/prql-js diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml index d307cb7ef1e6..086a5a133c21 100644 --- a/.github/workflows/test-lib.yaml +++ b/.github/workflows/test-lib.yaml @@ -31,5 +31,5 @@ jobs: # Currently requires a release build; would be useful to allow a debug build. args: --release -p prql-lib - name: Run basic C example - working-directory: prql-lib/examples/minimal-c + working-directory: bindings/prql-lib/examples/minimal-c run: make run diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml index 14ea0fb88983..b42d039a803c 100644 --- a/.github/workflows/test-php.yaml +++ b/.github/workflows/test-php.yaml @@ -26,12 +26,12 @@ jobs: with: toolchain: stable - run: sh build.sh - working-directory: prql-php + working-directory: bindings/prql-php - name: ๐Ÿ“ฆ Install dependencies using Composer uses: php-actions/composer@v6 with: - args: --working-dir=prql-php + args: --working-dir=bindings/prql-php php_extensions: FFI - name: ๐Ÿงช Run tests using PHPUnit run: vendor/bin/phpunit tests - working-directory: prql-php + working-directory: bindings/prql-php diff --git a/.github/workflows/test-python.yaml b/.github/workflows/test-python.yaml index 212967b4928a..9728961e589d 100644 --- a/.github/workflows/test-python.yaml +++ b/.github/workflows/test-python.yaml @@ -42,4 +42,4 @@ jobs: hashFiles('prql-python/requirements.txt') }} - name: Run tests shell: bash - run: nox -s tests -f prql-python/noxfile.py + run: nox -s tests -f bindings/prql-python/noxfile.py diff --git a/Cargo.toml b/Cargo.toml index a660c89e844b..0f937c56304b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,12 +4,12 @@ members = [ "prql-compiler/examples/compile-files", "prql-compiler/prql-compiler-macros", "prql-compiler/prqlc", - "prql-java", - "prql-lib", - "prql-js", - "prql-python", + "bindings/prql-java", + "bindings/prql-lib", + "bindings/prql-js", + "bindings/prql-python", "web/book", - "prql-elixir/native/prql", + "bindings/prql-elixir/native/prql", ] # Note we don't have a `default-members = ["prql-compiler"]`, since that causes # commands like `cargo test` to only run tests from the default package. And diff --git a/prql-dotnet/.gitignore b/bindings/prql-dotnet/.gitignore similarity index 100% rename from prql-dotnet/.gitignore rename to bindings/prql-dotnet/.gitignore diff --git a/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs similarity index 100% rename from prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs rename to bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs diff --git a/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj b/bindings/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj similarity index 100% rename from prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj rename to bindings/prql-dotnet/PrqlCompiler.Tests/PrqlCompiler.Tests.csproj diff --git a/prql-dotnet/PrqlCompiler.Tests/Usings.cs b/bindings/prql-dotnet/PrqlCompiler.Tests/Usings.cs similarity index 100% rename from prql-dotnet/PrqlCompiler.Tests/Usings.cs rename to bindings/prql-dotnet/PrqlCompiler.Tests/Usings.cs diff --git a/prql-dotnet/PrqlCompiler/PrqlCompiler.cs b/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs similarity index 100% rename from prql-dotnet/PrqlCompiler/PrqlCompiler.cs rename to bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs diff --git a/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj b/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj similarity index 100% rename from prql-dotnet/PrqlCompiler/PrqlCompiler.csproj rename to bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.csproj diff --git a/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs b/bindings/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs similarity index 100% rename from prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs rename to bindings/prql-dotnet/PrqlCompiler/PrqlCompilerOptions.cs diff --git a/prql-dotnet/README.md b/bindings/prql-dotnet/README.md similarity index 100% rename from prql-dotnet/README.md rename to bindings/prql-dotnet/README.md diff --git a/prql-dotnet/prql-net.sln b/bindings/prql-dotnet/prql-net.sln similarity index 100% rename from prql-dotnet/prql-net.sln rename to bindings/prql-dotnet/prql-net.sln diff --git a/prql-elixir/.formatter.exs b/bindings/prql-elixir/.formatter.exs similarity index 100% rename from prql-elixir/.formatter.exs rename to bindings/prql-elixir/.formatter.exs diff --git a/prql-elixir/.gitignore b/bindings/prql-elixir/.gitignore similarity index 100% rename from prql-elixir/.gitignore rename to bindings/prql-elixir/.gitignore diff --git a/prql-elixir/README.md b/bindings/prql-elixir/README.md similarity index 100% rename from prql-elixir/README.md rename to bindings/prql-elixir/README.md diff --git a/prql-elixir/lib/prql.ex b/bindings/prql-elixir/lib/prql.ex similarity index 100% rename from prql-elixir/lib/prql.ex rename to bindings/prql-elixir/lib/prql.ex diff --git a/prql-elixir/lib/prql/errors.ex b/bindings/prql-elixir/lib/prql/errors.ex similarity index 100% rename from prql-elixir/lib/prql/errors.ex rename to bindings/prql-elixir/lib/prql/errors.ex diff --git a/prql-elixir/lib/prql/native.ex b/bindings/prql-elixir/lib/prql/native.ex similarity index 100% rename from prql-elixir/lib/prql/native.ex rename to bindings/prql-elixir/lib/prql/native.ex diff --git a/prql-elixir/mix.exs b/bindings/prql-elixir/mix.exs similarity index 100% rename from prql-elixir/mix.exs rename to bindings/prql-elixir/mix.exs diff --git a/prql-elixir/mix.lock b/bindings/prql-elixir/mix.lock similarity index 100% rename from prql-elixir/mix.lock rename to bindings/prql-elixir/mix.lock diff --git a/prql-elixir/native/prql/.cargo/config.toml b/bindings/prql-elixir/native/prql/.cargo/config.toml similarity index 100% rename from prql-elixir/native/prql/.cargo/config.toml rename to bindings/prql-elixir/native/prql/.cargo/config.toml diff --git a/prql-elixir/native/prql/Cargo.toml b/bindings/prql-elixir/native/prql/Cargo.toml similarity index 83% rename from prql-elixir/native/prql/Cargo.toml rename to bindings/prql-elixir/native/prql/Cargo.toml index 5c900b50e5be..7eee02890463 100644 --- a/prql-elixir/native/prql/Cargo.toml +++ b/bindings/prql-elixir/native/prql/Cargo.toml @@ -16,7 +16,7 @@ name = "prql" path = "src/lib.rs" [dependencies] -prql-compiler = {path = "../../../prql-compiler", default-features = false, version = "0.6.0" } +prql-compiler = {path = "../../../../prql-compiler", default-features = false, version = "0.6.0"} # See Readme for details on Mac [target.'cfg(not(any(target_family="wasm", target_os = "macos")))'.dependencies] diff --git a/prql-elixir/native/prql/README.md b/bindings/prql-elixir/native/prql/README.md similarity index 100% rename from prql-elixir/native/prql/README.md rename to bindings/prql-elixir/native/prql/README.md diff --git a/prql-elixir/native/prql/src/lib.rs b/bindings/prql-elixir/native/prql/src/lib.rs similarity index 100% rename from prql-elixir/native/prql/src/lib.rs rename to bindings/prql-elixir/native/prql/src/lib.rs diff --git a/prql-elixir/test/prql_test.exs b/bindings/prql-elixir/test/prql_test.exs similarity index 100% rename from prql-elixir/test/prql_test.exs rename to bindings/prql-elixir/test/prql_test.exs diff --git a/prql-elixir/test/test_helper.exs b/bindings/prql-elixir/test/test_helper.exs similarity index 100% rename from prql-elixir/test/test_helper.exs rename to bindings/prql-elixir/test/test_helper.exs diff --git a/prql-java/.gitignore b/bindings/prql-java/.gitignore similarity index 100% rename from prql-java/.gitignore rename to bindings/prql-java/.gitignore diff --git a/prql-java/Cargo.toml b/bindings/prql-java/Cargo.toml similarity index 82% rename from prql-java/Cargo.toml rename to bindings/prql-java/Cargo.toml index 6a225e972546..4253773dbff8 100644 --- a/prql-java/Cargo.toml +++ b/bindings/prql-java/Cargo.toml @@ -15,7 +15,7 @@ test = false [dependencies] jni = "0.20.0" -prql-compiler = {path = "../prql-compiler", default-features = false} +prql-compiler = {path = "../../prql-compiler", default-features = false} [package.metadata.release] tag-name = "{{version}}" diff --git a/prql-java/DEVELOPMENT.md b/bindings/prql-java/DEVELOPMENT.md similarity index 100% rename from prql-java/DEVELOPMENT.md rename to bindings/prql-java/DEVELOPMENT.md diff --git a/prql-java/README.md b/bindings/prql-java/README.md similarity index 100% rename from prql-java/README.md rename to bindings/prql-java/README.md diff --git a/prql-java/cross.sh b/bindings/prql-java/cross.sh similarity index 100% rename from prql-java/cross.sh rename to bindings/prql-java/cross.sh diff --git a/prql-java/java/.mvn/wrapper/maven-wrapper.jar b/bindings/prql-java/java/.mvn/wrapper/maven-wrapper.jar similarity index 100% rename from prql-java/java/.mvn/wrapper/maven-wrapper.jar rename to bindings/prql-java/java/.mvn/wrapper/maven-wrapper.jar diff --git a/prql-java/java/.mvn/wrapper/maven-wrapper.properties b/bindings/prql-java/java/.mvn/wrapper/maven-wrapper.properties similarity index 100% rename from prql-java/java/.mvn/wrapper/maven-wrapper.properties rename to bindings/prql-java/java/.mvn/wrapper/maven-wrapper.properties diff --git a/prql-java/java/build.sh b/bindings/prql-java/java/build.sh similarity index 80% rename from prql-java/java/build.sh rename to bindings/prql-java/java/build.sh index 97ade6799fd5..faa4a5ba092a 100755 --- a/prql-java/java/build.sh +++ b/bindings/prql-java/java/build.sh @@ -1,6 +1,8 @@ #!/bin/sh set -e +# TODO: use a task file for these build scripts + JAVA_SRC_HOME=$1 ARCH="$(uname -m)" KERNEL_NAME="$(uname -s)" @@ -9,7 +11,6 @@ KERNEL_VERSION="$(uname -r)" echo JAVA_SRC_HOME="$JAVA_SRC_HOME" cd "$JAVA_SRC_HOME" -# cd prql-java/ cd ../ echo Platform Info: "$ARCH" "$KERNEL_NAME" "$KERNEL_VERSION" @@ -17,7 +18,7 @@ echo Platform Info: "$ARCH" "$KERNEL_NAME" "$KERNEL_VERSION" echo building... cargo build --release echo building successfully -ls -la ../target/release +ls -la ../../target/release if [ "$KERNEL_NAME" = 'Linux' ]; then if [ "$ARCH" = 'arm64' ] || [ "$ARCH" = 'aarch64' ]; then @@ -27,7 +28,7 @@ if [ "$KERNEL_NAME" = 'Linux' ]; then else target='libprql_java-linux32.so' fi - cp -f ../target/release/libprql_java.so java/src/test/resources/${target} + cp -f ../../target/release/libprql_java.so java/src/test/resources/${target} elif [ "$KERNEL_NAME" = 'Darwin' ]; then if [ "$ARCH" = 'arm64' ] || [ "$ARCH" = 'aarch64' ]; then target='libprql_java-osx-arm64.dylib' @@ -37,7 +38,7 @@ elif [ "$KERNEL_NAME" = 'Darwin' ]; then echo [ERROR] have not support $ARCH:$$KERNEL_NAME yet exit 1 fi - cp -f ../target/release/libprql_java.dylib java/src/test/resources/${target} + cp -f ../../target/release/libprql_java.dylib java/src/test/resources/${target} fi ls -la ./java/src/main/resources diff --git a/prql-java/java/mvnw b/bindings/prql-java/java/mvnw similarity index 100% rename from prql-java/java/mvnw rename to bindings/prql-java/java/mvnw diff --git a/prql-java/java/mvnw.cmd b/bindings/prql-java/java/mvnw.cmd similarity index 100% rename from prql-java/java/mvnw.cmd rename to bindings/prql-java/java/mvnw.cmd diff --git a/prql-java/java/pom.xml b/bindings/prql-java/java/pom.xml similarity index 100% rename from prql-java/java/pom.xml rename to bindings/prql-java/java/pom.xml diff --git a/prql-java/java/src/main/java/org/prql/prql4j/Environment.java b/bindings/prql-java/java/src/main/java/org/prql/prql4j/Environment.java similarity index 100% rename from prql-java/java/src/main/java/org/prql/prql4j/Environment.java rename to bindings/prql-java/java/src/main/java/org/prql/prql4j/Environment.java diff --git a/prql-java/java/src/main/java/org/prql/prql4j/NativeLibraryLoader.java b/bindings/prql-java/java/src/main/java/org/prql/prql4j/NativeLibraryLoader.java similarity index 100% rename from prql-java/java/src/main/java/org/prql/prql4j/NativeLibraryLoader.java rename to bindings/prql-java/java/src/main/java/org/prql/prql4j/NativeLibraryLoader.java diff --git a/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java b/bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java similarity index 100% rename from prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java rename to bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java diff --git a/prql-java/java/src/main/resources/.gitkeep b/bindings/prql-java/java/src/main/resources/.gitkeep similarity index 100% rename from prql-java/java/src/main/resources/.gitkeep rename to bindings/prql-java/java/src/main/resources/.gitkeep diff --git a/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java b/bindings/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java similarity index 100% rename from prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java rename to bindings/prql-java/java/src/test/java/org/prql/prql4j/PrqlCompilerTest.java diff --git a/prql-java/java/src/test/resources/.gitkeep b/bindings/prql-java/java/src/test/resources/.gitkeep similarity index 100% rename from prql-java/java/src/test/resources/.gitkeep rename to bindings/prql-java/java/src/test/resources/.gitkeep diff --git a/prql-java/src/lib.rs b/bindings/prql-java/src/lib.rs similarity index 100% rename from prql-java/src/lib.rs rename to bindings/prql-java/src/lib.rs diff --git a/prql-js/Cargo.toml b/bindings/prql-js/Cargo.toml similarity index 96% rename from prql-js/Cargo.toml rename to bindings/prql-js/Cargo.toml index c74ee4057dec..bc44373f6ef0 100644 --- a/prql-js/Cargo.toml +++ b/bindings/prql-js/Cargo.toml @@ -22,7 +22,7 @@ test = false default = ["console_error_panic_hook"] [dependencies] -prql-compiler = {path = "../prql-compiler", default-features = false} +prql-compiler = {path = "../../prql-compiler", default-features = false} # This was preventing the playground from working. It's possibly # https://github.com/rustwasm/wasm-bindgen/issues/3276 # If the playground works with a later version, we can unpin this. It's likely diff --git a/prql-js/README.md b/bindings/prql-js/README.md similarity index 100% rename from prql-js/README.md rename to bindings/prql-js/README.md diff --git a/prql-js/package-lock.json b/bindings/prql-js/package-lock.json similarity index 100% rename from prql-js/package-lock.json rename to bindings/prql-js/package-lock.json diff --git a/prql-js/package.json b/bindings/prql-js/package.json similarity index 100% rename from prql-js/package.json rename to bindings/prql-js/package.json diff --git a/prql-js/src/lib.rs b/bindings/prql-js/src/lib.rs similarity index 100% rename from prql-js/src/lib.rs rename to bindings/prql-js/src/lib.rs diff --git a/prql-js/src/utils.rs b/bindings/prql-js/src/utils.rs similarity index 100% rename from prql-js/src/utils.rs rename to bindings/prql-js/src/utils.rs diff --git a/prql-js/tests/test_all.js b/bindings/prql-js/tests/test_all.js similarity index 100% rename from prql-js/tests/test_all.js rename to bindings/prql-js/tests/test_all.js diff --git a/prql-lib/Cargo.toml b/bindings/prql-lib/Cargo.toml similarity index 83% rename from prql-lib/Cargo.toml rename to bindings/prql-lib/Cargo.toml index b1ea6bc72b77..0057fd96f4eb 100644 --- a/prql-lib/Cargo.toml +++ b/bindings/prql-lib/Cargo.toml @@ -15,7 +15,7 @@ test = false [dependencies] libc = "0.2" -prql-compiler = {path = "../prql-compiler", default-features = false} +prql-compiler = {path = "../../prql-compiler", default-features = false} serde_json = "1.0" [package.metadata.release] diff --git a/prql-lib/README.md b/bindings/prql-lib/README.md similarity index 100% rename from prql-lib/README.md rename to bindings/prql-lib/README.md diff --git a/prql-lib/cbindgen.toml b/bindings/prql-lib/cbindgen.toml similarity index 100% rename from prql-lib/cbindgen.toml rename to bindings/prql-lib/cbindgen.toml diff --git a/prql-lib/examples/minimal-c/Makefile b/bindings/prql-lib/examples/minimal-c/Makefile similarity index 82% rename from prql-lib/examples/minimal-c/Makefile rename to bindings/prql-lib/examples/minimal-c/Makefile index cf56b87285db..dfd78af60a5f 100644 --- a/prql-lib/examples/minimal-c/Makefile +++ b/bindings/prql-lib/examples/minimal-c/Makefile @@ -1,4 +1,4 @@ -PRQL_PROJECT=../../.. +PRQL_PROJECT=../../../.. build-prql: cargo build -p prql-lib --release @@ -6,7 +6,7 @@ build-prql: # TODO: would be helpful to allow running with a debug build too. build: main.c build-prql gcc main.c -o main.out \ - -I${PRQL_PROJECT}/prql-lib \ + -I${PRQL_PROJECT}/bindings/prql-lib \ -L${PRQL_PROJECT}/target/release \ -l:libprql_lib.a \ -pthread -ldl -lm diff --git a/prql-lib/examples/minimal-c/README.md b/bindings/prql-lib/examples/minimal-c/README.md similarity index 100% rename from prql-lib/examples/minimal-c/README.md rename to bindings/prql-lib/examples/minimal-c/README.md diff --git a/prql-lib/examples/minimal-c/main.c b/bindings/prql-lib/examples/minimal-c/main.c similarity index 100% rename from prql-lib/examples/minimal-c/main.c rename to bindings/prql-lib/examples/minimal-c/main.c diff --git a/prql-lib/libprql_lib.h b/bindings/prql-lib/libprql_lib.h similarity index 100% rename from prql-lib/libprql_lib.h rename to bindings/prql-lib/libprql_lib.h diff --git a/prql-lib/src/lib.rs b/bindings/prql-lib/src/lib.rs similarity index 100% rename from prql-lib/src/lib.rs rename to bindings/prql-lib/src/lib.rs diff --git a/prql-php/.gitignore b/bindings/prql-php/.gitignore similarity index 100% rename from prql-php/.gitignore rename to bindings/prql-php/.gitignore diff --git a/prql-php/README.md b/bindings/prql-php/README.md similarity index 100% rename from prql-php/README.md rename to bindings/prql-php/README.md diff --git a/bindings/prql-php/build.sh b/bindings/prql-php/build.sh new file mode 100644 index 000000000000..6964f183f88d --- /dev/null +++ b/bindings/prql-php/build.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +# TODO: use a task file for these build scripts + +cargo build -p prql-lib --release + +mkdir -p lib +cp ../../target/release/libprql_lib.so ../prql-lib/libprql_lib.h lib diff --git a/prql-php/composer.json b/bindings/prql-php/composer.json similarity index 100% rename from prql-php/composer.json rename to bindings/prql-php/composer.json diff --git a/prql-php/composer.lock b/bindings/prql-php/composer.lock similarity index 100% rename from prql-php/composer.lock rename to bindings/prql-php/composer.lock diff --git a/prql-php/src/Compiler.php b/bindings/prql-php/src/Compiler.php similarity index 100% rename from prql-php/src/Compiler.php rename to bindings/prql-php/src/Compiler.php diff --git a/prql-php/src/Message.php b/bindings/prql-php/src/Message.php similarity index 100% rename from prql-php/src/Message.php rename to bindings/prql-php/src/Message.php diff --git a/prql-php/src/MessageKind.php b/bindings/prql-php/src/MessageKind.php similarity index 100% rename from prql-php/src/MessageKind.php rename to bindings/prql-php/src/MessageKind.php diff --git a/prql-php/src/Options.php b/bindings/prql-php/src/Options.php similarity index 100% rename from prql-php/src/Options.php rename to bindings/prql-php/src/Options.php diff --git a/prql-php/src/Result.php b/bindings/prql-php/src/Result.php similarity index 100% rename from prql-php/src/Result.php rename to bindings/prql-php/src/Result.php diff --git a/prql-php/src/SourceLocation.php b/bindings/prql-php/src/SourceLocation.php similarity index 100% rename from prql-php/src/SourceLocation.php rename to bindings/prql-php/src/SourceLocation.php diff --git a/prql-php/src/Span.php b/bindings/prql-php/src/Span.php similarity index 100% rename from prql-php/src/Span.php rename to bindings/prql-php/src/Span.php diff --git a/prql-php/tests/CompilerTest.php b/bindings/prql-php/tests/CompilerTest.php similarity index 100% rename from prql-php/tests/CompilerTest.php rename to bindings/prql-php/tests/CompilerTest.php diff --git a/prql-python/.gitignore b/bindings/prql-python/.gitignore similarity index 100% rename from prql-python/.gitignore rename to bindings/prql-python/.gitignore diff --git a/prql-python/Cargo.toml b/bindings/prql-python/Cargo.toml similarity index 88% rename from prql-python/Cargo.toml rename to bindings/prql-python/Cargo.toml index 0f5adc08c9dd..23933f393284 100644 --- a/prql-python/Cargo.toml +++ b/bindings/prql-python/Cargo.toml @@ -17,7 +17,7 @@ name = "prql_python" pyo3 = {version = "0.18.0", features = ["abi3-py37"]} [dependencies] -prql-compiler = {path = "../prql-compiler", default-features = false} +prql-compiler = {path = "../../prql-compiler", default-features = false} [dev-dependencies] insta = {version = "1.28", features = ["colors", "glob", "yaml"]} diff --git a/prql-python/README.md b/bindings/prql-python/README.md similarity index 100% rename from prql-python/README.md rename to bindings/prql-python/README.md diff --git a/prql-python/build.rs b/bindings/prql-python/build.rs similarity index 100% rename from prql-python/build.rs rename to bindings/prql-python/build.rs diff --git a/prql-python/noxfile.py b/bindings/prql-python/noxfile.py similarity index 86% rename from prql-python/noxfile.py rename to bindings/prql-python/noxfile.py index a695600cfbed..101a38c7e9e0 100644 --- a/prql-python/noxfile.py +++ b/bindings/prql-python/noxfile.py @@ -22,7 +22,7 @@ def tests(session: Session) -> None: """Run the test suite with pytest.""" print("CWD", os.getcwd()) session.install( - "-v", "--no-index", f"--find-links={Path('..', 'dist')}", "prql_python" + "-v", "--no-index", f"--find-links={Path('..', '..', 'dist')}", "prql_python" ) session.install("-v", "-r", "requirements.txt") session.run("pytest", str(Path("python", "tests"))) diff --git a/prql-python/pyproject.toml b/bindings/prql-python/pyproject.toml similarity index 100% rename from prql-python/pyproject.toml rename to bindings/prql-python/pyproject.toml diff --git a/prql-python/python/tests/conftest.py b/bindings/prql-python/python/tests/conftest.py similarity index 83% rename from prql-python/python/tests/conftest.py rename to bindings/prql-python/python/tests/conftest.py index 195af308a287..a12d02b8049e 100644 --- a/prql-python/python/tests/conftest.py +++ b/bindings/prql-python/python/tests/conftest.py @@ -5,7 +5,7 @@ @pytest.fixture() def example_queries(): - website_path = "../web/website/content/_index.md" + website_path = "../../web/website/content/_index.md" with open(website_path, "r") as f: website = f.read() website_yaml = yaml.safe_load(website.replace("---", "")) diff --git a/prql-python/python/tests/test_all.py b/bindings/prql-python/python/tests/test_all.py similarity index 100% rename from prql-python/python/tests/test_all.py rename to bindings/prql-python/python/tests/test_all.py diff --git a/prql-python/python/tests/test_website_queries.py b/bindings/prql-python/python/tests/test_website_queries.py similarity index 100% rename from prql-python/python/tests/test_website_queries.py rename to bindings/prql-python/python/tests/test_website_queries.py diff --git a/prql-python/requirements.txt b/bindings/prql-python/requirements.txt similarity index 100% rename from prql-python/requirements.txt rename to bindings/prql-python/requirements.txt diff --git a/prql-python/src/lib.rs b/bindings/prql-python/src/lib.rs similarity index 100% rename from prql-python/src/lib.rs rename to bindings/prql-python/src/lib.rs diff --git a/prql-php/build.sh b/prql-php/build.sh deleted file mode 100644 index bbb545bbd312..000000000000 --- a/prql-php/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -cargo build -p prql-lib --release - -mkdir -p lib -cp ../target/release/libprql_lib.so ../prql-lib/libprql_lib.h lib diff --git a/web/book/src/bindings/dotnet.md b/web/book/src/bindings/dotnet.md index 44724dc1320e..3cfe08319f7a 100644 --- a/web/book/src/bindings/dotnet.md +++ b/web/book/src/bindings/dotnet.md @@ -1 +1 @@ -{{#include ../../../../prql-dotnet/README.md}} +{{#include ../../../../bindings/prql-dotnet/README.md}} diff --git a/web/book/src/bindings/elixir.md b/web/book/src/bindings/elixir.md index b59bf72d885c..ac694430503a 100644 --- a/web/book/src/bindings/elixir.md +++ b/web/book/src/bindings/elixir.md @@ -1 +1 @@ -{{#include ../../../../prql-elixir/README.md}} +{{#include ../../../../bindings/prql-elixir/README.md}} diff --git a/web/book/src/bindings/javascript.md b/web/book/src/bindings/javascript.md index 50b53cfd3090..4ba2eaf85f67 100644 --- a/web/book/src/bindings/javascript.md +++ b/web/book/src/bindings/javascript.md @@ -1 +1 @@ -{{#include ../../../../prql-js/README.md}} +{{#include ../../../../bindings/prql-js/README.md}} diff --git a/web/book/src/bindings/php.md b/web/book/src/bindings/php.md index 69bc83459d10..43726cc12334 100644 --- a/web/book/src/bindings/php.md +++ b/web/book/src/bindings/php.md @@ -1 +1 @@ -{{#include ../../../../prql-php/README.md}} +{{#include ../../../../bindings/prql-php/README.md}} From d427c8689384a5acb70b8e965f02c2a6b9fdcd71 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 03:15:36 -0700 Subject: [PATCH 171/184] chore: Fix web build (#2123) --- web/playground/package-lock.json | 15 ++++++++++++--- web/playground/package.json | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/web/playground/package-lock.json b/web/playground/package-lock.json index b37f5e564fec..506ad981ccd1 100644 --- a/web/playground/package-lock.json +++ b/web/playground/package-lock.json @@ -15,7 +15,7 @@ "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "monaco-editor": "^0.36.0", - "prql-js": "file:../../prql-js", + "prql-js": "file:../../bindings/prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", @@ -27,8 +27,17 @@ "npm-watch": "^0.11.0" } }, + "../../bindings/prql-js": { + "version": "0.6.0", + "license": "Apache-2.0", + "devDependencies": { + "chai": "^4.3.6", + "mocha": "^10.0.0" + } + }, "../../prql-js": { "version": "0.6.0", + "extraneous": true, "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", @@ -14617,7 +14626,7 @@ } }, "node_modules/prql-js": { - "resolved": "../../prql-js", + "resolved": "../../bindings/prql-js", "link": true }, "node_modules/prr": { @@ -28409,7 +28418,7 @@ } }, "prql-js": { - "version": "file:../../prql-js", + "version": "file:../../bindings/prql-js", "requires": { "chai": "^4.3.6", "mocha": "^10.0.0" diff --git a/web/playground/package.json b/web/playground/package.json index 777415fba84d..143a2c03ae0c 100644 --- a/web/playground/package.json +++ b/web/playground/package.json @@ -18,7 +18,7 @@ "@testing-library/react": "^14.0.0", "@testing-library/user-event": "^14.4.3", "monaco-editor": "^0.36.0", - "prql-js": "file:../../prql-js", + "prql-js": "file:../../bindings/prql-js", "react": "^18.2.0", "react-dom": "^18.2.0", "react-syntax-highlighter": "^15.5.0", @@ -41,7 +41,7 @@ "scripts": { "build": "react-scripts build", "eject": "react-scripts eject", - "preinstall": "cp -r ../../prql-compiler/tests/integration/data public && cd ../../prql-js && npm run build:bundler", + "preinstall": "cp -r ../../prql-compiler/tests/integration/data public && cd ../../bindings/prql-js && npm run build:bundler", "start": "react-scripts start", "test": "react-scripts test" }, From ebf3eed324b7a300e15617d0da2bc9d50b5a8a7c Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 12 Mar 2023 20:37:23 +0100 Subject: [PATCH 172/184] chore(prql-php): Cache the FFI (#2128) * Update Compiler.php * Update README.md --- bindings/prql-php/README.md | 2 +- bindings/prql-php/src/Compiler.php | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/bindings/prql-php/README.md b/bindings/prql-php/README.md index 66e283dcd7b5..73ae351e1958 100644 --- a/bindings/prql-php/README.md +++ b/bindings/prql-php/README.md @@ -23,7 +23,7 @@ use Prql\Compiler\Compiler; $prql = new Compiler(); $result = $prql->compile("from employees"); -echo($result->output); +echo $result->output; ``` ## Development diff --git a/bindings/prql-php/src/Compiler.php b/bindings/prql-php/src/Compiler.php index 3888f174ae90..c56a3a1f8eb0 100644 --- a/bindings/prql-php/src/Compiler.php +++ b/bindings/prql-php/src/Compiler.php @@ -31,15 +31,19 @@ */ final class Compiler { - private \FFI $ffi; + private static \FFI $ffi; /** * Initializes a new instance of the Compiler. * - * @param ?string|null $lib_path path to the libprql library + * @param string|null $lib_path path to the libprql library */ public function __construct(?string $lib_path = null) { + if (isset(self::$ffi)) { + return; + } + if ($lib_path === null) { $lib_path = __DIR__ . '/../lib'; } @@ -60,7 +64,7 @@ public function __construct(?string $lib_path = null) throw new \InvalidArgumentException('Cannot load header file.'); } - $this->ffi = \FFI::cdef($header_source, $library); + self::$ffi = \FFI::cdef($header_source, $library); } /** @@ -81,7 +85,7 @@ public function compile(string $prql_query, ?Options $options = null): Result $ffi_options = $this->optionsInit($options); - $res = $this->ffi->compile($prql_query, \FFI::addr($ffi_options)); + $res = self::$ffi->compile($prql_query, \FFI::addr($ffi_options)); $this->optionsDestroy($ffi_options); @@ -105,7 +109,7 @@ public function prqlToPL(string $prql_query): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->ffi->prql_to_pl($prql_query); + $res = self::$ffi->prql_to_pl($prql_query); return $this->convertResult($res); } @@ -127,7 +131,7 @@ public function plToRQ(string $pl_json): Result throw new \InvalidArgumentException('No query given.'); } - $res = $this->ffi->pl_to_rq($pl_json); + $res = self::$ffi->pl_to_rq($pl_json); return $this->convertResult($res); } @@ -152,7 +156,7 @@ public function rqToSQL(string $rq_json, ?Options $options = null): Result $ffi_options = $this->optionsInit($options); - $res = $this->ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); + $res = self::$ffi->rq_to_sql($rq_json, \FFI::addr($ffi_options)); $this->optionsDestroy($ffi_options); @@ -165,7 +169,7 @@ private function optionsInit(?Options $options = null) $options = new Options(); } - $ffi_options = $this->ffi->new('struct Options'); + $ffi_options = self::$ffi->new('struct Options'); $ffi_options->format = $options->format; $ffi_options->signature_comment = $options->signature_comment; @@ -200,7 +204,7 @@ private function convertResult($ffi_res): Result } // free the ffi_result - $this->ffi->result_destroy($ffi_res); + self::$ffi->result_destroy($ffi_res); return $res; } From 2233dfebd7e0dbeab85510ece28e182e1b56d010 Mon Sep 17 00:00:00 2001 From: Jelenkee <59470612+Jelenkee@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:48:36 +0100 Subject: [PATCH 173/184] feat: Code snippets from book in Playground (#2070) * added book examples to playground * fixed order of files * remove console.log * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * -visual changes * -used markdown instead of prql files * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fixed position of arrows * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * -moved generateBook --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- web/playground/.gitignore | 2 + web/playground/generateBook.js | 138 +++++++++++++++++++++++++ web/playground/package.json | 9 +- web/playground/src/app/App.js | 2 + web/playground/src/sidebar/Sidebar.css | 24 +++++ web/playground/src/sidebar/Sidebar.js | 48 +++++++-- 6 files changed, 212 insertions(+), 11 deletions(-) create mode 100644 web/playground/generateBook.js diff --git a/web/playground/.gitignore b/web/playground/.gitignore index b60248144766..a5f9e423a32e 100644 --- a/web/playground/.gitignore +++ b/web/playground/.gitignore @@ -24,3 +24,5 @@ npm-debug.log* yarn-debug.log* yarn-error.log* + +book.json diff --git a/web/playground/generateBook.js b/web/playground/generateBook.js new file mode 100644 index 000000000000..d5e5c3e2296f --- /dev/null +++ b/web/playground/generateBook.js @@ -0,0 +1,138 @@ +const { readdir, stat, readFile, writeFile } = require("fs/promises"); +const { join, relative, sep, normalize, basename } = require("path"); +const { EOL } = require("os"); + +async function* getAllFiles(dirPath) { + const files = await readdir(dirPath); + files.sort((a, b) => +isFile(a) - +isFile(b)); + + for (const file of files) { + const fullPath = join(dirPath, file); + if ((await stat(fullPath)).isDirectory()) { + yield fullPath; + yield* getAllFiles(fullPath); + } else { + if (fullPath.endsWith(".md")) { + yield fullPath; + } + } + } +} + +function depth(path) { + return path.split(sep).length; +} + +function isFile(path) { + return path.endsWith(".md"); +} + +/** + * @param {string} content + * @param {string} file + * @returns {{title:string, prql:string}[]} + */ +function getSnippets(content, file) { + const name = file.trim().toLowerCase().replace(/\s/g, "_"); + let heading = ""; + let prql = null; + const arr = []; + let index = 1; + const titles = new Set(); + content.split(/\r\n|\n/).forEach((line) => { + if (prql == null && line.startsWith("#") && line.includes("# ")) { + const spaceIndex = line.indexOf("# "); + heading = line + .slice(spaceIndex + 2) + .trim() + .toLowerCase() + .replace(/\s/g, "_"); + return; + } + if (line.trim() === "```prql") { + prql = ""; + return; + } + if (prql != null && line.trim() === "```") { + let title = heading || name; + if (titles.has(title)) { + title += `_${++index}`; + } else { + index = 1; + } + arr.push({ + title: title + ".prql", + prql: prql.trim(), + }); + titles.add(title); + prql = null; + return; + } + if (prql != null) { + prql = prql + line + EOL; + } + }); + if (arr.length !== titles.size) { + throw new Error("duplicate titles"); + } + return arr; +} + +(async () => { + const fileObject = {}; + const dir = join(__dirname, "..", "book", "src"); + const files = []; + let minDepth = 1e10; + for await (const file of getAllFiles(dir)) { + files.push(file); + minDepth = Math.min(depth(file)); + } + + for (const filePath of files) { + const relativeFile = relative(dir, filePath); + const snippets = isFile(filePath) + ? getSnippets( + (await readFile(filePath)).toString(), + basename(filePath).replace(/\..+/g, "").trim() + ) + : []; + if (!snippets.length && isFile(filePath)) { + continue; + } + const dept = depth(filePath) - minDepth; + fileObject[relativeFile] = [ + "", // editor + "", // content + dept, // depth + normalize(join(relativeFile, "..")), // parent + relativeFile, // id + basename(relativeFile).replace(/\..+/g, "").trim(), // name + ]; + for (const snippet of snippets) { + const id = relativeFile + "_" + snippet.title; + fileObject[id] = [ + "sql", + snippet.prql, + dept + 1, + relativeFile, + id, + snippet.title, + ]; + } + } + + // remove empty folders + const keys = Object.keys(fileObject); + const parents = new Set(); + Object.values(fileObject).forEach((v) => parents.add(v[3])); + for (const key of keys) { + if (!parents.has(key) && !fileObject[key][0]) { + delete fileObject[key]; + } + } + + await writeFile(join("src", "book.json"), JSON.stringify(fileObject)); +})().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/web/playground/package.json b/web/playground/package.json index 143a2c03ae0c..0ba2ec02f7af 100644 --- a/web/playground/package.json +++ b/web/playground/package.json @@ -39,11 +39,12 @@ "name": "prql-playground", "private": true, "scripts": { - "build": "react-scripts build", - "eject": "react-scripts eject", + "build": "npm run genBook && react-scripts build", + "eject": "npm run genBook && react-scripts eject", "preinstall": "cp -r ../../prql-compiler/tests/integration/data public && cd ../../bindings/prql-js && npm run build:bundler", - "start": "react-scripts start", - "test": "react-scripts test" + "start": "npm run genBook && react-scripts start", + "test": "npm run genBook && react-scripts test", + "genBook": "node generateBook.js" }, "version": "0.1.0" } diff --git a/web/playground/src/app/App.js b/web/playground/src/app/App.js index a0fe7531c76a..2bae9b889f0d 100644 --- a/web/playground/src/app/App.js +++ b/web/playground/src/app/App.js @@ -2,6 +2,7 @@ import "./App.css"; import Workbench from "../workbench/Workbench"; import Sidebar from "../sidebar/Sidebar"; import examples from "../examples"; +import book from "../book.json"; import * as duckdb from "../workbench/duckdb"; import React from "react"; @@ -26,6 +27,7 @@ class App extends React.Component { library: { examples, chinook, + book, "local storage": loadLocalStorage(), }, }; diff --git a/web/playground/src/sidebar/Sidebar.css b/web/playground/src/sidebar/Sidebar.css index 7a7293a025ce..8f6cca67af79 100644 --- a/web/playground/src/sidebar/Sidebar.css +++ b/web/playground/src/sidebar/Sidebar.css @@ -1,5 +1,7 @@ .sidebar { padding-top: 1rem; + min-width: fit-content; + overflow-y: auto; } section:not(:last-child) { border-bottom: 1px solid #666; @@ -20,6 +22,28 @@ section h2 { background-color: #ffffff1f; } +.folderRow ~ .fileRow:not(.folderRow)::before { + content: ""; + margin-right: 5px; +} + +.folderRow { + text-transform: capitalize; +} + +.folderRow::before { + content: "\1F892 "; + margin-right: 5px; + display: inline-block; + transition: transform 0.3s ease; + transform-origin: center; + transform: scale(1.25, 1.25); +} + +.folderRow.open::before { + transform: scale(1.25, 1.25) rotate(90deg); +} + section h1, section h2, section p, diff --git a/web/playground/src/sidebar/Sidebar.js b/web/playground/src/sidebar/Sidebar.js index 178c65408509..defd3f824017 100644 --- a/web/playground/src/sidebar/Sidebar.js +++ b/web/playground/src/sidebar/Sidebar.js @@ -1,24 +1,58 @@ import "./Sidebar.css"; import React from "react"; +import { useState } from "react"; function Sidebar({ library, onLoadFile }) { function loadFile(section, file) { onLoadFile(file, library[section][file]); } + function toggleFolder(id) { + openFolders[id] = !Boolean(openFolders[id]); + setOpenFolders(() => openFolders); + } + + function handleClick(section, file, id) { + if (isFile(file)) { + loadFile(section, file); + } else { + toggleFolder(id); + } + sv(($) => $ + 1); + } + + function isFile(path) { + return path.endsWith(".prql"); + } + const sections = []; + const [openFolders, setOpenFolders] = useState({}); + const [v, sv] = useState(1); for (const [section, files] of Object.entries(library)) { const fileRows = []; for (const [index, filename] of Object.keys(files).entries()) { + const array = files[filename]; + const depth = array[2]; + const parent = array[3]; + const id = array[4]; + const name = array[5]; fileRows.push( -
loadFile(section, filename)} - > - {filename} -
+ + {(parent == null || openFolders[parent] || depth === 0) && ( +
handleClick(section, filename, id)} + > + {name ?? filename} +
+ )} +
); } From 19aa5724229f97f18c94292cc1ddd735d59b9983 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 12 Mar 2023 21:12:37 +0100 Subject: [PATCH 174/184] chore(prql-php): Add PHPStan configuration file (#2127) * Create * Update phpstan.neon * Update bindings/prql-php/phpstan.neon Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> * Update phpstan.neon --------- Co-authored-by: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> --- bindings/prql-php/phpstan.neon | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 bindings/prql-php/phpstan.neon diff --git a/bindings/prql-php/phpstan.neon b/bindings/prql-php/phpstan.neon new file mode 100644 index 000000000000..e68e067527ee --- /dev/null +++ b/bindings/prql-php/phpstan.neon @@ -0,0 +1,16 @@ +parameters: + level: 9 + paths: + - src + - tests + ignoreErrors: + # Since PHPStan doesn't know about the existence of the functions in libprql, + # it complains since they get dynamically invoked on the FFI object instance + # without being statically defined, so they're unknown. + - '#Call to an undefined method FFI::compile\(\)\.#' + - '#Call to an undefined method FFI::prql_to_pl\(\)\.#' + - '#Call to an undefined method FFI::pl_to_rq\(\)\.#' + - '#Call to an undefined method FFI::rq_to_sql\(\)\.#' + - '#Cannot access property \$format on FFI\\CData\|null\.#' + - '#Cannot access property \$signature_comment on FFI\\CData\|null\.#' + - '#Cannot access property \$target on FFI\\CData\|null\.#' From 044ad29e30f3705c66eccafd569beb78bfa53042 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 13:37:58 -0700 Subject: [PATCH 175/184] chore(ci): Fix paths in CI triggers (#2130) --- .github/workflows/test-dotnet.yaml | 4 ++-- .github/workflows/test-elixir.yaml | 2 +- .github/workflows/test-java.yaml | 4 ++-- .github/workflows/test-js.yaml | 2 +- .github/workflows/test-lib.yaml | 2 +- .github/workflows/test-php.yaml | 4 ++-- .github/workflows/test-python.yaml | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml index 197135d9c0ec..ed7340794d95 100644 --- a/.github/workflows/test-dotnet.yaml +++ b/.github/workflows/test-dotnet.yaml @@ -3,8 +3,8 @@ name: test-dotnet on: # pull_request: # paths: - # - "prql-dotnet/**" - # - "prql-lib/**" + # - "bindings/prql-dotnet/**" + # - "bindings/prql-lib/**" # - ".github/workflows/test-dotnet.yaml" workflow_call: diff --git a/.github/workflows/test-elixir.yaml b/.github/workflows/test-elixir.yaml index c682f2506dc5..99de8f1cf12d 100644 --- a/.github/workflows/test-elixir.yaml +++ b/.github/workflows/test-elixir.yaml @@ -3,7 +3,7 @@ name: test-elixir on: # pull_request: # paths: - # - "prql-elixir/**" + # - "bindings/prql-elixir/**" # - ".github/workflows/test-elixir.yaml" workflow_call: diff --git a/.github/workflows/test-java.yaml b/.github/workflows/test-java.yaml index d8e5cb3562ac..a16bae9e8b22 100644 --- a/.github/workflows/test-java.yaml +++ b/.github/workflows/test-java.yaml @@ -3,8 +3,8 @@ name: test-java on: pull_request: paths: - - "prql-java/**" - - "prql-lib/**" + - "bindings/prql-java/**" + - "bindings/prql-lib/**" - ".github/workflows/test-java.yaml" workflow_call: diff --git a/.github/workflows/test-js.yaml b/.github/workflows/test-js.yaml index bca7583911a4..8ec0b0158c55 100644 --- a/.github/workflows/test-js.yaml +++ b/.github/workflows/test-js.yaml @@ -3,7 +3,7 @@ name: test-js on: pull_request: paths: - - "prql-js/**" + - "bindings/prql-js/**" - ".github/workflows/test-js.yaml" workflow_call: diff --git a/.github/workflows/test-lib.yaml b/.github/workflows/test-lib.yaml index 086a5a133c21..0e1a7a838cbb 100644 --- a/.github/workflows/test-lib.yaml +++ b/.github/workflows/test-lib.yaml @@ -4,7 +4,7 @@ on: pull_request: paths: # We also run the tests for the libraries that depend on this, from their workflow files. - - "prql-lib/**" + - "bindings/prql-lib/**" - ".github/workflows/test-lib.yaml" workflow_call: diff --git a/.github/workflows/test-php.yaml b/.github/workflows/test-php.yaml index b42d039a803c..197bfc3477a8 100644 --- a/.github/workflows/test-php.yaml +++ b/.github/workflows/test-php.yaml @@ -3,8 +3,8 @@ name: test-php on: pull_request: paths: - - "prql-php/**" - - "prql-lib/**" + - "bindings/prql-php/**" + - "bindings/prql-lib/**" - ".github/workflows/test-php.yaml" workflow_call: diff --git a/.github/workflows/test-python.yaml b/.github/workflows/test-python.yaml index 9728961e589d..43489999b4c3 100644 --- a/.github/workflows/test-python.yaml +++ b/.github/workflows/test-python.yaml @@ -3,7 +3,7 @@ name: test-python on: pull_request: paths: - - "prql-python/**" + - "bindings/prql-python/**" - ".github/workflows/test-python.yaml" workflow_call: From c197ce27fc50248c90010e842c3ef7cbd8203f37 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 13:41:25 -0700 Subject: [PATCH 176/184] ci: Add dependabot config for `prql-js` (#2131) --- .github/dependabot.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index cf0f85edf82a..28bf10f7d512 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,7 +19,18 @@ updates: prefix: "chore: " - package-ecosystem: "npm" - directory: "/playground" + directory: "/bindings/prql-js" + schedule: + interval: daily + ignore: + - dependency-name: "*" + update-types: + - version-update:semver-patch + commit-message: + prefix: "chore: " + + - package-ecosystem: "npm" + directory: "/web/playground" schedule: interval: daily ignore: From 8ecfdebedb031042b78d9ecfbb83910a5db1494a Mon Sep 17 00:00:00 2001 From: Jonathan Date: Sun, 12 Mar 2023 22:25:19 +0100 Subject: [PATCH 177/184] feat(prql-lib): Generate C++ header file (#2126) * Update README.md * Add files via upload * Update CHANGELOG.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update CHANGELOG.md * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 6 +- bindings/prql-lib/README.md | 7 ++ bindings/prql-lib/libprql_lib.hpp | 152 ++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 bindings/prql-lib/libprql_lib.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index 599c04d04e5f..1a752acfa513 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ **Integrations**: +- [prql-lib] Added C++ header file. (@vanillajonathan, #2126) + **Internal changes**: **New Contributors**: @@ -743,8 +745,8 @@ improvements: - More examples on homepage; e.g. `join` & `window`, lots of small docs improvements - Automated releases to homebrew (@roG0d ) -- [prql-js](https://github.com/PRQL/prql/tree/main/prql-js) is now a single - package for node, browsers & webpack (@charlie-sanders ) +- [prql-js](https://github.com/PRQL/prql/tree/main/bindings/prql-js) is now a + single package for Node, browsers & webpack (@charlie-sanders ) - Parsing has some fixes, including `>=` and leading underscores in idents (@mklopets ) - Ranges receive correct syntax highlighting (@max-sixty ) diff --git a/bindings/prql-lib/README.md b/bindings/prql-lib/README.md index b56e0cb8e1ba..eaea13af9701 100644 --- a/bindings/prql-lib/README.md +++ b/bindings/prql-lib/README.md @@ -97,3 +97,10 @@ The C header file `libprql_lib.h` was generated using cargo install --force cbindgen cbindgen --crate prql-lib --output libprql_lib.h + +### C++ header file + +The C++ header file `libprql_lib.hpp` was generated using cbindgen. To generate +a new one run: + + cbindgen --crate prql-lib --lang C++ --output libprql_lib.hpp diff --git a/bindings/prql-lib/libprql_lib.hpp b/bindings/prql-lib/libprql_lib.hpp new file mode 100644 index 000000000000..01730ea43e56 --- /dev/null +++ b/bindings/prql-lib/libprql_lib.hpp @@ -0,0 +1,152 @@ +/* + * PRQL is a modern language for transforming data โ€” a simple, powerful, pipelined SQL replacement + * + * License: Apache-2.0 + * Website: https://prql-lang.org/ + */ + +/* This file is autogenerated. Do not modify this file manually. */ + +#include +#include +#include +#include +#include +#define FFI_SCOPE "PRQL" + +/// Compile message kind. Currently only Error is implemented. +enum class MessageKind { + Error, + Warning, + Lint, +}; + +/// Identifier of a location in source. +/// Contains offsets in terms of chars. +struct Span { + size_t start; + size_t end; +}; + +/// Location within a source file. +struct SourceLocation { + size_t start_line; + size_t start_col; + size_t end_line; + size_t end_col; +}; + +/// Compile result message. +/// +/// Calling code is responsible for freeing all memory allocated +/// for fields as well as strings. +struct Message { + /// Message kind. Currently only Error is implemented. + MessageKind kind; + /// Machine-readable identifier of the error + const int8_t *const *code; + /// Plain text of the error + const int8_t *reason; + /// A list of suggestions of how to fix the error + const int8_t *const *hint; + /// Character offset of error origin within a source file + const Span *span; + /// Annotated code, containing cause and hints. + const int8_t *const *display; + /// Line and column number of error origin within a source file + const SourceLocation *location; +}; + +/// Result of compilation. +struct CompileResult { + const int8_t *output; + const Message *messages; + size_t messages_len; +}; + +/// Compilation options +struct Options { + /// Pass generated SQL string trough a formatter that splits it + /// into multiple lines and prettifies indentation and spacing. + /// + /// Defaults to true. + bool format; + /// Target and dialect to compile to. + /// + /// Defaults to `sql.any`, which uses `target` argument from the query header to determine + /// the SQL dialect. + char *target; + /// Emits the compiler signature as a comment after generated SQL + /// + /// Defaults to true. + bool signature_comment; +}; + +extern "C" { + +/// Compile a PRQL string into a SQL string. +/// +/// This is a wrapper for: `prql_to_pl`, `pl_to_rq` and `rq_to_sql` without converting to JSON +/// between each of the functions. +/// +/// See `Options` struct for available compilation options. +/// +/// # Safety +/// +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. +CompileResult compile(const char *prql_query, const Options *options); + +/// Build PL AST from a PRQL string. PL in documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/pl). +/// +/// Takes PRQL source buffer and writes PL serialized as JSON to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// +/// # Safety +/// +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. +CompileResult prql_to_pl(const char *prql_query); + +/// Finds variable references, validates functions calls, determines frames and converts PL to RQ. +/// PL and RQ are documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast). +/// +/// Takes PL serialized as JSON buffer and writes RQ serialized as JSON to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// +/// # Safety +/// +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. +CompileResult pl_to_rq(const char *pl_json); + +/// Convert RQ AST into an SQL string. RQ is documented in the +/// [prql-compiler Rust crate](https://docs.rs/prql-compiler/latest/prql_compiler/ast/rq). +/// +/// Takes RQ serialized as JSON buffer and writes SQL source to `out` buffer. +/// +/// Returns 0 on success and a negative number -1 on failure. +/// +/// # Safety +/// +/// This function assumes zero-terminated input strings. +/// Calling code is responsible for freeing memory allocated for `CompileResult` +/// by calling `result_destroy`. +CompileResult rq_to_sql(const char *rq_json, const Options *options); + +/// Destroy a `CompileResult` once you are done with it. +/// +/// # Safety +/// +/// This function expects to be called exactly once after the call of any the functions +/// that return CompileResult. No fields should be freed manually. +void result_destroy(CompileResult res); + +} // extern "C" From eaa174bb1c0dd77898a7fff79c6da3eb0311ac69 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 14:34:33 -0700 Subject: [PATCH 178/184] devops: Remove `bug` label from other issue type (#2132) --- .../ISSUE_TEMPLATE/{feature_request.yaml => something_else.yaml} | 1 - 1 file changed, 1 deletion(-) rename .github/ISSUE_TEMPLATE/{feature_request.yaml => something_else.yaml} (91%) diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/something_else.yaml similarity index 91% rename from .github/ISSUE_TEMPLATE/feature_request.yaml rename to .github/ISSUE_TEMPLATE/something_else.yaml index 9cb8dbd82079..56f5cad63e46 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/something_else.yaml @@ -1,6 +1,5 @@ name: Something else description: Anything that's not a bug report -labels: [bug] body: - type: textarea id: what-happened From e9ee29cf01a354691bc316473a6e1b5f751ed60e Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 13 Mar 2023 01:32:31 +0100 Subject: [PATCH 179/184] chore(prql-dotnet): Fix .NET bindings (#2111) * Update CompilerTest.cs * Add files via upload * Update PrqlCompiler.cs * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update test-all.yaml * Update Result.cs * Update PrqlCompiler.cs * Update CompilerTest.cs * Update PrqlCompiler.cs --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Maximilian Roos --- .github/workflows/test-all.yaml | 4 +- .github/workflows/test-dotnet.yaml | 15 ++-- .../PrqlCompiler.Tests/CompilerTest.cs | 36 +++++++- bindings/prql-dotnet/PrqlCompiler/Message.cs | 46 ++++++++++ .../prql-dotnet/PrqlCompiler/MessageKind.cs | 24 +++++ .../PrqlCompiler/NativePrqlCompilerOptions.cs | 16 ++++ .../prql-dotnet/PrqlCompiler/NativeResult.cs | 11 +++ .../prql-dotnet/PrqlCompiler/PrqlCompiler.cs | 89 +++++++++++++++---- bindings/prql-dotnet/PrqlCompiler/Result.cs | 38 ++++++++ .../PrqlCompiler/SourceLocation.cs | 31 +++++++ bindings/prql-dotnet/PrqlCompiler/Span.cs | 22 +++++ 11 files changed, 300 insertions(+), 32 deletions(-) create mode 100644 bindings/prql-dotnet/PrqlCompiler/Message.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/MessageKind.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/NativePrqlCompilerOptions.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/NativeResult.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/Result.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/SourceLocation.cs create mode 100644 bindings/prql-dotnet/PrqlCompiler/Span.cs diff --git a/.github/workflows/test-all.yaml b/.github/workflows/test-all.yaml index 88e58cbc5d63..c51da0711cf2 100644 --- a/.github/workflows/test-all.yaml +++ b/.github/workflows/test-all.yaml @@ -48,8 +48,8 @@ jobs: test-elixir: uses: ./.github/workflows/test-elixir.yaml - # test-dotnet: - # uses: ./.github/workflows/test-dotnet.yaml + test-dotnet: + uses: ./.github/workflows/test-dotnet.yaml test-lib: uses: ./.github/workflows/test-lib.yaml diff --git a/.github/workflows/test-dotnet.yaml b/.github/workflows/test-dotnet.yaml index ed7340794d95..2e9ffcfaa6a3 100644 --- a/.github/workflows/test-dotnet.yaml +++ b/.github/workflows/test-dotnet.yaml @@ -1,11 +1,11 @@ name: test-dotnet on: - # pull_request: - # paths: - # - "bindings/prql-dotnet/**" - # - "bindings/prql-lib/**" - # - ".github/workflows/test-dotnet.yaml" + pull_request: + paths: + - "bindings/prql-dotnet/**" + - "bindings/prql-lib/**" + - ".github/workflows/test-dotnet.yaml" workflow_call: concurrency: @@ -27,8 +27,9 @@ jobs: with: dotnet-version: 7 - name: ๐Ÿงช Build and test + working-directory: bindings run: | dotnet build prql-dotnet - cp target/debug/libprql_lib.* prql-dotnet/PrqlCompiler/bin/Debug/net*/ - cp target/debug/libprql_lib.* prql-dotnet/PrqlCompiler.Tests/bin/Debug/net*/ + cp ../target/debug/libprql_lib.* prql-dotnet/PrqlCompiler/bin/Debug/net*/ + cp ../target/debug/libprql_lib.* prql-dotnet/PrqlCompiler.Tests/bin/Debug/net*/ dotnet test prql-dotnet diff --git a/bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs b/bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs index 3b07fb20b183..c9bb7f06ddfa 100644 --- a/bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs +++ b/bindings/prql-dotnet/PrqlCompiler.Tests/CompilerTest.cs @@ -9,16 +9,44 @@ public void ToCompile_Works() { // Arrange var expected = "SELECT * FROM employees"; - - // Act var options = new PrqlCompilerOptions { Format = false, SignatureComment = false, + Target = "sql.mssql" }; - var sqlQuery = PrqlCompiler.Compile("from employees", options); + + // Act + var result = PrqlCompiler.Compile("from employees", options); // Assert - Assert.Equal(expected, sqlQuery); + Assert.Equal(expected, result.Output); + } + + [Fact(Skip = "Fails")] + public void TestOtherFunctions() + { + // Arrange + var query = """ + let a = (from employees | take 10) + + from a | select [first_name] + """; + var options = new PrqlCompilerOptions(); + + // Act and assert + var pl = PrqlCompiler.PrqlToPl(query); + Assert.Empty(pl.Messages); + + var rq = PrqlCompiler.PlToRq(pl.Output); + Assert.Empty(rq.Messages); + + var via_json = PrqlCompiler.RqToSql(rq.Output, options); + Assert.Empty(via_json.Messages); + + var direct = PrqlCompiler.Compile(query); + Assert.Empty(direct.Messages); + + Assert.Equal(via_json, direct); } } diff --git a/bindings/prql-dotnet/PrqlCompiler/Message.cs b/bindings/prql-dotnet/PrqlCompiler/Message.cs new file mode 100644 index 000000000000..d580dd823000 --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/Message.cs @@ -0,0 +1,46 @@ +using System.Runtime.InteropServices; + +namespace Prql.Compiler +{ + /// + /// Compile result message. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct Message + { + /// + /// Message kind. Currently only Error is implemented. + /// + public MessageKind Kind { get; set; } + + /// + /// Machine-readable identifier of the error. + /// + public string Code { get; set; } + + /// + /// Plain text of the error. + /// + public string Reason { get; set; } + + /// + /// A list of suggestions of how to fix the error. + /// + public string Hint { get; set; } + + /// + /// Character offset of error origin within a source file. + /// + public Span Span { get; set; } + + /// + /// Annotated code, containing cause and hints. + /// + public string Display { get; set; } + + /// + /// Line and column number of error origin within a source file. + /// + public SourceLocation Location { get; set; } + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/MessageKind.cs b/bindings/prql-dotnet/PrqlCompiler/MessageKind.cs new file mode 100644 index 000000000000..efb0a4cb015f --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/MessageKind.cs @@ -0,0 +1,24 @@ +using System; + +namespace Prql.Compiler +{ + /// + /// Compile message kind. Currently only Error is implemented. + /// + [Serializable] + public enum MessageKind + { + /// + /// Error message. + /// + Error, + /// + /// Warning message. + /// + Warning, + /// + /// Lint message. + /// + Lint + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/NativePrqlCompilerOptions.cs b/bindings/prql-dotnet/PrqlCompiler/NativePrqlCompilerOptions.cs new file mode 100644 index 000000000000..c267e4eeed1e --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/NativePrqlCompilerOptions.cs @@ -0,0 +1,16 @@ +namespace Prql.Compiler +{ + internal struct NativePrqlCompilerOptions + { + public bool Format; + public string Target; + public bool SignatureComment; + + public NativePrqlCompilerOptions(PrqlCompilerOptions options) + { + Format = options.Format; + Target = options.Target; + SignatureComment = options.SignatureComment; + } + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/NativeResult.cs b/bindings/prql-dotnet/PrqlCompiler/NativeResult.cs new file mode 100644 index 000000000000..304559dee481 --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/NativeResult.cs @@ -0,0 +1,11 @@ +using System; + +namespace Prql.Compiler +{ + internal struct NativeResult + { + public string Output; + public IntPtr Messages; + public int MessagesLen; + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs b/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs index 500fb4c7ea70..a275bfcf168d 100644 --- a/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs +++ b/bindings/prql-dotnet/PrqlCompiler/PrqlCompiler.cs @@ -1,7 +1,5 @@ using System; -using System.Linq; using System.Runtime.InteropServices; -using System.Text; namespace Prql.Compiler { @@ -17,7 +15,7 @@ public static class PrqlCompiler /// SQL query. /// is null or empty. /// cannot be compiled. - public static string Compile(string prqlQuery) + public static Result Compile(string prqlQuery) { if (string.IsNullOrEmpty(prqlQuery)) { @@ -38,53 +36,106 @@ public static string Compile(string prqlQuery) /// is null or empty. /// is null. /// cannot be compiled. - public static string Compile(string prqlQuery, PrqlCompilerOptions options) + public static Result Compile(string prqlQuery, PrqlCompilerOptions options) { if (string.IsNullOrEmpty(prqlQuery)) { throw new ArgumentException(nameof(prqlQuery)); } - byte[] bytes = new byte[1024]; - if (CompileExtern(prqlQuery, ref options, bytes) != 0) + if (options is null) { - throw new FormatException("Could not compile query."); + throw new ArgumentException(nameof(options)); } - bytes = bytes.TakeWhile(x => ((char)x) != '\0').ToArray(); + var nativeOptions = new NativePrqlCompilerOptions(options); + var nativeResult = CompileExtern(prqlQuery, ref nativeOptions); + var result = new Result(nativeResult); - return Encoding.UTF8.GetString(bytes); + return result; } /// - /// Compile a PRQL string into a JSON string. + /// Build PL AST from a PRQL string. /// /// A PRQL query. /// JSON. /// is null or empty. /// cannot be compiled. - public static string ToJson(string prqlQuery) + /// https://docs.rs/prql-compiler/latest/prql_compiler/ast/pl + public static Result PrqlToPl(string prqlQuery) { if (string.IsNullOrEmpty(prqlQuery)) { throw new ArgumentException(nameof(prqlQuery)); } - byte[] bytes = new byte[1024]; - if (ToJsonExtern(prqlQuery, bytes) != 0) + var nativeResult = PrqlToPlExtern(prqlQuery); + var result = new Result(nativeResult); + + return result; + } + + /// + /// Finds variable references, validates functions calls, determines frames and converts PL to RQ. + /// + /// A PRQL query. + /// JSON. + /// is null or empty. + /// cannot be compiled. + /// https://docs.rs/prql-compiler/latest/prql_compiler/ast + public static Result PlToRq(string plJson) + { + if (string.IsNullOrEmpty(plJson)) + { + throw new ArgumentException(nameof(plJson)); + } + + var nativeResult = PlToRqExtern(plJson); + var result = new Result(nativeResult); + + return result; + } + + /// + /// Convert RQ AST into an SQL string. + /// + /// RQ string in JSON format. + /// PRQL compiler options. + /// JSON. + /// is null or empty. + /// is null. + /// cannot be compiled. + /// https://docs.rs/prql-compiler/latest/prql_compiler/ast/rq + public static Result RqToSql(string rqJson, PrqlCompilerOptions options) + { + if (string.IsNullOrEmpty(rqJson)) + { + throw new ArgumentException(nameof(rqJson)); + } + + if (options is null) { - throw new FormatException("Could not compile query."); + throw new ArgumentException(nameof(options)); } - bytes = bytes.TakeWhile(x => ((char)x) != '\0').ToArray(); + var nativeOptions = new NativePrqlCompilerOptions(options); + var nativeResult = RqToSqlExtern(rqJson, ref nativeOptions); + var result = new Result(nativeResult); - return Encoding.UTF8.GetString(bytes); + return result; } [DllImport("libprql_lib", EntryPoint = "compile")] - private static extern int CompileExtern(string prql_query, ref PrqlCompilerOptions options, byte[] sql_query); + private static extern NativeResult CompileExtern(string prqlQuery, ref NativePrqlCompilerOptions options); + + [DllImport("libprql_lib", EntryPoint = "prql_to_pl")] + private static extern NativeResult PrqlToPlExtern(string prqlQuery); + + [DllImport("libprql_lib", EntryPoint = "pl_to_rq")] + private static extern NativeResult PlToRqExtern(string plJson); - [DllImport("libprql_lib", EntryPoint = "to_json")] - private static extern int ToJsonExtern(string prql_query, byte[] json); + [DllImport("libprql_lib", EntryPoint = "rq_to_sql")] + private static extern NativeResult RqToSqlExtern(string rqJson, ref NativePrqlCompilerOptions options); } } diff --git a/bindings/prql-dotnet/PrqlCompiler/Result.cs b/bindings/prql-dotnet/PrqlCompiler/Result.cs new file mode 100644 index 000000000000..60568751d282 --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/Result.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Prql.Compiler +{ + /// + /// Result of compilation. + /// + public class Result + { + private readonly IReadOnlyCollection _messages; + + internal Result(NativeResult result) + { + Output = result.Output; + + var messages = new List(); + + for (var i = 0; i < result.MessagesLen; i++) + { + messages.Add(Marshal.PtrToStructure(result.Messages)); + } + + _messages = messages.ToList().AsReadOnly(); + } + + /// + /// The compiler output. + /// + public string Output { get; } + + /// + /// Error, warning and lint messages. + /// + public IReadOnlyCollection Messages => _messages; + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/SourceLocation.cs b/bindings/prql-dotnet/PrqlCompiler/SourceLocation.cs new file mode 100644 index 000000000000..426c65835def --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/SourceLocation.cs @@ -0,0 +1,31 @@ +using System.Runtime.InteropServices; + +namespace Prql.Compiler +{ + /// + /// Location within a source file. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct SourceLocation + { + /// + /// Start line. + /// + public int StartLine { get; set; } + + /// + /// Start column. + /// + public int StartCol { get; set; } + + /// + /// End line. + /// + public int EndLine { get; set; } + + /// + /// End column. + /// + public int EndCol { get; set; } + } +} diff --git a/bindings/prql-dotnet/PrqlCompiler/Span.cs b/bindings/prql-dotnet/PrqlCompiler/Span.cs new file mode 100644 index 000000000000..441347a96390 --- /dev/null +++ b/bindings/prql-dotnet/PrqlCompiler/Span.cs @@ -0,0 +1,22 @@ +using System.Runtime.InteropServices; + +namespace Prql.Compiler +{ + /// + /// Identifier of a location in source. + /// Contains offsets in terms of chars. + /// + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public struct Span + { + /// + /// Start offset. + /// + public int Start { get; set; } + + /// + /// End offset. + /// + public int End { get; set; } + } +} From 284958258ca77c42fc5bf3a93b008a2159b404ec Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:40:04 -0700 Subject: [PATCH 180/184] refactor: Move `prql-lexer` into `grammars` (#2136) * refactor: Move `prql-lexer` into `gramamrs` This PR also fixes some links. This completes the refactor. --- .../java/org/prql/prql4j/PrqlCompiler.java | 2 +- grammars/README.md | 31 ++++++++++++++++++ {prql-lezer => grammars/prql-lezer}/README.md | 0 .../prql-lezer}/src/prql.grammar | 0 web/book/highlight-prql.js | 2 +- web/book/src/contributing/development.md | 22 ++++++------- web/book/src/internals/syntax-highlighting.md | 32 +------------------ 7 files changed, 45 insertions(+), 44 deletions(-) create mode 100644 grammars/README.md rename {prql-lezer => grammars/prql-lezer}/README.md (100%) rename {prql-lezer => grammars/prql-lezer}/src/prql.grammar (100%) diff --git a/bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java b/bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java index bf0efbf46f23..3ced22ce59ad 100644 --- a/bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java +++ b/bindings/prql-java/java/src/main/java/org/prql/prql4j/PrqlCompiler.java @@ -7,7 +7,7 @@ public class PrqlCompiler { /** * compile PRQL to SQL * @param query PRQL query - * @param target target dialect, such as sql.mysql etc. Please refer PRQL Target and Version + * @param target target dialect, such as sql.mysql etc. Please refer PRQL Target and Version * @param format format SQL or not * @param signature comment signature or not * @return SQL diff --git a/grammars/README.md b/grammars/README.md new file mode 100644 index 000000000000..b7a3ea320660 --- /dev/null +++ b/grammars/README.md @@ -0,0 +1,31 @@ +# Grammars / syntax highlighting + +PRQL contains multiple grammar definitions to enable tools to highlight PRQL +code. These are all intended to provide as good an experience as the grammar +supports. Please raise any shortcomings in a GitHub issue. + +The definitions are somewhat scattered around the codebase; this page serves as +an index. + +- [Lezer](https://lezer.codemirror.net/) โ€” used by CodeMirror editors. The PRQL + file is at + [`grammars/prql-lezer/README.me`](https://github.com/PRQL/prql/tree/main/grammars/prql-lezer/README.md). + +- [Handlebars](https://handlebarsjs.com/) โ€” currently duplicated: + + - The book: + [`book/highlight-prql.js`](https://github.com/PRQL/prql/blob/main/web/book/highlight-prql.js) + - The website (outside of the book & playground): + [`website/themes/prql-theme/static/plugins/highlight/prql.js`](https://github.com/PRQL/prql/blob/main/web/book/highlight-prql.js) + +- [Textmate](https://macromates.com/manual/en/language_grammars) โ€” used by the + VS Code extension. It's in the `prql-vscode` repo in + [`prql-vscode/syntaxes/prql.tmLanguage.json`](https://github.com/PRQL/prql-vscode/blob/main/syntaxes/prql.tmLanguage.json). + +- [Monarch](https://microsoft.github.io/monaco-editor/monarch.html) โ€” used by + the Monaco editor, which we use for the Playground. The grammar is at + [`playground/src/workbench/prql-syntax.js`](https://github.com/PRQL/prql/blob/main/web/playground/src/workbench/prql-syntax.js). + +- [Tree-Sitter](https://tree-sitter.github.io/tree-sitter) โ€” used by the neovim + and helix. The grammar can be found at + [https://github.com/PRQL/tree-sitter-prql](https://github.com/PRQL/tree-sitter-prql). diff --git a/prql-lezer/README.md b/grammars/prql-lezer/README.md similarity index 100% rename from prql-lezer/README.md rename to grammars/prql-lezer/README.md diff --git a/prql-lezer/src/prql.grammar b/grammars/prql-lezer/src/prql.grammar similarity index 100% rename from prql-lezer/src/prql.grammar rename to grammars/prql-lezer/src/prql.grammar diff --git a/web/book/highlight-prql.js b/web/book/highlight-prql.js index 36f704dbe5bb..bc78c7c7d511 100644 --- a/web/book/highlight-prql.js +++ b/web/book/highlight-prql.js @@ -1,7 +1,7 @@ // Syntax highlighting for PRQL. // Keep consistent with -// https://github.com/PRQL/prql/blob/main/website/themes/prql-theme/static/highlight/prql.js +// https://github.com/PRQL/prql/blob/main/web/website/themes/prql-theme/static/highlight/prql.js // TODO: can we import one from the other at build time? // Inspired by [Pest's book](https://github.com/pest-parser/book) diff --git a/web/book/src/contributing/development.md b/web/book/src/contributing/development.md index 360d3e73be8d..7e711a2515a4 100644 --- a/web/book/src/contributing/development.md +++ b/web/book/src/contributing/development.md @@ -219,31 +219,31 @@ we're happy to link to it / tweet it. The PRQL project has several components. Instructions for working with them are in the **README.md** file in their respective paths. Here's an overview: -**[book](https://github.com/PRQL/prql/blob/main/book/README.md)**: The PRQL +**[book](https://github.com/PRQL/prql/blob/main/web/book/README.md)**: The PRQL language book, which documents the language. -**[playground](https://github.com/PRQL/prql/blob/main/playground/README.md)**: A -web GUI for the PRQL compiler. It shows the PRQL source beside the resulting SQL -output. +**[playground](https://github.com/PRQL/prql/blob/main/web/playground/README.md)**: +A web GUI for the PRQL compiler. It shows the PRQL source beside the resulting +SQL output. **[prql-compiler](https://github.com/PRQL/prql/blob/main/prql-compiler/README.md)**: Installation and usage instructions for building and running the `prql-compiler`. -**[prql-java](https://github.com/PRQL/prql/blob/main/prql-java/README.md)**: +**[prql-java](https://github.com/PRQL/prql/blob/main/bindings/prql-java/README.md)**: Rust bindings to the `prql-compiler` Rust library. -**[prql-js](https://github.com/PRQL/prql/blob/main/prql-js/README.md)**: +**[prql-js](https://github.com/PRQL/prql/blob/main/bindings/prql-js/README.md)**: Javascript bindings to the `prql-compiler` Rust library. -**[prql-lib](https://github.com/PRQL/prql/blob/main/prql-lib/README.md)**: +**[prql-lib](https://github.com/PRQL/prql/blob/main/bindings/prql-lib/README.md)**: Generates `.a` and `.so` libraries from the `prql-compiler` Rust library for bindings to other languages -**[prql-python](https://github.com/PRQL/prql/blob/main/prql-python/README.md)**: +**[prql-python](https://github.com/PRQL/prql/blob/main/bindings/prql-python/README.md)**: Python bindings to the `prql-compiler` Rust library. -**[website](https://github.com/PRQL/prql/blob/main/website/README.md)**: Our +**[website](https://github.com/PRQL/prql/blob/main/web/website/README.md)**: Our website, hosted at , built with `hugo`. ## How we test @@ -334,12 +334,12 @@ inconsistent in watchexec. Let's revert back if it gets solved. get into a loop of writing snapshot files, triggering a change, writing a snapshot file, etc. --> -- **[Examples](https://github.com/PRQL/prql/blob/main/book/tests/snapshot.rs)** +- **[Examples](https://github.com/PRQL/prql/blob/main/web/book/tests/snapshot.rs)** โ€”ย we compile all examples in the PRQL Book, to test that they produce the SQL we expect, and that changes to our code don't cause any unexpected regressions. -- **[Integration tests](https://github.com/PRQL/prql/blob/main/book/src/integrations/README.md)** +- **[Integration tests](https://github.com/PRQL/prql/blob/main/web/book/src/integrations/README.md)** โ€” these run tests against real databases, to ensure we're producing correct SQL. diff --git a/web/book/src/internals/syntax-highlighting.md b/web/book/src/internals/syntax-highlighting.md index 7249f249f37f..e15d25a9f14e 100644 --- a/web/book/src/internals/syntax-highlighting.md +++ b/web/book/src/internals/syntax-highlighting.md @@ -1,31 +1 @@ -# Syntax highlighting - -PRQL contains multiple grammar definitions to enable tools to highlight PRQL -code. These are all intended to provide as good an experience as the grammar -supports. Please raise any shortcomings in a GitHub issue. - -The definitions are somewhat scattered around the codebase; this page serves as -an index. - -- [Lezer](https://lezer.codemirror.net/) โ€” used by CodeMirror editors. The PRQL - file is at - [`prql-lezer/README.me`](https://github.com/PRQL/prql/tree/main/prql-lezer/README.md). - -- [Handlebars](https://handlebarsjs.com/) โ€” currently duplicated: - - - The book: - [`book/highlight-prql.js`](https://github.com/PRQL/prql/blob/main/book/highlight-prql.js) - - The website (outside of the book & playground): - [`website/themes/prql-theme/static/plugins/highlight/prql.js`](https://github.com/PRQL/prql/blob/main/book/highlight-prql.js) - -- [Textmate](https://macromates.com/manual/en/language_grammars) โ€” used by the - VS Code extension. It's in the `prql-vscode` repo in - [`prql-vscode/syntaxes/prql.tmLanguage.json`](https://github.com/PRQL/prql-vscode/blob/main/syntaxes/prql.tmLanguage.json). - -- [Monarch](https://microsoft.github.io/monaco-editor/monarch.html) โ€” used by - the Monaco editor, which we use for the Playground. The grammar is at - [`playground/src/workbench/prql-syntax.js`](https://github.com/PRQL/prql/blob/main/playground/src/workbench/prql-syntax.js). - -- [Tree-Sitter](https://tree-sitter.github.io/tree-sitter) โ€” used by the neovim - and helix. The grammar can be found at - [https://github.com/PRQL/tree-sitter-prql](https://github.com/PRQL/tree-sitter-prql). +{{#include ../../../../grammars/README.md}} From 142ecaa6c72c2f0034fbd91822c9c750b160e26b Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 17:41:00 -0700 Subject: [PATCH 181/184] refactor: Move `snap` to `packages` path (#2135) * refactor: Move `snap` to `packages` path ...in line with the broader refactor. I'm not sure of the best way of testing this; our current `release.yaml` isn't really set up to test things. Possibly we wait until the next release and fix if it's broken -- not ideal but maybe the lowest cost approach? --- .github/workflows/release.yaml | 2 ++ {snap => packages/snap}/snapcraft.yaml | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) rename {snap => packages/snap}/snapcraft.yaml (92%) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 3a9b51b47422..d125cc2bf22a 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -88,6 +88,8 @@ jobs: uses: actions/checkout@v3 - name: ๐Ÿ“ฆ Build Snap uses: snapcore/action-build@v1 + with: + path: packages/ - name: ๐Ÿ†™ Publish Snap uses: snapcore/action-publish@v1 env: diff --git a/snap/snapcraft.yaml b/packages/snap/snapcraft.yaml similarity index 92% rename from snap/snapcraft.yaml rename to packages/snap/snapcraft.yaml index dfa1fd7c1fa4..f4d96d6fa4b1 100644 --- a/snap/snapcraft.yaml +++ b/packages/snap/snapcraft.yaml @@ -14,12 +14,12 @@ website: https://prql-lang.org/ license: Apache-2.0 grade: devel # must be 'stable' to release into candidate/stable channels confinement: strict -icon: website/themes/prql-theme/static/icon.svg +icon: ../web/website/themes/prql-theme/static/icon.svg parts: prqlc: plugin: rust - source: . + source: .. rust-path: [prql-compiler/prqlc] apps: From 31ec987606c057ff774cf5f1876bf2ba9a57bc65 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 22:38:37 -0700 Subject: [PATCH 182/184] chore: Add changelog for #2121 (#2138) --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a752acfa513..37ead6119631 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,7 +9,7 @@ - No longer incorrectly compile to `DISTINCT` when a `take 1` refers to a different set of columns than are in the `group`. (@max-sixty, with thanks to @cottrell, #2109) -- The version specification of the dependent Chumsky was bumped from `0.9.0` to +- The version specification of the dependency Chumsky was bumped from `0.9.0` to `0.9.2`. `0.9.0` has a bug that causes an infinite loop. (@eitsupi, #2110) **Documentation**: @@ -22,6 +22,10 @@ **Internal changes**: +- Many of the items that were in the root of the repo have been aggregated into + `web` & `bindings`, simplifying the repo's structure. There's also `grammars` + & `packages` (@max-sixty, #2135, #2117, #2121). + **New Contributors**: ## 0.6.0 โ€” 2022-03-08 From 55846092baa81cfc2c11d07efba8929dc4db9e82 Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 22:52:08 -0700 Subject: [PATCH 183/184] chore: Add changelog for 0.6.1 (#2139) --- CHANGELOG.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37ead6119631..c131f1d28577 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,11 @@ # PRQL Changelog -## 0.6.1 โ€” [unreleased] +## 0.6.1 โ€” 2022-03-12 -**Features**: +0.6.1 is a small release containing an internal refactoring and improved +bindings for C, PHP & .NET. + +This release has 54 commits from 6 contributors. Selected changes: **Fixes**: @@ -14,7 +17,8 @@ **Documentation**: -**Web**: +- Add a policy for which bindings are supported / unsupported / nascent + (@max-sixty, #2062) **Integrations**: @@ -26,8 +30,6 @@ `web` & `bindings`, simplifying the repo's structure. There's also `grammars` & `packages` (@max-sixty, #2135, #2117, #2121). -**New Contributors**: - ## 0.6.0 โ€” 2022-03-08 0.6.0 introduces a rewritten parser, giving us the ability to dramatically From ef064e1a8c2de7e8340f7080169367f539e62a8c Mon Sep 17 00:00:00 2001 From: Maximilian Roos <5635139+max-sixty@users.noreply.github.com> Date: Sun, 12 Mar 2023 23:21:16 -0700 Subject: [PATCH 184/184] chore: Bump version to 0.6.1 (#2140) --- Cargo.lock | 20 ++++++++-------- Cargo.toml | 23 +++++++++++-------- bindings/prql-elixir/native/prql/Cargo.toml | 2 +- bindings/prql-js/Cargo.toml | 2 +- bindings/prql-js/package-lock.json | 4 ++-- bindings/prql-js/package.json | 2 +- prql-compiler/Cargo.toml | 2 +- prql-compiler/prql-compiler-macros/Cargo.toml | 2 +- prql-compiler/prqlc/Cargo.toml | 2 +- web/book/src/language-features/target.md | 2 +- web/playground/package-lock.json | 2 +- 11 files changed, 34 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf52072cab03..9ab3d5af3278 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -620,7 +620,7 @@ dependencies = [ [[package]] name = "compile-files" -version = "0.6.0" +version = "0.6.1" dependencies = [ "prql-compiler", ] @@ -1606,7 +1606,7 @@ dependencies = [ [[package]] name = "mdbook-prql" -version = "0.6.0" +version = "0.6.1" dependencies = [ "anyhow", "clap 4.1.6", @@ -2109,7 +2109,7 @@ dependencies = [ [[package]] name = "prql" -version = "0.6.0" +version = "0.6.1" dependencies = [ "prql-compiler", "rustler", @@ -2117,7 +2117,7 @@ dependencies = [ [[package]] name = "prql-compiler" -version = "0.6.0" +version = "0.6.1" dependencies = [ "anyhow", "ariadne", @@ -2148,7 +2148,7 @@ dependencies = [ [[package]] name = "prql-compiler-macros" -version = "0.6.0" +version = "0.6.1" dependencies = [ "prql-compiler", "syn", @@ -2156,7 +2156,7 @@ dependencies = [ [[package]] name = "prql-java" -version = "0.6.0" +version = "0.6.1" dependencies = [ "jni", "prql-compiler", @@ -2164,7 +2164,7 @@ dependencies = [ [[package]] name = "prql-js" -version = "0.6.0" +version = "0.6.1" dependencies = [ "console_error_panic_hook", "prql-compiler", @@ -2174,7 +2174,7 @@ dependencies = [ [[package]] name = "prql-lib" -version = "0.6.0" +version = "0.6.1" dependencies = [ "libc", "prql-compiler", @@ -2183,7 +2183,7 @@ dependencies = [ [[package]] name = "prql-python" -version = "0.6.0" +version = "0.6.1" dependencies = [ "insta", "prql-compiler", @@ -2193,7 +2193,7 @@ dependencies = [ [[package]] name = "prqlc" -version = "0.6.0" +version = "0.6.1" dependencies = [ "anyhow", "ariadne", diff --git a/Cargo.toml b/Cargo.toml index 0f937c56304b..30d13c22c079 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,15 +1,21 @@ [workspace] members = [ - "prql-compiler", - "prql-compiler/examples/compile-files", - "prql-compiler/prql-compiler-macros", - "prql-compiler/prqlc", + # The main crate + "prql-compiler", # + # The CLI + "prql-compiler/prqlc", # + # Macros + "prql-compiler/prql-compiler-macros", # + # An example + "prql-compiler/examples/compile-files", # + # Bindings + "bindings/prql-elixir/native/prql", "bindings/prql-java", - "bindings/prql-lib", "bindings/prql-js", - "bindings/prql-python", + "bindings/prql-lib", + "bindings/prql-python", # + # The book / docs "web/book", - "bindings/prql-elixir/native/prql", ] # Note we don't have a `default-members = ["prql-compiler"]`, since that causes # commands like `cargo test` to only run tests from the default package. And @@ -21,7 +27,7 @@ edition = "2021" license = "Apache-2.0" repository = "https://github.com/PRQL/prql" rust-version = "1.65.0" -version = "0.6.0" +version = "0.6.1" [profile.release.package.prql-js] # Tell `rust-js` to optimize for small code size. @@ -30,4 +36,3 @@ opt-level = "s" [workspace.metadata.release] allow-branch = ["*"] consolidate-commits = true -pre-release-commit-message = "chore: Release {{version}}" diff --git a/bindings/prql-elixir/native/prql/Cargo.toml b/bindings/prql-elixir/native/prql/Cargo.toml index 7eee02890463..76e536e96fe0 100644 --- a/bindings/prql-elixir/native/prql/Cargo.toml +++ b/bindings/prql-elixir/native/prql/Cargo.toml @@ -16,7 +16,7 @@ name = "prql" path = "src/lib.rs" [dependencies] -prql-compiler = {path = "../../../../prql-compiler", default-features = false, version = "0.6.0"} +prql-compiler = {path = "../../../../prql-compiler", default-features = false, version = "0.6.1" } # See Readme for details on Mac [target.'cfg(not(any(target_family="wasm", target_os = "macos")))'.dependencies] diff --git a/bindings/prql-js/Cargo.toml b/bindings/prql-js/Cargo.toml index bc44373f6ef0..b0c8cf259dbe 100644 --- a/bindings/prql-js/Cargo.toml +++ b/bindings/prql-js/Cargo.toml @@ -62,6 +62,6 @@ search = '(\s+"prql-js",)\n(\s+"version": )"[\d\.]+"' [[package.metadata.release.pre-release-replacements]] exactly = 1 -file = "../playground/package-lock.json" +file = "../../web/playground/package-lock.json" replace = '''$1"{{version}}"''' search = '( "../prql-js": \{\n "version": )"[\d\.]+"' diff --git a/bindings/prql-js/package-lock.json b/bindings/prql-js/package-lock.json index 7e5cbb4f9287..025d9190129d 100644 --- a/bindings/prql-js/package-lock.json +++ b/bindings/prql-js/package-lock.json @@ -1,12 +1,12 @@ { "name": "prql-js", - "version": "0.6.0", + "version": "0.6.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "prql-js", - "version": "0.6.0", + "version": "0.6.1", "license": "Apache-2.0", "devDependencies": { "chai": "^4.3.6", diff --git a/bindings/prql-js/package.json b/bindings/prql-js/package.json index 43876e7d3daf..b20e185bd64d 100644 --- a/bindings/prql-js/package.json +++ b/bindings/prql-js/package.json @@ -24,5 +24,5 @@ "test": "mocha tests" }, "types": "dist/node/prql_js.d.ts", - "version": "0.6.0" + "version": "0.6.1" } diff --git a/prql-compiler/Cargo.toml b/prql-compiler/Cargo.toml index b28ada516f55..5cea1a4342f8 100644 --- a/prql-compiler/Cargo.toml +++ b/prql-compiler/Cargo.toml @@ -61,6 +61,6 @@ name = "bench" # to `prql-compiler`? We can place it there when that's fixed. [[package.metadata.release.pre-release-replacements]] exactly = 1 -file = "../book/src/language-features/target.md" +file = "../web/book/src/language-features/target.md" replace = 'prql version:"{{version}}"' search = 'prql version:"[\d.]+"' diff --git a/prql-compiler/prql-compiler-macros/Cargo.toml b/prql-compiler/prql-compiler-macros/Cargo.toml index d80e788df0ae..b83c4ea33d55 100644 --- a/prql-compiler/prql-compiler-macros/Cargo.toml +++ b/prql-compiler/prql-compiler-macros/Cargo.toml @@ -14,7 +14,7 @@ proc_macro = true test = false [dependencies] -prql-compiler = {path = "..", default-features = false, version = "0.6.0" } +prql-compiler = {path = "..", default-features = false, version = "0.6.1" } # Was getting build errors with more recent versions; can remove pin if it # successfully builds. syn = "=1.0.107" diff --git a/prql-compiler/prqlc/Cargo.toml b/prql-compiler/prqlc/Cargo.toml index 522f9776aa84..e95f5a281877 100644 --- a/prql-compiler/prqlc/Cargo.toml +++ b/prql-compiler/prqlc/Cargo.toml @@ -19,7 +19,7 @@ env_logger = {version = "0.10.0", features = ["color"]} itertools = "0.10.3" minijinja = {version = "0.30.4", features = ["unstable_machinery"]} notify = "^5.1.0" -prql-compiler = {path = '..', version = "0.6.0" } +prql-compiler = {path = '..', version = "0.6.1" } regex = {version = "1.7.1", features = ["std", "unicode"]} serde = "^1" serde_json = "1.0.81" diff --git a/web/book/src/language-features/target.md b/web/book/src/language-features/target.md index aef5fc914274..9a7a87391457 100644 --- a/web/book/src/language-features/target.md +++ b/web/book/src/language-features/target.md @@ -48,7 +48,7 @@ very welcome. PRQL allows specifying a version of the language in the PRQL header, like: ```prql_no_fmt -prql version:"0.6.0" +prql version:"0.6.1" from employees ``` diff --git a/web/playground/package-lock.json b/web/playground/package-lock.json index 506ad981ccd1..890656b3512f 100644 --- a/web/playground/package-lock.json +++ b/web/playground/package-lock.json @@ -45,7 +45,7 @@ } }, "../prql-js": { - "version": "0.6.0", + "version": "0.6.1", "extraneous": true, "license": "Apache-2.0", "devDependencies": {