ebd70eedd5
works for generated columns whose value is the result of a comparison operator. Ticket [bd8c280671ba44a7] FossilOrigin-Name: f3b39c71b88cb6721f443de56cdce4c08252453a5e340b00a2bd88dc10c42400
346 lines
8.8 KiB
Plaintext
346 lines
8.8 KiB
Plaintext
# 2019-10-31
|
|
#
|
|
# The author disclaims copyright to this source code. In place of
|
|
# a legal notice, here is a blessing:
|
|
#
|
|
# May you do good and not evil.
|
|
# May you find forgiveness for yourself and forgive others.
|
|
# May you share freely, never taking more than you give.
|
|
#
|
|
#***********************************************************************
|
|
#
|
|
# Test cases for generated columns.
|
|
#
|
|
|
|
set testdir [file dirname $argv0]
|
|
source $testdir/tester.tcl
|
|
|
|
# ticket 830277d9db6c3ba1 on 2019-10-31
|
|
do_execsql_test gencol1-100 {
|
|
CREATE TABLE t0(c0 AS(TYPEOF(c1)), c1);
|
|
INSERT INTO t0(c1) VALUES(0);
|
|
CREATE TABLE t1(x AS (typeof(y)), y);
|
|
INSERT INTO t1 SELECT * FROM t0;
|
|
SELECT * FROM t1;
|
|
} {integer 0}
|
|
|
|
foreach {tn schema} {
|
|
1 {
|
|
CREATE TABLE t1(
|
|
a INT,
|
|
b TEXT,
|
|
c ANY,
|
|
w INT GENERATED ALWAYS AS (a*10),
|
|
x TEXT AS (typeof(c)),
|
|
y TEXT AS (substr(b,a,a+2))
|
|
);
|
|
}
|
|
2 {
|
|
CREATE TABLE t1(
|
|
w INT GENERATED ALWAYS AS (a*10),
|
|
x TEXT AS (typeof(c)),
|
|
y TEXT AS (substr(b,a,a+2)),
|
|
a INT,
|
|
b TEXT,
|
|
c ANY
|
|
);
|
|
}
|
|
3 {
|
|
CREATE TABLE t1(
|
|
w INT GENERATED ALWAYS AS (a*10),
|
|
a INT,
|
|
x TEXT AS (typeof(c)) STORED,
|
|
b TEXT,
|
|
y TEXT AS (substr(b,a,a+2)),
|
|
c ANY
|
|
);
|
|
}
|
|
4 {
|
|
CREATE TABLE t1(
|
|
a INTEGER PRIMARY KEY,
|
|
w INT GENERATED ALWAYS AS (a*10),
|
|
b TEXT,
|
|
x TEXT AS (typeof(c)),
|
|
y TEXT AS (substr(b,a,a+2)) STORED,
|
|
c ANY
|
|
);
|
|
}
|
|
5 {
|
|
CREATE TABLE t1(
|
|
w INT GENERATED ALWAYS AS (a*10),
|
|
a INT,
|
|
x TEXT AS (typeof(c)),
|
|
b TEXT,
|
|
y TEXT AS (substr(b,a,a+2)) STORED,
|
|
c ANY,
|
|
PRIMARY KEY(a,b)
|
|
) WITHOUT ROWID;
|
|
}
|
|
6 {
|
|
CREATE TABLE t1(
|
|
w INT GENERATED ALWAYS AS (m*5),
|
|
m INT AS (a*2) STORED,
|
|
a INT,
|
|
x TEXT AS (typeof(c)),
|
|
b TEXT,
|
|
y TEXT AS (substr(b,m/2,m/2+2)) STORED,
|
|
c ANY,
|
|
PRIMARY KEY(a,b)
|
|
);
|
|
}
|
|
7 {
|
|
CREATE TABLE t1(
|
|
w INT GENERATED ALWAYS AS (m*5),
|
|
m INT AS (a*2) NOT NULL,
|
|
a INT,
|
|
x TEXT AS (typeof(c)) CHECK (x<>'blank'),
|
|
b TEXT,
|
|
y TEXT AS (substr(b,m/2,m/2+2)) STORED,
|
|
c ANY,
|
|
PRIMARY KEY(b,a)
|
|
) WITHOUT ROWID;
|
|
}
|
|
} {
|
|
catch {db close}
|
|
sqlite3 db :memory:
|
|
db eval $schema
|
|
do_execsql_test gencol1-2.$tn.100 {
|
|
INSERT INTO t1(a,b,c) VALUES(1,'abcdef',5.5),(3,'cantaloupe',NULL);
|
|
SELECT w, x, y, '|' FROM t1 ORDER BY a;
|
|
} {10 real abc | 30 null ntalo |}
|
|
do_execsql_test gencol1-2.$tn.101 {
|
|
SELECT w, x, y, '|' FROM t1 ORDER BY w;
|
|
} {10 real abc | 30 null ntalo |}
|
|
do_execsql_test gencol1-2.$tn.102 {
|
|
SELECT a FROM t1 WHERE w=30;
|
|
} {3}
|
|
do_execsql_test gencol1-2.$tn.103 {
|
|
SELECT a FROM t1 WHERE x='real';
|
|
} {1}
|
|
do_execsql_test gencol1-2.$tn.104 {
|
|
SELECT a FROM t1 WHERE y LIKE '%tal%' OR x='real' ORDER BY b;
|
|
} {1 3}
|
|
do_execsql_test gencol1-2.$tn.110 {
|
|
CREATE INDEX t1w ON t1(w);
|
|
SELECT a FROM t1 WHERE w=10;
|
|
} {1}
|
|
do_execsql_test gencol1-2.$tn.120 {
|
|
CREATE INDEX t1x ON t1(x) WHERE w BETWEEN 20 AND 40;
|
|
SELECT a FROM t1 WHERE x='null' AND w BETWEEN 20 AND 40;
|
|
} {3}
|
|
do_execsql_test gencol1-2.$tn.121 {
|
|
SELECT a FROM t1 WHERE x='real';
|
|
} {1}
|
|
do_execsql_test gencol1-2.$tn.130 {
|
|
VACUUM;
|
|
PRAGMA integrity_check;
|
|
} {ok}
|
|
do_execsql_test gencol1-2.$tn.140 {
|
|
UPDATE t1 SET a=a+100 WHERE w<20;
|
|
SELECT a, w, '|' FROM t1 ORDER BY w;
|
|
} {3 30 | 101 1010 |}
|
|
do_execsql_test gencol1-2.$tn.150 {
|
|
INSERT INTO t1 VALUES(4,'jambalaya','Chef John'),(15,87719874135,0);
|
|
SELECT w, x, y, '|' FROM t1 ORDER BY w;
|
|
} {30 null ntalo | 40 text balaya | 150 integer {} | 1010 real {} |}
|
|
}
|
|
|
|
# 2019-10-31 ticket b9befa4b83a660cc
|
|
db close
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-3.100 {
|
|
PRAGMA foreign_keys = true;
|
|
CREATE TABLE t0(c0 PRIMARY KEY, c1, c2 AS (c0+c1-c3) REFERENCES t0, c3);
|
|
INSERT INTO t0 VALUES (0, 0, 0), (11, 5, 5);
|
|
UPDATE t0 SET c1 = c0, c3 = c0;
|
|
SELECT *, '|' FROM t0 ORDER BY +c0;
|
|
} {0 0 0 0 | 11 11 11 11 |}
|
|
do_catchsql_test gencol1-3.110 {
|
|
UPDATE t0 SET c1 = c0, c3 = c0+1;
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
|
|
# 2019-11-01 ticket c28a01da72f8957c
|
|
db close
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-4.100 {
|
|
CREATE TABLE t0 (
|
|
c0,
|
|
c1 a UNIQUE AS (1),
|
|
c2,
|
|
c3 REFERENCES t0(c1)
|
|
);
|
|
PRAGMA foreign_keys = true;
|
|
INSERT INTO t0(c0,c2,c3) VALUES(0,0,1);
|
|
} {}
|
|
do_catchsql_test gencol1-4.110 {
|
|
REPLACE INTO t0(c0,c2,c3) VALUES(0,0,0),(0,0,0);
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
|
|
# 2019-11-01 Problem found while adding new foreign key test cases in TH3.
|
|
db close
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-5.100 {
|
|
PRAGMA foreign_keys=ON;
|
|
CREATE TABLE t1(
|
|
gcb AS (b*1),
|
|
a INTEGER PRIMARY KEY,
|
|
gcc AS (c+0),
|
|
b UNIQUE,
|
|
gca AS (1*a+0),
|
|
c UNIQUE
|
|
) WITHOUT ROWID;
|
|
INSERT INTO t1 VALUES(1,2,3);
|
|
INSERT INTO t1 VALUES(4,5,6);
|
|
INSERT INTO t1 VALUES(7,8,9);
|
|
CREATE TABLE t1a(
|
|
gcx AS (x+0) REFERENCES t1(a) ON DELETE CASCADE,
|
|
id,
|
|
x,
|
|
gcid AS (1*id)
|
|
);
|
|
INSERT INTO t1a VALUES(1, 1);
|
|
INSERT INTO t1a VALUES(2, 4);
|
|
INSERT INTO t1a VALUES(3, 7);
|
|
DELETE FROM t1 WHERE b=5;
|
|
SELECT id,x,'|' FROM t1a ORDER BY id;
|
|
} {1 1 | 3 7 |}
|
|
|
|
do_catchsql_test gencol1-6.10 {
|
|
DROP TABLE IF EXISTS t0;
|
|
CREATE TABLE t0(c0 NOT NULL AS(c1), c1);
|
|
REPLACE INTO t0(c1) VALUES(NULL);
|
|
} {1 {NOT NULL constraint failed: t0.c0}}
|
|
|
|
# 2019-11-06 ticket b13b7dce76e9352b34e7
|
|
do_execsql_test gencol1-7.10 {
|
|
DROP TABLE IF EXISTS t0;
|
|
CREATE TABLE t0 (c0 GENERATED ALWAYS AS (1), c1 UNIQUE, c2 UNIQUE);
|
|
INSERT INTO t0(c1) VALUES (1);
|
|
SELECT quote(0 = t0.c2 OR t0.c1 BETWEEN t0.c2 AND 1) FROM t0;
|
|
} {NULL}
|
|
do_execsql_test gencol1-7.20 {
|
|
SELECT 99 FROM t0 WHERE 0 = t0.c2 OR t0.c1 BETWEEN t0.c2 AND 1;
|
|
} {}
|
|
|
|
# 2019-11-06 ticket 4fc08501f4e56692
|
|
do_execsql_test gencol1-8.10 {
|
|
DROP TABLE IF EXISTS t0;
|
|
CREATE TABLE t0(
|
|
c0 AS (('a', 9) < ('b', c1)),
|
|
c1 AS (1),
|
|
c2 CHECK (1 = c1)
|
|
);
|
|
INSERT INTO t0 VALUES (0),(99);
|
|
SELECT * FROM t0;
|
|
} {1 1 0 1 1 99}
|
|
do_catchsql_test gencol1-8.20 {
|
|
DROP TABLE IF EXISTS t0;
|
|
CREATE TABLE t0(
|
|
c0,
|
|
c1 AS(c0 + c2),
|
|
c2 AS(c1) CHECK(c2)
|
|
);
|
|
UPDATE t0 SET c0 = NULL;
|
|
} {1 {generated column loop on "c2"}}
|
|
|
|
# 2019-11-21 Problems in the new generated column logic
|
|
# reported by Yongheng Chen and Rui Zhong
|
|
do_execsql_test gencol1-9.10 {
|
|
PRAGMA foreign_keys=OFF;
|
|
DROP TABLE t1;
|
|
CREATE TABLE t1(aa , bb AS (17) UNIQUE);
|
|
INSERT INTO t1 VALUES(17);
|
|
CREATE TABLE t2(cc);
|
|
INSERT INTO t2 VALUES(41);
|
|
SELECT * FROM t2 JOIN t1 WHERE t1.bb=t1.aa AND t1.bb=17;
|
|
} {41 17 17}
|
|
do_execsql_test gencol1-9.20 {
|
|
CREATE TABLE t3(aa INT PRIMARY KEY, bb UNIQUE AS(aa));
|
|
INSERT INTO t3 VALUES(1);
|
|
SELECT 100, * FROM t3;
|
|
DELETE FROM t3 WHERE (SELECT bb FROM t3);
|
|
SELECT 200, * FROM t3;
|
|
} {100 1 1}
|
|
|
|
# 2019-12-04 Generated column in a CREATE TABLE IF NOT EXISTS that
|
|
# does already exist.
|
|
#
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-10.10 {
|
|
CREATE TABLE t1(aa,bb);
|
|
CREATE TABLE IF NOT EXISTS t1(aa, bb AS (aa+1));
|
|
PRAGMA integrity_check;
|
|
} {ok}
|
|
|
|
# 2019-12-06 Found by mrigger
|
|
#
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-11.10 {
|
|
PRAGMA foreign_keys = true;
|
|
CREATE TABLE t0(
|
|
c0,
|
|
c1 INTEGER PRIMARY KEY,
|
|
c2 BLOB UNIQUE DEFAULT x'00',
|
|
c3 BLOB GENERATED ALWAYS AS (1),
|
|
FOREIGN KEY(c1) REFERENCES t0(c2)
|
|
);
|
|
}
|
|
do_catchsql_test gencol1-11.20 {
|
|
INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
do_execsql_test gencol1-11.30 {
|
|
DROP TABLE t0;
|
|
CREATE TABLE t0(
|
|
c0,
|
|
c1 INTEGER PRIMARY KEY,
|
|
c3 BLOB GENERATED ALWAYS AS (1),
|
|
c2 BLOB UNIQUE DEFAULT x'00',
|
|
FOREIGN KEY(c1) REFERENCES t0(c2)
|
|
);
|
|
}
|
|
do_catchsql_test gencol1-11.40 {
|
|
INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
do_execsql_test gencol1-11.50 {
|
|
DROP TABLE t0;
|
|
CREATE TABLE t0(
|
|
c0,
|
|
c3 BLOB GENERATED ALWAYS AS (1),
|
|
c1 INTEGER PRIMARY KEY,
|
|
c2 BLOB UNIQUE DEFAULT x'00',
|
|
FOREIGN KEY(c1) REFERENCES t0(c2)
|
|
);
|
|
}
|
|
do_catchsql_test gencol1-11.60 {
|
|
INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
do_execsql_test gencol1-11.70 {
|
|
DROP TABLE t0;
|
|
CREATE TABLE t0(
|
|
c3 BLOB GENERATED ALWAYS AS (1),
|
|
c0,
|
|
c1 INTEGER PRIMARY KEY,
|
|
c2 BLOB UNIQUE DEFAULT x'00',
|
|
FOREIGN KEY(c1) REFERENCES t0(c2)
|
|
);
|
|
}
|
|
do_catchsql_test gencol1-11.80 {
|
|
INSERT OR REPLACE INTO t0(c0, c1) VALUES (2, 1), (1, 0)
|
|
} {1 {FOREIGN KEY constraint failed}}
|
|
|
|
# 2019-12-09 ticket bd8c280671ba44a7
|
|
# With generated columns, the sqlite3ExprGetColumnOfTable() routine might
|
|
# generate a code sequence that does not end with OP_Column. So check to
|
|
# make sure that the last instruction generated is an OP_column prior to
|
|
# applying the OPFLAG_TYPEOFARG optimization to NOT NULL checks in the
|
|
# PRAGMA integrity_check code.
|
|
#
|
|
sqlite3 db :memory:
|
|
do_execsql_test gencol1-12.10 {
|
|
CREATE TABLE t0 (c0, c1 NOT NULL AS (c0==0));
|
|
INSERT INTO t0(c0) VALUES (0);
|
|
PRAGMA integrity_check;
|
|
} {ok}
|
|
|
|
finish_test
|