List:Commits« Previous MessageNext Message »
From:Tatiana A. Nurnberg Date:September 22 2008 2:30pm
Subject:bzr commit into mysql-6.0-bka-preview branch (azundris:2648) WL#4421
View as plain text  
#At file:///home/tnurnberg/forest/mysql-6.0-bka-preview/

 2648 Tatiana A. Nurnberg	2008-09-22
      WL#4421 Add hints on join buffer usage for join queries
      
      Adds USE/IGNORE/FORCE JOIN_BUFFER[(<size>[,<level>])]
modified:
  mysql-test/r/group_by.result
  mysql-test/r/join_cache.result
  mysql-test/t/group_by.test
  mysql-test/t/join_cache.test
  sql/lex.h
  sql/sql_lex.h
  sql/sql_select.cc
  sql/sql_select.h
  sql/sql_yacc.yy
  sql/table.h

per-file messages:
  mysql-test/r/group_by.result
    Test neglected to drop a table, confusing follow-up
    tests if they were run in a particular order.
  mysql-test/r/join_cache.result
    adds tests for the JOIN_BUFFER() hints.
  mysql-test/t/group_by.test
    Test neglected to drop a table, confusing follow-up
    tests if they were run in a particular order.
  mysql-test/t/join_cache.test
    adds tests for the JOIN_BUFFER() hints.
  sql/lex.h
    new keyword JOIN_BUFFER
  sql/sql_lex.h
    getters/setters for JOIN_BUFFER-related hints on
    st_select_lex
  sql/sql_select.cc
    If a size-hint is given for JOIN_BUFFER, use it for
    the cache instead of sysvar. Likewise for cache-level
    hint and IGNORE/FORCE/USE.  If we cannot get buffering
    at the requested level for a given table, decrease
    level until we succeed (or reach 0).
  sql/sql_select.h
    Set on cache what level it is (the level we actually
    got, not the one the user asked for).
    Adds helper get_buffer_size() that returns the size 
    requested for this join_buffer (specifically, or the
    sysvar value otherwise).
  sql/sql_yacc.yy
    parse JOIN_BUFFER hints
  sql/table.h
    define JOIN_BUFFER hints. set them on table.
=== modified file 'mysql-test/r/group_by.result'
--- a/mysql-test/r/group_by.result	2008-04-01 15:13:57 +0000
+++ b/mysql-test/r/group_by.result	2008-09-22 12:29:33 +0000
@@ -1624,7 +1624,7 @@ b
 NULL
 1
 2
-DROP TABLE t1;
+DROP TABLE t1,t2;
 CREATE TABLE t1 ( a INT, b INT );
 SELECT b c, (SELECT a FROM t1 WHERE b = c)
 FROM t1;

=== modified file 'mysql-test/r/join_cache.result'
--- a/mysql-test/r/join_cache.result	2008-07-22 04:54:18 +0000
+++ b/mysql-test/r/join_cache.result	2008-09-22 12:29:33 +0000
@@ -796,6 +796,33 @@ join_buffer_size	131072
 show variables like 'join_cache_level';
 Variable_name	Value
 join_cache_level	1
+JOIN_BUFFER(256) must give the same results as join_buffer_size=256
+EXPLAIN
+SELECT City.Name, Country.Name FROM City,Country FORCE JOIN_BUFFER(256)
+WHERE City.Country=Country.Code AND 
+Country.Name LIKE 'L%' AND City.Population > 100000;
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	Country	ALL	NULL	NULL	NULL	NULL	239	Using where
+1	SIMPLE	City	ALL	NULL	NULL	NULL	NULL	4079	Using where; Using join buffer
+SELECT City.Name, Country.Name FROM City,Country FORCE JOIN_BUFFER(256)
+WHERE City.Country=Country.Code AND 
+Country.Name LIKE 'L%' AND City.Population > 100000;
+Name	Name
+Vientiane	Laos
+Riga	Latvia
+Daugavpils	Latvia
+Maseru	Lesotho
+Beirut	Lebanon
+Tripoli	Lebanon
+Monrovia	Liberia
+Tripoli	Libyan Arab Jamahiriya
+Bengasi	Libyan Arab Jamahiriya
+Misrata	Libyan Arab Jamahiriya
+Vilnius	Lithuania
+Kaunas	Lithuania
+Klaipeda	Lithuania
+?iauliai	Lithuania
+Panevezys	Lithuania
 DROP DATABASE world;
 CREATE DATABASE world;
 use world;
