From ec7af195965a4efad50b21d477fc24cb4555351c Mon Sep 17 00:00:00 2001 From: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> Date: Mon, 14 Nov 2022 12:01:54 +0800 Subject: [PATCH 01/10] planner: support the view hint --- executor/infoschema_reader.go | 2 +- executor/show.go | 2 +- parser/hintparser.go | 601 +++++---- parser/hintparser.y | 39 + planner/core/integration_test.go | 69 + planner/core/logical_plan_builder.go | 103 +- .../core/testdata/integration_suite_in.json | 67 + .../core/testdata/integration_suite_out.json | 1192 +++++++++++++++++ util/hint/hint_processor.go | 93 +- 9 files changed, 1878 insertions(+), 290 deletions(-) diff --git a/executor/infoschema_reader.go b/executor/infoschema_reader.go index ebc13d6f6f245..18b78ae404c72 100644 --- a/executor/infoschema_reader.go +++ b/executor/infoschema_reader.go @@ -688,7 +688,7 @@ func (e *hugeMemTableRetriever) dataForColumnsInTable(ctx context.Context, sctx if err := runWithSystemSession(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 8ee1ba9b84607..0a26b94783672 100644 --- a/executor/show.go +++ b/executor/show.go @@ -1904,7 +1904,7 @@ func tryFillViewColumnType(ctx context.Context, sctx sessionctx.Context, is info return runWithSystemSession(sctx, func(s sessionctx.Context) error { // Retrieve view columns info. planBuilder, _ := plannercore.NewPlanBuilder().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/parser/hintparser.go b/parser/hintparser.go index b86638e44b682..f8e8cb46713c3 100644 --- a/parser/hintparser.go +++ b/parser/hintparser.go @@ -117,88 +117,88 @@ const ( hintUseToja = 57396 yyhintMaxDepth = 200 - yyhintTabOfs = -174 + yyhintTabOfs = -179 ) var ( yyhintXLAT = map[int]int{ - 41: 0, // ')' (131x) - 57377: 1, // hintAggToCop (123x) - 57390: 2, // hintBCJoin (123x) - 57355: 3, // hintBKA (123x) - 57357: 4, // hintBNL (123x) - 57401: 5, // hintForceIndex (123x) - 57379: 6, // hintHashAgg (123x) - 57359: 7, // hintHashJoin (123x) - 57380: 8, // hintIgnoreIndex (123x) - 57378: 9, // hintIgnorePlanCache (123x) - 57363: 10, // hintIndexMerge (123x) - 57381: 11, // hintInlHashJoin (123x) - 57382: 12, // hintInlJoin (123x) - 57383: 13, // hintInlMergeJoin (123x) - 57351: 14, // hintJoinFixedOrder (123x) - 57352: 15, // hintJoinOrder (123x) - 57353: 16, // hintJoinPrefix (123x) - 57354: 17, // hintJoinSuffix (123x) - 57403: 18, // hintLeading (123x) - 57400: 19, // hintLimitToCop (123x) - 57373: 20, // hintMaxExecutionTime (123x) - 57384: 21, // hintMemoryQuota (123x) - 57361: 22, // hintMerge (123x) - 57365: 23, // hintMRR (123x) - 57356: 24, // hintNoBKA (123x) - 57358: 25, // hintNoBNL (123x) - 57360: 26, // hintNoHashJoin (123x) - 57367: 27, // hintNoICP (123x) - 57364: 28, // hintNoIndexMerge (123x) - 57362: 29, // hintNoMerge (123x) - 57366: 30, // hintNoMRR (123x) - 57368: 31, // hintNoRangeOptimization (123x) - 57372: 32, // hintNoSemijoin (123x) - 57370: 33, // hintNoSkipScan (123x) - 57385: 34, // hintNoSwapJoinInputs (123x) - 57399: 35, // hintNthPlan (123x) - 57376: 36, // hintQBName (123x) - 57386: 37, // hintQueryType (123x) - 57387: 38, // hintReadConsistentReplica (123x) - 57388: 39, // hintReadFromStorage (123x) - 57375: 40, // hintResourceGroup (123x) - 57371: 41, // hintSemijoin (123x) - 57374: 42, // hintSetVar (123x) - 57369: 43, // hintSkipScan (123x) - 57389: 44, // hintSMJoin (123x) - 57402: 45, // hintStraightJoin (123x) - 57391: 46, // hintStreamAgg (123x) - 57392: 47, // hintSwapJoinInputs (123x) - 57397: 48, // hintTimeRange (123x) - 57398: 49, // hintUseCascades (123x) - 57394: 50, // hintUseIndex (123x) - 57393: 51, // hintUseIndexMerge (123x) - 57395: 52, // hintUsePlanCache (123x) - 57396: 53, // hintUseToja (123x) - 44: 54, // ',' (121x) - 57413: 55, // hintDupsWeedOut (101x) - 57414: 56, // hintFirstMatch (101x) - 57415: 57, // hintLooseScan (101x) - 57416: 58, // hintMaterialization (101x) - 57408: 59, // hintTiFlash (101x) - 57407: 60, // hintTiKV (101x) - 57409: 61, // hintFalse (100x) - 57404: 62, // hintOLAP (100x) - 57405: 63, // hintOLTP (100x) - 57410: 64, // hintTrue (100x) - 57412: 65, // hintGB (99x) - 57411: 66, // hintMB (99x) - 57347: 67, // hintIdentifier (98x) - 57349: 68, // hintSingleAtIdentifier (83x) + 41: 0, // ')' (139x) + 57377: 1, // hintAggToCop (126x) + 57390: 2, // hintBCJoin (126x) + 57355: 3, // hintBKA (126x) + 57357: 4, // hintBNL (126x) + 57401: 5, // hintForceIndex (126x) + 57379: 6, // hintHashAgg (126x) + 57359: 7, // hintHashJoin (126x) + 57380: 8, // hintIgnoreIndex (126x) + 57378: 9, // hintIgnorePlanCache (126x) + 57363: 10, // hintIndexMerge (126x) + 57381: 11, // hintInlHashJoin (126x) + 57382: 12, // hintInlJoin (126x) + 57383: 13, // hintInlMergeJoin (126x) + 57351: 14, // hintJoinFixedOrder (126x) + 57352: 15, // hintJoinOrder (126x) + 57353: 16, // hintJoinPrefix (126x) + 57354: 17, // hintJoinSuffix (126x) + 57403: 18, // hintLeading (126x) + 57400: 19, // hintLimitToCop (126x) + 57373: 20, // hintMaxExecutionTime (126x) + 57384: 21, // hintMemoryQuota (126x) + 57361: 22, // hintMerge (126x) + 57365: 23, // hintMRR (126x) + 57356: 24, // hintNoBKA (126x) + 57358: 25, // hintNoBNL (126x) + 57360: 26, // hintNoHashJoin (126x) + 57367: 27, // hintNoICP (126x) + 57364: 28, // hintNoIndexMerge (126x) + 57362: 29, // hintNoMerge (126x) + 57366: 30, // hintNoMRR (126x) + 57368: 31, // hintNoRangeOptimization (126x) + 57372: 32, // hintNoSemijoin (126x) + 57370: 33, // hintNoSkipScan (126x) + 57385: 34, // hintNoSwapJoinInputs (126x) + 57399: 35, // hintNthPlan (126x) + 57376: 36, // hintQBName (126x) + 57386: 37, // hintQueryType (126x) + 57387: 38, // hintReadConsistentReplica (126x) + 57388: 39, // hintReadFromStorage (126x) + 57375: 40, // hintResourceGroup (126x) + 57371: 41, // hintSemijoin (126x) + 57374: 42, // hintSetVar (126x) + 57369: 43, // hintSkipScan (126x) + 57389: 44, // hintSMJoin (126x) + 57402: 45, // hintStraightJoin (126x) + 57391: 46, // hintStreamAgg (126x) + 57392: 47, // hintSwapJoinInputs (126x) + 57397: 48, // hintTimeRange (126x) + 57398: 49, // hintUseCascades (126x) + 57394: 50, // hintUseIndex (126x) + 57393: 51, // hintUseIndexMerge (126x) + 57395: 52, // hintUsePlanCache (126x) + 57396: 53, // hintUseToja (126x) + 44: 54, // ',' (123x) + 57413: 55, // hintDupsWeedOut (103x) + 57414: 56, // hintFirstMatch (103x) + 57415: 57, // hintLooseScan (103x) + 57416: 58, // hintMaterialization (103x) + 57408: 59, // hintTiFlash (103x) + 57407: 60, // hintTiKV (103x) + 57409: 61, // hintFalse (102x) + 57404: 62, // hintOLAP (102x) + 57405: 63, // hintOLTP (102x) + 57410: 64, // hintTrue (102x) + 57412: 65, // hintGB (101x) + 57411: 66, // hintMB (101x) + 57347: 67, // hintIdentifier (100x) + 57349: 68, // hintSingleAtIdentifier (86x) 93: 69, // ']' (77x) - 57406: 70, // hintPartition (71x) - 46: 71, // '.' (67x) + 46: 70, // '.' (76x) + 57406: 71, // hintPartition (71x) 61: 72, // '=' (67x) 40: 73, // '(' (62x) - 57344: 74, // $end (24x) - 57437: 75, // QueryBlockOpt (17x) - 57429: 76, // Identifier (13x) + 57344: 74, // $end (25x) + 57437: 75, // QueryBlockOpt (20x) + 57429: 76, // Identifier (15x) 57346: 77, // hintIntLit (8x) 57350: 78, // hintStringLit (5x) 57419: 79, // CommaOpt (4x) @@ -221,21 +221,23 @@ var ( 57446: 96, // TableOptimizerHintOpt (2x) 57448: 97, // UnsupportedIndexLevelOptimizerHintName (2x) 57449: 98, // UnsupportedTableLevelOptimizerHintName (2x) - 57421: 99, // HintQueryType (1x) - 57424: 100, // HintStorageTypeAndTableList (1x) - 57428: 101, // HintTrueOrFalse (1x) - 57430: 102, // IndexNameList (1x) - 57431: 103, // IndexNameListOpt (1x) - 57434: 104, // OptimizerHintList (1x) - 57435: 105, // PartitionList (1x) - 57438: 106, // Start (1x) - 57441: 107, // SubqueryStrategies (1x) - 57442: 108, // SubqueryStrategiesOpt (1x) - 57447: 109, // UnitOfBytes (1x) - 57450: 110, // Value (1x) - 57417: 111, // $default (0x) - 57345: 112, // error (0x) - 57348: 113, // hintInvalid (0x) + 57451: 99, // ViewName (2x) + 57421: 100, // HintQueryType (1x) + 57424: 101, // HintStorageTypeAndTableList (1x) + 57428: 102, // HintTrueOrFalse (1x) + 57430: 103, // IndexNameList (1x) + 57431: 104, // IndexNameListOpt (1x) + 57434: 105, // OptimizerHintList (1x) + 57435: 106, // PartitionList (1x) + 57438: 107, // Start (1x) + 57441: 108, // SubqueryStrategies (1x) + 57442: 109, // SubqueryStrategiesOpt (1x) + 57447: 110, // UnitOfBytes (1x) + 57450: 111, // Value (1x) + 57452: 112, // ViewNameList (1x) + 57417: 113, // $default (0x) + 57345: 114, // error (0x) + 57348: 115, // hintInvalid (0x) } yyhintSymNames = []string{ @@ -309,8 +311,8 @@ var ( "hintIdentifier", "hintSingleAtIdentifier", "']'", - "hintPartition", "'.'", + "hintPartition", "'='", "'('", "$end", @@ -338,6 +340,7 @@ var ( "TableOptimizerHintOpt", "UnsupportedIndexLevelOptimizerHintName", "UnsupportedTableLevelOptimizerHintName", + "ViewName", "HintQueryType", "HintStorageTypeAndTableList", "HintTrueOrFalse", @@ -350,6 +353,7 @@ var ( "SubqueryStrategiesOpt", "UnitOfBytes", "Value", + "ViewNameList", "$default", "error", "hintInvalid", @@ -357,11 +361,11 @@ var ( yyhintReductions = []struct{ xsym, components int }{ {0, 1}, - {106, 1}, - {104, 1}, - {104, 3}, - {104, 1}, - {104, 3}, + {107, 1}, + {105, 1}, + {105, 3}, + {105, 1}, + {105, 3}, {96, 4}, {96, 4}, {96, 4}, @@ -376,12 +380,13 @@ var ( {96, 4}, {96, 6}, {96, 6}, + {96, 6}, {96, 5}, {96, 4}, {96, 5}, {91, 5}, - {100, 1}, - {100, 3}, + {101, 1}, + {101, 3}, {86, 4}, {75, 0}, {75, 1}, @@ -389,30 +394,34 @@ var ( {79, 1}, {90, 0}, {90, 4}, - {105, 1}, - {105, 3}, + {106, 1}, + {106, 3}, {87, 1}, {87, 1}, {81, 2}, {81, 3}, {80, 3}, {80, 5}, + {112, 3}, + {112, 1}, + {99, 2}, + {99, 1}, {84, 4}, - {103, 0}, + {104, 0}, + {104, 1}, {103, 1}, - {102, 1}, - {102, 3}, - {108, 0}, + {103, 3}, + {109, 0}, + {109, 1}, {108, 1}, - {107, 1}, - {107, 3}, - {110, 1}, + {108, 3}, + {111, 1}, + {111, 1}, + {111, 1}, {110, 1}, {110, 1}, - {109, 1}, - {109, 1}, - {101, 1}, - {101, 1}, + {102, 1}, + {102, 1}, {88, 1}, {88, 1}, {88, 1}, @@ -460,8 +469,8 @@ var ( {89, 1}, {89, 1}, {89, 1}, - {99, 1}, - {99, 1}, + {100, 1}, + {100, 1}, {85, 1}, {85, 1}, {76, 1}, @@ -534,35 +543,35 @@ var ( yyhintXErrors = map[yyhintXError]string{} - yyhintParseTab = [257][]uint16{ + yyhintParseTab = [266][]uint16{ // 0 - {1: 234, 208, 200, 202, 226, 232, 214, 224, 238, 216, 210, 209, 213, 179, 197, 198, 199, 215, 235, 186, 191, 205, 217, 201, 203, 204, 219, 236, 206, 218, 220, 228, 222, 212, 187, 190, 195, 237, 196, 189, 227, 188, 221, 207, 239, 233, 211, 192, 230, 223, 225, 231, 229, 83: 193, 88: 180, 194, 91: 178, 185, 94: 184, 182, 177, 183, 181, 104: 176, 106: 175}, - {74: 174}, - {1: 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 328, 74: 173, 79: 428}, - {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, 74: 172}, - {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, 74: 170}, + {1: 239, 213, 205, 207, 231, 237, 219, 229, 243, 221, 215, 214, 218, 184, 202, 203, 204, 220, 240, 191, 196, 210, 222, 206, 208, 209, 224, 241, 211, 223, 225, 233, 227, 217, 192, 195, 200, 242, 201, 194, 232, 193, 226, 212, 244, 238, 216, 197, 235, 228, 230, 236, 234, 83: 198, 88: 185, 199, 91: 183, 190, 94: 189, 187, 182, 188, 186, 105: 181, 107: 180}, + {74: 179}, + {1: 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, 333, 74: 178, 79: 442}, + {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, 74: 177}, + {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, 74: 175}, // 5 + {73: 439}, + {73: 436}, + {73: 433}, + {73: 428}, {73: 425}, - {73: 422}, - {73: 419}, - {73: 414}, - {73: 411}, // 10 - {73: 400}, - {73: 388}, - {73: 384}, - {73: 380}, - {73: 372}, + {73: 414}, + {73: 402}, + {73: 398}, + {73: 394}, + {73: 386}, // 15 - {73: 369}, - {73: 366}, + {73: 383}, + {73: 371}, + {73: 364}, {73: 359}, - {73: 354}, - {73: 348}, + {73: 353}, // 20 - {73: 345}, - {73: 339}, - {73: 240}, + {73: 350}, + {73: 344}, + {73: 245}, {73: 117}, {73: 116}, // 25 @@ -615,21 +624,21 @@ var ( {73: 72}, // 65 {73: 71}, - {59: 147, 147, 68: 242, 75: 241}, - {59: 247, 246, 85: 245, 244, 100: 243}, - {146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 69: 146, 146, 77: 146}, - {336, 54: 337}, + {59: 151, 151, 68: 247, 75: 246}, + {59: 252, 251, 85: 250, 249, 101: 248}, + {150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 150, 69: 150, 150, 150, 77: 150}, + {341, 54: 342}, // 70 - {150, 54: 150}, - {82: 248}, + {154, 54: 154}, + {82: 253}, {82: 68}, {82: 67}, - {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 250, 81: 249}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 255, 81: 254}, // 75 - {54: 334, 69: 333}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 252, 80: 251}, - {137, 54: 137, 69: 137}, - {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 147, 147, 320, 75: 319}, + {54: 339, 69: 338}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 257, 80: 256}, + {141, 54: 141, 69: 141}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 151, 325, 151, 75: 324}, {66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, 66}, // 80 {65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65}, @@ -710,140 +719,151 @@ var ( {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}, // 145 - {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 69: 143, 323, 90: 332}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 321}, - {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 147, 147, 75: 322}, - {143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 69: 143, 323, 90: 324}, - {73: 325}, + {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 69: 147, 71: 328, 90: 337}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 326}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 151, 71: 151, 75: 327}, + {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 69: 147, 71: 328, 90: 329}, + {73: 330}, // 150 - {134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 134, 69: 134}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 327, 105: 326}, - {329, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 328, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 79: 330}, - {141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141}, - {144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 55: 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 78: 144}, + {138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 138, 69: 138}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 332, 106: 331}, + {334, 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, 333, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 79: 335}, + {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145}, + {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, 55: 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 148, 78: 148}, // 155 - {142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, 69: 142}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 331}, - {140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140}, - {135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 135, 69: 135}, - {148, 54: 148}, + {146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 146, 69: 146}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 336}, + {144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144, 144}, + {139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 139, 69: 139}, + {152, 54: 152}, // 160 - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 252, 80: 335}, - {136, 54: 136, 69: 136}, - {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 74: 151}, - {59: 247, 246, 85: 245, 338}, - {149, 54: 149}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 257, 80: 340}, + {140, 54: 140, 69: 140}, + {1: 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, 74: 155}, + {59: 252, 251, 85: 250, 343}, + {153, 54: 153}, // 165 - {62: 147, 147, 68: 242, 75: 340}, - {62: 342, 343, 99: 341}, - {344}, + {62: 151, 151, 68: 247, 75: 345}, + {62: 347, 348, 100: 346}, + {349}, {70}, {69}, // 170 - {1: 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, 74: 152}, - {147, 68: 242, 75: 346}, - {347}, - {1: 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, 74: 153}, - {61: 147, 64: 147, 68: 242, 75: 349}, + {1: 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, 74: 156}, + {151, 68: 247, 75: 351}, + {352}, + {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, 74: 157}, + {61: 151, 64: 151, 68: 247, 75: 354}, // 175 - {61: 352, 64: 351, 101: 350}, - {353}, + {61: 357, 64: 356, 102: 355}, + {358}, {119}, {118}, - {1: 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, 74: 154}, + {1: 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, 74: 158}, // 180 - {78: 355}, - {54: 328, 78: 145, 356}, - {78: 357}, - {358}, - {1: 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, 74: 155}, + {78: 360}, + {54: 333, 78: 149, 361}, + {78: 362}, + {363}, + {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, 74: 159}, // 185 - {68: 242, 75: 360, 77: 147}, - {77: 361}, - {65: 364, 363, 109: 362}, - {365}, + {68: 247, 75: 365, 77: 151}, + {77: 366}, + {65: 369, 368, 110: 367}, + {370}, {121}, // 190 {120}, - {1: 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, 74: 156}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 367}, - {368}, - {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, 74: 157}, + {1: 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, 74: 160}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 372}, + {373, 54: 374}, + {1: 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, 74: 162}, // 195 - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 370}, - {371}, - {1: 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, 74: 158}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 373}, - {72: 374}, + {151, 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 247, 70: 151, 75: 378, 377, 99: 376, 112: 375}, + {380, 70: 381}, + {136, 70: 136}, + {151, 68: 247, 70: 151, 75: 379}, + {134, 70: 134}, // 200 - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 377, 378, 376, 110: 375}, - {379}, + {135, 70: 135}, + {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, 74: 161}, + {151, 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 247, 70: 151, 75: 378, 377, 99: 382}, + {137, 70: 137}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 384}, + // 205 + {385}, + {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, 74: 163}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 387}, + {72: 388}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 391, 392, 390, 111: 389}, + // 210 + {393}, {124}, {123}, {122}, - // 205 - {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, 74: 159}, - {68: 242, 75: 381, 77: 147}, - {77: 382}, - {383}, - {1: 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, 74: 160}, - // 210 - {68: 242, 75: 385, 77: 147}, - {77: 386}, - {387}, - {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, 74: 161}, - {147, 55: 147, 147, 147, 147, 68: 242, 75: 389}, + {1: 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, 74: 164}, // 215 - {128, 55: 393, 394, 395, 396, 93: 392, 107: 391, 390}, - {399}, - {127, 54: 397}, + {68: 247, 75: 395, 77: 151}, + {77: 396}, + {397}, + {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, 74: 165}, + {68: 247, 75: 399, 77: 151}, + // 220 + {77: 400}, + {401}, + {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, 74: 166}, + {151, 55: 151, 151, 151, 151, 68: 247, 75: 403}, + {128, 55: 407, 408, 409, 410, 93: 406, 108: 405, 404}, + // 225 + {413}, + {127, 54: 411}, {126, 54: 126}, {85, 54: 85}, - // 220 {84, 54: 84}, + // 230 {83, 54: 83}, {82, 54: 82}, - {55: 393, 394, 395, 396, 93: 398}, + {55: 407, 408, 409, 410, 93: 412}, {125, 54: 125}, - // 225 - {1: 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, 74: 162}, - {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 402, 84: 401}, - {410}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 252, 80: 403}, - {145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 328, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 145, 79: 404}, - // 230 - {132, 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 407, 102: 406, 405}, + {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, 74: 167}, + // 235 + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 416, 84: 415}, + {424}, + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 257, 80: 417}, + {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, 333, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 149, 79: 418}, + {132, 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 421, 103: 420, 419}, + // 240 {133}, - {131, 54: 408}, + {131, 54: 422}, {130, 54: 130}, - {1: 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 409}, - // 235 + {1: 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 423}, {129, 54: 129}, - {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, 74: 163}, - {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 402, 84: 412}, - {413}, - {1: 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, 74: 164}, - // 240 - {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 417, 81: 416, 87: 415}, - {418}, - {139, 54: 334}, - {138, 280, 294, 258, 260, 304, 283, 262, 284, 282, 266, 285, 286, 287, 254, 255, 256, 257, 306, 281, 276, 288, 264, 268, 259, 261, 263, 270, 267, 265, 269, 271, 275, 273, 289, 303, 279, 290, 291, 292, 278, 274, 277, 272, 293, 305, 295, 296, 301, 302, 298, 297, 299, 300, 55: 315, 316, 317, 318, 310, 309, 311, 307, 308, 312, 314, 313, 253, 76: 252, 80: 251}, - {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, 74: 165}, // 245 - {147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 417, 81: 416, 87: 420}, - {421}, - {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, 74: 166}, - {1: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 55: 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 242, 75: 250, 81: 423}, - {424, 54: 334}, - // 250 - {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, 74: 167}, - {147, 68: 242, 75: 426}, - {427}, {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, 74: 168}, - {1: 234, 208, 200, 202, 226, 232, 214, 224, 238, 216, 210, 209, 213, 179, 197, 198, 199, 215, 235, 186, 191, 205, 217, 201, 203, 204, 219, 236, 206, 218, 220, 228, 222, 212, 187, 190, 195, 237, 196, 189, 227, 188, 221, 207, 239, 233, 211, 192, 230, 223, 225, 231, 229, 83: 193, 88: 180, 194, 91: 430, 185, 94: 184, 182, 429, 183, 181}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 416, 84: 426}, + {427}, + {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, 74: 169}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 431, 81: 430, 87: 429}, + // 250 + {432}, + {143, 54: 339}, + {142, 285, 299, 263, 265, 309, 288, 267, 289, 287, 271, 290, 291, 292, 259, 260, 261, 262, 311, 286, 281, 293, 269, 273, 264, 266, 268, 275, 272, 270, 274, 276, 280, 278, 294, 308, 284, 295, 296, 297, 283, 279, 282, 277, 298, 310, 300, 301, 306, 307, 303, 302, 304, 305, 55: 320, 321, 322, 323, 315, 314, 316, 312, 313, 317, 319, 318, 258, 76: 257, 80: 256}, + {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, 74: 170}, + {151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 431, 81: 430, 87: 434}, // 255 + {435}, {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, 74: 171}, - {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, 74: 169}, + {1: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 55: 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, 247, 75: 255, 81: 437}, + {438, 54: 339}, + {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, 74: 172}, + // 260 + {151, 68: 247, 75: 440}, + {441}, + {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, 74: 173}, + {1: 239, 213, 205, 207, 231, 237, 219, 229, 243, 221, 215, 214, 218, 184, 202, 203, 204, 220, 240, 191, 196, 210, 222, 206, 208, 209, 224, 241, 211, 223, 225, 233, 227, 217, 192, 195, 200, 242, 201, 194, 232, 193, 226, 212, 244, 238, 216, 197, 235, 228, 230, 236, 234, 83: 198, 88: 185, 199, 91: 444, 190, 94: 189, 187, 443, 188, 186}, + {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, 74: 176}, + // 265 + {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, 74: 174}, } ) @@ -883,7 +903,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) { } func yyhintParse(yylex yyhintLexer, parser *hintParser) int { - const yyError = 112 + const yyError = 114 yyEx, _ := yylex.(yyhintLexerEx) var yyn int @@ -1160,6 +1180,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.Tables, + } + } + case 19: { maxValue := uint64(math.MaxInt64) / yyS[yypt-1].number if yyS[yypt-2].number <= maxValue { @@ -1174,7 +1202,7 @@ yynewstate: parser.yyVAL.hint = nil } } - case 19: + case 20: { parser.yyVAL.hint = &ast.TableOptimizerHint{ HintName: model.NewCIStr(yyS[yypt-5].ident), @@ -1184,21 +1212,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), @@ -1206,7 +1234,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) @@ -1217,60 +1245,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), @@ -1278,7 +1306,7 @@ yynewstate: PartitionList: yyS[yypt-0].modelIdents, } } - case 40: + case 41: { parser.yyVAL.table = ast.HintTable{ DBName: model.NewCIStr(yyS[yypt-4].ident), @@ -1287,46 +1315,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 e3c3dacf4faff..d714be674a766 100644 --- a/parser/hintparser.y +++ b/parser/hintparser.y @@ -155,6 +155,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" @@ -162,6 +163,7 @@ import ( %type HintTable "Table in optimizer hint" + ViewName "View name in optimizer hint" %type PartitionList "partition name list in optimizer hint" @@ -278,6 +280,14 @@ TableOptimizerHintOpt: QBName: model.NewCIStr($3), } } +| "QB_NAME" '(' Identifier ',' ViewNameList ')' + { + $$ = &ast.TableOptimizerHint{ + HintName: model.NewCIStr($1), + QBName: model.NewCIStr($3), + Tables: $5.Tables, + } + } | "MEMORY_QUOTA" '(' QueryBlockOpt hintIntLit UnitOfBytes ')' { maxValue := uint64(math.MaxInt64) / $5 @@ -440,6 +450,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: * diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 7d66336c947c2..70786397d1b2e 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1268,6 +1268,75 @@ 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 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, clean := testkit.CreateMockStore(t) defer clean() diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index b905f973d39fe..8c41fe1fd27b5 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -57,6 +57,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" @@ -823,10 +824,10 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica // on the "USING" clause. // // According to the standard SQL, columns are ordered in the following way: -// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they -// appears in "leftPlan". -// 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". -// 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". +// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they +// appears in "leftPlan". +// 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". +// 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". func (b *PlanBuilder) buildUsingClause(p *LogicalJoin, leftPlan, rightPlan LogicalPlan, join *ast.Join) error { filter := make(map[string]bool, len(join.Using)) for _, col := range join.Using { @@ -847,9 +848,10 @@ func (b *PlanBuilder) buildUsingClause(p *LogicalJoin, leftPlan, rightPlan Logic // buildNaturalJoin builds natural join output schema. It finds out all the common columns // then using the same mechanism as buildUsingClause to eliminate redundant columns and build join conditions. // According to standard SQL, producing this display order: -// All the common columns -// Every column in the first (left) table that is not a common column -// Every column in the second (right) table that is not a common column +// +// All the common columns +// Every column in the first (left) table that is not a common column +// Every column in the second (right) table that is not a common column func (b *PlanBuilder) buildNaturalJoin(p *LogicalJoin, leftPlan, rightPlan LogicalPlan, join *ast.Join) error { err := b.coalesceCommonColumns(p, leftPlan, rightPlan, join.Tp, nil) if err != nil { @@ -1788,7 +1790,9 @@ func (b *PlanBuilder) buildUnion(ctx context.Context, selects []LogicalPlan, aft // divideUnionSelectPlans resolves union's select stmts to logical plans. // and divide result plans into "union-distinct" and "union-all" parts. // divide rule ref: -// https://dev.mysql.com/doc/refman/5.7/en/union.html +// +// https://dev.mysql.com/doc/refman/5.7/en/union.html +// // "Mixed UNION types are treated such that a DISTINCT union overrides any ALL union to its left." func (b *PlanBuilder) divideUnionSelectPlans(ctx context.Context, selects []LogicalPlan, setOprTypes []*ast.SetOprType) (distinctSelects []LogicalPlan, allSelects []LogicalPlan, err error) { firstUnionAllIdx := 0 @@ -4233,7 +4237,36 @@ 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 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 { + if len(viewQBNameHintTable) == 0 { + continue + } + viewSelectOffset := b.getSelectOffset() + + var viewHintSelectOffset int + if viewQBNameHintTable[0].QBName.L == "" { + // 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) + } + + // Check whether the current view can match the view name in the hint. + if viewQBNameHintTable[0].TableName.L == tblName.L && viewHintSelectOffset == viewSelectOffset { + // 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) + } + } + return b.BuildDataSourceFromView(ctx, dbName, tableInfo, currentQBNameMap4View, currentViewHints) } if tableInfo.IsSequence() { @@ -4743,8 +4776,10 @@ func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIS return func() { delete(b.buildingViewStack, viewFullName) }, nil } -// BuildDataSourceFromView is used to build LogicalPlan from view -func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model.CIStr, tableInfo *model.TableInfo) (LogicalPlan, error) { +// 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) { deferFunc, err := b.checkRecursiveView(dbName, tableInfo.Name) if err != nil { return nil, err @@ -4760,6 +4795,52 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. } originalVisitInfo := b.visitInfo b.visitInfo = make([]visitInfo, 0) + + hintProcessor := &hint.BlockHintProcessor{Ctx: b.ctx} + 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 { + // Check whether the view hint belong the current view or its nested views. + selectOffset := -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 { + // 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 + + 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/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index a2a6c7e655efc..fb5055d467972 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -627,6 +627,73 @@ "desc format = 'brief' select /*+ read_from_storage(tiflash[t, ttt], tikv[tt]) */ * from ttt" ] }, + { + "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), 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;" + ] + }, + { + "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 f3f200872b93e..0d385de913db1 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4121,6 +4121,1198 @@ } ] }, + { + "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), 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)]", + "├─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))", + "│ └─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), 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", + "└─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 . 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": 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 + } + ] + }, + { + "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": [ + "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", + "│ │ │ └─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, 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 1bc49d92da301..e0ab49478f267 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -315,8 +315,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. - QbHints map[int][]*ast.TableOptimizerHint // Group all hints at same query block. + 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 } @@ -335,8 +340,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 } @@ -355,9 +367,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(errors.New(fmt.Sprintf("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 @@ -378,6 +396,75 @@ 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 + 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)) + } + } 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 != "" { + _, ok = p.QbNameMap4View[qbName] + } 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 + } + } + } + } + + 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 b075ecb703171ea8e558a93e5867f12e1e0f1819 Mon Sep 17 00:00:00 2001 From: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> Date: Tue, 15 Nov 2022 14:13:54 +0800 Subject: [PATCH 02/10] git add more test cases --- planner/core/integration_test.go | 108 +++++++++++++++++- planner/core/logical_plan_builder.go | 1 - .../core/testdata/integration_suite_in.json | 57 ++++++++- util/hint/hint_processor.go | 30 +++++ 4 files changed, 187 insertions(+), 9 deletions(-) diff --git a/planner/core/integration_test.go b/planner/core/integration_test.go index 70786397d1b2e..b11bf88f3e117 100644 --- a/planner/core/integration_test.go +++ b/planner/core/integration_test.go @@ -1269,11 +1269,12 @@ func TestReadFromStorageHint(t *testing.T) { } func TestViewHint(t *testing.T) { - store := testkit.CreateMockStore(t) + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") - tk.MustExec("drop view if exists v, v1") + tk.MustExec("drop view if exists v, v1, v2") 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);") @@ -1289,7 +1290,7 @@ func TestViewHint(t *testing.T) { Warn []string } integrationSuiteData := core.GetIntegrationSuiteData() - integrationSuiteData.LoadTestCases(t, &input, &output) + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { testdata.OnRecord(func() { output[i].SQL = tt @@ -1303,7 +1304,45 @@ func TestViewHint(t *testing.T) { } func TestViewHintScope(t *testing.T) { - store := testkit.CreateMockStore(t) + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("drop view if exists v, v1, v2, v3") + 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;") + tk.MustExec("create definer='root'@'localhost' view v3 as select /*+ merge_join(t) */ t.a, t.b from t join (select /*+ stream_agg() */ 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.GetTestCases(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 TestViewHintWithBinding(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() tk := testkit.NewTestKit(t, store) tk.MustExec("use test") @@ -1317,6 +1356,65 @@ func TestViewHintScope(t *testing.T) { 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;") + tk.MustExec("select * from v2") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + tk.MustExec("create global binding for select * from v2 using select /*+ qb_name(qb_v_2, v2.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. v1@sel_2 .v@sel_2 .@sel_1), merge_join(t@qb_v_1) */ * from v2;") + tk.MustExec("select * from v2") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("1")) + res := tk.MustQuery("show global bindings").Rows() + require.Equal(t, res[0][0], "select * from `test` . `v2`") + require.Equal(t, res[0][1], "SELECT /*+ qb_name(`qb_v_2` , `v2`. `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`. `v1`@`sel_2`. `v`@`sel_2`. ``@`sel_1`) merge_join(`t`@`qb_v_1`)*/ * FROM `test`.`v2`") + + tk.MustExec("drop global binding for select * from v2") + tk.MustExec("select * from v2") + tk.MustQuery("select @@last_plan_from_binding").Check(testkit.Rows("0")) + res = tk.MustQuery("show global bindings").Rows() + require.Equal(t, len(res), 0) +} + +func TestAllViewHintType(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + + tk.MustExec("use test") + tk.MustExec("set @@session.tidb_allow_mpp=ON") + tk.MustExec("set @@session.tidb_isolation_read_engines='tiflash, tikv'") + tk.MustExec("drop view if exists v, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12") + tk.MustExec("drop table if exists t, t1, t2, t4, t3, t5") + tk.MustExec("create table t(a int not null, b int, index idx_a(a));") + tk.MustExec("create table t1(a int not null, b int, index idx_a(a));") + tk.MustExec("create table t2(a int, b int, index idx_a(a));") + tk.MustExec("create table t3(a int, b int, index idx_a(a));") + tk.MustExec("create table t4(a int, b int, index idx_a(a));") + tk.MustExec("create table t5(a int, b int, index idx_a(a), index idx_b(b));") + + // Create virtual tiflash replica info. + dom := domain.GetDomain(tk.Session()) + is := dom.InfoSchema() + db, exists := is.SchemaByName(model.NewCIStr("test")) + require.True(t, exists) + for _, tblInfo := range db.Tables { + if tblInfo.Name.L == "t" { + tblInfo.TiFlashReplica = &model.TiFlashReplicaInfo{ + Count: 1, + Available: true, + } + } + } + + tk.MustExec("create definer='root'@'localhost' view v as select t.a, t.b from t join t1 on t.a = t1.a;") + tk.MustExec("create definer='root'@'localhost' view v1 as select t2.a, t2.b from t2 join t3 join v where t2.b = t3.b and t3.a = v.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;") + tk.MustExec("create definer='root'@'localhost' view v3 as select * from t5 where a > 1 and b < 2;") + tk.MustExec("create definer='root'@'localhost' view v4 as select * from t5 where a > 1 or b < 2;") + tk.MustExec("create definer='root'@'localhost' view v5 as SELECT * FROM t WHERE EXISTS (SELECT 1 FROM t1 WHERE t1.b = t.b);") + tk.MustExec("create definer='root'@'localhost' view v6 as select * from t1 where t1.a < (select sum(t2.a) from t2 where t2.b = t1.b);") + tk.MustExec("create definer='root'@'localhost' view v9 as select sum(a) from t;") + tk.MustExec("create definer='root'@'localhost' view v10 as SELECT * FROM t WHERE a > 10 ORDER BY b LIMIT 1;") + tk.MustExec("create definer='root'@'localhost' view v11 as select a, sum(b) from t group by a") + tk.MustExec("create definer='root'@'localhost' view v12 as select t.a, t.b from t join t t1 on t.a = t1.a;") + var input []string var output []struct { SQL string @@ -1324,7 +1422,7 @@ func TestViewHintScope(t *testing.T) { Warn []string } integrationSuiteData := core.GetIntegrationSuiteData() - integrationSuiteData.LoadTestCases(t, &input, &output) + integrationSuiteData.GetTestCases(t, &input, &output) for i, tt := range input { testdata.OnRecord(func() { output[i].SQL = tt diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 8c41fe1fd27b5..d1c78b39ee0d5 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4806,7 +4806,6 @@ func (b *PlanBuilder) BuildDataSourceFromView(ctx context.Context, dbName model. for qbName, viewQbNameHint := range qbNameMap4View { // Check whether the view hint belong the current view or its nested views. selectOffset := -1 - qbNameMap4View[qbName] = viewQbNameHint if len(viewQbNameHint) == 0 { selectOffset = 1 } else if len(viewQbNameHint) == 1 && viewQbNameHint[0].TableName.L == "" { diff --git a/planner/core/testdata/integration_suite_in.json b/planner/core/testdata/integration_suite_in.json index fb5055d467972..d755966372f46 100644 --- a/planner/core/testdata/integration_suite_in.json +++ b/planner/core/testdata/integration_suite_in.json @@ -632,7 +632,7 @@ "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), 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, v@sel_1 .@sel_2), merge_join(t1@qb_v_2), stream_agg(@qb_v_2), qb_name(qb_v_1, v@sel_1 .@sel_1), 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;", @@ -646,7 +646,7 @@ // 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;" + "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, v2), merge_join(t@qb_v2_1) */ * from v2;" ] }, { @@ -691,7 +691,58 @@ // 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;" + "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 .@sel_1) */ * from v;", + + // The view contains the hint when creation + "explain format = 'brief' select /*+ qb_name(qb_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2), hash_agg(@qb_v3_2), qb_name(qb_v3_1, v3@sel_1 .@sel_1), hash_join(t@qb_v3_1) */ * from v3;" + ] + }, + { + "name": "TestAllViewHintType", + "cases": [ + // leading hint + // join nodes in the same view + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 v, t2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(v@qb_v1, t2@qb_v1) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 t3, t2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(t3@qb_v1, t2@qb_v1) */ * from v1;", + + // join node across view + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), qb_name(qb_v, v1.v), leading(t2@qb_v1, t@qb_v) */ * from v1;", + + // hash_join hint + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(@qb_v1 v, t2) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(t2@qb_v1, t3@qb_v1) */ * from v1;", + + // merge join hint + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(@qb_v1 v) */ * from v1;", + "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(t2@qb_v1) */ * from v1;", + + // index join hint + "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(@qb_v t) */ * from v;", + "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(t@qb_v) */ * from v;", + + // agg hint + "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), hash_agg(@qb_v2) */ * from v2;", + "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), stream_agg(@qb_v2) */ * from v2;", + + // index hint + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(t5@qb_v3, idx_a) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(@qb_v3 t5, idx_b) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(t5@qb_v3, idx_a) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(@qb_v3 t5, idx_b) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(t5@qb_v3, idx_a) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(@qb_v3 t5, idx_b) */ * from v3;", + "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(t5@qb_v4, idx_a, idx_b) */ * from v4;", + "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(@qb_v4 t5, idx_b, idx_a) */ * from v4;", + + // read from storage + "explain format = 'brief' select /*+ qb_name(qb_v, v), READ_FROM_STORAGE(TIFLASH[t@qb_v], TIKV[t1@qb_v]) */ * from v;", + + // agg to cop hint + "explain format = 'brief' select /*+ qb_name(qb_v9, v9), AGG_TO_COP(@qb_v9) */ * from v9;", + "explain format = 'brief' select /*+ qb_name(qb_v10, v10), LIMIT_TO_COP(@qb_v10) */ * from v10;" ] }, { diff --git a/util/hint/hint_processor.go b/util/hint/hint_processor.go index e0ab49478f267..5bd383773eab2 100644 --- a/util/hint/hint_processor.go +++ b/util/hint/hint_processor.go @@ -274,6 +274,13 @@ func ParseHintsSet(p *parser.Parser, sql, charset, collation, db string) (*Hints } for _, tblHint := range tblHints { if tblHint.HintName.L == hintQBName { + if len(tblHint.Tables) > 0 { + newHints = append(newHints, tblHint) + } + continue + } + if processor.isHint4View(tblHint) { + newHints = append(newHints, tblHint) continue } offset := processor.GetHintOffset(tblHint.QBName, curOffset) @@ -445,6 +452,10 @@ func (p *BlockHintProcessor) handleViewHints(hints []*ast.TableOptimizerHint) (l break } } + if !ok { + p.Ctx.GetSessionVars().StmtCtx.AppendWarning(fmt.Errorf("Only one query block name is allowed in a view hint, otherwise the hint will be invalid")) + usedHints[i] = true + } } } @@ -540,6 +551,25 @@ func (p *BlockHintProcessor) checkTableQBName(tables []ast.HintTable) bool { return true } +func (p *BlockHintProcessor) isHint4View(hint *ast.TableOptimizerHint) bool { + if hint.QBName.L != "" { + if p.QbNameMap4View != nil { + _, ok := p.QbNameMap4View[hint.QBName.L] + return ok + } + return false + } + allViewHints := true + for _, table := range hint.Tables { + qbName := table.QBName.L + if _, ok := p.QbNameMap4View[qbName]; !ok { + allViewHints = false + break + } + } + return allViewHints +} + // GetCurrentStmtHints extracts all hints that take effects at current stmt. func (p *BlockHintProcessor) GetCurrentStmtHints(hints []*ast.TableOptimizerHint, currentOffset int) []*ast.TableOptimizerHint { if p.QbHints == nil { From 01aafcd654fab042c4181c4f2c5b93295cdf4bf9 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 15 Nov 2022 16:35:18 +0800 Subject: [PATCH 03/10] update the test cases --- .../core/testdata/integration_suite_out.json | 378 ++++++++++++++++++ 1 file changed, 378 insertions(+) diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 0d385de913db1..25cc90b4b5055 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -5313,6 +5313,384 @@ } ] }, + { + "Name": "TestAllViewHintType", + "Cases": [ + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 v, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": [ + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(v@qb_v1, t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": [ + "[planner:1815]We can only use one leading hint at most, when multiple leading hints are used, all leading hints will be invalid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(@qb_v1 t3, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), leading(t3@qb_v1, t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), qb_name(qb_v, v1.v), leading(t2@qb_v1, t@qb_v) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t3.a, test.t.a)]", + " ├─TableReader(Build) 10000.00 root data:TableFullScan", + " │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + " └─HashJoin(Probe) 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": [ + "Only one query block name is allowed in a view hint, otherwise the hint will be invalid" + ] + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(@qb_v1 v, t2) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "├─HashJoin(Build) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 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", + "└─HashJoin(Probe) 12500.00 root inner join, equal:[eq(test.t.a, test.t1.a)]", + " ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), hash_join(t2@qb_v1, t3@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t3.a)]", + "├─HashJoin(Build) 12475.01 root inner join, equal:[eq(test.t2.b, test.t3.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 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", + "└─HashJoin(Probe) 12500.00 root inner join, equal:[eq(test.t.a, test.t1.a)]", + " ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(@qb_v1 v) */ * from v1;", + "Plan": [ + "MergeJoin 19492.21 root inner join, left key:test.t3.a, right key:test.t.a", + "├─MergeJoin(Build) 12500.00 root inner join, left key:test.t.a, right key:test.t1.a", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:true, stats:pseudo", + "│ └─IndexReader(Probe) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t, index:idx_a(a) keep order:true, stats:pseudo", + "└─Sort(Probe) 12475.01 root test.t3.a", + " └─Projection 12475.01 root test.t2.a, test.t2.b, test.t3.a", + " └─HashJoin 12475.01 root inner join, equal:[eq(test.t3.b, test.t2.b)]", + " ├─TableReader(Build) 9980.01 root data:Selection", + " │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + " │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + " └─TableReader(Probe) 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" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v1, v1), merge_join(t2@qb_v1) */ * from v1;", + "Plan": [ + "HashJoin 19492.21 root inner join, equal:[eq(test.t.a, test.t3.a)]", + "├─MergeJoin(Build) 12475.01 root inner join, left key:test.t2.b, right key:test.t3.b", + "│ ├─Sort(Build) 9980.01 root test.t3.b", + "│ │ └─TableReader 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─Sort(Probe) 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", + "└─HashJoin(Probe) 12500.00 root inner join, equal:[eq(test.t.a, test.t1.a)]", + " ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + " │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + " └─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(@qb_v t) */ * from v;", + "Plan": [ + "IndexJoin 12500.00 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t.a, equal cond:eq(test.t1.a, test.t.a)", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─IndexRangeScan(Build) 1.25 cop[tikv] table:t, index:idx_a(a) range: decided by [eq(test.t.a, test.t1.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), INL_JOIN(t@qb_v) */ * from v;", + "Plan": [ + "IndexJoin 12500.00 root inner join, inner:IndexLookUp, outer key:test.t1.a, inner key:test.t.a, equal cond:eq(test.t1.a, test.t.a)", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─IndexLookUp(Probe) 1.25 root ", + " ├─IndexRangeScan(Build) 1.25 cop[tikv] table:t, index:idx_a(a) range: decided by [eq(test.t.a, test.t1.a)], keep order:false, stats:pseudo", + " └─TableRowIDScan(Probe) 1.25 cop[tikv] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), hash_agg(@qb_v2) */ * from v2;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#19)]", + "├─HashAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ └─HashJoin 24365.26 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 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.t3.b, test.t2.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 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) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v2, v2.@sel_2), stream_agg(@qb_v2) */ * from v2;", + "Plan": [ + "HashJoin 9990.00 root inner join, equal:[eq(test.t.a, Column#19)]", + "├─StreamAgg(Build) 7992.00 root group by:test.t2.a, funcs:count(1)->Column#19", + "│ └─Sort 24365.26 root test.t2.a", + "│ └─HashJoin 24365.26 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "│ ├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ │ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 19492.21 root inner join, equal:[eq(test.t3.a, test.t.a)]", + "│ ├─TableReader(Build) 10000.00 root data:TableFullScan", + "│ │ └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo", + "│ └─HashJoin(Probe) 15593.77 root inner join, equal:[eq(test.t2.b, test.t1.b)]", + "│ ├─TableReader(Build) 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.t3.b, test.t2.b)]", + "│ ├─TableReader(Build) 9980.01 root data:Selection", + "│ │ └─Selection 9980.01 cop[tikv] not(isnull(test.t3.a)), not(isnull(test.t3.b))", + "│ │ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo", + "│ └─TableReader(Probe) 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) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] lt(test.t5.b, 2)", + " └─TableRowIDScan 3333.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), use_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] gt(test.t5.a, 1)", + " └─TableRowIDScan 3323.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] lt(test.t5.b, 2)", + " └─TableRowIDScan 3333.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), force_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "IndexLookUp 1107.78 root ", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─Selection(Probe) 1107.78 cop[tikv] gt(test.t5.a, 1)", + " └─TableRowIDScan 3323.33 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(t5@qb_v3, idx_a) */ * from v3;", + "Plan": [ + "TableReader 1107.78 root data:Selection", + "└─Selection 1107.78 cop[tikv] gt(test.t5.a, 1), lt(test.t5.b, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v3, v3), ignore_index(@qb_v3 t5, idx_b) */ * from v3;", + "Plan": [ + "TableReader 1107.78 root data:Selection", + "└─Selection 1107.78 cop[tikv] gt(test.t5.a, 1), lt(test.t5.b, 2)", + " └─TableFullScan 10000.00 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(t5@qb_v4, idx_a, idx_b) */ * from v4;", + "Plan": [ + "IndexMerge 5548.89 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─TableRowIDScan(Probe) 5548.89 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v4, v4), use_index_merge(@qb_v4 t5, idx_b, idx_a) */ * from v4;", + "Plan": [ + "IndexMerge 5548.89 root ", + "├─IndexRangeScan(Build) 3333.33 cop[tikv] table:t5, index:idx_a(a) range:(1,+inf], keep order:false, stats:pseudo", + "├─IndexRangeScan(Build) 3323.33 cop[tikv] table:t5, index:idx_b(b) range:[-inf,2), keep order:false, stats:pseudo", + "└─TableRowIDScan(Probe) 5548.89 cop[tikv] table:t5 keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v, v), READ_FROM_STORAGE(TIFLASH[t@qb_v], TIKV[t1@qb_v]) */ * from v;", + "Plan": [ + "HashJoin 12500.00 root inner join, equal:[eq(test.t.a, test.t1.a)]", + "├─IndexReader(Build) 10000.00 root index:IndexFullScan", + "│ └─IndexFullScan 10000.00 cop[tikv] table:t1, index:idx_a(a) keep order:false, stats:pseudo", + "└─TableReader(Probe) 10000.00 root data:TableFullScan", + " └─TableFullScan 10000.00 cop[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v9, v9), AGG_TO_COP(@qb_v9) */ * from v9;", + "Plan": [ + "HashAgg 1.00 root funcs:sum(Column#6)->Column#4", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─HashAgg 1.00 mpp[tiflash] funcs:sum(Column#8)->Column#6", + " └─Projection 10000.00 mpp[tiflash] cast(test.t.a, decimal(10,0) BINARY)->Column#8", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + }, + { + "SQL": "explain format = 'brief' select /*+ qb_name(qb_v10, v10), LIMIT_TO_COP(@qb_v10) */ * from v10;", + "Plan": [ + "TopN 1.00 root test.t.b, offset:0, count:1", + "└─TableReader 1.00 root data:ExchangeSender", + " └─ExchangeSender 1.00 mpp[tiflash] ExchangeType: PassThrough", + " └─TopN 1.00 mpp[tiflash] test.t.b, offset:0, count:1", + " └─Selection 3333.33 mpp[tiflash] gt(test.t.a, 10)", + " └─TableFullScan 10000.00 mpp[tiflash] table:t keep order:false, stats:pseudo" + ], + "Warn": null + } + ] + }, { "Name": "TestReadFromStorageHintAndIsolationRead", "Cases": [ From edfafbc4d82ddc4acfd679d8cd04c64b4ae2d690 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 15 Nov 2022 16:37:41 +0800 Subject: [PATCH 04/10] update the test cases --- .../core/testdata/integration_suite_out.json | 126 +++++++++++++++--- 1 file changed, 109 insertions(+), 17 deletions(-) diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 25cc90b4b5055..49dd20c22a00a 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -5059,7 +5059,7 @@ " └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo" ], "Warn": [ - "Hint merge_join(`t1`@`qb_v1_2`, `t`@`qb_v1_1`) is ignored due to unknown query block name" + "Only one query block name is allowed in a view hint, otherwise the hint will be invalid" ] }, { @@ -5289,27 +5289,119 @@ "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;", + "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 .@sel_1) */ * 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", + "MergeJoin 9980.01 root inner join, left key:test.t.a, right key:Column#13", + "├─Sort(Build) 7984.01 root Column#13", + "│ └─StreamAgg 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", + "└─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_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2) */ * from v3;", + "Plan": [ + "MergeJoin 9980.01 root inner join, left key:test.t.a, right key:Column#27", + "├─Sort(Build) 7984.01 root Column#27", + "│ └─StreamAgg 7984.01 root group by:test.t.a, funcs:count(1)->Column#27", + "│ └─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#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", + "└─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_v3_2, v3@sel_1 .@sel_2), merge_join(t1@qb_v3_2), hash_agg(@qb_v3_2), qb_name(qb_v3_1, v3@sel_1 .@sel_1), hash_join(t@qb_v3_1) */ * from v3;", + "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 + "Warn": [ + "[planner:1815]Join hints are conflict, you can only specify one type of join", + "[planner:1815]Optimizer aggregation hints are conflicted" + ] } ] }, From 8ac5c0b4006467fa3eee91aa98f8d9e5a8d51103 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 15 Nov 2022 16:39:17 +0800 Subject: [PATCH 05/10] update the test cases --- .../core/testdata/integration_suite_out.json | 106 +++++++++--------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/planner/core/testdata/integration_suite_out.json b/planner/core/testdata/integration_suite_out.json index 49dd20c22a00a..f68588176c2e4 100644 --- a/planner/core/testdata/integration_suite_out.json +++ b/planner/core/testdata/integration_suite_out.json @@ -4145,23 +4145,25 @@ "Warn": null }, { - "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)]", - "├─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" + "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 .@sel_1), merge_join(t@qb_v_1) */ * from v;", + "Plan": [ + "MergeJoin 9990.00 root inner join, left key:test.t.a, right key:Column#10", + "├─Sort(Build) 7992.00 root Column#10", + "│ └─StreamAgg 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", + "└─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 }, @@ -4477,41 +4479,43 @@ "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;", + "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, v2), 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" + "MergeJoin 9980.01 root inner join, left key:test.t.a, right key:Column#24", + "├─Sort(Build) 7984.01 root Column#24", + "│ └─StreamAgg 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", + "└─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 } From 31af17ab8cf250179e75effdf5f5ea21f53fb560 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 15 Nov 2022 16:49:13 +0800 Subject: [PATCH 06/10] fix --- planner/core/logical_plan_builder.go | 1 + 1 file changed, 1 insertion(+) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index d1c78b39ee0d5..b309ff559cfe8 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -4776,6 +4776,7 @@ func (b *PlanBuilder) checkRecursiveView(dbName model.CIStr, tableName model.CIS return func() { delete(b.buildingViewStack, viewFullName) }, nil } +// 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. From 19d0b844c4aea762ef023cc262957eb0fecb37a7 Mon Sep 17 00:00:00 2001 From: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> Date: Tue, 15 Nov 2022 16:50:34 +0800 Subject: [PATCH 07/10] Update planner/core/logical_plan_builder.go --- planner/core/logical_plan_builder.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index d1c78b39ee0d5..f167c17534274 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -824,10 +824,10 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica // on the "USING" clause. // // According to the standard SQL, columns are ordered in the following way: -// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they -// appears in "leftPlan". -// 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". -// 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". +// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they + // appears in "leftPlan". + // 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". + // 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". func (b *PlanBuilder) buildUsingClause(p *LogicalJoin, leftPlan, rightPlan LogicalPlan, join *ast.Join) error { filter := make(map[string]bool, len(join.Using)) for _, col := range join.Using { From 1397b355dfcd2caa245508691bef0ced968be2ef Mon Sep 17 00:00:00 2001 From: Chengpeng Yan <41809508+Reminiscent@users.noreply.github.com> Date: Tue, 15 Nov 2022 16:51:15 +0800 Subject: [PATCH 08/10] Update planner/core/logical_plan_builder.go --- planner/core/logical_plan_builder.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index f167c17534274..6b89569105be8 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1790,9 +1790,7 @@ func (b *PlanBuilder) buildUnion(ctx context.Context, selects []LogicalPlan, aft // divideUnionSelectPlans resolves union's select stmts to logical plans. // and divide result plans into "union-distinct" and "union-all" parts. // divide rule ref: -// -// https://dev.mysql.com/doc/refman/5.7/en/union.html -// +// https://dev.mysql.com/doc/refman/5.7/en/union.html // "Mixed UNION types are treated such that a DISTINCT union overrides any ALL union to its left." func (b *PlanBuilder) divideUnionSelectPlans(ctx context.Context, selects []LogicalPlan, setOprTypes []*ast.SetOprType) (distinctSelects []LogicalPlan, allSelects []LogicalPlan, err error) { firstUnionAllIdx := 0 From 02322066f5249e1d07f04c9756860dce1624c707 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Tue, 15 Nov 2022 16:57:21 +0800 Subject: [PATCH 09/10] update --- planner/core/logical_plan_builder.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index 550137479601b..b309ff559cfe8 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -824,10 +824,10 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica // on the "USING" clause. // // According to the standard SQL, columns are ordered in the following way: -// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they - // appears in "leftPlan". - // 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". - // 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". +// 1. coalesced common columns of "leftPlan" and "rightPlan", in the order they +// appears in "leftPlan". +// 2. the rest columns in "leftPlan", in the order they appears in "leftPlan". +// 3. the rest columns in "rightPlan", in the order they appears in "rightPlan". func (b *PlanBuilder) buildUsingClause(p *LogicalJoin, leftPlan, rightPlan LogicalPlan, join *ast.Join) error { filter := make(map[string]bool, len(join.Using)) for _, col := range join.Using { @@ -1790,7 +1790,9 @@ func (b *PlanBuilder) buildUnion(ctx context.Context, selects []LogicalPlan, aft // divideUnionSelectPlans resolves union's select stmts to logical plans. // and divide result plans into "union-distinct" and "union-all" parts. // divide rule ref: -// https://dev.mysql.com/doc/refman/5.7/en/union.html +// +// https://dev.mysql.com/doc/refman/5.7/en/union.html +// // "Mixed UNION types are treated such that a DISTINCT union overrides any ALL union to its left." func (b *PlanBuilder) divideUnionSelectPlans(ctx context.Context, selects []LogicalPlan, setOprTypes []*ast.SetOprType) (distinctSelects []LogicalPlan, allSelects []LogicalPlan, err error) { firstUnionAllIdx := 0 From 845f4609901d9325779c6abaa470cfabc36ee5e1 Mon Sep 17 00:00:00 2001 From: Reminiscent Date: Wed, 16 Nov 2022 14:47:34 +0800 Subject: [PATCH 10/10] update --- parser/ast/misc.go | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/parser/ast/misc.go b/parser/ast/misc.go index 5fc1feb396b1a..b4a348cd804c6 100644 --- a/parser/ast/misc.go +++ b/parser/ast/misc.go @@ -1808,9 +1808,10 @@ type StatisticsSpec struct { // CreateStatisticsStmt is a statement to create extended statistics. // Examples: -// CREATE STATISTICS stats1 (cardinality) ON t(a, b, c); -// CREATE STATISTICS stats2 (dependency) ON t(a, b); -// CREATE STATISTICS stats3 (correlation) ON t(a, b); +// +// CREATE STATISTICS stats1 (cardinality) ON t(a, b, c); +// CREATE STATISTICS stats2 (dependency) ON t(a, b); +// CREATE STATISTICS stats3 (correlation) ON t(a, b); type CreateStatisticsStmt struct { stmtNode @@ -1878,7 +1879,8 @@ func (n *CreateStatisticsStmt) Accept(v Visitor) (Node, bool) { // DropStatisticsStmt is a statement to drop extended statistics. // Examples: -// DROP STATISTICS stats1; +// +// DROP STATISTICS stats1; type DropStatisticsStmt struct { stmtNode @@ -2009,6 +2011,7 @@ const ( ) // ShowSlow is used for the following command: +// // admin show slow top [ internal | all] N // admin show slow recent N type ShowSlow struct { @@ -3464,9 +3467,13 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { } ctx.WriteName(n.QBName.String()) } + if n.HintName.L == "qb_name" && len(n.Tables) == 0 { + ctx.WritePlain(")") + return nil + } // Hints without args except query block. switch n.HintName.L { - case "hash_agg", "stream_agg", "agg_to_cop", "read_consistent_replica", "no_index_merge", "qb_name", "ignore_plan_cache", "limit_to_cop", "straight_join": + case "hash_agg", "stream_agg", "agg_to_cop", "read_consistent_replica", "no_index_merge", "ignore_plan_cache", "limit_to_cop", "straight_join": ctx.WritePlain(")") return nil } @@ -3495,6 +3502,16 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error { } ctx.WriteName(index.String()) } + case "qb_name": + if len(n.Tables) > 0 { + ctx.WritePlain(", ") + for i, table := range n.Tables { + if i != 0 { + ctx.WritePlain(". ") + } + table.Restore(ctx) + } + } case "use_toja", "use_cascades": if n.HintData.(bool) { ctx.WritePlain("TRUE")