> On 29 Jan 2020, at 14:59, Richard Hipp <drh at sqlite.org> wrote:
>
> On 1/29/20, Markus Winand <markus.winand at winand.at> wrote:
>> Hi!
>>
>> I think there might be a glitch in the way SQLite 3.31.x derives the
>> collation information from the expression of a generated column.
>
> I think the current behavior is correct.
>
> If you want a column to have a non-standard collating sequence, you
> should add a COLLATE constraint to that column definition. The fact
> that there is a COLLATE operator on the expression that determines the
> value of that column seems irrelevant.
>
> Consider this:
>
> CREATE TABLE t1(a TEXT DEFAULT('xyzzy' COLLATE nocase));
>
> Would you expect the COLLATE operator in the DEFAULT clause to change
> the collating sequence associated with column a? Why should a
> GENERATED ALWAYS AS constraint work differently from a DEFAULT
> constraint?
The critical point here is that SQLite accepts a GENERATED clause without
explicit type:
CREATE TABLE tmp (str VARCHAR(255), str_nc1 GENERATED ALWAYS AS (str COLLATE
NOCASE), str_nc2 GENERATED ALWAYS AS (str) COLLATE NOCASE);
In that case, the type of the generated column should taken from the result
type of the expression[0]. As collations are part of the character string
types[1], also the collation is taken from the expression. The COLLATE clause
applied to expressions (as opposed to following the name of a data type) just
changes the collation in of the character string type of that expression[2].
If the GENERATED clause explicitly sets a data type, then the collation of the
expression is irrelevant as it doesn’t affect the type of the generated column,
similar to your example with DEFAULT (it is only a value assignment in that
case).
At the end everything boils down to this question:
What is the type, including the character set and collation, of generated
columns that don’t specify a type explicitly? I think the only sensible answer
is that it is the type of the expression, including its character set and
collation.
Unfortunately, the “what would PostgreSQL do” approach doesn’t provide guidance
here as PostgreSQL requires an explicit type for generated columns (and so do
MySQL and MariaDB). In SQL Server, however, it works like I would expect it.
I guess the SQLite approach to types might affect all of my reasoning, but in
other cases like the following it seems that SQLite also “transports” the
applicable collation together with the result (type?) of an expression:
sqlite> CREATE TABLE tmp (str VARCHAR(255));
sqlite> INSERT INTO tmp VALUES ('a'), ('A'), ('b'), ('B');
sqlite> SELECT * FROM (SELECT str COLLATE NOCASE FROM tmp) ORDER BY str;
a
A
b
B
-markus
References to SQL:2016, Part 2. I know that this is not a strong argument to
you, but nevertheless ;)
[0] 11.4 SR 13 c:
• If <generation clause> is specified, then the declared type of GE.
Whereas GE is defined in SR 10 a:
• Let GE be the <generation expression> contained in GC.
[1] 4.2.1
A character string type descriptor contains:
[….]
• — The catalog name, schema name, and collation name of the collation
of the character string type.
[2] 6.31 SR 4a:
• If <collate clause> is specified, then the declared type of the
<character factor> is the declared type of the <character primary>, except that
the declared type collation is the collation identified by <collate clause>,
and its collation derivation is explicit.
>
> --
> D. Richard Hipp
> drh at sqlite.org
>
_______________________________________________
sqlite-users mailing list
[email protected]
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users