xref: /sqlite-3.40.0/test/e_delete.test (revision b3366b99)
1# 2010 September 21
2#
3# The author disclaims copyright to this source code.  In place of
4# a legal notice, here is a blessing:
5#
6#    May you do good and not evil.
7#    May you find forgiveness for yourself and forgive others.
8#    May you share freely, never taking more than you give.
9#
10#***********************************************************************
11#
12# This file implements tests to verify that the "testable statements" in
13# the lang_delete.html document are correct.
14#
15set testdir [file dirname $argv0]
16source $testdir/tester.tcl
17
18ifcapable !compound {
19  finish_test
20  return
21}
22
23proc do_delete_tests {args} {
24  uplevel do_select_tests $args
25}
26
27do_execsql_test e_delete-0.0 {
28  CREATE TABLE t1(a, b);
29  CREATE INDEX i1 ON t1(a);
30} {}
31
32# -- syntax diagram delete-stmt
33# -- syntax diagram qualified-table-name
34#
35do_delete_tests e_delete-0.1 {
36  1  "DELETE FROM t1"                              {}
37  2  "DELETE FROM t1 INDEXED BY i1"                {}
38  3  "DELETE FROM t1 NOT INDEXED"                  {}
39  4  "DELETE FROM main.t1"                         {}
40  5  "DELETE FROM main.t1 INDEXED BY i1"           {}
41  6  "DELETE FROM main.t1 NOT INDEXED"             {}
42  7  "DELETE FROM t1 WHERE a>2"                    {}
43  8  "DELETE FROM t1 INDEXED BY i1 WHERE a>2"      {}
44  9  "DELETE FROM t1 NOT INDEXED WHERE a>2"        {}
45  10 "DELETE FROM main.t1 WHERE a>2"               {}
46  11 "DELETE FROM main.t1 INDEXED BY i1 WHERE a>2" {}
47  12 "DELETE FROM main.t1 NOT INDEXED WHERE a>2"   {}
48}
49
50# EVIDENCE-OF: R-20205-17349 If the WHERE clause is not present, all
51# records in the table are deleted.
52#
53drop_all_tables
54do_test e_delete-1.0 {
55  db transaction {
56    foreach t {t1 t2 t3 t4 t5 t6} {
57      execsql [string map [list %T% $t] {
58        CREATE TABLE %T%(x, y);
59        INSERT INTO %T% VALUES(1, 'one');
60        INSERT INTO %T% VALUES(2, 'two');
61        INSERT INTO %T% VALUES(3, 'three');
62        INSERT INTO %T% VALUES(4, 'four');
63        INSERT INTO %T% VALUES(5, 'five');
64      }]
65    }
66  }
67} {}
68do_delete_tests e_delete-1.1 {
69  1  "DELETE FROM t1       ; SELECT * FROM t1"       {}
70  2  "DELETE FROM main.t2  ; SELECT * FROM t2"       {}
71}
72
73# EVIDENCE-OF: R-26300-50198 If a WHERE clause is supplied, then only
74# those rows for which the WHERE clause boolean expression is true are
75# deleted.
76#
77# EVIDENCE-OF: R-23360-48280 Rows for which the expression is false or
78# NULL are retained.
79#
80do_delete_tests e_delete-1.2 {
81  1  "DELETE FROM t3 WHERE 1       ; SELECT x FROM t3"       {}
82  2  "DELETE FROM main.t4 WHERE 0  ; SELECT x FROM t4"       {1 2 3 4 5}
83  3  "DELETE FROM t4 WHERE 0.0     ; SELECT x FROM t4"       {1 2 3 4 5}
84  4  "DELETE FROM t4 WHERE NULL    ; SELECT x FROM t4"       {1 2 3 4 5}
85  5  "DELETE FROM t4 WHERE y!='two'; SELECT x FROM t4"       {2}
86  6  "DELETE FROM t4 WHERE y='two' ; SELECT x FROM t4"       {}
87  7  "DELETE FROM t5 WHERE x=(SELECT max(x) FROM t5);SELECT x FROM t5" {1 2 3 4}
88  8  "DELETE FROM t5 WHERE (SELECT max(x) FROM t4)  ;SELECT x FROM t5" {1 2 3 4}
89  9  "DELETE FROM t5 WHERE (SELECT max(x) FROM t6)  ;SELECT x FROM t5" {}
90  10 "DELETE FROM t6 WHERE y>'seven' ; SELECT y FROM t6"     {one four five}
91}
92
93
94#-------------------------------------------------------------------------
95# Tests for restrictions on DELETE statements that appear within trigger
96# programs.
97#
98forcedelete test.db2
99forcedelete test.db3
100do_execsql_test e_delete-2.0 {
101  ATTACH 'test.db2' AS aux;
102  ATTACH 'test.db3' AS aux2;
103
104  CREATE TABLE temp.t7(a, b);   INSERT INTO temp.t7 VALUES(1, 2);
105  CREATE TABLE main.t7(a, b);   INSERT INTO main.t7 VALUES(3, 4);
106  CREATE TABLE aux.t7(a, b);    INSERT INTO aux.t7 VALUES(5, 6);
107  CREATE TABLE aux2.t7(a, b);   INSERT INTO aux2.t7 VALUES(7, 8);
108
109  CREATE TABLE main.t8(a, b);   INSERT INTO main.t8 VALUES(1, 2);
110  CREATE TABLE aux.t8(a, b);    INSERT INTO aux.t8 VALUES(3, 4);
111  CREATE TABLE aux2.t8(a, b);   INSERT INTO aux2.t8 VALUES(5, 6);
112
113  CREATE TABLE aux.t9(a, b);    INSERT INTO aux.t9 VALUES(1, 2);
114  CREATE TABLE aux2.t9(a, b);   INSERT INTO aux2.t9 VALUES(3, 4);
115
116  CREATE TABLE aux2.t10(a, b);  INSERT INTO aux2.t10 VALUES(1, 2);
117} {}
118
119
120# EVIDENCE-OF: R-09681-58560 The table-name specified as part of a
121# DELETE statement within a trigger body must be unqualified.
122#
123# EVIDENCE-OF: R-12275-20298 In other words, the schema-name. prefix on
124# the table name is not allowed within triggers.
125#
126do_delete_tests e_delete-2.1 -error {
127  qualified table names are not allowed on INSERT, UPDATE, and DELETE statements within triggers
128} {
129  1 {
130      CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
131        DELETE FROM main.t2;
132      END;
133  } {}
134
135  2 {
136      CREATE TRIGGER tr1 BEFORE UPDATE ON t2 BEGIN
137        DELETE FROM temp.t7 WHERE a=new.a;
138      END;
139  } {}
140
141  3 {
142      CREATE TRIGGER tr1 AFTER UPDATE ON t8 BEGIN
143        DELETE FROM aux2.t8 WHERE b!=a;
144      END;
145  } {}
146}
147
148# EVIDENCE-OF: R-28818-63526 If the table to which the trigger is
149# attached is not in the temp database, then DELETE statements within
150# the trigger body must operate on tables within the same database as
151# it.
152#
153#   This is tested in two parts. First, check that if a table of the
154#   specified name does not exist, an error is raised. Secondly, test
155#   that if tables with the specified name exist in multiple databases,
156#   the local database table is used.
157#
158do_delete_tests e_delete-2.2.1 -error { no such table: %s } {
159  1 {
160      CREATE TRIGGER main.tr1 AFTER INSERT ON main.t7 BEGIN
161        DELETE FROM t9;
162      END;
163      INSERT INTO main.t7 VALUES(1, 2);
164  } {main.t9}
165
166  2 {
167      CREATE TRIGGER aux.tr2 BEFORE UPDATE ON t9 BEGIN
168        DELETE FROM t10;
169      END;
170      UPDATE t9 SET a=1;
171  } {aux.t10}
172}
173do_execsql_test e_delete-2.2.X {
174  DROP TRIGGER main.tr1;
175  DROP TRIGGER aux.tr2;
176} {}
177
178do_delete_tests e_delete-2.2.2 {
179  1 {
180      CREATE TRIGGER aux.tr1 AFTER INSERT ON t8 BEGIN
181        DELETE FROM t9;
182      END;
183      INSERT INTO aux.t8 VALUES(1, 2);
184
185      SELECT count(*) FROM aux.t9
186        UNION ALL
187      SELECT count(*) FROM aux2.t9;
188  } {0 1}
189
190  2 {
191      CREATE TRIGGER main.tr1 AFTER INSERT ON t8 BEGIN
192        DELETE FROM t7;
193      END;
194      INSERT INTO main.t8 VALUES(1, 2);
195
196      SELECT count(*) FROM temp.t7
197        UNION ALL
198      SELECT count(*) FROM main.t7
199        UNION ALL
200      SELECT count(*) FROM aux.t7
201        UNION ALL
202      SELECT count(*) FROM aux2.t7;
203  } {1 0 1 1}
204}
205
206# EVIDENCE-OF: R-31567-38587 If the table to which the trigger is
207# attached is in the TEMP database, then the unqualified name of the
208# table being deleted is resolved in the same way as it is for a
209# top-level statement (by searching first the TEMP database, then the
210# main database, then any other databases in the order they were
211# attached).
212#
213do_execsql_test e_delete-2.3.0 {
214  DROP TRIGGER aux.tr1;
215  DROP TRIGGER main.tr1;
216  DELETE FROM main.t8 WHERE oid>1;
217  DELETE FROM aux.t8 WHERE oid>1;
218  INSERT INTO aux.t9 VALUES(1, 2);
219  INSERT INTO main.t7 VALUES(3, 4);
220} {}
221do_execsql_test e_delete-2.3.1 {
222  SELECT count(*) FROM temp.t7 UNION ALL SELECT count(*) FROM main.t7 UNION ALL
223  SELECT count(*) FROM aux.t7  UNION ALL SELECT count(*) FROM aux2.t7;
224
225  SELECT count(*) FROM main.t8 UNION ALL SELECT count(*) FROM aux.t8
226  UNION ALL SELECT count(*) FROM aux2.t8;
227
228  SELECT count(*) FROM aux.t9  UNION ALL SELECT count(*) FROM aux2.t9;
229
230  SELECT count(*) FROM aux2.t10;
231} {1 1 1 1 1 1 1 1 1 1}
232do_execsql_test e_delete-2.3.2 {
233  CREATE TRIGGER temp.tr1 AFTER INSERT ON t7 BEGIN
234    DELETE FROM t7;
235    DELETE FROM t8;
236    DELETE FROM t9;
237    DELETE FROM t10;
238  END;
239  INSERT INTO temp.t7 VALUES('hello', 'world');
240} {}
241do_execsql_test e_delete-2.3.3 {
242  SELECT count(*) FROM temp.t7 UNION ALL SELECT count(*) FROM main.t7 UNION ALL
243  SELECT count(*) FROM aux.t7  UNION ALL SELECT count(*) FROM aux2.t7;
244
245  SELECT count(*) FROM main.t8 UNION ALL SELECT count(*) FROM aux.t8
246  UNION ALL SELECT count(*) FROM aux2.t8;
247
248  SELECT count(*) FROM aux.t9  UNION ALL SELECT count(*) FROM aux2.t9;
249
250  SELECT count(*) FROM aux2.t10;
251} {0 1 1 1 0 1 1 0 1 0}
252
253# EVIDENCE-OF: R-28691-49464 The INDEXED BY and NOT INDEXED clauses are
254# not allowed on DELETE statements within triggers.
255#
256do_execsql_test e_delete-2.4.0 {
257  CREATE INDEX i8 ON t8(a, b);
258} {}
259do_delete_tests e_delete-2.4 -error {
260  the %s %s clause is not allowed on UPDATE or DELETE statements within triggers
261} {
262  1 {
263    CREATE TRIGGER tr3 AFTER INSERT ON t8 BEGIN
264      DELETE FROM t8 INDEXED BY i8 WHERE a=5;
265    END;
266  } {INDEXED BY}
267  2 {
268    CREATE TRIGGER tr3 AFTER INSERT ON t8 BEGIN
269      DELETE FROM t8 NOT INDEXED WHERE a=5;
270    END;
271  } {NOT INDEXED}
272}
273
274ifcapable update_delete_limit {
275
276# EVIDENCE-OF: R-64942-06615 The LIMIT and ORDER BY clauses (described
277# below) are unsupported for DELETE statements within triggers.
278#
279do_delete_tests e_delete-2.5 -error { near "%s": syntax error } {
280  1 {
281    CREATE TRIGGER tr3 AFTER INSERT ON t8 BEGIN
282      DELETE FROM t8 LIMIT 10;
283    END;
284  } {LIMIT}
285  2 {
286    CREATE TRIGGER tr3 AFTER INSERT ON t8 BEGIN
287      DELETE FROM t8 ORDER BY a LIMIT 5;
288    END;
289  } {ORDER}
290}
291
292# EVIDENCE-OF: R-40026-10531 If SQLite is compiled with the
293# SQLITE_ENABLE_UPDATE_DELETE_LIMIT compile-time option, then the syntax
294# of the DELETE statement is extended by the addition of optional ORDER
295# BY and LIMIT clauses:
296#
297# -- syntax diagram delete-stmt-limited
298#
299do_delete_tests e_delete-3.1 {
300  1   "DELETE FROM t1 LIMIT 5"                                    {}
301  2   "DELETE FROM t1 LIMIT 5-1 OFFSET 2+2"                       {}
302  3   "DELETE FROM t1 LIMIT 2+2, 16/4"                            {}
303  4   "DELETE FROM t1 ORDER BY x LIMIT 5"                         {}
304  5   "DELETE FROM t1 ORDER BY x LIMIT 5-1 OFFSET 2+2"            {}
305  6   "DELETE FROM t1 ORDER BY x LIMIT 2+2, 16/4"                 {}
306  7   "DELETE FROM t1 WHERE x>2 LIMIT 5"                          {}
307  8   "DELETE FROM t1 WHERE x>2 LIMIT 5-1 OFFSET 2+2"             {}
308  9   "DELETE FROM t1 WHERE x>2 LIMIT 2+2, 16/4"                  {}
309  10  "DELETE FROM t1 WHERE x>2 ORDER BY x LIMIT 5"               {}
310  11  "DELETE FROM t1 WHERE x>2 ORDER BY x LIMIT 5-1 OFFSET 2+2"  {}
311  12  "DELETE FROM t1 WHERE x>2 ORDER BY x LIMIT 2+2, 16/4"       {}
312}
313
314drop_all_tables
315proc rebuild_t1 {} {
316  catchsql { DROP TABLE t1 }
317  execsql {
318    CREATE TABLE t1(a, b);
319    INSERT INTO t1 VALUES(1, 'one');
320    INSERT INTO t1 VALUES(2, 'two');
321    INSERT INTO t1 VALUES(3, 'three');
322    INSERT INTO t1 VALUES(4, 'four');
323    INSERT INTO t1 VALUES(5, 'five');
324  }
325}
326
327# EVIDENCE-OF: R-44062-08550 If a DELETE statement has a LIMIT clause,
328# the maximum number of rows that will be deleted is found by evaluating
329# the accompanying expression and casting it to an integer value.
330#
331rebuild_t1
332do_delete_tests e_delete-3.2 -repair rebuild_t1 -query {
333  SELECT a FROM t1
334} {
335  1   "DELETE FROM t1 LIMIT 3"       {4 5}
336  2   "DELETE FROM t1 LIMIT 1+1"     {3 4 5}
337  3   "DELETE FROM t1 LIMIT '4'"     {5}
338  4   "DELETE FROM t1 LIMIT '1.0'"   {2 3 4 5}
339}
340
341# EVIDENCE-OF: R-02661-56399 If the result of the evaluating the LIMIT
342# clause cannot be losslessly converted to an integer value, it is an
343# error.
344#
345do_delete_tests e_delete-3.3 -error { datatype mismatch } {
346  1   "DELETE FROM t1 LIMIT 'abc'"   {}
347  2   "DELETE FROM t1 LIMIT NULL"    {}
348  3   "DELETE FROM t1 LIMIT X'ABCD'" {}
349  4   "DELETE FROM t1 LIMIT 1.2"     {}
350}
351
352# EVIDENCE-OF: R-00598-03741 A negative LIMIT value is interpreted as
353# "no limit".
354#
355do_delete_tests e_delete-3.4 -repair rebuild_t1 -query {
356  SELECT a FROM t1
357} {
358  1   "DELETE FROM t1 LIMIT -1"       {}
359  2   "DELETE FROM t1 LIMIT 2-4"      {}
360  3   "DELETE FROM t1 LIMIT -4.0"     {}
361  4   "DELETE FROM t1 LIMIT 5*-1"     {}
362}
363
364# EVIDENCE-OF: R-26377-49195 If the DELETE statement also has an OFFSET
365# clause, then it is similarly evaluated and cast to an integer value.
366# Again, it is an error if the value cannot be losslessly converted to
367# an integer.
368#
369do_delete_tests e_delete-3.5 -error { datatype mismatch } {
370  1   "DELETE FROM t1 LIMIT 1 OFFSET 'abc'"   {}
371  2   "DELETE FROM t1 LIMIT 1 OFFSET NULL"    {}
372  3   "DELETE FROM t1 LIMIT 1 OFFSET X'ABCD'" {}
373  4   "DELETE FROM t1 LIMIT 1 OFFSET 1.2"     {}
374  5   "DELETE FROM t1 LIMIT 'abc', 1"         {}
375  6   "DELETE FROM t1 LIMIT NULL, 1"          {}
376  7   "DELETE FROM t1 LIMIT X'ABCD', 1"       {}
377  8   "DELETE FROM t1 LIMIT 1.2, 1"           {}
378}
379
380
381# EVIDENCE-OF: R-64004-53814 If there is no OFFSET clause, or the
382# calculated integer value is negative, the effective OFFSET value is
383# zero.
384#
385do_delete_tests e_delete-3.6 -repair rebuild_t1 -query {
386  SELECT a FROM t1
387} {
388  1a  "DELETE FROM t1 LIMIT 3 OFFSET 0"        {4 5}
389  1b  "DELETE FROM t1 LIMIT 3"                 {4 5}
390  1c  "DELETE FROM t1 LIMIT 3 OFFSET -1"       {4 5}
391  2a  "DELETE FROM t1 LIMIT 1+1 OFFSET 0"      {3 4 5}
392  2b  "DELETE FROM t1 LIMIT 1+1"               {3 4 5}
393  2c  "DELETE FROM t1 LIMIT 1+1 OFFSET 2-5"    {3 4 5}
394  3a  "DELETE FROM t1 LIMIT '4' OFFSET 0"      {5}
395  3b  "DELETE FROM t1 LIMIT '4'"               {5}
396  3c  "DELETE FROM t1 LIMIT '4' OFFSET -1.0"   {5}
397  4a  "DELETE FROM t1 LIMIT '1.0' OFFSET 0"    {2 3 4 5}
398  4b  "DELETE FROM t1 LIMIT '1.0'"             {2 3 4 5}
399  4c  "DELETE FROM t1 LIMIT '1.0' OFFSET -11"  {2 3 4 5}
400}
401
402# EVIDENCE-OF: R-48141-52334 If the DELETE statement has an ORDER BY
403# clause, then all rows that would be deleted in the absence of the
404# LIMIT clause are sorted according to the ORDER BY. The first M rows,
405# where M is the value found by evaluating the OFFSET clause expression,
406# are skipped, and the following N, where N is the value of the LIMIT
407# expression, are deleted.
408#
409do_delete_tests e_delete-3.7 -repair rebuild_t1 -query {
410  SELECT a FROM t1
411} {
412  1   "DELETE FROM t1 ORDER BY b LIMIT 2"               {1 2 3}
413  2   "DELETE FROM t1 ORDER BY length(b), a LIMIT 3"    {3 5}
414  3   "DELETE FROM t1 ORDER BY a DESC LIMIT 1 OFFSET 0"  {1 2 3 4}
415  4   "DELETE FROM t1 ORDER BY a DESC LIMIT 1 OFFSET 1"  {1 2 3 5}
416  5   "DELETE FROM t1 ORDER BY a DESC LIMIT 1 OFFSET 2"  {1 2 4 5}
417}
418
419# EVIDENCE-OF: R-64535-08414 If there are less than N rows remaining
420# after taking the OFFSET clause into account, or if the LIMIT clause
421# evaluated to a negative value, then all remaining rows are deleted.
422#
423do_delete_tests e_delete-3.8 -repair rebuild_t1 -query {
424  SELECT a FROM t1
425} {
426  1   "DELETE FROM t1 ORDER BY a ASC LIMIT 10"           {}
427  2   "DELETE FROM t1 ORDER BY a ASC LIMIT -1"           {}
428  3   "DELETE FROM t1 ORDER BY a ASC LIMIT 4 OFFSET 2"   {1 2}
429}
430
431# EVIDENCE-OF: R-37284-06965 If the DELETE statement has no ORDER BY
432# clause, then all rows that would be deleted in the absence of the
433# LIMIT clause are assembled in an arbitrary order before applying the
434# LIMIT and OFFSET clauses to determine the subset that are actually
435# deleted.
436#
437#     In practice, the "arbitrary order" is rowid order.
438#
439do_delete_tests e_delete-3.9 -repair rebuild_t1 -query {
440  SELECT a FROM t1
441} {
442  1   "DELETE FROM t1 LIMIT 2"               {3 4 5}
443  2   "DELETE FROM t1 LIMIT 3"               {4 5}
444  3   "DELETE FROM t1 LIMIT 1 OFFSET 0"      {2 3 4 5}
445  4   "DELETE FROM t1 LIMIT 1 OFFSET 1"      {1 3 4 5}
446  5   "DELETE FROM t1 LIMIT 1 OFFSET 2"      {1 2 4 5}
447}
448
449
450# EVIDENCE-OF: R-07548-13422 The ORDER BY clause on a DELETE statement
451# is used only to determine which rows fall within the LIMIT. The order
452# in which rows are deleted is arbitrary and is not influenced by the
453# ORDER BY clause.
454#
455#     In practice, rows are always deleted in rowid order.
456#
457do_delete_tests e_delete-3.10 -repair {
458  rebuild_t1
459  catchsql { DROP TABLE t1log }
460  execsql {
461    CREATE TABLE t1log(x);
462    CREATE TRIGGER tr1 AFTER DELETE ON t1 BEGIN
463      INSERT INTO t1log VALUES(old.a);
464    END;
465  }
466} -query {
467  SELECT x FROM t1log
468} {
469  1   "DELETE FROM t1 ORDER BY a DESC LIMIT 2"   {4 5}
470  2   "DELETE FROM t1 ORDER BY a DESC LIMIT -1"  {1 2 3 4 5}
471  3   "DELETE FROM t1 ORDER BY a ASC LIMIT 2"    {1 2}
472  4   "DELETE FROM t1 ORDER BY a ASC LIMIT -1"   {1 2 3 4 5}
473}
474
475}
476
477finish_test
478