sql_union.cc 14.8 KB
Newer Older
1
/* Copyright (C) 2000-2003 MySQL AB
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

   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 */


/*
  UNION  of select's
  UNION's  were introduced by Monty and Sinisa <sinisa@mysql.com>
*/


#include "mysql_priv.h"
#include "sql_select.h"

27
int mysql_union(THD *thd, LEX *lex, select_result *result,
28
		SELECT_LEX_UNIT *unit)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
29 30 31
{
  DBUG_ENTER("mysql_union");
  int res= 0;
32
  if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK)))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
33 34 35 36 37 38 39 40 41 42 43
    res= unit->exec();
  res|= unit->cleanup();
  DBUG_RETURN(res);
}


/***************************************************************************
** store records in temporary table for UNION
***************************************************************************/

select_union::select_union(TABLE *table_par)
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
44
  :table(table_par), not_describe(0)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
{
  bzero((char*) &info,sizeof(info));
  /*
    We can always use DUP_IGNORE because the temporary table will only
    contain a unique key if we are using not using UNION ALL
  */
  info.handle_duplicates= DUP_IGNORE;
}

select_union::~select_union()
{
}


int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
  unit= u;
  return 0;
}

65

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
66 67 68 69 70 71 72
bool select_union::send_data(List<Item> &values)
{
  if (unit->offset_limit_cnt)
  {						// using limit offset,count
    unit->offset_limit_cnt--;
    return 0;
  }
73
  fill_record(table->field, values, 1);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
74
  if (thd->net.report_error || write_record(table,&info))
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
75
  {
76 77 78
    if (thd->net.last_errno == ER_RECORD_FILE_FULL)
    {
      thd->clear_error(); // do not report user about table overflow
79
      if (create_myisam_from_heap(thd, table, &tmp_table_param,
monty@mashka.mysql.fi's avatar
monty@mashka.mysql.fi committed
80
				  info.last_errno, 1))
81 82 83
	return 1;
    }
    else
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
84 85 86 87 88
      return 1;
  }
  return 0;
}

89

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
90 91 92 93
bool select_union::send_eof()
{
  return 0;
}
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
94

95

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
96
bool select_union::flush()
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
97
{
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
98 99 100 101
  int error;
  if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
  {
    table->file->print_error(error,MYF(0));
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
102
    ::send_error(thd);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
103 104 105 106 107
    return 1;
  }
  return 0;
}

108

109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
/*
  initialization procedures before fake_select_lex preparation()

  SYNOPSIS
    st_select_lex_unit::init_prepare_fake_select_lex()
    thd		- thread handler

  RETURN
    options of SELECT
*/

ulong
st_select_lex_unit::init_prepare_fake_select_lex(THD *thd) 
{
  ulong options_tmp= thd->options;
  thd->lex->current_select= fake_select_lex;
  offset_limit_cnt= global_parameters->offset_limit;
  select_limit_cnt= global_parameters->select_limit +
    global_parameters->offset_limit;

  if (select_limit_cnt < global_parameters->select_limit)
    select_limit_cnt= HA_POS_ERROR;		// no limit
  if (select_limit_cnt == HA_POS_ERROR)
    options_tmp&= ~OPTION_FOUND_ROWS;
  else if (found_rows_for_union && !thd->lex->describe)
    options_tmp|= OPTION_FOUND_ROWS;
  fake_select_lex->ftfunc_list_alloc.empty();
  fake_select_lex->ftfunc_list= &fake_select_lex->ftfunc_list_alloc;
  fake_select_lex->table_list.link_in_list((byte *)&result_table_list,
					   (byte **)
					   &result_table_list.next);
  return options_tmp;
}


144 145
int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
				ulong additional_options)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
