diff options
author | unknown <Sinisa@sinisa.nasamreza.org> | 2002-07-20 14:51:52 +0300 |
---|---|---|
committer | unknown <Sinisa@sinisa.nasamreza.org> | 2002-07-20 14:51:52 +0300 |
commit | 907c668729b279c480f028d795b55b761b3aff33 (patch) | |
tree | 59a3e303f4dceb2b56763aee0bf50408cb5c153e /sql/sql_olap.cc | |
parent | 4ce602e619d92c697e4a43f38f582c7fe1a9ad2f (diff) | |
download | mariadb-git-907c668729b279c480f028d795b55b761b3aff33.tar.gz |
OLAP functionality plus some small bug fixes
Diffstat (limited to 'sql/sql_olap.cc')
-rw-r--r-- | sql/sql_olap.cc | 181 |
1 files changed, 181 insertions, 0 deletions
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; +} |