Show HN: PRQL in PostgreSQL
2 years ago (github.com)
This extension let's you write PRQL functions in PostgreSQL.
When I first saw PRQL on Hacker News a few months ago, I was immediately captivated by the idea, yet equally disappointed that there was no integration for PostgreSQL. Having previous experience with writing PostgreSQL extensions in C, I thought this was a great opportunity to try out the pgrx framework and decided to integrate PRQL with PostgreSQL myself.
The maintainers of both PRQL and pgrx were very nice to work with. Thanks guys.
Nice work. A few months back, I experimented with having a DSL like PRQL in Postgres, but back then, I found the language a bit cumbersome; however, it was great as an idea. IMHO, the best "data transformation" language is jq and awk is second.
PRQL and EdgeQL (EdgeDB) are the most interesting ones to watch how they evolve, though.
I've also written a PG extension to make jq available in Postgres [0]
I believe Postgres, in general, will flourish as a host for DSL languages [1].
0: https://github.com/Florents-Tselai/pgJQ 1: https://tselai.com/pgjq-dsl-database.html
Would love to see EdgeQL become adopted beyond EdgeDB. I don't like the vendor lock-in with EdgeDB, but I think they're doing great work
Yes, they are. Beyond the core database offering, I'd also like to underline the quality of their software engineering work. There are not many Python-powered databases out there; their codebase has some real gems from the setup.py to their core compiler and Postgres-based storage layer.
> Would love to see EdgeQL become adopted beyond EdgeDB
We'll soon be announcing some interesting developments on that front, stay tuned :)
All the best to the team. I however truly hope this isn't the direction the industry moves toward. I thought we learned our lesson from MongoDB. I still believe data is best modeled in sets, not objects.
The solution isn't for databases to become more like object stores but for general purpose programming languages to be more amenable to seamless access of set-oriented data.
More stuff like this:
https://github.com/porsager/postgres
https://github.com/launchbadge/sqlx
1 reply →
Damn, now my bachelor's thesis will be less unique :)
I'm working on a new language that compiles directly to Postgres' post-analysis structs. It's working out pretty well so far, but my chosen "universal set" (aggregation/array/subquery/... as one thing) semantics are sometimes a pain to encode.
Not to change your direction but something I've been toying around is being able to support Algebraic types when defining tables. That way you can offload a lot of the error checking to the database engine's type system and keep application code simpler.
I'd like to do something like that too, if/when I ever get to replacing the DDL. In Postgres you could create custom types for tagged unions, but it might be better to translate table-level unions to a set of constraints, for performance and flexibility (you can't create referential integrity constraints using expressions IIRC).
Sounds wonderful. I actually think this is the highest value thing anyone could contribute to Postgres (assuming it could handle foreign key constraints inside the sum types).
Sounds interesting! What's the benefit of compiling directly to Postgres's internal structs over compiling to SQL?
There's little direct benefit, since the internal structs pretty closely model SQL. But having the language compiler a part of the Postgres process does help. It gives you easy access to the database's structure, so you know the type of every identifier, what columns tables have, what functions are available, etc. You can then do your own (better) error reporting and, more importantly, move away from SQL's semantics.
For example, I want to have universal broadcasting of operators on subquery results, array values, and aggregated columns. To do this, I need to know which of these the operand expressions represent, which is slow or impossible with transpilation.
I’m very, very interested in stuff like this. I think SQL is a bad API to the capabilities of Postgres and I want to be able to speak to it directly.
Very interesting, it looks a lot like the Elixir package Ecto that has a DSL for writing SQL queries. Obviously there are some differences here and I wonder if the compiler can do further optimisations than Ecto can but interesting to see they align quite a bit.
Related:
PRQL as a DuckDB Extension - https://news.ycombinator.com/item?id=30060784 - Jan 2022 (292 comments)
Nice to see extensions like this one developed in Rust/pgrx. Reminds me of https://github.com/tcdi/plrust
Yes, the PL/Rust code base was a very useful when developing this extension
Off-topic: does anyone know of SQL-to-SQL optimisers or simplifiers? I understand that databases themselves have query-optimisers, and that's not what I'm talking about - I work with generated query systems and SQL macro systems that make fairly complex queries quite easy to generate, but often times come up with unnecessary joins/subqueries etc.
PostgreSQL's query-optimiser does handle these cases quite well for me once I explain and add the appropriate indexes, yet complex source queries carry undiscountable costs (longer planning times, missed optimisations e.g. predicate pushdowns).
I find myself needing to mechanically transform and simplify SQL every now and then, and it hardly seems something out of reach of automation, yet somehow I've never been able to find software that simplifies and transforms SQL source-to-source. When I look, I only find optimisers for SQL execution plans. It's a bit hard to believe that such a thing doesn't exist, given how significant the SQL ecosystem is.
You should make the first instance of “PQRL” in your readme a link to that project.
Good suggestion, thanks
It looks a lot like Microsoft’s Kusto query language which is a pleasure to use. Piping is better than nesting and from-first is the way to go as it’s necessary for autocomplete.
Just out of curiosity, did PRQL evolve from some theoretical innovation or did arise bottom up from practical utilities?
Is it a new tool with great new powers or is it just syntactic sugar?
it compiles to SQL so no extra powers. But it does make some common patterns more succinct. They have good documentation on the website.
Personally, I was very excited about using it to write some complex queries in my application that does some fancy backtesting with sliding windows etc, but I reverted back to SQL pretty quickly because I found myself first thinking in SQL and translating back to PRQL :/
Yep, just syntactic sugar.
I often wonder if NL-SQL tasks would benefit from an intermediate query language that is more compatible with the next-logical token approach that is used to generate the code. Obviously there is less of this in the training set, but if it transpires in a testable way, you could generate training data yourself from known good sql queries? Are there any languages that have been designed specifically for this?
There are very interesting improvements to SQL, which are much more ergonomic, extend functionality, and provide higher-level abstractions. Also backward compatible. PRQL and Malloy immediately come to mind but there are more. Anybody has good explanations why they struggle to get wide adoption?
When it comes to data stack tooling, organizations aren't always optimizing for a better way to do things as much as minimizing the worst possible scenario.
New syntax is nice, but it means that analysts and engineers need to learn something new and are more likely to make mistakes that could bubble up to production. There's always an argument to be made why shiny new tool XYZ is better, but unless it's 100X better, organizations are reluctant to switch from something like vanilla PostgreSQL that they know works 100% of the time.
Normally I would agree, except for the fact that this system works by converting PRQL to SQL. So it's not 100% throwing out the baby with the bath water, since there there are still means for newer engineers to learn SQL through this tooling!
PRQL looks interesting enough to at least give it an honest try.
> PRQL allows for powerful autocomplete, type-checking, and helpful error messages (in progress)
Without some kind of autocomplete though I'm a lot less motivated to do so.
Why is this PRQL extension for Postgres limited to Mac and Linux? What dependencies on Windows are the obstacles, and is there an expected solution in the near-term?
This extension has been developed on top of pgrx and depends on the platforms that pgrx supports. From the pgrx readme:
> Windows is not supported. It could be, but will require a bit of work with cargo-pgrx and figuring out how to compile pgrx's "cshim" static library.
Is PRQL faster than the standard query model?
PRQL compiles to SQL. Why would it be faster?
The intention is rather for it to be simpler, as it uses a linear direction of data handling. SQL jumps back and forth with its order of operations and can be confusing in this way.
PRQL also has a more modern syntax that reuses more universal concepts with fewer keywords to learn. In contrast to SQL which has a unique keyword, syntax, and behavior for everything.
I think more relevant question would be is naive idiomatic prql faster than naive idiomatic sql? Of course you can tune any sql to hell and back, but the chances for some non-expert developer to land on anything nearly optimal sql are not so great. So if prql helps non-experts to get decent perf easier, I'd chalk that up as a win, and that is not so outlandish goal anymore.
1 reply →
Can this be used inside Grafana?
Can someone explain to me why “Show HN” and “Ask HN” posts are always, always in hard-to-read light gray? Is there some cabal that automatically downvotes such posts? Is there something intrinsic to The Algorithm that penalizes such posts? Or do I just have really bad luck and always manage to click through on posts that have gained traction despite having gotten enough downvotes to put them at risk of sudden termination?
This is one of the great HN mysteries to me, and if anyone can shed some light on it, it would be much appreciated.
I think I read here on HN some time ago that it is intentionally hard to read to discourage posts with text. I think the reasoning was that posting links to external blogs / websites is usually higher quality than someone creating a quick post on HN.
Could be wrong though, just writing this from memory.
HN has some really non-obvious UX, between this and the mysterious green usernames I still don't understand. And the fact that only some users can downvote. Or the weird logic behind which words cannot appear in titles.
5 replies →
They are not penalized, the grey text applies to all text posts.
It's confusing, but greying out is used on HN for a single purpose: to discourage reading (and therefore writing).
Low-quality comments are greyed by downvotes from other users and moderators.
Text posts (including Ask and Show HN) are greyed automatically.
Ask/Show posters are encouraged to post a comment on their own story, and to let that comment rise or fall according to its up/down votes.
Meta-meta: Your comment might be downvoted for being meta to the post. It looks like it has already been "detached" from the comment tree so that it appears at the bottom instead of responding to up/downvotes. This is actually protective of your karma and this conversation. Your question is valid, but it's not germane to the post. If your comment was allowed to float to its normal location, it would be downvoted by others who considered it off-topic.
They aren’t downvoted; it’s just a styling thing. I believe dang gave some reasoning for deliberately making the post text less prominent, but I can’t remember it.
I don't understand the need for libraries that abstract away SQL when you could just write SQL directly and have full access to the power of the language which is quite rich (recursive CTE, windowing, ... aka Modern SQL). You could also use stored procedures/functions for more complex stuff and e.g. JSON (or native types) to transfer data between the database and the application. Why limit ourselves with a sub-optimal language be it PRQL, Ecto, other ORMs, ... ?
This comes up every time PRQL makes it onto HackerNews and is a fair question:
Short answer: DX
Slightly longer answer: Developer productivity and experience, especially for EDA and interactively writing complex analytical queries.
Most people that have tried PRQL just find it more convenient to write their analytical queries in it. PRQL compiles to SQL so it can't express anything you can't already do in SQL, but you can probably express yourself much faster in PRQL.
Just try the following query in the online PRQL Playground (https://prql-lang.org/playground/) to find the longest track per album:
```prql
from tracks
group album_id (
```
How long would it take you to write the SQL for that?
Disclaimer: I'm a PRQL contributor.
Reformatted for readability (indent code blocks with two spaces):
Editorializing:
Data query specification is all about getting the details right. This does not look simpler than the corresponding SQL to me though. All components must be present -- scope, group, limit, order.
SQL, for all its faults, is generally succinct at incorporating the required details. The PRQL sample here is succinct as well, but to me at least, not differentiating.
> How long would it take you to write the SQL for that?
I don't want to appear rude, but unless I'm missing something, this is a pretty simple SQL query, of the kind anyone with mimimal SQL experience could write off the top of their head in seconds.
I like the idea of PRQL, but I think a better example is needed to sell it.
13 replies →
This seems like a micro-optimization to me. That's faster to write, but you pay for that with extra tooling and an abstraction layer that you now have to train or hire for, and I'm not sure that's a good payoff.
This idea seems like it'd be better as an editor plugin that lets you write shorthand and have it automatically expanded into correct SQL rather than as a build time thing.
2 replies →
> How long would it take you to write the SQL for that?
10 replies →
select id from tracks qualify row_number() over partition by (album_id order by milliseconds desc) =1
That should work
Look I’m a diehard SQL just use it guy but open to improvements. But I’m loathe to use abstractions for things when the underlying thing is so expressive.
Autocomplete of fields in a good editor, schema help, etc go a long way to making SQL being written raw very nice.
5 replies →
In the real world, probably something like:
I agree the PRQL's pretty nice here, but I think such a generalised example (chances you actually want to `select *`?) overstates the advantage.
2 replies →
They can ask chatgpt to generate the SQL query and use the SQL output that everyone is familiar with rather than use an abstraction that is prone to versioning and behavioral changes and will consume everyone else's time to go learn a new language and become profficient in it.
1 reply →
I have a feeling this language will be more familiar to programmers who think functionally. I say this because it seems to consist of transformations applied to data and of `derive`, which defines new variables later used in other transformations.
This would have been awesome for me 2 years ago.
Currently much of my complicated SQL is generated by a LLM.
3 replies →
Sorry to be that guy :-) The `introduction.prql` example on the playground gives an idea of the better readability of PRQL vs SQL and your small example an idea of the speed you may gain from writing PRQL vs SQL. It is interesting. Indeed, me writing the SQL would have taken more time than you writing the PRQL.
Won't this just lead to developers wrecking performance because they don't understand what's happening?
The thing I hate most about SQL is lack of composability.
In most languages it's easy to pull out functions.
In SQL you end up with a giant hard to comprehend mess.
I think the underlying relational concepts in SQL are sound but I'd love to see ideas like PRQL that aim make SQL easier to write and maintain.
Stored procedures and functions are nice but don't allow the basic idea of breaking a large query apart into smaller logical components.
Your statement about breaking large queries apart is wrong. You can write queries with CTES to improve readability, and extract CTEs into functions that can be selected as queries get too large and unwieldly. SQL is just as composable as any other language.
The thing that's lacking right now is the tooling for managing/testing/deploying database code. There are solutions out there and the supabase folks have been working to make things better but database first development still has some hurdles in terms of DX.
14 replies →
Composition is available in sql, but works a bit different than in a procedural language. In sql you express sets of data, composition consists of defining subsets that you compose into more complex sets. Views and CTEs are the tools for composition in SQL.
SQL is incompatible with many types of autocompletion. For example columns in a select statement are not known here you write FROM. This alone justifies PRQL in my opinion.
There are tools in most languages to deal with this. For example, take https://jawj.github.io/zapatos/. It introspects your database schema to generate types, and gives you autocompletion inside tagged template strings.
It's not a real problem in a practical sense. Yes, you have to write the FROM clause before autocomplete happens even though the SELECT must appear before it. Fortunately, however, text editiors used as IDEs allow for out-of-sequence code editing. You can just enter the FROM and move back to complete the SELECT.
It's like complaining that you have to know the variable name you're going to assign something to before you start writing the expression that will set the value.
The idea is to evaluate the expression and store it, but the expression doesn't actually read that way left-to-right. Wouldn't it make more sense for it to be:
Technically, that's written more in execution order. In practice it just isn't that big of a deal. It only trips up beginners.
Jetbrains tools (Datagrip, IntelliJ IDEA, PyCharm) deal well with this if you leave a placeholder column before FROM, and write the FROM part with proper joins. You can go back to the columns and autocomplete goes just fine. You can amend our extended any part and the autocomplete logic adapts well.
One notable reason is being database-agnostic. Like ORM's, if you can generate SQL you can generate database-specific SQL as well.
SQL is also quite verbose in places (JOINs are the most trivial example), and lack a decent amount of abstraction (CTEs are relatively low level).
Updating a large set of FK'd tables can be a nightmare (this is what ORMs shine at).
Finally, some modern additions are quite unreadable, Postgres' JSON syntax, for example.
I'm not saying that PRQL solves any of the above, but these are all legit problems with "plain" SQL.
Database agnosticism is so 2010. There's very little reason to choose a DB other than postgres, and if you have a reason to choose a specific niche db you're not probably not going to be migrating away from it any time soon.
CTEs are a first step in structuring queries to make them decomposable. You can extract CTEs to functions and mark them stable and it's logically equivalent to the original query.
8 replies →
How are joins verbose? It’s pretty straight to the point: combine these 2 tables on these columns… what do you want to remove to make it less verbose?
PRQL is not an ORM in any kind of way, it’s the less quirky SQL, basically.
In my opinion SQL is the sub-optimal language.
Whenever I am writing SQL I am not thinking in SQL, but I am thinking in what I consider to be the mathematical sound way, which I translate into SQL while writing. I consider thinking in SQL a much greater mental handicap than having to translate mentally into it.
I would prefer to write directly in what I would consider as a good query language and have it translated automatically into SQL, for compatibility with what is, for unfortunate historical reasons, the standard.
I have not attempted previously to do or use something like this, but work like that discussed here seems like a step in the right direction.
Can you expand on this? I have always seen SQL as a DSL for set theory. How are you seeing things "mathematically" that do not comport with set manipulation in SQL?
SQL is pretty great, but for some things (I thought the example in the readme was decent) it can be quite cumbersome. Stored procedures are very imperative (and hard to debug, depending on the platform IME). This seems like a more functional approach to stored procedures.
I don't think it's suggested that this replaces SQL. Use the right tool (and abstraction) for the job?
I think the debuggability is the #1 issue with database-as-a-platform. Using notices to debug functions is such a poor workflow that even though I'm bullish on putting stuff in PG I avoid writing complex code might need to be debugged as an integrated unit.
Maybe. I already think in terms of transformations (relational algebra and its closure property) when I write SQL and use a lot of CTEs. But I guess the functional way might help people see what's going on.
> Why limit ourselves with a sub-optimal language be it PRQL?
Actually why limit yourself with SQL...?
PRQL is a language compiled into SQL and makes certain hard-to-do things in SQL easy purely because it allows to streamline operations which SQL needs CTE joins or whatever hoop jumping to solve.
My favorite example which sounds easy but isn't - select the row which is MAX(...).
> Actually why limit yourself with SQL...?
Because it's everywhere, has extensive documentation and tutorials, all database tools support it, all relational engines support it, some non-relational engines support it, all programming languages have library support for it, it can be accessed through command line tools as well as graphical interfaces, etc.
You think an industry is going to give up 50 years of infrastructure because some (typically junior) devs think the syntax is "kinda icky"?
> My favorite example which sound easy but isn't - select the row which is MAX(...).
If you look earlier in the comments you will see queries that have "DISTINCT ON" in them. It solves the problem that sounds easy, but actually is pretty easy if you know SQL.
2 replies →
Because SQL can be cumbersome to write. It's often repetitive, requires nesting, aliases, and a specific order of statements.
1. Notice language is complicated for some tasks
2. Propose newer, simpler language to take care of these
3. Newer, simpler language lacks features of original language
4. Newer language adds features, making it more complicated
5. GOTO 1
2 replies →