github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/testdata/fk-on-update-set-null (about)

     1  exec-ddl
     2  CREATE TABLE parent (p INT PRIMARY KEY)
     3  ----
     4  
     5  exec-ddl
     6  CREATE TABLE child (c INT PRIMARY KEY, p INT NOT NULL REFERENCES parent(p) ON UPDATE SET NULL)
     7  ----
     8  
     9  build-cascades
    10  UPDATE parent SET p = p * 10 WHERE p > 1
    11  ----
    12  root
    13   ├── update parent
    14   │    ├── columns: <none>
    15   │    ├── fetch columns: p:2
    16   │    ├── update-mapping:
    17   │    │    └── p_new:3 => p:1
    18   │    ├── input binding: &1
    19   │    ├── cascades
    20   │    │    └── fk_p_ref_parent
    21   │    └── project
    22   │         ├── columns: p_new:3!null p:2!null
    23   │         ├── select
    24   │         │    ├── columns: p:2!null
    25   │         │    ├── scan parent
    26   │         │    │    └── columns: p:2!null
    27   │         │    └── filters
    28   │         │         └── p:2 > 1
    29   │         └── projections
    30   │              └── p:2 * 10 [as=p_new:3]
    31   └── cascade
    32        └── update child
    33             ├── columns: <none>
    34             ├── fetch columns: c:6 child.p:7
    35             ├── update-mapping:
    36             │    └── p_new:10 => child.p:5
    37             └── project
    38                  ├── columns: p_new:10 c:6!null child.p:7!null p:8!null p_new:9!null
    39                  ├── inner-join (hash)
    40                  │    ├── columns: c:6!null child.p:7!null p:8!null p_new:9!null
    41                  │    ├── scan child
    42                  │    │    └── columns: c:6!null child.p:7!null
    43                  │    ├── select
    44                  │    │    ├── columns: p:8!null p_new:9!null
    45                  │    │    ├── with-scan &1
    46                  │    │    │    ├── columns: p:8!null p_new:9!null
    47                  │    │    │    └── mapping:
    48                  │    │    │         ├──  parent.p:2 => p:8
    49                  │    │    │         └──  p_new:3 => p_new:9
    50                  │    │    └── filters
    51                  │    │         └── p:8 IS DISTINCT FROM p_new:9
    52                  │    └── filters
    53                  │         └── child.p:7 = p:8
    54                  └── projections
    55                       └── NULL::INT8 [as=p_new:10]
    56  
    57  exec-ddl
    58  CREATE TABLE parent_multi (
    59    pk INT PRIMARY KEY,
    60    p INT, q INT,
    61    UNIQUE (p, q),
    62    FAMILY (pk),
    63    FAMILY (p),
    64    FAMILY (q)
    65  )
    66  ----
    67  
    68  exec-ddl
    69  CREATE TABLE child_multi (
    70    c INT PRIMARY KEY,
    71    p INT, q INT,
    72    UNIQUE (c, q),
    73    CONSTRAINT fk FOREIGN KEY (p, q) REFERENCES parent_multi(p, q) ON UPDATE SET NULL 
    74  )
    75  ----
    76  
    77  build-cascades
    78  UPDATE parent_multi SET p = p * 10, q = q + 1 WHERE pk > 1
    79  ----
    80  root
    81   ├── update parent_multi
    82   │    ├── columns: <none>
    83   │    ├── fetch columns: pk:4 p:5 q:6
    84   │    ├── update-mapping:
    85   │    │    ├── p_new:7 => p:2
    86   │    │    └── q_new:8 => q:3
    87   │    ├── input binding: &1
    88   │    ├── cascades
    89   │    │    └── fk
    90   │    └── project
    91   │         ├── columns: p_new:7 q_new:8 pk:4!null p:5 q:6
    92   │         ├── select
    93   │         │    ├── columns: pk:4!null p:5 q:6
    94   │         │    ├── scan parent_multi
    95   │         │    │    └── columns: pk:4!null p:5 q:6
    96   │         │    └── filters
    97   │         │         └── pk:4 > 1
    98   │         └── projections
    99   │              ├── p:5 * 10 [as=p_new:7]
   100   │              └── q:6 + 1 [as=q_new:8]
   101   └── cascade
   102        └── update child_multi
   103             ├── columns: <none>
   104             ├── fetch columns: c:12 child_multi.p:13 child_multi.q:14
   105             ├── update-mapping:
   106             │    ├── p_new:19 => child_multi.p:10
   107             │    └── p_new:19 => child_multi.q:11
   108             └── project
   109                  ├── columns: p_new:19 c:12!null child_multi.p:13!null child_multi.q:14!null p:15!null q:16!null p_new:17 q_new:18
   110                  ├── inner-join (hash)
   111                  │    ├── columns: c:12!null child_multi.p:13!null child_multi.q:14!null p:15!null q:16!null p_new:17 q_new:18
   112                  │    ├── scan child_multi
   113                  │    │    └── columns: c:12!null child_multi.p:13 child_multi.q:14
   114                  │    ├── select
   115                  │    │    ├── columns: p:15 q:16 p_new:17 q_new:18
   116                  │    │    ├── with-scan &1
   117                  │    │    │    ├── columns: p:15 q:16 p_new:17 q_new:18
   118                  │    │    │    └── mapping:
   119                  │    │    │         ├──  parent_multi.p:5 => p:15
   120                  │    │    │         ├──  parent_multi.q:6 => q:16
   121                  │    │    │         ├──  p_new:7 => p_new:17
   122                  │    │    │         └──  q_new:8 => q_new:18
   123                  │    │    └── filters
   124                  │    │         └── (p:15 IS DISTINCT FROM p_new:17) OR (q:16 IS DISTINCT FROM q_new:18)
   125                  │    └── filters
   126                  │         ├── child_multi.p:13 = p:15
   127                  │         └── child_multi.q:14 = q:16
   128                  └── projections
   129                       └── NULL::INT8 [as=p_new:19]
   130  
   131  # Update only one of the two FK columns.
   132  build-cascades
   133  UPDATE parent_multi SET p = p * 10 WHERE p > 1
   134  ----
   135  root
   136   ├── update parent_multi
   137   │    ├── columns: <none>
   138   │    ├── fetch columns: pk:4 p:5 q:6
   139   │    ├── update-mapping:
   140   │    │    └── p_new:7 => p:2
   141   │    ├── input binding: &1
   142   │    ├── cascades
   143   │    │    └── fk
   144   │    └── project
   145   │         ├── columns: p_new:7!null pk:4!null p:5!null q:6
   146   │         ├── select
   147   │         │    ├── columns: pk:4!null p:5!null q:6
   148   │         │    ├── scan parent_multi
   149   │         │    │    └── columns: pk:4!null p:5 q:6
   150   │         │    └── filters
   151   │         │         └── p:5 > 1
   152   │         └── projections
   153   │              └── p:5 * 10 [as=p_new:7]
   154   └── cascade
   155        └── update child_multi
   156             ├── columns: <none>
   157             ├── fetch columns: c:11 child_multi.p:12 child_multi.q:13
   158             ├── update-mapping:
   159             │    ├── p_new:18 => child_multi.p:9
   160             │    └── p_new:18 => child_multi.q:10
   161             └── project
   162                  ├── columns: p_new:18 c:11!null child_multi.p:12!null child_multi.q:13!null p:14!null q:15!null p_new:16!null q:17
   163                  ├── inner-join (hash)
   164                  │    ├── columns: c:11!null child_multi.p:12!null child_multi.q:13!null p:14!null q:15!null p_new:16!null q:17
   165                  │    ├── scan child_multi
   166                  │    │    └── columns: c:11!null child_multi.p:12 child_multi.q:13
   167                  │    ├── select
   168                  │    │    ├── columns: p:14!null q:15 p_new:16!null q:17
   169                  │    │    ├── with-scan &1
   170                  │    │    │    ├── columns: p:14!null q:15 p_new:16!null q:17
   171                  │    │    │    └── mapping:
   172                  │    │    │         ├──  parent_multi.p:5 => p:14
   173                  │    │    │         ├──  parent_multi.q:6 => q:15
   174                  │    │    │         ├──  p_new:7 => p_new:16
   175                  │    │    │         └──  parent_multi.q:6 => q:17
   176                  │    │    └── filters
   177                  │    │         └── (p:14 IS DISTINCT FROM p_new:16) OR (q:15 IS DISTINCT FROM q:17)
   178                  │    └── filters
   179                  │         ├── child_multi.p:12 = p:14
   180                  │         └── child_multi.q:13 = q:15
   181                  └── projections
   182                       └── NULL::INT8 [as=p_new:18]
   183  
   184  # Test a two-level cascade.
   185  exec-ddl
   186  CREATE TABLE grandchild (
   187    g INT PRIMARY KEY,
   188    c INT, q INT,
   189    CONSTRAINT fk2 FOREIGN KEY (c, q) REFERENCES child_multi(c, q) ON UPDATE SET NULL
   190  )
   191  ----
   192  
   193  build-cascades
   194  UPDATE parent_multi SET q = q * 10 WHERE p > 1
   195  ----
   196  root
   197   ├── update parent_multi
   198   │    ├── columns: <none>
   199   │    ├── fetch columns: pk:4 p:5 q:6
   200   │    ├── update-mapping:
   201   │    │    └── q_new:7 => q:3
   202   │    ├── input binding: &1
   203   │    ├── cascades
   204   │    │    └── fk
   205   │    └── project
   206   │         ├── columns: q_new:7 pk:4!null p:5!null q:6
   207   │         ├── select
   208   │         │    ├── columns: pk:4!null p:5!null q:6
   209   │         │    ├── scan parent_multi
   210   │         │    │    └── columns: pk:4!null p:5 q:6
   211   │         │    └── filters
   212   │         │         └── p:5 > 1
   213   │         └── projections
   214   │              └── q:6 * 10 [as=q_new:7]
   215   └── cascade
   216        ├── update child_multi
   217        │    ├── columns: <none>
   218        │    ├── fetch columns: c:11 child_multi.p:12 child_multi.q:13
   219        │    ├── update-mapping:
   220        │    │    ├── p_new:18 => child_multi.p:9
   221        │    │    └── p_new:18 => child_multi.q:10
   222        │    ├── input binding: &2
   223        │    ├── cascades
   224        │    │    └── fk2
   225        │    └── project
   226        │         ├── columns: p_new:18 c:11!null child_multi.p:12!null child_multi.q:13!null p:14!null q:15!null p:16!null q_new:17
   227        │         ├── inner-join (hash)
   228        │         │    ├── columns: c:11!null child_multi.p:12!null child_multi.q:13!null p:14!null q:15!null p:16!null q_new:17
   229        │         │    ├── scan child_multi
   230        │         │    │    └── columns: c:11!null child_multi.p:12 child_multi.q:13
   231        │         │    ├── select
   232        │         │    │    ├── columns: p:14!null q:15 p:16!null q_new:17
   233        │         │    │    ├── with-scan &1
   234        │         │    │    │    ├── columns: p:14!null q:15 p:16!null q_new:17
   235        │         │    │    │    └── mapping:
   236        │         │    │    │         ├──  parent_multi.p:5 => p:14
   237        │         │    │    │         ├──  parent_multi.q:6 => q:15
   238        │         │    │    │         ├──  parent_multi.p:5 => p:16
   239        │         │    │    │         └──  q_new:7 => q_new:17
   240        │         │    │    └── filters
   241        │         │    │         └── (p:14 IS DISTINCT FROM p:16) OR (q:15 IS DISTINCT FROM q_new:17)
   242        │         │    └── filters
   243        │         │         ├── child_multi.p:12 = p:14
   244        │         │         └── child_multi.q:13 = q:15
   245        │         └── projections
   246        │              └── NULL::INT8 [as=p_new:18]
   247        └── cascade
   248             └── update grandchild
   249                  ├── columns: <none>
   250                  ├── fetch columns: g:22 grandchild.c:23 grandchild.q:24
   251                  ├── update-mapping:
   252                  │    ├── c_new:29 => grandchild.c:20
   253                  │    └── c_new:29 => grandchild.q:21
   254                  └── project
   255                       ├── columns: c_new:29 g:22!null grandchild.c:23!null grandchild.q:24!null c:25!null q:26!null c:27!null p_new:28
   256                       ├── inner-join (hash)
   257                       │    ├── columns: g:22!null grandchild.c:23!null grandchild.q:24!null c:25!null q:26!null c:27!null p_new:28
   258                       │    ├── scan grandchild
   259                       │    │    └── columns: g:22!null grandchild.c:23 grandchild.q:24
   260                       │    ├── select
   261                       │    │    ├── columns: c:25!null q:26!null c:27!null p_new:28
   262                       │    │    ├── with-scan &2
   263                       │    │    │    ├── columns: c:25!null q:26!null c:27!null p_new:28
   264                       │    │    │    └── mapping:
   265                       │    │    │         ├──  child_multi.c:11 => c:25
   266                       │    │    │         ├──  child_multi.q:13 => q:26
   267                       │    │    │         ├──  child_multi.c:11 => c:27
   268                       │    │    │         └──  p_new:18 => p_new:28
   269                       │    │    └── filters
   270                       │    │         └── (c:25 IS DISTINCT FROM c:27) OR (q:26 IS DISTINCT FROM p_new:28)
   271                       │    └── filters
   272                       │         ├── grandchild.c:23 = c:25
   273                       │         └── grandchild.q:24 = q:26
   274                       └── projections
   275                            └── NULL::INT8 [as=c_new:29]