From 2e8fb546dcff4426d0c6bc5a7fed5d1ccdc2e2d6 Mon Sep 17 00:00:00 2001
From: "Sinisa@sinisa.nasamreza.org" <>
Date: Sat, 20 Jul 2002 14:51:52 +0300
Subject: OLAP functionality plus some small bug fixes

---
 sql/sql_olap.cc | 181 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 181 insertions(+)
 create mode 100644 sql/sql_olap.cc

(limited to 'sql/sql_olap.cc')

diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
new file mode 100644
index 00000000000..a18fbd24efd
--- /dev/null
+++ b/sql/sql_olap.cc
@@ -0,0 +1,181 @@
+/* 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*/
+
+#ifdef __GNUC__
+#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_string *constant= new Item_string("ALL",3);
+
+  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=false;
+	  ((Item_field*)new_item)->db_name=iif->db_name;
+	  Item_field *new_one=new Item_field(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;
+
+// a fix for UNION's
+  for (TABLE_LIST *cursor= (TABLE_LIST *)select_lex->table_list.first;
+       cursor;
+       cursor=cursor->next)
+  {
+    if (cursor->do_redirect)
+    {
+      cursor->table= ((TABLE_LIST*) cursor->table)->table;
+      cursor->do_redirect=false;
+    }
+  }
+
+  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((TABLE_LIST *)select_lex->table_list.first) ||
+      setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) ||
+      setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,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;
+}
-- 
cgit v1.2.1