From 67b20cee294f480e14ef1a87ea64978a7b5f3a6b Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Thu, 20 Oct 2022 14:38:25 +0800 Subject: [PATCH 1/9] planner: support parser part for the view hint --- parser/ast/misc.go | 1 + parser/hintparser.go | 619 +++++++++++++++++++++++-------------------- parser/hintparser.y | 39 +++ 3 files changed, 376 insertions(+), 283 deletions(-) diff --git a/parser/ast/misc.go b/parser/ast/misc.go index 0746beac76032..31b53f5824f60 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -3574,6 +3574,7 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("@") } ctx.WriteName(n.QBName.String()) + // TODO: add the restore part for view hint } // Hints without args except query block. switch n.HintName.L { diff --git a/parser/hintparser.go b/parser/hintparser.go index 5fea7fb9a680c..024b047f5416f 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -126,97 +126,97 @@ const ( hintUseToja = 57403 yyhintMaxDepth = 200 - yyhintTabOfs = -192 + yyhintTabOfs = -197 ) var ( yyhintXLAT = map[int]int{ - 41: 0, // ')' (140x) - 57379: 1, // hintAggToCop (132x) - 57396: 2, // hintBCJoin (132x) - 57355: 3, // hintBKA (132x) - 57357: 4, // hintBNL (132x) - 57408: 5, // hintForceIndex (132x) - 57381: 6, // hintHashAgg (132x) - 57359: 7, // hintHashJoin (132x) - 57360: 8, // hintHashJoinBuild (132x) - 57361: 9, // hintHashJoinProbe (132x) - 57386: 10, // hintIgnoreIndex (132x) - 57380: 11, // hintIgnorePlanCache (132x) - 57365: 12, // hintIndexMerge (132x) - 57387: 13, // hintInlHashJoin (132x) - 57388: 14, // hintInlJoin (132x) - 57389: 15, // hintInlMergeJoin (132x) - 57351: 16, // hintJoinFixedOrder (132x) - 57352: 17, // hintJoinOrder (132x) - 57353: 18, // hintJoinPrefix (132x) - 57354: 19, // hintJoinSuffix (132x) - 57410: 20, // hintLeading (132x) - 57407: 21, // hintLimitToCop (132x) - 57375: 22, // hintMaxExecutionTime (132x) - 57390: 23, // hintMemoryQuota (132x) - 57363: 24, // hintMerge (132x) - 57382: 25, // hintMpp1PhaseAgg (132x) - 57383: 26, // hintMpp2PhaseAgg (132x) - 57385: 27, // hintMPPScalarAgg (132x) - 57384: 28, // hintMppTiDBAgg (132x) - 57367: 29, // hintMRR (132x) - 57356: 30, // hintNoBKA (132x) - 57358: 31, // hintNoBNL (132x) - 57412: 32, // hintNoDecorrelate (132x) - 57362: 33, // hintNoHashJoin (132x) - 57369: 34, // hintNoICP (132x) - 57366: 35, // hintNoIndexMerge (132x) - 57364: 36, // hintNoMerge (132x) - 57368: 37, // hintNoMRR (132x) - 57370: 38, // hintNoRangeOptimization (132x) - 57374: 39, // hintNoSemijoin (132x) - 57372: 40, // hintNoSkipScan (132x) - 57391: 41, // hintNoSwapJoinInputs (132x) - 57406: 42, // hintNthPlan (132x) - 57378: 43, // hintQBName (132x) - 57392: 44, // hintQueryType (132x) - 57393: 45, // hintReadConsistentReplica (132x) - 57394: 46, // hintReadFromStorage (132x) - 57377: 47, // hintResourceGroup (132x) - 57373: 48, // hintSemijoin (132x) - 57411: 49, // hintSemiJoinRewrite (132x) - 57376: 50, // hintSetVar (132x) - 57397: 51, // hintShuffleJoin (132x) - 57371: 52, // hintSkipScan (132x) - 57395: 53, // hintSMJoin (132x) - 57409: 54, // hintStraightJoin (132x) - 57398: 55, // hintStreamAgg (132x) - 57399: 56, // hintSwapJoinInputs (132x) - 57404: 57, // hintTimeRange (132x) - 57405: 58, // hintUseCascades (132x) - 57401: 59, // hintUseIndex (132x) - 57400: 60, // hintUseIndexMerge (132x) - 57402: 61, // hintUsePlanCache (132x) - 57403: 62, // hintUseToja (132x) - 44: 63, // ',' (130x) - 57422: 64, // hintDupsWeedOut (110x) - 57423: 65, // hintFirstMatch (110x) - 57424: 66, // hintLooseScan (110x) - 57425: 67, // hintMaterialization (110x) - 57417: 68, // hintTiFlash (110x) - 57416: 69, // hintTiKV (110x) - 57418: 70, // hintFalse (109x) - 57413: 71, // hintOLAP (109x) - 57414: 72, // hintOLTP (109x) - 57419: 73, // hintTrue (109x) - 57421: 74, // hintGB (108x) - 57420: 75, // hintMB (108x) - 57347: 76, // hintIdentifier (107x) - 57349: 77, // hintSingleAtIdentifier (92x) + 41: 0, // ')' (148x) + 57379: 1, // hintAggToCop (135x) + 57396: 2, // hintBCJoin (135x) + 57355: 3, // hintBKA (135x) + 57357: 4, // hintBNL (135x) + 57408: 5, // hintForceIndex (135x) + 57381: 6, // hintHashAgg (135x) + 57359: 7, // hintHashJoin (135x) + 57360: 8, // hintHashJoinBuild (135x) + 57361: 9, // hintHashJoinProbe (135x) + 57386: 10, // hintIgnoreIndex (135x) + 57380: 11, // hintIgnorePlanCache (135x) + 57365: 12, // hintIndexMerge (135x) + 57387: 13, // hintInlHashJoin (135x) + 57388: 14, // hintInlJoin (135x) + 57389: 15, // hintInlMergeJoin (135x) + 57351: 16, // hintJoinFixedOrder (135x) + 57352: 17, // hintJoinOrder (135x) + 57353: 18, // hintJoinPrefix (135x) + 57354: 19, // hintJoinSuffix (135x) + 57410: 20, // hintLeading (135x) + 57407: 21, // hintLimitToCop (135x) + 57375: 22, // hintMaxExecutionTime (135x) + 57390: 23, // hintMemoryQuota (135x) + 57363: 24, // hintMerge (135x) + 57382: 25, // hintMpp1PhaseAgg (135x) + 57383: 26, // hintMpp2PhaseAgg (135x) + 57385: 27, // hintMPPScalarAgg (135x) + 57384: 28, // hintMppTiDBAgg (135x) + 57367: 29, // hintMRR (135x) + 57356: 30, // hintNoBKA (135x) + 57358: 31, // hintNoBNL (135x) + 57412: 32, // hintNoDecorrelate (135x) + 57362: 33, // hintNoHashJoin (135x) + 57369: 34, // hintNoICP (135x) + 57366: 35, // hintNoIndexMerge (135x) + 57364: 36, // hintNoMerge (135x) + 57368: 37, // hintNoMRR (135x) + 57370: 38, // hintNoRangeOptimization (135x) + 57374: 39, // hintNoSemijoin (135x) + 57372: 40, // hintNoSkipScan (135x) + 57391: 41, // hintNoSwapJoinInputs (135x) + 57406: 42, // hintNthPlan (135x) + 57378: 43, // hintQBName (135x) + 57392: 44, // hintQueryType (135x) + 57393: 45, // hintReadConsistentReplica (135x) + 57394: 46, // hintReadFromStorage (135x) + 57377: 47, // hintResourceGroup (135x) + 57373: 48, // hintSemijoin (135x) + 57411: 49, // hintSemiJoinRewrite (135x) + 57376: 50, // hintSetVar (135x) + 57397: 51, // hintShuffleJoin (135x) + 57371: 52, // hintSkipScan (135x) + 57395: 53, // hintSMJoin (135x) + 57409: 54, // hintStraightJoin (135x) + 57398: 55, // hintStreamAgg (135x) + 57399: 56, // hintSwapJoinInputs (135x) + 57404: 57, // hintTimeRange (135x) + 57405: 58, // hintUseCascades (135x) + 57401: 59, // hintUseIndex (135x) + 57400: 60, // hintUseIndexMerge (135x) + 57402: 61, // hintUsePlanCache (135x) + 57403: 62, // hintUseToja (135x) + 44: 63, // ',' (132x) + 57422: 64, // hintDupsWeedOut (112x) + 57423: 65, // hintFirstMatch (112x) + 57424: 66, // hintLooseScan (112x) + 57425: 67, // hintMaterialization (112x) + 57417: 68, // hintTiFlash (112x) + 57416: 69, // hintTiKV (112x) + 57418: 70, // hintFalse (111x) + 57413: 71, // hintOLAP (111x) + 57414: 72, // hintOLTP (111x) + 57419: 73, // hintTrue (111x) + 57421: 74, // hintGB (110x) + 57420: 75, // hintMB (110x) + 57347: 76, // hintIdentifier (109x) + 57349: 77, // hintSingleAtIdentifier (95x) 93: 78, // ']' (86x) - 57415: 79, // hintPartition (80x) - 46: 80, // '.' (76x) + 46: 79, // '.' (85x) + 57415: 80, // hintPartition (80x) 61: 81, // '=' (76x) 40: 82, // '(' (71x) - 57344: 83, // $end (24x) - 57446: 84, // QueryBlockOpt (17x) - 57438: 85, // Identifier (13x) + 57344: 83, // $end (25x) + 57446: 84, // QueryBlockOpt (20x) + 57438: 85, // Identifier (15x) 57346: 86, // hintIntLit (8x) 57350: 87, // hintStringLit (5x) 57428: 88, // CommaOpt (4x) @@ -239,21 +239,23 @@ var ( 57455: 105, // TableOptimizerHintOpt (2x) 57457: 106, // UnsupportedIndexLevelOptimizerHintName (2x) 57458: 107, // UnsupportedTableLevelOptimizerHintName (2x) - 57430: 108, // HintQueryType (1x) - 57433: 109, // HintStorageTypeAndTableList (1x) - 57437: 110, // HintTrueOrFalse (1x) - 57439: 111, // IndexNameList (1x) - 57440: 112, // IndexNameListOpt (1x) - 57443: 113, // OptimizerHintList (1x) - 57444: 114, // PartitionList (1x) - 57447: 115, // Start (1x) - 57450: 116, // SubqueryStrategies (1x) - 57451: 117, // SubqueryStrategiesOpt (1x) - 57456: 118, // UnitOfBytes (1x) - 57459: 119, // Value (1x) - 57426: 120, // $default (0x) - 57345: 121, // error (0x) - 57348: 122, // hintInvalid (0x) + 57460: 108, // ViewName (2x) + 57430: 109, // HintQueryType (1x) + 57433: 110, // HintStorageTypeAndTableList (1x) + 57437: 111, // HintTrueOrFalse (1x) + 57439: 112, // IndexNameList (1x) + 57440: 113, // IndexNameListOpt (1x) + 57443: 114, // OptimizerHintList (1x) + 57444: 115, // PartitionList (1x) + 57447: 116, // Start (1x) + 57450: 117, // SubqueryStrategies (1x) + 57451: 118, // SubqueryStrategiesOpt (1x) + 57456: 119, // UnitOfBytes (1x) + 57459: 120, // Value (1x) + 57461: 121, // ViewNameList (1x) + 57426: 122, // $default (0x) + 57345: 123, // error (0x) + 57348: 124, // hintInvalid (0x) } yyhintSymNames = []string{ @@ -336,8 +338,8 @@ var ( "hintIdentifier", "hintSingleAtIdentifier", "']'", - "hintPartition", "'.'", + "hintPartition", "'='", "'('", "$end", @@ -365,6 +367,7 @@ var ( "TableOptimizerHintOpt", "UnsupportedIndexLevelOptimizerHintName", "UnsupportedTableLevelOptimizerHintName", + "ViewName", "HintQueryType", "HintStorageTypeAndTableList", "HintTrueOrFalse", @@ -377,6 +380,7 @@ var ( "SubqueryStrategiesOpt", "UnitOfBytes", "Value", + "ViewNameList", "$default", "error", "hintInvalid", @@ -384,11 +388,11 @@ var ( yyhintReductions = []struct{ xsym, components int }{ {0, 1}, - {115, 1}, - {113, 1}, - {113, 3}, - {113, 1}, - {113, 3}, + {116, 1}, + {114, 1}, + {114, 3}, + {114, 1}, + {114, 3}, {105, 4}, {105, 4}, {105, 4}, @@ -403,12 +407,13 @@ var ( {105, 4}, {105, 6}, {105, 6}, + {105, 6}, {105, 5}, {105, 4}, {105, 5}, {100, 5}, - {109, 1}, - {109, 3}, + {110, 1}, + {110, 3}, {95, 4}, {84, 0}, {84, 1}, @@ -416,30 +421,34 @@ var ( {88, 1}, {99, 0}, {99, 4}, - {114, 1}, - {114, 3}, + {115, 1}, + {115, 3}, {96, 1}, {96, 1}, {90, 2}, {90, 3}, {89, 3}, {89, 5}, + {121, 3}, + {121, 1}, + {108, 2}, + {108, 1}, {93, 4}, - {112, 0}, + {113, 0}, + {113, 1}, {112, 1}, - {111, 1}, - {111, 3}, - {117, 0}, + {112, 3}, + {118, 0}, + {118, 1}, {117, 1}, - {116, 1}, - {116, 3}, - {119, 1}, + {117, 3}, + {120, 1}, + {120, 1}, + {120, 1}, {119, 1}, {119, 1}, - {118, 1}, - {118, 1}, - {110, 1}, - {110, 1}, + {111, 1}, + {111, 1}, {97, 1}, {97, 1}, {97, 1}, @@ -496,8 +505,8 @@ var ( {98, 1}, {98, 1}, {98, 1}, - {108, 1}, - {108, 1}, + {109, 1}, + {109, 1}, {94, 1}, {94, 1}, {85, 1}, @@ -579,35 +588,35 @@ var ( yyhintXErrors = map[yyhintXError]string{} - yyhintParseTab = [275][]uint16{ + yyhintParseTab = [284][]uint16{ // 0 - {1: 259, 225, 218, 220, 247, 253, 233, 234, 235, 245, 263, 237, 229, 227, 232, 197, 215, 216, 217, 236, 260, 204, 209, 228, 255, 256, 258, 257, 238, 219, 221, 266, 222, 240, 261, 223, 239, 241, 249, 243, 231, 205, 208, 213, 262, 214, 207, 248, 265, 206, 226, 242, 224, 264, 254, 230, 210, 251, 244, 246, 252, 250, 92: 211, 97: 198, 212, 100: 196, 203, 103: 202, 200, 195, 201, 199, 113: 194, 115: 193}, - {83: 192}, - {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 364, 83: 191, 88: 464}, - {1: 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 83: 190}, - {1: 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 83: 188}, + {1: 264, 230, 223, 225, 252, 258, 238, 239, 240, 250, 268, 242, 234, 232, 237, 202, 220, 221, 222, 241, 265, 209, 214, 233, 259, 260, 262, 261, 243, 224, 226, 271, 227, 245, 266, 228, 244, 246, 254, 248, 236, 210, 213, 218, 267, 219, 212, 253, 270, 211, 231, 247, 229, 269, 263, 235, 215, 256, 249, 251, 257, 255, 92: 216, 97: 203, 217, 100: 201, 208, 103: 207, 205, 200, 206, 204, 114: 199, 116: 198}, + {83: 197}, + {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 369, 83: 196, 88: 478}, + {1: 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 195, 83: 195}, + {1: 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 193, 83: 193}, // 5 + {82: 475}, + {82: 472}, + {82: 469}, + {82: 464}, {82: 461}, - {82: 458}, - {82: 455}, - {82: 450}, - {82: 447}, // 10 - {82: 436}, - {82: 424}, - {82: 420}, - {82: 416}, - {82: 408}, + {82: 450}, + {82: 438}, + {82: 434}, + {82: 430}, + {82: 422}, // 15 - {82: 405}, - {82: 402}, + {82: 419}, + {82: 407}, + {82: 400}, {82: 395}, - {82: 390}, - {82: 384}, + {82: 389}, // 20 - {82: 381}, - {82: 375}, - {82: 267}, + {82: 386}, + {82: 380}, + {82: 272}, {82: 135}, {82: 134}, // 25 @@ -671,21 +680,21 @@ var ( {82: 81}, {82: 80}, // 75 - {68: 165, 165, 77: 269, 84: 268}, - {68: 274, 273, 94: 272, 271, 109: 270}, - {164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 78: 164, 164, 86: 164}, - {372, 63: 373}, - {168, 63: 168}, + {68: 169, 169, 77: 274, 84: 273}, + {68: 279, 278, 94: 277, 276, 110: 275}, + {168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 78: 168, 168, 168, 86: 168}, + {377, 63: 378}, + {172, 63: 172}, // 80 - {91: 275}, + {91: 280}, {91: 77}, {91: 76}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 277, 90: 276}, - {63: 370, 78: 369}, + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 282, 90: 281}, + {63: 375, 78: 374}, // 85 - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 279, 89: 278}, - {155, 63: 155, 78: 155}, - {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 165, 165, 356, 84: 355}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 284, 89: 283}, + {159, 63: 159, 78: 159}, + {169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 169, 361, 169, 84: 360}, {75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75}, {74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74}, // 90 @@ -776,140 +785,151 @@ var ( {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 78: 161, 359, 99: 368}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 357}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 78: 165, 80: 364, 99: 373}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 362}, // 165 - {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 165, 165, 84: 358}, - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 78: 161, 359, 99: 360}, - {82: 361}, - {152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 78: 152}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 363, 114: 362}, + {169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 169, 80: 169, 84: 363}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 78: 165, 80: 364, 99: 365}, + {82: 366}, + {156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 78: 156}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 368, 115: 367}, // 170 - {365, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 364, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 88: 366}, - {159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159}, - {162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 64: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 87: 162}, - {160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 78: 160}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 367}, + {370, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 369, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 88: 371}, + {163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163}, + {166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 64: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 87: 166}, + {164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 78: 164}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 372}, // 175 - {158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158}, - {153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 78: 153}, - {166, 63: 166}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 279, 89: 371}, - {154, 63: 154, 78: 154}, + {162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162}, + {157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 78: 157}, + {170, 63: 170}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 284, 89: 376}, + {158, 63: 158, 78: 158}, // 180 - {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 83: 169}, - {68: 274, 273, 94: 272, 374}, - {167, 63: 167}, - {71: 165, 165, 77: 269, 84: 376}, - {71: 378, 379, 108: 377}, + {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 83: 173}, + {68: 279, 278, 94: 277, 379}, + {171, 63: 171}, + {71: 169, 169, 77: 274, 84: 381}, + {71: 383, 384, 109: 382}, // 185 - {380}, + {385}, {79}, {78}, - {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 83: 170}, - {165, 77: 269, 84: 382}, + {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 83: 174}, + {169, 77: 274, 84: 387}, // 190 - {383}, - {1: 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 83: 171}, - {70: 165, 73: 165, 77: 269, 84: 385}, - {70: 388, 73: 387, 110: 386}, - {389}, + {388}, + {1: 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 83: 175}, + {70: 169, 73: 169, 77: 274, 84: 390}, + {70: 393, 73: 392, 111: 391}, + {394}, // 195 {137}, {136}, - {1: 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 83: 172}, - {87: 391}, - {63: 364, 87: 163, 392}, + {1: 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 83: 176}, + {87: 396}, + {63: 369, 87: 167, 397}, // 200 - {87: 393}, - {394}, - {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 83: 173}, - {77: 269, 84: 396, 86: 165}, - {86: 397}, + {87: 398}, + {399}, + {1: 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 83: 177}, + {77: 274, 84: 401, 86: 169}, + {86: 402}, // 205 - {74: 400, 399, 118: 398}, - {401}, + {74: 405, 404, 119: 403}, + {406}, {139}, {138}, - {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 83: 174}, + {1: 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 83: 178}, // 210 - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 403}, - {404}, - {1: 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 83: 175}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 406}, - {407}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 408}, + {409, 63: 410}, + {1: 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 83: 180}, + {169, 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 274, 79: 169, 84: 414, 413, 108: 412, 121: 411}, + {416, 79: 417}, // 215 - {1: 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 83: 176}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 409}, - {81: 410}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 413, 414, 412, 119: 411}, - {415}, + {154, 79: 154}, + {169, 77: 274, 79: 169, 84: 415}, + {152, 79: 152}, + {153, 79: 153}, + {1: 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 83: 179}, // 220 + {169, 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 274, 79: 169, 84: 414, 413, 108: 418}, + {155, 79: 155}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 420}, + {421}, + {1: 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 83: 181}, + // 225 + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 423}, + {81: 424}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 427, 428, 426, 120: 425}, + {429}, {142}, + // 230 {141}, {140}, - {1: 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 83: 177}, - {77: 269, 84: 417, 86: 165}, - // 225 - {86: 418}, - {419}, - {1: 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 83: 178}, - {77: 269, 84: 421, 86: 165}, - {86: 422}, - // 230 - {423}, - {1: 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 83: 179}, - {165, 64: 165, 165, 165, 165, 77: 269, 84: 425}, - {146, 64: 429, 430, 431, 432, 102: 428, 116: 427, 426}, - {435}, + {1: 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 83: 182}, + {77: 274, 84: 431, 86: 169}, + {86: 432}, // 235 - {145, 63: 433}, + {433}, + {1: 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 83: 183}, + {77: 274, 84: 435, 86: 169}, + {86: 436}, + {437}, + // 240 + {1: 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 83: 184}, + {169, 64: 169, 169, 169, 169, 77: 274, 84: 439}, + {146, 64: 443, 444, 445, 446, 102: 442, 117: 441, 440}, + {449}, + {145, 63: 447}, + // 245 {144, 63: 144}, {100, 63: 100}, {99, 63: 99}, {98, 63: 98}, - // 240 {97, 63: 97}, - {64: 429, 430, 431, 432, 102: 434}, + // 250 + {64: 443, 444, 445, 446, 102: 448}, {143, 63: 143}, - {1: 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 83: 180}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 438, 93: 437}, - // 245 - {446}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 279, 89: 439}, - {163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 364, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 88: 440}, - {150, 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 443, 111: 442, 441}, + {1: 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 83: 185}, + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 452, 93: 451}, + {460}, + // 255 + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 284, 89: 453}, + {167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 369, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 88: 454}, + {150, 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 457, 112: 456, 455}, {151}, - // 250 - {149, 63: 444}, + {149, 63: 458}, + // 260 {148, 63: 148}, - {1: 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 445}, + {1: 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 459}, {147, 63: 147}, - {1: 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 83: 181}, - // 255 - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 438, 93: 448}, - {449}, - {1: 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 83: 182}, - {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 453, 90: 452, 96: 451}, - {454}, - // 260 - {157, 63: 370}, - {156, 309, 327, 285, 287, 338, 312, 289, 290, 291, 313, 311, 295, 318, 319, 320, 281, 282, 283, 284, 340, 310, 305, 321, 293, 314, 315, 317, 316, 297, 286, 288, 342, 292, 299, 296, 294, 298, 300, 304, 302, 322, 337, 308, 323, 324, 325, 307, 303, 341, 306, 328, 301, 326, 339, 329, 330, 335, 336, 332, 331, 333, 334, 64: 351, 352, 353, 354, 346, 345, 347, 343, 344, 348, 350, 349, 280, 85: 279, 89: 278}, - {1: 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 83: 183}, - {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 453, 90: 452, 96: 456}, - {457}, + {1: 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 83: 186}, + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 452, 93: 462}, // 265 - {1: 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 83: 184}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 64: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 269, 84: 277, 90: 459}, - {460, 63: 370}, - {1: 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 83: 185}, - {165, 77: 269, 84: 462}, - // 270 {463}, - {1: 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 83: 186}, - {1: 259, 225, 218, 220, 247, 253, 233, 234, 235, 245, 263, 237, 229, 227, 232, 197, 215, 216, 217, 236, 260, 204, 209, 228, 255, 256, 258, 257, 238, 219, 221, 266, 222, 240, 261, 223, 239, 241, 249, 243, 231, 205, 208, 213, 262, 214, 207, 248, 265, 206, 226, 242, 224, 264, 254, 230, 210, 251, 244, 246, 252, 250, 92: 211, 97: 198, 212, 100: 466, 203, 103: 202, 200, 465, 201, 199}, - {1: 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 83: 189}, {1: 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 83: 187}, + {169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 467, 90: 466, 96: 465}, + {468}, + {161, 63: 375}, + // 270 + {160, 314, 332, 290, 292, 343, 317, 294, 295, 296, 322, 316, 300, 323, 324, 325, 286, 287, 288, 289, 345, 315, 310, 326, 298, 318, 319, 321, 320, 302, 291, 293, 347, 297, 304, 301, 299, 303, 305, 309, 307, 327, 342, 313, 328, 329, 330, 312, 308, 346, 311, 333, 306, 331, 344, 334, 335, 340, 341, 337, 336, 338, 339, 64: 356, 357, 358, 359, 351, 350, 352, 348, 349, 353, 355, 354, 285, 85: 284, 89: 283}, + {1: 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 83: 188}, + {169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 467, 90: 466, 96: 470}, + {471}, + {1: 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 83: 189}, + // 275 + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 64: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 274, 84: 282, 90: 473}, + {474, 63: 375}, + {1: 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 83: 190}, + {169, 77: 274, 84: 476}, + {477}, + // 280 + {1: 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 83: 191}, + {1: 264, 230, 223, 225, 252, 258, 238, 239, 240, 250, 268, 242, 234, 232, 237, 202, 220, 221, 222, 241, 265, 209, 214, 233, 259, 260, 262, 261, 243, 224, 226, 271, 227, 245, 266, 228, 244, 246, 254, 248, 236, 210, 213, 218, 267, 219, 212, 253, 270, 211, 231, 247, 229, 269, 263, 235, 215, 256, 249, 251, 257, 255, 92: 216, 97: 203, 217, 100: 480, 208, 103: 207, 205, 479, 206, 204}, + {1: 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 83: 194}, + {1: 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 83: 192}, } ) @@ -949,7 +969,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) { } func yyhintParse(yylex yyhintLexer, parser *hintParser) int { - const yyError = 121 + const yyError = 123 yyEx, _ := yylex.(yyhintLexerEx) var yyn int @@ -1226,6 +1246,14 @@ yynewstate: } } case 18: + { + parser.yyVAL.hint = &ast.TableOptimizerHint{ + HintName: model.NewCIStr(yyS[yypt-5].ident), + QBName: model.NewCIStr(yyS[yypt-3].ident), + Tables: yyS[yypt-1].hint, + } + } + case 19: { maxValue := uint64(math.MaxInt64) / yyS[yypt-1].number if yyS[yypt-2].number <= maxValue { @@ -1240,7 +1268,7 @@ yynewstate: parser.yyVAL.hint = nil } } - case 19: + case 20: { parser.yyVAL.hint = &ast.TableOptimizerHint{ HintName: model.NewCIStr(yyS[yypt-5].ident), @@ -1250,21 +1278,21 @@ yynewstate: }, } } - case 20: + case 21: { h := yyS[yypt-1].hint h.HintName = model.NewCIStr(yyS[yypt-4].ident) h.QBName = model.NewCIStr(yyS[yypt-2].ident) parser.yyVAL.hint = h } - case 21: + case 22: { parser.yyVAL.hint = &ast.TableOptimizerHint{ HintName: model.NewCIStr(yyS[yypt-3].ident), QBName: model.NewCIStr(yyS[yypt-1].ident), } } - case 22: + case 23: { parser.yyVAL.hint = &ast.TableOptimizerHint{ HintName: model.NewCIStr(yyS[yypt-4].ident), @@ -1272,7 +1300,7 @@ yynewstate: HintData: model.NewCIStr(yyS[yypt-1].ident), } } - case 23: + case 24: { hs := yyS[yypt-1].hints name := model.NewCIStr(yyS[yypt-4].ident) @@ -1283,60 +1311,60 @@ yynewstate: } parser.yyVAL.hints = hs } - case 24: + case 25: { parser.yyVAL.hints = []*ast.TableOptimizerHint{yyS[yypt-0].hint} } - case 25: + case 26: { parser.yyVAL.hints = append(yyS[yypt-2].hints, yyS[yypt-0].hint) } - case 26: + case 27: { h := yyS[yypt-1].hint h.HintData = model.NewCIStr(yyS[yypt-3].ident) parser.yyVAL.hint = h } - case 27: + case 28: { parser.yyVAL.ident = "" } - case 31: + case 32: { parser.yyVAL.modelIdents = nil } - case 32: + case 33: { parser.yyVAL.modelIdents = yyS[yypt-1].modelIdents } - case 33: + case 34: { parser.yyVAL.modelIdents = []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)} } - case 34: + case 35: { parser.yyVAL.modelIdents = append(yyS[yypt-2].modelIdents, model.NewCIStr(yyS[yypt-0].ident)) } - case 36: + case 37: { parser.yyVAL.hint = &ast.TableOptimizerHint{ QBName: model.NewCIStr(yyS[yypt-0].ident), } } - case 37: + case 38: { parser.yyVAL.hint = &ast.TableOptimizerHint{ Tables: []ast.HintTable{yyS[yypt-0].table}, QBName: model.NewCIStr(yyS[yypt-1].ident), } } - case 38: + case 39: { h := yyS[yypt-2].hint h.Tables = append(h.Tables, yyS[yypt-0].table) parser.yyVAL.hint = h } - case 39: + case 40: { parser.yyVAL.table = ast.HintTable{ TableName: model.NewCIStr(yyS[yypt-2].ident), @@ -1344,7 +1372,7 @@ yynewstate: PartitionList: yyS[yypt-0].modelIdents, } } - case 40: + case 41: { parser.yyVAL.table = ast.HintTable{ DBName: model.NewCIStr(yyS[yypt-4].ident), @@ -1353,46 +1381,71 @@ yynewstate: PartitionList: yyS[yypt-0].modelIdents, } } - case 41: + case 42: + { + h := yyS[yypt-2].hint + h.Tables = append(h.Tables, yyS[yypt-0].table) + parser.yyVAL.hint = h + } + case 43: + { + parser.yyVAL.hint = &ast.TableOptimizerHint{ + Tables: []ast.HintTable{yyS[yypt-0].table}, + } + } + case 44: + { + parser.yyVAL.table = ast.HintTable{ + TableName: model.NewCIStr(yyS[yypt-1].ident), + QBName: model.NewCIStr(yyS[yypt-0].ident), + } + } + case 45: + { + parser.yyVAL.table = ast.HintTable{ + QBName: model.NewCIStr(yyS[yypt-0].ident), + } + } + case 46: { h := yyS[yypt-0].hint h.Tables = []ast.HintTable{yyS[yypt-2].table} h.QBName = model.NewCIStr(yyS[yypt-3].ident) parser.yyVAL.hint = h } - case 42: + case 47: { parser.yyVAL.hint = &ast.TableOptimizerHint{} } - case 44: + case 49: { parser.yyVAL.hint = &ast.TableOptimizerHint{ Indexes: []model.CIStr{model.NewCIStr(yyS[yypt-0].ident)}, } } - case 45: + case 50: { h := yyS[yypt-2].hint h.Indexes = append(h.Indexes, model.NewCIStr(yyS[yypt-0].ident)) parser.yyVAL.hint = h } - case 52: + case 57: { parser.yyVAL.ident = strconv.FormatUint(yyS[yypt-0].number, 10) } - case 53: + case 58: { parser.yyVAL.number = 1024 * 1024 } - case 54: + case 59: { parser.yyVAL.number = 1024 * 1024 * 1024 } - case 55: + case 60: { parser.yyVAL.hint = &ast.TableOptimizerHint{HintData: true} } - case 56: + case 61: { parser.yyVAL.hint = &ast.TableOptimizerHint{HintData: false} } diff --git a/parser/hintparser.y b/parser/hintparser.y index 7dc5735a6f6b9..319d372f367b4 100644 --- a/parser/hintparser.y +++ b/parser/hintparser.y @@ -164,6 +164,7 @@ import ( HintIndexList "table name with index list in optimizer hint" IndexNameList "index list in optimizer hint" IndexNameListOpt "optional index list in optimizer hint" + ViewNameList "view name list in optimizer hint" SubqueryStrategies "subquery strategies" SubqueryStrategiesOpt "optional subquery strategies" HintTrueOrFalse "true or false in optimizer hint" @@ -171,6 +172,7 @@ import ( %type HintTable "Table in optimizer hint" + ViewName "View name in optimizer hint" %type PartitionList "partition name list in optimizer hint" @@ -287,6 +289,14 @@ TableOptimizerHintOpt: QBName: model.NewCIStr($3), } } +| "QB_NAME" '(' Identifier ',' ViewNameList ')' + { + $$ = &ast.TableOptimizerHint{ + HintName: model.NewCIStr($1), + QBName: model.NewCIStr($3), + Tables: $5, + } + } | "MEMORY_QUOTA" '(' QueryBlockOpt hintIntLit UnitOfBytes ')' { maxValue := uint64(math.MaxInt64) / $5 @@ -449,6 +459,35 @@ HintTable: } } +ViewNameList: + ViewNameList '.' ViewName + { + h := $1 + h.Tables = append(h.Tables, $3) + $$ = h + } +| ViewName + { + $$ = &ast.TableOptimizerHint{ + Tables: []ast.HintTable{$1}, + } + } + +ViewName: + Identifier QueryBlockOpt + { + $$ = ast.HintTable{ + TableName: model.NewCIStr($1), + QBName: model.NewCIStr($2), + } + } +| QueryBlockOpt + { + $$ = ast.HintTable{ + QBName: model.NewCIStr($1), + } + } + /** * HintIndexList: * From fee847f2f30c5c6c90e0f6e782145ae4fc17daaf Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Thu, 20 Oct 2022 16:14:19 +0800 Subject: [PATCH 2/9] planner: support planner part for the view hint --- executor/infoschema_reader.go | 2 +- executor/show.go | 2 +- planner/core/logical_plan_builder.go | 71 ++++++++++++++++++++++++++- util/hint/hint_processor.go | 73 +++++++++++++++++++++++++++- 4 files changed, 143 insertions(+), 5 deletions(-) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index 0f33a34e269e9..5ca23110bd800 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -794,7 +794,7 @@ func (e *hugeMemTableRetriever) dataForColumnsInTable(ctx context.Context, sctx if err := runWithSystemSession(internalCtx, sctx, func(s sessionctx.Context) error { planBuilder, _ := plannercore.NewPlanBuilder().Init(s, is, &hint.BlockHintProcessor{}) var err error - viewLogicalPlan, err = planBuilder.BuildDataSourceFromView(ctx, schema.Name, tbl) + viewLogicalPlan, err = planBuilder.BuildDataSourceFromView(ctx, schema.Name, tbl, nil, nil) return errors.Trace(err) }); err != nil { sctx.GetSessionVars().StmtCtx.AppendWarning(err) diff --git a/executor/show.go b/executor/show.go index bd0f779f488ee..fc78fb85364a4 100644 --- a/executor/show.go +++ b/executor/show.go @@ -2051,7 +2051,7 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info // Retrieve view columns info. planBuilder, _ := plannercore.NewPlanBuilder( plannercore.PlanBuilderOptNoExecution{}).Init(s, is, &hint.BlockHintProcessor{}) - if viewLogicalPlan, err := planBuilder.BuildDataSourceFromView(ctx, dbName, tbl); err == nil { + if viewLogicalPlan, err := planBuilder.BuildDataSourceFromView(ctx, dbName, tbl, nil, nil); err == nil { viewSchema := viewLogicalPlan.Schema() viewOutputNames := viewLogicalPlan.OutputNames() for _, col := range tbl.Columns { diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 9f9e883a3551e..c7642b91e012d 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -59,6 +59,7 @@ import ( "github.com/pingcap/tidb/util/collate" "github.com/pingcap/tidb/util/dbterror" "github.com/pingcap/tidb/util/hack" + "github.com/pingcap/tidb/util/hint" "github.com/pingcap/tidb/util/logutil" "github.com/pingcap/tidb/util/mathutil" "github.com/pingcap/tidb/util/plancodec" @@ -4419,7 +4420,30 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as if tn.TableSample != nil { return nil, expression.ErrInvalidTableSample.GenWithStackByArgs("Unsupported TABLESAMPLE in views") } - return b.BuildDataSourceFromView(ctx, dbName, tableInfo) + + // Get the hint belong to the view. + currentQBNameMap4View := make(map[string][]ast.HintTable) + currentViewHints := make(map[string][]*ast.TableOptimizerHint) + for qbName, viewQBNameHintTable := range b.hintProcessor.QbNameMap4View { + if len(viewQBNameHintTable) == 0 { + // TODO: need to check whether this will happen(maybe in the recursion) + continue + } + // TODO: can not handle the different DB. + if viewQBNameHintTable[0].QBName.L == "" { + // TODO: need to check if we do not explicit set the qbName. Is it empty or use the 'sel_1' as the default value. + continue + } + viewSelectOffset := b.getSelectOffset() + viewHintSelectOffset := b.hintProcessor.GetHintOffset(viewQBNameHintTable[0].QBName, viewSelectOffset) + if viewQBNameHintTable[0].TableName.L == tableInfo.Name.L && viewHintSelectOffset == viewSelectOffset { + currentQBNameMap4View[qbName] = viewQBNameHintTable + currentViewHints[qbName] = b.hintProcessor.QbHints4View[qbName] + delete(b.hintProcessor.QbNameMap4View, qbName) + delete(b.hintProcessor.QbHints4View, qbName) + } + } + return b.BuildDataSourceFromView(ctx, dbName, tableInfo, currentQBNameMap4View, currentViewHints) } if tableInfo.IsSequence() { @@ -4949,7 +4973,7 @@ func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIS } // BuildDataSourceFromView is used to build LogicalPlan from view -func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo) (LogicalPlan, error) { +func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo, QbNameMap4View map[string][]ast.HintTable, ViewHints map[string][]*ast.TableOptimizerHint) (LogicalPlan, error) { viewDepth := b.ctx.GetSessionVars().StmtCtx.ViewDepth b.ctx.GetSessionVars().StmtCtx.ViewDepth++ deferFunc, err := b.checkRecursiveView(dbName, tableInfo.Name) @@ -4984,6 +5008,49 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. b.buildingCTE = o }() + hintProcessor := &hint.BlockHintProcessor{Ctx: b.ctx} + // TODO: need to check whether the selectOffset has already been set. Is necessary to use the 'Accept' function here. + selectNode.Accept(hintProcessor) + currentQbNameMap4View := make(map[string][]ast.HintTable) + currentQbHints4View := make(map[string][]*ast.TableOptimizerHint) + currentQbHints := make(map[int][]*ast.TableOptimizerHint) + currentQbNameMap := make(map[string]int) + + for qbName, viewQbNameHint := range QbNameMap4View { + selectOffset := -1 + viewQbNameHint = viewQbNameHint[1:] + QbNameMap4View[qbName] = viewQbNameHint + if len(viewQbNameHint) == 0 { + selectOffset = 1 + } else if len(viewQbNameHint) == 1 && viewQbNameHint[0].TableName.L == "" { + selectOffset = hintProcessor.GetHintOffset(viewQbNameHint[0].QBName, -1) + } else { + currentQbNameMap4View[qbName] = viewQbNameHint + currentQbHints4View[qbName] = ViewHints[qbName] + } + + if selectOffset != -1 { + currentQbHints[selectOffset] = ViewHints[qbName] + currentQbNameMap[qbName] = selectOffset + + delete(QbNameMap4View, qbName) + delete(ViewHints, qbName) + } + } + + hintProcessor.QbNameMap4View = QbNameMap4View + hintProcessor.QbHints4View = ViewHints + hintProcessor.QbHints = currentQbHints + hintProcessor.QbNameMap = currentQbNameMap + + originHintProcessor := b.hintProcessor + originPlannerSelectBlockAsName := b.ctx.GetSessionVars().PlannerSelectBlockAsName + b.hintProcessor = hintProcessor + b.ctx.GetSessionVars().PlannerSelectBlockAsName = make([]ast.HintTable, hintProcessor.MaxSelectStmtOffset()+1) + defer func() { + b.hintProcessor = originHintProcessor + b.ctx.GetSessionVars().PlannerSelectBlockAsName = originPlannerSelectBlockAsName + }() selectLogicalPlan, err := b.Build(ctx, selectNode) if err != nil { if terror.ErrorNotEqual(err, ErrViewRecursive) && diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index ce61936aa1cf7..71f10a05de886 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -314,8 +314,10 @@ func extractHintWarns(warns []error) []error { // BlockHintProcessor processes hints at different level of sql statement. type BlockHintProcessor struct { - QbNameMap map[string]int // Map from query block name to select stmt offset. + QbNameMap map[string]int // Map from query block name to select stmt offset. + QbNameMap4View map[string][]ast.HintTable QbHints map[int][]*ast.TableOptimizerHint // Group all hints at same query block. + QbHints4View map[string][]*ast.TableOptimizerHint Ctx sessionctx.Context selectStmtOffset int } @@ -334,8 +336,15 @@ func (p *BlockHintProcessor) Enter(in ast.Node) (ast.Node, bool) { p.checkQueryBlockHints(node.TableHints, 0) case *ast.SelectStmt: p.selectStmtOffset++ + // Only support view hints which appear in the outer select part + if p.selectStmtOffset == 1 { + // Handle the view hints and update the left hint. + node.TableHints = p.handleViewHints(node.TableHints) + } node.QueryBlockOffset = p.selectStmtOffset p.checkQueryBlockHints(node.TableHints, node.QueryBlockOffset) + case *ast.ExplainStmt: + return in, true } return in, false } @@ -377,6 +386,68 @@ func (p *BlockHintProcessor) checkQueryBlockHints(hints []*ast.TableOptimizerHin } } +func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (leftHints []*ast.TableOptimizerHint) { + if len(hints) == 0 { + return + } + + usedHints := make([]bool, len(hints)) + // handle the query block name hints for view + for i, hint := range hints { + if hint.HintName.L != hintQBName || len(hint.Tables) == 0 { + continue + } + usedHints[i] = true + // TODO: need to check whether the qbName can be empty + if p.QbNameMap4View == nil { + p.QbNameMap4View = make(map[string][]ast.HintTable) + } + qbName := hint.QBName.L + if _, ok := p.QbNameMap4View[qbName]; ok { + if p.Ctx != nil { + p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Duplicate query block name %s for view's query block hint, only the first one is effective", qbName)) + } + } else { + p.QbNameMap4View[qbName] = hint.Tables + } + } + + // handle the view hints + for i, hint := range hints { + if usedHints[i] || hint.HintName.L == hintQBName { + continue + } + + ok := false + qbName := hint.QBName.L + if qbName != "" { + // xx_agg(@qb_name) + _, ok = p.QbNameMap4View[qbName] + } else { + if len(hint.Tables) == 1 { + // TODO: only support one table in view hints. Need to check what happened if there are more table name appear in one hint + qbName = hint.Tables[0].QBName.L + _, ok = p.QbNameMap4View[qbName] + } + } + + if ok { + if p.QbHints4View == nil { + p.QbHints4View = make(map[string][]*ast.TableOptimizerHint) + } + usedHints[i] = true + p.QbHints4View[qbName] = append(p.QbHints4View[qbName], hint) + } + } + + for i, hint := range hints { + if !usedHints[i] { + leftHints = append(leftHints, hint) + } + } + return +} + const ( defaultUpdateBlockName = "upd_1" defaultDeleteBlockName = "del_1" From ea233a356dfde14ca916cdf85bd71c2b82ca52cb Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Thu, 20 Oct 2022 19:40:47 +0800 Subject: [PATCH 3/9] add a test case --- parser/hintparser.go | 2 +- parser/hintparser.y | 2 +- planner/core/integration_test.go | 34 ++++++++ .../core/testdata/integration_suite_in.json | 10 +++ .../core/testdata/integration_suite_out.json | 84 +++++++++++++++++++ 5 files changed, 130 insertions(+), 2 deletions(-) diff --git a/parser/hintparser.go b/parser/hintparser.go index 024b047f5416f..3103423c0b6aa 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -1250,7 +1250,7 @@ yynewstate: parser.yyVAL.hint = &ast.TableOptimizerHint{ HintName: model.NewCIStr(yyS[yypt-5].ident), QBName: model.NewCIStr(yyS[yypt-3].ident), - Tables: yyS[yypt-1].hint, + Tables: yyS[yypt-1].hint.Tables, } } case 19: diff --git a/parser/hintparser.y b/parser/hintparser.y index 319d372f367b4..f348284eca1c0 100644 --- a/parser/hintparser.y +++ b/parser/hintparser.y @@ -294,7 +294,7 @@ TableOptimizerHintOpt: $$ = &ast.TableOptimizerHint{ HintName: model.NewCIStr($1), QBName: model.NewCIStr($3), - Tables: $5, + Tables: $5.Tables, } } | "MEMORY_QUOTA" '(' QueryBlockOpt hintIntLit UnitOfBytes ')' diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 911bedace451e..657244028e7b8 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1306,6 +1306,40 @@ func TestReadFromStorageHint(t *testing.T) { } } +func TestViewHint(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop view if exists v, v1") + tk.MustExec("drop table if exists t, t1, t2") + tk.MustExec("create table t(a int, b int);") + tk.MustExec("create table t1(a int, b int);") + tk.MustExec("create table t2(a int, b int);") + tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 on t1.b=t2.b group by t2.a) tt on t.a = tt.a;") + tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;") + tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;") + + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.LoadTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) + }) + res := tk.MustQuery(tt) + res.Check(testkit.Rows(output[i].Plan...)) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) + } +} + func TestReadFromStorageHintAndIsolationRead(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 940c67c7f0f47..30a21636539e4 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -653,6 +653,16 @@ "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt" ] }, + { + "name": "TestViewHint", + "cases": [ + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), stream_agg(@qb_v_2) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1 .@sel_1), merge_join(t1@qb_v_2) */ * from v;" + + ] + }, { "name": "TestReadFromStorageHintAndIsolationRead", "cases": [ diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 4ffc80ce82787..a24acff2f8cd4 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4328,6 +4328,90 @@ } ] }, + { + "Name": "TestViewHint", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", + "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", + "│ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", + "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", + "│ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), stream_agg(@qb_v_2) */ * from v;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", + "│ └─Sort 12487.50 root test.t2.a", + "│ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1 .@sel_1), merge_join(t1@qb_v_2) */ * from v;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", + "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", + "│ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" + ] + } + ] + }, { "Name": "TestReadFromStorageHintAndIsolationRead", "Cases": [ From a4f53ab3b2517012d4d31275fe17979aa4f02f4a Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Wed, 26 Oct 2022 16:01:46 +0800 Subject: [PATCH 4/9] add more test cases --- .../core/testdata/integration_suite_in.json | 18 +- .../core/testdata/integration_suite_out.json | 372 ++++++++++++++++-- 2 files changed, 357 insertions(+), 33 deletions(-) diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 30a21636539e4..4ab4f562987f1 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -656,11 +656,23 @@ { "name": "TestViewHint", "cases": [ + // Hint for view v "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v;", - "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", - "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), stream_agg(@qb_v_2) */ * from v;", - "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1 .@sel_1), merge_join(t1@qb_v_2) */ * from v;" + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v2;", + // Hint for view v1 + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;", + + // Hint for view v2 + "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2), stream_agg(@qb_v2_2), qb_name(qb_v2_1, v1@sel_1 .@sel_1), merge_join(t@qb_v2_1) */ * from v2;" ] }, { diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index a24acff2f8cd4..bd871483f5cf6 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4352,15 +4352,185 @@ "Warn": null }, { - "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v;", "Plan": [ "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", - "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", - "│ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", - "│ ├─Sort(Build) 9990.00 root test.t2.b", - "│ │ └─TableReader 9990.00 root data:Selection", - "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", - "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", + "│ └─Sort 12487.50 root test.t2.a", + "│ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#17)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#17", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#16)]", + "│ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#16", + "│ │ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#17)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#17", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t.b)]", + "│ ├─MergeJoin(Build) 9980.01 root inner join, left key:test.t.a, right key:Column#16", + "│ │ ├─Sort(Build) 7992.00 root Column#16", + "│ │ │ └─StreamAgg 7992.00 root group by:test.t2.a, funcs:count(1)->Column#16", + "│ │ │ └─Sort 12487.50 root test.t2.a", + "│ │ │ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─Sort(Probe) 9980.01 root test.t.a", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]", + "│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t.b)]", + "│ │ ├─MergeJoin(Build) 9980.01 root inner join, left key:test.t.a, right key:Column#22", + "│ │ │ ├─Sort(Build) 7992.00 root Column#22", + "│ │ │ │ └─StreamAgg 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ │ └─Sort 12487.50 root test.t2.a", + "│ │ │ │ └─MergeJoin 12487.50 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ │ ├─Sort(Build) 9990.00 root test.t2.b", + "│ │ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9980.01 root test.t.a", + "│ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#17)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#17", + "│ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b", + "│ ├─Sort(Build) 9980.01 root test.t.b", + "│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#16)]", + "│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#16", + "│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", "│ └─Sort(Probe) 9990.00 root test.t1.b", "│ └─TableReader 9990.00 root data:Selection", "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", @@ -4372,15 +4542,64 @@ "Warn": null }, { - "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), stream_agg(@qb_v_2) */ * from v;", - "Plan": [ - "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", - "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", - "│ └─Sort 12487.50 root test.t2.a", - "│ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", - "│ ├─TableReader(Build) 9990.00 root data:Selection", - "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", - "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v1;", + "Plan": [ + "MergeJoin 9980.01 root inner join, left key:test.t.a, right key:Column#17", + "├─Sort(Build) 7984.01 root Column#17", + "│ └─StreamAgg 7984.01 root group by:test.t.a, funcs:count(1)->Column#17", + "│ └─Sort 12475.01 root test.t.a", + "│ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b", + "│ ├─Sort(Build) 9980.01 root test.t.b", + "│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#16)]", + "│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#16", + "│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─Sort(Probe) 9990.00 root test.t.a", + " └─TableReader 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]", + "│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", "│ └─TableReader(Probe) 9990.00 root data:Selection", "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", @@ -4391,24 +4610,117 @@ "Warn": null }, { - "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1 .@sel_1), merge_join(t1@qb_v_2) */ * from v;", - "Plan": [ - "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#10)]", - "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#10", - "│ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", - "│ ├─TableReader(Build) 9990.00 root data:Selection", - "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", - "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - "│ └─TableReader(Probe) 9990.00 root data:Selection", - "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", - "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), merge_join(t1@qb_v1_2), stream_agg(@qb_v1_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t@qb_v1_1) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]", + "│ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", "└─TableReader(Probe) 9990.00 root data:Selection", " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" - ] + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b", + "│ ├─Sort(Build) 9980.01 root test.t.b", + "│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]", + "│ │ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2), stream_agg(@qb_v2_2), qb_name(qb_v2_1, v1@sel_1 .@sel_1), merge_join(t@qb_v2_1) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#24)]", + "├─StreamAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#24", + "│ └─Sort 12475.01 root test.t.a", + "│ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b", + "│ ├─Sort(Build) 9980.01 root test.t.b", + "│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#23)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#23", + "│ │ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#22)]", + "│ │ │ ├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#22", + "│ │ │ │ └─HashJoin 12487.50 root inner join, equal:[eq(test.t1.b, test.t2.b)]", + "│ │ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t2.b))", + "│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null } ] }, From 5c52844bbf968b5b9760353ca5edae0077cc9709 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Fri, 4 Nov 2022 16:28:28 +0800 Subject: [PATCH 5/9] add test cases for view hint scope --- parser/hintparser.go | 530 ++++++------ planner/core/integration_test.go | 35 + planner/core/logical_plan_builder.go | 13 +- .../core/testdata/integration_suite_in.json | 45 + .../core/testdata/integration_suite_out.json | 796 ++++++++++++++++++ util/hint/hint_processor.go | 13 +- 6 files changed, 1169 insertions(+), 263 deletions(-) diff --git a/parser/hintparser.go b/parser/hintparser.go index 608e4db9f8c58..1b14e7d292e1e 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -124,95 +124,95 @@ const ( hintUseToja = 57401 yyhintMaxDepth = 200 - yyhintTabOfs = -188 + yyhintTabOfs = -193 ) var ( yyhintXLAT = map[int]int{ - 41: 0, // ')' (138x) - 57379: 1, // hintAggToCop (130x) - 57394: 2, // hintBCJoin (130x) - 57355: 3, // hintBKA (130x) - 57357: 4, // hintBNL (130x) - 57406: 5, // hintForceIndex (130x) - 57381: 6, // hintHashAgg (130x) - 57359: 7, // hintHashJoin (130x) - 57360: 8, // hintHashJoinBuild (130x) - 57361: 9, // hintHashJoinProbe (130x) - 57384: 10, // hintIgnoreIndex (130x) - 57380: 11, // hintIgnorePlanCache (130x) - 57365: 12, // hintIndexMerge (130x) - 57385: 13, // hintInlHashJoin (130x) - 57386: 14, // hintInlJoin (130x) - 57387: 15, // hintInlMergeJoin (130x) - 57351: 16, // hintJoinFixedOrder (130x) - 57352: 17, // hintJoinOrder (130x) - 57353: 18, // hintJoinPrefix (130x) - 57354: 19, // hintJoinSuffix (130x) - 57408: 20, // hintLeading (130x) - 57405: 21, // hintLimitToCop (130x) - 57375: 22, // hintMaxExecutionTime (130x) - 57388: 23, // hintMemoryQuota (130x) - 57363: 24, // hintMerge (130x) - 57382: 25, // hintMpp1PhaseAgg (130x) - 57383: 26, // hintMpp2PhaseAgg (130x) - 57367: 27, // hintMRR (130x) - 57356: 28, // hintNoBKA (130x) - 57358: 29, // hintNoBNL (130x) - 57410: 30, // hintNoDecorrelate (130x) - 57362: 31, // hintNoHashJoin (130x) - 57369: 32, // hintNoICP (130x) - 57366: 33, // hintNoIndexMerge (130x) - 57364: 34, // hintNoMerge (130x) - 57368: 35, // hintNoMRR (130x) - 57370: 36, // hintNoRangeOptimization (130x) - 57374: 37, // hintNoSemijoin (130x) - 57372: 38, // hintNoSkipScan (130x) - 57389: 39, // hintNoSwapJoinInputs (130x) - 57404: 40, // hintNthPlan (130x) - 57378: 41, // hintQBName (130x) - 57390: 42, // hintQueryType (130x) - 57391: 43, // hintReadConsistentReplica (130x) - 57392: 44, // hintReadFromStorage (130x) - 57377: 45, // hintResourceGroup (130x) - 57373: 46, // hintSemijoin (130x) - 57409: 47, // hintSemiJoinRewrite (130x) - 57376: 48, // hintSetVar (130x) - 57395: 49, // hintShuffleJoin (130x) - 57371: 50, // hintSkipScan (130x) - 57393: 51, // hintSMJoin (130x) - 57407: 52, // hintStraightJoin (130x) - 57396: 53, // hintStreamAgg (130x) - 57397: 54, // hintSwapJoinInputs (130x) - 57402: 55, // hintTimeRange (130x) - 57403: 56, // hintUseCascades (130x) - 57399: 57, // hintUseIndex (130x) - 57398: 58, // hintUseIndexMerge (130x) - 57400: 59, // hintUsePlanCache (130x) - 57401: 60, // hintUseToja (130x) - 44: 61, // ',' (128x) - 57420: 62, // hintDupsWeedOut (108x) - 57421: 63, // hintFirstMatch (108x) - 57422: 64, // hintLooseScan (108x) - 57423: 65, // hintMaterialization (108x) - 57415: 66, // hintTiFlash (108x) - 57414: 67, // hintTiKV (108x) - 57416: 68, // hintFalse (107x) - 57411: 69, // hintOLAP (107x) - 57412: 70, // hintOLTP (107x) - 57417: 71, // hintTrue (107x) - 57419: 72, // hintGB (106x) - 57418: 73, // hintMB (106x) - 57347: 74, // hintIdentifier (105x) - 57349: 75, // hintSingleAtIdentifier (90x) + 41: 0, // ')' (146x) + 57379: 1, // hintAggToCop (133x) + 57394: 2, // hintBCJoin (133x) + 57355: 3, // hintBKA (133x) + 57357: 4, // hintBNL (133x) + 57406: 5, // hintForceIndex (133x) + 57381: 6, // hintHashAgg (133x) + 57359: 7, // hintHashJoin (133x) + 57360: 8, // hintHashJoinBuild (133x) + 57361: 9, // hintHashJoinProbe (133x) + 57384: 10, // hintIgnoreIndex (133x) + 57380: 11, // hintIgnorePlanCache (133x) + 57365: 12, // hintIndexMerge (133x) + 57385: 13, // hintInlHashJoin (133x) + 57386: 14, // hintInlJoin (133x) + 57387: 15, // hintInlMergeJoin (133x) + 57351: 16, // hintJoinFixedOrder (133x) + 57352: 17, // hintJoinOrder (133x) + 57353: 18, // hintJoinPrefix (133x) + 57354: 19, // hintJoinSuffix (133x) + 57408: 20, // hintLeading (133x) + 57405: 21, // hintLimitToCop (133x) + 57375: 22, // hintMaxExecutionTime (133x) + 57388: 23, // hintMemoryQuota (133x) + 57363: 24, // hintMerge (133x) + 57382: 25, // hintMpp1PhaseAgg (133x) + 57383: 26, // hintMpp2PhaseAgg (133x) + 57367: 27, // hintMRR (133x) + 57356: 28, // hintNoBKA (133x) + 57358: 29, // hintNoBNL (133x) + 57410: 30, // hintNoDecorrelate (133x) + 57362: 31, // hintNoHashJoin (133x) + 57369: 32, // hintNoICP (133x) + 57366: 33, // hintNoIndexMerge (133x) + 57364: 34, // hintNoMerge (133x) + 57368: 35, // hintNoMRR (133x) + 57370: 36, // hintNoRangeOptimization (133x) + 57374: 37, // hintNoSemijoin (133x) + 57372: 38, // hintNoSkipScan (133x) + 57389: 39, // hintNoSwapJoinInputs (133x) + 57404: 40, // hintNthPlan (133x) + 57378: 41, // hintQBName (133x) + 57390: 42, // hintQueryType (133x) + 57391: 43, // hintReadConsistentReplica (133x) + 57392: 44, // hintReadFromStorage (133x) + 57377: 45, // hintResourceGroup (133x) + 57373: 46, // hintSemijoin (133x) + 57409: 47, // hintSemiJoinRewrite (133x) + 57376: 48, // hintSetVar (133x) + 57395: 49, // hintShuffleJoin (133x) + 57371: 50, // hintSkipScan (133x) + 57393: 51, // hintSMJoin (133x) + 57407: 52, // hintStraightJoin (133x) + 57396: 53, // hintStreamAgg (133x) + 57397: 54, // hintSwapJoinInputs (133x) + 57402: 55, // hintTimeRange (133x) + 57403: 56, // hintUseCascades (133x) + 57399: 57, // hintUseIndex (133x) + 57398: 58, // hintUseIndexMerge (133x) + 57400: 59, // hintUsePlanCache (133x) + 57401: 60, // hintUseToja (133x) + 44: 61, // ',' (130x) + 57420: 62, // hintDupsWeedOut (110x) + 57421: 63, // hintFirstMatch (110x) + 57422: 64, // hintLooseScan (110x) + 57423: 65, // hintMaterialization (110x) + 57415: 66, // hintTiFlash (110x) + 57414: 67, // hintTiKV (110x) + 57416: 68, // hintFalse (109x) + 57411: 69, // hintOLAP (109x) + 57412: 70, // hintOLTP (109x) + 57417: 71, // hintTrue (109x) + 57419: 72, // hintGB (108x) + 57418: 73, // hintMB (108x) + 57347: 74, // hintIdentifier (107x) + 57349: 75, // hintSingleAtIdentifier (93x) 93: 76, // ']' (84x) - 57413: 77, // hintPartition (78x) - 46: 78, // '.' (74x) + 46: 77, // '.' (83x) + 57413: 78, // hintPartition (78x) 61: 79, // '=' (74x) 40: 80, // '(' (69x) - 57344: 81, // $end (24x) - 57444: 82, // QueryBlockOpt (17x) - 57436: 83, // Identifier (13x) + 57344: 81, // $end (25x) + 57444: 82, // QueryBlockOpt (20x) + 57436: 83, // Identifier (15x) 57346: 84, // hintIntLit (8x) 57350: 85, // hintStringLit (5x) 57426: 86, // CommaOpt (4x) @@ -235,21 +235,23 @@ var ( 57453: 103, // TableOptimizerHintOpt (2x) 57455: 104, // UnsupportedIndexLevelOptimizerHintName (2x) 57456: 105, // UnsupportedTableLevelOptimizerHintName (2x) - 57428: 106, // HintQueryType (1x) - 57431: 107, // HintStorageTypeAndTableList (1x) - 57435: 108, // HintTrueOrFalse (1x) - 57437: 109, // IndexNameList (1x) - 57438: 110, // IndexNameListOpt (1x) - 57441: 111, // OptimizerHintList (1x) - 57442: 112, // PartitionList (1x) - 57445: 113, // Start (1x) - 57448: 114, // SubqueryStrategies (1x) - 57449: 115, // SubqueryStrategiesOpt (1x) - 57454: 116, // UnitOfBytes (1x) - 57457: 117, // Value (1x) - 57424: 118, // $default (0x) - 57345: 119, // error (0x) - 57348: 120, // hintInvalid (0x) + 57458: 106, // ViewName (2x) + 57428: 107, // HintQueryType (1x) + 57431: 108, // HintStorageTypeAndTableList (1x) + 57435: 109, // HintTrueOrFalse (1x) + 57437: 110, // IndexNameList (1x) + 57438: 111, // IndexNameListOpt (1x) + 57441: 112, // OptimizerHintList (1x) + 57442: 113, // PartitionList (1x) + 57445: 114, // Start (1x) + 57448: 115, // SubqueryStrategies (1x) + 57449: 116, // SubqueryStrategiesOpt (1x) + 57454: 117, // UnitOfBytes (1x) + 57457: 118, // Value (1x) + 57459: 119, // ViewNameList (1x) + 57424: 120, // $default (0x) + 57345: 121, // error (0x) + 57348: 122, // hintInvalid (0x) } yyhintSymNames = []string{ @@ -380,11 +382,11 @@ var ( yyhintReductions = []struct{ xsym, components int }{ {0, 1}, - {113, 1}, - {111, 1}, - {111, 3}, - {111, 1}, - {111, 3}, + {114, 1}, + {112, 1}, + {112, 3}, + {112, 1}, + {112, 3}, {103, 4}, {103, 4}, {103, 4}, @@ -399,12 +401,13 @@ var ( {103, 4}, {103, 6}, {103, 6}, + {103, 6}, {103, 5}, {103, 4}, {103, 5}, {98, 5}, - {107, 1}, - {107, 3}, + {108, 1}, + {108, 3}, {93, 4}, {82, 0}, {82, 1}, @@ -412,30 +415,34 @@ var ( {86, 1}, {97, 0}, {97, 4}, - {112, 1}, - {112, 3}, + {113, 1}, + {113, 3}, {94, 1}, {94, 1}, {88, 2}, {88, 3}, {87, 3}, {87, 5}, + {119, 3}, + {119, 1}, + {106, 2}, + {106, 1}, {91, 4}, - {110, 0}, + {111, 0}, + {111, 1}, {110, 1}, - {109, 1}, - {109, 3}, - {115, 0}, + {110, 3}, + {116, 0}, + {116, 1}, {115, 1}, - {114, 1}, - {114, 3}, - {117, 1}, + {115, 3}, + {118, 1}, + {118, 1}, + {118, 1}, {117, 1}, {117, 1}, - {116, 1}, - {116, 1}, - {108, 1}, - {108, 1}, + {109, 1}, + {109, 1}, {95, 1}, {95, 1}, {95, 1}, @@ -490,8 +497,8 @@ var ( {96, 1}, {96, 1}, {96, 1}, - {106, 1}, - {106, 1}, + {107, 1}, + {107, 1}, {92, 1}, {92, 1}, {83, 1}, @@ -569,36 +576,37 @@ var ( {83, 1}, } - yyhintXErrors = map[yyhintXError]string{} - yyhintParseTab = [271][]uint16{ + yyhintXErrors = map[yyhintXError]string{} + + yyhintParseTab = [280][]uint16{ // 0 - {1: 253, 221, 214, 216, 243, 249, 229, 230, 231, 241, 257, 233, 225, 223, 228, 193, 211, 212, 213, 232, 254, 200, 205, 224, 250, 251, 234, 215, 217, 260, 218, 236, 255, 219, 235, 237, 245, 239, 227, 201, 204, 209, 256, 210, 203, 244, 259, 202, 222, 238, 220, 258, 252, 226, 206, 247, 240, 242, 248, 246, 90: 207, 95: 194, 208, 98: 192, 199, 101: 198, 196, 191, 197, 195, 111: 190, 113: 189}, - {81: 188}, - {1: 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 356, 81: 187, 86: 456}, - {1: 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 81: 186}, - {1: 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 81: 184}, + {1: 258, 226, 219, 221, 248, 254, 234, 235, 236, 246, 262, 238, 230, 228, 233, 198, 216, 217, 218, 237, 259, 205, 210, 229, 255, 256, 239, 220, 222, 265, 223, 241, 260, 224, 240, 242, 250, 244, 232, 206, 209, 214, 261, 215, 208, 249, 264, 207, 227, 243, 225, 263, 257, 231, 211, 252, 245, 247, 253, 251, 90: 212, 95: 199, 213, 98: 197, 204, 101: 203, 201, 196, 202, 200, 112: 195, 114: 194}, + {81: 193}, + {1: 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 361, 81: 192, 86: 470}, + {1: 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 191, 81: 191}, + {1: 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 189, 81: 189}, // 5 + {80: 467}, + {80: 464}, + {80: 461}, + {80: 456}, {80: 453}, - {80: 450}, - {80: 447}, - {80: 442}, - {80: 439}, // 10 - {80: 428}, - {80: 416}, - {80: 412}, - {80: 408}, - {80: 400}, + {80: 442}, + {80: 430}, + {80: 426}, + {80: 422}, + {80: 414}, // 15 - {80: 397}, - {80: 394}, + {80: 411}, + {80: 399}, + {80: 392}, {80: 387}, - {80: 382}, - {80: 376}, + {80: 381}, // 20 - {80: 373}, - {80: 367}, - {80: 261}, + {80: 378}, + {80: 372}, + {80: 266}, {80: 131}, {80: 130}, // 25 @@ -659,26 +667,26 @@ var ( {80: 80}, {80: 79}, {80: 78}, - {66: 161, 161, 75: 263, 82: 262}, - {66: 268, 267, 92: 266, 265, 107: 264}, + {66: 165, 165, 75: 268, 82: 267}, + {66: 273, 272, 92: 271, 270, 108: 269}, // 75 - {160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 76: 160, 160, 84: 160}, - {364, 61: 365}, - {164, 61: 164}, - {89: 269}, + {164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 76: 164, 164, 164, 84: 164}, + {369, 61: 370}, + {168, 61: 168}, + {89: 274}, {89: 75}, // 80 {89: 74}, - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 271, 88: 270}, - {61: 362, 76: 361}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 273, 87: 272}, - {151, 61: 151, 76: 151}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 276, 88: 275}, + {61: 367, 76: 366}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 278, 87: 277}, + {155, 61: 155, 76: 155}, // 85 - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 161, 161, 348, 82: 347}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 165, 353, 165, 82: 352}, {73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73, 73}, {72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72}, {71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71}, - + {70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, 70}, // 90 {69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69}, {68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68}, @@ -762,141 +770,151 @@ var ( {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, - {157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 76: 157, 351, 97: 360}, + {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 76: 161, 78: 356, 97: 365}, // 160 - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 349}, - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 161, 161, 82: 350}, - {157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 157, 76: 157, 351, 97: 352}, - {80: 353}, - {148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 76: 148}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 354}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 165, 78: 165, 82: 355}, + {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 76: 161, 78: 356, 97: 357}, + {80: 358}, + {152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, 76: 152}, // 165 - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 355, 112: 354}, - {357, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 356, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 86: 358}, - {155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155, 155}, - {158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 62: 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 85: 158}, - {156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 156, 76: 156}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 360, 113: 359}, + {362, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 361, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 86: 363}, + {159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159}, + {162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 62: 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 162, 85: 162}, + {160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 76: 160}, // 170 - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 359}, - {154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154, 154}, - {149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 76: 149}, - {162, 61: 162}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 273, 87: 363}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 364}, + {158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158, 158}, + {153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 153, 76: 153}, + {166, 61: 166}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 278, 87: 368}, // 175 - {150, 61: 150, 76: 150}, - {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 81: 165}, - {66: 268, 267, 92: 266, 366}, - {163, 61: 163}, - {69: 161, 161, 75: 263, 82: 368}, + {154, 61: 154, 76: 154}, + {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 81: 169}, + {66: 273, 272, 92: 271, 371}, + {167, 61: 167}, + {69: 165, 165, 75: 268, 82: 373}, // 180 - {69: 370, 371, 106: 369}, - {372}, + {69: 375, 376, 107: 374}, + {377}, {77}, {76}, - {1: 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 166, 81: 166}, + {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 81: 170}, // 185 - {161, 75: 263, 82: 374}, - {375}, - {1: 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 167, 81: 167}, - {68: 161, 71: 161, 75: 263, 82: 377}, - {68: 380, 71: 379, 108: 378}, + {165, 75: 268, 82: 379}, + {380}, + {1: 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 81: 171}, + {68: 165, 71: 165, 75: 268, 82: 382}, + {68: 385, 71: 384, 109: 383}, // 190 - {381}, + {386}, {133}, {132}, - {1: 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 81: 168}, - {85: 383}, + {1: 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 81: 172}, + {85: 388}, // 195 - {61: 356, 85: 159, 384}, - {85: 385}, - {386}, - {1: 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 169, 81: 169}, - {75: 263, 82: 388, 84: 161}, + {61: 361, 85: 163, 389}, + {85: 390}, + {391}, + {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 81: 173}, + {75: 268, 82: 393, 84: 165}, // 200 - {84: 389}, - {72: 392, 391, 116: 390}, - {393}, + {84: 394}, + {72: 397, 396, 117: 395}, + {398}, {135}, {134}, // 205 - {1: 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 81: 170}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 395}, - {396}, - {1: 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 171, 81: 171}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 398}, + {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 81: 174}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 400}, + {401, 61: 402}, + {1: 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 81: 176}, + {165, 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 268, 77: 165, 82: 406, 405, 106: 404, 119: 403}, // 210 - {399}, - {1: 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 172, 81: 172}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 401}, - {79: 402}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 405, 406, 404, 117: 403}, + {408, 77: 409}, + {150, 77: 150}, + {165, 75: 268, 77: 165, 82: 407}, + {148, 77: 148}, + {149, 77: 149}, // 215 - {407}, + {1: 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 81: 175}, + {165, 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 268, 77: 165, 82: 406, 405, 106: 410}, + {151, 77: 151}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 412}, + {413}, + // 220 + {1: 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 81: 177}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 415}, + {79: 416}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 419, 420, 418, 118: 417}, + {421}, + // 225 {138}, {137}, {136}, - {1: 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 173, 81: 173}, - // 220 - {75: 263, 82: 409, 84: 161}, - {84: 410}, - {411}, - {1: 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, 81: 174}, - {75: 263, 82: 413, 84: 161}, - // 225 - {84: 414}, - {415}, - {1: 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 175, 81: 175}, - {161, 62: 161, 161, 161, 161, 75: 263, 82: 417}, - {142, 62: 421, 422, 423, 424, 100: 420, 114: 419, 418}, + {1: 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 81: 178}, + {75: 268, 82: 423, 84: 165}, // 230 - {427}, - {141, 61: 425}, + {84: 424}, + {425}, + {1: 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 81: 179}, + {75: 268, 82: 427, 84: 165}, + {84: 428}, + // 235 + {429}, + {1: 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 81: 180}, + {165, 62: 165, 165, 165, 165, 75: 268, 82: 431}, + {142, 62: 435, 436, 437, 438, 100: 434, 115: 433, 432}, + {441}, + // 240 + {141, 61: 439}, {140, 61: 140}, {96, 61: 96}, {95, 61: 95}, - // 235 {94, 61: 94}, + // 245 {93, 61: 93}, - {62: 421, 422, 423, 424, 100: 426}, + {62: 435, 436, 437, 438, 100: 440}, {139, 61: 139}, - {1: 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 176, 81: 176}, - // 240 - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 430, 91: 429}, - {438}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 273, 87: 431}, - {159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 356, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 86: 432}, - {146, 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 435, 109: 434, 433}, - // 245 + {1: 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 81: 181}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 444, 91: 443}, + // 250 + {452}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 278, 87: 445}, + {163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 361, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 86: 446}, + {146, 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 449, 110: 448, 447}, {147}, - {145, 61: 436}, + // 255 + {145, 61: 450}, {144, 61: 144}, - {1: 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 437}, + {1: 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 451}, {143, 61: 143}, - // 250 - {1: 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 177, 81: 177}, - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 430, 91: 440}, - {441}, - {1: 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 178, 81: 178}, - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 445, 88: 444, 94: 443}, - // 255 - {446}, - {153, 61: 362}, - {152, 303, 319, 279, 281, 330, 306, 283, 284, 285, 309, 305, 289, 310, 311, 312, 275, 276, 277, 278, 332, 304, 299, 313, 287, 307, 308, 291, 280, 282, 334, 286, 293, 290, 288, 292, 294, 298, 296, 314, 329, 302, 315, 316, 317, 301, 297, 333, 300, 320, 295, 318, 331, 321, 322, 327, 328, 324, 323, 325, 326, 62: 343, 344, 345, 346, 338, 337, 339, 335, 336, 340, 342, 341, 274, 83: 273, 87: 272}, - {1: 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 179, 81: 179}, - {161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 445, 88: 444, 94: 448}, + {1: 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 81: 182}, // 260 - {449}, - {1: 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 180, 81: 180}, - {1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 62: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 263, 82: 271, 88: 451}, - {452, 61: 362}, - {1: 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 181, 81: 181}, - // 265 - {161, 75: 263, 82: 454}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 444, 91: 454}, {455}, - {1: 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 182, 81: 182}, - {1: 253, 221, 214, 216, 243, 249, 229, 230, 231, 241, 257, 233, 225, 223, 228, 193, 211, 212, 213, 232, 254, 200, 205, 224, 250, 251, 234, 215, 217, 260, 218, 236, 255, 219, 235, 237, 245, 239, 227, 201, 204, 209, 256, 210, 203, 244, 259, 202, 222, 238, 220, 258, 252, 226, 206, 247, 240, 242, 248, 246, 90: 207, 95: 194, 208, 98: 458, 199, 101: 198, 196, 457, 197, 195}, - {1: 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 81: 185}, - // 270 {1: 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 183, 81: 183}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 459, 88: 458, 94: 457}, + {460}, + // 265 + {157, 61: 367}, + {156, 308, 324, 284, 286, 335, 311, 288, 289, 290, 314, 310, 294, 315, 316, 317, 280, 281, 282, 283, 337, 309, 304, 318, 292, 312, 313, 296, 285, 287, 339, 291, 298, 295, 293, 297, 299, 303, 301, 319, 334, 307, 320, 321, 322, 306, 302, 338, 305, 325, 300, 323, 336, 326, 327, 332, 333, 329, 328, 330, 331, 62: 348, 349, 350, 351, 343, 342, 344, 340, 341, 345, 347, 346, 279, 83: 278, 87: 277}, + {1: 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 184, 81: 184}, + {165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 459, 88: 458, 94: 462}, + {463}, + // 270 + {1: 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 185, 81: 185}, + {1: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 62: 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 268, 82: 276, 88: 465}, + {466, 61: 367}, + {1: 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 186, 81: 186}, + {165, 75: 268, 82: 468}, + // 275 + {469}, + {1: 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 187, 81: 187}, + {1: 258, 226, 219, 221, 248, 254, 234, 235, 236, 246, 262, 238, 230, 228, 233, 198, 216, 217, 218, 237, 259, 205, 210, 229, 255, 256, 239, 220, 222, 265, 223, 241, 260, 224, 240, 242, 250, 244, 232, 206, 209, 214, 261, 215, 208, 249, 264, 207, 227, 243, 225, 263, 257, 231, 211, 252, 245, 247, 253, 251, 90: 212, 95: 199, 213, 98: 472, 204, 101: 203, 201, 471, 202, 200}, + {1: 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 190, 81: 190}, + {1: 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 188, 81: 188}, } ) @@ -936,7 +954,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) { } func yyhintParse(yylex yyhintLexer, parser *hintParser) int { - const yyError = 119 + const yyError = 121 yyEx, _ := yylex.(yyhintLexerEx) var yyn int diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 7822396b10de4..99587caade8c2 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1340,6 +1340,41 @@ func TestViewHint(t *testing.T) { } } +func TestViewHintScope(t *testing.T) { + store := testkit.CreateMockStore(t) + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop view if exists v, v1") + tk.MustExec("drop table if exists t, t1, t2") + tk.MustExec("create table t(a int, b int);") + tk.MustExec("create table t1(a int, b int);") + tk.MustExec("create table t2(a int, b int);") + tk.MustExec("create table t3(a int, b int)") + tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join (select count(*) as a from t1 join t2 join t3 where t1.b=t2.b and t2.a = t3.a group by t2.a) tt on t.a = tt.a;") + tk.MustExec("create definer='root'@'localhost' view v1 as select t.a, t.b from t join (select count(*) as a from t1 join v on t1.b=v.b group by v.a) tt on t.a = tt.a;") + tk.MustExec("create definer='root'@'localhost' view v2 as select t.a, t.b from t join (select count(*) as a from t1 join v1 on t1.b=v1.b group by v1.a) tt on t.a = tt.a;") + + var input []string + var output []struct { + SQL string + Plan []string + Warn []string + } + integrationSuiteData := core.GetIntegrationSuiteData() + integrationSuiteData.LoadTestCases(t, &input, &output) + for i, tt := range input { + testdata.OnRecord(func() { + output[i].SQL = tt + output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery(tt).Rows()) + output[i].Warn = testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings()) + }) + res := tk.MustQuery(tt) + res.Check(testkit.Rows(output[i].Plan...)) + require.Equal(t, output[i].Warn, testdata.ConvertSQLWarnToStrings(tk.Session().GetSessionVars().StmtCtx.GetWarnings())) + } +} + func TestReadFromStorageHintAndIsolationRead(t *testing.T) { store := testkit.CreateMockStore(t) tk := testkit.NewTestKit(t, store) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index a11ec3e13b335..123b420be8553 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4421,14 +4421,17 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as // TODO: need to check whether this will happen(maybe in the recursion) continue } + viewSelectOffset := b.getSelectOffset() + + var viewHintSelectOffset int // TODO: can not handle the different DB. if viewQBNameHintTable[0].QBName.L == "" { - // TODO: need to check if we do not explicit set the qbName. Is it empty or use the 'sel_1' as the default value. - continue + // If we do not explicit set the qbName, we will improve the empty qb name to @sel_1. + viewHintSelectOffset = 1 + } else { + viewHintSelectOffset = b.hintProcessor.GetHintOffset(viewQBNameHintTable[0].QBName, viewSelectOffset) } - viewSelectOffset := b.getSelectOffset() - viewHintSelectOffset := b.hintProcessor.GetHintOffset(viewQBNameHintTable[0].QBName, viewSelectOffset) - if viewQBNameHintTable[0].TableName.L == tableInfo.Name.L && viewHintSelectOffset == viewSelectOffset { + if viewQBNameHintTable[0].TableName.L == tblName.L && viewHintSelectOffset == viewSelectOffset { currentQBNameMap4View[qbName] = viewQBNameHintTable currentViewHints[qbName] = b.hintProcessor.QbHints4View[qbName] delete(b.hintProcessor.QbNameMap4View, qbName) diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index 690a158a9d5be..376b50149d0ee 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -675,6 +675,51 @@ "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2), stream_agg(@qb_v2_2), qb_name(qb_v2_1, v1@sel_1 .@sel_1), merge_join(t@qb_v2_1) */ * from v2;" ] }, + { + "name": "TestViewHintScope", + "cases": [ + // Same qb name in one query + "explain format = 'brief' select /*+ qb_name(qb_v, v@sel_1 .@sel_2), qb_name(qb_v, v@sel_1 .@sel_1), merge_join(t1@qb_v) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v, v1@sel_1 .v@sel_2 .@sel_2), qb_name(qb_v, v1@sel_1 .v@sel_2 .@sel_1), merge_join(t1@qb_v) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_2), qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_1), merge_join(t1@qb_v) */ * from v2;", + + // Set the unappeared view name + // TODO: add the warning for the unused the view hints + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;", + + // Exist the view alias + "explain format = 'brief' select /*+ qb_name(qb_v2_2, vv@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2 vv;", + "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2 vv;", + + // Tht view hint isn't set in the first query block. + "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v) t;", + "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;", + "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1) t;", + "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;", + + // TODO: add the warning when the view hints don't set in the first query block + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;", + + // Define more tables in one view hint + "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(t1@qb_v_2, t3@qb_v_2) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(@qb_v_2 t1, t3) */ * from v2;", + + // Ignore the @sel_1 query block + "explain format = 'brief' select /*+ qb_name(qb_v_2, v .@sel_2), merge_join(t1@qb_v_2) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1), merge_join(t@qb_v_1) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v_2, v1 .v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v_1, v1 .v@sel_2), merge_join(t@qb_v_1) */ * from v1;", + + // Use the query block before define it + "explain format = 'brief' select /*+ merge_join(t1@qb_v_2), qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from v;", + "explain format = 'brief' select /*+ merge_join(t@qb_v_1), stream_agg(@qb_v_2), qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from v;" + ] + }, { "name": "TestReadFromStorageHintAndIsolationRead", "cases": [ diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 5f872a70b629e..70cb9fc90d725 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4724,6 +4724,802 @@ } ] }, + { + "Name": "TestViewHintScope", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v@sel_1 .@sel_2), qb_name(qb_v, v@sel_1 .@sel_1), merge_join(t1@qb_v) */ * from v;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Duplicate query block name qb_v for view's query block hint, only the first one is effective" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v1@sel_1 .v@sel_2 .@sel_2), qb_name(qb_v, v1@sel_1 .v@sel_2 .@sel_1), merge_join(t1@qb_v) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Duplicate query block name qb_v for view's query block hint, only the first one is effective" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_2), qb_name(qb_v, v2@sel_1 .v1@sel_2 .v@sel_2 .@sel_1), merge_join(t1@qb_v) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Duplicate query block name qb_v for view's query block hint, only the first one is effective" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v@sel_1 .@sel_2), merge_join(t1@qb_v1_2) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2_2, vv@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2 vv;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t.b", + "│ ├─Sort(Build) 9980.01 root test.t.b", + "│ │ └─HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2_2, v2@sel_1 .@sel_2), merge_join(t1@qb_v2_2) */ * from v2 vv;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2) */ * from v) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "The qb_name hint for view only supports to be defined in the first query block", + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel1), merge_join(t@qb_v_1) */ * from v) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "The qb_name hint for view only supports to be defined in the first query block", + "The qb_name hint for view only supports to be defined in the first query block", + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name", + "Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name", + "Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "The qb_name hint for view only supports to be defined in the first query block", + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select * from (select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v1) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "The qb_name hint for view only supports to be defined in the first query block", + "The qb_name hint for view only supports to be defined in the first query block", + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name", + "Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name", + "Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name", + "Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name", + "Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2) */ * from (select /*+ merge_join(t1@qb_v_2) */ * from v1) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1@sel_1 . v@sel_2 .@sel_2), qb_name(qb_v_1, v1@sel_1 . v@sel_2 .@sel_1) */ * from (select /*+ merge_join(t1@qb_v_2), stream_agg(@qb_v_2), merge_join(t@qb_v_1) */ * from v1) t;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Hint merge_join(`t1`@`qb_v_2`) is ignored due to unknown query block name", + "Hint stream_agg(@`qb_v_2`) is ignored due to unknown query block name", + "Hint merge_join(`t`@`qb_v_1`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1_2, v2@sel_1 . v1@sel_1 .@sel_2), qb_name(qb_v1_1, v2@sel_1 . v1@sel_1 .@sel_1), merge_join(t1@qb_v1_2, t@qb_v1_1) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Only support to define one table in one view hint", + "Hint merge_join(`t1`@`qb_v1_2`, `t`@`qb_v1_1`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(t1@qb_v_2, t3@qb_v_2) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": [ + "Only support to define one table in one view hint", + "Hint merge_join(`t1`@`qb_v_2`, `t3`@`qb_v_2`) is ignored due to unknown query block name" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(@qb_v_2 t1, t3) */ * from v2;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#27)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#26)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", + "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", + "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", + "│ │ │ └─MergeJoin 15593.77 root inner join, left key:test.t2.a, right key:test.t3.a", + "│ │ │ ├─Sort(Build) 9990.00 root test.t3.a", + "│ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 12475.01 root test.t2.a", + "│ │ │ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v .@sel_2), merge_join(t1@qb_v_2) */ * from v;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_1, v@sel_1), merge_join(t@qb_v_1) */ * from v;", + "Plan": [ + "MergeJoin 9980.01 root inner join, left key:test.t.a, right key:Column#13", + "├─Sort(Build) 7984.01 root Column#13", + "│ └─HashAgg 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─Sort(Probe) 9990.00 root test.t.a", + " └─TableReader 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v1 .v@sel_2 .@sel_2), merge_join(t1@qb_v_2) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#19)]", + "│ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ └─TableReader 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_1, v1 .v@sel_2), merge_join(t@qb_v_1) */ * from v1;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#20)]", + "├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#20", + "│ └─HashJoin 12475.01 root inner join, equal:[eq(test.t1.b, test.t.b)]", + "│ ├─MergeJoin(Build) 9980.01 root inner join, left key:test.t.a, right key:Column#19", + "│ │ ├─Sort(Build) 7984.01 root Column#19", + "│ │ │ └─HashAgg 7984.01 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ └─Sort(Probe) 9980.01 root test.t.a", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ merge_join(t1@qb_v_2), qb_name(qb_v_2, v@sel_1 .@sel_2) */ * from v;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t3.a, test.t2.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─MergeJoin(Probe) 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 9990.00 root test.t1.b", + "│ └─TableReader 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ merge_join(t@qb_v_1), stream_agg(@qb_v_2), qb_name(qb_v_2, v@sel_1 .@sel_2), qb_name(qb_v_1, v@sel_1 .@sel1) */ * from v;", + "Plan": [ + "HashJoin 9980.01 root inner join, equal:[eq(test.t.a, Column#13)]", + "├─StreamAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#13", + "│ └─Sort 15593.77 root test.t2.a", + "│ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", + "│ ├─TableReader(Build) 9990.00 root data:Selection", + "│ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 9990.00 root data:Selection", + "│ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "└─TableReader(Probe) 9990.00 root data:Selection", + " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", + " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, { "Name": "TestReadFromStorageHintAndIsolationRead", "Cases": [ diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index 71f10a05de886..6edd6b1181279 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -363,9 +363,15 @@ func (p *BlockHintProcessor) checkQueryBlockHints(hints []*ast.TableOptimizerHin if hint.HintName.L != hintQBName { continue } + if offset > 1 && len(hint.Tables) > 0 { + if p.Ctx != nil { + p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("The qb_name hint for view only supports to be defined in the first query block")) + } + continue + } if qbName != "" { if p.Ctx != nil { - p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("There are more than two query names in same query block,, using the first one %s", qbName)) + p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("There are more than two query names in same query block, using the first one %s", qbName)) } } else { qbName = hint.QBName.L @@ -421,13 +427,16 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l ok := false qbName := hint.QBName.L if qbName != "" { - // xx_agg(@qb_name) _, ok = p.QbNameMap4View[qbName] } else { if len(hint.Tables) == 1 { // TODO: only support one table in view hints. Need to check what happened if there are more table name appear in one hint qbName = hint.Tables[0].QBName.L _, ok = p.QbNameMap4View[qbName] + } else { + if p.Ctx != nil { + p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Only support to define one table in one view hint")) + } } } From 8939624caff4454551c1ef2198b3b1ff0010aa42 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 8 Nov 2022 15:36:20 +0800 Subject: [PATCH 6/9] fix build --- planner/core/logical_plan_builder.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 4f2d2d2357149..2a56f912e96be 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4968,7 +4968,7 @@ func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIS } // BuildDataSourceFromView is used to build LogicalPlan from view -func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo, QbNameMap4View map[string][]ast.HintTable, ViewHints map[string][]*ast.TableOptimizerHint) (LogicalPlan, error) { +func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo, qbNameMap4View map[string][]ast.HintTable, viewHints map[string][]*ast.TableOptimizerHint) (LogicalPlan, error) { viewDepth := b.ctx.GetSessionVars().StmtCtx.ViewDepth b.ctx.GetSessionVars().StmtCtx.ViewDepth++ deferFunc, err := b.checkRecursiveView(dbName, tableInfo.Name) @@ -5011,30 +5011,30 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. currentQbHints := make(map[int][]*ast.TableOptimizerHint) currentQbNameMap := make(map[string]int) - for qbName, viewQbNameHint := range QbNameMap4View { + for qbName, viewQbNameHint := range qbNameMap4View { selectOffset := -1 viewQbNameHint = viewQbNameHint[1:] - QbNameMap4View[qbName] = viewQbNameHint + qbNameMap4View[qbName] = viewQbNameHint if len(viewQbNameHint) == 0 { selectOffset = 1 } else if len(viewQbNameHint) == 1 && viewQbNameHint[0].TableName.L == "" { selectOffset = hintProcessor.GetHintOffset(viewQbNameHint[0].QBName, -1) } else { currentQbNameMap4View[qbName] = viewQbNameHint - currentQbHints4View[qbName] = ViewHints[qbName] + currentQbHints4View[qbName] = viewHints[qbName] } if selectOffset != -1 { - currentQbHints[selectOffset] = ViewHints[qbName] + currentQbHints[selectOffset] = viewHints[qbName] currentQbNameMap[qbName] = selectOffset - delete(QbNameMap4View, qbName) - delete(ViewHints, qbName) + delete(qbNameMap4View, qbName) + delete(viewHints, qbName) } } - hintProcessor.QbNameMap4View = QbNameMap4View - hintProcessor.QbHints4View = ViewHints + hintProcessor.QbNameMap4View = qbNameMap4View + hintProcessor.QbHints4View = viewHints hintProcessor.QbHints = currentQbHints hintProcessor.QbNameMap = currentQbNameMap From 7c9b5746cbcf73ee15acc8cb5d0ad36031b17380 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 8 Nov 2022 15:56:31 +0800 Subject: [PATCH 7/9] fix ut --- .../core/testdata/integration_suite_out.json | 32 +++++++++---------- util/hint/hint_processor.go | 18 ++++++----- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index f0506580434fb..749729a138ddb 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -5265,7 +5265,6 @@ " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warn": [ - "Only support to define one table in one view hint", "Hint merge_join(`t1`@`qb_v1_2`, `t`@`qb_v1_1`) is ignored due to unknown query block name" ] }, @@ -5278,17 +5277,21 @@ "│ ├─HashAgg(Build) 7984.01 root group by:test.t.a, funcs:count(1)->Column#26", "│ │ └─HashJoin 12475.01 root inner join, equal:[eq(test.t.a, Column#25)]", "│ │ ├─HashAgg(Build) 7984.01 root group by:test.t2.a, funcs:count(1)->Column#25", - "│ │ │ └─HashJoin 15593.77 root inner join, equal:[eq(test.t2.a, test.t3.a)]", - "│ │ │ ├─TableReader(Build) 9990.00 root data:Selection", - "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", - "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", - "│ │ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t2.b, test.t1.b)]", - "│ │ │ ├─TableReader(Build) 9980.01 root data:Selection", - "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", - "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", - "│ │ │ └─TableReader(Probe) 9990.00 root data:Selection", - "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", - "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", + "│ │ │ └─MergeJoin 15593.77 root inner join, left key:test.t2.a, right key:test.t3.a", + "│ │ │ ├─Sort(Build) 9990.00 root test.t3.a", + "│ │ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t3.a))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 12475.01 root test.t2.a", + "│ │ │ └─MergeJoin 12475.01 root inner join, left key:test.t1.b, right key:test.t2.b", + "│ │ │ ├─Sort(Build) 9980.01 root test.t2.b", + "│ │ │ │ └─TableReader 9980.01 root data:Selection", + "│ │ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t2.a)), not(isnull(test.t2.b))", + "│ │ │ │ └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo", + "│ │ │ └─Sort(Probe) 9990.00 root test.t1.b", + "│ │ │ └─TableReader 9990.00 root data:Selection", + "│ │ │ └─Selection 9990.00 cop[tikv] not(isnull(test.t1.b))", + "│ │ │ └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo", "│ │ └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t.b, test.t1.b)]", "│ │ ├─TableReader(Build) 9980.01 root data:Selection", "│ │ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t.a)), not(isnull(test.t.b))", @@ -5307,10 +5310,7 @@ " └─Selection 9990.00 cop[tikv] not(isnull(test.t.a))", " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], - "Warn": [ - "Only support to define one table in one view hint", - "Hint merge_join(`t1`@`qb_v_2`, `t3`@`qb_v_2`) is ignored due to unknown query block name" - ] + "Warn": null }, { "SQL": "explain format = 'brief' select /*+ qb_name(qb_v_2, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_2), qb_name(qb_v_1, v2@sel_1 . v1@sel_2 . v@sel_2 .@sel_1), merge_join(@qb_v_2 t1, t3) */ * from v2;", diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index 6edd6b1181279..16bb552c3afab 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -428,14 +428,16 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l qbName := hint.QBName.L if qbName != "" { _, ok = p.QbNameMap4View[qbName] - } else { - if len(hint.Tables) == 1 { - // TODO: only support one table in view hints. Need to check what happened if there are more table name appear in one hint - qbName = hint.Tables[0].QBName.L - _, ok = p.QbNameMap4View[qbName] - } else { - if p.Ctx != nil { - p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Only support to define one table in one view hint")) + } else if len(hint.Tables) > 0 { + // Only support to define the tables belong to the same query block in one view hint + qbName = hint.Tables[0].QBName.L + _, ok = p.QbNameMap4View[qbName] + if ok { + for _, table := range hint.Tables { + if table.QBName.L != qbName { + ok = false + break + } } } } From 3440def8b4b4aa7a053149f0d4805ad384adf365 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 8 Nov 2022 16:10:55 +0800 Subject: [PATCH 8/9] remove all of the todo parts --- parser/ast/misc.go | 1 - planner/core/logical_plan_builder.go | 5 +---- util/hint/hint_processor.go | 4 +++- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/parser/ast/misc.go b/parser/ast/misc.go index 4b5e37639ba3e..b0668c7a09a7e 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -3647,7 +3647,6 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { ctx.WriteKeyWord("@") } ctx.WriteName(n.QBName.String()) - // TODO: add the restore part for view hint } // Hints without args except query block. switch n.HintName.L { diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 2a56f912e96be..e8187390982b8 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4418,15 +4418,13 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as currentViewHints := make(map[string][]*ast.TableOptimizerHint) for qbName, viewQBNameHintTable := range b.hintProcessor.QbNameMap4View { if len(viewQBNameHintTable) == 0 { - // TODO: need to check whether this will happen(maybe in the recursion) continue } viewSelectOffset := b.getSelectOffset() var viewHintSelectOffset int - // TODO: can not handle the different DB. if viewQBNameHintTable[0].QBName.L == "" { - // If we do not explicit set the qbName, we will improve the empty qb name to @sel_1. + // If we do not explicit set the qbName, we will set the empty qb name to @sel_1. viewHintSelectOffset = 1 } else { viewHintSelectOffset = b.hintProcessor.GetHintOffset(viewQBNameHintTable[0].QBName, viewSelectOffset) @@ -5004,7 +5002,6 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. }() hintProcessor := &hint.BlockHintProcessor{Ctx: b.ctx} - // TODO: need to check whether the selectOffset has already been set. Is necessary to use the 'Accept' function here. selectNode.Accept(hintProcessor) currentQbNameMap4View := make(map[string][]ast.HintTable) currentQbHints4View := make(map[string][]*ast.TableOptimizerHint) diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index 16bb552c3afab..a043b0c241bad 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -404,11 +404,13 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l continue } usedHints[i] = true - // TODO: need to check whether the qbName can be empty if p.QbNameMap4View == nil { p.QbNameMap4View = make(map[string][]ast.HintTable) } qbName := hint.QBName.L + if qbName == "" { + continue + } if _, ok := p.QbNameMap4View[qbName]; ok { if p.Ctx != nil { p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Duplicate query block name %s for view's query block hint, only the first one is effective", qbName)) From 3b12fad432aa101b1caa22d1ce49d345cc0c5cd9 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Fri, 11 Nov 2022 12:42:41 +0800 Subject: [PATCH 9/9] address comments --- planner/core/logical_plan_builder.go | 16 +++++++++++++--- util/hint/hint_processor.go | 11 +++++++---- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index e8187390982b8..18edbd52be994 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4413,7 +4413,7 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as return nil, expression.ErrInvalidTableSample.GenWithStackByArgs("Unsupported TABLESAMPLE in views") } - // Get the hint belong to the view. + // Get the hints belong to the current view. currentQBNameMap4View := make(map[string][]ast.HintTable) currentViewHints := make(map[string][]*ast.TableOptimizerHint) for qbName, viewQBNameHintTable := range b.hintProcessor.QbNameMap4View { @@ -4429,8 +4429,13 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as } else { viewHintSelectOffset = b.hintProcessor.GetHintOffset(viewQBNameHintTable[0].QBName, viewSelectOffset) } + + // Check whether the current view can match the view name in the hint. if viewQBNameHintTable[0].TableName.L == tblName.L && viewHintSelectOffset == viewSelectOffset { - currentQBNameMap4View[qbName] = viewQBNameHintTable + // If the view hint can match the current view, we pop the first view table in the query block hint's table list. + // It means the hint belong the current view, the first view name in hint is matched. + // Because of the nested views, so we should check the left table list in hint when build the data source from the view inside the current view. + currentQBNameMap4View[qbName] = viewQBNameHintTable[1:] currentViewHints[qbName] = b.hintProcessor.QbHints4View[qbName] delete(b.hintProcessor.QbNameMap4View, qbName) delete(b.hintProcessor.QbHints4View, qbName) @@ -4966,6 +4971,9 @@ func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIS } // BuildDataSourceFromView is used to build LogicalPlan from view +// qbNameMap4View and viewHints are used for the view's hint. +// qbNameMap4View maps the query block name to the view table lists. +// viewHints group the view hints based on the view's query block name. func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo, qbNameMap4View map[string][]ast.HintTable, viewHints map[string][]*ast.TableOptimizerHint) (LogicalPlan, error) { viewDepth := b.ctx.GetSessionVars().StmtCtx.ViewDepth b.ctx.GetSessionVars().StmtCtx.ViewDepth++ @@ -5009,8 +5017,8 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. currentQbNameMap := make(map[string]int) for qbName, viewQbNameHint := range qbNameMap4View { + // Check whether the view hint belong the current view or its nested views. selectOffset := -1 - viewQbNameHint = viewQbNameHint[1:] qbNameMap4View[qbName] = viewQbNameHint if len(viewQbNameHint) == 0 { selectOffset = 1 @@ -5022,6 +5030,8 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. } if selectOffset != -1 { + // If the hint belongs to the current view and not belongs to it's nested views, we should convert the view hint to the normal hint. + // After we convert the view hint to the normal hint, it can be reused the origin hint's infrastructure. currentQbHints[selectOffset] = viewHints[qbName] currentQbNameMap[qbName] = selectOffset diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index a043b0c241bad..47613a429d99a 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -314,10 +314,13 @@ func extractHintWarns(warns []error) []error { // BlockHintProcessor processes hints at different level of sql statement. type BlockHintProcessor struct { - QbNameMap map[string]int // Map from query block name to select stmt offset. - QbNameMap4View map[string][]ast.HintTable - QbHints map[int][]*ast.TableOptimizerHint // Group all hints at same query block. - QbHints4View map[string][]*ast.TableOptimizerHint + QbNameMap map[string]int // Map from query block name to select stmt offset. + QbHints map[int][]*ast.TableOptimizerHint // Group all hints at same query block. + + // Used for the view's hint + QbNameMap4View map[string][]ast.HintTable // Map from view's query block name to view's table list. + QbHints4View map[string][]*ast.TableOptimizerHint // Group all hints at same query block for view hints. + Ctx sessionctx.Context selectStmtOffset int }