Motivation
LogicalOperatorUtils::logicalOperatorTypeToString() threw Unknown logical operator type. at runtime on LSQB q9: the recent COUNT_ANTI_EDGE_CHAIN operator was added to the enum but a case was never added to the type-to-string switch.
-Wall -Wextra (which includes -Wswitch) would have caught this at compile time — but the switch ended in default: throw RuntimeException(...), and any default: label silences -Wswitch. The failure mode was converted from a build error into a runtime crash.
The same bug class exists in the sibling enum→string switches listed below. This was fixed for logicalOperatorTypeToString (see commit adding COUNT_ANTI_EDGE_CHAIN); this issue tracks applying the pattern to the rest.
The pattern
For switches that are exhaustive in intent (every enumerator returns / is handled):
// Before: -Wswitch silently disabled
switch (type) {
case Foo::A: return "A";
default: throw RuntimeException("Unknown type.");
}
// After: -Wswitch enforces coverage; missing enumerator = build failure with -Werror
switch (type) {
case Foo::A: return "A";
}
// No default label: -Wswitch then enforces that every enumerator is handled above.
throw RuntimeException("Unknown type."); // guards only out-of-range values
Switches using default: UNREACHABLE_CODE; get the same treatment (replace the default label with the unreachable check after the switch).
Candidate files
Exhaustive-in-intent enum→string switches currently carrying a default: label:
src/common/enums/accumulate_type.cpp (1)
src/common/enums/conflict_action.cpp (1)
src/common/enums/drop_type.cpp (1)
src/common/enums/extend_direction_util.cpp (1)
src/common/enums/path_semantic.cpp (1)
src/common/enums/query_rel_type.cpp (2)
src/common/enums/rel_direction.cpp (2)
src/common/enums/rel_multiplicity.cpp (1)
src/common/enums/scan_source_type.cpp (1)
src/common/enums/table_type.cpp (1)
src/common/enums/transaction_action.cpp (1)
src/common/expression_type.cpp (2)
src/catalog/catalog_entry/catalog_entry_type.cpp (2)
src/processor/operator/physical_operator.cpp (1)
src/transaction/transaction_manager.cpp (1 — review; may be semantically non-exhaustive)
Out of scope
Not every switch with a default: should change:
- Switches where
default is semantically meaningful, e.g. LogicalOperatorUtils::isUpdate() returns false for everything else. -Wswitch forcing a case per new operator there would be noise.
- Deserialize switches that intentionally tolerate unknown serialized values for forward compatibility.
Verification
With the pattern applied, temporarily commenting out any single case must produce warning: enumeration value 'X' not handled in switch [-Wswitch] — a hard failure under ENABLE_WERROR=ON (CI), and a visible warning in all other configs.
Notes
An X-macro generating both the enum and its string table would guarantee sync by construction, but is less readable/navigable; compiler enforcement via -Wswitch is preferred unless this class of bug recurs.
Motivation
LogicalOperatorUtils::logicalOperatorTypeToString()threwUnknown logical operator type.at runtime on LSQB q9: the recentCOUNT_ANTI_EDGE_CHAINoperator was added to the enum but a case was never added to the type-to-string switch.-Wall -Wextra(which includes-Wswitch) would have caught this at compile time — but the switch ended indefault: throw RuntimeException(...), and anydefault:label silences-Wswitch. The failure mode was converted from a build error into a runtime crash.The same bug class exists in the sibling enum→string switches listed below. This was fixed for
logicalOperatorTypeToString(see commit addingCOUNT_ANTI_EDGE_CHAIN); this issue tracks applying the pattern to the rest.The pattern
For switches that are exhaustive in intent (every enumerator returns / is handled):
Switches using
default: UNREACHABLE_CODE;get the same treatment (replace the default label with the unreachable check after the switch).Candidate files
Exhaustive-in-intent enum→string switches currently carrying a
default:label:src/common/enums/accumulate_type.cpp(1)src/common/enums/conflict_action.cpp(1)src/common/enums/drop_type.cpp(1)src/common/enums/extend_direction_util.cpp(1)src/common/enums/path_semantic.cpp(1)src/common/enums/query_rel_type.cpp(2)src/common/enums/rel_direction.cpp(2)src/common/enums/rel_multiplicity.cpp(1)src/common/enums/scan_source_type.cpp(1)src/common/enums/table_type.cpp(1)src/common/enums/transaction_action.cpp(1)src/common/expression_type.cpp(2)src/catalog/catalog_entry/catalog_entry_type.cpp(2)src/processor/operator/physical_operator.cpp(1)src/transaction/transaction_manager.cpp(1 — review; may be semantically non-exhaustive)Out of scope
Not every switch with a
default:should change:defaultis semantically meaningful, e.g.LogicalOperatorUtils::isUpdate()returnsfalsefor everything else.-Wswitchforcing a case per new operator there would be noise.Verification
With the pattern applied, temporarily commenting out any single
casemust producewarning: enumeration value 'X' not handled in switch [-Wswitch]— a hard failure underENABLE_WERROR=ON(CI), and a visible warning in all other configs.Notes
An X-macro generating both the enum and its string table would guarantee sync by construction, but is less readable/navigable; compiler enforcement via
-Wswitchis preferred unless this class of bug recurs.