@@ -3053,6 +3080,52 @@ PRIMARY KEY  (genreid)
 CREATE INDEX t11_masterclip ON t11( masterclip);
 INSERT INTO t11 VALUES
 (19, "Pop & Dance", 95, 'Y'), (3, "Rock & Alternative", 100, 'Y');
+JOIN_BUFFER(DEFAULT,6) must give the same results as join_cache_level=6
+set join_cache_level=default;
+show variables like 'join_cache_level';
+Variable_name	Value
+join_cache_level	1
+EXPLAIN
+SELECT t1.uniquekey, t1.xml AS affiliateXml,
+t8.name AS artistName, t8.artistid, 
+t11.name AS genreName, t11.genreid, t11.priority AS genrePriority,
+t10.subgenreid, t10.name AS subgenreName,
+t2.name AS metaName, t2.metaid, t2.xml AS metaXml,
+t4.priority + t5.priority + t6.priority AS overallPriority,
+t3.path AS path, t3.mediaid, 
+t4.formatid, t4.name AS formatName, 
+t5.formatclassid, t5.name AS formatclassName, 
+t6.formattypeid, t6.name AS formattypeName 
+FROM t1  FORCE JOIN_BUFFER(DEFAULT,6),
+t2  FORCE JOIN_BUFFER(DEFAULT,6),
+t3  FORCE JOIN_BUFFER(DEFAULT,6),
+t4  FORCE JOIN_BUFFER(DEFAULT,6),
+t5  FORCE JOIN_BUFFER(DEFAULT,6),
+t6  FORCE JOIN_BUFFER(DEFAULT,6),
+t7  FORCE JOIN_BUFFER(DEFAULT,6),
+t8  FORCE JOIN_BUFFER(DEFAULT,6),
+t9  FORCE JOIN_BUFFER(DEFAULT,6),
+t10 FORCE JOIN_BUFFER(DEFAULT,6),
+t11 FORCE JOIN_BUFFER(DEFAULT,6)
+WHERE t7.metaid = t2.metaid AND t7.artistid = t8.artistid AND
+t9.metaid = t2.metaid AND t9.subgenreid = t10.subgenreid AND 
+t10.genreid = t11.genreid AND  t3.metaid = t2.metaid AND
+t3.formatid = t4.formatid AND t4.formatclassid = t5.formatclassid AND
+t4.canaddtocapability =  'Y' AND t5.formattypeid = t6.formattypeid AND
+t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
+t1.metaid = t2.metaid AND t1.affiliateid = '2';
+id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
+1	SIMPLE	t6	system	PRIMARY	NULL	NULL	NULL	1	
+1	SIMPLE	t1	ref	t1_affiliateid,t1_metaid	t1_affiliateid	4	const	1	
+1	SIMPLE	t4	ref	PRIMARY,t4_formatclassid,t4_formats_idx	t4_formats_idx	1	const	1	Using index condition; Using where; Using join buffer
+1	SIMPLE	t5	eq_ref	PRIMARY,t5_formattypeid	PRIMARY	4	test.t4.formatclassid	1	Using where; Using join buffer
+1	SIMPLE	t2	eq_ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using join buffer
+1	SIMPLE	t7	ref	PRIMARY	PRIMARY	4	test.t1.metaid	1	Using index
+1	SIMPLE	t3	ref	t3_metaid,t3_formatid,t3_metaidformatid	t3_metaid	4	test.t1.metaid	2	Using where; Using join buffer
+1	SIMPLE	t8	eq_ref	PRIMARY	PRIMARY	4	test.t7.artistid	1	Using join buffer
+1	SIMPLE	t9	index	PRIMARY,t9_subgenreid,t9_metaid	PRIMARY	8	NULL	2	Using where; Using index; Using join buffer
+1	SIMPLE	t10	eq_ref	PRIMARY,t10_genreid	PRIMARY	4	test.t9.subgenreid	1	Using join buffer
+1	SIMPLE	t11	eq_ref	PRIMARY	PRIMARY	4	test.t10.genreid	1	Using join buffer
 set join_cache_level=6;
 EXPLAIN
 SELECT t1.uniquekey, t1.xml AS affiliateXml,

