github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/ui/src/views/statements/planView.spec.tsx (about) 1 // Copyright 2018 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 import { assert } from "chai"; 12 13 import { cockroach } from "src/js/protos"; 14 import { FlatPlanNode, FlatPlanNodeAttribute, flattenTree, flattenAttributes } from "src/views/statements/planView"; 15 import IAttr = cockroach.sql.ExplainTreePlanNode.IAttr; 16 import IExplainTreePlanNode = cockroach.sql.IExplainTreePlanNode; 17 18 const testAttrs1: IAttr[] = [ 19 { 20 key: "key1", 21 value: "value1", 22 }, 23 { 24 key: "key2", 25 value: "value2", 26 }, 27 ]; 28 29 const testAttrs2: IAttr[] = [ 30 { 31 key: "key3", 32 value: "value3", 33 }, 34 { 35 key: "key4", 36 value: "value4", 37 }, 38 ]; 39 40 const testFlatAttrs1: FlatPlanNodeAttribute[] = [ 41 { 42 key: "key1", 43 values: ["value1"], 44 warn: false, 45 }, 46 { 47 key: "key2", 48 values: ["value2"], 49 warn: false, 50 }, 51 ]; 52 53 const testFlatAttrs2: FlatPlanNodeAttribute[] = [ 54 { 55 key: "key3", 56 values: ["value3"], 57 warn: false, 58 }, 59 { 60 key: "key4", 61 values: ["value4"], 62 warn: false, 63 }, 64 ]; 65 66 const treePlanWithSingleChildPaths: IExplainTreePlanNode = { 67 name: "root", 68 attrs: null, 69 children: [ 70 { 71 name: "single_grandparent", 72 attrs: testAttrs1, 73 children: [ 74 { 75 name: "single_parent", 76 attrs: null, 77 children: [ 78 { 79 name: "single_child", 80 attrs: testAttrs2, 81 children: [], 82 }, 83 ], 84 }, 85 ], 86 }, 87 ], 88 }; 89 90 const expectedFlatPlanWithSingleChildPaths: FlatPlanNode[] = [ 91 { 92 name: "root", 93 attrs: [], 94 children: [], 95 }, 96 { 97 name: "single_grandparent", 98 attrs: testFlatAttrs1, 99 children: [], 100 }, 101 { 102 name: "single_parent", 103 attrs: [], 104 children: [], 105 }, 106 { 107 name: "single_child", 108 attrs: testFlatAttrs2, 109 children: [], 110 }, 111 ]; 112 113 const treePlanWithChildren1: IExplainTreePlanNode = { 114 name: "root", 115 attrs: testAttrs1, 116 children: [ 117 { 118 name: "single_grandparent", 119 attrs: testAttrs1, 120 children: [ 121 { 122 name: "parent_1", 123 attrs: null, 124 children: [ 125 { 126 name: "single_child", 127 attrs: testAttrs2, 128 children: [], 129 }, 130 ], 131 }, 132 { 133 name: "parent_2", 134 attrs: null, 135 children: [], 136 }, 137 ], 138 }, 139 ], 140 }; 141 142 const expectedFlatPlanWithChildren1: FlatPlanNode[] = [ 143 { 144 name: "root", 145 attrs: testFlatAttrs1, 146 children: [], 147 }, 148 { 149 name: "single_grandparent", 150 attrs: testFlatAttrs1, 151 children: [ 152 [ 153 { 154 name: "parent_1", 155 attrs: [], 156 children: [], 157 }, 158 { 159 name: "single_child", 160 attrs: testFlatAttrs2, 161 children: [], 162 }, 163 ], 164 [ 165 { 166 name: "parent_2", 167 attrs: [], 168 children: [], 169 }, 170 ], 171 ], 172 }, 173 ]; 174 175 const treePlanWithChildren2: IExplainTreePlanNode = { 176 name: "root", 177 attrs: null, 178 children: [ 179 { 180 name: "single_grandparent", 181 attrs: null, 182 children: [ 183 { 184 name: "single_parent", 185 attrs: null, 186 children: [ 187 { 188 name: "child_1", 189 attrs: testAttrs1, 190 children: [], 191 }, 192 { 193 name: "child_2", 194 attrs: testAttrs2, 195 children: [], 196 }, 197 ], 198 }, 199 ], 200 }, 201 ], 202 }; 203 204 const expectedFlatPlanWithChildren2: FlatPlanNode[] = [ 205 { 206 name: "root", 207 attrs: [], 208 children: [], 209 }, 210 { 211 name: "single_grandparent", 212 attrs: [], 213 children: [], 214 }, 215 { 216 name: "single_parent", 217 attrs: [], 218 children: [ 219 [ 220 { 221 name: "child_1", 222 attrs: testFlatAttrs1, 223 children: [], 224 }, 225 ], 226 [ 227 { 228 name: "child_2", 229 attrs: testFlatAttrs2, 230 children: [], 231 }, 232 ], 233 ], 234 }, 235 ]; 236 237 const treePlanWithNoChildren: IExplainTreePlanNode = { 238 name: "root", 239 attrs: testAttrs1, 240 children: [], 241 }; 242 243 const expectedFlatPlanWithNoChildren: FlatPlanNode[] = [ 244 { 245 name: "root", 246 attrs: testFlatAttrs1, 247 children: [], 248 }, 249 ]; 250 251 describe("flattenTree", () => { 252 describe("when node has children", () => { 253 it("flattens single child paths.", () => { 254 assert.deepEqual( 255 flattenTree(treePlanWithSingleChildPaths), 256 expectedFlatPlanWithSingleChildPaths, 257 ); 258 }); 259 it("increases level if multiple children.", () => { 260 assert.deepEqual( 261 flattenTree(treePlanWithChildren1), 262 expectedFlatPlanWithChildren1, 263 ); 264 assert.deepEqual( 265 flattenTree(treePlanWithChildren2), 266 expectedFlatPlanWithChildren2, 267 ); 268 }); 269 }); 270 describe("when node has no children", () => { 271 it("returns valid flattened plan.", () => { 272 assert.deepEqual( 273 flattenTree(treePlanWithNoChildren), 274 expectedFlatPlanWithNoChildren, 275 ); 276 }); 277 }); 278 }); 279 280 describe("flattenAttributes", () => { 281 describe("when all attributes have different keys", () => { 282 it("creates array with exactly one value for each attribute", () => { 283 const testAttrs: IAttr[] = [ 284 { 285 key: "key1", 286 value: "value1", 287 }, 288 { 289 key: "key2", 290 value: "value2", 291 }, 292 ]; 293 const expectedTestAttrs: FlatPlanNodeAttribute[] = [ 294 { 295 key: "key1", 296 values: ["value1"], 297 warn: false, 298 }, 299 { 300 key: "key2", 301 values: ["value2"], 302 warn: false, 303 }, 304 ]; 305 306 assert.deepEqual( 307 flattenAttributes(testAttrs), 308 expectedTestAttrs, 309 ); 310 }); 311 }); 312 describe("when there are multiple attributes with same key", () => { 313 it("collects values into one array for same key", () => { 314 const testAttrs: IAttr[] = [ 315 { 316 key: "key1", 317 value: "key1-value1", 318 }, 319 { 320 key: "key2", 321 value: "key2-value1", 322 }, 323 { 324 key: "key1", 325 value: "key1-value2", 326 }, 327 ]; 328 const expectedTestAttrs: FlatPlanNodeAttribute[] = [ 329 { 330 key: "key1", 331 values: ["key1-value1", "key1-value2"], 332 warn: false, 333 }, 334 { 335 key: "key2", 336 values: ["key2-value1"], 337 warn: false, 338 }, 339 ]; 340 341 assert.deepEqual( 342 flattenAttributes(testAttrs), 343 expectedTestAttrs, 344 ); 345 }); 346 }); 347 describe("when attribute key/value is `spans FULL SCAN`", () => { 348 it("sets warn to true", () => { 349 const testAttrs: IAttr[] = [ 350 { 351 key: "foo", 352 value: "bar", 353 }, 354 { 355 key: "spans", 356 value: "FULL SCAN", 357 }, 358 ]; 359 const expectedTestAttrs: FlatPlanNodeAttribute[] = [ 360 { 361 key: "foo", 362 values: ["bar"], 363 warn: false, 364 }, 365 { 366 key: "spans", 367 values: ["FULL SCAN"], 368 warn: true, 369 }, 370 ]; 371 372 assert.deepEqual( 373 flattenAttributes(testAttrs), 374 expectedTestAttrs, 375 ); 376 }); 377 }); 378 describe("when keys are unsorted", () => { 379 it("puts table key first, and sorts remaining keys alphabetically", () => { 380 const testAttrs: IAttr[] = [ 381 { 382 key: "zebra", 383 value: "foo", 384 }, 385 { 386 key: "table", 387 value: "foo", 388 }, 389 { 390 key: "cheetah", 391 value: "foo", 392 }, 393 { 394 key: "table", 395 value: "bar", 396 }, 397 ]; 398 const expectedTestAttrs: FlatPlanNodeAttribute[] = [ 399 { 400 key: "table", 401 values: ["foo", "bar"], 402 warn: false, 403 }, 404 { 405 key: "cheetah", 406 values: ["foo"], 407 warn: false, 408 }, 409 { 410 key: "zebra", 411 values: ["foo"], 412 warn: false, 413 }, 414 ]; 415 416 assert.deepEqual( 417 flattenAttributes(testAttrs), 418 expectedTestAttrs, 419 ); 420 }); 421 }); 422 });