Join.JoinType maps every join type JoinRel.JoinType defines. The three physical join classes map eight of the twelve theirs define. physical/HashJoin.java:79, physical/MergeJoin.java:79 and physical/NestedLoopJoin.java:33 each declare INNER, OUTER, LEFT, RIGHT, LEFT_SEMI, RIGHT_SEMI, LEFT_ANTI, RIGHT_ANTI beside the UNKNOWN sentinel and stop, while HashJoinRel.JoinType, MergeJoinRel.JoinType and NestedLoopJoinRel.JoinType in algebra.proto each carry the same twelve JoinRel.JoinType does. The four with no mapping are LEFT_SINGLE, RIGHT_SINGLE, LEFT_MARK and RIGHT_MARK.
A plan using any of the four is rejected while it is being read. ProtoRelConverter calls fromProto at lines 1133, 1172 and 1253, and the enum throws: IllegalArgumentException: Unknown type: JOIN_TYPE_LEFT_MARK, at physical/HashJoin.java:118, physical/MergeJoin.java:118 and physical/NestedLoopJoin.java:82.
Observed
One plan per cell, each a two-column read joined to a two-column read with nothing varied but the message and the join type. LEFT_SEMI is the control.
| join type |
HashJoinRel |
MergeJoinRel |
NestedLoopJoinRel |
LEFT_SEMI (control) |
[i64, i64?] |
[i64, i64?] |
[i64, i64?] |
LEFT_SINGLE |
Unknown type |
Unknown type |
Unknown type |
RIGHT_SINGLE |
Unknown type |
Unknown type |
Unknown type |
LEFT_MARK |
Unknown type |
Unknown type |
Unknown type |
RIGHT_MARK |
Unknown type |
Unknown type |
Unknown type |
The same four types on JoinRel are read without complaint and derive a schema, so this is the physical classes rather than the join types.
Reproduced at fff639064df794840db36fffcd881c09100e23df (v0.103.0), and main at ee9f3d20a declares the same eight in all three.
#1067 fixed MergeJoin.getLeftTypes() in these same classes; the table in it lists those eight types and the four here were outside it.
Reproducer
Convert this plan through ProtoPlanConverter. The other eleven cells change only hashJoin to mergeJoin or nestedLoopJoin and the value of type; the nested-loop form carries expression instead of keys.
{
"version": {
"minorNumber": 102
},
"relations": [
{
"root": {
"names": [
"a",
"b",
"c"
],
"input": {
"hashJoin": {
"common": {
"direct": {}
},
"left": {
"read": {
"common": {
"direct": {}
},
"baseSchema": {
"names": [
"c0",
"c1"
],
"struct": {
"types": [
{
"i64": {
"nullability": "NULLABILITY_REQUIRED"
}
},
{
"i64": {
"nullability": "NULLABILITY_NULLABLE"
}
}
],
"nullability": "NULLABILITY_REQUIRED"
}
},
"namedTable": {
"names": [
"l"
]
}
}
},
"right": {
"read": {
"common": {
"direct": {}
},
"baseSchema": {
"names": [
"c0",
"c1"
],
"struct": {
"types": [
{
"i64": {
"nullability": "NULLABILITY_NULLABLE"
}
},
{
"i64": {
"nullability": "NULLABILITY_REQUIRED"
}
}
],
"nullability": "NULLABILITY_REQUIRED"
}
},
"namedTable": {
"names": [
"r"
]
}
}
},
"keys": [
{
"left": {
"directReference": {
"structField": {}
},
"rootReference": {}
},
"right": {
"directReference": {
"structField": {}
},
"rootReference": {}
},
"comparison": {
"simple": "SIMPLE_COMPARISON_TYPE_EQ"
}
}
],
"type": "JOIN_TYPE_LEFT_MARK"
}
}
}
}
]
}
Join.JoinTypemaps every join typeJoinRel.JoinTypedefines. The three physical join classes map eight of the twelve theirs define.physical/HashJoin.java:79,physical/MergeJoin.java:79andphysical/NestedLoopJoin.java:33each declareINNER, OUTER, LEFT, RIGHT, LEFT_SEMI, RIGHT_SEMI, LEFT_ANTI, RIGHT_ANTIbeside theUNKNOWNsentinel and stop, whileHashJoinRel.JoinType,MergeJoinRel.JoinTypeandNestedLoopJoinRel.JoinTypeinalgebra.protoeach carry the same twelveJoinRel.JoinTypedoes. The four with no mapping areLEFT_SINGLE,RIGHT_SINGLE,LEFT_MARKandRIGHT_MARK.A plan using any of the four is rejected while it is being read.
ProtoRelConvertercallsfromProtoat lines 1133, 1172 and 1253, and the enum throws:IllegalArgumentException: Unknown type: JOIN_TYPE_LEFT_MARK, atphysical/HashJoin.java:118,physical/MergeJoin.java:118andphysical/NestedLoopJoin.java:82.Observed
One plan per cell, each a two-column read joined to a two-column read with nothing varied but the message and the join type.
LEFT_SEMIis the control.LEFT_SEMI(control)[i64, i64?][i64, i64?][i64, i64?]LEFT_SINGLEUnknown typeUnknown typeUnknown typeRIGHT_SINGLEUnknown typeUnknown typeUnknown typeLEFT_MARKUnknown typeUnknown typeUnknown typeRIGHT_MARKUnknown typeUnknown typeUnknown typeThe same four types on
JoinRelare read without complaint and derive a schema, so this is the physical classes rather than the join types.Reproduced at
fff639064df794840db36fffcd881c09100e23df(v0.103.0), andmainatee9f3d20adeclares the same eight in all three.#1067 fixed
MergeJoin.getLeftTypes()in these same classes; the table in it lists those eight types and the four here were outside it.Reproducer
Convert this plan through
ProtoPlanConverter. The other eleven cells change onlyhashJointomergeJoinornestedLoopJoinand the value oftype; the nested-loop form carriesexpressioninstead ofkeys.{ "version": { "minorNumber": 102 }, "relations": [ { "root": { "names": [ "a", "b", "c" ], "input": { "hashJoin": { "common": { "direct": {} }, "left": { "read": { "common": { "direct": {} }, "baseSchema": { "names": [ "c0", "c1" ], "struct": { "types": [ { "i64": { "nullability": "NULLABILITY_REQUIRED" } }, { "i64": { "nullability": "NULLABILITY_NULLABLE" } } ], "nullability": "NULLABILITY_REQUIRED" } }, "namedTable": { "names": [ "l" ] } } }, "right": { "read": { "common": { "direct": {} }, "baseSchema": { "names": [ "c0", "c1" ], "struct": { "types": [ { "i64": { "nullability": "NULLABILITY_NULLABLE" } }, { "i64": { "nullability": "NULLABILITY_REQUIRED" } } ], "nullability": "NULLABILITY_REQUIRED" } }, "namedTable": { "names": [ "r" ] } } }, "keys": [ { "left": { "directReference": { "structField": {} }, "rootReference": {} }, "right": { "directReference": { "structField": {} }, "rootReference": {} }, "comparison": { "simple": "SIMPLE_COMPARISON_TYPE_EQ" } } ], "type": "JOIN_TYPE_LEFT_MARK" } } } } ] }