146
{
147
  SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
148 149
  SELECT_LEX *sl, *first_select;
  select_result *tmp_result;
150 151
  DBUG_ENTER("st_select_lex_unit::prepare");

152 153 154 155 156 157
  /*
    result object should be reassigned even if preparing already done for
    max/min subquery (ALL/ANY optimization)
  */
  result= sel_result;

158 159 160
  if (prepared)
    DBUG_RETURN(0);
  prepared= 1;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
161
  res= 0;
162
  
163
  thd_arg->lex->current_select= sl= first_select= first_select_in_union();
164 165
  found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;

166
  /* Global option */
167 168

  if (first_select->next_select())
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
169
  {
170 171 172
    if (!(tmp_result= union_result= new select_union(0)))
      goto err;
    union_result->not_describe= 1;
173
    union_result->tmp_table_param.init();
174 175 176
  }
  else
  {
177 178 179
    tmp_result= sel_result;
    // single select should be processed like select in p[arantses
    first_select->braces= 1;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
180
  }
181

182
  for (;sl; sl= sl->next_select())
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
183
  {
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
184
    sl->options|=  SELECT_NO_UNLOCK;
185
    JOIN *join= new JOIN(thd_arg, sl->item_list, 
186
			 sl->options | thd_arg->options | additional_options,
187
			 tmp_result);
monty@mysql.com's avatar
monty@mysql.com committed
188 189 190
    if (!join)
      goto err;

191
    thd_arg->lex->current_select= sl;
192 193 194 195
    offset_limit_cnt= sl->offset_limit;
    select_limit_cnt= sl->select_limit+sl->offset_limit;
    if (select_limit_cnt < sl->select_limit)
      select_limit_cnt= HA_POS_ERROR;		// no limit
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
196
    if (select_limit_cnt == HA_POS_ERROR || sl->braces)
197 198 199 200 201 202 203 204 205 206 207 208
      sl->options&= ~OPTION_FOUND_ROWS;
    
    res= join->prepare(&sl->ref_pointer_array,
		       (TABLE_LIST*) sl->table_list.first, sl->with_wild,
		       sl->where,
		       ((sl->braces) ? sl->order_list.elements : 0) +
		       sl->group_list.elements,
		       (sl->braces) ? 
		       (ORDER *)sl->order_list.first : (ORDER *) 0,
		       (ORDER*) sl->group_list.first,
		       sl->having,
		       (ORDER*) NULL,
209
		       sl, this);
210
    if (res || thd_arg->is_fatal_error)
211
      goto err;
212 213 214 215
    if (sl == first_select)
    {
      types.empty();
      List_iterator_fast<Item> it(sl->item_list);
216 217
      Item *item_tmp;
      while ((item_tmp= it++))
218
      {
monty@mysql.com's avatar
monty@mysql.com committed
219
	/* Error's in 'new' will be detected after loop */
220
	types.push_back(new Item_type_holder(thd_arg, item_tmp));
221 222
      }

223
      if (thd_arg->is_fatal_error)
224 225 226 227 228 229 230 231 232 233 234 235
	goto err; // out of memory
    }
    else
    {
      if (types.elements != sl->item_list.elements)
      {
	my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
		   ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
	goto err;
      }
      List_iterator_fast<Item> it(sl->item_list);
      List_iterator_fast<Item> tp(types);	
236 237
      Item *type, *item_tmp;
      while ((type= tp++, item_tmp= it++))
238
      {
239
	if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
igor@rurik.mysql.com's avatar
igor@rurik.mysql.com committed
240
	  DBUG_RETURN(-1);
241 242
      }
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
243
  }
244

245
  // it is not single select
246
  if (first_select->next_select())
247
  {
248 249 250
    union_result->tmp_table_param.field_count= types.elements;
    if (!(table= create_tmp_table(thd_arg,
				  &union_result->tmp_table_param, types,
251
				  (ORDER*) 0, (bool) union_distinct, 1, 
252
				  (first_select_in_union()->options |
253
				   thd_arg->options |
254 255 256 257 258 259 260 261 262 263
				   TMP_TABLE_ALL_COLUMNS),
				  HA_POS_ERROR, (char*) "")))
      goto err;
    table->file->extra(HA_EXTRA_WRITE_CACHE);
    table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
    bzero((char*) &result_table_list, sizeof(result_table_list));
    result_table_list.db= (char*) "";
    result_table_list.real_name= result_table_list.alias= (char*) "union";
    result_table_list.table= table;
    union_result->set_table(table);
264

265
    thd_arg->lex->current_select= lex_select_save;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
266 267
    if (!item_list.elements)
    {
268 269 270 271
      Statement *stmt= thd->current_statement;
      Statement backup;
      if (stmt)
	thd->set_n_backup_item_arena(stmt, &backup);
272 273 274
      Field **field;
      for (field= table->field; *field; field++)
      {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
275 276
	Item_field *item= new Item_field(*field);
	if (!item || item_list.push_back(item))
277 278 279
	{
	  if (stmt)
	    thd->restore_backup_item_arena(stmt, &backup);
280
	  DBUG_RETURN(-1);
281
	}
282
      }
283
      if (stmt)
284
      {
285
	thd->restore_backup_item_arena(stmt, &backup);
286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307

	/* prepare fake select to initialize it correctly */
	ulong options_tmp= init_prepare_fake_select_lex(thd);
	if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
					      result)))
	{
	  fake_select_lex->table_list.empty();
	  DBUG_RETURN(-1);
	}
	fake_select_lex->item_list= item_list;

	thd_arg->lex->current_select= fake_select_lex;
	res= fake_select_lex->join->
	  prepare(&fake_select_lex->ref_pointer_array,
		  (TABLE_LIST*) fake_select_lex->table_list.first,
		  0, 0,
		  fake_select_lex->order_list.elements,
		  (ORDER*) fake_select_lex->order_list.first,
		  (ORDER*) NULL, NULL, (ORDER*) NULL,
		  fake_select_lex, this);
	fake_select_lex->table_list.empty();
      }
308 309
    }
  }
