hintparser.y 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. %{
  2. // Copyright 2020 PingCAP, Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package parser
  15. import (
  16. "math"
  17. "strconv"
  18. "github.com/pingcap/parser/ast"
  19. "github.com/pingcap/parser/model"
  20. )
  21. %}
  22. %union {
  23. offset int
  24. ident string
  25. number uint64
  26. hint *ast.TableOptimizerHint
  27. hints []*ast.TableOptimizerHint
  28. table ast.HintTable
  29. modelIdents []model.CIStr
  30. }
  31. %token <number>
  32. /*yy:token "%d" */
  33. hintIntLit "a 64-bit unsigned integer"
  34. %token <ident>
  35. /*yy:token "%c" */
  36. hintIdentifier
  37. /*yy:token "@%c" */
  38. hintSingleAtIdentifier "identifier with single leading at"
  39. /*yy:token "'%c'" */
  40. hintStringLit
  41. /* MySQL 8.0 hint names */
  42. hintJoinFixedOrder "JOIN_FIXED_ORDER"
  43. hintJoinOrder "JOIN_ORDER"
  44. hintJoinPrefix "JOIN_PREFIX"
  45. hintJoinSuffix "JOIN_SUFFIX"
  46. hintBKA "BKA"
  47. hintNoBKA "NO_BKA"
  48. hintBNL "BNL"
  49. hintNoBNL "NO_BNL"
  50. hintHashJoin "HASH_JOIN"
  51. hintNoHashJoin "NO_HASH_JOIN"
  52. hintMerge "MERGE"
  53. hintNoMerge "NO_MERGE"
  54. hintIndexMerge "INDEX_MERGE"
  55. hintNoIndexMerge "NO_INDEX_MERGE"
  56. hintMRR "MRR"
  57. hintNoMRR "NO_MRR"
  58. hintNoICP "NO_ICP"
  59. hintNoRangeOptimization "NO_RANGE_OPTIMIZATION"
  60. hintSkipScan "SKIP_SCAN"
  61. hintNoSkipScan "NO_SKIP_SCAN"
  62. hintSemijoin "SEMIJOIN"
  63. hintNoSemijoin "NO_SEMIJOIN"
  64. hintMaxExecutionTime "MAX_EXECUTION_TIME"
  65. hintSetVar "SET_VAR"
  66. hintResourceGroup "RESOURCE_GROUP"
  67. hintQBName "QB_NAME"
  68. /* TiDB hint names */
  69. hintAggToCop "AGG_TO_COP"
  70. hintIgnorePlanCache "IGNORE_PLAN_CACHE"
  71. hintHashAgg "HASH_AGG"
  72. hintIgnoreIndex "IGNORE_INDEX"
  73. hintInlHashJoin "INL_HASH_JOIN"
  74. hintInlJoin "INL_JOIN"
  75. hintInlMergeJoin "INL_MERGE_JOIN"
  76. hintMemoryQuota "MEMORY_QUOTA"
  77. hintNoSwapJoinInputs "NO_SWAP_JOIN_INPUTS"
  78. hintQueryType "QUERY_TYPE"
  79. hintReadConsistentReplica "READ_CONSISTENT_REPLICA"
  80. hintReadFromStorage "READ_FROM_STORAGE"
  81. hintSMJoin "MERGE_JOIN"
  82. hintBCJoin "BROADCAST_JOIN"
  83. hintBCJoinPreferLocal "BROADCAST_JOIN_LOCAL"
  84. hintStreamAgg "STREAM_AGG"
  85. hintSwapJoinInputs "SWAP_JOIN_INPUTS"
  86. hintUseIndexMerge "USE_INDEX_MERGE"
  87. hintUseIndex "USE_INDEX"
  88. hintUsePlanCache "USE_PLAN_CACHE"
  89. hintUseToja "USE_TOJA"
  90. hintTimeRange "TIME_RANGE"
  91. hintUseCascades "USE_CASCADES"
  92. hintNthPlan "NTH_PLAN"
  93. hintLimitToCop "LIMIT_TO_COP"
  94. hintForceIndex "FORCE_INDEX"
  95. /* Other keywords */
  96. hintOLAP "OLAP"
  97. hintOLTP "OLTP"
  98. hintPartition "PARTITION"
  99. hintTiKV "TIKV"
  100. hintTiFlash "TIFLASH"
  101. hintFalse "FALSE"
  102. hintTrue "TRUE"
  103. hintMB "MB"
  104. hintGB "GB"
  105. hintDupsWeedOut "DUPSWEEDOUT"
  106. hintFirstMatch "FIRSTMATCH"
  107. hintLooseScan "LOOSESCAN"
  108. hintMaterialization "MATERIALIZATION"
  109. %type <ident>
  110. Identifier "identifier (including keywords)"
  111. QueryBlockOpt "Query block identifier optional"
  112. JoinOrderOptimizerHintName
  113. UnsupportedTableLevelOptimizerHintName
  114. SupportedTableLevelOptimizerHintName
  115. UnsupportedIndexLevelOptimizerHintName
  116. SupportedIndexLevelOptimizerHintName
  117. SubqueryOptimizerHintName
  118. BooleanHintName "name of hints which take a boolean input"
  119. NullaryHintName "name of hints which take no input"
  120. SubqueryStrategy
  121. Value "the value in the SET_VAR() hint"
  122. HintQueryType "query type in optimizer hint (OLAP or OLTP)"
  123. HintStorageType "storage type in optimizer hint (TiKV or TiFlash)"
  124. %type <number>
  125. UnitOfBytes "unit of bytes (MB or GB)"
  126. CommaOpt "optional ','"
  127. %type <hints>
  128. OptimizerHintList "optimizer hint list"
  129. StorageOptimizerHintOpt "storage level optimizer hint"
  130. HintStorageTypeAndTableList "storage type and tables list in optimizer hint"
  131. %type <hint>
  132. TableOptimizerHintOpt "optimizer hint"
  133. HintTableList "table list in optimizer hint"
  134. HintTableListOpt "optional table list in optimizer hint"
  135. HintIndexList "table name with index list in optimizer hint"
  136. IndexNameList "index list in optimizer hint"
  137. IndexNameListOpt "optional index list in optimizer hint"
  138. SubqueryStrategies "subquery strategies"
  139. SubqueryStrategiesOpt "optional subquery strategies"
  140. HintTrueOrFalse "true or false in optimizer hint"
  141. HintStorageTypeAndTable "storage type and tables in optimizer hint"
  142. %type <table>
  143. HintTable "Table in optimizer hint"
  144. %type <modelIdents>
  145. PartitionList "partition name list in optimizer hint"
  146. PartitionListOpt "optional partition name list in optimizer hint"
  147. %start Start
  148. %%
  149. Start:
  150. OptimizerHintList
  151. {
  152. parser.result = $1
  153. }
  154. OptimizerHintList:
  155. TableOptimizerHintOpt
  156. {
  157. if $1 != nil {
  158. $$ = []*ast.TableOptimizerHint{$1}
  159. }
  160. }
  161. | OptimizerHintList CommaOpt TableOptimizerHintOpt
  162. {
  163. if $3 != nil {
  164. $$ = append($1, $3)
  165. } else {
  166. $$ = $1
  167. }
  168. }
  169. | StorageOptimizerHintOpt
  170. {
  171. $$ = $1
  172. }
  173. | OptimizerHintList CommaOpt StorageOptimizerHintOpt
  174. {
  175. $$ = append($1, $3...)
  176. }
  177. TableOptimizerHintOpt:
  178. "JOIN_FIXED_ORDER" '(' QueryBlockOpt ')'
  179. {
  180. parser.warnUnsupportedHint($1)
  181. $$ = nil
  182. }
  183. | JoinOrderOptimizerHintName '(' HintTableList ')'
  184. {
  185. parser.warnUnsupportedHint($1)
  186. $$ = nil
  187. }
  188. | UnsupportedTableLevelOptimizerHintName '(' HintTableListOpt ')'
  189. {
  190. parser.warnUnsupportedHint($1)
  191. $$ = nil
  192. }
  193. | SupportedTableLevelOptimizerHintName '(' HintTableListOpt ')'
  194. {
  195. h := $3
  196. h.HintName = model.NewCIStr($1)
  197. $$ = h
  198. }
  199. | UnsupportedIndexLevelOptimizerHintName '(' HintIndexList ')'
  200. {
  201. parser.warnUnsupportedHint($1)
  202. $$ = nil
  203. }
  204. | SupportedIndexLevelOptimizerHintName '(' HintIndexList ')'
  205. {
  206. h := $3
  207. h.HintName = model.NewCIStr($1)
  208. $$ = h
  209. }
  210. | SubqueryOptimizerHintName '(' QueryBlockOpt SubqueryStrategiesOpt ')'
  211. {
  212. parser.warnUnsupportedHint($1)
  213. $$ = nil
  214. }
  215. | "MAX_EXECUTION_TIME" '(' QueryBlockOpt hintIntLit ')'
  216. {
  217. $$ = &ast.TableOptimizerHint{
  218. HintName: model.NewCIStr($1),
  219. QBName: model.NewCIStr($3),
  220. HintData: $4,
  221. }
  222. }
  223. | "NTH_PLAN" '(' QueryBlockOpt hintIntLit ')'
  224. {
  225. $$ = &ast.TableOptimizerHint{
  226. HintName: model.NewCIStr($1),
  227. QBName: model.NewCIStr($3),
  228. HintData: int64($4),
  229. }
  230. }
  231. | "SET_VAR" '(' Identifier '=' Value ')'
  232. {
  233. $$ = &ast.TableOptimizerHint{
  234. HintName: model.NewCIStr($1),
  235. HintData: ast.HintSetVar{
  236. VarName: $3,
  237. Value: $5,
  238. },
  239. }
  240. }
  241. | "RESOURCE_GROUP" '(' Identifier ')'
  242. {
  243. parser.warnUnsupportedHint($1)
  244. $$ = nil
  245. }
  246. | "QB_NAME" '(' Identifier ')'
  247. {
  248. $$ = &ast.TableOptimizerHint{
  249. HintName: model.NewCIStr($1),
  250. QBName: model.NewCIStr($3),
  251. }
  252. }
  253. | "MEMORY_QUOTA" '(' QueryBlockOpt hintIntLit UnitOfBytes ')'
  254. {
  255. maxValue := uint64(math.MaxInt64) / $5
  256. if $4 <= maxValue {
  257. $$ = &ast.TableOptimizerHint{
  258. HintName: model.NewCIStr($1),
  259. HintData: int64($4 * $5),
  260. QBName: model.NewCIStr($3),
  261. }
  262. } else {
  263. yylex.AppendError(ErrWarnMemoryQuotaOverflow.GenWithStackByArgs(math.MaxInt64))
  264. parser.lastErrorAsWarn()
  265. $$ = nil
  266. }
  267. }
  268. | "TIME_RANGE" '(' hintStringLit CommaOpt hintStringLit ')'
  269. {
  270. $$ = &ast.TableOptimizerHint{
  271. HintName: model.NewCIStr($1),
  272. HintData: ast.HintTimeRange{
  273. From: $3,
  274. To: $5,
  275. },
  276. }
  277. }
  278. | BooleanHintName '(' QueryBlockOpt HintTrueOrFalse ')'
  279. {
  280. h := $4
  281. h.HintName = model.NewCIStr($1)
  282. h.QBName = model.NewCIStr($3)
  283. $$ = h
  284. }
  285. | NullaryHintName '(' QueryBlockOpt ')'
  286. {
  287. $$ = &ast.TableOptimizerHint{
  288. HintName: model.NewCIStr($1),
  289. QBName: model.NewCIStr($3),
  290. }
  291. }
  292. | "QUERY_TYPE" '(' QueryBlockOpt HintQueryType ')'
  293. {
  294. $$ = &ast.TableOptimizerHint{
  295. HintName: model.NewCIStr($1),
  296. QBName: model.NewCIStr($3),
  297. HintData: model.NewCIStr($4),
  298. }
  299. }
  300. StorageOptimizerHintOpt:
  301. "READ_FROM_STORAGE" '(' QueryBlockOpt HintStorageTypeAndTableList ')'
  302. {
  303. hs := $4
  304. name := model.NewCIStr($1)
  305. qb := model.NewCIStr($3)
  306. for _, h := range hs {
  307. h.HintName = name
  308. h.QBName = qb
  309. }
  310. $$ = hs
  311. }
  312. HintStorageTypeAndTableList:
  313. HintStorageTypeAndTable
  314. {
  315. $$ = []*ast.TableOptimizerHint{$1}
  316. }
  317. | HintStorageTypeAndTableList ',' HintStorageTypeAndTable
  318. {
  319. $$ = append($1, $3)
  320. }
  321. HintStorageTypeAndTable:
  322. HintStorageType '[' HintTableList ']'
  323. {
  324. h := $3
  325. h.HintData = model.NewCIStr($1)
  326. $$ = h
  327. }
  328. QueryBlockOpt:
  329. /* empty */
  330. {
  331. $$ = ""
  332. }
  333. | hintSingleAtIdentifier
  334. CommaOpt:
  335. /*empty*/
  336. {}
  337. | ','
  338. {}
  339. PartitionListOpt:
  340. /* empty */
  341. {
  342. $$ = nil
  343. }
  344. | "PARTITION" '(' PartitionList ')'
  345. {
  346. $$ = $3
  347. }
  348. PartitionList:
  349. Identifier
  350. {
  351. $$ = []model.CIStr{model.NewCIStr($1)}
  352. }
  353. | PartitionList CommaOpt Identifier
  354. {
  355. $$ = append($1, model.NewCIStr($3))
  356. }
  357. /**
  358. * HintTableListOpt:
  359. *
  360. * [@query_block_name] [tbl_name [, tbl_name] ...]
  361. * [tbl_name@query_block_name [, tbl_name@query_block_name] ...]
  362. *
  363. */
  364. HintTableListOpt:
  365. HintTableList
  366. | QueryBlockOpt
  367. {
  368. $$ = &ast.TableOptimizerHint{
  369. QBName: model.NewCIStr($1),
  370. }
  371. }
  372. HintTableList:
  373. QueryBlockOpt HintTable
  374. {
  375. $$ = &ast.TableOptimizerHint{
  376. Tables: []ast.HintTable{$2},
  377. QBName: model.NewCIStr($1),
  378. }
  379. }
  380. | HintTableList ',' HintTable
  381. {
  382. h := $1
  383. h.Tables = append(h.Tables, $3)
  384. $$ = h
  385. }
  386. HintTable:
  387. Identifier QueryBlockOpt PartitionListOpt
  388. {
  389. $$ = ast.HintTable{
  390. TableName: model.NewCIStr($1),
  391. QBName: model.NewCIStr($2),
  392. PartitionList: $3,
  393. }
  394. }
  395. | Identifier '.' Identifier QueryBlockOpt PartitionListOpt
  396. {
  397. $$ = ast.HintTable{
  398. DBName: model.NewCIStr($1),
  399. TableName: model.NewCIStr($3),
  400. QBName: model.NewCIStr($4),
  401. PartitionList: $5,
  402. }
  403. }
  404. /**
  405. * HintIndexList:
  406. *
  407. * [@query_block_name] tbl_name [index_name [, index_name] ...]
  408. * tbl_name@query_block_name [index_name [, index_name] ...]
  409. */
  410. HintIndexList:
  411. QueryBlockOpt HintTable CommaOpt IndexNameListOpt
  412. {
  413. h := $4
  414. h.Tables = []ast.HintTable{$2}
  415. h.QBName = model.NewCIStr($1)
  416. $$ = h
  417. }
  418. IndexNameListOpt:
  419. /* empty */
  420. {
  421. $$ = &ast.TableOptimizerHint{}
  422. }
  423. | IndexNameList
  424. IndexNameList:
  425. Identifier
  426. {
  427. $$ = &ast.TableOptimizerHint{
  428. Indexes: []model.CIStr{model.NewCIStr($1)},
  429. }
  430. }
  431. | IndexNameList ',' Identifier
  432. {
  433. h := $1
  434. h.Indexes = append(h.Indexes, model.NewCIStr($3))
  435. $$ = h
  436. }
  437. /**
  438. * Miscellaneous rules
  439. */
  440. SubqueryStrategiesOpt:
  441. /* empty */
  442. {}
  443. | SubqueryStrategies
  444. SubqueryStrategies:
  445. SubqueryStrategy
  446. {}
  447. | SubqueryStrategies ',' SubqueryStrategy
  448. Value:
  449. hintStringLit
  450. | Identifier
  451. | hintIntLit
  452. {
  453. $$ = strconv.FormatUint($1, 10)
  454. }
  455. UnitOfBytes:
  456. "MB"
  457. {
  458. $$ = 1024 * 1024
  459. }
  460. | "GB"
  461. {
  462. $$ = 1024 * 1024 * 1024
  463. }
  464. HintTrueOrFalse:
  465. "TRUE"
  466. {
  467. $$ = &ast.TableOptimizerHint{HintData: true}
  468. }
  469. | "FALSE"
  470. {
  471. $$ = &ast.TableOptimizerHint{HintData: false}
  472. }
  473. JoinOrderOptimizerHintName:
  474. "JOIN_ORDER"
  475. | "JOIN_PREFIX"
  476. | "JOIN_SUFFIX"
  477. UnsupportedTableLevelOptimizerHintName:
  478. "BKA"
  479. | "NO_BKA"
  480. | "BNL"
  481. | "NO_BNL"
  482. /* HASH_JOIN is supported by TiDB */
  483. | "NO_HASH_JOIN"
  484. | "MERGE"
  485. | "NO_MERGE"
  486. SupportedTableLevelOptimizerHintName:
  487. "MERGE_JOIN"
  488. | "BROADCAST_JOIN"
  489. | "BROADCAST_JOIN_LOCAL"
  490. | "INL_JOIN"
  491. | "INL_HASH_JOIN"
  492. | "SWAP_JOIN_INPUTS"
  493. | "NO_SWAP_JOIN_INPUTS"
  494. | "INL_MERGE_JOIN"
  495. | "HASH_JOIN"
  496. UnsupportedIndexLevelOptimizerHintName:
  497. "INDEX_MERGE"
  498. /* NO_INDEX_MERGE is currently a nullary hint in TiDB */
  499. | "MRR"
  500. | "NO_MRR"
  501. | "NO_ICP"
  502. | "NO_RANGE_OPTIMIZATION"
  503. | "SKIP_SCAN"
  504. | "NO_SKIP_SCAN"
  505. SupportedIndexLevelOptimizerHintName:
  506. "USE_INDEX"
  507. | "IGNORE_INDEX"
  508. | "USE_INDEX_MERGE"
  509. | "FORCE_INDEX"
  510. SubqueryOptimizerHintName:
  511. "SEMIJOIN"
  512. | "NO_SEMIJOIN"
  513. SubqueryStrategy:
  514. "DUPSWEEDOUT"
  515. | "FIRSTMATCH"
  516. | "LOOSESCAN"
  517. | "MATERIALIZATION"
  518. BooleanHintName:
  519. "USE_TOJA"
  520. | "USE_CASCADES"
  521. NullaryHintName:
  522. "USE_PLAN_CACHE"
  523. | "HASH_AGG"
  524. | "STREAM_AGG"
  525. | "AGG_TO_COP"
  526. | "LIMIT_TO_COP"
  527. | "NO_INDEX_MERGE"
  528. | "READ_CONSISTENT_REPLICA"
  529. | "IGNORE_PLAN_CACHE"
  530. HintQueryType:
  531. "OLAP"
  532. | "OLTP"
  533. HintStorageType:
  534. "TIKV"
  535. | "TIFLASH"
  536. Identifier:
  537. hintIdentifier
  538. /* MySQL 8.0 hint names */
  539. | "JOIN_FIXED_ORDER"
  540. | "JOIN_ORDER"
  541. | "JOIN_PREFIX"
  542. | "JOIN_SUFFIX"
  543. | "BKA"
  544. | "NO_BKA"
  545. | "BNL"
  546. | "NO_BNL"
  547. | "HASH_JOIN"
  548. | "NO_HASH_JOIN"
  549. | "MERGE"
  550. | "NO_MERGE"
  551. | "INDEX_MERGE"
  552. | "NO_INDEX_MERGE"
  553. | "MRR"
  554. | "NO_MRR"
  555. | "NO_ICP"
  556. | "NO_RANGE_OPTIMIZATION"
  557. | "SKIP_SCAN"
  558. | "NO_SKIP_SCAN"
  559. | "SEMIJOIN"
  560. | "NO_SEMIJOIN"
  561. | "MAX_EXECUTION_TIME"
  562. | "SET_VAR"
  563. | "RESOURCE_GROUP"
  564. | "QB_NAME"
  565. /* TiDB hint names */
  566. | "AGG_TO_COP"
  567. | "LIMIT_TO_COP"
  568. | "IGNORE_PLAN_CACHE"
  569. | "HASH_AGG"
  570. | "IGNORE_INDEX"
  571. | "INL_HASH_JOIN"
  572. | "INL_JOIN"
  573. | "INL_MERGE_JOIN"
  574. | "MEMORY_QUOTA"
  575. | "NO_SWAP_JOIN_INPUTS"
  576. | "QUERY_TYPE"
  577. | "READ_CONSISTENT_REPLICA"
  578. | "READ_FROM_STORAGE"
  579. | "MERGE_JOIN"
  580. | "BROADCAST_JOIN"
  581. | "BROADCAST_JOIN_LOCAL"
  582. | "STREAM_AGG"
  583. | "SWAP_JOIN_INPUTS"
  584. | "USE_INDEX_MERGE"
  585. | "USE_INDEX"
  586. | "USE_PLAN_CACHE"
  587. | "USE_TOJA"
  588. | "TIME_RANGE"
  589. | "USE_CASCADES"
  590. | "NTH_PLAN"
  591. | "FORCE_INDEX"
  592. /* other keywords */
  593. | "OLAP"
  594. | "OLTP"
  595. | "TIKV"
  596. | "TIFLASH"
  597. | "FALSE"
  598. | "TRUE"
  599. | "MB"
  600. | "GB"
  601. | "DUPSWEEDOUT"
  602. | "FIRSTMATCH"
  603. | "LOOSESCAN"
  604. | "MATERIALIZATION"
  605. %%