=== modified file 'mysql-test/t/group_by.test'
--- a/mysql-test/t/group_by.test	2008-04-01 15:13:57 +0000
+++ b/mysql-test/t/group_by.test	2008-09-22 12:29:33 +0000
@@ -1062,7 +1062,7 @@ SELECT a from t2 GROUP BY a;
 EXPLAIN SELECT b from t2 GROUP BY b;
 SELECT b from t2 GROUP BY b;
 
-DROP TABLE t1;
+DROP TABLE t1,t2;
 
 #
 # Bug #31797: error while parsing subqueries -- WHERE is parsed as HAVING

=== modified file 'mysql-test/t/join_cache.test'
--- a/mysql-test/t/join_cache.test	2008-07-06 20:22:50 +0000
+++ b/mysql-test/t/join_cache.test	2008-09-22 12:29:33 +0000
@@ -140,6 +140,22 @@ set join_buffer_size=default;
 show variables like 'join_buffer_size';
 show variables like 'join_cache_level';
 
+
+
+### WL4421 -- Add hints on join buffer usage for join queries
+
+--echo JOIN_BUFFER(256) must give the same results as join_buffer_size=256
+
+EXPLAIN
+SELECT City.Name, Country.Name FROM City,Country FORCE JOIN_BUFFER(256)
+  WHERE City.Country=Country.Code AND 
+        Country.Name LIKE 'L%' AND City.Population > 100000;
+
+SELECT City.Name, Country.Name FROM City,Country FORCE JOIN_BUFFER(256)
+  WHERE City.Country=Country.Code AND 
+        Country.Name LIKE 'L%' AND City.Population > 100000;
+
+
 DROP DATABASE world; 
 
 