310 311 312
  else
    first_select->braces= 0; // remove our changes

313
  thd_arg->lex->current_select= lex_select_save;
314

315
  DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0);
316

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
317
err:
318
  thd_arg->lex->current_select= lex_select_save;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
319
  DBUG_RETURN(-1);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
320 321
}

322

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
323 324
int st_select_lex_unit::exec()
{
325
  SELECT_LEX *lex_select_save= thd->lex->current_select;
326
  SELECT_LEX *select_cursor=first_select_in_union();
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
327
  ulonglong add_rows=0;
328 329
  DBUG_ENTER("st_select_lex_unit::exec");

330
  if (executed && !uncacheable)
331 332 333
    DBUG_RETURN(0);
  executed= 1;
  
334
  if (uncacheable || !item || !item->assigned())
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
335 336
  {
    if (optimized && item && item->assigned())
337
    {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
338
      item->assigned(0); // We will reinit & rexecute unit
339
      item->reset();
340 341
      table->file->delete_all_rows();
    }
342 343
    if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL))
      DBUG_RETURN(1);  // For sub-selects
344
    for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
345
    {
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
346
      ha_rows records_at_start= 0;
347
      thd->lex->current_select= sl;
348

349
      if (optimized)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
350
	res= sl->join->reinit();
351 352
      else
      {
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
	if (sl != global_parameters)
	{
	  offset_limit_cnt= sl->offset_limit;
	  select_limit_cnt= sl->select_limit+sl->offset_limit;
	}
	else
	{
	  offset_limit_cnt= 0;
	  /*
	    We can't use LIMIT at this stage if we are using ORDER BY for the
	    whole query
	  */
	  if (sl->order_list.first)
	    select_limit_cnt= HA_POS_ERROR;
	  else
	    select_limit_cnt= sl->select_limit+sl->offset_limit;
	}
370 371
	if (select_limit_cnt < sl->select_limit)
	  select_limit_cnt= HA_POS_ERROR;		// no limit
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
372 373 374 375 376

	/*
	  When using braces, SQL_CALC_FOUND_ROWS affects the whole query.
	  We don't calculate found_rows() per union part
	*/
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
377
	if (select_limit_cnt == HA_POS_ERROR || sl->braces)
378
	  sl->options&= ~OPTION_FOUND_ROWS;
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
379
	else 
380
	{
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
381 382 383 384 385
	  /*
	    We are doing an union without braces.  In this case
	    SQL_CALC_FOUND_ROWS should be done on all sub parts
	  */
	  sl->options|= found_rows_for_union;
386
	}
387
	sl->join->select_options=sl->options;
388 389
	res= sl->join->optimize();
      }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
390 391
      if (!res)
      {
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
392
	records_at_start= table->file->records;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
393
	sl->join->exec();
394
        if (sl == union_distinct)
395 396 397 398 399
	{
	  if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
	    DBUG_RETURN(1);
	  table->no_keyread=1;
	}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
400
	res= sl->join->error;
401
	offset_limit_cnt= sl->offset_limit;
402 403
	if (!res && union_result->flush())
	{
404
	  thd->lex->current_select= lex_select_save;
405 406
	  DBUG_RETURN(1);
	}
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
407
      }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
408
      if (res)
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
409
      {
410
	thd->lex->current_select= lex_select_save;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
411
	DBUG_RETURN(res);
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
412
      }
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
413 414
      /* Needed for the following test and for records_at_start in next loop */
      table->file->info(HA_STATUS_VARIABLE);
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
415 416 417
      if (found_rows_for_union & sl->options)
      {
	/*
monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
418 419
	  This is a union without braces. Remember the number of rows that
	  could also have been part of the result set.
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
420 421 422
	  We get this from the difference of between total number of possible
	  rows and actual rows added to the temporary table.
	*/
423
	add_rows+= (ulonglong) (thd->limit_found_rows - (ulonglong)
424
			      ((table->file->records -  records_at_start)));
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
425
      }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
426
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
427
  }
428
  optimized= 1;
429 430

  /* Send result to 'result' */
431
  res= -1;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
