1212import java .io .Serializable ;
1313import java .util .List ;
1414
15+ /**
16+ * A MySQL index hint after a table reference:
17+ * {@code {USE|IGNORE|FORCE} {INDEX|KEY} [FOR {JOIN|ORDER BY|GROUP BY}] (index_list)}.
18+ * <p>
19+ * A table may carry several hints, see {@code Table.getIndexHints()}. {@code USE INDEX ()} has an
20+ * empty index list.
21+ */
1522public class MySQLIndexHint implements Serializable {
1623
1724 private final String action ;
1825 private final String indexQualifier ;
26+ private final Scope scope ;
1927 private final List <String > indexNames ;
2028
2129 public MySQLIndexHint (String action , String indexQualifier , List <String > indexNames ) {
30+ this (action , indexQualifier , null , indexNames );
31+ }
32+
33+ /**
34+ * @param action {@code USE}, {@code IGNORE} or {@code FORCE}
35+ * @param indexQualifier {@code INDEX} or {@code KEY}
36+ * @param scope the {@code FOR JOIN|ORDER BY|GROUP BY} scope, or {@code null} for every use
37+ * @param indexNames the index names, empty for {@code USE INDEX ()}
38+ */
39+ public MySQLIndexHint (String action , String indexQualifier , Scope scope ,
40+ List <String > indexNames ) {
2241 this .action = action ;
2342 this .indexQualifier = indexQualifier ;
43+ this .scope = scope ;
2444 this .indexNames = indexNames ;
2545 }
2646
@@ -32,22 +52,53 @@ public String getIndexQualifier() {
3252 return indexQualifier ;
3353 }
3454
55+ /**
56+ * Returns the part of the query the hint applies to, or {@code null} when no {@code FOR} clause
57+ * was given.
58+ */
59+ public Scope getScope () {
60+ return scope ;
61+ }
62+
3563 public List <String > getIndexNames () {
3664 return indexNames ;
3765 }
3866
39- @ Override
40- public String toString () {
41- // use|ignore|force key|index (index1,...,indexN)
42- StringBuilder buffer = new StringBuilder ();
43- buffer .append (" " ).append (action ).append (" " ).append (indexQualifier ).append (" (" );
67+ /** Appends {@code " USE INDEX [FOR scope] (i1,i2)"}, with a leading space. */
68+ public StringBuilder appendTo (StringBuilder builder ) {
69+ // use|ignore|force key|index [for join|order by|group by] (index1,...,indexN)
70+ builder .append (" " ).append (action ).append (" " ).append (indexQualifier );
71+ if (scope != null ) {
72+ builder .append (" FOR " ).append (scope .getKeywords ());
73+ }
74+ builder .append (" (" );
4475 for (int i = 0 ; i < indexNames .size (); i ++) {
4576 if (i > 0 ) {
46- buffer .append ("," );
77+ builder .append ("," );
4778 }
48- buffer .append (indexNames .get (i ));
79+ builder .append (indexNames .get (i ));
80+ }
81+ return builder .append (")" );
82+ }
83+
84+ @ Override
85+ public String toString () {
86+ return appendTo (new StringBuilder ()).toString ();
87+ }
88+
89+ /** The {@code FOR} clause of an index hint. */
90+ public enum Scope {
91+ JOIN ("JOIN" ), ORDER_BY ("ORDER BY" ), GROUP_BY ("GROUP BY" );
92+
93+ private final String keywords ;
94+
95+ Scope (String keywords ) {
96+ this .keywords = keywords ;
97+ }
98+
99+ /** Returns the keywords after {@code FOR}, for example {@code ORDER BY}. */
100+ public String getKeywords () {
101+ return keywords ;
49102 }
50- buffer .append (")" );
51- return buffer .toString ();
52103 }
53104}
0 commit comments