-
-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support real life SQL #21
Comments
I think if we find a generic and composable way to represent each SQL feature it will be possible to create large and complex query. So, I’ll put it here some thoughts about some of the “special” features you used on your example. Not all at once. And please comment every one you’d like to! |
I don’t know if it is possible but the way I think to do something like this WITH RECURSIVE t(n) AS (
VALUES (1)
UNION ALL
SELECT n+1 FROM t WHERE n < 100
)
SELECT sum(n) FROM t; Is with something like this (Red.select({ 1 }), * + 1 ... * < 100).sum |
WITH RECURSIVE included_parts(sub_part, part, quantity) AS (
SELECT sub_part, part, quantity FROM parts WHERE part = 'our_product'
UNION ALL
SELECT p.sub_part, p.part, p.quantity
FROM included_parts pr, parts p
WHERE p.part = pr.sub_part
)
SELECT sub_part, SUM(quantity) as total_quantity
FROM included_parts
GROUP BY sub_part I know, it’s not complete... and I don’t know if it is possible (yet). But the way I’m thinking of taking is something like: (IncludedParts.where({ .part eq “our_product” }), { .^where: .part == IncludedParts.sub-part } ... *).classify: *.sub-part, :reduce-field{ .quantity.sum } |
I was thinking about that and Im starting to disagree... |
Having recently spent a week fighting hand and fist against SQLAlchemy to get it to just produce a union query with selects from subqueries with aggregate and window functions, that took me ten minutes to actually write by hand. You want to be able to go from SQL into language syntax thats like SQL, as well as language syntax thats idiomatic to whatever crazy rendered SQL that can get the job done. Personally I am a fan of the escape hatch abstraction. Something that's very thinly abstracting the SQL so you avoid vendor lock in, but close enough I can translate almost directly. Might not have to be related to the ORM really, just work relatively nicely with SQL generation in concert with the ORM. So perhaps a subquery is from an ORM expression, the other is some vendor specific directly optimised by hand query close to raw SQL, and the two are nicely combined to be rendered together with a parent query like object referencing either as if it was more ORM like. |
I think Red is tracking a way to transform perl6 code to SQL, something like:https://github.com/FCO/Red/wiki/Better-map-grep and https://gist.github.com/FCO/87831dd190e1bb12adb138ce866acb73 |
A lesson taught by all existing attempts at creating ORMs (in any language) but one that has yet to be learned is that while most SQL statements are rather simple, there will be use cases that require some real SQL mastery and if the ORM does not allow for the latter, it's value is greatly diminished.
It seems like every ORM starts out with the simple stuff. How can we make fetching one row from a table simple? How do we allow for boolean expressions in the where clause? Let's make joining simple tables by id key trivial.
These (and a couple more) are the things that ORMs make really simple but then real users come along and ask for more and more complicated things which then get bolted on top of the simple mechanisms. And suddenly you reach the point, where writing the SQL query is the easy part, but getting your ORM to generate that query starts getting really hard or downright impossible. Then you end up with an application that's a crude mixture of ORM code and hand crafted SQL statements combining the disadvantages of both.
The conclusion is that for the API design one should start with the absolute worst and most complicated SQL statement imaginable and find an API that allows one to express this. This statement should at least contain:
I'm sure there are a couple more interesting aspects of SQL, but this should get you started. They are all features that are in use in our code base. The trick will be to make these possible while keeping the trivial cases simple.
To finish, here's an example of a real life query from our production code that DBIx::Class is completely unequipped to handle:
The text was updated successfully, but these errors were encountered: