mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-30 04:26:45 +03:00 
			
		
		
		
	"Process NATURAL and USING joins according to SQL:2003".
* Some of the main problems fixed by the patch:
  - in "select *" queries the * expanded correctly according to
    ANSI for arbitrary natural/using joins
  - natural/using joins are correctly transformed into JOIN ... ON
    for any number/nesting of the joins.
  - column references are correctly resolved against natural joins
    of any nesting and combined with arbitrary other joins.
* This patch also contains a fix for name resolution of items
  inside the ON condition of JOIN ... ON - in this case items must
  be resolved only against the JOIN operands. To support such
  'local' name resolution, the patch introduces a stack of
  name resolution contexts used at parse time.
NOTICE:
- This patch is not complete in the sense that
  - there are 2 test cases that still do not pass -
    one in join.test, one in select.test. Both are marked
    with a comment "TODO: WL#2486".
  - it does not include a new test specific for the task
mysql-test/include/ps_query.inc:
  Adjusted according to standard NATURAL/USING join semantics.,
mysql-test/r/bdb.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/derived.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/errors.result:
  The column as a whole cannot be resolved, so different error message.
mysql-test/r/fulltext.result:
  Adjusted according to standard JOIN ... ON semantics =>
  the ON condition can refer only to the join operands.
mysql-test/r/fulltext_order_by.result:
  More detailed error message.
mysql-test/r/innodb.result:
  Adjusted according to standard NATURAL/USING join semantics.
  This test doesn't pass completetly yet!
mysql-test/r/insert_select.result:
  More detailed error message.
mysql-test/r/join.result:
  Adjusted according to standard NATURAL/USING join semantics.
  
  NOTICE: there is one test case that still fails, and it is
  commeted out and marked with WL#2486 in the test file.
mysql-test/r/join_crash.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/join_nested.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/join_outer.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/multi_update.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/null_key.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/order_by.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_2myisam.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_3innodb.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_4heap.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_5merge.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_6bdb.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/ps_7ndb.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/select.result:
  Adjusted according to standard NATURAL/USING join semantics.
  
  NOTICE: there is one failing test case which is commented with
  WL#2486 in the test file.
mysql-test/r/subselect.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/type_ranges.result:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/r/union.result:
  More detailed error message.
mysql-test/t/bdb.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/errors.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/fulltext.test:
  Adjusted according to standard JOIN ... ON semantics =>
  the ON condition can refer only to the join operands.
mysql-test/t/fulltext_order_by.test:
  More detailed error message.
mysql-test/t/innodb.test:
  Adjusted according to standard NATURAL/USING join semantics.
  This test doesn't pass completetly yet!
mysql-test/t/insert_select.test:
  More detailed error message.
mysql-test/t/join.test:
  Adjusted according to standard NATURAL/USING join semantics.
  
  NOTICE: there is one test case that still fails, and it is
  commeted out and marked with WL#2486 in the test file.
mysql-test/t/join_crash.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/join_nested.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/join_outer.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/null_key.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/order_by.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/select.test:
  Adjusted according to standard NATURAL/USING join semantics.
  
  NOTICE: there is one test case that still fails, and it is
  commeted out and marked with WL#2486 in the test file.
mysql-test/t/subselect.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/type_ranges.test:
  Adjusted according to standard NATURAL/USING join semantics.
mysql-test/t/union.test:
  More detailed error message.
sql/item.cc:
  - extra parameter to find_field_in_tables
  - find_field_in_real_table renamed to find_field_in_table
  - fixed comments/typos
sql/item.h:
  - added [first | last]_name_resolution_table to class
    Name_resolution_context
  - commented old code
  - standardized formatting
sql/mysql_priv.h:
  - refactored the find_field_in_XXX procedures,
  - added a new procedure for natural join table references,
  - renamed the find_field_in_XXX procedures to clearer names
sql/sp.cc:
  - pass the top-most list of the FROM clause to setup_tables
  - extra parameter to find_field_in_tables
sql/sql_acl.cc:
  - renamed find_field_in_table => find_field_in_table_ref
  - extra parameter to find_field_in_table_ref
  - commented old code
