Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 13 additions & 6 deletions query-graphs/src/hyper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,10 @@ function convertHyperNode(rawNode: Json, parentKey, conversionState: ConversionS
}
}

// Display these properties always as properties, even if they are more complex
const propertyKeys = ["debugName", "analyze", "sqlpos"];
// Display these properties always as properties, even if they are more complex.
// `debugName` is the pre-kebab-case spelling of `debug-name`; we accept both for
// backwards compatibility with plans produced before the Hyper kebab-case cutover.
const propertyKeys = ["debug-name", "debugName", "analyze", "sqlpos"];
for (const key of propertyKeys) {
if (!rawNode.hasOwnProperty(key)) {
continue;
Expand All @@ -152,7 +154,9 @@ function convertHyperNode(rawNode: Json, parentKey, conversionState: ConversionS
// Determine the order in which other keys are displayed.
// For some keys, we enforce a specific order here (e.g., "left" comes before "right").
// For all other keys, we use alphabetic order.
const fixedChildOrder = ["inputs", "input", "left", "right", "value", "valueForComparison"];
// `value-for-comparison` / `valueForComparison`: both spellings are listed so the
// fixed child ordering works for plans from before and after the kebab-case cutover.
const fixedChildOrder = ["inputs", "input", "left", "right", "value", "value-for-comparison", "valueForComparison"];
const orderedKeys = Object.getOwnPropertyNames(rawNode)
.filter((k) => {
// `propertyKeys` and `operator`/`expression` were already handled
Expand Down Expand Up @@ -210,7 +214,9 @@ function convertHyperNode(rawNode: Json, parentKey, conversionState: ConversionS

// Figure out the display name
const specificDisplayName = renderingConfig.displayNameKey ? properties.get(renderingConfig.displayNameKey) : undefined;
const debugNameNode = tryGetPropertyPath(rawNode, ["debugName", "value"]);
// Accept both `debug-name` (post kebab-case cutover) and the legacy `debugName`.
const debugNameNode =
tryGetPropertyPath(rawNode, ["debug-name", "value"]) ?? tryGetPropertyPath(rawNode, ["debugName", "value"]);
const debugName = typeof debugNameNode === "string" ? debugNameNode : undefined;
const displayName = debugName ?? specificDisplayName ?? properties?.get("name") ?? nodeTag ?? "";

Expand Down Expand Up @@ -257,9 +263,10 @@ function convertHyperNode(rawNode: Json, parentKey, conversionState: ConversionS
}
}

// Add to `operatorId` map if applicable
// Add to `operator-id` map if applicable.
// `operatorId` is the legacy spelling; accept both for backwards compatibility.
if (nodeType == "operator") {
const operatorId = properties?.get("operatorId");
const operatorId = properties?.get("operator-id") ?? properties?.get("operatorId");
if (operatorId !== undefined) {
conversionState.operatorsById.set(operatorId, convertedNode);
}
Expand Down
21 changes: 21 additions & 0 deletions standalone-app/examples/hyper/tablescan-kebab-case.plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"operator": "executiontarget",
"operator-id": 1,
"cardinality": 5,
"produces-rows": true,
"output": [{"expression": "iuref", "iu": ["scan_r_name", ["Char", 25]]}],
"output-names": ["r_name"],
"inputs": [{
"operator": "tablescan",
"operator-id": 2,
"sqlpos": [[41, 47]],
"cardinality": 5,
"volatility": "stable",
"relation-id": 9,
"schema": {"type":"sessionschema"},
"attribute-count": 3,
"attributes": [{"col-id": 1, "name": "r_name", "type": ["Char", 25], "iu": ["scan_r_name", ["Char", 25]]}],
"debug-name": {"classification": "nonsensitive", "value": "region"},
"selectivity": 1
}]
}
Loading