github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/opt/optbuilder/testdata/fk-on-delete-cascade (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 DELETE CASCADE) 7 ---- 8 9 # Simple cascade. 10 build-cascades 11 DELETE FROM parent WHERE p > 1 12 ---- 13 root 14 ├── delete parent 15 │ ├── columns: <none> 16 │ ├── fetch columns: p:2 17 │ ├── input binding: &1 18 │ ├── cascades 19 │ │ └── fk_p_ref_parent 20 │ └── select 21 │ ├── columns: p:2!null 22 │ ├── scan parent 23 │ │ └── columns: p:2!null 24 │ └── filters 25 │ └── p:2 > 1 26 └── cascade 27 └── delete child 28 ├── columns: <none> 29 ├── fetch columns: c:5 child.p:6 30 └── semi-join (hash) 31 ├── columns: c:5!null child.p:6!null 32 ├── scan child 33 │ └── columns: c:5!null child.p:6!null 34 ├── with-scan &1 35 │ ├── columns: p:7!null 36 │ └── mapping: 37 │ └── parent.p:2 => p:7 38 └── filters 39 └── child.p:6 = p:7 40 41 exec-ddl 42 CREATE TABLE grandchild (g INT PRIMARY KEY, c INT REFERENCES child(c) ON DELETE CASCADE) 43 ---- 44 45 # Two-level cascade. 46 build-cascades 47 DELETE FROM parent WHERE p > 1 48 ---- 49 root 50 ├── delete parent 51 │ ├── columns: <none> 52 │ ├── fetch columns: p:2 53 │ ├── input binding: &1 54 │ ├── cascades 55 │ │ └── fk_p_ref_parent 56 │ └── select 57 │ ├── columns: p:2!null 58 │ ├── scan parent 59 │ │ └── columns: p:2!null 60 │ └── filters 61 │ └── p:2 > 1 62 └── cascade 63 ├── delete child 64 │ ├── columns: <none> 65 │ ├── fetch columns: c:5 child.p:6 66 │ ├── input binding: &2 67 │ ├── cascades 68 │ │ └── fk_c_ref_child 69 │ └── semi-join (hash) 70 │ ├── columns: c:5!null child.p:6!null 71 │ ├── scan child 72 │ │ └── columns: c:5!null child.p:6!null 73 │ ├── with-scan &1 74 │ │ ├── columns: p:7!null 75 │ │ └── mapping: 76 │ │ └── parent.p:2 => p:7 77 │ └── filters 78 │ └── child.p:6 = p:7 79 └── cascade 80 └── delete grandchild 81 ├── columns: <none> 82 ├── fetch columns: g:10 grandchild.c:11 83 └── semi-join (hash) 84 ├── columns: g:10!null grandchild.c:11 85 ├── scan grandchild 86 │ └── columns: g:10!null grandchild.c:11 87 ├── with-scan &2 88 │ ├── columns: c:12!null 89 │ └── mapping: 90 │ └── child.c:5 => c:12 91 └── filters 92 └── grandchild.c:11 = c:12 93 94 # Cascade with check query. 95 exec-ddl 96 DROP TABLE grandchild 97 ---- 98 99 exec-ddl 100 CREATE TABLE grandchild (g INT PRIMARY KEY, c INT REFERENCES child(c)) 101 ---- 102 103 build-cascades 104 DELETE FROM parent WHERE p > 1 105 ---- 106 root 107 ├── delete parent 108 │ ├── columns: <none> 109 │ ├── fetch columns: p:2 110 │ ├── input binding: &1 111 │ ├── cascades 112 │ │ └── fk_p_ref_parent 113 │ └── select 114 │ ├── columns: p:2!null 115 │ ├── scan parent 116 │ │ └── columns: p:2!null 117 │ └── filters 118 │ └── p:2 > 1 119 └── cascade 120 └── delete child 121 ├── columns: <none> 122 ├── fetch columns: child.c:5 child.p:6 123 ├── input binding: &2 124 ├── semi-join (hash) 125 │ ├── columns: child.c:5!null child.p:6!null 126 │ ├── scan child 127 │ │ └── columns: child.c:5!null child.p:6!null 128 │ ├── with-scan &1 129 │ │ ├── columns: p:7!null 130 │ │ └── mapping: 131 │ │ └── parent.p:2 => p:7 132 │ └── filters 133 │ └── child.p:6 = p:7 134 └── f-k-checks 135 └── f-k-checks-item: grandchild(c) -> child(c) 136 └── semi-join (hash) 137 ├── columns: c:8!null 138 ├── with-scan &2 139 │ ├── columns: c:8!null 140 │ └── mapping: 141 │ └── child.c:5 => c:8 142 ├── scan grandchild 143 │ └── columns: grandchild.c:10 144 └── filters 145 └── c:8 = grandchild.c:10 146 147 # Self-reference with cascade. 148 exec-ddl 149 CREATE TABLE self (a INT PRIMARY KEY, b INT REFERENCES self(a) ON DELETE CASCADE) 150 ---- 151 152 build-cascades cascade-levels=3 153 DELETE FROM self WHERE a=1 154 ---- 155 root 156 ├── delete self 157 │ ├── columns: <none> 158 │ ├── fetch columns: a:3 b:4 159 │ ├── input binding: &1 160 │ ├── cascades 161 │ │ └── fk_b_ref_self 162 │ └── select 163 │ ├── columns: a:3!null b:4 164 │ ├── scan self 165 │ │ └── columns: a:3!null b:4 166 │ └── filters 167 │ └── a:3 = 1 168 └── cascade 169 ├── delete self 170 │ ├── columns: <none> 171 │ ├── fetch columns: self.a:7 b:8 172 │ ├── input binding: &2 173 │ ├── cascades 174 │ │ └── fk_b_ref_self 175 │ └── semi-join (hash) 176 │ ├── columns: self.a:7!null b:8 177 │ ├── scan self 178 │ │ └── columns: self.a:7!null b:8 179 │ ├── with-scan &1 180 │ │ ├── columns: a:9!null 181 │ │ └── mapping: 182 │ │ └── self.a:3 => a:9 183 │ └── filters 184 │ └── b:8 = a:9 185 └── cascade 186 ├── delete self 187 │ ├── columns: <none> 188 │ ├── fetch columns: self.a:12 b:13 189 │ ├── input binding: &3 190 │ ├── cascades 191 │ │ └── fk_b_ref_self 192 │ └── semi-join (hash) 193 │ ├── columns: self.a:12!null b:13 194 │ ├── scan self 195 │ │ └── columns: self.a:12!null b:13 196 │ ├── with-scan &2 197 │ │ ├── columns: a:14!null 198 │ │ └── mapping: 199 │ │ └── self.a:7 => a:14 200 │ └── filters 201 │ └── b:13 = a:14 202 └── cascade 203 └── delete self 204 ├── columns: <none> 205 ├── fetch columns: self.a:17 b:18 206 ├── input binding: &4 207 ├── cascades 208 │ └── fk_b_ref_self 209 └── semi-join (hash) 210 ├── columns: self.a:17!null b:18 211 ├── scan self 212 │ └── columns: self.a:17!null b:18 213 ├── with-scan &3 214 │ ├── columns: a:19!null 215 │ └── mapping: 216 │ └── self.a:12 => a:19 217 └── filters 218 └── b:18 = a:19 219 220 # Cascade cycle. 221 exec-ddl 222 CREATE TABLE ab (a INT PRIMARY KEY, b INT) 223 ---- 224 225 exec-ddl 226 CREATE TABLE cd (c INT PRIMARY KEY, d INT) 227 ---- 228 229 exec-ddl 230 CREATE TABLE ef (e INT PRIMARY KEY, f INT) 231 ---- 232 233 exec-ddl 234 ALTER TABLE ab ADD CONSTRAINT ab_cd FOREIGN KEY (b) REFERENCES cd(c) ON DELETE CASCADE 235 ---- 236 237 exec-ddl 238 ALTER TABLE cd ADD CONSTRAINT cd_ef FOREIGN KEY (d) REFERENCES ef(e) ON DELETE CASCADE 239 ---- 240 241 exec-ddl 242 ALTER TABLE ef ADD CONSTRAINT ef_ab FOREIGN KEY (f) REFERENCES ab(a) ON DELETE CASCADE 243 ---- 244 245 build-cascades cascade-levels=3 246 DELETE FROM ab WHERE a = 1 247 ---- 248 root 249 ├── delete ab 250 │ ├── columns: <none> 251 │ ├── fetch columns: a:3 b:4 252 │ ├── input binding: &1 253 │ ├── cascades 254 │ │ └── ef_ab 255 │ └── select 256 │ ├── columns: a:3!null b:4 257 │ ├── scan ab 258 │ │ └── columns: a:3!null b:4 259 │ └── filters 260 │ └── a:3 = 1 261 └── cascade 262 ├── delete ef 263 │ ├── columns: <none> 264 │ ├── fetch columns: e:7 f:8 265 │ ├── input binding: &2 266 │ ├── cascades 267 │ │ └── cd_ef 268 │ └── semi-join (hash) 269 │ ├── columns: e:7!null f:8 270 │ ├── scan ef 271 │ │ └── columns: e:7!null f:8 272 │ ├── with-scan &1 273 │ │ ├── columns: a:9!null 274 │ │ └── mapping: 275 │ │ └── ab.a:3 => a:9 276 │ └── filters 277 │ └── f:8 = a:9 278 └── cascade 279 ├── delete cd 280 │ ├── columns: <none> 281 │ ├── fetch columns: c:12 d:13 282 │ ├── input binding: &3 283 │ ├── cascades 284 │ │ └── ab_cd 285 │ └── semi-join (hash) 286 │ ├── columns: c:12!null d:13 287 │ ├── scan cd 288 │ │ └── columns: c:12!null d:13 289 │ ├── with-scan &2 290 │ │ ├── columns: e:14!null 291 │ │ └── mapping: 292 │ │ └── ef.e:7 => e:14 293 │ └── filters 294 │ └── d:13 = e:14 295 └── cascade 296 └── delete ab 297 ├── columns: <none> 298 ├── fetch columns: ab.a:17 b:18 299 ├── input binding: &4 300 ├── cascades 301 │ └── ef_ab 302 └── semi-join (hash) 303 ├── columns: ab.a:17!null b:18 304 ├── scan ab 305 │ └── columns: ab.a:17!null b:18 306 ├── with-scan &3 307 │ ├── columns: c:19!null 308 │ └── mapping: 309 │ └── cd.c:12 => c:19 310 └── filters 311 └── b:18 = c:19