Placeholder as ORDER BY expression
(1.1) By klaus (triendl.kj) on 2022-03-15 17:21:33 edited from 1.0 [link] [source]
In one of SQLite ORM's channels we are discussing about placeholders in ORDER-BY expressions, and to what extent we should prohibit placeholders just because they don't seem to make sense.
Consider e.g.
select 42 order by ?1
No matter which value will be bound to parameter ?1
the result set will always be unsorted.
Of course there are more complex and more useful ORDER-BY expressions, however the question remains why SQLite allows such parameterized statements:
- by design.
- oversight.
- the principle of "be liberal in what you accept" as described in the quirks section.
- something not worth the effort to rule out.
Thanks for any hints!
(2) By Larry Brasfield (larrybr) on 2022-03-15 17:37:49 in reply to 1.0 [link] [source]
SQLite allows such because that last token is where an expression might be found in the syntax and, logically, an expression can be a single literal which may be expressed as a to-be-bound-later parameter. It would take more code and execution time to disallow the construct than to simply allow it as a legal instance of the language (which it is.) So, your alternative 4 is the answer.
This does raise an interesting issue though. It is a feature (or quirk) of SQL that an ORDER BY expression can be a simple integer greater than 0, in which case it can specify a result column rather than simply providing a value. One might imagine that by binding different integers to a parameter in the ORDER BY expression list that it would be possible to select different columns for the ordering. But it is not. Should it be?
(3) By David Jones (vman59) on 2022-03-15 18:13:34 in reply to 2 [link] [source]
I think it is a quirk that a natural number will be treated as a column index when used as the expression in an ORDER BY clause. Specifying a number n for a result column returns n for the value, not the value of the nth column.
(5) By Keith Medcalf (kmedcalf) on 2022-03-15 18:47:18 in reply to 3 [link] [source]
To the contrary I believe that the ability to specify projection order via positional indicators in the order-by clause referencing the projection result was part of the original language specification way back in the begininning of time, and that the "design by committee" standard merely kept what was, by the time the committee did anything, already a "standard feature" of the language. Positional indication in group-by is an addition (though whether by committee or as a non-standard extension) that is uncommon.
In either case, if a parameter in the order-by clause can be used as a positional indicator in the projection result, then the same logic should also apply to parameters specified in the group-by clause in order to prevent "surprise".
(4) By Keith Medcalf (kmedcalf) on 2022-03-15 18:27:40 in reply to 2 [link] [source]
One might imagine that by binding different integers to a parameter in the ORDER BY expression list that it would be possible to select different columns for the ordering. But it is not. Should it be?
That would be reasonable, but is not the standard (I do not believe). As you say, a parameter binding into the order clause is permitted, although it is not useful to do so.
Permitting that would be a non-standard extension to the language.
Quite similarly it is possible to request that the sqare root of a negative number be computed, although there is no capability to return a result (no SQL implemetations of which I am aware handle imaginary numbers -- they are confined to real numbers).
That is to say that just because something is possible, does not mean that it will work as intended. There is presently no intention anywhere in the SQL standard that a "parameter" can be used to represent anything other than a value.
I can see where it may be advantageous to permit a bound integer in the order by clause to represent a projection-position ordering, but that would not be portable anywhere else.
I can also see where it would be very useful, for example in queries used to populate a UI, so that the order-by of the projection can be altered without having to "generate" the SQL statement. (That is, the query would be unchanged except for the parameters specifying the key and ordering, whereas without such an ability the SQL query itself would have to be regenerated and prepared each time).
(7) By Gunter Hick (gunter_hick) on 2022-03-16 06:15:31 in reply to 2 [link] [source]
Please note that parameters may be rebound between calls to sqlite3_step. If binding a number were to impose ordering by the corresponding column, what do you propose rebinding a different number (maybe even exceeding the count of returned columns, or rebinding with something else) should do?
(8) By Larry Brasfield (larrybr) on 2022-03-16 06:38:25 in reply to 7 [link] [source]
I think that modifying sort ordering criteria in the middle of any sorted result producing sequence is nonsensical. For that reason, I also think that using a bindable parameter as a whole expression in the comma-separated ORDER BY (or GROUP BY) list is nonsensical. IMO, such SQL should be accepted, but the term treated as a constant during query and not able to index into the result columnsa, and thereby ignored.
My question, "Should it be?", was rhetorical and intended to bring out the folly of using such constructs. Should they be "disallowed"? Maybe, if there was ever a sophisticated (non-Lite) warning system, they would draw a "Tsk, tsk", just as "SELECT NULL LIMIT 0" would.
a. Disallowing such a parameter to index into the columns is a practical requirement. It avoids a host of messy problems.
(10) By Keith Medcalf (kmedcalf) on 2022-03-16 17:15:46 in reply to 7 [link] [source]
Probably exactly the same thing as would happen if you did that for any bound parameter: explode. The parameters are supposed to be held invariant during statement execution so this straw-man would have the same result as it presently does: the heat death of the multiverse.
(6) By Gunter Hick (gunter_hick) on 2022-03-16 06:11:12 in reply to 1.1 [source]
That is just a fancy way of expressing ORDER BY <constant> which, as correctly stated, presents the result set in generation order. Note that ?1 is the name of a variable and not a plain ordinal number aka output column reference.
(9.1) By klaus (triendl.kj) on 2022-03-16 13:12:03 edited from 9.0 in reply to 6 [link] [source]
Yes, I am aware that it's not a positional ordinal but a variable name.
Larry, Gunter, thanks for the plain text :)
Since it's a "fancy" way of expressing ORDER BY <constant>, but doesn't do anything useful (except perhaps play tricks with SQLite's optimizer?), it might make sense to forbid such simple "bindable" expressions at a language projection level (SQLite ORM is a C++ library). This is fairly cheap as it can be checked at compile time of the program itself rather than at SQLite parsing of the statement.
If you were using a library that is able to check expressions up front would you be happy if the library warns or disallows it? I don't want to start a discussion about library design, I just want to get some expert opinions or preferences.
To give you some context (C++ code):
int n = 5;
select(&User::name, from<User>(), order_by(n));
... is serialized to
select name from user order by ?1
Calling order_by(n)
could be disallowed.