432
  {
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
433 434
    List<Item_func_match> empty_list;
    empty_list.empty();
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
435

monty@narttu.mysql.fi's avatar
monty@narttu.mysql.fi committed
436
    if (!thd->is_fatal_error)				// Check if EOM
437
    {
438
      ulong options_tmp= init_prepare_fake_select_lex(thd);
439 440 441 442
      JOIN *join= fake_select_lex->join;
      if (!join)
      {
	/*
monty@mysql.com's avatar
monty@mysql.com committed
443
	  allocate JOIN for fake select only once (prevent
444 445
	  mysql_select automatic allocation)
	*/
monty@mysql.com's avatar
monty@mysql.com committed
446 447
	if (!(fake_select_lex->join= new JOIN(thd, item_list, thd->options,
					      result)))
448 449
	{
	  fake_select_lex->table_list.empty();
monty@mysql.com's avatar
monty@mysql.com committed
450
	  DBUG_RETURN(-1);
451
	}
monty@mysql.com's avatar
monty@mysql.com committed
452

453 454 455 456 457
	/*
	  Fake st_select_lex should have item list for correctref_array
	  allocation.
	*/
	fake_select_lex->item_list= item_list;
458 459 460 461 462 463 464 465 466 467 468
      }
      else
      {
	JOIN_TAB *tab,*end;
	for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
	{
	  delete tab->select;
	  delete tab->quick;
	}
	join->init(thd, item_list, thd->options, result);
      }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
469 470
      res= mysql_select(thd, &fake_select_lex->ref_pointer_array,
			&result_table_list,
471 472
			0, item_list, NULL,
			global_parameters->order_list.elements,
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
473
			(ORDER*)global_parameters->order_list.first,
474
			(ORDER*) NULL, NULL, (ORDER*) NULL,
475
			options_tmp | SELECT_NO_UNLOCK,
476
			result, this, fake_select_lex);
477 478

      fake_select_lex->table_list.empty();
Sinisa@sinisa.nasamreza.org's avatar
Sinisa@sinisa.nasamreza.org committed
479 480
      if (!res)
	thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
481 482 483 484
      /*
	Mark for slow query log if any of the union parts didn't use
	indexes efficiently
      */
485
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
486
  }
487
  thd->lex->current_select= lex_select_save;
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
488 489 490
  DBUG_RETURN(res);
}

491

bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
492
int st_select_lex_unit::cleanup()
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
493
{
494
  int error= 0;
495
  DBUG_ENTER("st_select_lex_unit::cleanup");
496

497 498 499 500
  if (cleaned)
  {
    DBUG_RETURN(0);
  }
501
  cleaned= 1;
502

503 504 505
  if (union_result)
  {
    delete union_result;
506
    union_result=0; // Safety
507 508
    if (table)
      free_tmp_table(thd, table);
509 510
    table= 0; // Safety
  }
511
  JOIN *join;
512 513
  SELECT_LEX *sl= first_select_in_union();
  for (; sl; sl= sl->next_select())
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
514
  {
515 516
    if ((join= sl->join))
    {
517
      error|= sl->join->cleanup();
518 519
      delete join;
    }
520 521 522 523 524 525 526 527 528 529
    else
    {
      // it can be DO/SET with subqueries
      for (SELECT_LEX_UNIT *lex_unit= sl->first_inner_unit();
	   lex_unit != 0;
	   lex_unit= lex_unit->next_unit())
      {
	error|= lex_unit->cleanup();
      }
    }
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
530
  }
531 532 533 534 535 536 537
  if (fake_select_lex && (join= fake_select_lex->join))
  {
    join->tables_list= 0;
    join->tables= 0;
    error|= join->cleanup();
    delete join;
  }
538
  DBUG_RETURN(error);
monty@tik.mysql.fi's avatar
monty@tik.mysql.fi committed
539
}
540 541 542 543 544


void st_select_lex_unit::reinit_exec_mechanism()
{
  prepared= optimized= executed= 0;
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
545
#ifndef DBUG_OFF
546
  if (first_select()->next_select())
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
547
  {
548 549 550 551 552 553 554 555 556 557 558
    List_iterator_fast<Item> it(item_list);
    Item *field;
    while ((field= it++))
    {
      /*
	we can't cleanup here, because it broke link to temporary table field,
	but have to drop fixed flag to allow next fix_field of this field
	during re-executing
      */
      field->fixed= 0;
    }
bell@sanja.is.com.ua's avatar
bell@sanja.is.com.ua committed
559 560
  }
#endif
561
}
562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590


/*
  change select_result object of unit

  SYNOPSIS
    st_select_lex_unit::change_result()
    result	new select_result object
    old_result	old select_result object

  RETURN
    0 - OK
    -1 - error
*/

int st_select_lex_unit::change_result(select_subselect *result,
				      select_subselect *old_result)
{
  int res= 0;
  for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
  {
    if (sl->join && sl->join->result == old_result)
      if ((res= sl->join->change_result(result)))
	return (res);
  }
  if (fake_select_lex && fake_select_lex->join)
    res= fake_select_lex->join->change_result(result);
  return (res);
}