github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/upfrom2.test (about)

     1  # 2020 April 29
     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  
    13  set testdir [file dirname $argv0]
    14  source $testdir/tester.tcl
    15  set testprefix upfrom2
    16  
    17  # Test cases:
    18  #
    19  #   1.*: Test that triggers are fired correctly for UPDATE FROM statements,
    20  #        and only once for each row. Except for INSTEAD OF triggers on 
    21  #        views - these are fired once for each row returned by the join, 
    22  #        including duplicates.
    23  #
    24  #   2.*: Test adding ORDER BY and LIMIT clauses with UPDATE FROM statements.
    25  #
    26  #   5.*: Test that specifying the target table name or alias in the FROM
    27  #        clause of an UPDATE statement is an error.
    28  #
    29  
    30  foreach {tn wo} {
    31    1 ""
    32    2 "WITHOUT ROWID"
    33  } {
    34    reset_db
    35  
    36    eval [string map [list %WO% $wo %TN% $tn] {
    37    do_execsql_test 1.%TN%.0 {
    38      CREATE TABLE log(t TEXT);
    39      CREATE TABLE t1(x PRIMARY KEY, y, z UNIQUE) %WO%;
    40      CREATE INDEX t1y ON t1(y);
    41  
    42      INSERT INTO t1 VALUES(1, 'i',   'one');
    43      INSERT INTO t1 VALUES(2, 'ii',  'two');
    44      INSERT INTO t1 VALUES(3, 'iii', 'three');
    45      INSERT INTO t1 VALUES(4, 'iv',  'four');
    46  
    47      CREATE TRIGGER tr1 BEFORE UPDATE ON t1 BEGIN
    48        INSERT INTO log VALUES(old.z || '->' || new.z);
    49      END;
    50      CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN
    51        INSERT INTO log VALUES(old.y || '->' || new.y);
    52      END;
    53    }
    54  
    55    do_execsql_test 1.%TN%.1 {
    56      WITH data(k, v) AS (
    57        VALUES(3, 'thirty'), (1, 'ten')
    58      )
    59      UPDATE t1 SET z=v FROM data WHERE x=k;
    60  
    61      SELECT * FROM t1;
    62      SELECT * FROM log;
    63    } {
    64      1 i ten   2 ii two   3 iii thirty   4 iv four
    65      one->ten        i->i
    66      three->thirty   iii->iii
    67    }
    68  
    69    do_execsql_test 1.%TN%.2 {
    70      CREATE TABLE t2(a, b);
    71      CREATE TABLE t3(k, v);
    72    
    73      INSERT INTO t3 VALUES(5,   'v');
    74      INSERT INTO t3 VALUES(12, 'xii');
    75    
    76      INSERT INTO t2 VALUES(2, 12);
    77      INSERT INTO t2 VALUES(3, 5);
    78    
    79      DELETE FROM log;
    80      UPDATE t1 SET y=v FROM t2, t3 WHERE t1.x=t2.a AND t3.k=t2.b;
    81    
    82      SELECT * FROM t1;
    83      SELECT * FROM log;
    84    } {
    85      1 i ten   2 xii two   3 v thirty   4 iv four
    86      two->two         ii->xii
    87      thirty->thirty   iii->v
    88    }
    89  
    90    do_execsql_test 1.%TN%.3 {
    91      DELETE FROM log;
    92      WITH data(k, v) AS (
    93        VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
    94      )
    95      UPDATE t1 SET z=v FROM data WHERE x=k;
    96    
    97      SELECT * FROM t1;
    98      SELECT * FROM log;
    99    } {
   100      1 i eight   2 xii twelve   3 v thirty   4 iv four
   101      ten->eight        i->i
   102      two->twelve       xii->xii
   103    }
   104  
   105    do_test 1.%TN%.4 { db changes } {2}
   106  
   107    do_execsql_test 1.%TN%.5 { 
   108      CREATE VIEW v1 AS SELECT * FROM t1;
   109      CREATE TRIGGER v1tr INSTEAD OF UPDATE ON v1 BEGIN
   110        UPDATE t1 SET y=new.y, z=new.z WHERE x=new.x;
   111      END;
   112  
   113      DELETE FROM log;
   114      WITH data(k, v) AS (
   115        VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
   116      )
   117      UPDATE v1 SET z=v FROM data WHERE x=k;
   118    }
   119  
   120    do_execsql_test 1.%TN%.6 {
   121      SELECT * FROM v1;
   122      SELECT * FROM log;
   123    } {
   124      1 i eight   2 xii twelve   3 v fourteen   4 iv sixteen
   125      thirty->thirteen  v->v
   126      thirteen->fourteen  v->v
   127      four->fifteen  iv->iv
   128      fifteen->sixteen  iv->iv
   129    }
   130  
   131    #--------------------------------------------------------------
   132  
   133    do_execsql_test 1.%TN%.7 {
   134      CREATE TABLE o1(w, x, y, z UNIQUE, PRIMARY KEY(w, x)) %WO%;
   135      CREATE INDEX o1y ON t1(y);
   136  
   137      INSERT INTO o1 VALUES(0, 0, 'i', 'one');
   138      INSERT INTO o1 VALUES(0, 1, 'ii', 'two');
   139      INSERT INTO o1 VALUES(1, 0, 'iii', 'three');
   140      INSERT INTO o1 VALUES(1, 1, 'iv', 'four');
   141  
   142      CREATE TRIGGER tro1 BEFORE UPDATE ON o1 BEGIN
   143        INSERT INTO log VALUES(old.z || '->' || new.z);
   144      END;
   145      CREATE TRIGGER tro2 AFTER UPDATE ON o1 BEGIN
   146        INSERT INTO log VALUES(old.y || '->' || new.y);
   147      END;
   148    }
   149  
   150    do_execsql_test 1.%TN%.8 {
   151      DELETE FROM log;
   152      WITH data(k, v) AS (
   153        VALUES(3, 'thirty'), (1, 'ten')
   154      )
   155      UPDATE o1 SET z=v FROM data WHERE (1+x+w*2)=k;
   156  
   157      SELECT * FROM o1;
   158      SELECT * FROM log;
   159    } {
   160      0 0 i ten   0 1 ii two   1 0 iii thirty   1 1 iv four
   161      one->ten        i->i
   162      three->thirty   iii->iii
   163    }
   164  
   165    do_execsql_test 1.%TN%.9 {
   166      DELETE FROM log;
   167      UPDATE o1 SET y=v FROM t2, t3 WHERE (1+o1.w*2+o1.x)=t2.a AND t3.k=t2.b;
   168    
   169      SELECT * FROM o1;
   170      SELECT * FROM log;
   171    } {
   172      0 0 i ten   0 1 xii two   1 0 v thirty   1 1 iv four
   173      two->two         ii->xii
   174      thirty->thirty   iii->v
   175    }
   176  
   177    do_execsql_test 1.%TN%.10 {
   178      DELETE FROM log;
   179      WITH data(k, v) AS (
   180        VALUES(1, 'seven'), (1, 'eight'), (2, 'eleven'), (2, 'twelve')
   181      )
   182      UPDATE o1 SET z=v FROM data WHERE (1+w*2+x)=k;
   183    
   184      SELECT * FROM o1;
   185      SELECT * FROM log;
   186    } {
   187      0 0 i eight   0 1 xii twelve   1 0 v thirty   1 1 iv four
   188      ten->eight        i->i
   189      two->twelve       xii->xii
   190    }
   191  
   192    do_test 1.%TN%.11 { db changes } {2}
   193  
   194    do_execsql_test 1.%TN%.12 { 
   195      CREATE VIEW w1 AS SELECT * FROM o1;
   196      CREATE TRIGGER w1tr INSTEAD OF UPDATE ON w1 BEGIN
   197        UPDATE o1 SET y=new.y, z=new.z WHERE w=new.w AND x=new.x;
   198      END;
   199  
   200      DELETE FROM log;
   201      WITH data(k, v) AS (
   202        VALUES(3, 'thirteen'), (3, 'fourteen'), (4, 'fifteen'), (4, 'sixteen')
   203      )
   204      UPDATE w1 SET z=v FROM data WHERE (1+w*2+x)=k;
   205    }
   206  
   207    do_execsql_test 1.%TN%.13 {
   208      SELECT * FROM w1;
   209      SELECT * FROM log;
   210    } {
   211      0 0 i eight   0 1 xii twelve   1 0 v fourteen   1 1 iv sixteen
   212      thirty->thirteen  v->v
   213      thirteen->fourteen  v->v
   214      four->fifteen  iv->iv
   215      fifteen->sixteen  iv->iv
   216    }
   217  
   218  }]
   219  }
   220  
   221  ifcapable update_delete_limit {
   222  foreach {tn wo} {
   223    1 ""
   224    2 "WITHOUT ROWID"
   225  } {
   226    reset_db
   227  
   228  eval [string map [list %WO% $wo %TN% $tn] {
   229    do_execsql_test 2.%TN%.1 {
   230      CREATE TABLE x1(a INTEGER PRIMARY KEY, b) %WO%;
   231      INSERT INTO x1 VALUES
   232          (1, 'one'), (2, 'two'), (3, 'three'), (4, 'four'),
   233          (5, 'five'), (6, 'six'), (7, 'seven'), (8, 'eight');
   234    }
   235  
   236    do_execsql_test 2.%TN%.2 {
   237      CREATE TABLE data1(x, y);
   238      INSERT INTO data1 VALUES
   239      (1, 'eleven'), (1, 'twenty-one'), (2, 'twelve'), (2, 'twenty-two'),
   240      (3, 'thirteen'), (3, 'twenty-three'), (4, 'fourteen'), (4, 'twenty-four');
   241    }
   242  
   243    do_execsql_test 2.%TN%.3 {
   244      UPDATE x1 SET b=y FROM data1 WHERE a=x ORDER BY a LIMIT 3;
   245      SELECT * FROM x1;
   246    } {
   247      1 eleven 2 twelve 3 thirteen 4 four 5 five 6 six 7 seven 8 eight
   248    }
   249  
   250    do_execsql_test 2.%TN%.4 {
   251      UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b LIMIT 3;
   252      SELECT * FROM x1;
   253    } {
   254      1 eleveneleven 2 twelve 3 thirteenthirteen 4 fourfourteen 
   255      5 five 6 six 7 seven 8 eight
   256    }
   257  
   258    do_catchsql_test 2.%TN%.5 {
   259      UPDATE x1 SET b=b||b ORDER BY b;
   260    } {1 {ORDER BY without LIMIT on UPDATE}}
   261    do_catchsql_test 2.%TN%.6 {
   262      UPDATE x1 SET b=b||y FROM data1 WHERE a=x ORDER BY b;
   263    } {1 {ORDER BY without LIMIT on UPDATE}}
   264  
   265    #-----------------------------------------------------------------------
   266  
   267    do_execsql_test 2.%TN%.6 {
   268      DROP TABLE x1;
   269      CREATE TABLE x1(u, v, b, PRIMARY KEY(u, v)) %WO%;
   270      INSERT INTO x1 VALUES
   271          (0, 1, 'one'), (1, 0, 'two'), (1, 1, 'three'), (2, 0, 'four'),
   272          (2, 1, 'five'), (3, 0, 'six'), (3, 1, 'seven'), (4, 0, 'eight');
   273    }
   274  
   275    do_execsql_test 2.%TN%.7 {
   276      UPDATE x1 SET b=y FROM data1 WHERE (u*2+v)=x ORDER BY u, v LIMIT 3;
   277      SELECT * FROM x1;
   278    } {
   279      0 1 eleven 1 0 twelve 1 1 thirteen 2 0 four 
   280      2 1 five 3 0 six 3 1 seven 4 0 eight
   281    }
   282  
   283    do_execsql_test 2.%TN%.8 {
   284      UPDATE x1 SET b=b||y FROM data1 WHERE (u*2+v)=x ORDER BY b LIMIT 3;
   285      SELECT * FROM x1;
   286    } {
   287      0 1 eleveneleven 1 0 twelve 1 1 thirteenthirteen 2 0 fourfourteen 
   288      2 1 five  3 0 six 3 1 seven 4 0 eight
   289    }
   290  
   291  
   292  }]
   293  }}
   294  
   295  reset_db
   296  do_execsql_test 3.0 {
   297    CREATE TABLE data(x, y, z);
   298    CREATE VIEW t1 AS SELECT * FROM data;
   299    CREATE TRIGGER t1_insert INSTEAD OF INSERT ON t1 BEGIN
   300      INSERT INTO data VALUES(new.x, new.y, new.z);
   301    END;
   302    CREATE TRIGGER t1_update INSTEAD OF UPDATE ON t1 BEGIN
   303      INSERT INTO log VALUES(old.z || '->' || new.z);
   304    END;
   305  
   306    CREATE TABLE log(t TEXT);
   307  
   308    INSERT INTO t1 VALUES(1, 'i',   'one');
   309    INSERT INTO t1 VALUES(2, 'ii',  'two');
   310    INSERT INTO t1 VALUES(3, 'iii', 'three');
   311    INSERT INTO t1 VALUES(4, 'iv',  'four');
   312  }
   313  
   314  do_execsql_test 3.1 {
   315    WITH input(k, v) AS (
   316        VALUES(3, 'thirty'), (1, 'ten')
   317    )
   318    UPDATE t1 SET z=v FROM input WHERE x=k;
   319  }
   320  
   321  foreach {tn sql} {
   322    2 { 
   323      CREATE TABLE x1(a INT PRIMARY KEY, b, c) WITHOUT ROWID;
   324    }
   325    1 { 
   326      CREATE TABLE x1(a INTEGER PRIMARY KEY, b, c);
   327    }
   328    3 { 
   329      CREATE TABLE x1(a INT PRIMARY KEY, b, c);
   330    }
   331  } {
   332  
   333    reset_db
   334    execsql $sql
   335  
   336    do_execsql_test 4.$tn.0 {
   337      INSERT INTO x1 VALUES(1, 1, 1);
   338      INSERT INTO x1 VALUES(2, 2, 2);
   339      INSERT INTO x1 VALUES(3, 3, 3);
   340      INSERT INTO x1 VALUES(4, 4, 4);
   341      INSERT INTO x1 VALUES(5, 5, 5);
   342      CREATE TABLE map(o, t);
   343      INSERT INTO map VALUES(3, 30), (4, 40), (1, 10);
   344    }
   345  
   346    do_execsql_test 4.$tn.1 {
   347      UPDATE x1 SET a=t FROM map WHERE a=o;
   348      SELECT * FROM x1 ORDER BY a;
   349    } {2 2 2   5 5 5   10 1 1  30 3 3  40 4 4}
   350  }
   351  
   352  reset_db
   353  do_execsql_test 5.0 {
   354    CREATE TABLE x1(a, b, c);
   355    CREATE TABLE x2(a, b, c);
   356  }
   357  
   358  foreach {tn update nm} {
   359    1 "UPDATE x1 SET a=5 FROM x1" x1
   360    2 "UPDATE x1 AS grapes SET a=5 FROM x1 AS grapes" grapes
   361    3 "UPDATE x1 SET a=5 FROM x2, x1" x1
   362    4 "UPDATE x1 AS grapes SET a=5 FROM x2, x1 AS grapes" grapes
   363  } {
   364    do_catchsql_test 5.$tn $update \
   365      "1 {target object/alias may not appear in FROM clause: $nm}"
   366  }
   367  
   368  
   369  finish_test