github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/testdata/fk-on-update-set-default (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 DEFAULT 0 NOT NULL REFERENCES parent(p) ON UPDATE SET DEFAULT) 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 ├── input binding: &2 38 ├── project 39 │ ├── columns: p_new:10!null c:6!null child.p:7!null p:8!null p_new:9!null 40 │ ├── inner-join (hash) 41 │ │ ├── columns: c:6!null child.p:7!null p:8!null p_new:9!null 42 │ │ ├── scan child 43 │ │ │ └── columns: c:6!null child.p:7!null 44 │ │ ├── select 45 │ │ │ ├── columns: p:8!null p_new:9!null 46 │ │ │ ├── with-scan &1 47 │ │ │ │ ├── columns: p:8!null p_new:9!null 48 │ │ │ │ └── mapping: 49 │ │ │ │ ├── parent.p:2 => p:8 50 │ │ │ │ └── p_new:3 => p_new:9 51 │ │ │ └── filters 52 │ │ │ └── p:8 IS DISTINCT FROM p_new:9 53 │ │ └── filters 54 │ │ └── child.p:7 = p:8 55 │ └── projections 56 │ └── 0 [as=p_new:10] 57 └── f-k-checks 58 └── f-k-checks-item: child(p) -> parent(p) 59 └── anti-join (hash) 60 ├── columns: p_new:11!null 61 ├── with-scan &2 62 │ ├── columns: p_new:11!null 63 │ └── mapping: 64 │ └── p_new:10 => p_new:11 65 ├── scan parent 66 │ └── columns: parent.p:12!null 67 └── filters 68 └── p_new:11 = parent.p:12 69 70 exec-ddl 71 CREATE TABLE parent_multi ( 72 pk INT PRIMARY KEY, 73 p INT, q INT, 74 UNIQUE (p, q), 75 FAMILY (pk), 76 FAMILY (p), 77 FAMILY (q) 78 ) 79 ---- 80 81 exec-ddl 82 CREATE TABLE child_multi ( 83 c INT PRIMARY KEY, 84 p INT DEFAULT 0, 85 q INT DEFAULT 1, 86 UNIQUE (c, q), 87 CONSTRAINT fk FOREIGN KEY (p, q) REFERENCES parent_multi(p, q) ON UPDATE SET DEFAULT 88 ) 89 ---- 90 91 build-cascades 92 UPDATE parent_multi SET p = p * 10, q = q + 1 WHERE pk > 1 93 ---- 94 root 95 ├── update parent_multi 96 │ ├── columns: <none> 97 │ ├── fetch columns: pk:4 p:5 q:6 98 │ ├── update-mapping: 99 │ │ ├── p_new:7 => p:2 100 │ │ └── q_new:8 => q:3 101 │ ├── input binding: &1 102 │ ├── cascades 103 │ │ └── fk 104 │ └── project 105 │ ├── columns: p_new:7 q_new:8 pk:4!null p:5 q:6 106 │ ├── select 107 │ │ ├── columns: pk:4!null p:5 q:6 108 │ │ ├── scan parent_multi 109 │ │ │ └── columns: pk:4!null p:5 q:6 110 │ │ └── filters 111 │ │ └── pk:4 > 1 112 │ └── projections 113 │ ├── p:5 * 10 [as=p_new:7] 114 │ └── q:6 + 1 [as=q_new:8] 115 └── cascade 116 └── update child_multi 117 ├── columns: <none> 118 ├── fetch columns: c:12 child_multi.p:13 child_multi.q:14 119 ├── update-mapping: 120 │ ├── p_new:19 => child_multi.p:10 121 │ └── q_new:20 => child_multi.q:11 122 ├── input binding: &2 123 ├── project 124 │ ├── columns: p_new:19!null q_new:20!null 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 125 │ ├── inner-join (hash) 126 │ │ ├── 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 127 │ │ ├── scan child_multi 128 │ │ │ └── columns: c:12!null child_multi.p:13 child_multi.q:14 129 │ │ ├── select 130 │ │ │ ├── columns: p:15 q:16 p_new:17 q_new:18 131 │ │ │ ├── with-scan &1 132 │ │ │ │ ├── columns: p:15 q:16 p_new:17 q_new:18 133 │ │ │ │ └── mapping: 134 │ │ │ │ ├── parent_multi.p:5 => p:15 135 │ │ │ │ ├── parent_multi.q:6 => q:16 136 │ │ │ │ ├── p_new:7 => p_new:17 137 │ │ │ │ └── q_new:8 => q_new:18 138 │ │ │ └── filters 139 │ │ │ └── (p:15 IS DISTINCT FROM p_new:17) OR (q:16 IS DISTINCT FROM q_new:18) 140 │ │ └── filters 141 │ │ ├── child_multi.p:13 = p:15 142 │ │ └── child_multi.q:14 = q:16 143 │ └── projections 144 │ ├── 0 [as=p_new:19] 145 │ └── 1 [as=q_new:20] 146 └── f-k-checks 147 └── f-k-checks-item: child_multi(p,q) -> parent_multi(p,q) 148 └── anti-join (hash) 149 ├── columns: p_new:21!null q_new:22!null 150 ├── with-scan &2 151 │ ├── columns: p_new:21!null q_new:22!null 152 │ └── mapping: 153 │ ├── p_new:19 => p_new:21 154 │ └── q_new:20 => q_new:22 155 ├── scan parent_multi 156 │ └── columns: parent_multi.p:24 parent_multi.q:25 157 └── filters 158 ├── p_new:21 = parent_multi.p:24 159 └── q_new:22 = parent_multi.q:25 160 161 # Update only one of the two FK columns. The "before" and "after" values of q 162 # come from the same column in the mutation input. 163 build-cascades 164 UPDATE parent_multi SET p = p * 10 WHERE p > 1 165 ---- 166 root 167 ├── update parent_multi 168 │ ├── columns: <none> 169 │ ├── fetch columns: pk:4 p:5 q:6 170 │ ├── update-mapping: 171 │ │ └── p_new:7 => p:2 172 │ ├── input binding: &1 173 │ ├── cascades 174 │ │ └── fk 175 │ └── project 176 │ ├── columns: p_new:7!null pk:4!null p:5!null q:6 177 │ ├── select 178 │ │ ├── columns: pk:4!null p:5!null q:6 179 │ │ ├── scan parent_multi 180 │ │ │ └── columns: pk:4!null p:5 q:6 181 │ │ └── filters 182 │ │ └── p:5 > 1 183 │ └── projections 184 │ └── p:5 * 10 [as=p_new:7] 185 └── cascade 186 └── update child_multi 187 ├── columns: <none> 188 ├── fetch columns: c:11 child_multi.p:12 child_multi.q:13 189 ├── update-mapping: 190 │ ├── p_new:18 => child_multi.p:9 191 │ └── q_new:19 => child_multi.q:10 192 ├── input binding: &2 193 ├── project 194 │ ├── columns: p_new:18!null q_new:19!null 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 195 │ ├── inner-join (hash) 196 │ │ ├── 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 197 │ │ ├── scan child_multi 198 │ │ │ └── columns: c:11!null child_multi.p:12 child_multi.q:13 199 │ │ ├── select 200 │ │ │ ├── columns: p:14!null q:15 p_new:16!null q:17 201 │ │ │ ├── with-scan &1 202 │ │ │ │ ├── columns: p:14!null q:15 p_new:16!null q:17 203 │ │ │ │ └── mapping: 204 │ │ │ │ ├── parent_multi.p:5 => p:14 205 │ │ │ │ ├── parent_multi.q:6 => q:15 206 │ │ │ │ ├── p_new:7 => p_new:16 207 │ │ │ │ └── parent_multi.q:6 => q:17 208 │ │ │ └── filters 209 │ │ │ └── (p:14 IS DISTINCT FROM p_new:16) OR (q:15 IS DISTINCT FROM q:17) 210 │ │ └── filters 211 │ │ ├── child_multi.p:12 = p:14 212 │ │ └── child_multi.q:13 = q:15 213 │ └── projections 214 │ ├── 0 [as=p_new:18] 215 │ └── 1 [as=q_new:19] 216 └── f-k-checks 217 └── f-k-checks-item: child_multi(p,q) -> parent_multi(p,q) 218 └── anti-join (hash) 219 ├── columns: p_new:20!null q_new:21!null 220 ├── with-scan &2 221 │ ├── columns: p_new:20!null q_new:21!null 222 │ └── mapping: 223 │ ├── p_new:18 => p_new:20 224 │ └── q_new:19 => q_new:21 225 ├── scan parent_multi 226 │ └── columns: parent_multi.p:23 parent_multi.q:24 227 └── filters 228 ├── p_new:20 = parent_multi.p:23 229 └── q_new:21 = parent_multi.q:24 230 231 # Test a two-level cascade. 232 exec-ddl 233 CREATE TABLE grandchild ( 234 g INT PRIMARY KEY, 235 c INT DEFAULT 10, q INT DEFAULT 11, 236 CONSTRAINT fk2 FOREIGN KEY (c, q) REFERENCES child_multi(c, q) ON UPDATE SET DEFAULT 237 ) 238 ---- 239 240 build-cascades 241 UPDATE parent_multi SET q = q * 10 WHERE p > 1 242 ---- 243 root 244 ├── update parent_multi 245 │ ├── columns: <none> 246 │ ├── fetch columns: pk:4 p:5 q:6 247 │ ├── update-mapping: 248 │ │ └── q_new:7 => q:3 249 │ ├── input binding: &1 250 │ ├── cascades 251 │ │ └── fk 252 │ └── project 253 │ ├── columns: q_new:7 pk:4!null p:5!null q:6 254 │ ├── select 255 │ │ ├── columns: pk:4!null p:5!null q:6 256 │ │ ├── scan parent_multi 257 │ │ │ └── columns: pk:4!null p:5 q:6 258 │ │ └── filters 259 │ │ └── p:5 > 1 260 │ └── projections 261 │ └── q:6 * 10 [as=q_new:7] 262 └── cascade 263 ├── update child_multi 264 │ ├── columns: <none> 265 │ ├── fetch columns: c:11 child_multi.p:12 child_multi.q:13 266 │ ├── update-mapping: 267 │ │ ├── p_new:18 => child_multi.p:9 268 │ │ └── q_new:19 => child_multi.q:10 269 │ ├── input binding: &2 270 │ ├── cascades 271 │ │ └── fk2 272 │ ├── project 273 │ │ ├── columns: p_new:18!null q_new:19!null 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 274 │ │ ├── inner-join (hash) 275 │ │ │ ├── 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 276 │ │ │ ├── scan child_multi 277 │ │ │ │ └── columns: c:11!null child_multi.p:12 child_multi.q:13 278 │ │ │ ├── select 279 │ │ │ │ ├── columns: p:14!null q:15 p:16!null q_new:17 280 │ │ │ │ ├── with-scan &1 281 │ │ │ │ │ ├── columns: p:14!null q:15 p:16!null q_new:17 282 │ │ │ │ │ └── mapping: 283 │ │ │ │ │ ├── parent_multi.p:5 => p:14 284 │ │ │ │ │ ├── parent_multi.q:6 => q:15 285 │ │ │ │ │ ├── parent_multi.p:5 => p:16 286 │ │ │ │ │ └── q_new:7 => q_new:17 287 │ │ │ │ └── filters 288 │ │ │ │ └── (p:14 IS DISTINCT FROM p:16) OR (q:15 IS DISTINCT FROM q_new:17) 289 │ │ │ └── filters 290 │ │ │ ├── child_multi.p:12 = p:14 291 │ │ │ └── child_multi.q:13 = q:15 292 │ │ └── projections 293 │ │ ├── 0 [as=p_new:18] 294 │ │ └── 1 [as=q_new:19] 295 │ └── f-k-checks 296 │ └── f-k-checks-item: child_multi(p,q) -> parent_multi(p,q) 297 │ └── anti-join (hash) 298 │ ├── columns: p_new:20!null q_new:21!null 299 │ ├── with-scan &2 300 │ │ ├── columns: p_new:20!null q_new:21!null 301 │ │ └── mapping: 302 │ │ ├── p_new:18 => p_new:20 303 │ │ └── q_new:19 => q_new:21 304 │ ├── scan parent_multi 305 │ │ └── columns: parent_multi.p:23 parent_multi.q:24 306 │ └── filters 307 │ ├── p_new:20 = parent_multi.p:23 308 │ └── q_new:21 = parent_multi.q:24 309 └── cascade 310 └── update grandchild 311 ├── columns: <none> 312 ├── fetch columns: g:28 grandchild.c:29 grandchild.q:30 313 ├── update-mapping: 314 │ ├── c_new:35 => grandchild.c:26 315 │ └── q_new:36 => grandchild.q:27 316 ├── input binding: &3 317 ├── project 318 │ ├── columns: c_new:35!null q_new:36!null g:28!null grandchild.c:29!null grandchild.q:30!null c:31!null q:32!null c:33!null q_new:34!null 319 │ ├── inner-join (hash) 320 │ │ ├── columns: g:28!null grandchild.c:29!null grandchild.q:30!null c:31!null q:32!null c:33!null q_new:34!null 321 │ │ ├── scan grandchild 322 │ │ │ └── columns: g:28!null grandchild.c:29 grandchild.q:30 323 │ │ ├── select 324 │ │ │ ├── columns: c:31!null q:32!null c:33!null q_new:34!null 325 │ │ │ ├── with-scan &2 326 │ │ │ │ ├── columns: c:31!null q:32!null c:33!null q_new:34!null 327 │ │ │ │ └── mapping: 328 │ │ │ │ ├── child_multi.c:11 => c:31 329 │ │ │ │ ├── child_multi.q:13 => q:32 330 │ │ │ │ ├── child_multi.c:11 => c:33 331 │ │ │ │ └── q_new:19 => q_new:34 332 │ │ │ └── filters 333 │ │ │ └── (c:31 IS DISTINCT FROM c:33) OR (q:32 IS DISTINCT FROM q_new:34) 334 │ │ └── filters 335 │ │ ├── grandchild.c:29 = c:31 336 │ │ └── grandchild.q:30 = q:32 337 │ └── projections 338 │ ├── 10 [as=c_new:35] 339 │ └── 11 [as=q_new:36] 340 └── f-k-checks 341 └── f-k-checks-item: grandchild(c,q) -> child_multi(c,q) 342 └── anti-join (hash) 343 ├── columns: c_new:37!null q_new:38!null 344 ├── with-scan &3 345 │ ├── columns: c_new:37!null q_new:38!null 346 │ └── mapping: 347 │ ├── c_new:35 => c_new:37 348 │ └── q_new:36 => q_new:38 349 ├── scan child_multi 350 │ └── columns: child_multi.c:39!null child_multi.q:41 351 └── filters 352 ├── c_new:37 = child_multi.c:39 353 └── q_new:38 = child_multi.q:41