{"id":26426317,"url":"https://github.com/prql/dbt-prql","last_synced_at":"2025-04-09T05:12:40.753Z","repository":{"id":39639981,"uuid":"497688675","full_name":"PRQL/dbt-prql","owner":"PRQL","description":"dbt-prql allows writing PRQL in dbt models","archived":false,"fork":false,"pushed_at":"2025-03-31T17:51:43.000Z","size":136,"stargazers_count":104,"open_issues_count":2,"forks_count":4,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-02T04:05:16.296Z","etag":null,"topics":["dbt","prql","sql"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PRQL.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-29T19:24:30.000Z","updated_at":"2025-03-31T17:51:46.000Z","dependencies_parsed_at":"2023-01-29T20:45:47.871Z","dependency_job_id":"82b035d4-b19e-4488-affb-78fa0b7932d8","html_url":"https://github.com/PRQL/dbt-prql","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRQL%2Fdbt-prql","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRQL%2Fdbt-prql/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRQL%2Fdbt-prql/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PRQL%2Fdbt-prql/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PRQL","download_url":"https://codeload.github.com/PRQL/dbt-prql/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247980844,"owners_count":21027808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dbt","prql","sql"],"created_at":"2025-03-18T03:29:35.451Z","updated_at":"2025-04-09T05:12:40.736Z","avatar_url":"https://github.com/PRQL.png","language":"Python","readme":"# dbt-prql\n\n\u003e **Note**\n\u003e As of Feb 2023, we're again considering how to best integrate with dbt\n\u003e more closely. Ideally a file with a `.prql`\n\u003e extension will just work™.\n\u003e\n\u003e If you're interested in this, subscribe or 👍 to\n\u003e \u003chttps://github.com/dbt-labs/dbt-core/pull/5982\u003e.\n\u003e\n\u003e The original plugin is hosted here, but only works\n\u003e with a minority of dialects, and isn't a focus of development at the moment.\n\ndbt-prql allows writing PRQL in [dbt](https://www.getdbt.com/) models. This\ncombines the benefits of PRQL's power \u0026 simplicity _within_ queries, with dbt's\nversion control, lineage \u0026 testing _across_ queries.\n\nOnce `dbt-prql` in installed, dbt commands compile PRQL between `{% prql %}` \u0026\n`{% endprql %}` jinja tags to SQL as part of dbt's compilation. No additional\nconfig is required.\n\n## Examples\n\n### Simple example\n\n```elm\n{% prql %}\nfrom employees\nfilter (age | in 20..30)\n{% endprql %}\n```\n\n...would appear to dbt as:\n\n```sql\nSELECT\n  employees.*\nFROM\n  employees\nWHERE\n  age BETWEEN 20\n  AND 30\n```\n\n### Less simple example\n\n```elm\n{% prql %}\nfrom in_process = {{ source('salesforce', 'in_process') }}\nderive expected_sales = probability * value\njoin {{ ref('team', 'team_sales') }} [name]\ngroup name (\n  aggregate (sum expected_sales)\n)\n{% endprql %}\n```\n\n...would appear to dbt as:\n\n```sql\nSELECT\n  name,\n  sum(in_process.probability * in_process.value) AS expected_sales\nFROM\n  {{ source('salesforce', 'in_process') }} AS in_process\n  JOIN {{ ref('team', 'team_sales') }} USING(name)\nGROUP BY\n  name\n```\n\n...and then dbt will compile the `source` and `ref`s to a full SQL query.\n\n### Replacing macros\n\ndbt's use of macros has saved many of us many lines of code, and even saved some\npeople some time. But imperatively programming text generation with code like\n`if not loop.last` is not our highest calling. It's the \"necessary\" part rather\nthan beautiful part of dbt.\n\nHere's the canonical example of macros in the [dbt\ndocumentation](https://docs.getdbt.com/tutorial/learning-more/using-jinja):\n\n```sql\n{%- set payment_methods = [\"bank_transfer\", \"credit_card\", \"gift_card\"] -%}\n\nselect\norder_id,\n{%- for payment_method in payment_methods %}\nsum(case when payment_method = '{{payment_method}}' then amount end) as {{payment_method}}_amount\n{%- if not loop.last %},{% endif -%}\n{% endfor %}\nfrom {{ ref('raw_payments') }}\ngroup by 1\n```\n\nHere's that model using PRQL[^1], including the prql jinja tags.\n\n```elm\n{% prql %}\nfunc filter_amount method -\u003e s\"sum(case when payment_method = '{method}' then amount end) as {method}_amount\"\n\nfrom {{ ref('raw_payments') }}\ngroup order_id (\n  aggregate [\n    filter_amount bank_transfer,\n    filter_amount credit_card,\n    filter_amount gift_card,\n  ]\n)\n{% endprql %}\n```\n\nAs well the query being simpler in its final form, writing in PRQL also gives us\nlive feedback around any errors, on every keystroke. Though there's much more to\ncome, check out the current version on [PRQL\nPlayground](https://prql-lang.org/playground/).\n\n[^1]:\n    Note that when \u003chttps://github.com/prql/prql/issues/82\u003e is implemented, we\n    can dispense with the s-string, and optionally dispense with the function.\n\n    ```elm\n    from {{ ref('raw_payments') }}\n    group order_id (\n      aggregate [\n        bank_transfer_amount = amount | filter payment_method == 'bank'        | sum,\n        credit_card_amount = amount   | filter payment_method == 'credit_card' | sum,\n        gift_amount = amount          | filter payment_method == 'gift_card'   | sum,\n      ]\n    )\n    ```\n\n    or\n\n    ```elm\n    func filter_amount method -\u003e amount | filter payment_method == method | sum\n\n    from {{ ref('raw_payments') }}\n    group order_id (\n      aggregate [\n        bank_transfer_amount = filter_amount 'bank'\n        credit_card_amount   = filter_amount 'credit_card'\n        gift_amount          = filter_amount 'gift_card'\n      ]\n    )\n    ```\n\n## What it does\n\nWhen dbt compiles models to SQL queries:\n\n- Any text in a dbt model between `{% prql %}` and `{% endprql %}` tags is\n  compiled from PRQL to SQL before being passed to dbt.\n- The PRQL complier passes text that's containing `{{` \u0026 `}}` through to dbt\n  without modification, which allows us to embed jinja expressions in PRQL.\n  (This was added to PRQL specifically for this use-case.)\n- dbt will then compile the resulting model into its final form of raw SQL, and\n  dispatch it to the database, as per usual.\n\nThere's no config needed in the dbt project; this works automatically on any dbt\ncommand (e.g. `dbt run`) assuming `dbt-prql` is installed.\n\n## Installation\n\n```sh\npip install dbt-prql\n```\n\n## Current state\n\nCurrently this is new, but fairly feature-complete. It's enthusiastically\nsupported — if there are any problems, please open an issue.\n\n## How does it work?\n\nIt's some dark magic, unfortunately.\n\ndbt doesn't allow adding behavior beyond the database adapters (e.g.\n`dbt-bigquery`) or jinja-only plugins (e.g. `dbt-utils`). So this library hacks\nthe python import system to monkeypatch dbt's jinja environment with an\nadditional jinja extension on python's startup[^2].\n\n[^2]:\n    Thanks to\n    [mtkennerly/poetry-dynamic-versioning](https://github.com/mtkennerly/poetry-dynamic-versioning)\n    for the technique.\n\nThis approach was discussed with the dbt team\n[here](https://github.com/prql/prql/issues/375) and\n[here](https://github.com/prql/prql/issues/13).\n\nThis isn't stable between dbt versions, since it relies on internal dbt APIs.\nThe technique is also normatively bad — it runs a few lines of code every time\nthe python interpreter starts — whose errors could lead to very confusing bugs\nbeyond the domain of the problem (though in the case of this library, it's small\nand well-constructed™).\n\nIf there's ever any concern that the library might be causing a problem, just\nset an environment variable `DBT_PRQL_DISABLE=1`, and this library won't\nmonkeypatch anything. It's also fully uninstallable with `pip uninstall\ndbt-prql`.\n\n## Roadmap\n\nOpen to ideas; at the moment it's fairly feature-complete. If we were\nunconstrained in dbt functionality:\n\n- If dbt allowed for external plugins, we'd enthusiastically move to that.\n- We'd love to have this work on `.prql` files without the `{% prql %}` tags;\n  but with the current approach that would require quite invasive\n  monkeypatching.\n- If we could add the dialect in automatically (i.e. `prql dialect:snowflake`),\n  that would save a line per model.\n- If we could upstream this into dbt-core, that would be awesome. It may be on\n  PRQL to demonstrate its staying power before that, though.\n\nWe may move this library to the \u003chttps://github.com/prql/PyPrql\u003e or\n\u003chttps://github.com/prql/prql\u003e repos. We'd prefer to keep it as its own package\ngiven the hackery above, but there's no need for it to be its own repo.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprql%2Fdbt-prql","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprql%2Fdbt-prql","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprql%2Fdbt-prql/lists"}