@@ -652,6 +668,43 @@ CREATE INDEX t11_masterclip ON t11( mast
 INSERT INTO t11 VALUES
   (19, "Pop & Dance", 95, 'Y'), (3, "Rock & Alternative", 100, 'Y');
 
+
+### WL4421 -- Add hints on join buffer usage for join queries
+
+--echo JOIN_BUFFER(DEFAULT,6) must give the same results as join_cache_level=6
+
+set join_cache_level=default;
+show variables like 'join_cache_level';
+EXPLAIN
+SELECT t1.uniquekey, t1.xml AS affiliateXml,
+       t8.name AS artistName, t8.artistid, 
+       t11.name AS genreName, t11.genreid, t11.priority AS genrePriority,
+       t10.subgenreid, t10.name AS subgenreName,
+       t2.name AS metaName, t2.metaid, t2.xml AS metaXml,
+       t4.priority + t5.priority + t6.priority AS overallPriority,
+       t3.path AS path, t3.mediaid, 
+       t4.formatid, t4.name AS formatName, 
+       t5.formatclassid, t5.name AS formatclassName, 
+       t6.formattypeid, t6.name AS formattypeName 
+FROM t1  FORCE JOIN_BUFFER(DEFAULT,6),
+     t2  FORCE JOIN_BUFFER(DEFAULT,6),
+     t3  FORCE JOIN_BUFFER(DEFAULT,6),
+     t4  FORCE JOIN_BUFFER(DEFAULT,6),
+     t5  FORCE JOIN_BUFFER(DEFAULT,6),
+     t6  FORCE JOIN_BUFFER(DEFAULT,6),
+     t7  FORCE JOIN_BUFFER(DEFAULT,6),
+     t8  FORCE JOIN_BUFFER(DEFAULT,6),
+     t9  FORCE JOIN_BUFFER(DEFAULT,6),
+     t10 FORCE JOIN_BUFFER(DEFAULT,6),
+     t11 FORCE JOIN_BUFFER(DEFAULT,6)
+WHERE t7.metaid = t2.metaid AND t7.artistid = t8.artistid AND
+      t9.metaid = t2.metaid AND t9.subgenreid = t10.subgenreid AND 
+      t10.genreid = t11.genreid AND  t3.metaid = t2.metaid AND
+      t3.formatid = t4.formatid AND t4.formatclassid = t5.formatclassid AND
+      t4.canaddtocapability =  'Y' AND t5.formattypeid = t6.formattypeid AND
+      t6.formattypeid IN (2) AND (t3.formatid IN (31, 8, 76)) AND
+      t1.metaid = t2.metaid AND t1.affiliateid = '2';
+
 set join_cache_level=6;
 
 EXPLAIN

=== modified file 'sql/lex.h'
--- a/sql/lex.h	2008-08-16 05:15:49 +0000
+++ b/sql/lex.h	2008-09-22 12:29:33 +0000
@@ -275,6 +275,7 @@ static SYMBOL symbols[] = {
   { "ITERATE",          SYM(ITERATE_SYM)},
   { "INVOKER",          SYM(INVOKER_SYM)},
   { "JOIN",		SYM(JOIN_SYM)},
+  { "JOIN_BUFFER",	SYM(JOIN_BUFFER_SYM)},
   { "KEY",		SYM(KEY_SYM)},
   { "KEYS",		SYM(KEYS)},
   { "KEY_BLOCK_SIZE",	SYM(KEY_BLOCK_SIZE)},

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2008-09-04 18:18:11 +0000
+++ b/sql/sql_lex.h	2008-09-22 12:29:33 +0000
@@ -820,12 +820,48 @@ public:
 
   void clear_index_hints(void) { index_hints= NULL; }
 
+  void set_join_buffer_hint_size(ulong size)
+  {
+    current_join_buffer_hint_size= max(size, 128 + MALLOC_OVERHEAD);
+    current_join_buffer_hint_type |= JOIN_BUFFER_HINT_SIZE;
+  }
+
+  ulong get_join_buffer_hint_size(void)
+  {
+    return current_join_buffer_hint_size;
+  }
+
+  void set_join_buffer_hint_type(enum join_buffer_hint_type type)
+  {
+    current_join_buffer_hint_type= type;
+  }
+
+  int get_join_buffer_hint_type(void)
+  {
+    return current_join_buffer_hint_type;
+  }
+
+  void set_join_buffer_hint_level(int level)
+  {
+    current_join_buffer_hint_level= level;
+    current_join_buffer_hint_type |= JOIN_BUFFER_HINT_LEVEL;
+  }
+
+  int get_join_buffer_hint_level(void)
+  {
+    return current_join_buffer_hint_level;
+  }
+
 private:  
   /* current index hint kind. used in filling up index_hints */
   enum index_hint_type current_index_hint_type;
   index_clause_map current_index_hint_clause;
   /* a list of USE/FORCE/IGNORE INDEX */
   List<Index_hint> *index_hints;
+
+  ulong current_join_buffer_hint_size;            // ulong, like the global
+  int current_join_buffer_hint_type;
+  int current_join_buffer_hint_level;
 };
 typedef class st_select_lex SELECT_LEX;
 

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	2008-09-04 18:41:27 +0000
+++ b/sql/sql_select.cc	2008-09-22 12:29:33 +0000
@@ -6025,10 +6025,13 @@ best_access_path(JOIN      *join,
       }
       else
       {
-        /* We read the table as many times as join buffer becomes full. */
+        /*
+          We read the table as many times as join buffer becomes full.
+          Heed hint for join-buffer size or, missing that, use sysvar.
+        */
         tmp*= (1.0 + floor((double) cache_record_length(join,idx) *
                            record_count /
-                           (double) thd->variables.join_buff_size));
+                           (double) s->get_buffer_size(thd)));
         /* 
             We don't make full cartesian product between rows in the scanned
            table and existing records because we skip all rows from the
@@ -8361,16 +8364,31 @@ void revise_cache_usage(JOIN_TAB *join_t
 }
 
 
+/**
+  Should we use join-buffering at given level for given table?
+
+  @param    tab             The table to make the decision for
+  @param    join            Join being processed
+  @param    options         Join's options (checking for SELECT_DESCRIBE,
+                            SELECT_NO_JOIN_CACHE)
+  @param    no_jbuf_after   Don't use join buffering after this table
+  @param    cache_level     The desired cache-level
+  @return                   TRUE if can use join-buffer at that level
+
+  @details
+    Check whether we can use join-buffering at the given level.
+    Called from check_join_cache_usage().
+ */
+
 static
-bool check_join_cache_usage(JOIN_TAB *tab,
-                            JOIN *join, ulonglong options,
-                            uint no_jbuf_after)
+bool check_join_cache_at_level(JOIN_TAB *tab,
+                               JOIN *join, ulonglong options,
+                               uint no_jbuf_after, int cache_level)
 {
   uint flags;
   COST_VECT cost;
   uint bufsz= 4096;
   JOIN_CACHE *prev_cache=0;
-  uint cache_level= join->thd->variables.join_cache_level;
   bool force_unlinked_cache= test(cache_level & 1);
   uint i= tab-join->join_tab;
   ha_rows rows;
@@ -8441,6 +8459,74 @@ no_join_cache:
   return FALSE;          
 }
 
