Hello,

First of all, I'm not sure is this a good place to report a SQLite bug, however let me try.

SQLite version: 3.7.15.2

How to reproduce error:
1. Create in-memory (or disk, whatever) database
2. Execute following statements to prepare schema:

CREATE TABLE data (id INTEGER PRIMARY KEY AUTOINCREMENT, a INTEGER NOT NULL, b INTEGER NOT NULL)

INSERT INTO data(a,b) VALUES(1,1)
INSERT INTO data(a,b) VALUES(2,2)
INSERT INTO data(a,b) VALUES(3,3)
INSERT INTO data(a,b) VALUES(4,4)

CREATE VIEW dataView AS
    SELECT d.a AS a,
    (CASE WHEN d.a%2 = 1 THEN d.a ELSE d.b END) AS b,
    CAST((CASE WHEN d.a%2 = 1 THEN d.a ELSE d.b END) AS INTEGER) AS c
    FROM data d

For now, you have database set up.

3. Let us execute the following query:

SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM dataView

output:
1,integer,1,integer,1,integer
2,integer,2,integer,2,integer
3,integer,3,integer,3,integer
4,integer,4,integer,4,integer

As far, as we see all columns have type affinity "integer". Values of each column in corresponding rows are the same.

On the other hand, take a look at a type seen by SQLite for strings:

SELECT '1', typeof('1')

output:
1,text

So, type of '1' is 'text'.

4. Before we continue, let us cite the following sentence from SQLite documentation (Sec. 3.3. from Datatypes In SQLite Version 3): "Affinity is applied to operands of a comparison operator prior to the comparison according to the following rules in the order shown: * If one operand has INTEGER, REAL or NUMERIC affinity and the other operand as TEXT or NONE affinity then NUMERIC affinity is applied to other operand. "

So, if we compare 1 with '1' (e.g. 1='1'), '1' should be converted to numeric, right? It's not particularly true. See the following point.

5. Let us execute a query from point 3 with additional constraint in WHERE clause (note the quotes around '1'):

SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM dataView WHERE a='1'

output:
1,integer,1,integer,1,integer

The output is not surprising, SQLite returned the only row that has 1 in 'a' column. Ok, let us do the same for 'b' column:

SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM dataView WHERE b='1'

output:
0 rows

Strange, right? As we have seen there is a row for which b is 1, however SQLite did not returned that. What happen then? Note that 'b' is not a column in table 'data', its a column in view 'dataView' defined as a result of CASE statement. I hypothesize that the result of CASE statement, regardless type reported by typeof(b) function, is not internally seen as integer/numeric, so the conversion of the other argument (i.e. '1' to 1) is not applied. To confirm this hypothesis we created additional column 'c' in the view. C's definition is the same as b's, except that we explicitly cast value returned by CASE statement to integer. The query now works as expected.

SELECT a, typeof(a), b, typeof(b), c, typeof(c) FROM dataView WHERE c='1'

output:
1,integer,1,integer,1,integer


In conclusion, I think that there is an error in SQLite, that computes wrong type affinity for values returned by CASE statement.

I am looking forward for explanation of SQLite behavior or fixing of the bug described above.

With best regards,
Tomasz Pawlak



_______________________________________________
sqlite-users mailing list
sqlite-users@sqlite.org
http://sqlite.org:8080/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to