sql/sql_base.cc:
  This file contains the core of the implementation of the processing
  of NATURAL/USING joins (WL#2486).
  - added many comments to old code
  - refactored the group of find_field_in_XXX procedures, and added a
    new procedure for natural joins. There is one find_field_in_XXX procedure
    per each type of table reference (stored table, merge view, or natural
    join); one meta-procedure that selects the correct one depeneding on the
    table reference; and one procedure that goes over a list of table
    referenes.
  - NATURAL/USING joins are processed through the procedures:
      mark_common_columns, store_natural_using_join_columns,
      store_top_level_join_columns, setup_natural_join_row_types.
    The entry point to processing NATURAL/USING joins is the
    procedure 'setup_natural_join_row_types'.
  - Replaced the specialized Field_iterator_XXX iterators with one
    generic iterator over the fields of a table reference.
  - Simplified 'insert_fields' and 'setup_conds' due to encapsulation of
    the processing of natural joins in a separate set of procedures.
sql/sql_class.h:
  - Commented old code.
sql/sql_delete.cc:
  - Pass the FROM clause to setup_tables.
sql/sql_help.cc:
  - pass the end name resolution table to find_field_in_tables
  - adjust the list of tables for name resolution
sql/sql_insert.cc:
  - Changed the code that saves and restores the current context to
    support the list of tables for name resolution -
    context->first_name_resolution_table, and
    table_list->next_name_resolution_table.
    Needed to support an ugly trick to resolve inserted columns only in
    the first table.
  - Added Name_resolution_context::[first | last]_name_resolution_table.
  - Commented old code
sql/sql_lex.cc:
  - set select_lex.parent_lex correctly
  - set correct state of the current name resolution context
sql/sql_lex.h:
  - Added a stack of name resolution contexts to support local
    contexts for JOIN ... ON conditions.
  - Commented old code.
sql/sql_load.cc:
  - Pass the FROM clause to setup_tables.
sql/sql_olap.cc:
  - Pass the FROM clause to setup_tables.
sql/sql_parse.cc:
  - correctly set SELECT_LEX::parent_lex
  - set the first table of the current name resoltion context
  - added support for NATURAL/USING joins
  - commented old code
sql/sql_select.cc:
  - Pass the FROM clause to setup_tables.
  - Pass the end table to find_field_in_tables
  - Improved comments
sql/sql_show.cc:
  - Set SELECT_LEX::parent_lex.
sql/sql_update.cc:
  - Pass the FROM clause to setup_tables.
sql/sql_yacc.yy:
  - Added support for a stack of name resolution contexts needed to
    implement name resolution for JOIN ... ON. A context is pushed
    for each new JOIN ... ON, and popped afterwards.
  - Added support for NATURAL/USING joins.
sql/table.cc:
  - Added new class Natural_join_column to hide the heterogeneous
    representation of column references for stored tables and for
    views.
  - Added a new list TABLE_LIST::next_name_resolution_table to
    support name resolution with NATURAL/USING joins. Also added
    other members to TABLE_LIST to support NATURAL/USING joins.
  - Added a generic iterator over the fields of table references
    of various types - class Field_iterator_table_ref
sql/table.h:
  - Added new class Natural_join_column to hide the heterogeneous
    representation of column references for stored tables and for
    views.
  - Added a new list TABLE_LIST::next_name_resolution_table to
    support name resolution with NATURAL/USING joins. Also added
    other members to TABLE_LIST to support NATURAL/USING joins.
  - Added a generic iterator over the fields of table references
    of various types - class Field_iterator_table_ref
tests/mysql_client_test.c:
  Adjusted according to standard NATURAL JOIN syntax.
		
	
		
			
				
	
	
		
			187 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			187 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 | |
| 
 | |
|    This program is free software; you can redistribute it and/or modify
 | |
|    it under the terms of the GNU General Public License as published by
 | |
|    the Free Software Foundation; either version 2 of the License, or
 | |
|    (at your option) any later version.
 | |
| 
 | |
|    This program is distributed in the hope that it will be useful,
 | |
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|    GNU General Public License for more details.
 | |
| 
 | |
|    You should have received a copy of the GNU General Public License
 | |
|    along with this program; if not, write to the Free Software
 | |
|    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 | |
| 
 | |
| 
 | |
| /*
 | |
|   OLAP implementation by Sinisa Milivojevic <sinisa@mysql.com>
 | |
|   Inspired by code submitted by Srilakshmi <lakshmi@gdit.iiit.net>
 | |
| 
 | |
|   The ROLLUP code in this file has to be complitely rewritten as it's
 | |
|   not good enough to satisfy the goals of MySQL.
 | |
| 
 | |
|   In 4.1 we will replace this with a working, superior implementation
 | |
|   of ROLLUP.
 | |
| */
 | |
| 
 | |
| #ifdef DISABLED_UNTIL_REWRITTEN_IN_4_1
 | |
| 
 | |
| #ifdef USE_PRAGMA_IMPLEMENTATION
 | |
| #pragma implementation				// gcc: Class implementation
 | |
| #endif
 | |
| 
 | |
| #include "mysql_priv.h"
 | |
| #include "sql_select.h"
 | |
| 
 | |
| 
 | |
| /****************************************************************************
 | |
|   Functions that recursively actually creates new SELECT's
 | |
|   Returns 0 if OK, 1 if error, -1 if error already printed to client
 | |
| ****************************************************************************/
 | |
| 
 | |
| 
 | |
| static int make_new_olap_select(LEX *lex, SELECT_LEX *select_lex, List<Item> new_fields)
 | |
| {
 | |
|   THD	*thd=current_thd;
 | |
|   Item *item, *new_item;
 | |
|   Item_null *constant= new Item_null("ALL");
 | |
| 
 | |
|   SELECT_LEX *new_select = (SELECT_LEX *) thd->memdup((char*) select_lex, sizeof(*select_lex));
 | |
|   if (!new_select)
 | |
|     return 1;
 | |
|   lex->last_selects->next=new_select;
 | |
|   new_select->linkage=OLAP_TYPE;
 | |
|   new_select->olap=NON_EXISTING_ONE;
 | |
|   new_select->group_list.elements=0;
 | |
|   new_select->group_list.first=(byte *)0;
 | |
|   new_select->group_list.next=(byte **)&new_select->group_list.first;
 | |
|   List<Item> privlist;
 | |
|   
 | |
|   List_iterator<Item> list_it(select_lex->item_list);
 | |
|   List_iterator<Item> new_it(new_fields);
 | |
|     
 | |
|   while ((item=list_it++))
 | |
|   {
 | |
|     bool not_found= TRUE;
 | |
|     if (item->type()==Item::FIELD_ITEM)
 | |
|     {
 | |
|       Item_field *iif = (Item_field *)item;
 | |
|       new_it.rewind();
 | |
|       while ((new_item=new_it++))
 | |
|       {
 | |
| 	if (new_item->type()==Item::FIELD_ITEM && 
 | |
| 	    !strcmp(((Item_field*)new_item)->table_name,iif->table_name) &&
 | |
| 	    !strcmp(((Item_field*)new_item)->field_name,iif->field_name))
 | |
| 	{
 | |
| 	  not_found= 0;
 | |
| 	  ((Item_field*)new_item)->db_name=iif->db_name;
 | |
| 	  Item_field *new_one=new Item_field(&select_lex->context,
 | |
|                                              iif->db_name, iif->table_name, iif->field_name);
 | |
| 	  privlist.push_back(new_one);
 | |
| 	  if (add_to_list(new_select->group_list,new_one,1))
 | |
| 	    return 1;
 | |
| 	  break;
 | |
| 	}
 | |
|       }
 | |
|     }
 | |
|     if (not_found)
 | |
|     {
 | |
|       if (item->type() == Item::FIELD_ITEM)
 | |
| 	privlist.push_back(constant);
 | |
|       else
 | |
| 	privlist.push_back((Item*)thd->memdup((char *)item,item->size_of()));
 | |
|     }
 | |
|   }
 | |
|   new_select->item_list=privlist;
 | |
| 
 | |
|   lex->last_selects = new_select;
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /****************************************************************************
 | |
|   Functions that recursively creates combinations of queries for OLAP
 | |
|   Returns 0 if OK, 1 if error, -1 if error already printed to client
 | |
| ****************************************************************************/
 | |
| 
 | |
| static int  olap_combos(List<Item> old_fields, List<Item> new_fields, Item *item, LEX *lex, 
 | |
| 			      SELECT_LEX *select_lex, int position, int selection, int num_fields, 
 | |
| 			      int num_new_fields)
 | |
| {
 | |
|   int sl_return = 0;
 | |
|   if (position == num_new_fields)
 | |
|   {
 | |
|     if (item)
 | |
|       new_fields.push_front(item);
 | |
|     sl_return = make_new_olap_select(lex, select_lex, new_fields);
 | |
|   }
 | |
|   else
 | |
|   {
 | |
|     if (item)
 | |
|       new_fields.push_front(item);
 | |
|     while ((num_fields - num_new_fields >= selection - position) && !sl_return)
 | |
|     {
 | |
|       item = old_fields.pop();
 | |
|       sl_return = olap_combos(old_fields, new_fields, item, lex, select_lex, position+1, ++selection, num_fields, num_new_fields);
 | |
|     }
 | |
|   }
 | |
|   return sl_return;
 | |
| }
 | |
| 
 | |
| 
 | |
| /****************************************************************************
 | |
|   Top level function for converting OLAP clauses to multiple selects
 | |
|   This is also a place where clauses treatment depends on OLAP type 
 | |
|   Returns 0 if OK, 1 if error, -1 if error already printed to client
 | |
| ****************************************************************************/
 | |
| 
 | |
| int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
 | |
| {
 | |
|   List<Item> item_list_copy, new_item_list;
 | |
|   item_list_copy.empty();
 | |
|   new_item_list.empty();
 | |
|   int count=select_lex->group_list.elements;
 | |
|   int sl_return=0;
 | |
| 
 | |
| 
 | |
|   lex->last_selects=select_lex;
 | |
| 
 | |
|   for (ORDER *order=(ORDER *)select_lex->group_list.first ; order ; order=order->next)
 | |
|     item_list_copy.push_back(*(order->item));
 | |
| 
 | |
|   List<Item>	all_fields(select_lex->item_list);
 | |
| 
 | |
| 
 | |
|   if (setup_tables(lex->thd, &select_lex->context, &select_lex->top_join_list,
 | |
|                    (TABLE_LIST *)select_lex->table_list.first
 | |
|                    &select_lex->where, &select_lex->leaf_tables, FALSE) ||
 | |
|       setup_fields(lex->thd, 0, select_lex->item_list, 1, &all_fields,1) ||
 | |
|       setup_fields(lex->thd, 0, item_list_copy, 1, &all_fields, 1))
 | |
|     return -1;
 | |
| 
 | |
|   if (select_lex->olap == CUBE_TYPE)
 | |
|   {
 | |
|     for ( int i=count-1; i>=0 && !sl_return; i--)
 | |
|       sl_return=olap_combos(item_list_copy, new_item_list, (Item *)0, lex, select_lex, 0, 0, count, i);
 | |
|   }
 | |
|   else if (select_lex->olap == ROLLUP_TYPE)
 | |
|   {
 | |
|     for ( int i=count-1; i>=0 && !sl_return; i--)
 | |
|     {
 | |
|       Item *item;
 | |
|       item_list_copy.pop();
 | |
|       List_iterator<Item> it(item_list_copy);
 | |
|       new_item_list.empty();
 | |
|       while ((item = it++))
 | |
| 	new_item_list.push_front(item);
 | |
|       sl_return=make_new_olap_select(lex, select_lex, new_item_list);
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|     sl_return=1; // impossible
 | |
|   return sl_return;
 | |
| }
 | |
| 
 | |
| #endif /* DISABLED_UNTIL_REWRITTEN_IN_4_1 */
 |