+
+/**
+  Find most appropriate cache-level for joining given table.
+
+  @param    tab             The table to make the decision for
+  @param    join            Join being processed
+  @param    options         Join's options (checking for SELECT_DESCRIBE,
+                            SELECT_NO_JOIN_CACHE)
+  @param    no_jbuf_after   Don't use join buffering after this table
+  @return                   TRUE if we are to use join-buffer
+
+  @details
+    Apply all join-buffer hints except size-hints.
+    Then check whether we can use join-buffering at all, starting at the
+    level selected by the user and descending until we get a positive.
+    Called from make_join_readinfo().
+ */
+
+static
+bool check_join_cache_usage(JOIN_TAB *tab,
+                            JOIN *join, ulonglong options,
+                            uint no_jbuf_after)
+{
+  uint cache_level;
+  uint i= tab-join->join_tab;
+  uint hint= tab->table->pos_in_table_list->join_buffer_hint_type;
+
+  if (hint)
+  {
+    /*
+       join_buffer_hint_type can be one of FORCE/USE/IGNORE.
+       Since FORCE and USE are functionally equivalent for the time
+       being, we just need to bail here on IGNORE.
+    */
+    if (hint & JOIN_BUFFER_HINT_IGNORE)
+      return FALSE;
+
+    /*
+      If the user gave a level-hint, we'll start with that; otherwise,
+      we'll start with the maximum.
+    */
+    if (hint & JOIN_BUFFER_HINT_LEVEL)
+      cache_level= tab->table->pos_in_table_list->join_buffer_hint_level;
+    else
+      cache_level= 8;
+  }
+  else
+    /*
+       No hints given, use sysvar join-cache level.
+    */
+    cache_level= join->thd->variables.join_cache_level;
+
+  while (cache_level > 0)
+  {
+    if (check_join_cache_at_level(tab, join, options,
+                                  no_jbuf_after, cache_level))
+    {
+      if (tab->cache)                           // NULL for SELECT_DESCRIBE
+        tab->cache->cache_level= cache_level;
+      return TRUE;
+    }
+    cache_level--;
+  }
+
+  return FALSE;
+}
+
+
 /*
   Plan refinement stage: do various set ups for the executioner
 
@@ -17303,7 +17389,9 @@ void JOIN_CACHE::set_constants()
   uint len= length + fields*sizeof(uint)+blobs*sizeof(uchar *) +
             (prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
             sizeof(ulong);
-  buff_size= max(join->thd->variables.join_buff_size, 2*len);
+
+  buff_size= max(join_tab->get_buffer_size(join->thd), 2*len);
+
   size_of_rec_ofs= offset_size(buff_size);
   size_of_rec_len= blobs ? size_of_rec_ofs : offset_size(len); 
   size_of_fld_ofs= size_of_rec_len;

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	2008-09-04 18:18:11 +0000
+++ b/sql/sql_select.h	2008-09-22 12:29:33 +0000
@@ -329,6 +329,16 @@ typedef struct st_join_table {
       return first_inner;
     return first_sj_inner_tab; 
   }
+  /*
+    If a size-hint was given, return that, otherwise use the sysvar.
+  */
+  ulong get_buffer_size(THD *thd)
+  {
+    return (table->pos_in_table_list->join_buffer_hint_type &
+            JOIN_BUFFER_HINT_SIZE)
+           ?table->pos_in_table_list->join_buffer_hint_size
+           :thd->variables.join_buff_size;
+  }
 } JOIN_TAB;
 
 /* 
@@ -661,6 +671,9 @@ public:
   /* Table to be joined with the partial join records from the cache */ 
   JOIN_TAB *join_tab;
 
+  /* This identifies the level we got rather than the one we asked for. */
+  int cache_level;
+
   /* Pointer to the previous join cache if there is any */
   JOIN_CACHE *prev_cache;
   /* Pointer to the next join cache if there is any */

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2008-09-04 18:18:11 +0000
+++ b/sql/sql_yacc.yy	2008-09-22 12:29:33 +0000
@@ -1194,6 +1194,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  YEAR_SYM                      /* SQL-2003-R */
 %token  ZEROFILL
 %token  BACKUP_TEST_SYM
