Comment by krick
7 years ago
I wholeheartedly agree with the "complaining" part of the post, but then here comes the "solution" and I'm not quite sold.
I mean, I don't necessarily claim that this is not a solution, it just isn't obvious to me at all. Maybe a more extensive explanation with better examples would make it all clear to me and I'd be super-hyped about it already, but right now I'm more like confused.
First off, it would be helpful show the table structure in the examples, and then compare EdgeQL query to the easiest solution in the SQL. After all, the readers supposedly use SQL almost daily for many years (I know I do), but don't know a thing about EdgeQL, so if it can do everything SQL can, but easier, such a comparison must make it pretty obvious.
TBH, my knowledge of the relational algebra is quite rusty by now, so maybe that's the problem, but as I remember, many queries we commonly use with the SQL are not really "relational" queries. Relational algebra deals with the sets of tuples, so things like count(*) or ORDER BY, or GROUP BY are not really a part of relational model, they just exist because they are super-helpful in what we usually are trying to achieve with SQL.
The problems with NULL are of a similar nature. I don't think we should pretend that NULL not being equal NULL is not useful (we don't expect "missing data" to be exactly the same value as another "missing data", do we?), and SELECT DISTINCT treating them as equals is not intuitive (for me it absolutely is: when I'm asking what values occur in a table, a missing entry is a missing entry to me, I don't want to see NULL 10000 times).
So, the introduction kind of made me to expect the solution to be more in compliance with relational concepts, but it doesn't seem to be, since all of the above are present in the EdgeQL in one form or another.
I'm not sure how {} is different from NULL in the EdgeQL, since {} seems to be kind of special thing here, the same as NULL is in the SQL. I mean, it doesn't behave like a true empty set at all! Non-empty set {value} OR {} = {value}, not {} (OR ≡ ∪). <bool>{} being {} instead of a true boolean value looks even more confusing to me than NULL OR (NOT NULL) = NULL. Same ternary algebra here.
Then, I don't really understand a concept of a flat set here. I do kind of understand what we are trying to achieve here: we want to solve the problem of SELECT x, (SELECT y) FROM z throwing an error in a runtime, if count(SELECT y) != 1. And it kind of would make sense in SQL, but it's explicitly advertised as a feature of EdgeQL that it can return trees (json-like structures), and here it doesn't seem to make sense that an output of a query (which is a "flat set", I guess?) cannot have another set as an element. Moreover, it obviusly can be ordered, which also isn't a property of how "set" is commonly defined in the set theory.
As a first impression, syntax and overall structure of the queries doesn't strike me as obvious as well. In fact, since
> SQL does not integrate well enough with application languages and protocols
I would ultimately hope for something that can be expressed as a number of function calls and commonly used data structures (a list, a dictionary/record, etc.) in most/any mainstream PLs, not a one more DSL as in "free form text". (Maybe with a more succinct DSL for the use in a console. Maybe.)
And my ultimate source of confusion. SQL is more or less the same thing even in these DBMS where it isn't exactly The SQL (like ClickHouse). And given I know the overall structure of the DBMS (like, is it, for instance, row-based or column-based?) I can make pretty good assumptions of performance of a given query, even though SQL is still declarative and I do not know what exactly the query-optimizer will do. Maybe it's just that I'm not used to it, but I don't have a feel about how performant would be the last EdgeQL example of the article, and if it would be better to separate it into several queries at some scale. In fact, I don't even understand if it's something that would be reasonable easy to implement in other major RDBMS', or is it ultimately EdgeDB-only feature? If so, it can be only as good as EdgeDB — and is it as good as PosgreSQL, or MariaDB, or sqlite? Unfortunately, in the real world I have to worry more about how performant and robust a thing is under load, than I can worry about programming convenience.
> {value} OR {} = {value}, not {} (OR ≡ ∪), <bool>{} being {} instead of a true boolean value
This is because we define infix OR as
{a OR b | ∀ (a, b) ∈ (A x B)}
Same goes for the cast function.
You may argue that this is confusing, but if you think about everything as a set comprehension, it is way more consistent. For example the `CASE WHEN` example from the post would always return `{}` for empty input, making it obvious.
> but it's explicitly advertised as a feature of EdgeQL that it can return trees (json-like structures)
The tree-like return is not an aspect of a language system, it's a matter of output representation. For example:
still returns a flat set of User objects. The shape selector `{ ... }` is an annotation that defines how an object is serialized in the output.
> I would ultimately hope for something that can be expressed as a number of function calls and commonly used data structures
This is exactly where we are going. Orthogonality in the underlying language makes it much easier to achieve this.
> and is it as good as PosgreSQL, or MariaDB, or sqlite?
EdgeDB is based on Postgres, we actually transpile EdgeQL to SQL. EXPLAIN and query performance analysis are being worked on.
> in the real world I have to worry more about how performant and robust a thing is under load, than I can worry about programming convenience.
We have posted some benchmarks [1], and more are coming.
[1] https://edgedb.com/blog/edgedb-1-0-alpha-1/