From 001eaf669efaf30efebf221c16c70974d75e1074 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 29 Apr 2022 15:53:54 +0800
Subject: [PATCH 01/10] parser: support join order hint

---
 parser/ast/misc.go      |    4 +-
 parser/ast/misc_test.go |   10 +
 parser/hintparser.go    | 1079 ++++++++++++++++++++-------------------
 parser/hintparser.y     |    6 +
 parser/misc.go          |    2 +
 parser/parser_test.go   |   32 ++
 6 files changed, 599 insertions(+), 534 deletions(-)

diff --git a/parser/ast/misc.go b/parser/ast/misc.go
index ab42cfbc13192..3c95431f1ceb8 100644
--- a/parser/ast/misc.go
+++ b/parser/ast/misc.go
@@ -3417,7 +3417,7 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error {
 	}
 	// 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":
+	case "hash_agg", "stream_agg", "agg_to_cop", "read_consistent_replica", "no_index_merge", "qb_name", "ignore_plan_cache", "limit_to_cop", "straight_join":
 		ctx.WritePlain(")")
 		return nil
 	}
@@ -3430,7 +3430,7 @@ func (n *TableOptimizerHint) Restore(ctx *format.RestoreCtx) error {
 		ctx.WritePlainf("%d", n.HintData.(uint64))
 	case "nth_plan":
 		ctx.WritePlainf("%d", n.HintData.(int64))
-	case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "merge_join", "inl_join", "broadcast_join", "inl_hash_join", "inl_merge_join":
+	case "tidb_hj", "tidb_smj", "tidb_inlj", "hash_join", "merge_join", "inl_join", "broadcast_join", "inl_hash_join", "inl_merge_join", "leading":
 		for i, table := range n.Tables {
 			if i != 0 {
 				ctx.WritePlain(", ")
diff --git a/parser/ast/misc_test.go b/parser/ast/misc_test.go
index 7b7df348f86fa..6aa2c5b1ac5cc 100644
--- a/parser/ast/misc_test.go
+++ b/parser/ast/misc_test.go
@@ -245,6 +245,15 @@ func TestTableOptimizerHintRestore(t *testing.T) {
 		{"USE_INDEX_MERGE(t1 c1)", "USE_INDEX_MERGE(`t1` `c1`)"},
 		{"USE_INDEX_MERGE(@sel1 t1 c1)", "USE_INDEX_MERGE(@`sel1` `t1` `c1`)"},
 		{"USE_INDEX_MERGE(t1@sel1 c1)", "USE_INDEX_MERGE(`t1`@`sel1` `c1`)"},
+		{"LEADING(t1)", "LEADING(`t1`)"},
+		{"LEADING(t1 c1)", "LEADING(`t1` `c1`)"},
+		{"LEADING(t1 c1 t2)", "LEADING(`t1` `c1` `t2`)"},
+		{"LEADING(@sel1 t1 c1)", "LEADING(@`sel1` `t1` `c1`)"},
+		{"LEADING(@sel1 t1)", "LEADING(@`sel1` `t1`)"},
+		{"LEADING(@sel1 t1 c1 t2)", "LEADING(@`sel1` `t1` `c1` `t2`)"},
+		{"LEADING(t1@sel1)", "LEADING(`t1`@`sel1`)"},
+		{"LEADING(t1@sel1 c1)", "LEADING(`t1`@`sel1` `c1`)"},
+		{"LEADING(t1@sel1 c1 t2)", "LEADING(`t1`@`sel1` `c1` `t2`)"},
 		{"USE_TOJA(TRUE)", "USE_TOJA(TRUE)"},
 		{"USE_TOJA(FALSE)", "USE_TOJA(FALSE)"},
 		{"USE_TOJA(@sel1 TRUE)", "USE_TOJA(@`sel1` TRUE)"},
@@ -265,6 +274,7 @@ func TestTableOptimizerHintRestore(t *testing.T) {
 		{"AGG_TO_COP()", "AGG_TO_COP()"},
 		{"AGG_TO_COP(@sel_1)", "AGG_TO_COP(@`sel_1`)"},
 		{"LIMIT_TO_COP()", "LIMIT_TO_COP()"},
+		{"STRAIGHT_JOIN()", "STRAIGHT_JOIN()"},
 		{"NO_INDEX_MERGE()", "NO_INDEX_MERGE()"},
 		{"NO_INDEX_MERGE(@sel1)", "NO_INDEX_MERGE(@`sel1`)"},
 		{"READ_CONSISTENT_REPLICA()", "READ_CONSISTENT_REPLICA()"},
diff --git a/parser/hintparser.go b/parser/hintparser.go
index 4020f5832970d..b86638e44b682 100644
--- a/parser/hintparser.go
+++ b/parser/hintparser.go
@@ -41,18 +41,18 @@ type yyhintXError struct {
 }
 
 const (
-	yyhintDefault             = 57415
+	yyhintDefault             = 57417
 	yyhintEOFCode             = 57344
 	yyhintErrCode             = 57345
 	hintAggToCop              = 57377
 	hintBCJoin                = 57390
 	hintBKA                   = 57355
 	hintBNL                   = 57357
-	hintDupsWeedOut           = 57411
-	hintFalse                 = 57407
-	hintFirstMatch            = 57412
+	hintDupsWeedOut           = 57413
+	hintFalse                 = 57409
+	hintFirstMatch            = 57414
 	hintForceIndex            = 57401
-	hintGB                    = 57410
+	hintGB                    = 57412
 	hintHashAgg               = 57379
 	hintHashJoin              = 57359
 	hintIdentifier            = 57347
@@ -68,11 +68,12 @@ const (
 	hintJoinOrder             = 57352
 	hintJoinPrefix            = 57353
 	hintJoinSuffix            = 57354
+	hintLeading               = 57403
 	hintLimitToCop            = 57400
-	hintLooseScan             = 57413
-	hintMB                    = 57409
+	hintLooseScan             = 57415
+	hintMB                    = 57411
 	hintMRR                   = 57365
-	hintMaterialization       = 57414
+	hintMaterialization       = 57416
 	hintMaxExecutionTime      = 57373
 	hintMemoryQuota           = 57384
 	hintMerge                 = 57361
@@ -88,9 +89,9 @@ const (
 	hintNoSkipScan            = 57370
 	hintNoSwapJoinInputs      = 57385
 	hintNthPlan               = 57399
-	hintOLAP                  = 57402
-	hintOLTP                  = 57403
-	hintPartition             = 57404
+	hintOLAP                  = 57404
+	hintOLTP                  = 57405
+	hintPartition             = 57406
 	hintQBName                = 57376
 	hintQueryType             = 57386
 	hintReadConsistentReplica = 57387
@@ -101,13 +102,14 @@ const (
 	hintSetVar                = 57374
 	hintSingleAtIdentifier    = 57349
 	hintSkipScan              = 57369
+	hintStraightJoin          = 57402
 	hintStreamAgg             = 57391
 	hintStringLit             = 57350
 	hintSwapJoinInputs        = 57392
-	hintTiFlash               = 57406
-	hintTiKV                  = 57405
+	hintTiFlash               = 57408
+	hintTiKV                  = 57407
 	hintTimeRange             = 57397
-	hintTrue                  = 57408
+	hintTrue                  = 57410
 	hintUseCascades           = 57398
 	hintUseIndex              = 57394
 	hintUseIndexMerge         = 57393
@@ -115,123 +117,125 @@ const (
 	hintUseToja               = 57396
 
 	yyhintMaxDepth = 200
-	yyhintTabOfs   = -170
+	yyhintTabOfs   = -174
 )
 
 var (
 	yyhintXLAT = map[int]int{
-		41:    0,   // ')' (129x)
-		57377: 1,   // hintAggToCop (121x)
-		57390: 2,   // hintBCJoin (121x)
-		57355: 3,   // hintBKA (121x)
-		57357: 4,   // hintBNL (121x)
-		57401: 5,   // hintForceIndex (121x)
-		57379: 6,   // hintHashAgg (121x)
-		57359: 7,   // hintHashJoin (121x)
-		57380: 8,   // hintIgnoreIndex (121x)
-		57378: 9,   // hintIgnorePlanCache (121x)
-		57363: 10,  // hintIndexMerge (121x)
-		57381: 11,  // hintInlHashJoin (121x)
-		57382: 12,  // hintInlJoin (121x)
-		57383: 13,  // hintInlMergeJoin (121x)
-		57351: 14,  // hintJoinFixedOrder (121x)
-		57352: 15,  // hintJoinOrder (121x)
-		57353: 16,  // hintJoinPrefix (121x)
-		57354: 17,  // hintJoinSuffix (121x)
-		57400: 18,  // hintLimitToCop (121x)
-		57373: 19,  // hintMaxExecutionTime (121x)
-		57384: 20,  // hintMemoryQuota (121x)
-		57361: 21,  // hintMerge (121x)
-		57365: 22,  // hintMRR (121x)
-		57356: 23,  // hintNoBKA (121x)
-		57358: 24,  // hintNoBNL (121x)
-		57360: 25,  // hintNoHashJoin (121x)
-		57367: 26,  // hintNoICP (121x)
-		57364: 27,  // hintNoIndexMerge (121x)
-		57362: 28,  // hintNoMerge (121x)
-		57366: 29,  // hintNoMRR (121x)
-		57368: 30,  // hintNoRangeOptimization (121x)
-		57372: 31,  // hintNoSemijoin (121x)
-		57370: 32,  // hintNoSkipScan (121x)
-		57385: 33,  // hintNoSwapJoinInputs (121x)
-		57399: 34,  // hintNthPlan (121x)
-		57376: 35,  // hintQBName (121x)
-		57386: 36,  // hintQueryType (121x)
-		57387: 37,  // hintReadConsistentReplica (121x)
-		57388: 38,  // hintReadFromStorage (121x)
-		57375: 39,  // hintResourceGroup (121x)
-		57371: 40,  // hintSemijoin (121x)
-		57374: 41,  // hintSetVar (121x)
-		57369: 42,  // hintSkipScan (121x)
-		57389: 43,  // hintSMJoin (121x)
-		57391: 44,  // hintStreamAgg (121x)
-		57392: 45,  // hintSwapJoinInputs (121x)
-		57397: 46,  // hintTimeRange (121x)
-		57398: 47,  // hintUseCascades (121x)
-		57394: 48,  // hintUseIndex (121x)
-		57393: 49,  // hintUseIndexMerge (121x)
-		57395: 50,  // hintUsePlanCache (121x)
-		57396: 51,  // hintUseToja (121x)
-		44:    52,  // ',' (119x)
-		57411: 53,  // hintDupsWeedOut (99x)
-		57412: 54,  // hintFirstMatch (99x)
-		57413: 55,  // hintLooseScan (99x)
-		57414: 56,  // hintMaterialization (99x)
-		57406: 57,  // hintTiFlash (99x)
-		57405: 58,  // hintTiKV (99x)
-		57407: 59,  // hintFalse (98x)
-		57402: 60,  // hintOLAP (98x)
-		57403: 61,  // hintOLTP (98x)
-		57408: 62,  // hintTrue (98x)
-		57410: 63,  // hintGB (97x)
-		57409: 64,  // hintMB (97x)
-		57347: 65,  // hintIdentifier (96x)
-		57349: 66,  // hintSingleAtIdentifier (81x)
-		93:    67,  // ']' (75x)
-		57404: 68,  // hintPartition (69x)
-		46:    69,  // '.' (65x)
-		61:    70,  // '=' (65x)
-		40:    71,  // '(' (60x)
-		57344: 72,  // $end (24x)
-		57435: 73,  // QueryBlockOpt (17x)
-		57427: 74,  // Identifier (13x)
-		57346: 75,  // hintIntLit (8x)
-		57350: 76,  // hintStringLit (5x)
-		57417: 77,  // CommaOpt (4x)
-		57423: 78,  // HintTable (4x)
-		57424: 79,  // HintTableList (4x)
-		91:    80,  // '[' (3x)
-		57416: 81,  // BooleanHintName (2x)
-		57418: 82,  // HintIndexList (2x)
-		57420: 83,  // HintStorageType (2x)
-		57421: 84,  // HintStorageTypeAndTable (2x)
-		57425: 85,  // HintTableListOpt (2x)
-		57430: 86,  // JoinOrderOptimizerHintName (2x)
-		57431: 87,  // NullaryHintName (2x)
-		57434: 88,  // PartitionListOpt (2x)
-		57437: 89,  // StorageOptimizerHintOpt (2x)
-		57438: 90,  // SubqueryOptimizerHintName (2x)
-		57441: 91,  // SubqueryStrategy (2x)
-		57442: 92,  // SupportedIndexLevelOptimizerHintName (2x)
-		57443: 93,  // SupportedTableLevelOptimizerHintName (2x)
-		57444: 94,  // TableOptimizerHintOpt (2x)
-		57446: 95,  // UnsupportedIndexLevelOptimizerHintName (2x)
-		57447: 96,  // UnsupportedTableLevelOptimizerHintName (2x)
-		57419: 97,  // HintQueryType (1x)
-		57422: 98,  // HintStorageTypeAndTableList (1x)
-		57426: 99,  // HintTrueOrFalse (1x)
-		57428: 100, // IndexNameList (1x)
-		57429: 101, // IndexNameListOpt (1x)
-		57432: 102, // OptimizerHintList (1x)
-		57433: 103, // PartitionList (1x)
-		57436: 104, // Start (1x)
-		57439: 105, // SubqueryStrategies (1x)
-		57440: 106, // SubqueryStrategiesOpt (1x)
-		57445: 107, // UnitOfBytes (1x)
-		57448: 108, // Value (1x)
-		57415: 109, // $default (0x)
-		57345: 110, // error (0x)
-		57348: 111, // hintInvalid (0x)
+		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)
+		93:    69,  // ']' (77x)
+		57406: 70,  // hintPartition (71x)
+		46:    71,  // '.' (67x)
+		61:    72,  // '=' (67x)
+		40:    73,  // '(' (62x)
+		57344: 74,  // $end (24x)
+		57437: 75,  // QueryBlockOpt (17x)
+		57429: 76,  // Identifier (13x)
+		57346: 77,  // hintIntLit (8x)
+		57350: 78,  // hintStringLit (5x)
+		57419: 79,  // CommaOpt (4x)
+		57425: 80,  // HintTable (4x)
+		57426: 81,  // HintTableList (4x)
+		91:    82,  // '[' (3x)
+		57418: 83,  // BooleanHintName (2x)
+		57420: 84,  // HintIndexList (2x)
+		57422: 85,  // HintStorageType (2x)
+		57423: 86,  // HintStorageTypeAndTable (2x)
+		57427: 87,  // HintTableListOpt (2x)
+		57432: 88,  // JoinOrderOptimizerHintName (2x)
+		57433: 89,  // NullaryHintName (2x)
+		57436: 90,  // PartitionListOpt (2x)
+		57439: 91,  // StorageOptimizerHintOpt (2x)
+		57440: 92,  // SubqueryOptimizerHintName (2x)
+		57443: 93,  // SubqueryStrategy (2x)
+		57444: 94,  // SupportedIndexLevelOptimizerHintName (2x)
+		57445: 95,  // SupportedTableLevelOptimizerHintName (2x)
+		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)
 	}
 
 	yyhintSymNames = []string{
@@ -253,6 +257,7 @@ var (
 		"hintJoinOrder",
 		"hintJoinPrefix",
 		"hintJoinSuffix",
+		"hintLeading",
 		"hintLimitToCop",
 		"hintMaxExecutionTime",
 		"hintMemoryQuota",
@@ -279,6 +284,7 @@ var (
 		"hintSetVar",
 		"hintSkipScan",
 		"hintSMJoin",
+		"hintStraightJoin",
 		"hintStreamAgg",
 		"hintSwapJoinInputs",
 		"hintTimeRange",
@@ -351,80 +357,72 @@ var (
 
 	yyhintReductions = []struct{ xsym, components int }{
 		{0, 1},
+		{106, 1},
 		{104, 1},
-		{102, 1},
-		{102, 3},
-		{102, 1},
-		{102, 3},
-		{94, 4},
-		{94, 4},
-		{94, 4},
-		{94, 4},
-		{94, 4},
-		{94, 4},
-		{94, 5},
-		{94, 5},
-		{94, 5},
-		{94, 6},
-		{94, 4},
-		{94, 4},
-		{94, 6},
-		{94, 6},
-		{94, 5},
-		{94, 4},
-		{94, 5},
-		{89, 5},
-		{98, 1},
-		{98, 3},
-		{84, 4},
-		{73, 0},
-		{73, 1},
-		{77, 0},
-		{77, 1},
-		{88, 0},
-		{88, 4},
-		{103, 1},
-		{103, 3},
-		{85, 1},
-		{85, 1},
-		{79, 2},
-		{79, 3},
-		{78, 3},
-		{78, 5},
-		{82, 4},
-		{101, 0},
-		{101, 1},
+		{104, 3},
+		{104, 1},
+		{104, 3},
+		{96, 4},
+		{96, 4},
+		{96, 4},
+		{96, 4},
+		{96, 4},
+		{96, 4},
+		{96, 5},
+		{96, 5},
+		{96, 5},
+		{96, 6},
+		{96, 4},
+		{96, 4},
+		{96, 6},
+		{96, 6},
+		{96, 5},
+		{96, 4},
+		{96, 5},
+		{91, 5},
 		{100, 1},
 		{100, 3},
-		{106, 0},
-		{106, 1},
+		{86, 4},
+		{75, 0},
+		{75, 1},
+		{79, 0},
+		{79, 1},
+		{90, 0},
+		{90, 4},
 		{105, 1},
 		{105, 3},
-		{108, 1},
-		{108, 1},
+		{87, 1},
+		{87, 1},
+		{81, 2},
+		{81, 3},
+		{80, 3},
+		{80, 5},
+		{84, 4},
+		{103, 0},
+		{103, 1},
+		{102, 1},
+		{102, 3},
+		{108, 0},
 		{108, 1},
 		{107, 1},
-		{107, 1},
-		{99, 1},
-		{99, 1},
-		{86, 1},
-		{86, 1},
-		{86, 1},
-		{96, 1},
-		{96, 1},
-		{96, 1},
-		{96, 1},
-		{96, 1},
-		{96, 1},
-		{96, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
-		{93, 1},
+		{107, 3},
+		{110, 1},
+		{110, 1},
+		{110, 1},
+		{109, 1},
+		{109, 1},
+		{101, 1},
+		{101, 1},
+		{88, 1},
+		{88, 1},
+		{88, 1},
+		{98, 1},
+		{98, 1},
+		{98, 1},
+		{98, 1},
+		{98, 1},
+		{98, 1},
+		{98, 1},
 		{95, 1},
 		{95, 1},
 		{95, 1},
@@ -432,403 +430,420 @@ var (
 		{95, 1},
 		{95, 1},
 		{95, 1},
-		{92, 1},
-		{92, 1},
-		{92, 1},
-		{92, 1},
-		{90, 1},
-		{90, 1},
-		{91, 1},
-		{91, 1},
-		{91, 1},
-		{91, 1},
-		{81, 1},
-		{81, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
-		{87, 1},
+		{95, 1},
+		{95, 1},
+		{97, 1},
+		{97, 1},
 		{97, 1},
 		{97, 1},
+		{97, 1},
+		{97, 1},
+		{97, 1},
+		{94, 1},
+		{94, 1},
+		{94, 1},
+		{94, 1},
+		{92, 1},
+		{92, 1},
+		{93, 1},
+		{93, 1},
+		{93, 1},
+		{93, 1},
 		{83, 1},
 		{83, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
-		{74, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{89, 1},
+		{99, 1},
+		{99, 1},
+		{85, 1},
+		{85, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
+		{76, 1},
 	}
 
 	yyhintXErrors = map[yyhintXError]string{}
 
-	yyhintParseTab = [253][]uint16{
+	yyhintParseTab = [257][]uint16{
 		// 0
-		{1: 229, 204, 196, 198, 221, 227, 210, 219, 233, 211, 206, 205, 209, 175, 193, 194, 195, 230, 182, 187, 201, 212, 197, 199, 200, 214, 231, 202, 213, 215, 223, 217, 208, 183, 186, 191, 232, 192, 185, 222, 184, 216, 203, 228, 207, 188, 225, 218, 220, 226, 224, 81: 189, 86: 176, 190, 89: 174, 181, 92: 180, 178, 173, 179, 177, 102: 172, 104: 171},
-		{72: 170},
-		{1: 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, 320, 72: 169, 77: 420},
-		{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, 72: 168},
-		{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, 72: 166},
+		{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},
 		// 5
-		{71: 417},
-		{71: 414},
-		{71: 411},
-		{71: 406},
-		{71: 403},
+		{73: 425},
+		{73: 422},
+		{73: 419},
+		{73: 414},
+		{73: 411},
 		// 10
-		{71: 392},
-		{71: 380},
-		{71: 376},
-		{71: 372},
-		{71: 364},
+		{73: 400},
+		{73: 388},
+		{73: 384},
+		{73: 380},
+		{73: 372},
 		// 15
-		{71: 361},
-		{71: 358},
-		{71: 351},
-		{71: 346},
-		{71: 340},
+		{73: 369},
+		{73: 366},
+		{73: 359},
+		{73: 354},
+		{73: 348},
 		// 20
-		{71: 337},
-		{71: 331},
-		{71: 234},
-		{71: 113},
-		{71: 112},
+		{73: 345},
+		{73: 339},
+		{73: 240},
+		{73: 117},
+		{73: 116},
 		// 25
-		{71: 111},
-		{71: 110},
-		{71: 109},
-		{71: 108},
-		{71: 107},
+		{73: 115},
+		{73: 114},
+		{73: 113},
+		{73: 112},
+		{73: 111},
 		// 30
-		{71: 106},
-		{71: 105},
-		{71: 104},
-		{71: 103},
-		{71: 102},
+		{73: 110},
+		{73: 109},
+		{73: 108},
+		{73: 107},
+		{73: 106},
 		// 35
-		{71: 101},
-		{71: 100},
-		{71: 99},
-		{71: 98},
-		{71: 97},
+		{73: 105},
+		{73: 104},
+		{73: 103},
+		{73: 102},
+		{73: 101},
 		// 40
-		{71: 96},
-		{71: 95},
-		{71: 94},
-		{71: 93},
-		{71: 92},
+		{73: 100},
+		{73: 99},
+		{73: 98},
+		{73: 97},
+		{73: 96},
 		// 45
-		{71: 91},
-		{71: 90},
-		{71: 89},
-		{71: 88},
-		{71: 87},
+		{73: 95},
+		{73: 94},
+		{73: 93},
+		{73: 92},
+		{73: 91},
 		// 50
-		{71: 86},
-		{71: 85},
-		{71: 84},
-		{71: 83},
-		{71: 78},
+		{73: 90},
+		{73: 89},
+		{73: 88},
+		{73: 87},
+		{73: 86},
 		// 55
-		{71: 77},
-		{71: 76},
-		{71: 75},
-		{71: 74},
-		{71: 73},
+		{73: 81},
+		{73: 80},
+		{73: 79},
+		{73: 78},
+		{73: 77},
 		// 60
-		{71: 72},
-		{71: 71},
-		{71: 70},
-		{71: 69},
-		{57: 143, 143, 66: 236, 73: 235},
+		{73: 76},
+		{73: 75},
+		{73: 74},
+		{73: 73},
+		{73: 72},
 		// 65
-		{57: 241, 240, 83: 239, 238, 98: 237},
-		{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, 67: 142, 142, 75: 142},
-		{328, 52: 329},
-		{146, 52: 146},
-		{80: 242},
+		{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},
 		// 70
-		{80: 66},
-		{80: 65},
-		{1: 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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 244, 79: 243},
-		{52: 326, 67: 325},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 245},
+		{150, 54: 150},
+		{82: 248},
+		{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},
 		// 75
-		{133, 52: 133, 67: 133},
-		{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, 236, 143, 143, 312, 73: 311},
-		{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
-		{63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63},
-		{62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62},
+		{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},
+		{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
-		{61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61},
-		{60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60},
-		{59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
-		{58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58},
-		{57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57},
+		{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},
+		{64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64},
+		{63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63, 63},
+		{62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, 62},
+		{61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61, 61},
 		// 85
-		{56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56},
-		{55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55},
-		{54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54},
-		{53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53},
-		{52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52},
+		{60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60},
+		{59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, 59},
+		{58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, 58},
+		{57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57},
+		{56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56},
 		// 90
-		{51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51},
-		{50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50},
-		{49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49},
-		{48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48},
-		{47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47},
+		{55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55},
+		{54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54},
+		{53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53},
+		{52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52},
+		{51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51},
 		// 95
-		{46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46},
-		{45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45},
-		{44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44},
-		{43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43},
-		{42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42},
+		{50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50},
+		{49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49},
+		{48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48},
+		{47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47},
+		{46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46},
 		// 100
-		{41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41},
-		{40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
-		{39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39},
-		{38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38},
-		{37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37},
+		{45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45},
+		{44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44},
+		{43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43},
+		{42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42},
+		{41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41},
 		// 105
-		{36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36},
-		{35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35},
-		{34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34},
-		{33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33},
-		{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32},
+		{40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40},
+		{39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39, 39},
+		{38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, 38},
+		{37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, 37},
+		{36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, 36},
 		// 110
-		{31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31},
-		{30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
-		{29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29},
-		{28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28},
-		{27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27},
+		{35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, 35},
+		{34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34, 34},
+		{33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33},
+		{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32},
+		{31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31},
 		// 115
-		{26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26},
-		{25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25},
-		{24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24},
-		{23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23},
-		{22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
+		{30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30},
+		{29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29},
+		{28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28},
+		{27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27},
+		{26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26},
 		// 120
-		{21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21},
-		{20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20},
-		{19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19},
-		{18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18},
-		{17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17},
+		{25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25},
+		{24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24},
+		{23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23},
+		{22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22},
+		{21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21},
 		// 125
-		{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16},
-		{15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15},
-		{14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14},
-		{13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13},
-		{12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12},
+		{20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20},
+		{19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19},
+		{18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18},
+		{17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17},
+		{16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16},
 		// 130
-		{11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
-		{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
-		{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9},
-		{8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
-		{7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7},
+		{15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15},
+		{14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14},
+		{13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13},
+		{12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12},
+		{11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11},
 		// 135
-		{6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6},
-		{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
-		{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
-		{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
-		{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+		{10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10},
+		{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9},
+		{8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8},
+		{7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7},
+		{6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6},
 		// 140
-		{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},
-		{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, 67: 139, 315, 88: 324},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 313},
-		{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, 236, 143, 143, 73: 314},
-		{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, 67: 139, 315, 88: 316},
+		{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5},
+		{4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4},
+		{3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3},
+		{2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
+		{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
-		{71: 317},
-		{130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 67: 130},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 319, 103: 318},
-		{321, 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, 320, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 77: 322},
-		{137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137},
+		{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},
 		// 150
-		{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, 53: 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 140, 76: 140},
-		{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, 67: 138},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 323},
-		{136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136, 136},
-		{131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 131, 67: 131},
+		{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},
 		// 155
-		{144, 52: 144},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 327},
-		{132, 52: 132, 67: 132},
-		{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, 72: 147},
-		{57: 241, 240, 83: 239, 330},
+		{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},
 		// 160
-		{145, 52: 145},
-		{60: 143, 143, 66: 236, 73: 332},
-		{60: 334, 335, 97: 333},
-		{336},
-		{68},
+		{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},
 		// 165
-		{67},
-		{1: 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, 72: 148},
-		{143, 66: 236, 73: 338},
-		{339},
-		{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, 72: 149},
+		{62: 147, 147, 68: 242, 75: 340},
+		{62: 342, 343, 99: 341},
+		{344},
+		{70},
+		{69},
 		// 170
-		{59: 143, 62: 143, 66: 236, 73: 341},
-		{59: 344, 62: 343, 99: 342},
-		{345},
-		{115},
-		{114},
+		{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},
 		// 175
-		{1: 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, 72: 150},
-		{76: 347},
-		{52: 320, 76: 141, 348},
-		{76: 349},
-		{350},
+		{61: 352, 64: 351, 101: 350},
+		{353},
+		{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},
 		// 180
-		{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, 72: 151},
-		{66: 236, 73: 352, 75: 143},
-		{75: 353},
-		{63: 356, 355, 107: 354},
-		{357},
+		{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},
 		// 185
-		{117},
-		{116},
-		{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, 72: 152},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 359},
-		{360},
+		{68: 242, 75: 360, 77: 147},
+		{77: 361},
+		{65: 364, 363, 109: 362},
+		{365},
+		{121},
 		// 190
-		{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, 72: 153},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 362},
-		{363},
-		{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, 72: 154},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 365},
+		{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},
 		// 195
-		{70: 366},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 369, 370, 368, 108: 367},
+		{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},
-		{120},
-		{119},
+		{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},
 		// 200
-		{118},
-		{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, 72: 155},
-		{66: 236, 73: 373, 75: 143},
-		{75: 374},
-		{375},
-		// 205
-		{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, 72: 156},
-		{66: 236, 73: 377, 75: 143},
-		{75: 378},
+		{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},
-		{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, 72: 157},
+		{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
-		{143, 53: 143, 143, 143, 143, 66: 236, 73: 381},
-		{124, 53: 385, 386, 387, 388, 91: 384, 105: 383, 382},
-		{391},
-		{123, 52: 389},
-		{122, 52: 122},
+		{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},
 		// 215
-		{82, 52: 82},
-		{81, 52: 81},
-		{80, 52: 80},
-		{79, 52: 79},
-		{53: 385, 386, 387, 388, 91: 390},
+		{128, 55: 393, 394, 395, 396, 93: 392, 107: 391, 390},
+		{399},
+		{127, 54: 397},
+		{126, 54: 126},
+		{85, 54: 85},
 		// 220
-		{121, 52: 121},
-		{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, 72: 158},
-		{1: 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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 394, 82: 393},
-		{402},
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 395},
+		{84, 54: 84},
+		{83, 54: 83},
+		{82, 54: 82},
+		{55: 393, 394, 395, 396, 93: 398},
+		{125, 54: 125},
 		// 225
-		{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, 320, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 141, 77: 396},
-		{128, 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 399, 100: 398, 397},
-		{129},
-		{127, 52: 400},
-		{126, 52: 126},
+		{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
-		{1: 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 401},
-		{125, 52: 125},
-		{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, 72: 159},
-		{1: 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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 394, 82: 404},
-		{405},
+		{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},
+		{133},
+		{131, 54: 408},
+		{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: 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, 72: 160},
-		{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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 409, 79: 408, 85: 407},
-		{410},
-		{135, 52: 326},
-		{134, 274, 288, 252, 254, 298, 277, 256, 278, 276, 260, 279, 280, 281, 248, 249, 250, 251, 275, 270, 282, 258, 262, 253, 255, 257, 264, 261, 259, 263, 265, 269, 267, 283, 297, 273, 284, 285, 286, 272, 268, 271, 266, 287, 289, 290, 295, 296, 292, 291, 293, 294, 53: 307, 308, 309, 310, 302, 301, 303, 299, 300, 304, 306, 305, 247, 74: 246, 78: 245},
-		// 240
-		{1: 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 72: 161},
-		{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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 409, 79: 408, 85: 412},
+		{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: 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, 72: 162},
-		{1: 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, 53: 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, 236, 73: 244, 79: 415},
+		{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
-		{416, 52: 326},
-		{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, 72: 163},
-		{143, 66: 236, 73: 418},
-		{419},
-		{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, 72: 164},
+		{147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, 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: 229, 204, 196, 198, 221, 227, 210, 219, 233, 211, 206, 205, 209, 175, 193, 194, 195, 230, 182, 187, 201, 212, 197, 199, 200, 214, 231, 202, 213, 215, 223, 217, 208, 183, 186, 191, 232, 192, 185, 222, 184, 216, 203, 228, 207, 188, 225, 218, 220, 226, 224, 81: 189, 86: 176, 190, 89: 422, 181, 92: 180, 178, 421, 179, 177},
-		{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, 72: 167},
-		{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, 72: 165},
+		{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},
+		// 255
+		{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},
 	}
 )
 
@@ -868,7 +883,7 @@ func yyhintlex1(yylex yyhintLexer, lval *yyhintSymType) (n int) {
 }
 
 func yyhintParse(yylex yyhintLexer, parser *hintParser) int {
-	const yyError = 110
+	const yyError = 112
 
 	yyEx, _ := yylex.(yyhintLexerEx)
 	var yyn int
diff --git a/parser/hintparser.y b/parser/hintparser.y
index 332d53eb7379e..e3c3dacf4faff 100644
--- a/parser/hintparser.y
+++ b/parser/hintparser.y
@@ -105,6 +105,8 @@ import (
 	hintNthPlan               "NTH_PLAN"
 	hintLimitToCop            "LIMIT_TO_COP"
 	hintForceIndex            "FORCE_INDEX"
+	hintStraightJoin          "STRAIGHT_JOIN"
+	hintLeading               "LEADING"
 
 	/* Other keywords */
 	hintOLAP            "OLAP"
@@ -539,6 +541,7 @@ SupportedTableLevelOptimizerHintName:
 |	"NO_SWAP_JOIN_INPUTS"
 |	"INL_MERGE_JOIN"
 |	"HASH_JOIN"
+|	"LEADING"
 
 UnsupportedIndexLevelOptimizerHintName:
 	"INDEX_MERGE"
@@ -579,6 +582,7 @@ NullaryHintName:
 |	"NO_INDEX_MERGE"
 |	"READ_CONSISTENT_REPLICA"
 |	"IGNORE_PLAN_CACHE"
+|	"STRAIGHT_JOIN"
 
 HintQueryType:
 	"OLAP"
@@ -643,6 +647,8 @@ Identifier:
 |	"USE_CASCADES"
 |	"NTH_PLAN"
 |	"FORCE_INDEX"
+|	"STRAIGHT_JOIN"
+|	"LEADING"
 /* other keywords */
 |	"OLAP"
 |	"OLTP"
diff --git a/parser/misc.go b/parser/misc.go
index d52563142c84e..7c73cff2dfed8 100644
--- a/parser/misc.go
+++ b/parser/misc.go
@@ -933,6 +933,8 @@ var hintTokenMap = map[string]int{
 	"USE_CASCADES":            hintUseCascades,
 	"NTH_PLAN":                hintNthPlan,
 	"FORCE_INDEX":             hintForceIndex,
+	"STRAIGHT_JOIN":           hintStraightJoin,
+	"LEADING":                 hintLeading,
 
 	// TiDB hint aliases
 	"TIDB_HJ":   hintHashJoin,
diff --git a/parser/parser_test.go b/parser/parser_test.go
index ece8b15c1dcc0..78d1b8ea69441 100644
--- a/parser/parser_test.go
+++ b/parser/parser_test.go
@@ -4192,6 +4192,38 @@ func TestOptimizerHints(t *testing.T) {
 	require.Len(t, hints, 2)
 	require.Equal(t, "limit_to_cop", hints[0].HintName.L)
 	require.Equal(t, "limit_to_cop", hints[1].HintName.L)
+
+	// Test STRAIGHT_JOIN
+	stmt, _, err = p.Parse("select /*+ STRAIGHT_JOIN(), straight_join() */ c1, c2 from t1, t2 where t1.c1 = t2.c1", "", "")
+	require.NoError(t, err)
+	selectStmt = stmt[0].(*ast.SelectStmt)
+
+	hints = selectStmt.TableHints
+	require.Len(t, hints, 2)
+	require.Equal(t, "straight_join", hints[0].HintName.L)
+	require.Equal(t, "straight_join", hints[1].HintName.L)
+
+	// Test LEADING
+	stmt, _, err = p.Parse("select /*+ LEADING(T1), LEADING(t2, t3), LEADING(T4, t5, t6) */ c1, c2 from t1, t2 where t1.c1 = t2.c1", "", "")
+	require.NoError(t, err)
+	selectStmt = stmt[0].(*ast.SelectStmt)
+
+	hints = selectStmt.TableHints
+	require.Len(t, hints, 3)
+	require.Equal(t, "leading", hints[0].HintName.L)
+	require.Len(t, hints[0].Tables, 1)
+	require.Equal(t, "t1", hints[0].Tables[0].TableName.L)
+
+	require.Equal(t, "leading", hints[1].HintName.L)
+	require.Len(t, hints[1].Tables, 2)
+	require.Equal(t, "t2", hints[1].Tables[0].TableName.L)
+	require.Equal(t, "t3", hints[1].Tables[1].TableName.L)
+
+	require.Equal(t, "leading", hints[2].HintName.L)
+	require.Len(t, hints[2].Tables, 3)
+	require.Equal(t, "t4", hints[2].Tables[0].TableName.L)
+	require.Equal(t, "t5", hints[2].Tables[1].TableName.L)
+	require.Equal(t, "t6", hints[2].Tables[1].TableName.L)
 }
 
 func TestType(t *testing.T) {

From 8ad871ec887c541d8ab166160ed2f57dd998c305 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 29 Apr 2022 16:04:17 +0800
Subject: [PATCH 02/10] planner: support straight join order hint

---
 planner/core/expression_rewriter.go  |  5 ++++-
 planner/core/logical_plan_builder.go | 12 +++++++++++-
 planner/core/planbuilder.go          |  1 +
 3 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go
index ee5669a45e81f..24fa2059f2ba1 100644
--- a/planner/core/expression_rewriter.go
+++ b/planner/core/expression_rewriter.go
@@ -936,7 +936,10 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte
 		// We need to try to eliminate the agg and the projection produced by this operation.
 		er.b.optFlag |= flagEliminateAgg
 		er.b.optFlag |= flagEliminateProjection
-		er.b.optFlag |= flagJoinReOrder
+		tableHints := er.b.TableHints()
+		if tableHints == nil || !tableHints.straightJoinOrder {
+			er.b.optFlag |= flagJoinReOrder
+		}
 		// Build distinct for the inner query.
 		agg, err := er.b.buildDistinct(np, np.Schema().Len())
 		if err != nil {
diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go
index 55dc47854c59b..ad4e6523b40ce 100644
--- a/planner/core/logical_plan_builder.go
+++ b/planner/core/logical_plan_builder.go
@@ -74,6 +74,9 @@ const (
 	// HintBCJ indicates applying broadcast join by force.
 	HintBCJ = "broadcast_join"
 
+	// HintStraightJoin causes TiDB to join tables in the order in which they appear in the FROM clause.
+	HintStraightJoin = "straight_join"
+
 	// TiDBIndexNestedLoopJoin is hint enforce index nested loop join.
 	TiDBIndexNestedLoopJoin = "tidb_inlj"
 	// HintINLJ is hint enforce index nested loop join.
@@ -674,7 +677,10 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica
 
 	b.optFlag = b.optFlag | flagPredicatePushDown
 	// Add join reorder flag regardless of inner join or outer join.
-	b.optFlag = b.optFlag | flagJoinReOrder
+	tableHints := b.TableHints()
+	if tableHints == nil || !tableHints.straightJoinOrder {
+		b.optFlag = b.optFlag | flagJoinReOrder
+	}
 
 	leftPlan, err := b.buildResultSetNode(ctx, joinNode.Left)
 	if err != nil {
@@ -3508,6 +3514,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 		aggHints                                                                        aggHintInfo
 		timeRangeHint                                                                   ast.HintTimeRange
 		limitHints                                                                      limitHintInfo
+		straightJoinOrder                                                               bool
 	)
 	for _, hint := range hints {
 		// Set warning for the hint that requires the table name.
@@ -3610,6 +3617,8 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 			timeRangeHint = hint.HintData.(ast.HintTimeRange)
 		case HintLimitToCop:
 			limitHints.preferLimitToCop = true
+		case HintStraightJoin:
+			straightJoinOrder = true
 		default:
 			// ignore hints that not implemented
 		}
@@ -3626,6 +3635,7 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 		indexMergeHintList:        indexMergeHintList,
 		timeRangeHint:             timeRangeHint,
 		limitHints:                limitHints,
+		straightJoinOrder:         straightJoinOrder,
 	})
 }
 
diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go
index bf608aa1c413d..7b2b34e4d2372 100644
--- a/planner/core/planbuilder.go
+++ b/planner/core/planbuilder.go
@@ -97,6 +97,7 @@ type tableHintInfo struct {
 	indexMergeHintList  []indexHintInfo
 	timeRangeHint       ast.HintTimeRange
 	limitHints          limitHintInfo
+	straightJoinOrder   bool
 }
 
 type limitHintInfo struct {

From d10d932622cae564bd63e13c88b491f08926d3d4 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 29 Apr 2022 16:36:35 +0800
Subject: [PATCH 03/10] fix ut

---
 parser/ast/misc_test.go | 18 +++++++++---------
 parser/parser_test.go   |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/parser/ast/misc_test.go b/parser/ast/misc_test.go
index 6aa2c5b1ac5cc..9370ae77f208d 100644
--- a/parser/ast/misc_test.go
+++ b/parser/ast/misc_test.go
@@ -240,20 +240,20 @@ func TestTableOptimizerHintRestore(t *testing.T) {
 		{"INL_MERGE_JOIN(t1,t2)", "INL_MERGE_JOIN(`t1`, `t2`)"},
 		{"INL_JOIN(t1,t2)", "INL_JOIN(`t1`, `t2`)"},
 		{"HASH_JOIN(t1,t2)", "HASH_JOIN(`t1`, `t2`)"},
+		{"LEADING(t1)", "LEADING(`t1`)"},
+		{"LEADING(t1, c1)", "LEADING(`t1`, `c1`)"},
+		{"LEADING(t1, c1, t2)", "LEADING(`t1`, `c1`, `t2`)"},
+		{"LEADING(@sel1 t1, c1)", "LEADING(@`sel1` `t1`, `c1`)"},
+		{"LEADING(@sel1 t1)", "LEADING(@`sel1` `t1`)"},
+		{"LEADING(@sel1 t1, c1, t2)", "LEADING(@`sel1` `t1`, `c1`, `t2`)"},
+		{"LEADING(t1@sel1)", "LEADING(`t1`@`sel1`)"},
+		{"LEADING(t1@sel1, c1)", "LEADING(`t1`@`sel1`, `c1`)"},
+		{"LEADING(t1@sel1, c1, t2)", "LEADING(`t1`@`sel1`, `c1`, `t2`)"},
 		{"MAX_EXECUTION_TIME(3000)", "MAX_EXECUTION_TIME(3000)"},
 		{"MAX_EXECUTION_TIME(@sel1 3000)", "MAX_EXECUTION_TIME(@`sel1` 3000)"},
 		{"USE_INDEX_MERGE(t1 c1)", "USE_INDEX_MERGE(`t1` `c1`)"},
 		{"USE_INDEX_MERGE(@sel1 t1 c1)", "USE_INDEX_MERGE(@`sel1` `t1` `c1`)"},
 		{"USE_INDEX_MERGE(t1@sel1 c1)", "USE_INDEX_MERGE(`t1`@`sel1` `c1`)"},
-		{"LEADING(t1)", "LEADING(`t1`)"},
-		{"LEADING(t1 c1)", "LEADING(`t1` `c1`)"},
-		{"LEADING(t1 c1 t2)", "LEADING(`t1` `c1` `t2`)"},
-		{"LEADING(@sel1 t1 c1)", "LEADING(@`sel1` `t1` `c1`)"},
-		{"LEADING(@sel1 t1)", "LEADING(@`sel1` `t1`)"},
-		{"LEADING(@sel1 t1 c1 t2)", "LEADING(@`sel1` `t1` `c1` `t2`)"},
-		{"LEADING(t1@sel1)", "LEADING(`t1`@`sel1`)"},
-		{"LEADING(t1@sel1 c1)", "LEADING(`t1`@`sel1` `c1`)"},
-		{"LEADING(t1@sel1 c1 t2)", "LEADING(`t1`@`sel1` `c1` `t2`)"},
 		{"USE_TOJA(TRUE)", "USE_TOJA(TRUE)"},
 		{"USE_TOJA(FALSE)", "USE_TOJA(FALSE)"},
 		{"USE_TOJA(@sel1 TRUE)", "USE_TOJA(@`sel1` TRUE)"},
diff --git a/parser/parser_test.go b/parser/parser_test.go
index 78d1b8ea69441..a77fd5bdbd0b5 100644
--- a/parser/parser_test.go
+++ b/parser/parser_test.go
@@ -4223,7 +4223,7 @@ func TestOptimizerHints(t *testing.T) {
 	require.Len(t, hints[2].Tables, 3)
 	require.Equal(t, "t4", hints[2].Tables[0].TableName.L)
 	require.Equal(t, "t5", hints[2].Tables[1].TableName.L)
-	require.Equal(t, "t6", hints[2].Tables[1].TableName.L)
+	require.Equal(t, "t6", hints[2].Tables[2].TableName.L)
 }
 
 func TestType(t *testing.T) {

From 1eb5e618af58f1a2c288823a473cd60a04ac123b Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 6 May 2022 15:36:06 +0800
Subject: [PATCH 04/10] add more test cases

---
 planner/core/main_test.go                     |   5 +
 planner/core/rule_join_reorder_test.go        |  55 ++++
 .../core/testdata/join_reorder_suite_in.json  |  21 ++
 .../core/testdata/join_reorder_suite_out.json | 244 ++++++++++++++++++
 4 files changed, 325 insertions(+)
 create mode 100644 planner/core/rule_join_reorder_test.go
 create mode 100644 planner/core/testdata/join_reorder_suite_in.json
 create mode 100644 planner/core/testdata/join_reorder_suite_out.json

diff --git a/planner/core/main_test.go b/planner/core/main_test.go
index 669de70e669e9..6d5436701f138 100644
--- a/planner/core/main_test.go
+++ b/planner/core/main_test.go
@@ -46,6 +46,7 @@ func TestMain(m *testing.M) {
 	testDataMap.LoadTestSuiteData("testdata", "integration_suite")
 	testDataMap.LoadTestSuiteData("testdata", "analyze_suite")
 	testDataMap.LoadTestSuiteData("testdata", "plan_suite_unexported")
+	testDataMap.LoadTestSuiteData("testdata", "join_reorder_suite")
 
 	indexMergeSuiteData = testDataMap["index_merge_suite"]
 	planSuiteUnexportedData = testDataMap["plan_suite_unexported"]
@@ -80,6 +81,10 @@ func GetOrderedResultModeSuiteData() testdata.TestData {
 	return testDataMap["ordered_result_mode_suite"]
 }
 
+func GetJoinReorderSuiteData() testdata.TestData {
+	return testDataMap["join_reorder_suite"]
+}
+
 func GetPointGetPlanData() testdata.TestData {
 	return testDataMap["point_get_plan"]
 }
diff --git a/planner/core/rule_join_reorder_test.go b/planner/core/rule_join_reorder_test.go
new file mode 100644
index 0000000000000..fc98e7308c07c
--- /dev/null
+++ b/planner/core/rule_join_reorder_test.go
@@ -0,0 +1,55 @@
+// Copyright 2022 PingCAP, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package core_test
+
+import (
+	"testing"
+
+	plannercore "github.com/pingcap/tidb/planner/core"
+	"github.com/pingcap/tidb/testkit"
+	"github.com/pingcap/tidb/testkit/testdata"
+	"github.com/stretchr/testify/require"
+)
+
+func runJoinReorderTestData(t *testing.T, tk *testkit.TestKit, name string) {
+	var input []string
+	var output []struct {
+		Plan []string
+	}
+	joinReorderSuiteData := plannercore.GetJoinReorderSuiteData()
+	joinReorderSuiteData.GetTestCasesByName(name, t, &input, &output)
+	require.Equal(t, len(input), len(output))
+	for i := range input {
+		testdata.OnRecord(func() {
+			output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + input[i]).Rows())
+		})
+		tk.MustQuery("explain format = 'brief' " + input[i]).Check(testkit.Rows(output[i].Plan...))
+	}
+}
+
+func TestStraightJoinHint(t *testing.T) {
+	store, clean := testkit.CreateMockStore(t)
+	defer clean()
+
+	tk := testkit.NewTestKit(t, store)
+	tk.MustExec("use test")
+	tk.MustExec("drop table if exists t, t1, t2, t3;")
+	tk.MustExec("create table t(a int, b int, key(a));")
+	tk.MustExec("create table t1(a int, b int, key(a));")
+	tk.MustExec("create table t2(a int, b int, key(a));")
+	tk.MustExec("create table t3(a int, b int, key(a));")
+	tk.MustExec("create table t4(a int, b int, key(a));")
+	runJoinReorderTestData(t, tk, "TestStraightJoinHint")
+}
diff --git a/planner/core/testdata/join_reorder_suite_in.json b/planner/core/testdata/join_reorder_suite_in.json
new file mode 100644
index 0000000000000..b0476e108e718
--- /dev/null
+++ b/planner/core/testdata/join_reorder_suite_in.json
@@ -0,0 +1,21 @@
+[
+  {
+    "name": "TestStraightJoinHint",
+    "cases": [
+      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t2 join t1 on t2.a=t1.a join t3 on t1.b=t3.b;",
+      "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=1;",
+      "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from t2 join t1 on t1.a=t2.a join t3 on t2.b=t3.b;",
+      "select /*+ straight_join() */ * from t1 join t2 on t1.a=t2.a join t3 on t2.b=t3.b;",
+      "select /*+ straight_join() */ * from t2 join t3 on t3.a=t2.a join t1 on t2.a=t1.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t1.a=t4.a;"
+    ]
+  }
+]
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
new file mode 100644
index 0000000000000..3630f237e3331
--- /dev/null
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -0,0 +1,244 @@
+[
+  {
+    "Name": "TestStraightJoinHint",
+    "Cases": [
+      {
+        "Plan": [
+          "HashJoin 155937656.25 root  CARTESIAN inner join",
+          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 15593.77 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",
+          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 155937656.25 root  CARTESIAN inner join",
+          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 15593.77 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",
+          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 155937656.25 root  CARTESIAN inner join",
+          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 15593.77 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",
+          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 155937656.25 root  CARTESIAN inner join",
+          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 15593.77 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",
+          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 155937656.25 root  CARTESIAN inner join",
+          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 15593.77 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",
+          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 15593.77 root  inner join, equal:[eq(test.t1.b, test.t3.b)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t3.b))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t2.a, test.t1.a)]",
+          "  ├─TableReader(Build) 9980.01 root  data:Selection",
+          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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.t2.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 124875.00 root  CARTESIAN inner join",
+          "├─IndexLookUp(Build) 10.00 root  ",
+          "│ ├─IndexRangeScan(Build) 10.00 cop[tikv] table:t2, index:a(a) range:[1,1], keep order:false, stats:pseudo",
+          "│ └─TableRowIDScan(Probe) 10.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t1.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",
+          "  └─TableReader(Probe) 9990.00 root  data:Selection",
+          "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 15609.38 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.t2.a))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t1.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",
+          "  └─TableReader(Probe) 9990.00 root  data:Selection",
+          "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 15593.77 root  inner join, equal:[eq(test.t2.b, test.t3.b)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t3.b))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t2.a, test.t1.a)]",
+          "  ├─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 15593.77 root  inner join, equal:[eq(test.t2.b, test.t3.b)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t3.b))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "  ├─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 15609.38 root  inner join, equal:[eq(test.t2.a, test.t1.a)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 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",
+          "  └─TableReader(Probe) 9990.00 root  data:Selection",
+          "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t2.a, test.t4.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "│ └─TableReader(Probe) 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) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "  │   └─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "│ └─TableReader(Probe) 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) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "  │   └─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t1.a, test.t4.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "│ │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "│ └─TableReader(Probe) 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) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "  │   └─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      }
+    ]
+  }
+]

From f84307c024401db9ab499ee90db0bfba7672cecb Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 6 May 2022 15:44:13 +0800
Subject: [PATCH 05/10] add more test cases info

---
 planner/core/rule_join_reorder_test.go            |  2 ++
 planner/core/testdata/join_reorder_suite_out.json | 14 ++++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/planner/core/rule_join_reorder_test.go b/planner/core/rule_join_reorder_test.go
index fc98e7308c07c..40bbf12c8a623 100644
--- a/planner/core/rule_join_reorder_test.go
+++ b/planner/core/rule_join_reorder_test.go
@@ -26,6 +26,7 @@ import (
 func runJoinReorderTestData(t *testing.T, tk *testkit.TestKit, name string) {
 	var input []string
 	var output []struct {
+		SQL  string
 		Plan []string
 	}
 	joinReorderSuiteData := plannercore.GetJoinReorderSuiteData()
@@ -33,6 +34,7 @@ func runJoinReorderTestData(t *testing.T, tk *testkit.TestKit, name string) {
 	require.Equal(t, len(input), len(output))
 	for i := range input {
 		testdata.OnRecord(func() {
+			output[i].SQL = input[i]
 			output[i].Plan = testdata.ConvertRowsToStrings(tk.MustQuery("explain format = 'brief' " + input[i]).Rows())
 		})
 		tk.MustQuery("explain format = 'brief' " + input[i]).Check(testkit.Rows(output[i].Plan...))
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
index 3630f237e3331..14377f9c99191 100644
--- a/planner/core/testdata/join_reorder_suite_out.json
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -3,6 +3,7 @@
     "Name": "TestStraightJoinHint",
     "Cases": [
       {
+        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [
           "HashJoin 155937656.25 root  CARTESIAN inner join",
           "├─TableReader(Build) 10000.00 root  data:TableFullScan",
@@ -21,6 +22,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [
           "HashJoin 155937656.25 root  CARTESIAN inner join",
           "├─TableReader(Build) 10000.00 root  data:TableFullScan",
@@ -39,6 +41,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [
           "HashJoin 155937656.25 root  CARTESIAN inner join",
           "├─TableReader(Build) 10000.00 root  data:TableFullScan",
@@ -57,6 +60,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [
           "HashJoin 155937656.25 root  CARTESIAN inner join",
           "├─TableReader(Build) 10000.00 root  data:TableFullScan",
@@ -75,6 +79,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [
           "HashJoin 155937656.25 root  CARTESIAN inner join",
           "├─TableReader(Build) 10000.00 root  data:TableFullScan",
@@ -93,6 +98,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t2 join t1 on t2.a=t1.a join t3 on t1.b=t3.b;",
         "Plan": [
           "HashJoin 15593.77 root  inner join, equal:[eq(test.t1.b, test.t3.b)]",
           "├─TableReader(Build) 9990.00 root  data:Selection",
@@ -108,6 +114,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=1;",
         "Plan": [
           "HashJoin 124875.00 root  CARTESIAN inner join",
           "├─IndexLookUp(Build) 10.00 root  ",
@@ -123,6 +130,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=t3.a;",
         "Plan": [
           "HashJoin 15609.38 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
           "├─TableReader(Build) 9990.00 root  data:Selection",
@@ -138,6 +146,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t2 join t1 on t1.a=t2.a join t3 on t2.b=t3.b;",
         "Plan": [
           "HashJoin 15593.77 root  inner join, equal:[eq(test.t2.b, test.t3.b)]",
           "├─TableReader(Build) 9990.00 root  data:Selection",
@@ -153,6 +162,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t1 join t2 on t1.a=t2.a join t3 on t2.b=t3.b;",
         "Plan": [
           "HashJoin 15593.77 root  inner join, equal:[eq(test.t2.b, test.t3.b)]",
           "├─TableReader(Build) 9990.00 root  data:Selection",
@@ -168,6 +178,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from t2 join t3 on t3.a=t2.a join t1 on t2.a=t1.a;",
         "Plan": [
           "HashJoin 15609.38 root  inner join, equal:[eq(test.t2.a, test.t1.a)]",
           "├─TableReader(Build) 9990.00 root  data:Selection",
@@ -183,6 +194,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
         "Plan": [
           "HashJoin 19511.72 root  inner join, equal:[eq(test.t2.a, test.t4.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
@@ -202,6 +214,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
         "Plan": [
           "HashJoin 19511.72 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
@@ -221,6 +234,7 @@
         ]
       },
       {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
         "Plan": [
           "HashJoin 19511.72 root  inner join, equal:[eq(test.t1.a, test.t4.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",

From 5dcdef9dc76e265020d172fb4ad9b3aa787f5297 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Fri, 6 May 2022 15:48:50 +0800
Subject: [PATCH 06/10] remove useless test cases

---
 .../core/testdata/join_reorder_suite_in.json  |  4 -
 .../core/testdata/join_reorder_suite_out.json | 76 -------------------
 2 files changed, 80 deletions(-)

diff --git a/planner/core/testdata/join_reorder_suite_in.json b/planner/core/testdata/join_reorder_suite_in.json
index b0476e108e718..d1724d4e1f784 100644
--- a/planner/core/testdata/join_reorder_suite_in.json
+++ b/planner/core/testdata/join_reorder_suite_in.json
@@ -2,10 +2,6 @@
   {
     "name": "TestStraightJoinHint",
     "cases": [
-      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-      "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
       "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
       "select /*+ straight_join() */ * from t2 join t1 on t2.a=t1.a join t3 on t1.b=t3.b;",
       "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=1;",
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
index 14377f9c99191..775211578722f 100644
--- a/planner/core/testdata/join_reorder_suite_out.json
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -2,82 +2,6 @@
   {
     "Name": "TestStraightJoinHint",
     "Cases": [
-      {
-        "SQL": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-        "Plan": [
-          "HashJoin 155937656.25 root  CARTESIAN inner join",
-          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
-          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
-          "└─HashJoin(Probe) 15593.77 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",
-          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "    ├─TableReader(Build) 9980.01 root  data:Selection",
-          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-        "Plan": [
-          "HashJoin 155937656.25 root  CARTESIAN inner join",
-          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
-          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
-          "└─HashJoin(Probe) 15593.77 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",
-          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "    ├─TableReader(Build) 9980.01 root  data:Selection",
-          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-        "Plan": [
-          "HashJoin 155937656.25 root  CARTESIAN inner join",
-          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
-          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
-          "└─HashJoin(Probe) 15593.77 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",
-          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "    ├─TableReader(Build) 9980.01 root  data:Selection",
-          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
-        "Plan": [
-          "HashJoin 155937656.25 root  CARTESIAN inner join",
-          "├─TableReader(Build) 10000.00 root  data:TableFullScan",
-          "│ └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo",
-          "└─HashJoin(Probe) 15593.77 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",
-          "  └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "    ├─TableReader(Build) 9980.01 root  data:Selection",
-          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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": "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
         "Plan": [

From 8a6246eeec62f264f753928a4da328e239cd6625 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Sat, 7 May 2022 15:56:14 +0800
Subject: [PATCH 07/10] add more test cases

---
 .../core/testdata/join_reorder_suite_in.json  |  12 +-
 .../core/testdata/join_reorder_suite_out.json | 181 ++++++++++++++++++
 2 files changed, 192 insertions(+), 1 deletion(-)

diff --git a/planner/core/testdata/join_reorder_suite_in.json b/planner/core/testdata/join_reorder_suite_in.json
index d1724d4e1f784..2482235ce94cd 100644
--- a/planner/core/testdata/join_reorder_suite_in.json
+++ b/planner/core/testdata/join_reorder_suite_in.json
@@ -3,15 +3,25 @@
     "name": "TestStraightJoinHint",
     "cases": [
       "select /*+ straight_join() */ * from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t2, t1, t3, t where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b;",
+      "select /*+ straight_join() */ * from t3, t1, t, t2 where t.a = t1.a and t1.b=t2.b;",
       "select /*+ straight_join() */ * from t2 join t1 on t2.a=t1.a join t3 on t1.b=t3.b;",
+      "select /*+ straight_join() */ * from t3 join t1 on t1.b=t3.b join t2 on t2.a=t1.a;",
+      "select /*+ straight_join() */ * from t3 join t2 on t2.b=t3.b join t1 on t2.a=t1.a;",
       "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=1;",
       "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from t1 join (t2 join t3 on t2.a=t3.a) on t1.a=t3.a;",
+      "select /*+ straight_join() */ * from t3 join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
       "select /*+ straight_join() */ * from t2 join t1 on t1.a=t2.a join t3 on t2.b=t3.b;",
       "select /*+ straight_join() */ * from t1 join t2 on t1.a=t2.a join t3 on t2.b=t3.b;",
       "select /*+ straight_join() */ * from t2 join t3 on t3.a=t2.a join t1 on t2.a=t1.a;",
       "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
       "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
-      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t1.a=t4.a;"
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
+      "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+      "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;"
     ]
   }
 ]
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
index 775211578722f..705c9dbcd0194 100644
--- a/planner/core/testdata/join_reorder_suite_out.json
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -21,6 +21,63 @@
           "        └─TableFullScan 10000.00 cop[tikv] table:t keep order:false, stats:pseudo"
         ]
       },
+      {
+        "SQL": "select /*+ straight_join() */ * from t2, t1, t3, t where t.a = t1.a and t1.b=t2.b;",
+        "Plan": [
+          "HashJoin 155937656.25 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "├─TableReader(Build) 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",
+          "└─HashJoin(Probe) 124750125.00 root  CARTESIAN inner join",
+          "  ├─TableReader(Build) 10000.00 root  data:TableFullScan",
+          "  │ └─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.t1.a)), 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.t2.b))",
+          "        └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b;",
+        "Plan": [
+          "HashJoin 155937656.25 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "├─TableReader(Build) 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",
+          "└─HashJoin(Probe) 124750125.00 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.t1.a)), not(isnull(test.t1.b))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 99900000.00 root  CARTESIAN inner join",
+          "    ├─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) 10000.00 root  data:TableFullScan",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from t3, t1, t, t2 where t.a = t1.a and t1.b=t2.b;",
+        "Plan": [
+          "HashJoin 155937656.25 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",
+          "└─HashJoin(Probe) 124750125.00 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "  ├─TableReader(Build) 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",
+          "  └─HashJoin(Probe) 99800100.00 root  CARTESIAN inner join",
+          "    ├─TableReader(Build) 9980.01 root  data:Selection",
+          "    │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "    │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "    └─TableReader(Probe) 10000.00 root  data:TableFullScan",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
+        ]
+      },
       {
         "SQL": "select /*+ straight_join() */ * from t2 join t1 on t2.a=t1.a join t3 on t1.b=t3.b;",
         "Plan": [
@@ -37,6 +94,38 @@
           "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
         ]
       },
+      {
+        "SQL": "select /*+ straight_join() */ * from t3 join t1 on t1.b=t3.b join t2 on t2.a=t1.a;",
+        "Plan": [
+          "HashJoin 15593.77 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t3.b, test.t1.b)]",
+          "  ├─TableReader(Build) 9980.01 root  data:Selection",
+          "  │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), 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.t3.b))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from t3 join t2 on t2.b=t3.b join t1 on t2.a=t1.a;",
+        "Plan": [
+          "HashJoin 15593.77 root  inner join, equal:[eq(test.t2.a, test.t1.a)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
+          "│   └─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.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.t3.b))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
+        ]
+      },
       {
         "SQL": "select /*+ straight_join() */ * from t2 join (t1 join t3 on t1.a=t3.a) on t2.a=1;",
         "Plan": [
@@ -69,6 +158,38 @@
           "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
         ]
       },
+      {
+        "SQL": "select /*+ straight_join() */ * from t1 join (t2 join t3 on t2.a=t3.a) on t1.a=t3.a;",
+        "Plan": [
+          "HashJoin 15609.38 root  inner join, equal:[eq(test.t1.a, test.t3.a)]",
+          "├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
+          "│   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 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",
+          "  └─TableReader(Probe) 9990.00 root  data:Selection",
+          "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t2 keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from t3 join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+        "Plan": [
+          "HashJoin 15609.38 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",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "  │   └─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.a))",
+          "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
+        ]
+      },
       {
         "SQL": "select /*+ straight_join() */ * from t2 join t1 on t1.a=t2.a join t3 on t2.b=t3.b;",
         "Plan": [
@@ -176,6 +297,66 @@
           "    └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
           "      └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo"
         ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t4.a, test.t2.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─TableReader(Probe) 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"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─TableReader(Probe) 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"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
+        "Plan": [
+          "HashJoin 19511.72 root  inner join, equal:[eq(test.t4.a, test.t1.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─TableReader(Probe) 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"
+        ]
       }
     ]
   }

From f42f0153213b1134bd4c776513082c2bc06ba47e Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Tue, 10 May 2022 15:20:15 +0800
Subject: [PATCH 08/10] fix ut

---
 planner/core/expression_rewriter.go           |   3 +-
 planner/core/logical_plan_builder.go          |   7 +-
 planner/core/planbuilder.go                   |   1 -
 .../core/testdata/join_reorder_suite_in.json  |   8 +-
 .../core/testdata/join_reorder_suite_out.json | 209 +++++++++++++++++-
 planner/optimize.go                           |  13 +-
 session/session_legacy_test.go                |   6 +
 sessionctx/stmtctx/stmtctx.go                 |   1 +
 8 files changed, 231 insertions(+), 17 deletions(-)

diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go
index 24fa2059f2ba1..7ae67e361afbd 100644
--- a/planner/core/expression_rewriter.go
+++ b/planner/core/expression_rewriter.go
@@ -936,8 +936,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte
 		// We need to try to eliminate the agg and the projection produced by this operation.
 		er.b.optFlag |= flagEliminateAgg
 		er.b.optFlag |= flagEliminateProjection
-		tableHints := er.b.TableHints()
-		if tableHints == nil || !tableHints.straightJoinOrder {
+		if !er.sctx.GetSessionVars().StmtCtx.StraightJoinOrder {
 			er.b.optFlag |= flagJoinReOrder
 		}
 		// Build distinct for the inner query.
diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go
index 5b75032f59a6c..a13b6d05b0c3c 100644
--- a/planner/core/logical_plan_builder.go
+++ b/planner/core/logical_plan_builder.go
@@ -677,8 +677,7 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica
 
 	b.optFlag = b.optFlag | flagPredicatePushDown
 	// Add join reorder flag regardless of inner join or outer join.
-	tableHints := b.TableHints()
-	if tableHints == nil || !tableHints.straightJoinOrder {
+	if !b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder {
 		b.optFlag = b.optFlag | flagJoinReOrder
 	}
 
@@ -3514,7 +3513,6 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 		aggHints                                                                        aggHintInfo
 		timeRangeHint                                                                   ast.HintTimeRange
 		limitHints                                                                      limitHintInfo
-		straightJoinOrder                                                               bool
 	)
 	for _, hint := range hints {
 		// Set warning for the hint that requires the table name.
@@ -3617,8 +3615,6 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 			timeRangeHint = hint.HintData.(ast.HintTimeRange)
 		case HintLimitToCop:
 			limitHints.preferLimitToCop = true
-		case HintStraightJoin:
-			straightJoinOrder = true
 		default:
 			// ignore hints that not implemented
 		}
@@ -3635,7 +3631,6 @@ func (b *PlanBuilder) pushTableHints(hints []*ast.TableOptimizerHint, currentLev
 		indexMergeHintList:        indexMergeHintList,
 		timeRangeHint:             timeRangeHint,
 		limitHints:                limitHints,
-		straightJoinOrder:         straightJoinOrder,
 	})
 }
 
diff --git a/planner/core/planbuilder.go b/planner/core/planbuilder.go
index c446619a13aec..f2005a20c40be 100644
--- a/planner/core/planbuilder.go
+++ b/planner/core/planbuilder.go
@@ -97,7 +97,6 @@ type tableHintInfo struct {
 	indexMergeHintList  []indexHintInfo
 	timeRangeHint       ast.HintTimeRange
 	limitHints          limitHintInfo
-	straightJoinOrder   bool
 }
 
 type limitHintInfo struct {
diff --git a/planner/core/testdata/join_reorder_suite_in.json b/planner/core/testdata/join_reorder_suite_in.json
index 2482235ce94cd..0c6b211f824b6 100644
--- a/planner/core/testdata/join_reorder_suite_in.json
+++ b/planner/core/testdata/join_reorder_suite_in.json
@@ -21,7 +21,13 @@
       "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join (t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
       "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
       "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
-      "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;"
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;"
     ]
   }
 ]
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
index 705c9dbcd0194..b07ee082952f9 100644
--- a/planner/core/testdata/join_reorder_suite_out.json
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -339,9 +339,9 @@
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
         "Plan": [
-          "HashJoin 19511.72 root  inner join, equal:[eq(test.t4.a, test.t1.a)]",
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t4.a, test.t1.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
           "│ ├─TableReader(Build) 9990.00 root  data:Selection",
           "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
@@ -349,13 +349,210 @@
           "│ └─TableReader(Probe) 9990.00 root  data:Selection",
           "│   └─Selection 9990.00 cop[tikv]  not(isnull(test.t1.a))",
           "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "└─HashJoin(Probe) 12487.50 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
           "  ├─TableReader(Build) 9990.00 root  data:Selection",
           "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
           "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
-          "  └─TableReader(Probe) 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) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t2.a, test.t4.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t1.a, test.t4.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t4.a, test.t2.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+        ]
+      },
+      {
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
+        "Plan": [
+          "HashJoin 304261169.13 root  inner join, equal:[eq(test.t4.a, test.t1.a)]",
+          "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
+          "│ ├─TableReader(Build) 9990.00 root  data:Selection",
+          "│ │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t2.a))",
+          "│ │   └─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.a))",
+          "│     └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "└─HashJoin(Probe) 194727148.24 root  inner join, equal:[eq(test.t3.a, test.t4.a)]",
+          "  ├─TableReader(Build) 9990.00 root  data:Selection",
+          "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
+          "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
+          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
+          "    ├─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) 15593.77 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",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "        ├─TableReader(Build) 9980.01 root  data:Selection",
+          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
+          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
+          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
         ]
       }
     ]
diff --git a/planner/optimize.go b/planner/optimize.go
index fcf58000a2976..26328f64b610a 100644
--- a/planner/optimize.go
+++ b/planner/optimize.go
@@ -554,7 +554,7 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin
 	}
 	hintOffs := make(map[string]int, len(hints))
 	var forceNthPlan *ast.TableOptimizerHint
-	var memoryQuotaHintCnt, useToJAHintCnt, useCascadesHintCnt, noIndexMergeHintCnt, readReplicaHintCnt, maxExecutionTimeCnt, forceNthPlanCnt int
+	var memoryQuotaHintCnt, useToJAHintCnt, useCascadesHintCnt, noIndexMergeHintCnt, readReplicaHintCnt, maxExecutionTimeCnt, forceNthPlanCnt, straightJoinHintCnt int
 	setVars := make(map[string]string)
 	setVarsOffs := make([]int, 0, len(hints))
 	for i, hint := range hints {
@@ -580,6 +580,9 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin
 		case "nth_plan":
 			forceNthPlanCnt++
 			forceNthPlan = hint
+		case "straight_join":
+			hintOffs[hint.HintName.L] = i
+			straightJoinHintCnt++
 		case "set_var":
 			setVarHint := hint.HintData.(ast.HintSetVar)
 
@@ -655,6 +658,14 @@ func handleStmtHints(hints []*ast.TableOptimizerHint) (stmtHints stmtctx.StmtHin
 		}
 		stmtHints.NoIndexMergeHint = true
 	}
+	// Handle straight_join
+	if straightJoinHintCnt != 0 {
+		if straightJoinHintCnt > 1 {
+			warn := errors.New("STRAIGHT_JOIN() is defined more than once, only the last definition takes effect")
+			warns = append(warns, warn)
+		}
+		stmtHints.StraightJoinOrder = true
+	}
 	// Handle READ_CONSISTENT_REPLICA
 	if readReplicaHintCnt != 0 {
 		if readReplicaHintCnt > 1 {
diff --git a/session/session_legacy_test.go b/session/session_legacy_test.go
index 93bca3c9c5f40..871781041585a 100644
--- a/session/session_legacy_test.go
+++ b/session/session_legacy_test.go
@@ -2801,6 +2801,12 @@ func (s *testSessionSuite2) TestStmtHints(c *C) {
 	c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1)
 	c.Assert(tk.Se.GetSessionVars().GetEnableIndexMerge(), IsTrue)
 
+	// Test STRAIGHT_JOIN hint
+	tk.MustExec("select /*+ straight_join() */ 1;")
+	c.Assert(tk.Se.GetSessionVars().StmtCtx.StraightJoinOrder, IsTrue)
+	tk.MustExec("select /*+ straight_join(), straight_join() */ 1;")
+	c.Assert(tk.Se.GetSessionVars().StmtCtx.GetWarnings(), HasLen, 1)
+
 	// Test USE_TOJA hint
 	tk.Se.GetSessionVars().SetAllowInSubqToJoinAndAgg(true)
 	tk.MustExec("select /*+ USE_TOJA(false) */ 1;")
diff --git a/sessionctx/stmtctx/stmtctx.go b/sessionctx/stmtctx/stmtctx.go
index 3320ce672e13c..ebcbd72a2ef67 100644
--- a/sessionctx/stmtctx/stmtctx.go
+++ b/sessionctx/stmtctx/stmtctx.go
@@ -259,6 +259,7 @@ type StmtHints struct {
 	ReplicaRead             byte
 	AllowInSubqToJoinAndAgg bool
 	NoIndexMergeHint        bool
+	StraightJoinOrder       bool
 	// EnableCascadesPlanner is use cascades planner for a single query only.
 	EnableCascadesPlanner bool
 	// ForceNthPlan indicates the PlanCounterTp number for finding physical plan.

From 6f19b4de0be7370c5ab2cef5460f8a4693fa4ee4 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Tue, 10 May 2022 15:28:00 +0800
Subject: [PATCH 09/10] fix ut

---
 .../core/testdata/join_reorder_suite_in.json  |  10 +-
 .../core/testdata/join_reorder_suite_out.json | 110 +++++++++---------
 2 files changed, 60 insertions(+), 60 deletions(-)

diff --git a/planner/core/testdata/join_reorder_suite_in.json b/planner/core/testdata/join_reorder_suite_in.json
index 0c6b211f824b6..02b41c4355c4f 100644
--- a/planner/core/testdata/join_reorder_suite_in.json
+++ b/planner/core/testdata/join_reorder_suite_in.json
@@ -23,11 +23,11 @@
       "select /*+ straight_join() */ * from (t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
       "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
       "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t4.a;",
-      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
-      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
-      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
-      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
-      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;"
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t1, t3, t2, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t1, t2, t, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t2, t1, t, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+      "select /*+ straight_join() */ * from ((select t3.a, t3.b from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;"
     ]
   }
 ]
diff --git a/planner/core/testdata/join_reorder_suite_out.json b/planner/core/testdata/join_reorder_suite_out.json
index b07ee082952f9..a0af850e8a9d8 100644
--- a/planner/core/testdata/join_reorder_suite_out.json
+++ b/planner/core/testdata/join_reorder_suite_out.json
@@ -401,7 +401,7 @@
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t1, t3, t2, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t2.a=t3.a;",
         "Plan": [
           "HashJoin 304261169.13 root  inner join, equal:[eq(test.t2.a, test.t3.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
@@ -415,24 +415,24 @@
           "  ├─TableReader(Build) 9990.00 root  data:Selection",
           "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
           "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
-          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
-          "    ├─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) 15593.77 root  inner join, equal:[eq(test.t1.b, test.t2.b)]",
+          "  └─HashJoin(Probe) 155781718.59 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
+          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo",
+          "    └─HashJoin(Probe) 124625374.88 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",
-          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "      └─HashJoin(Probe) 99700299.90 root  CARTESIAN inner join",
           "        ├─TableReader(Build) 9980.01 root  data:Selection",
           "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
           "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
-          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+          "        └─TableReader(Probe) 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"
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
+        "SQL": "select /*+ straight_join() */ * from (t1 join t2 on t1.a=t2.a) join ((select t3.a, t3.b from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) on t1.a=t4.a;",
         "Plan": [
           "HashJoin 304261169.13 root  inner join, equal:[eq(test.t1.a, test.t4.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
@@ -446,24 +446,24 @@
           "  ├─TableReader(Build) 9990.00 root  data:Selection",
           "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
           "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
-          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
-          "    ├─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) 15593.77 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",
-          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "        ├─TableReader(Build) 9980.01 root  data:Selection",
-          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
-          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
-          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+          "  └─HashJoin(Probe) 155781718.59 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
+          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo",
+          "    └─HashJoin(Probe) 124625374.88 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.t1.a)), not(isnull(test.t1.b))",
+          "      │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "      └─HashJoin(Probe) 99800100.00 root  CARTESIAN inner join",
+          "        ├─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.t3.a))",
+          "            └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t1, t2, t, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t4.a;",
         "Plan": [
           "HashJoin 304261169.13 root  inner join, equal:[eq(test.t4.a, test.t2.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
@@ -481,20 +481,20 @@
           "    ├─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) 15593.77 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",
-          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    └─HashJoin(Probe) 15593.77 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "      ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
+          "      │ └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo",
+          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t1.b, test.t2.b)]",
           "        ├─TableReader(Build) 9980.01 root  data:Selection",
           "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
           "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
-          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) 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"
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t2, t1, t, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t2.a=t3.a;",
         "Plan": [
           "HashJoin 304261169.13 root  inner join, equal:[eq(test.t3.a, test.t2.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
@@ -512,20 +512,20 @@
           "    ├─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) 15593.77 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",
-          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
+          "    └─HashJoin(Probe) 15593.77 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "      ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
+          "      │ └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) 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.t1.a)), not(isnull(test.t1.b))",
           "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
-          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) 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"
         ]
       },
       {
-        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t, t1, t2, t3 where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
+        "SQL": "select /*+ straight_join() */ * from ((select t3.a, t3.b from t3, t2, t1, t where t.a = t1.a and t1.b=t2.b) t3 join t4 on t3.a=t4.a) join (t1 join t2 on t1.a=t2.a) on t1.a=t4.a;",
         "Plan": [
           "HashJoin 304261169.13 root  inner join, equal:[eq(test.t4.a, test.t1.a)]",
           "├─HashJoin(Build) 12487.50 root  inner join, equal:[eq(test.t1.a, test.t2.a)]",
@@ -539,20 +539,20 @@
           "  ├─TableReader(Build) 9990.00 root  data:Selection",
           "  │ └─Selection 9990.00 cop[tikv]  not(isnull(test.t4.a))",
           "  │   └─TableFullScan 10000.00 cop[tikv] table:t4 keep order:false, stats:pseudo",
-          "  └─HashJoin(Probe) 155781718.59 root  CARTESIAN inner join",
-          "    ├─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) 15593.77 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",
-          "      └─HashJoin(Probe) 12475.01 root  inner join, equal:[eq(test.t.a, test.t1.a)]",
-          "        ├─TableReader(Build) 9980.01 root  data:Selection",
-          "        │ └─Selection 9980.01 cop[tikv]  not(isnull(test.t1.a)), not(isnull(test.t1.b))",
-          "        │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
-          "        └─IndexReader(Probe) 9990.00 root  index:IndexFullScan",
-          "          └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo"
+          "  └─HashJoin(Probe) 155781718.59 root  inner join, equal:[eq(test.t1.a, test.t.a)]",
+          "    ├─IndexReader(Build) 9990.00 root  index:IndexFullScan",
+          "    │ └─IndexFullScan 9990.00 cop[tikv] table:t, index:a(a) keep order:false, stats:pseudo",
+          "    └─HashJoin(Probe) 124625374.88 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.t1.a)), not(isnull(test.t1.b))",
+          "      │   └─TableFullScan 10000.00 cop[tikv] table:t1 keep order:false, stats:pseudo",
+          "      └─HashJoin(Probe) 99800100.00 root  CARTESIAN inner join",
+          "        ├─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.t3.a))",
+          "            └─TableFullScan 10000.00 cop[tikv] table:t3 keep order:false, stats:pseudo"
         ]
       }
     ]

From 4782b87356ecc43f31a30b76f0a82e7e40087331 Mon Sep 17 00:00:00 2001
From: Reminiscent <y870414423@gmail.com>
Date: Wed, 11 May 2022 10:22:27 +0800
Subject: [PATCH 10/10] fix ut

---
 planner/core/expression_rewriter.go  | 4 +---
 planner/core/logical_plan_builder.go | 4 +---
 planner/core/optimizer.go            | 4 ++++
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/planner/core/expression_rewriter.go b/planner/core/expression_rewriter.go
index 7ae67e361afbd..ee5669a45e81f 100644
--- a/planner/core/expression_rewriter.go
+++ b/planner/core/expression_rewriter.go
@@ -936,9 +936,7 @@ func (er *expressionRewriter) handleInSubquery(ctx context.Context, v *ast.Patte
 		// We need to try to eliminate the agg and the projection produced by this operation.
 		er.b.optFlag |= flagEliminateAgg
 		er.b.optFlag |= flagEliminateProjection
-		if !er.sctx.GetSessionVars().StmtCtx.StraightJoinOrder {
-			er.b.optFlag |= flagJoinReOrder
-		}
+		er.b.optFlag |= flagJoinReOrder
 		// Build distinct for the inner query.
 		agg, err := er.b.buildDistinct(np, np.Schema().Len())
 		if err != nil {
diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go
index a13b6d05b0c3c..69773f62d9535 100644
--- a/planner/core/logical_plan_builder.go
+++ b/planner/core/logical_plan_builder.go
@@ -677,9 +677,7 @@ func (b *PlanBuilder) buildJoin(ctx context.Context, joinNode *ast.Join) (Logica
 
 	b.optFlag = b.optFlag | flagPredicatePushDown
 	// Add join reorder flag regardless of inner join or outer join.
-	if !b.ctx.GetSessionVars().StmtCtx.StraightJoinOrder {
-		b.optFlag = b.optFlag | flagJoinReOrder
-	}
+	b.optFlag = b.optFlag | flagJoinReOrder
 
 	leftPlan, err := b.buildResultSetNode(ctx, joinNode.Left)
 	if err != nil {
diff --git a/planner/core/optimizer.go b/planner/core/optimizer.go
index a93b2c257a4a3..b1d8dcd04ced4 100644
--- a/planner/core/optimizer.go
+++ b/planner/core/optimizer.go
@@ -269,6 +269,10 @@ func DoOptimize(ctx context.Context, sctx sessionctx.Context, flag uint64, logic
 	if checkStableResultMode(sctx) {
 		flag |= flagStabilizeResults
 	}
+	if sctx.GetSessionVars().StmtCtx.StraightJoinOrder {
+		// When we use the straight Join Order hint, we should disable the join reorder optimization.
+		flag &= ^flagJoinReOrder
+	}
 	flag |= flagCollectPredicateColumnsPoint
 	flag |= flagSyncWaitStatsLoadPoint
 	logic, err := logicalOptimize(ctx, flag, logic)