+%token  JOIN_BUFFER_SYM               /* WL4421 */
 
 %left   JOIN_SYM INNER_SYM STRAIGHT_JOIN CROSS LEFT RIGHT
 /* A dummy token to force the priority of table_ref production in a join. */
@@ -8775,6 +8776,7 @@ table_factor:
           {
             SELECT_LEX *sel= Select;
             sel->table_join_options= 0;
+            sel->set_join_buffer_hint_type(JOIN_BUFFER_HINT_DEFAULT);
           }
           table_ident opt_table_alias opt_key_definition
           {
@@ -8783,6 +8785,9 @@ table_factor:
                                                 Lex->lock_option,
                                                 Select->pop_index_hints())))
               MYSQL_YYABORT;
+            $$->join_buffer_hint_size = Select->get_join_buffer_hint_size();
+            $$->join_buffer_hint_level= Select->get_join_buffer_hint_level();
+            $$->join_buffer_hint_type = Select->get_join_buffer_hint_type();
             Select->add_joined_table($$);
           }
         | select_derived_init get_select_lex select_derived2
@@ -9006,6 +9011,32 @@ opt_outer:
         | OUTER {}
         ;
 
+join_buffer_hint_size:
+          size_number
+          { Select->set_join_buffer_hint_size($1); }
+        ;
+
+join_buffer_hint_options:
+          join_buffer_hint_size
+        | join_buffer_hint_size ',' ulong_num
+          { Select->set_join_buffer_hint_level($3); }
+        | DEFAULT ',' ulong_num
+          { Select->set_join_buffer_hint_level($3); }
+        | DEFAULT
+        ;
+
+join_buffer_hint_type:
+          FORCE_SYM   { Select->set_join_buffer_hint_type(JOIN_BUFFER_HINT_FORCE); }
+        | USE_SYM     { Select->set_join_buffer_hint_type(JOIN_BUFFER_HINT_USE); }
+        ;
+
+join_buffer_hint_definition:
+          join_buffer_hint_type JOIN_BUFFER_SYM
+        | join_buffer_hint_type JOIN_BUFFER_SYM '(' join_buffer_hint_options ')'
+        | IGNORE_SYM JOIN_BUFFER_SYM
+          { Select->set_join_buffer_hint_type(JOIN_BUFFER_HINT_IGNORE); }
+        ;
+
 index_hint_clause:
           /* empty */
           {
@@ -9023,7 +9054,8 @@ index_hint_type:
         ;
 
 index_hint_definition:
-          index_hint_type key_or_index index_hint_clause
+          join_buffer_hint_definition
+        | index_hint_type key_or_index index_hint_clause
           {
             Select->set_index_hint_type($1, $3);
           }

=== modified file 'sql/table.h'
--- a/sql/table.h	2008-08-18 05:43:50 +0000
+++ b/sql/table.h	2008-09-22 12:29:33 +0000
@@ -563,6 +563,16 @@ enum index_hint_type
   INDEX_HINT_FORCE
 };
 
+enum join_buffer_hint_type
+{
+  JOIN_BUFFER_HINT_DEFAULT=0,
+  JOIN_BUFFER_HINT_IGNORE=1,
+  JOIN_BUFFER_HINT_USE=2,
+  JOIN_BUFFER_HINT_FORCE=4,
+  JOIN_BUFFER_HINT_SIZE=32,
+  JOIN_BUFFER_HINT_LEVEL=64
+};
+
 struct st_table {
   st_table() {}                               /* Remove gcc warning */
 
@@ -1126,6 +1136,12 @@ struct TABLE_LIST
   List<Index_hint> *index_hints;
   TABLE        *table;                          /* opened table */
   uint          table_id; /* table id (from binlog) for opened table */
+
+  /* JOIN_BUFFER hints (USE/IGNORE/FORCE, SIZE) */
+  ulong join_buffer_hint_size;
+  int join_buffer_hint_level;
+  int join_buffer_hint_type;
+
   /*
     select_result for derived table to pass it from table creation to table
     filling procedure

Thread
bzr commit into mysql-6.0-bka-preview branch (azundris:2648) WL#4421Tatiana A. Nurnberg22 Sep