2002-05-12 23:46:42 +03:00
|
|
|
/* Copyright (C) 2000 MySQL 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 */
|
|
|
|
|
2004-07-04 08:46:28 +03:00
|
|
|
/*
|
2002-05-12 23:46:42 +03:00
|
|
|
subselect Item
|
|
|
|
|
|
|
|
SUBSELECT TODO:
|
|
|
|
- add function from mysql_select that use JOIN* as parameter to JOIN methods
|
|
|
|
(sql_select.h/sql_select.cc)
|
|
|
|
*/
|
|
|
|
|
2005-05-26 12:09:14 +02:00
|
|
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
2002-05-12 23:46:42 +03:00
|
|
|
#pragma implementation // gcc: Class implementation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "mysql_priv.h"
|
|
|
|
#include "sql_select.h"
|
|
|
|
|
2002-12-28 01:01:05 +02:00
|
|
|
inline Item * and_items(Item* cond, Item *item)
|
|
|
|
{
|
|
|
|
return (cond? (new Item_cond_and(cond, item)) : item);
|
|
|
|
}
|
|
|
|
|
2002-10-08 23:49:59 +03:00
|
|
|
Item_subselect::Item_subselect():
|
2004-02-08 20:14:13 +02:00
|
|
|
Item_result_field(), value_assigned(0), thd(0), substitution(0),
|
|
|
|
engine(0), old_engine(0), used_tables_cache(0), have_to_be_excluded(0),
|
|
|
|
const_item_cache(1), engine_changed(0), changed(0)
|
2002-05-12 23:46:42 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-10-08 23:49:59 +03:00
|
|
|
/*
|
2004-07-04 08:46:28 +03:00
|
|
|
item value is NULL if select_subselect not changed this value
|
2002-10-08 23:49:59 +03:00
|
|
|
(i.e. some rows will be found returned)
|
|
|
|
*/
|
|
|
|
null_value= 1;
|
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-10-02 22:19:41 +03:00
|
|
|
void Item_subselect::init(st_select_lex *select_lex,
|
2002-11-07 23:45:19 +02:00
|
|
|
select_subselect *result)
|
2002-10-08 23:49:59 +03:00
|
|
|
{
|
|
|
|
|
|
|
|
DBUG_ENTER("Item_subselect::init");
|
2005-02-05 16:05:46 +02:00
|
|
|
DBUG_PRINT("enter", ("select_lex: 0x%x", (ulong) select_lex));
|
2004-02-08 20:14:13 +02:00
|
|
|
unit= select_lex->master_unit();
|
2002-09-03 09:50:36 +03:00
|
|
|
|
2004-05-07 23:06:11 +03:00
|
|
|
if (unit->item)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Item can be changed in JOIN::prepare while engine in JOIN::optimize
|
|
|
|
=> we do not copy old_engine here
|
|
|
|
*/
|
|
|
|
engine= unit->item->engine;
|
2004-08-13 10:01:30 +03:00
|
|
|
parsing_place= unit->item->parsing_place;
|
2004-05-07 23:06:11 +03:00
|
|
|
unit->item->engine= 0;
|
|
|
|
unit->item= this;
|
2004-10-20 04:04:37 +03:00
|
|
|
engine->change_result(this, result);
|
2004-05-07 23:06:11 +03:00
|
|
|
}
|
2002-09-03 09:50:36 +03:00
|
|
|
else
|
2004-05-07 23:06:11 +03:00
|
|
|
{
|
2004-08-23 22:31:01 +03:00
|
|
|
SELECT_LEX *outer_select= unit->outer_select();
|
|
|
|
/*
|
|
|
|
do not take into account expression inside aggregate functions because
|
|
|
|
they can access original table fields
|
|
|
|
*/
|
|
|
|
parsing_place= (outer_select->in_sum_expr ?
|
|
|
|
NO_MATTER :
|
|
|
|
outer_select->parsing_place);
|
2004-05-07 23:06:11 +03:00
|
|
|
if (select_lex->next_select())
|
|
|
|
engine= new subselect_union_engine(unit, result, this);
|
|
|
|
else
|
|
|
|
engine= new subselect_single_select_engine(select_lex, result, this);
|
|
|
|
}
|
2004-06-09 23:32:20 +03:00
|
|
|
{
|
|
|
|
SELECT_LEX *upper= unit->outer_select();
|
2004-08-13 10:01:30 +03:00
|
|
|
if (upper->parsing_place == IN_HAVING)
|
2004-06-09 23:32:20 +03:00
|
|
|
upper->subquery_in_having= 1;
|
|
|
|
}
|
2002-05-12 23:46:42 +03:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2003-12-30 14:08:19 +04:00
|
|
|
void Item_subselect::cleanup()
|
|
|
|
{
|
2004-02-08 20:14:13 +02:00
|
|
|
DBUG_ENTER("Item_subselect::cleanup");
|
2003-12-30 14:08:19 +04:00
|
|
|
Item_result_field::cleanup();
|
2004-02-08 20:14:13 +02:00
|
|
|
if (old_engine)
|
|
|
|
{
|
2004-05-07 23:06:11 +03:00
|
|
|
if (engine)
|
|
|
|
engine->cleanup();
|
2004-02-08 20:14:13 +02:00
|
|
|
engine= old_engine;
|
|
|
|
old_engine= 0;
|
|
|
|
}
|
2004-05-07 23:06:11 +03:00
|
|
|
if (engine)
|
|
|
|
engine->cleanup();
|
2004-02-08 20:14:13 +02:00
|
|
|
reset();
|
|
|
|
value_assigned= 0;
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Item_singlerow_subselect::cleanup()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_singlerow_subselect::cleanup");
|
|
|
|
value= 0; row= 0;
|
|
|
|
Item_subselect::cleanup();
|
|
|
|
DBUG_VOID_RETURN;
|
2003-12-30 14:08:19 +04:00
|
|
|
}
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2002-09-03 09:50:36 +03:00
|
|
|
Item_subselect::~Item_subselect()
|
|
|
|
{
|
2003-10-27 01:01:27 +02:00
|
|
|
delete engine;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2004-07-04 08:46:28 +03:00
|
|
|
Item_subselect::select_transformer(JOIN *join)
|
2002-10-27 23:27:00 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_subselect::select_transformer");
|
2003-08-28 13:21:30 +03:00
|
|
|
DBUG_RETURN(RES_OK);
|
2002-10-27 23:27:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-01 07:05:42 +03:00
|
|
|
bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
|
2002-05-12 23:46:42 +03:00
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
char const *save_where= thd_param->where;
|
Table definition cache, part 2
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
Other noteworthy changes:
- In TABLE_SHARE the most common strings are now LEX_STRING's
- Better error message when table is not found
- Variable table_cache is now renamed 'table_open_cache'
- New variable 'table_definition_cache' that is the number of table defintions that will be cached
- strxnmov() calls are now fixed to avoid overflows
- strxnmov() will now always add one end \0 to result
- engine objects are now created with a TABLE_SHARE object instead of a TABLE object.
- After creating a field object one must call field->init(table) before using it
- For a busy system this change will give you:
- Less memory usage for table object
- Faster opening of tables (if it's has been in use or is in table definition cache)
- Allow you to cache many table definitions objects
- Faster drop of table
mysql-test/mysql-test-run.sh:
Fixed some problems with --gdb option
Test both with socket and tcp/ip port that all old servers are killed
mysql-test/r/flush_table.result:
More tests with lock table with 2 threads + flush table
mysql-test/r/information_schema.result:
Removed old (now wrong) result
mysql-test/r/innodb.result:
Better error messages (thanks to TDC patch)
mysql-test/r/merge.result:
Extra flush table test
mysql-test/r/ndb_bitfield.result:
Better error messages (thanks to TDC patch)
mysql-test/r/ndb_partition_error.result:
Better error messages (thanks to TDC patch)
mysql-test/r/query_cache.result:
Remove tables left from old tests
mysql-test/r/temp_table.result:
Test truncate with temporary tables
mysql-test/r/variables.result:
Table_cache -> Table_open_cache
mysql-test/t/flush_table.test:
More tests with lock table with 2 threads + flush table
mysql-test/t/merge.test:
Extra flush table test
mysql-test/t/multi_update.test:
Added 'sleep' to make test predictable
mysql-test/t/query_cache.test:
Remove tables left from old tests
mysql-test/t/temp_table.test:
Test truncate with temporary tables
mysql-test/t/variables.test:
Table_cache -> Table_open_cache
mysql-test/valgrind.supp:
Remove warning that may happens becasue threads dies in different order
mysys/hash.c:
Fixed wrong DBUG_PRINT
mysys/mf_dirname.c:
More DBUG
mysys/mf_pack.c:
Better comment
mysys/mf_tempdir.c:
More DBUG
Ensure that we call cleanup_dirname() on all temporary directory paths.
If we don't do this, we will get a failure when comparing temporary table
names as in some cases the temporary table name is run through convert_dirname())
mysys/my_alloc.c:
Indentation fix
sql/examples/ha_example.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_example.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/field.cc:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Use s->db instead of s->table_cache_key
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/field.h:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/ha_archive.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_archive.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_berkeley.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Changed name of argument create() to not hide internal 'table' variable.
table->s -> table_share
sql/ha_berkeley.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_federated.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed comments
Remove index variable and replace with pointers (simple optimization)
move_field() -> move_field_offset()
Removed some strlen() calls
sql/ha_federated.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_heap.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Simplify delete_table() and create() as the given file names are now without extension
sql/ha_heap.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisam.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Remove not needed fn_format()
Fixed for new table->s structure
sql/ha_myisam.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisammrg.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Don't set 'is_view' for MERGE tables
Use new interface to find_temporary_table()
sql/ha_myisammrg.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Added flag HA_NO_COPY_ON_ALTER
sql/ha_ndbcluster.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed wrong calls to strxnmov()
Give error HA_ERR_TABLE_DEF_CHANGED if table definition has changed
drop_table -> intern_drop_table()
table->s -> table_share
Move part_info to TABLE
Fixed comments & DBUG print's
New arguments to print_error()
sql/ha_ndbcluster.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_partition.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
We can't set up or use part_info when creating handler as there is not yet any table object
New ha_intialise() to work with TDC (Done by Mikael)
sql/ha_partition.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Got set_part_info() from Mikael
sql/handler.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
ha_delete_table() now also takes database as an argument
handler::ha_open() now takes TABLE as argument
ha_open() now calls ha_allocate_read_write_set()
Simplify ha_allocate_read_write_set()
Remove ha_deallocate_read_write_set()
Use table_share (Cached by table definition cache)
sql/handler.h:
New table flag: HA_NO_COPY_ON_ALTER (used by merge tables)
Remove ha_deallocate_read_write_set()
get_new_handler() now takes TABLE_SHARE as argument
ha_delete_table() now gets database as argument
sql/item.cc:
table_name and db are now LEX_STRING objects
When creating fields, we have now have to call field->init(table)
move_field -> move_field_offset()
sql/item.h:
tmp_table_field_from_field_type() now takes an extra paramenter 'fixed_length' to allow one to force usage of CHAR
instead of BLOB
sql/item_cmpfunc.cc:
Fixed call to tmp_table_field_from_field_type()
sql/item_create.cc:
Assert if new not handled cast type
sql/item_func.cc:
When creating fields, we have now have to call field->init(table)
dummy_table used by 'sp' now needs a TABLE_SHARE object
sql/item_subselect.cc:
Trivial code cleanups
sql/item_sum.cc:
When creating fields, we have now have to call field->init(table)
sql/item_timefunc.cc:
Item_func_str_to_date::tmp_table_field() now replaced by call to
tmp_table_field_from_field_type() (see item_timefunc.h)
sql/item_timefunc.h:
Simply tmp_table_field()
sql/item_uniq.cc:
When creating fields, we have now have to call field->init(table)
sql/key.cc:
Added 'KEY' argument to 'find_ref_key' to simplify code
sql/lock.cc:
More debugging
Use create_table_def_key() to create key for table cache
Allocate TABLE_SHARE properly when creating name lock
Fix that locked_table_name doesn't test same table twice
sql/mysql_priv.h:
New functions for table definition cache
New interfaces to a lot of functions.
New faster interface to find_temporary_table() and close_temporary_table()
sql/mysqld.cc:
Added support for table definition cache of size 'table_def_size'
Fixed som calls to strnmov()
Changed name of 'table_cache' to 'table_open_cache'
sql/opt_range.cc:
Use new interfaces
Fixed warnings from valgrind
sql/parse_file.cc:
Safer calls to strxnmov()
Fixed typo
sql/set_var.cc:
Added variable 'table_definition_cache'
Variable table_cache renamed to 'table_open_cache'
sql/slave.cc:
Use new interface
sql/sp.cc:
Proper use of TABLE_SHARE
sql/sp_head.cc:
Remove compiler warnings
We have now to call field->init(table)
sql/sp_head.h:
Pointers to parsed strings are now const
sql/sql_acl.cc:
table_name is now a LEX_STRING
sql/sql_base.cc:
Main implementation of table definition cache
(The #ifdef's are there for the future when table definition cache will replace open table cache)
Now table definitions are cached indepndent of open tables, which will speed up things when a table is in use at once from several places
Views are not yet cached; For the moment we only cache if a table is a view or not.
Faster implementation of find_temorary_table()
Replace 'wait_for_refresh()' with the more general function 'wait_for_condition()'
Drop table is slightly faster as we can use the table definition cache to know the type of the table
sql/sql_cache.cc:
table_cache_key and table_name are now LEX_STRING
'sDBUG print fixes
sql/sql_class.cc:
table_cache_key is now a LEX_STRING
safer strxnmov()
sql/sql_class.h:
Added number of open table shares (table definitions)
sql/sql_db.cc:
safer strxnmov()
sql/sql_delete.cc:
Use new interface to find_temporary_table()
sql/sql_derived.cc:
table_name is now a LEX_STRING
sql/sql_handler.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_insert.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_lex.cc:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_lex.h:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_load.cc:
Safer strxnmov()
sql/sql_parse.cc:
Better error if wrong DB name
sql/sql_partition.cc:
part_info moved to TABLE from TABLE_SHARE
Indentation changes
sql/sql_select.cc:
Indentation fixes
Call field->init(TABLE) for new created fields
Update create_tmp_table() to use TABLE_SHARE properly
sql/sql_select.h:
Call field->init(TABLE) for new created fields
sql/sql_show.cc:
table_name is now a LEX_STRING
part_info moved to TABLE
sql/sql_table.cc:
Use table definition cache to speed up delete of tables
Fixed calls to functions with new interfaces
Don't use 'share_not_to_be_used'
Instead of doing openfrm() when doing repair, we now have to call
get_table_share() followed by open_table_from_share().
Replace some fn_format() with faster unpack_filename().
Safer strxnmov()
part_info is now in TABLE
Added Mikaels patch for partition and ALTER TABLE
Instead of using 'TABLE_SHARE->is_view' use 'table_flags() & HA_NO_COPY_ON_ALTER
sql/sql_test.cc:
table_name and table_cache_key are now LEX_STRING's
sql/sql_trigger.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
safer strxnmov()
Removed compiler warnings
sql/sql_update.cc:
Call field->init(TABLE) after field is created
sql/sql_view.cc:
safer strxnmov()
Create common TABLE_SHARE object for views to allow us to cache if table is a view
sql/structs.h:
Added SHOW_TABLE_DEFINITIONS
sql/table.cc:
Creation and destruct of TABLE_SHARE objects that are common for many TABLE objects
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
open_table_def() is written in such a way that it should be trival to add parsing of the .frm files in new formats
sql/table.h:
TABLE objects for the same database table now share a common TABLE_SHARE object
In TABLE_SHARE the most common strings are now LEX_STRING's
sql/unireg.cc:
Changed arguments to rea_create_table() to have same order as other functions
Call field->init(table) for new created fields
sql/unireg.h:
Added OPEN_VIEW
strings/strxnmov.c:
Change strxnmov() to always add end \0
This makes usage of strxnmov() safer as most of MySQL code assumes that strxnmov() will create a null terminated string
2005-11-23 22:45:02 +02:00
|
|
|
uint8 uncacheable;
|
2004-10-20 04:04:37 +03:00
|
|
|
bool res;
|
2004-09-06 15:14:10 +03:00
|
|
|
|
2004-03-17 14:26:26 +02:00
|
|
|
DBUG_ASSERT(fixed == 0);
|
2003-10-02 22:19:41 +03:00
|
|
|
engine->set_thd((thd= thd_param));
|
2003-05-28 16:52:56 +03:00
|
|
|
|
2005-05-31 12:06:15 +02:00
|
|
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, (gptr)&res))
|
2004-10-20 04:04:37 +03:00
|
|
|
return TRUE;
|
2004-07-14 23:57:14 +03:00
|
|
|
|
|
|
|
res= engine->prepare();
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
// all transformation is done (used by prepared statements)
|
2004-02-08 20:14:13 +02:00
|
|
|
changed= 1;
|
|
|
|
|
2002-10-08 14:50:12 +03:00
|
|
|
if (!res)
|
2002-10-12 01:09:47 +03:00
|
|
|
{
|
2003-05-14 21:51:33 +03:00
|
|
|
if (substitution)
|
|
|
|
{
|
2004-03-20 13:36:26 +02:00
|
|
|
int ret= 0;
|
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
// did we changed top item of WHERE condition
|
|
|
|
if (unit->outer_select()->where == (*ref))
|
|
|
|
unit->outer_select()->where= substitution; // correct WHERE for PS
|
2004-12-09 00:37:17 +03:00
|
|
|
else if (unit->outer_select()->having == (*ref))
|
|
|
|
unit->outer_select()->having= substitution; // correct HAVING for PS
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
(*ref)= substitution;
|
|
|
|
substitution->name= name;
|
|
|
|
if (have_to_be_excluded)
|
|
|
|
engine->exclude();
|
|
|
|
substitution= 0;
|
2004-07-04 08:46:28 +03:00
|
|
|
thd->where= "checking transformed subquery";
|
2004-03-17 14:26:26 +02:00
|
|
|
if (!(*ref)->fixed)
|
2005-07-01 07:05:42 +03:00
|
|
|
ret= (*ref)->fix_fields(thd, ref);
|
2004-10-27 21:11:06 +03:00
|
|
|
thd->where= save_where;
|
2003-05-14 21:51:33 +03:00
|
|
|
return ret;
|
|
|
|
}
|
2002-10-12 01:09:47 +03:00
|
|
|
// Is it one field subselect?
|
|
|
|
if (engine->cols() > max_columns)
|
2004-07-04 08:46:28 +03:00
|
|
|
{
|
2003-10-06 22:35:05 +03:00
|
|
|
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
2004-10-20 04:04:37 +03:00
|
|
|
return TRUE;
|
2002-10-12 01:09:47 +03:00
|
|
|
}
|
2002-10-08 14:50:12 +03:00
|
|
|
fix_length_and_dec();
|
2002-10-12 01:09:47 +03:00
|
|
|
}
|
2005-01-18 17:26:05 +03:00
|
|
|
else
|
Table definition cache, part 2
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
Other noteworthy changes:
- In TABLE_SHARE the most common strings are now LEX_STRING's
- Better error message when table is not found
- Variable table_cache is now renamed 'table_open_cache'
- New variable 'table_definition_cache' that is the number of table defintions that will be cached
- strxnmov() calls are now fixed to avoid overflows
- strxnmov() will now always add one end \0 to result
- engine objects are now created with a TABLE_SHARE object instead of a TABLE object.
- After creating a field object one must call field->init(table) before using it
- For a busy system this change will give you:
- Less memory usage for table object
- Faster opening of tables (if it's has been in use or is in table definition cache)
- Allow you to cache many table definitions objects
- Faster drop of table
mysql-test/mysql-test-run.sh:
Fixed some problems with --gdb option
Test both with socket and tcp/ip port that all old servers are killed
mysql-test/r/flush_table.result:
More tests with lock table with 2 threads + flush table
mysql-test/r/information_schema.result:
Removed old (now wrong) result
mysql-test/r/innodb.result:
Better error messages (thanks to TDC patch)
mysql-test/r/merge.result:
Extra flush table test
mysql-test/r/ndb_bitfield.result:
Better error messages (thanks to TDC patch)
mysql-test/r/ndb_partition_error.result:
Better error messages (thanks to TDC patch)
mysql-test/r/query_cache.result:
Remove tables left from old tests
mysql-test/r/temp_table.result:
Test truncate with temporary tables
mysql-test/r/variables.result:
Table_cache -> Table_open_cache
mysql-test/t/flush_table.test:
More tests with lock table with 2 threads + flush table
mysql-test/t/merge.test:
Extra flush table test
mysql-test/t/multi_update.test:
Added 'sleep' to make test predictable
mysql-test/t/query_cache.test:
Remove tables left from old tests
mysql-test/t/temp_table.test:
Test truncate with temporary tables
mysql-test/t/variables.test:
Table_cache -> Table_open_cache
mysql-test/valgrind.supp:
Remove warning that may happens becasue threads dies in different order
mysys/hash.c:
Fixed wrong DBUG_PRINT
mysys/mf_dirname.c:
More DBUG
mysys/mf_pack.c:
Better comment
mysys/mf_tempdir.c:
More DBUG
Ensure that we call cleanup_dirname() on all temporary directory paths.
If we don't do this, we will get a failure when comparing temporary table
names as in some cases the temporary table name is run through convert_dirname())
mysys/my_alloc.c:
Indentation fix
sql/examples/ha_example.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_example.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/field.cc:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Use s->db instead of s->table_cache_key
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/field.h:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/ha_archive.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_archive.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_berkeley.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Changed name of argument create() to not hide internal 'table' variable.
table->s -> table_share
sql/ha_berkeley.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_federated.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed comments
Remove index variable and replace with pointers (simple optimization)
move_field() -> move_field_offset()
Removed some strlen() calls
sql/ha_federated.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_heap.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Simplify delete_table() and create() as the given file names are now without extension
sql/ha_heap.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisam.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Remove not needed fn_format()
Fixed for new table->s structure
sql/ha_myisam.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisammrg.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Don't set 'is_view' for MERGE tables
Use new interface to find_temporary_table()
sql/ha_myisammrg.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Added flag HA_NO_COPY_ON_ALTER
sql/ha_ndbcluster.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed wrong calls to strxnmov()
Give error HA_ERR_TABLE_DEF_CHANGED if table definition has changed
drop_table -> intern_drop_table()
table->s -> table_share
Move part_info to TABLE
Fixed comments & DBUG print's
New arguments to print_error()
sql/ha_ndbcluster.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_partition.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
We can't set up or use part_info when creating handler as there is not yet any table object
New ha_intialise() to work with TDC (Done by Mikael)
sql/ha_partition.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Got set_part_info() from Mikael
sql/handler.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
ha_delete_table() now also takes database as an argument
handler::ha_open() now takes TABLE as argument
ha_open() now calls ha_allocate_read_write_set()
Simplify ha_allocate_read_write_set()
Remove ha_deallocate_read_write_set()
Use table_share (Cached by table definition cache)
sql/handler.h:
New table flag: HA_NO_COPY_ON_ALTER (used by merge tables)
Remove ha_deallocate_read_write_set()
get_new_handler() now takes TABLE_SHARE as argument
ha_delete_table() now gets database as argument
sql/item.cc:
table_name and db are now LEX_STRING objects
When creating fields, we have now have to call field->init(table)
move_field -> move_field_offset()
sql/item.h:
tmp_table_field_from_field_type() now takes an extra paramenter 'fixed_length' to allow one to force usage of CHAR
instead of BLOB
sql/item_cmpfunc.cc:
Fixed call to tmp_table_field_from_field_type()
sql/item_create.cc:
Assert if new not handled cast type
sql/item_func.cc:
When creating fields, we have now have to call field->init(table)
dummy_table used by 'sp' now needs a TABLE_SHARE object
sql/item_subselect.cc:
Trivial code cleanups
sql/item_sum.cc:
When creating fields, we have now have to call field->init(table)
sql/item_timefunc.cc:
Item_func_str_to_date::tmp_table_field() now replaced by call to
tmp_table_field_from_field_type() (see item_timefunc.h)
sql/item_timefunc.h:
Simply tmp_table_field()
sql/item_uniq.cc:
When creating fields, we have now have to call field->init(table)
sql/key.cc:
Added 'KEY' argument to 'find_ref_key' to simplify code
sql/lock.cc:
More debugging
Use create_table_def_key() to create key for table cache
Allocate TABLE_SHARE properly when creating name lock
Fix that locked_table_name doesn't test same table twice
sql/mysql_priv.h:
New functions for table definition cache
New interfaces to a lot of functions.
New faster interface to find_temporary_table() and close_temporary_table()
sql/mysqld.cc:
Added support for table definition cache of size 'table_def_size'
Fixed som calls to strnmov()
Changed name of 'table_cache' to 'table_open_cache'
sql/opt_range.cc:
Use new interfaces
Fixed warnings from valgrind
sql/parse_file.cc:
Safer calls to strxnmov()
Fixed typo
sql/set_var.cc:
Added variable 'table_definition_cache'
Variable table_cache renamed to 'table_open_cache'
sql/slave.cc:
Use new interface
sql/sp.cc:
Proper use of TABLE_SHARE
sql/sp_head.cc:
Remove compiler warnings
We have now to call field->init(table)
sql/sp_head.h:
Pointers to parsed strings are now const
sql/sql_acl.cc:
table_name is now a LEX_STRING
sql/sql_base.cc:
Main implementation of table definition cache
(The #ifdef's are there for the future when table definition cache will replace open table cache)
Now table definitions are cached indepndent of open tables, which will speed up things when a table is in use at once from several places
Views are not yet cached; For the moment we only cache if a table is a view or not.
Faster implementation of find_temorary_table()
Replace 'wait_for_refresh()' with the more general function 'wait_for_condition()'
Drop table is slightly faster as we can use the table definition cache to know the type of the table
sql/sql_cache.cc:
table_cache_key and table_name are now LEX_STRING
'sDBUG print fixes
sql/sql_class.cc:
table_cache_key is now a LEX_STRING
safer strxnmov()
sql/sql_class.h:
Added number of open table shares (table definitions)
sql/sql_db.cc:
safer strxnmov()
sql/sql_delete.cc:
Use new interface to find_temporary_table()
sql/sql_derived.cc:
table_name is now a LEX_STRING
sql/sql_handler.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_insert.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_lex.cc:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_lex.h:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_load.cc:
Safer strxnmov()
sql/sql_parse.cc:
Better error if wrong DB name
sql/sql_partition.cc:
part_info moved to TABLE from TABLE_SHARE
Indentation changes
sql/sql_select.cc:
Indentation fixes
Call field->init(TABLE) for new created fields
Update create_tmp_table() to use TABLE_SHARE properly
sql/sql_select.h:
Call field->init(TABLE) for new created fields
sql/sql_show.cc:
table_name is now a LEX_STRING
part_info moved to TABLE
sql/sql_table.cc:
Use table definition cache to speed up delete of tables
Fixed calls to functions with new interfaces
Don't use 'share_not_to_be_used'
Instead of doing openfrm() when doing repair, we now have to call
get_table_share() followed by open_table_from_share().
Replace some fn_format() with faster unpack_filename().
Safer strxnmov()
part_info is now in TABLE
Added Mikaels patch for partition and ALTER TABLE
Instead of using 'TABLE_SHARE->is_view' use 'table_flags() & HA_NO_COPY_ON_ALTER
sql/sql_test.cc:
table_name and table_cache_key are now LEX_STRING's
sql/sql_trigger.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
safer strxnmov()
Removed compiler warnings
sql/sql_update.cc:
Call field->init(TABLE) after field is created
sql/sql_view.cc:
safer strxnmov()
Create common TABLE_SHARE object for views to allow us to cache if table is a view
sql/structs.h:
Added SHOW_TABLE_DEFINITIONS
sql/table.cc:
Creation and destruct of TABLE_SHARE objects that are common for many TABLE objects
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
open_table_def() is written in such a way that it should be trival to add parsing of the .frm files in new formats
sql/table.h:
TABLE objects for the same database table now share a common TABLE_SHARE object
In TABLE_SHARE the most common strings are now LEX_STRING's
sql/unireg.cc:
Changed arguments to rea_create_table() to have same order as other functions
Call field->init(table) for new created fields
sql/unireg.h:
Added OPEN_VIEW
strings/strxnmov.c:
Change strxnmov() to always add end \0
This makes usage of strxnmov() safer as most of MySQL code assumes that strxnmov() will create a null terminated string
2005-11-23 22:45:02 +02:00
|
|
|
goto err;
|
|
|
|
|
|
|
|
if ((uncacheable= engine->uncacheable()))
|
2003-10-23 20:50:53 +03:00
|
|
|
{
|
|
|
|
const_item_cache= 0;
|
2003-11-17 20:53:40 +02:00
|
|
|
if (uncacheable & UNCACHEABLE_RAND)
|
|
|
|
used_tables_cache|= RAND_TABLE_BIT;
|
2003-10-23 20:50:53 +03:00
|
|
|
}
|
2002-11-21 11:01:33 +02:00
|
|
|
fixed= 1;
|
Table definition cache, part 2
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
Other noteworthy changes:
- In TABLE_SHARE the most common strings are now LEX_STRING's
- Better error message when table is not found
- Variable table_cache is now renamed 'table_open_cache'
- New variable 'table_definition_cache' that is the number of table defintions that will be cached
- strxnmov() calls are now fixed to avoid overflows
- strxnmov() will now always add one end \0 to result
- engine objects are now created with a TABLE_SHARE object instead of a TABLE object.
- After creating a field object one must call field->init(table) before using it
- For a busy system this change will give you:
- Less memory usage for table object
- Faster opening of tables (if it's has been in use or is in table definition cache)
- Allow you to cache many table definitions objects
- Faster drop of table
mysql-test/mysql-test-run.sh:
Fixed some problems with --gdb option
Test both with socket and tcp/ip port that all old servers are killed
mysql-test/r/flush_table.result:
More tests with lock table with 2 threads + flush table
mysql-test/r/information_schema.result:
Removed old (now wrong) result
mysql-test/r/innodb.result:
Better error messages (thanks to TDC patch)
mysql-test/r/merge.result:
Extra flush table test
mysql-test/r/ndb_bitfield.result:
Better error messages (thanks to TDC patch)
mysql-test/r/ndb_partition_error.result:
Better error messages (thanks to TDC patch)
mysql-test/r/query_cache.result:
Remove tables left from old tests
mysql-test/r/temp_table.result:
Test truncate with temporary tables
mysql-test/r/variables.result:
Table_cache -> Table_open_cache
mysql-test/t/flush_table.test:
More tests with lock table with 2 threads + flush table
mysql-test/t/merge.test:
Extra flush table test
mysql-test/t/multi_update.test:
Added 'sleep' to make test predictable
mysql-test/t/query_cache.test:
Remove tables left from old tests
mysql-test/t/temp_table.test:
Test truncate with temporary tables
mysql-test/t/variables.test:
Table_cache -> Table_open_cache
mysql-test/valgrind.supp:
Remove warning that may happens becasue threads dies in different order
mysys/hash.c:
Fixed wrong DBUG_PRINT
mysys/mf_dirname.c:
More DBUG
mysys/mf_pack.c:
Better comment
mysys/mf_tempdir.c:
More DBUG
Ensure that we call cleanup_dirname() on all temporary directory paths.
If we don't do this, we will get a failure when comparing temporary table
names as in some cases the temporary table name is run through convert_dirname())
mysys/my_alloc.c:
Indentation fix
sql/examples/ha_example.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_example.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/field.cc:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Use s->db instead of s->table_cache_key
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/field.h:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/ha_archive.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_archive.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_berkeley.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Changed name of argument create() to not hide internal 'table' variable.
table->s -> table_share
sql/ha_berkeley.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_federated.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed comments
Remove index variable and replace with pointers (simple optimization)
move_field() -> move_field_offset()
Removed some strlen() calls
sql/ha_federated.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_heap.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Simplify delete_table() and create() as the given file names are now without extension
sql/ha_heap.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisam.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Remove not needed fn_format()
Fixed for new table->s structure
sql/ha_myisam.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisammrg.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Don't set 'is_view' for MERGE tables
Use new interface to find_temporary_table()
sql/ha_myisammrg.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Added flag HA_NO_COPY_ON_ALTER
sql/ha_ndbcluster.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed wrong calls to strxnmov()
Give error HA_ERR_TABLE_DEF_CHANGED if table definition has changed
drop_table -> intern_drop_table()
table->s -> table_share
Move part_info to TABLE
Fixed comments & DBUG print's
New arguments to print_error()
sql/ha_ndbcluster.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_partition.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
We can't set up or use part_info when creating handler as there is not yet any table object
New ha_intialise() to work with TDC (Done by Mikael)
sql/ha_partition.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Got set_part_info() from Mikael
sql/handler.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
ha_delete_table() now also takes database as an argument
handler::ha_open() now takes TABLE as argument
ha_open() now calls ha_allocate_read_write_set()
Simplify ha_allocate_read_write_set()
Remove ha_deallocate_read_write_set()
Use table_share (Cached by table definition cache)
sql/handler.h:
New table flag: HA_NO_COPY_ON_ALTER (used by merge tables)
Remove ha_deallocate_read_write_set()
get_new_handler() now takes TABLE_SHARE as argument
ha_delete_table() now gets database as argument
sql/item.cc:
table_name and db are now LEX_STRING objects
When creating fields, we have now have to call field->init(table)
move_field -> move_field_offset()
sql/item.h:
tmp_table_field_from_field_type() now takes an extra paramenter 'fixed_length' to allow one to force usage of CHAR
instead of BLOB
sql/item_cmpfunc.cc:
Fixed call to tmp_table_field_from_field_type()
sql/item_create.cc:
Assert if new not handled cast type
sql/item_func.cc:
When creating fields, we have now have to call field->init(table)
dummy_table used by 'sp' now needs a TABLE_SHARE object
sql/item_subselect.cc:
Trivial code cleanups
sql/item_sum.cc:
When creating fields, we have now have to call field->init(table)
sql/item_timefunc.cc:
Item_func_str_to_date::tmp_table_field() now replaced by call to
tmp_table_field_from_field_type() (see item_timefunc.h)
sql/item_timefunc.h:
Simply tmp_table_field()
sql/item_uniq.cc:
When creating fields, we have now have to call field->init(table)
sql/key.cc:
Added 'KEY' argument to 'find_ref_key' to simplify code
sql/lock.cc:
More debugging
Use create_table_def_key() to create key for table cache
Allocate TABLE_SHARE properly when creating name lock
Fix that locked_table_name doesn't test same table twice
sql/mysql_priv.h:
New functions for table definition cache
New interfaces to a lot of functions.
New faster interface to find_temporary_table() and close_temporary_table()
sql/mysqld.cc:
Added support for table definition cache of size 'table_def_size'
Fixed som calls to strnmov()
Changed name of 'table_cache' to 'table_open_cache'
sql/opt_range.cc:
Use new interfaces
Fixed warnings from valgrind
sql/parse_file.cc:
Safer calls to strxnmov()
Fixed typo
sql/set_var.cc:
Added variable 'table_definition_cache'
Variable table_cache renamed to 'table_open_cache'
sql/slave.cc:
Use new interface
sql/sp.cc:
Proper use of TABLE_SHARE
sql/sp_head.cc:
Remove compiler warnings
We have now to call field->init(table)
sql/sp_head.h:
Pointers to parsed strings are now const
sql/sql_acl.cc:
table_name is now a LEX_STRING
sql/sql_base.cc:
Main implementation of table definition cache
(The #ifdef's are there for the future when table definition cache will replace open table cache)
Now table definitions are cached indepndent of open tables, which will speed up things when a table is in use at once from several places
Views are not yet cached; For the moment we only cache if a table is a view or not.
Faster implementation of find_temorary_table()
Replace 'wait_for_refresh()' with the more general function 'wait_for_condition()'
Drop table is slightly faster as we can use the table definition cache to know the type of the table
sql/sql_cache.cc:
table_cache_key and table_name are now LEX_STRING
'sDBUG print fixes
sql/sql_class.cc:
table_cache_key is now a LEX_STRING
safer strxnmov()
sql/sql_class.h:
Added number of open table shares (table definitions)
sql/sql_db.cc:
safer strxnmov()
sql/sql_delete.cc:
Use new interface to find_temporary_table()
sql/sql_derived.cc:
table_name is now a LEX_STRING
sql/sql_handler.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_insert.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_lex.cc:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_lex.h:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_load.cc:
Safer strxnmov()
sql/sql_parse.cc:
Better error if wrong DB name
sql/sql_partition.cc:
part_info moved to TABLE from TABLE_SHARE
Indentation changes
sql/sql_select.cc:
Indentation fixes
Call field->init(TABLE) for new created fields
Update create_tmp_table() to use TABLE_SHARE properly
sql/sql_select.h:
Call field->init(TABLE) for new created fields
sql/sql_show.cc:
table_name is now a LEX_STRING
part_info moved to TABLE
sql/sql_table.cc:
Use table definition cache to speed up delete of tables
Fixed calls to functions with new interfaces
Don't use 'share_not_to_be_used'
Instead of doing openfrm() when doing repair, we now have to call
get_table_share() followed by open_table_from_share().
Replace some fn_format() with faster unpack_filename().
Safer strxnmov()
part_info is now in TABLE
Added Mikaels patch for partition and ALTER TABLE
Instead of using 'TABLE_SHARE->is_view' use 'table_flags() & HA_NO_COPY_ON_ALTER
sql/sql_test.cc:
table_name and table_cache_key are now LEX_STRING's
sql/sql_trigger.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
safer strxnmov()
Removed compiler warnings
sql/sql_update.cc:
Call field->init(TABLE) after field is created
sql/sql_view.cc:
safer strxnmov()
Create common TABLE_SHARE object for views to allow us to cache if table is a view
sql/structs.h:
Added SHOW_TABLE_DEFINITIONS
sql/table.cc:
Creation and destruct of TABLE_SHARE objects that are common for many TABLE objects
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
open_table_def() is written in such a way that it should be trival to add parsing of the .frm files in new formats
sql/table.h:
TABLE objects for the same database table now share a common TABLE_SHARE object
In TABLE_SHARE the most common strings are now LEX_STRING's
sql/unireg.cc:
Changed arguments to rea_create_table() to have same order as other functions
Call field->init(table) for new created fields
sql/unireg.h:
Added OPEN_VIEW
strings/strxnmov.c:
Change strxnmov() to always add end \0
This makes usage of strxnmov() safer as most of MySQL code assumes that strxnmov() will create a null terminated string
2005-11-23 22:45:02 +02:00
|
|
|
|
|
|
|
err:
|
2002-11-24 21:10:52 +02:00
|
|
|
thd->where= save_where;
|
2002-09-28 18:34:56 +03:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2003-05-28 16:52:56 +03:00
|
|
|
bool Item_subselect::exec()
|
|
|
|
{
|
2003-07-07 18:40:19 +03:00
|
|
|
int res;
|
2004-11-08 01:13:54 +02:00
|
|
|
|
|
|
|
res= engine->exec();
|
|
|
|
|
2003-07-07 18:40:19 +03:00
|
|
|
if (engine_changed)
|
|
|
|
{
|
|
|
|
engine_changed= 0;
|
|
|
|
return exec();
|
|
|
|
}
|
|
|
|
return (res);
|
2003-05-28 16:52:56 +03:00
|
|
|
}
|
|
|
|
|
2004-07-04 08:46:28 +03:00
|
|
|
Item::Type Item_subselect::type() const
|
2002-12-19 07:38:33 +02:00
|
|
|
{
|
|
|
|
return SUBSELECT_ITEM;
|
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2002-09-28 18:34:56 +03:00
|
|
|
void Item_subselect::fix_length_and_dec()
|
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
engine->fix_length_and_dec(0);
|
2002-05-12 23:46:42 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2003-10-17 00:36:01 +03:00
|
|
|
table_map Item_subselect::used_tables() const
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2003-11-17 20:53:40 +02:00
|
|
|
return (table_map) (engine->uncacheable() ? used_tables_cache : 0L);
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2003-10-28 12:45:37 +02:00
|
|
|
|
2003-10-17 00:36:01 +03:00
|
|
|
bool Item_subselect::const_item() const
|
|
|
|
{
|
2003-10-23 20:50:53 +03:00
|
|
|
return const_item_cache;
|
2003-10-17 00:36:01 +03:00
|
|
|
}
|
|
|
|
|
2003-12-06 23:37:24 +04:00
|
|
|
Item *Item_subselect::get_tmp_table_item(THD *thd)
|
|
|
|
{
|
|
|
|
if (!with_sum_func && !const_item())
|
2004-03-20 13:36:26 +02:00
|
|
|
return new Item_field(result_field);
|
2003-12-06 23:37:24 +04:00
|
|
|
return copy_or_same(thd);
|
|
|
|
}
|
2003-10-28 12:45:37 +02:00
|
|
|
|
2003-10-17 00:36:01 +03:00
|
|
|
void Item_subselect::update_used_tables()
|
|
|
|
{
|
|
|
|
if (!engine->uncacheable())
|
|
|
|
{
|
2005-02-09 02:50:45 +04:00
|
|
|
// did all used tables become static?
|
2003-11-01 19:02:43 +02:00
|
|
|
if (!(used_tables_cache & ~engine->upper_select_const_tables()))
|
2003-10-17 00:36:01 +03:00
|
|
|
const_item_cache= 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
|
|
|
void Item_subselect::print(String *str)
|
|
|
|
{
|
|
|
|
str->append('(');
|
|
|
|
engine->print(str);
|
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-07 08:51:09 +03:00
|
|
|
Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
|
2003-08-12 12:38:03 +03:00
|
|
|
:Item_subselect(), value(0)
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2002-12-19 21:15:09 +02:00
|
|
|
DBUG_ENTER("Item_singlerow_subselect::Item_singlerow_subselect");
|
2003-10-02 22:19:41 +03:00
|
|
|
init(select_lex, new select_singlerow_subselect(this));
|
2002-06-19 17:52:44 +03:00
|
|
|
maybe_null= 1;
|
2002-12-19 07:38:33 +02:00
|
|
|
max_columns= UINT_MAX;
|
2002-10-27 23:27:00 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2004-09-10 13:09:27 +03:00
|
|
|
Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
|
|
|
|
Item_subselect *parent,
|
2003-10-27 01:01:27 +02:00
|
|
|
st_select_lex *select_lex,
|
2003-10-16 15:54:47 +03:00
|
|
|
bool max_arg)
|
2004-11-18 18:10:07 +02:00
|
|
|
:Item_singlerow_subselect(), was_values(TRUE)
|
2003-08-12 12:38:03 +03:00
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect");
|
2003-10-16 15:54:47 +03:00
|
|
|
max= max_arg;
|
|
|
|
init(select_lex, new select_max_min_finder_subselect(this, max_arg));
|
2003-08-12 12:38:03 +03:00
|
|
|
max_columns= 1;
|
|
|
|
maybe_null= 1;
|
|
|
|
max_columns= 1;
|
2003-10-27 01:01:27 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Following information was collected during performing fix_fields()
|
|
|
|
of Items belonged to subquery, which will be not repeated
|
|
|
|
*/
|
|
|
|
used_tables_cache= parent->get_used_tables_cache();
|
|
|
|
const_item_cache= parent->get_const_item_cache();
|
2004-07-04 08:46:28 +03:00
|
|
|
|
2004-09-10 13:09:27 +03:00
|
|
|
/*
|
2005-02-09 02:50:45 +04:00
|
|
|
this subquery always creates during preparation, so we can assign
|
2004-09-10 13:09:27 +03:00
|
|
|
thd here
|
|
|
|
*/
|
|
|
|
thd= thd_param;
|
|
|
|
|
2003-08-12 12:38:03 +03:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2004-11-18 18:10:07 +02:00
|
|
|
void Item_maxmin_subselect::cleanup()
|
|
|
|
{
|
2004-12-07 21:18:15 +02:00
|
|
|
DBUG_ENTER("Item_maxmin_subselect::cleanup");
|
|
|
|
Item_singlerow_subselect::cleanup();
|
|
|
|
|
2004-11-18 18:10:07 +02:00
|
|
|
/*
|
2004-12-07 21:18:15 +02:00
|
|
|
By default it is TRUE to avoid TRUE reporting by
|
2004-11-18 18:10:07 +02:00
|
|
|
Item_func_not_all/Item_func_nop_all if this item was never called.
|
|
|
|
|
|
|
|
Engine exec() set it to FALSE by reset_value_registration() call.
|
2004-12-07 21:18:15 +02:00
|
|
|
select_max_min_finder_subselect::send_data() set it back to TRUE if some
|
|
|
|
value will be found.
|
2004-11-18 18:10:07 +02:00
|
|
|
*/
|
|
|
|
was_values= TRUE;
|
2004-12-07 21:18:15 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-11-18 18:10:07 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
void Item_maxmin_subselect::print(String *str)
|
|
|
|
{
|
2003-10-30 12:57:26 +02:00
|
|
|
str->append(max?"<max>":"<min>", 5);
|
2003-10-16 15:54:47 +03:00
|
|
|
Item_singlerow_subselect::print(str);
|
|
|
|
}
|
|
|
|
|
2004-11-18 18:10:07 +02:00
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
void Item_singlerow_subselect::reset()
|
2002-09-28 18:34:56 +03:00
|
|
|
{
|
2002-12-19 07:38:32 +02:00
|
|
|
null_value= 1;
|
|
|
|
if (value)
|
|
|
|
value->null_value= 1;
|
2002-09-28 18:34:56 +03:00
|
|
|
}
|
|
|
|
|
2004-11-18 18:10:07 +02:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2003-07-02 01:45:22 +03:00
|
|
|
Item_singlerow_subselect::select_transformer(JOIN *join)
|
2002-12-26 01:28:59 +02:00
|
|
|
{
|
2004-02-08 20:14:13 +02:00
|
|
|
if (changed)
|
|
|
|
return RES_OK;
|
2004-07-04 08:46:28 +03:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
SELECT_LEX *select_lex= join->select_lex;
|
2005-09-02 17:21:19 +04:00
|
|
|
Query_arena *arena= thd->stmt_arena;
|
2004-10-29 19:26:52 +03:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
if (!select_lex->master_unit()->first_select()->next_select() &&
|
|
|
|
!select_lex->table_list.elements &&
|
2002-12-31 18:39:16 +02:00
|
|
|
select_lex->item_list.elements == 1 &&
|
2004-10-27 21:11:06 +03:00
|
|
|
!select_lex->item_list.head()->with_sum_func &&
|
2003-02-02 23:30:01 +02:00
|
|
|
/*
|
|
|
|
We cant change name of Item_field or Item_ref, because it will
|
|
|
|
prevent it's correct resolving, but we should save name of
|
|
|
|
removed item => we do not make optimization if top item of
|
|
|
|
list is field or reference.
|
|
|
|
TODO: solve above problem
|
|
|
|
*/
|
2002-12-31 18:39:16 +02:00
|
|
|
!(select_lex->item_list.head()->type() == FIELD_ITEM ||
|
2004-10-27 21:11:06 +03:00
|
|
|
select_lex->item_list.head()->type() == REF_ITEM) &&
|
|
|
|
/*
|
2005-02-09 02:50:45 +04:00
|
|
|
switch off this optimization for prepare statement,
|
2004-10-27 21:11:06 +03:00
|
|
|
because we do not rollback this changes
|
|
|
|
TODO: make rollback for it, or special name resolving mode in 5.0.
|
|
|
|
*/
|
2005-06-03 00:02:47 +04:00
|
|
|
!arena->is_stmt_prepare_or_first_sp_execute()
|
2002-12-31 18:39:16 +02:00
|
|
|
)
|
2002-12-26 01:28:59 +02:00
|
|
|
{
|
2004-07-04 08:46:28 +03:00
|
|
|
|
2002-12-26 01:28:59 +02:00
|
|
|
have_to_be_excluded= 1;
|
2004-09-10 02:22:44 +03:00
|
|
|
if (thd->lex->describe)
|
2002-12-26 01:28:59 +02:00
|
|
|
{
|
|
|
|
char warn_buff[MYSQL_ERRMSG_SIZE];
|
|
|
|
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
|
2004-09-10 02:22:44 +03:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
2002-12-26 01:28:59 +02:00
|
|
|
ER_SELECT_REDUCED, warn_buff);
|
|
|
|
}
|
|
|
|
substitution= select_lex->item_list.head();
|
2003-07-02 13:12:18 +03:00
|
|
|
/*
|
2005-02-09 02:50:45 +04:00
|
|
|
as far as we moved content to upper level, field which depend of
|
2003-07-02 13:12:18 +03:00
|
|
|
'upper' select is not really dependent => we remove this dependence
|
|
|
|
*/
|
|
|
|
substitution->walk(&Item::remove_dependence_processor,
|
|
|
|
(byte *) select_lex->outer_select());
|
2005-03-30 10:07:08 +03:00
|
|
|
/* SELECT without FROM clause can't have WHERE or HAVING clause */
|
|
|
|
DBUG_ASSERT(join->conds == 0 && join->having == 0);
|
2003-08-28 13:21:30 +03:00
|
|
|
return RES_REDUCE;
|
2002-12-26 01:28:59 +02:00
|
|
|
}
|
2003-08-28 13:21:30 +03:00
|
|
|
return RES_OK;
|
2002-12-26 01:28:59 +02:00
|
|
|
}
|
|
|
|
|
2004-10-29 19:26:52 +03:00
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
void Item_singlerow_subselect::store(uint i, Item *item)
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
row[i]->store(item);
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
enum Item_result Item_singlerow_subselect::result_type() const
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2002-12-19 07:38:32 +02:00
|
|
|
return engine->type();
|
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
void Item_singlerow_subselect::fix_length_and_dec()
|
2002-09-28 18:34:56 +03:00
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
if ((max_columns= engine->cols()) == 1)
|
|
|
|
{
|
|
|
|
engine->fix_length_and_dec(row= &value);
|
|
|
|
}
|
|
|
|
else
|
2002-12-19 07:38:32 +02:00
|
|
|
{
|
2003-11-28 12:18:13 +02:00
|
|
|
if (!(row= (Item_cache**) sql_alloc(sizeof(Item_cache*)*max_columns)))
|
2002-12-19 07:38:33 +02:00
|
|
|
return;
|
|
|
|
engine->fix_length_and_dec(row);
|
|
|
|
value= *row;
|
2002-12-19 07:38:32 +02:00
|
|
|
}
|
2004-10-27 21:11:06 +03:00
|
|
|
/*
|
|
|
|
If there are not tables in subquery then ability to have NULL value
|
|
|
|
depends on SELECT list (if single row subquery have tables then it
|
|
|
|
always can be NULL if there are not records fetched).
|
|
|
|
*/
|
|
|
|
if (engine->no_tables())
|
|
|
|
maybe_null= engine->may_be_null();
|
2002-09-28 18:34:56 +03:00
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
uint Item_singlerow_subselect::cols()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
return engine->cols();
|
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
bool Item_singlerow_subselect::check_cols(uint c)
|
2002-12-19 07:38:33 +02:00
|
|
|
{
|
|
|
|
if (c != engine->cols())
|
|
|
|
{
|
2003-10-06 22:35:05 +03:00
|
|
|
my_error(ER_OPERAND_COLUMNS, MYF(0), c);
|
2002-12-19 07:38:33 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
bool Item_singlerow_subselect::null_inside()
|
2002-12-19 07:38:33 +02:00
|
|
|
{
|
|
|
|
for (uint i= 0; i < max_columns ; i++)
|
|
|
|
{
|
|
|
|
if (row[i]->null_value)
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-12-19 21:15:09 +02:00
|
|
|
void Item_singlerow_subselect::bring_value()
|
2002-12-19 07:38:33 +02:00
|
|
|
{
|
2003-05-28 16:52:56 +03:00
|
|
|
exec();
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2004-11-11 21:39:35 +03:00
|
|
|
double Item_singlerow_subselect::val_real()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (!exec() && !value->null_value)
|
2002-12-19 07:38:32 +02:00
|
|
|
{
|
|
|
|
null_value= 0;
|
2004-11-11 21:39:35 +03:00
|
|
|
return value->val_real();
|
2002-12-19 07:38:32 +02:00
|
|
|
}
|
|
|
|
else
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2004-07-04 08:46:28 +03:00
|
|
|
longlong Item_singlerow_subselect::val_int()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (!exec() && !value->null_value)
|
2002-12-19 07:38:32 +02:00
|
|
|
{
|
|
|
|
null_value= 0;
|
|
|
|
return value->val_int();
|
|
|
|
}
|
|
|
|
else
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
String *Item_singlerow_subselect::val_str(String *str)
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2003-05-28 16:52:56 +03:00
|
|
|
if (!exec() && !value->null_value)
|
2002-12-19 07:38:32 +02:00
|
|
|
{
|
|
|
|
null_value= 0;
|
|
|
|
return value->val_str(str);
|
|
|
|
}
|
|
|
|
else
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
my_decimal *Item_singlerow_subselect::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
if (!exec() && !value->null_value)
|
|
|
|
{
|
|
|
|
null_value= 0;
|
|
|
|
return value->val_decimal(decimal_value);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Item_singlerow_subselect::val_bool()
|
|
|
|
{
|
|
|
|
if (!exec() && !value->null_value)
|
|
|
|
{
|
|
|
|
null_value= 0;
|
|
|
|
return value->val_bool();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-02 22:19:41 +03:00
|
|
|
Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
|
2002-10-08 23:49:59 +03:00
|
|
|
Item_subselect()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2002-10-27 23:27:00 +02:00
|
|
|
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
|
2005-02-09 02:50:45 +04:00
|
|
|
bool val_bool();
|
2003-10-02 22:19:41 +03:00
|
|
|
init(select_lex, new select_exists_subselect(this));
|
2002-06-19 17:52:44 +03:00
|
|
|
max_columns= UINT_MAX;
|
|
|
|
null_value= 0; //can't be NULL
|
|
|
|
maybe_null= 0; //can't be NULL
|
|
|
|
value= 0;
|
2002-10-27 23:27:00 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
|
|
|
void Item_exists_subselect::print(String *str)
|
|
|
|
{
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN("exists"));
|
2003-10-16 15:54:47 +03:00
|
|
|
Item_subselect::print(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
|
|
|
|
{
|
2003-07-03 02:30:52 +03:00
|
|
|
if (unit->fake_select_lex &&
|
|
|
|
unit->fake_select_lex->test_limit())
|
2003-05-14 21:51:33 +03:00
|
|
|
return(1);
|
2003-07-02 01:45:22 +03:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
SELECT_LEX *sl= unit->first_select();
|
|
|
|
for (; sl; sl= sl->next_select())
|
|
|
|
{
|
2003-07-02 01:45:22 +03:00
|
|
|
if (sl->test_limit())
|
2003-05-14 21:51:33 +03:00
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:19:41 +03:00
|
|
|
Item_in_subselect::Item_in_subselect(Item * left_exp,
|
2002-10-27 23:27:00 +02:00
|
|
|
st_select_lex *select_lex):
|
2005-03-10 14:01:22 +02:00
|
|
|
Item_exists_subselect(), optimizer(0), transformed(0), upper_item(0)
|
2002-10-27 23:27:00 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
2002-11-07 23:45:19 +02:00
|
|
|
left_expr= left_exp;
|
2003-10-02 22:19:41 +03:00
|
|
|
init(select_lex, new select_exists_subselect(this));
|
2002-11-07 23:45:19 +02:00
|
|
|
max_columns= UINT_MAX;
|
2002-12-06 21:55:53 +02:00
|
|
|
maybe_null= 1;
|
2003-05-14 21:51:33 +03:00
|
|
|
abort_on_null= 0;
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2003-07-02 01:45:22 +03:00
|
|
|
//if test_limit will fail then error will be reported to client
|
2003-05-14 21:51:33 +03:00
|
|
|
test_limit(select_lex->master_unit());
|
2002-11-07 23:45:19 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2003-10-02 22:19:41 +03:00
|
|
|
Item_allany_subselect::Item_allany_subselect(Item * left_exp,
|
2003-11-03 12:28:36 +02:00
|
|
|
Comp_creator *fn,
|
2003-10-16 15:54:47 +03:00
|
|
|
st_select_lex *select_lex,
|
|
|
|
bool all_arg)
|
|
|
|
:Item_in_subselect(), all(all_arg)
|
2002-11-07 23:45:19 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_in_subselect::Item_in_subselect");
|
|
|
|
left_expr= left_exp;
|
2003-05-14 21:51:33 +03:00
|
|
|
func= fn;
|
2003-10-02 22:19:41 +03:00
|
|
|
init(select_lex, new select_exists_subselect(this));
|
2002-12-19 21:15:09 +02:00
|
|
|
max_columns= 1;
|
2003-05-14 21:51:33 +03:00
|
|
|
abort_on_null= 0;
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2003-07-02 01:45:22 +03:00
|
|
|
//if test_limit will fail then error will be reported to client
|
2003-05-14 21:51:33 +03:00
|
|
|
test_limit(select_lex->master_unit());
|
2002-10-27 23:27:00 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2002-06-19 17:52:44 +03:00
|
|
|
}
|
|
|
|
|
2002-10-27 23:27:00 +02:00
|
|
|
|
2002-09-28 18:34:56 +03:00
|
|
|
void Item_exists_subselect::fix_length_and_dec()
|
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
decimals= 0;
|
2002-12-06 21:55:53 +02:00
|
|
|
max_length= 1;
|
2002-12-19 21:15:09 +02:00
|
|
|
max_columns= engine->cols();
|
Patch two (the final one) for Bug#7306 "the server side preparedStatement
error for LIMIT placeholder".
The patch adds grammar support for LIMIT ?, ? and changes the
type of ST_SELECT_LEX::select_limit,offset_limit from ha_rows to Item*,
so that it can point to Item_param.
mysql-test/include/ps_modify.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/include/ps_query.inc:
Fix existing tests: now LIMIT can contain placeholders.
mysql-test/r/ps.result:
Add basic test coverage for LIMIT ?, ? and fix test results.
mysql-test/r/ps_2myisam.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_3innodb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_4heap.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_5merge.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_6bdb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/r/ps_7ndb.result:
Fix test results: now LIMIT can contain placeholders.
mysql-test/t/ps.test:
Add basic test coverage for LIMIT ?, ?.
sql/item.h:
Add a short-cut for (ulonglong) val_int() to Item.
Add a constructor to Item_int() that accepts ulonglong.
Simplify Item_uint constructor by using the c-tor above.
sql/item_subselect.cc:
Now select_limit has type Item *.
We can safely create an Item in Item_exists_subselect::fix_length_and_dec():
it will be allocated in runtime memory root and freed in the end of
execution.
sql/sp_head.cc:
Add a special initalization state for stored procedures to
be able to easily distinguish the first execution of a stored procedure
from prepared statement prepare.
sql/sql_class.h:
Introduce new state 'INITIALIZED_FOR_SP' to be able to easily distinguish
the first execution of a stored procedure from prepared statement prepare.
sql/sql_derived.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace. Add a warning about use of set_limit in
mysql_derived_filling.
sql/sql_error.cc:
- use unit->set_limit() to set unit->select_limit_cnt, offset_limit_cnt
evreryplace.
- this change is also aware of bug#11095 "show warnings limit 0 returns
all rows instead of zero rows", so the one who merges the bugfix from
4.1 can use local version of sql_error.cc.
sql/sql_handler.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
sql/sql_lex.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_lex.h:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_parse.cc:
- use unit->set_limit() to initalize
unit->select_limit_cnt,offset_limit_cnt everyplace.
- we can create an Item_int to set global limit of a statement:
it will be created in the runtime mem root and freed in the end of
execution.
sql/sql_repl.cc:
Use unit->set_limit to initialize limits.
sql/sql_select.cc:
- select_limit is now Item* so the proper way to check for default value
is to compare it with NULL.
sql/sql_union.cc:
Evaluate offset_limit_cnt using the new type of ST_SELECT_LEX::offset_limit
sql/sql_view.cc:
Now ST_SELECT_LEX::select_limit, offset_limit have type Item *
sql/sql_yacc.yy:
Add grammar support for LIMIT ?, ? clause.
2005-06-07 14:11:36 +04:00
|
|
|
/* We need only 1 row to determine existence */
|
2005-06-08 11:37:43 +05:00
|
|
|
unit->global_parameters->select_limit= new Item_int((int32) 1);
|
2002-09-28 18:34:56 +03:00
|
|
|
}
|
|
|
|
|
2004-11-11 21:39:35 +03:00
|
|
|
double Item_exists_subselect::val_real()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
return (double) value;
|
|
|
|
}
|
|
|
|
|
2004-07-04 08:46:28 +03:00
|
|
|
longlong Item_exists_subselect::val_int()
|
2002-06-19 17:52:44 +03:00
|
|
|
{
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2002-06-19 17:52:44 +03:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
String *Item_exists_subselect::val_str(String *str)
|
|
|
|
{
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-10-07 22:21:17 +03:00
|
|
|
{
|
2002-12-06 21:55:53 +02:00
|
|
|
reset();
|
|
|
|
return 0;
|
|
|
|
}
|
2005-04-01 02:14:30 +03:00
|
|
|
str->set((ulonglong)value,&my_charset_bin);
|
2002-12-06 21:55:53 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
|
|
|
|
my_decimal *Item_exists_subselect::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
if (exec())
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
|
|
|
|
return decimal_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Item_exists_subselect::val_bool()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
if (exec())
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
return 0;
|
|
|
|
}
|
2005-03-18 16:12:25 -08:00
|
|
|
return value != 0;
|
2005-02-09 02:50:45 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 21:39:35 +03:00
|
|
|
double Item_in_subselect::val_real()
|
2002-12-06 21:55:53 +02:00
|
|
|
{
|
2005-03-30 10:07:08 +03:00
|
|
|
/*
|
|
|
|
As far as Item_in_subselect called only from Item_in_optimizer this
|
|
|
|
method should not be used
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(0);
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-12-06 21:55:53 +02:00
|
|
|
{
|
|
|
|
reset();
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (was_null && !value)
|
|
|
|
null_value= 1;
|
|
|
|
return (double) value;
|
|
|
|
}
|
|
|
|
|
2005-03-30 10:07:08 +03:00
|
|
|
|
2004-07-04 08:46:28 +03:00
|
|
|
longlong Item_in_subselect::val_int()
|
2002-12-06 21:55:53 +02:00
|
|
|
{
|
2005-03-31 10:39:48 +03:00
|
|
|
/*
|
|
|
|
As far as Item_in_subselect called only from Item_in_optimizer this
|
|
|
|
method should not be used
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(0);
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-12-06 21:55:53 +02:00
|
|
|
{
|
|
|
|
reset();
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (was_null && !value)
|
|
|
|
null_value= 1;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2005-03-30 10:07:08 +03:00
|
|
|
|
2002-12-06 21:55:53 +02:00
|
|
|
String *Item_in_subselect::val_str(String *str)
|
|
|
|
{
|
2005-03-30 10:07:08 +03:00
|
|
|
/*
|
|
|
|
As far as Item_in_subselect called only from Item_in_optimizer this
|
|
|
|
method should not be used
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(0);
|
2004-03-18 15:14:36 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-05-28 16:52:56 +03:00
|
|
|
if (exec())
|
2002-12-06 21:55:53 +02:00
|
|
|
{
|
|
|
|
reset();
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (was_null && !value)
|
|
|
|
{
|
|
|
|
null_value= 1;
|
2002-06-19 17:52:44 +03:00
|
|
|
return 0;
|
2002-10-07 22:21:17 +03:00
|
|
|
}
|
2005-04-01 02:14:30 +03:00
|
|
|
str->set((ulonglong)value, &my_charset_bin);
|
2002-06-19 17:52:44 +03:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2002-11-07 23:45:19 +02:00
|
|
|
|
2005-04-01 02:14:30 +03:00
|
|
|
bool Item_in_subselect::val_bool()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
if (exec())
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (was_null && !value)
|
|
|
|
null_value= 1;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
my_decimal *Item_in_subselect::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
As far as Item_in_subselect called only from Item_in_optimizer this
|
|
|
|
method should not be used
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
if (exec())
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (was_null && !value)
|
|
|
|
null_value= 1;
|
|
|
|
int2my_decimal(E_DEC_FATAL_ERROR, value, 0, decimal_value);
|
|
|
|
return decimal_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-04 18:58:06 +04:00
|
|
|
/* Rewrite a single-column IN/ALL/ANY subselect. */
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2003-07-02 01:45:22 +03:00
|
|
|
Item_in_subselect::single_value_transformer(JOIN *join,
|
2003-11-03 12:28:36 +02:00
|
|
|
Comp_creator *func)
|
2002-11-07 23:45:19 +02:00
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
Item_subselect::trans_res result= RES_ERROR;
|
2003-05-14 21:51:33 +03:00
|
|
|
SELECT_LEX *select_lex= join->select_lex;
|
2005-05-30 20:48:40 +03:00
|
|
|
DBUG_ENTER("Item_in_subselect::single_value_transformer");
|
2004-09-06 15:14:10 +03:00
|
|
|
|
2004-10-04 18:58:06 +04:00
|
|
|
/*
|
|
|
|
Check that the right part of the subselect contains no more than one
|
|
|
|
column. E.g. in SELECT 1 IN (SELECT * ..) the right part is (SELECT * ...)
|
|
|
|
*/
|
2003-10-23 23:54:21 +03:00
|
|
|
if (select_lex->item_list.elements > 1)
|
|
|
|
{
|
|
|
|
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-10-23 23:54:21 +03:00
|
|
|
}
|
|
|
|
|
2004-10-04 18:58:06 +04:00
|
|
|
/*
|
|
|
|
If this is an ALL/ANY single-value subselect, try to rewrite it with
|
|
|
|
a MIN/MAX subselect. We can do that if a possible NULL result of the
|
|
|
|
subselect can be ignored.
|
|
|
|
E.g. SELECT * FROM t1 WHERE b > ANY (SELECT a FROM t2) can be rewritten
|
|
|
|
with SELECT * FROM t1 WHERE b > (SELECT MAX(a) FROM t2).
|
|
|
|
We can't check that this optimization is safe if it's not a top-level
|
|
|
|
item of the WHERE clause (e.g. because the WHERE clause can contain IS
|
|
|
|
NULL/IS NOT NULL functions). If so, we rewrite ALL/ANY with NOT EXISTS
|
|
|
|
later in this method.
|
|
|
|
*/
|
2004-11-18 18:10:07 +02:00
|
|
|
if ((abort_on_null || (upper_item && upper_item->top_level())) &&
|
2003-11-17 20:53:40 +02:00
|
|
|
!select_lex->master_unit()->uncacheable && !func->eqne_op())
|
2003-07-24 15:26:21 +03:00
|
|
|
{
|
2003-10-27 01:01:27 +02:00
|
|
|
if (substitution)
|
|
|
|
{
|
|
|
|
// It is second (third, ...) SELECT of UNION => All is done
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_OK);
|
2003-10-27 01:01:27 +02:00
|
|
|
}
|
|
|
|
|
2003-08-12 12:38:03 +03:00
|
|
|
Item *subs;
|
|
|
|
if (!select_lex->group_list.elements &&
|
2005-03-30 10:07:08 +03:00
|
|
|
!select_lex->having &&
|
2003-10-27 01:01:27 +02:00
|
|
|
!select_lex->with_sum_func &&
|
|
|
|
!(select_lex->next_select()))
|
2003-07-24 15:26:21 +03:00
|
|
|
{
|
2004-11-18 18:10:07 +02:00
|
|
|
Item_sum_hybrid *item;
|
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
mysql-test/r/func_gconcat.result:
Changed a query when fixing bug #12762.
mysql-test/r/subselect.result:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
mysql-test/t/func_gconcat.test:
Changed a query when fixing bug #12762.
mysql-test/t/subselect.test:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
sql/item.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
Changed Item_field::fix_fields to calculate attributes used when checking context conditions
for set functions.
Allowed alliases for set functions defined in outer subqueries.
sql/item.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_cmpfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_func.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_row.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_strfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_subselect.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/item_sum.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/item_sum.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/mysql_priv.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a type of bitmaps to be used for nesting constructs.
sql/sql_base.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_class.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_class.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_delete.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_lex.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_lex.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_parse.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
sql/sql_prepare.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showingin what subqueries a set function can be aggregated.
sql/sql_select.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_update.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_yacc.yy:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
2005-10-15 14:32:37 -07:00
|
|
|
nesting_map save_allow_sum_func;
|
2003-11-03 12:28:36 +02:00
|
|
|
if (func->l_op())
|
2003-08-12 12:38:03 +03:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
(ALL && (> || =>)) || (ANY && (< || =<))
|
|
|
|
for ALL condition is inverted
|
|
|
|
*/
|
|
|
|
item= new Item_sum_max(*select_lex->ref_pointer_array);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
(ALL && (< || =<)) || (ANY && (> || =>))
|
|
|
|
for ALL condition is inverted
|
|
|
|
*/
|
|
|
|
item= new Item_sum_min(*select_lex->ref_pointer_array);
|
|
|
|
}
|
2004-11-18 18:10:07 +02:00
|
|
|
if (upper_item)
|
|
|
|
upper_item->set_sum_test(item);
|
2003-08-12 12:38:03 +03:00
|
|
|
*select_lex->ref_pointer_array= item;
|
2004-05-07 23:06:11 +03:00
|
|
|
{
|
|
|
|
List_iterator<Item> it(select_lex->item_list);
|
|
|
|
it++;
|
|
|
|
it.replace(item);
|
|
|
|
}
|
2004-03-09 12:52:25 +02:00
|
|
|
|
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
mysql-test/r/func_gconcat.result:
Changed a query when fixing bug #12762.
mysql-test/r/subselect.result:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
mysql-test/t/func_gconcat.test:
Changed a query when fixing bug #12762.
mysql-test/t/subselect.test:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
sql/item.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
Changed Item_field::fix_fields to calculate attributes used when checking context conditions
for set functions.
Allowed alliases for set functions defined in outer subqueries.
sql/item.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_cmpfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_func.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_row.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_strfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_subselect.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/item_sum.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/item_sum.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/mysql_priv.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a type of bitmaps to be used for nesting constructs.
sql/sql_base.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_class.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_class.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_delete.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_lex.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_lex.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_parse.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
sql/sql_prepare.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showingin what subqueries a set function can be aggregated.
sql/sql_select.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_update.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_yacc.yy:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
2005-10-15 14:32:37 -07:00
|
|
|
save_allow_sum_func= thd->lex->allow_sum_func;
|
|
|
|
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
|
2004-05-07 23:06:11 +03:00
|
|
|
/*
|
|
|
|
Item_sum_(max|min) can't substitute other item => we can use 0 as
|
2005-02-09 02:50:45 +04:00
|
|
|
reference, also Item_sum_(max|min) can't be fixed after creation, so
|
|
|
|
we do not check item->fixed
|
2004-05-07 23:06:11 +03:00
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
if (item->fix_fields(thd, 0))
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
mysql-test/r/func_gconcat.result:
Changed a query when fixing bug #12762.
mysql-test/r/subselect.result:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
mysql-test/t/func_gconcat.test:
Changed a query when fixing bug #12762.
mysql-test/t/subselect.test:
Added test cases for bug #12762.
Allowed set functions aggregated in outer subqueries. Allowed nested set functions.
sql/item.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
Changed Item_field::fix_fields to calculate attributes used when checking context conditions
for set functions.
Allowed alliases for set functions defined in outer subqueries.
sql/item.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_cmpfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_func.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_row.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_strfunc.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added a parameter to Item::split_sum_func2 aliowing to defer splitting for set functions
aggregated in outer subquries.
sql/item_subselect.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/item_sum.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/item_sum.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Added Item_sum methods to check context conditions imposed on set functions.
sql/mysql_priv.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a type of bitmaps to be used for nesting constructs.
sql/sql_base.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_class.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_class.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_delete.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_lex.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_lex.h:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_parse.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
sql/sql_prepare.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showingin what subqueries a set function can be aggregated.
sql/sql_select.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries and a bitmap of nesting levels showing
in what subqueries a set function can be aggregated.
sql/sql_update.cc:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced a bitmap of nesting levels showing in what subqueries a set function can be aggregated.
sql/sql_yacc.yy:
Fixed bug #12762:
allowed set functions aggregated in outer subqueries, allowed nested set functions.
Introduced next levels for subqueries.
2005-10-15 14:32:37 -07:00
|
|
|
thd->lex->allow_sum_func= save_allow_sum_func;
|
2004-05-07 23:06:11 +03:00
|
|
|
/* we added aggregate function => we have to change statistic */
|
|
|
|
count_field_types(&join->tmp_table_param, join->all_fields, 0);
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2003-10-07 13:31:44 +03:00
|
|
|
subs= new Item_singlerow_subselect(select_lex);
|
2003-07-24 15:26:21 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-11-18 18:10:07 +02:00
|
|
|
Item_maxmin_subselect *item;
|
2004-12-22 13:54:39 +02:00
|
|
|
subs= item= new Item_maxmin_subselect(thd, this, select_lex, func->l_op());
|
2004-11-18 18:10:07 +02:00
|
|
|
if (upper_item)
|
|
|
|
upper_item->set_sub_test(item);
|
2003-07-24 15:26:21 +03:00
|
|
|
}
|
2005-03-10 14:01:22 +02:00
|
|
|
/* fix fields is already called for left expression */
|
2003-11-03 12:28:36 +02:00
|
|
|
substitution= func->create(left_expr, subs);
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_OK);
|
2003-07-24 15:26:21 +03:00
|
|
|
}
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
if (!substitution)
|
2002-10-27 23:27:00 +02:00
|
|
|
{
|
2003-05-14 21:51:33 +03:00
|
|
|
//first call for this unit
|
|
|
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
2005-03-10 14:01:22 +02:00
|
|
|
substitution= optimizer;
|
2003-05-14 21:51:33 +03:00
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
2003-07-03 02:30:52 +03:00
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
thd->lex->current_select= up= current->return_after_parsing();
|
2003-05-14 21:51:33 +03:00
|
|
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
2005-07-01 07:05:42 +03:00
|
|
|
if (!optimizer || optimizer->fix_left(thd, 0))
|
2002-12-23 18:25:25 +02:00
|
|
|
{
|
2004-02-08 20:14:13 +02:00
|
|
|
thd->lex->current_select= current;
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2002-12-23 18:25:25 +02:00
|
|
|
}
|
2004-02-08 20:14:13 +02:00
|
|
|
thd->lex->current_select= current;
|
2002-12-23 18:25:25 +02:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
/*
|
2005-02-09 02:50:45 +04:00
|
|
|
As far as Item_ref_in_optimizer do not substitute itself on fix_fields
|
2003-05-14 21:51:33 +03:00
|
|
|
we can use same item for all selects.
|
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
expr= new Item_direct_ref(&select_lex->context,
|
|
|
|
(Item**)optimizer->get_cache(),
|
2004-12-11 17:13:19 +02:00
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)in_left_expr_name);
|
2003-05-14 21:51:33 +03:00
|
|
|
|
2003-11-17 20:53:40 +02:00
|
|
|
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
2002-10-31 02:11:59 +02:00
|
|
|
|
2003-11-17 20:53:40 +02:00
|
|
|
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
2004-10-04 18:58:06 +04:00
|
|
|
/*
|
|
|
|
Add the left part of a subselect to a WHERE or HAVING clause of
|
|
|
|
the right part, e.g. SELECT 1 IN (SELECT a FROM t1) =>
|
|
|
|
SELECT Item_in_optimizer(1, SELECT a FROM t1 WHERE a=1)
|
|
|
|
HAVING is used only if the right part contains a SUM function, a GROUP
|
|
|
|
BY or a HAVING clause.
|
|
|
|
*/
|
2003-05-14 21:51:33 +03:00
|
|
|
if (join->having || select_lex->with_sum_func ||
|
|
|
|
select_lex->group_list.elements)
|
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
bool tmp;
|
|
|
|
Item *item= func->create(expr,
|
2005-07-01 07:05:42 +03:00
|
|
|
new Item_ref_null_helper(&select_lex->context,
|
|
|
|
this,
|
2004-09-06 15:14:10 +03:00
|
|
|
select_lex->
|
|
|
|
ref_pointer_array,
|
|
|
|
(char *)"<ref>",
|
|
|
|
this->full_name()));
|
2005-02-10 02:27:37 +02:00
|
|
|
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
subselect.result, subselect.test:
Added test cases for bug #7351.
item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
mysql-test/t/subselect.test:
Added test cases for bug #7351.
mysql-test/r/subselect.result:
Added test cases for bug #7351.
2004-12-25 19:17:57 -08:00
|
|
|
if (!abort_on_null && left_expr->maybe_null)
|
|
|
|
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
|
2005-02-10 02:27:37 +02:00
|
|
|
#endif
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
|
|
|
AND and comparison functions can't be changed during fix_fields()
|
|
|
|
we can assign select_lex->having here, and pass 0 as last
|
|
|
|
argument (reference) to fix_fields()
|
|
|
|
*/
|
2004-02-08 20:14:13 +02:00
|
|
|
select_lex->having= join->having= and_items(join->having, item);
|
2003-05-14 21:51:33 +03:00
|
|
|
select_lex->having_fix_field= 1;
|
2005-02-09 02:50:45 +04:00
|
|
|
/*
|
|
|
|
we do not check join->having->fixed, because Item_and (from and_items)
|
|
|
|
or comparison function (from func->create) can't be fixed after creation
|
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
tmp= join->having->fix_fields(thd, 0);
|
2003-05-14 21:51:33 +03:00
|
|
|
select_lex->having_fix_field= 0;
|
2004-09-06 15:14:10 +03:00
|
|
|
if (tmp)
|
2005-03-31 10:39:48 +03:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
Item *item= (Item*) select_lex->item_list.head();
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
select_lex->item_list.empty();
|
|
|
|
select_lex->item_list.push_back(new Item_int("Not_used",
|
|
|
|
(longlong) 1, 21));
|
|
|
|
select_lex->ref_pointer_array[0]= select_lex->item_list.head();
|
|
|
|
if (select_lex->table_list.elements)
|
2002-10-31 02:11:59 +02:00
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
bool tmp;
|
2004-02-02 02:23:53 +02:00
|
|
|
Item *having= item, *orig_item= item;
|
2003-11-03 12:28:36 +02:00
|
|
|
item= func->create(expr, item);
|
2004-02-02 02:23:53 +02:00
|
|
|
if (!abort_on_null && orig_item->maybe_null)
|
2002-11-28 19:29:26 +02:00
|
|
|
{
|
2003-05-14 21:51:33 +03:00
|
|
|
having= new Item_is_not_null_test(this, having);
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
|
|
|
Item_is_not_null_test can't be changed during fix_fields()
|
|
|
|
we can assign select_lex->having here, and pass 0 as last
|
|
|
|
argument (reference) to fix_fields()
|
|
|
|
*/
|
2004-02-08 20:14:13 +02:00
|
|
|
select_lex->having=
|
|
|
|
join->having= (join->having ?
|
|
|
|
new Item_cond_and(having, join->having) :
|
|
|
|
having);
|
2003-05-14 21:51:33 +03:00
|
|
|
select_lex->having_fix_field= 1;
|
2005-02-09 02:50:45 +04:00
|
|
|
/*
|
|
|
|
we do not check join->having->fixed, because Item_and (from
|
|
|
|
and_items) or comparison function (from func->create) can't be
|
|
|
|
fixed after creation
|
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
tmp= join->having->fix_fields(thd, 0);
|
2004-09-06 15:14:10 +03:00
|
|
|
select_lex->having_fix_field= 0;
|
|
|
|
if (tmp)
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-05-14 21:51:33 +03:00
|
|
|
item= new Item_cond_or(item,
|
2004-02-02 02:23:53 +02:00
|
|
|
new Item_func_isnull(orig_item));
|
2005-02-10 02:27:37 +02:00
|
|
|
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
subselect.result, subselect.test:
Added test cases for bug #7351.
item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
mysql-test/t/subselect.test:
Added test cases for bug #7351.
mysql-test/r/subselect.result:
Added test cases for bug #7351.
2004-12-25 19:17:57 -08:00
|
|
|
if (left_expr->maybe_null)
|
|
|
|
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
|
2005-02-10 02:27:37 +02:00
|
|
|
#endif
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
2003-09-08 21:58:09 +03:00
|
|
|
item->name= (char *)in_additional_cond;
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
|
|
|
AND can't be changed during fix_fields()
|
|
|
|
we can assign select_lex->having here, and pass 0 as last
|
|
|
|
argument (reference) to fix_fields()
|
|
|
|
*/
|
2004-02-08 20:14:13 +02:00
|
|
|
select_lex->where= join->conds= and_items(join->conds, item);
|
2005-08-13 07:45:14 +03:00
|
|
|
select_lex->where->top_level_item();
|
2005-02-09 02:50:45 +04:00
|
|
|
/*
|
|
|
|
we do not check join->conds->fixed, because Item_and can't be fixed
|
|
|
|
after creation
|
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
if (join->conds->fix_fields(thd, 0))
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
bool tmp;
|
2003-05-14 21:51:33 +03:00
|
|
|
if (select_lex->master_unit()->first_select()->next_select())
|
|
|
|
{
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
|
|
|
comparison functions can't be changed during fix_fields()
|
|
|
|
we can assign select_lex->having here, and pass 0 as last
|
|
|
|
argument (reference) to fix_fields()
|
2005-07-01 07:05:42 +03:00
|
|
|
*/
|
|
|
|
item= func->create(expr,
|
|
|
|
new Item_null_helper(&select_lex->context,
|
|
|
|
this, item,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<result>"));
|
2005-02-10 02:27:37 +02:00
|
|
|
#ifdef CORRECT_BUT_TOO_SLOW_TO_BE_USABLE
|
subselect.result, subselect.test:
Added test cases for bug #7351.
item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_subselect.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
The problem was due to not a quite legal transformation
for 'IN' subqueries. A subquery containing a predicate
of the form
v IN (SELECT a FROM t WHERE cond)
was transformed into
EXISTS(SELECT a FROM t WHERE cond AND (a=v OR a IS NULL)).
Yet, this transformation is valid only if v is not null.
If v is null, then, in the case when
(SELECT a FROM t WHERE cond) returns an empty set the value
of the predicate is FALSE, otherwise the result of the
predicate is INKNOWN.
The fix resolves this problem by changing the result
of the transformation to
EXISTS(SELECT a FROM t WHERE cond AND (v IS NULL OR (a=v OR a IS NULL)))
in the case when v is nullable.
The new transformation prevents applying the lookup
optimization for IN subqueries. To make it still
applicable we have to introduce guarded access methods.
sql/item_cmpfunc.cc:
Fixed bug #7351: incorrect result for a query with a
subquery returning empty set.
If in the predicate v IN (SELECT a FROM t WHERE cond)
v is null, then the result of the predicate is either
INKNOWN or FALSE. It is FALSE if the subquery returns
an empty set.
mysql-test/t/subselect.test:
Added test cases for bug #7351.
mysql-test/r/subselect.result:
Added test cases for bug #7351.
2004-12-25 19:17:57 -08:00
|
|
|
if (!abort_on_null && left_expr->maybe_null)
|
|
|
|
item= new Item_cond_or(new Item_func_isnull(left_expr), item);
|
2005-02-10 02:27:37 +02:00
|
|
|
#endif
|
2005-07-01 07:05:42 +03:00
|
|
|
select_lex->having= join->having= item;
|
2003-05-14 21:51:33 +03:00
|
|
|
select_lex->having_fix_field= 1;
|
2005-02-09 02:50:45 +04:00
|
|
|
/*
|
|
|
|
we do not check join->having->fixed, because comparison function
|
|
|
|
(from func->create) can't be fixed after creation
|
|
|
|
*/
|
2005-07-01 07:05:42 +03:00
|
|
|
tmp= join->having->fix_fields(thd, 0);
|
2004-09-06 15:14:10 +03:00
|
|
|
select_lex->having_fix_field= 0;
|
|
|
|
if (tmp)
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// it is single select without tables => possible optimization
|
2003-11-03 12:28:36 +02:00
|
|
|
item= func->create(left_expr, item);
|
2004-07-20 15:34:57 +02:00
|
|
|
// fix_field of item will be done in time of substituting
|
2003-05-14 21:51:33 +03:00
|
|
|
substitution= item;
|
|
|
|
have_to_be_excluded= 1;
|
2004-02-08 20:14:13 +02:00
|
|
|
if (thd->lex->describe)
|
2002-11-28 19:29:26 +02:00
|
|
|
{
|
2003-05-14 21:51:33 +03:00
|
|
|
char warn_buff[MYSQL_ERRMSG_SIZE];
|
|
|
|
sprintf(warn_buff, ER(ER_SELECT_REDUCED), select_lex->select_number);
|
2004-02-08 20:14:13 +02:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
2003-05-14 21:51:33 +03:00
|
|
|
ER_SELECT_REDUCED, warn_buff);
|
2002-11-28 19:29:26 +02:00
|
|
|
}
|
2003-08-28 13:21:30 +03:00
|
|
|
DBUG_RETURN(RES_REDUCE);
|
2002-11-28 19:29:26 +02:00
|
|
|
}
|
2002-10-31 02:11:59 +02:00
|
|
|
}
|
2002-10-27 23:27:00 +02:00
|
|
|
}
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2003-08-28 13:21:30 +03:00
|
|
|
DBUG_RETURN(RES_OK);
|
2002-10-27 23:27:00 +02:00
|
|
|
}
|
2002-09-03 09:50:36 +03:00
|
|
|
|
2003-11-28 12:18:13 +02:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2003-11-02 17:27:35 +02:00
|
|
|
Item_in_subselect::row_value_transformer(JOIN *join)
|
2002-12-19 21:15:09 +02:00
|
|
|
{
|
2004-09-06 15:14:10 +03:00
|
|
|
SELECT_LEX *select_lex= join->select_lex;
|
2005-08-13 07:45:14 +03:00
|
|
|
Item *having_item= 0;
|
|
|
|
uint cols_num= left_expr->cols();
|
|
|
|
bool is_having_used= (join->having || select_lex->with_sum_func ||
|
|
|
|
select_lex->group_list.first ||
|
|
|
|
!select_lex->table_list.elements);
|
2002-12-19 21:15:09 +02:00
|
|
|
DBUG_ENTER("Item_in_subselect::row_value_transformer");
|
2002-12-31 18:39:16 +02:00
|
|
|
|
2003-10-23 23:54:21 +03:00
|
|
|
if (select_lex->item_list.elements != left_expr->cols())
|
|
|
|
{
|
|
|
|
my_error(ER_OPERAND_COLUMNS, MYF(0), left_expr->cols());
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2003-10-23 23:54:21 +03:00
|
|
|
}
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
if (!substitution)
|
2002-12-19 21:15:09 +02:00
|
|
|
{
|
2003-05-14 21:51:33 +03:00
|
|
|
//first call for this unit
|
|
|
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
2005-03-10 14:01:22 +02:00
|
|
|
substitution= optimizer;
|
2003-05-14 21:51:33 +03:00
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
|
|
|
thd->lex->current_select= up= current->return_after_parsing();
|
2003-05-14 21:51:33 +03:00
|
|
|
//optimizer never use Item **ref => we can pass 0 as parameter
|
2005-07-01 07:05:42 +03:00
|
|
|
if (!optimizer || optimizer->fix_left(thd, 0))
|
2002-12-25 12:03:08 +02:00
|
|
|
{
|
2004-02-08 20:14:13 +02:00
|
|
|
thd->lex->current_select= current;
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2002-12-25 12:03:08 +02:00
|
|
|
}
|
2004-02-12 03:10:26 +02:00
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
// we will refer to upper level cache array => we have to save it in PS
|
2004-02-12 03:10:26 +02:00
|
|
|
optimizer->keep_top_level_cache();
|
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
thd->lex->current_select= current;
|
2003-11-17 20:53:40 +02:00
|
|
|
unit->uncacheable|= UNCACHEABLE_DEPENDENT;
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
|
|
|
|
2003-11-17 20:53:40 +02:00
|
|
|
select_lex->uncacheable|= UNCACHEABLE_DEPENDENT;
|
2005-08-13 07:45:14 +03:00
|
|
|
if (is_having_used)
|
2004-02-08 20:14:13 +02:00
|
|
|
{
|
2005-08-13 07:45:14 +03:00
|
|
|
/*
|
|
|
|
(l1, l2, l3) IN (SELECT v1, v2, v3 ... HAVING having) =>
|
|
|
|
EXISTS (SELECT ... HAVING having and
|
|
|
|
(l1 = v1 or is null v1) and
|
|
|
|
(l2 = v2 or is null v2) and
|
|
|
|
(l3 = v3 or is null v3) and
|
|
|
|
is_not_null_test(v1) and
|
|
|
|
is_not_null_test(v2) and
|
|
|
|
is_not_null_test(v3))
|
|
|
|
where is_not_null_test used to register nulls in case if we have
|
|
|
|
not found matching to return correct NULL value
|
|
|
|
*/
|
|
|
|
Item *item_having_part2= 0;
|
|
|
|
for (uint i= 0; i < cols_num; i++)
|
2004-02-08 20:14:13 +02:00
|
|
|
{
|
2005-01-24 15:56:57 +02:00
|
|
|
DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed);
|
|
|
|
if (select_lex->ref_pointer_array[i]->
|
|
|
|
check_cols(left_expr->el(i)->cols()))
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2005-08-13 07:45:14 +03:00
|
|
|
Item *item_eq=
|
|
|
|
new Item_func_eq(new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
(*optimizer->get_cache())->
|
2005-08-13 07:45:14 +03:00
|
|
|
addr(i),
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)in_left_expr_name),
|
|
|
|
new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->ref_pointer_array + i,
|
2005-08-13 07:45:14 +03:00
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
|
|
|
);
|
|
|
|
Item *item_isnull=
|
|
|
|
new Item_func_isnull(new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->
|
|
|
|
ref_pointer_array+i,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
2005-08-13 07:45:14 +03:00
|
|
|
);
|
|
|
|
having_item=
|
|
|
|
and_items(having_item,
|
|
|
|
new Item_cond_or(item_eq, item_isnull));
|
|
|
|
item_having_part2=
|
|
|
|
and_items(item_having_part2,
|
|
|
|
new
|
|
|
|
Item_is_not_null_test(this,
|
|
|
|
new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->
|
2005-08-13 07:45:14 +03:00
|
|
|
ref_pointer_array + i,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
|
|
|
)
|
|
|
|
);
|
|
|
|
item_having_part2->top_level_item();
|
2004-02-08 20:14:13 +02:00
|
|
|
}
|
2005-08-13 07:45:14 +03:00
|
|
|
having_item= and_items(having_item, item_having_part2);
|
|
|
|
having_item->top_level_item();
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
2005-08-13 07:45:14 +03:00
|
|
|
else
|
2003-05-14 21:51:33 +03:00
|
|
|
{
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
2005-08-13 07:45:14 +03:00
|
|
|
(l1, l2, l3) IN (SELECT v1, v2, v3 ... WHERE where) =>
|
|
|
|
EXISTS (SELECT ... WHERE where and
|
|
|
|
(l1 = v1 or is null v1) and
|
|
|
|
(l2 = v2 or is null v2) and
|
|
|
|
(l3 = v3 or is null v3)
|
|
|
|
HAVING is_not_null_test(v1) and
|
|
|
|
is_not_null_test(v2) and
|
|
|
|
is_not_null_test(v3))
|
|
|
|
where is_not_null_test register NULLs values but reject rows
|
|
|
|
|
|
|
|
in case when we do not need correct NULL, we have simplier construction:
|
|
|
|
EXISTS (SELECT ... WHERE where and
|
|
|
|
(l1 = v1) and
|
|
|
|
(l2 = v2) and
|
|
|
|
(l3 = v3)
|
2004-02-18 22:14:41 +02:00
|
|
|
*/
|
2005-08-13 07:45:14 +03:00
|
|
|
Item *where_item= 0;
|
|
|
|
for (uint i= 0; i < cols_num; i++)
|
|
|
|
{
|
|
|
|
Item *item, *item_isnull;
|
|
|
|
DBUG_ASSERT(left_expr->fixed && select_lex->ref_pointer_array[i]->fixed);
|
|
|
|
if (select_lex->ref_pointer_array[i]->
|
|
|
|
check_cols(left_expr->el(i)->cols()))
|
|
|
|
DBUG_RETURN(RES_ERROR);
|
|
|
|
item=
|
|
|
|
new Item_func_eq(new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
(*optimizer->get_cache())->
|
2005-08-13 07:45:14 +03:00
|
|
|
addr(i),
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)in_left_expr_name),
|
|
|
|
new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->
|
|
|
|
ref_pointer_array+i,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
2005-08-13 07:45:14 +03:00
|
|
|
);
|
|
|
|
if (!abort_on_null)
|
|
|
|
{
|
|
|
|
having_item=
|
|
|
|
and_items(having_item,
|
|
|
|
new
|
|
|
|
Item_is_not_null_test(this,
|
|
|
|
new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->
|
2005-08-13 07:45:14 +03:00
|
|
|
ref_pointer_array + i,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
|
|
|
)
|
|
|
|
);
|
|
|
|
item_isnull= new
|
|
|
|
Item_func_isnull(new
|
2005-08-13 11:15:17 +03:00
|
|
|
Item_direct_ref(&select_lex->context,
|
|
|
|
select_lex->
|
|
|
|
ref_pointer_array+i,
|
|
|
|
(char *)"<no matter>",
|
|
|
|
(char *)"<list ref>")
|
2005-08-13 07:45:14 +03:00
|
|
|
);
|
|
|
|
|
|
|
|
item= new Item_cond_or(item, item_isnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
where_item= and_items(where_item, item);
|
|
|
|
}
|
2005-02-09 02:50:45 +04:00
|
|
|
/*
|
2004-02-18 22:14:41 +02:00
|
|
|
AND can't be changed during fix_fields()
|
2005-08-13 07:45:14 +03:00
|
|
|
we can assign select_lex->where here, and pass 0 as last
|
2004-02-18 22:14:41 +02:00
|
|
|
argument (reference) to fix_fields()
|
2005-02-09 02:50:45 +04:00
|
|
|
*/
|
2005-08-13 07:45:14 +03:00
|
|
|
select_lex->where= join->conds= and_items(join->conds, where_item);
|
|
|
|
select_lex->where->top_level_item();
|
2005-08-13 08:19:34 +03:00
|
|
|
if (join->conds->fix_fields(thd, 0))
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2002-12-19 21:15:09 +02:00
|
|
|
}
|
2005-08-13 07:45:14 +03:00
|
|
|
if (having_item)
|
2003-05-14 21:51:33 +03:00
|
|
|
{
|
2005-08-13 07:45:14 +03:00
|
|
|
bool res;
|
|
|
|
select_lex->having= join->having= and_items(join->having, having_item);
|
|
|
|
select_lex->having->top_level_item();
|
2004-02-18 22:14:41 +02:00
|
|
|
/*
|
|
|
|
AND can't be changed during fix_fields()
|
|
|
|
we can assign select_lex->having here, and pass 0 as last
|
|
|
|
argument (reference) to fix_fields()
|
|
|
|
*/
|
2005-08-13 07:45:14 +03:00
|
|
|
select_lex->having_fix_field= 1;
|
2005-08-13 08:19:34 +03:00
|
|
|
res= join->having->fix_fields(thd, 0);
|
2005-08-13 07:45:14 +03:00
|
|
|
select_lex->having_fix_field= 0;
|
|
|
|
if (res)
|
|
|
|
{
|
2005-03-10 14:01:22 +02:00
|
|
|
DBUG_RETURN(RES_ERROR);
|
2005-08-13 07:45:14 +03:00
|
|
|
}
|
2003-05-14 21:51:33 +03:00
|
|
|
}
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2003-08-28 13:21:30 +03:00
|
|
|
DBUG_RETURN(RES_OK);
|
2002-12-19 21:15:09 +02:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2003-07-02 01:45:22 +03:00
|
|
|
Item_in_subselect::select_transformer(JOIN *join)
|
2002-11-07 23:45:19 +02:00
|
|
|
{
|
2005-03-10 14:01:22 +02:00
|
|
|
return select_in_like_transformer(join, &eq_creator);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Prepare IN/ALL/ANY/SOME subquery transformation and call appropriate
|
|
|
|
transformation function
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
Item_in_subselect::select_in_like_transformer()
|
|
|
|
join JOIN object of transforming subquery
|
|
|
|
func creator of condition function of subquery
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
To decide which transformation procedure (scalar or row) applicable here
|
|
|
|
we have to call fix_fields() for left expression to be able to call
|
|
|
|
cols() method on it. Also this method make arena management for
|
|
|
|
underlying transformation methods.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
RES_OK OK
|
|
|
|
RES_REDUCE OK, and current subquery was reduced during transformation
|
|
|
|
RES_ERROR Error
|
|
|
|
*/
|
|
|
|
|
|
|
|
Item_subselect::trans_res
|
|
|
|
Item_in_subselect::select_in_like_transformer(JOIN *join, Comp_creator *func)
|
|
|
|
{
|
2005-06-15 19:58:35 +02:00
|
|
|
Query_arena *arena, backup;
|
2005-03-10 14:01:22 +02:00
|
|
|
SELECT_LEX *current= thd->lex->current_select, *up;
|
|
|
|
const char *save_where= thd->where;
|
|
|
|
Item_subselect::trans_res res= RES_ERROR;
|
|
|
|
bool result;
|
|
|
|
|
|
|
|
DBUG_ENTER("Item_in_subselect::select_in_like_transformer");
|
2005-03-30 10:07:08 +03:00
|
|
|
|
2005-03-10 14:01:22 +02:00
|
|
|
if (changed)
|
|
|
|
{
|
|
|
|
DBUG_RETURN(RES_OK);
|
|
|
|
}
|
|
|
|
|
|
|
|
thd->where= "IN/ALL/ANY subquery";
|
|
|
|
|
|
|
|
/*
|
|
|
|
In some optimisation cases we will not need this Item_in_optimizer
|
|
|
|
object, but we can't know it here, but here we need address correct
|
|
|
|
reference on left expresion.
|
|
|
|
*/
|
|
|
|
if (!optimizer)
|
|
|
|
{
|
2005-09-02 17:21:19 +04:00
|
|
|
arena= thd->activate_stmt_arena_if_needed(&backup);
|
2005-03-10 14:01:22 +02:00
|
|
|
result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
|
|
|
|
if (arena)
|
2005-09-02 17:21:19 +04:00
|
|
|
thd->restore_active_arena(arena, &backup);
|
2005-03-10 14:01:22 +02:00
|
|
|
if (result)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
thd->lex->current_select= up= current->return_after_parsing();
|
|
|
|
result= (!left_expr->fixed &&
|
2005-07-01 07:05:42 +03:00
|
|
|
left_expr->fix_fields(thd, optimizer->arguments()));
|
2005-03-10 14:01:22 +02:00
|
|
|
/* fix_fields can change reference to left_expr, we need reassign it */
|
|
|
|
left_expr= optimizer->arguments()[0];
|
|
|
|
|
|
|
|
thd->lex->current_select= current;
|
|
|
|
if (result)
|
|
|
|
goto err;
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
transformed= 1;
|
2005-09-02 17:21:19 +04:00
|
|
|
arena= thd->activate_stmt_arena_if_needed(&backup);
|
2005-03-10 14:01:22 +02:00
|
|
|
/*
|
|
|
|
Both transformers call fix_fields() only for Items created inside them,
|
|
|
|
and all that items do not make permanent changes in current item arena
|
|
|
|
which allow to us call them with changed arena (if we do not know nature
|
|
|
|
of Item, we have to call fix_fields() for it only with original arena to
|
|
|
|
avoid memory leack)
|
|
|
|
*/
|
2002-12-19 21:15:09 +02:00
|
|
|
if (left_expr->cols() == 1)
|
2005-03-10 14:01:22 +02:00
|
|
|
res= single_value_transformer(join, func);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* we do not support row operation for ALL/ANY/SOME */
|
|
|
|
if (func != &eq_creator)
|
|
|
|
{
|
2005-03-30 10:07:08 +03:00
|
|
|
if (arena)
|
2005-09-02 17:21:19 +04:00
|
|
|
thd->restore_active_arena(arena, &backup);
|
2005-03-10 14:01:22 +02:00
|
|
|
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
|
|
|
|
DBUG_RETURN(RES_ERROR);
|
|
|
|
}
|
|
|
|
res= row_value_transformer(join);
|
|
|
|
}
|
|
|
|
if (arena)
|
2005-09-02 17:21:19 +04:00
|
|
|
thd->restore_active_arena(arena, &backup);
|
2005-03-10 14:01:22 +02:00
|
|
|
err:
|
|
|
|
thd->where= save_where;
|
|
|
|
DBUG_RETURN(res);
|
2002-11-07 23:45:19 +02:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
void Item_in_subselect::print(String *str)
|
|
|
|
{
|
|
|
|
if (transformed)
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN("<exists>"));
|
2003-10-16 15:54:47 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
left_expr->print(str);
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" in "));
|
2003-10-16 15:54:47 +03:00
|
|
|
}
|
|
|
|
Item_subselect::print(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-05-14 21:51:33 +03:00
|
|
|
Item_subselect::trans_res
|
2003-07-02 01:45:22 +03:00
|
|
|
Item_allany_subselect::select_transformer(JOIN *join)
|
2002-11-07 23:45:19 +02:00
|
|
|
{
|
2003-10-16 15:54:47 +03:00
|
|
|
transformed= 1;
|
2004-11-18 18:10:07 +02:00
|
|
|
if (upper_item)
|
|
|
|
upper_item->show= 1;
|
2005-03-10 14:01:22 +02:00
|
|
|
return select_in_like_transformer(join, func);
|
2002-11-07 23:45:19 +02:00
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
|
|
|
void Item_allany_subselect::print(String *str)
|
|
|
|
{
|
|
|
|
if (transformed)
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN("<exists>"));
|
2003-10-16 15:54:47 +03:00
|
|
|
else
|
|
|
|
{
|
|
|
|
left_expr->print(str);
|
|
|
|
str->append(' ');
|
2003-11-03 12:28:36 +02:00
|
|
|
str->append(func->symbol(all));
|
|
|
|
str->append(all ? " all " : " any ", 5);
|
2003-10-16 15:54:47 +03:00
|
|
|
}
|
|
|
|
Item_subselect::print(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-10 00:23:56 +04:00
|
|
|
void subselect_engine::set_thd(THD *thd_arg)
|
|
|
|
{
|
|
|
|
thd= thd_arg;
|
|
|
|
if (result)
|
|
|
|
result->set_thd(thd_arg);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-24 15:26:21 +03:00
|
|
|
subselect_single_select_engine::
|
2003-10-02 22:19:41 +03:00
|
|
|
subselect_single_select_engine(st_select_lex *select,
|
|
|
|
select_subselect *result,
|
|
|
|
Item_subselect *item)
|
|
|
|
:subselect_engine(item, result),
|
2005-05-30 20:54:37 +04:00
|
|
|
prepared(0), optimized(0), executed(0),
|
|
|
|
select_lex(select), join(0)
|
2002-09-03 09:50:36 +03:00
|
|
|
{
|
2005-05-30 20:54:37 +04:00
|
|
|
select_lex->master_unit()->item= item;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2003-12-30 14:08:19 +04:00
|
|
|
void subselect_single_select_engine::cleanup()
|
|
|
|
{
|
2004-02-08 20:14:13 +02:00
|
|
|
DBUG_ENTER("subselect_single_select_engine::cleanup");
|
|
|
|
prepared= optimized= executed= 0;
|
2004-02-12 03:10:26 +02:00
|
|
|
join= 0;
|
2005-01-26 15:27:45 +02:00
|
|
|
result->cleanup();
|
2004-02-08 20:14:13 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2003-12-30 14:08:19 +04:00
|
|
|
}
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
|
|
|
|
void subselect_union_engine::cleanup()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("subselect_union_engine::cleanup");
|
|
|
|
unit->reinit_exec_mechanism();
|
2005-01-26 15:27:45 +02:00
|
|
|
result->cleanup();
|
2004-02-08 20:14:13 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2003-12-30 14:08:19 +04:00
|
|
|
}
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
|
2005-10-13 11:53:00 +04:00
|
|
|
bool subselect_union_engine::is_executed() const
|
|
|
|
{
|
|
|
|
return unit->executed;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-08 20:14:13 +02:00
|
|
|
void subselect_uniquesubquery_engine::cleanup()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("subselect_uniquesubquery_engine::cleanup");
|
2005-01-26 15:27:45 +02:00
|
|
|
/*
|
|
|
|
subselect_uniquesubquery_engine have not 'result' assigbed, so we do not
|
|
|
|
cleanup() it
|
|
|
|
*/
|
2004-02-08 20:14:13 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-02 22:19:41 +03:00
|
|
|
subselect_union_engine::subselect_union_engine(st_select_lex_unit *u,
|
2003-11-28 12:18:13 +02:00
|
|
|
select_subselect *result_arg,
|
|
|
|
Item_subselect *item_arg)
|
|
|
|
:subselect_engine(item_arg, result_arg)
|
2002-09-03 09:50:36 +03:00
|
|
|
{
|
|
|
|
unit= u;
|
2003-11-28 12:18:13 +02:00
|
|
|
if (!result_arg) //out of memory
|
2003-10-02 22:19:41 +03:00
|
|
|
current_thd->fatal_error();
|
2003-11-28 12:18:13 +02:00
|
|
|
unit->item= item_arg;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-11-28 12:18:13 +02:00
|
|
|
|
2002-09-03 09:50:36 +03:00
|
|
|
int subselect_single_select_engine::prepare()
|
|
|
|
{
|
2002-10-13 14:25:16 +03:00
|
|
|
if (prepared)
|
|
|
|
return 0;
|
2003-12-10 22:46:14 +02:00
|
|
|
join= new JOIN(thd, select_lex->item_list,
|
|
|
|
select_lex->options | SELECT_NO_UNLOCK, result);
|
2003-10-02 22:19:41 +03:00
|
|
|
if (!join || !result)
|
|
|
|
{
|
2003-11-28 12:18:13 +02:00
|
|
|
thd->fatal_error(); //out of memory
|
2003-10-02 22:19:41 +03:00
|
|
|
return 1;
|
|
|
|
}
|
2002-10-13 14:25:16 +03:00
|
|
|
prepared= 1;
|
2003-12-19 20:52:13 +03:00
|
|
|
SELECT_LEX *save_select= thd->lex->current_select;
|
|
|
|
thd->lex->current_select= select_lex;
|
2003-01-25 13:19:46 +02:00
|
|
|
if (join->prepare(&select_lex->ref_pointer_array,
|
|
|
|
(TABLE_LIST*) select_lex->table_list.first,
|
|
|
|
select_lex->with_wild,
|
2002-12-28 01:01:05 +02:00
|
|
|
select_lex->where,
|
2003-01-25 13:19:46 +02:00
|
|
|
select_lex->order_list.elements +
|
|
|
|
select_lex->group_list.elements,
|
2002-12-28 01:01:05 +02:00
|
|
|
(ORDER*) select_lex->order_list.first,
|
|
|
|
(ORDER*) select_lex->group_list.first,
|
|
|
|
select_lex->having,
|
2004-07-04 08:46:28 +03:00
|
|
|
(ORDER*) 0, select_lex,
|
2003-11-23 02:01:15 +02:00
|
|
|
select_lex->master_unit()))
|
2002-09-03 09:50:36 +03:00
|
|
|
return 1;
|
2003-12-19 20:52:13 +03:00
|
|
|
thd->lex->current_select= save_select;
|
2002-09-03 09:50:36 +03:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int subselect_union_engine::prepare()
|
|
|
|
{
|
A fix and a test case for Bug#6513 "Test Suite: Values inserted by using
cursor is interpreted latin1 character and Bug#9819 "Cursors: Mysql Server
Crash while fetching from table with 5 million records."
A fix for a possible memory leak when fetching into an SP cursor
in a long loop.
The patch uses a common implementation of cursors in the binary protocol and
in stored procedures and implements materialized cursors.
For implementation details, see comments in sql_cursor.cc
include/my_sys.h:
- declaration for multi_alloc_root
libmysqld/Makefile.am:
- drop protocol_cursor.cc, add sql_cursor.cc (replaces the old
implementation of cursors with a new one)
mysql-test/r/ctype_ujis.result:
- test results fixed (a test case for Bug#6513)
mysql-test/r/sp-big.result:
- test results fixed (a test case for Bug#9819)
mysql-test/t/ctype_ujis.test:
Add a test case for Bug#6513 "Test Suite: Values inserted by using cursor is
interpreted latin1 character"
mysql-test/t/sp-big.test:
Add a restricted test case for Bug#9819 "Cursors: Mysql Server Crash
while fetching from table with 5 million records."
mysys/my_alloc.c:
- an implementation of multi_alloc_root; this is largely a copy-paste
from mulalloc.c, but the function is small and there is no easy way
to reuse the existing C function.
sql/Makefile.am:
- add sql_cursor.h, sql_cursor.cc (a new implementation of stored procedure
cursors) and drop protocol_cursor.cc (the old one)
sql/handler.cc:
- now TABLE object has its mem_root always initialized.
Adjust the implementation handler::ha_open
sql/item_subselect.cc:
- adjust to the changed declaration of st_select_lex_unit::prepare
sql/protocol.h:
- drop Protocol_cursor
sql/sp_head.cc:
- move juggling with Query_arena::free_list and Item::next to
sp_eval_func_item, as this is needed in 3 places already.
sql/sp_head.h:
- declare a no-op implementation for cleanup_stmt in sp_instr_cpush.
This method is needed for non-materializing cursors, which are yet not
used in stored procedures.
- declaration for sp_eval_func_item
sql/sp_rcontext.cc:
- reimplement sp_cursor using the new implementation of server side cursors.
- use sp_eval_func_item to assign values of SP variables from the
row fetched from a cursor. This should fix a possible memory leak in
the old implementation of sp_cursor::fetch
sql/sp_rcontext.h:
- reimplement sp_cursor using the new implementation of server side cursors.
sql/sql_class.cc:
- disable the functionality that closes transient cursors at commit/rollback;
transient cursors are not used in 5.0, instead we use materialized ones.
To be enabled in a later version.
sql/sql_class.h:
- adjust to the rename Cursor -> Server_side_cursor
- additional declarations of select_union used in materialized cursors
sql/sql_derived.cc:
- reuse bits of tmp table code in UNION, derived tables, and materialized
cursors
- cleanup comments
sql/sql_lex.h:
- declarations of auxiliary methods used by materialized cursors
- a cleanup in st_select_lex_unit interface
sql/sql_list.h:
- add an array operator new[] to class Sql_alloc
sql/sql_prepare.cc:
- split the tight coupling of cursors and prepared statements to reuse
the same implementation in stored procedures
- cleanups of error processing in Prepared_statement::{prepare,execute}
sql/sql_select.cc:
- move the implementation of sensitive (non-materializing) cursors to
sql_cursor.cc
- make temporary tables self-contained: the table, its record and fields
are allocated in TABLE::mem_root. This implementation is not clean
and resets thd->mem_root several times because of the way create_tmp_table
works (many additional things are done inside it).
- adjust to the changed declaration of st_select_lex_unit::prepare
sql/sql_select.h:
- move the declaration of sensitive (non-materializing) cursors to
sql_cursor.cc
sql/sql_union.cc:
- move pieces of st_select_unit::prepare to select_union and st_table
methods to be able to reuse code in the implementation of materialized
cursors
sql/sql_view.cc:
- adjust to the changed signature of st_select_lex_unit::prepare
sql/table.cc:
- implement auxiliary st_table methods for use with temporary tables
sql/table.h:
- add declarations for auxiliary methods of st_table used to work with
temporary tables
tests/mysql_client_test.c:
- if cursors are materialized, a parallel update of the table used
in the cursor may go through: update the test.
sql/sql_cursor.cc:
New BitKeeper file ``sql/sql_cursor.cc'' -- implementation of server side
cursors
sql/sql_cursor.h:
New BitKeeper file ``sql/sql_cursor.h'' - declarations for
server side cursors.
2005-09-22 02:11:21 +04:00
|
|
|
return unit->prepare(thd, result, SELECT_NO_UNLOCK);
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-09-14 09:40:57 +03:00
|
|
|
int subselect_uniquesubquery_engine::prepare()
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
|
|
|
//this never should be called
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2003-11-23 02:01:15 +02:00
|
|
|
static Item_result set_row(List<Item> &item_list, Item *item,
|
2002-12-27 21:19:25 +02:00
|
|
|
Item_cache **row, bool *maybe_null)
|
2002-09-28 18:34:56 +03:00
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
Item_result res_type= STRING_RESULT;
|
|
|
|
Item *sel_item;
|
2003-11-23 02:01:15 +02:00
|
|
|
List_iterator_fast<Item> li(item_list);
|
2002-12-19 07:38:33 +02:00
|
|
|
for (uint i= 0; (sel_item= li++); i++)
|
|
|
|
{
|
|
|
|
item->max_length= sel_item->max_length;
|
|
|
|
res_type= sel_item->result_type();
|
|
|
|
item->decimals= sel_item->decimals;
|
2002-12-27 21:19:25 +02:00
|
|
|
*maybe_null= sel_item->maybe_null;
|
2003-12-25 18:50:22 +04:00
|
|
|
if (!(row[i]= Item_cache::get_cache(res_type)))
|
|
|
|
return STRING_RESULT; // we should return something
|
|
|
|
row[i]->setup(sel_item);
|
2002-12-19 07:38:33 +02:00
|
|
|
}
|
2003-11-23 02:01:15 +02:00
|
|
|
if (item_list.elements > 1)
|
2002-12-19 07:38:33 +02:00
|
|
|
res_type= ROW_RESULT;
|
|
|
|
return res_type;
|
2002-09-28 18:34:56 +03:00
|
|
|
}
|
|
|
|
|
2002-12-19 07:38:33 +02:00
|
|
|
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
|
2002-09-28 18:34:56 +03:00
|
|
|
{
|
2002-12-19 07:38:33 +02:00
|
|
|
DBUG_ASSERT(row || select_lex->item_list.elements==1);
|
2003-11-23 02:01:15 +02:00
|
|
|
res_type= set_row(select_lex->item_list, item, row, &maybe_null);
|
2003-07-30 14:15:25 +05:00
|
|
|
item->collation.set(row[0]->collation);
|
2002-12-27 21:19:25 +02:00
|
|
|
if (cols() != 1)
|
|
|
|
maybe_null= 0;
|
2002-12-19 07:38:33 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void subselect_union_engine::fix_length_and_dec(Item_cache **row)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
|
|
|
|
|
|
|
|
if (unit->first_select()->item_list.elements == 1)
|
2003-12-25 18:50:22 +04:00
|
|
|
{
|
2003-11-23 02:01:15 +02:00
|
|
|
res_type= set_row(unit->types, item, row, &maybe_null);
|
2003-12-25 18:50:22 +04:00
|
|
|
item->collation.set(row[0]->collation);
|
|
|
|
}
|
2002-12-19 07:38:33 +02:00
|
|
|
else
|
|
|
|
{
|
2002-12-27 21:19:25 +02:00
|
|
|
bool fake= 0;
|
2003-11-23 02:01:15 +02:00
|
|
|
res_type= set_row(unit->types, item, row, &fake);
|
2002-09-28 18:34:56 +03:00
|
|
|
}
|
|
|
|
}
|
2002-09-03 09:50:36 +03:00
|
|
|
|
2003-09-14 09:40:57 +03:00
|
|
|
void subselect_uniquesubquery_engine::fix_length_and_dec(Item_cache **row)
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
|
|
|
//this never should be called
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
|
2002-09-03 09:50:36 +03:00
|
|
|
int subselect_single_select_engine::exec()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("subselect_single_select_engine::exec");
|
2004-09-10 02:22:44 +03:00
|
|
|
char const *save_where= thd->where;
|
|
|
|
SELECT_LEX *save_select= thd->lex->current_select;
|
|
|
|
thd->lex->current_select= select_lex;
|
2002-09-03 09:50:36 +03:00
|
|
|
if (!optimized)
|
|
|
|
{
|
2005-05-30 20:54:37 +04:00
|
|
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
|
|
|
|
|
|
|
optimized= 1;
|
|
|
|
unit->set_limit(unit->global_parameters);
|
2002-09-03 09:50:36 +03:00
|
|
|
if (join->optimize())
|
|
|
|
{
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->where= save_where;
|
2002-09-03 09:50:36 +03:00
|
|
|
executed= 1;
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->lex->current_select= save_select;
|
2004-06-23 12:29:05 +02:00
|
|
|
DBUG_RETURN(join->error ? join->error : 1);
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
2003-07-07 18:40:19 +03:00
|
|
|
if (item->engine_changed)
|
|
|
|
{
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
2003-11-17 20:53:40 +02:00
|
|
|
if (select_lex->uncacheable && executed)
|
2002-09-03 09:50:36 +03:00
|
|
|
{
|
|
|
|
if (join->reinit())
|
2002-11-24 21:10:52 +02:00
|
|
|
{
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->where= save_where;
|
|
|
|
thd->lex->current_select= save_select;
|
2002-09-03 09:50:36 +03:00
|
|
|
DBUG_RETURN(1);
|
2002-11-24 21:10:52 +02:00
|
|
|
}
|
2002-12-06 21:55:53 +02:00
|
|
|
item->reset();
|
2002-09-03 09:50:36 +03:00
|
|
|
item->assigned((executed= 0));
|
|
|
|
}
|
|
|
|
if (!executed)
|
|
|
|
{
|
2004-11-18 18:10:07 +02:00
|
|
|
item->reset_value_registration();
|
2002-09-03 09:50:36 +03:00
|
|
|
join->exec();
|
|
|
|
executed= 1;
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->where= save_where;
|
|
|
|
thd->lex->current_select= save_select;
|
2003-01-30 22:15:44 +02:00
|
|
|
DBUG_RETURN(join->error||thd->is_fatal_error);
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->where= save_where;
|
|
|
|
thd->lex->current_select= save_select;
|
2002-09-03 09:50:36 +03:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int subselect_union_engine::exec()
|
|
|
|
{
|
2004-09-10 02:22:44 +03:00
|
|
|
char const *save_where= thd->where;
|
2002-11-24 21:10:52 +02:00
|
|
|
int res= unit->exec();
|
2004-09-10 02:22:44 +03:00
|
|
|
thd->where= save_where;
|
2002-11-24 21:10:52 +02:00
|
|
|
return res;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-09-14 09:40:57 +03:00
|
|
|
int subselect_uniquesubquery_engine::exec()
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
2003-09-14 09:40:57 +03:00
|
|
|
DBUG_ENTER("subselect_uniquesubquery_engine::exec");
|
2003-07-07 18:40:19 +03:00
|
|
|
int error;
|
|
|
|
TABLE *table= tab->table;
|
2004-08-12 17:31:23 +03:00
|
|
|
for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
func_str.result, func_str.test:
Added a test case for bug #10124.
sql_select.h, item_subselect.cc, sql_select.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
field.cc:
Fixed bug #10124.
When ussuing a warning the store methods return 2 instead of 1 now.
sql/field.cc:
Fixed bug #10124.
When ussuing a warning the store methods return 2 instead of 1 now.
sql/sql_select.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
sql/item_subselect.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
sql/sql_select.h:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
mysql-test/t/func_str.test:
Added a test case for bug #10124.
mysql-test/r/func_str.result:
Added a test case for bug #10124.
2005-06-23 06:15:50 -07:00
|
|
|
if ((tab->ref.key_err= (*copy)->copy()) & 1)
|
2004-08-12 17:31:23 +03:00
|
|
|
{
|
|
|
|
table->status= STATUS_NOT_FOUND;
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2003-07-07 18:40:19 +03:00
|
|
|
}
|
2004-08-12 17:31:23 +03:00
|
|
|
|
|
|
|
if (!table->file->inited)
|
2005-07-18 13:31:02 +02:00
|
|
|
table->file->ha_index_init(tab->ref.key, 0);
|
2004-08-12 17:31:23 +03:00
|
|
|
error= table->file->index_read(table->record[0],
|
|
|
|
tab->ref.key_buff,
|
|
|
|
tab->ref.key_length,HA_READ_KEY_EXACT);
|
2004-10-07 14:13:42 +03:00
|
|
|
if (error &&
|
|
|
|
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
2004-08-12 17:31:23 +03:00
|
|
|
error= report_error(table, error);
|
2003-07-07 18:40:19 +03:00
|
|
|
else
|
|
|
|
{
|
2004-08-12 17:31:23 +03:00
|
|
|
error= 0;
|
|
|
|
table->null_row= 0;
|
|
|
|
((Item_in_subselect *) item)->value= (!table->status &&
|
|
|
|
(!cond || cond->val_int()) ? 1 :
|
|
|
|
0);
|
2003-07-07 18:40:19 +03:00
|
|
|
}
|
2004-08-12 17:31:23 +03:00
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
DBUG_RETURN(error != 0);
|
2003-07-08 00:08:00 +03:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
|
|
|
subselect_uniquesubquery_engine::~subselect_uniquesubquery_engine()
|
2003-07-08 00:08:00 +03:00
|
|
|
{
|
2003-09-29 12:39:38 +03:00
|
|
|
/* Tell handler we don't need the index anymore */
|
2004-06-23 12:29:05 +02:00
|
|
|
tab->table->file->ha_index_end();
|
2003-07-08 00:08:00 +03:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-09-14 09:40:57 +03:00
|
|
|
int subselect_indexsubquery_engine::exec()
|
2003-07-08 00:08:00 +03:00
|
|
|
{
|
2003-09-14 09:40:57 +03:00
|
|
|
DBUG_ENTER("subselect_indexsubselect_engine::exec");
|
2003-07-08 00:08:00 +03:00
|
|
|
int error;
|
2003-09-08 21:58:09 +03:00
|
|
|
bool null_finding= 0;
|
2003-07-08 00:08:00 +03:00
|
|
|
TABLE *table= tab->table;
|
2003-07-17 19:39:31 +03:00
|
|
|
|
2003-07-08 00:08:00 +03:00
|
|
|
((Item_in_subselect *) item)->value= 0;
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2003-07-17 19:39:31 +03:00
|
|
|
if (check_null)
|
|
|
|
{
|
2003-09-29 12:39:38 +03:00
|
|
|
/* We need to check for NULL if there wasn't a matching value */
|
2004-01-31 10:04:16 +04:00
|
|
|
*tab->ref.null_ref_key= 0; // Search first for not null
|
2003-07-17 19:39:31 +03:00
|
|
|
((Item_in_subselect *) item)->was_null= 0;
|
|
|
|
}
|
|
|
|
|
2004-08-12 17:31:23 +03:00
|
|
|
for (store_key **copy=tab->ref.key_copy ; *copy ; copy++)
|
2003-07-08 00:08:00 +03:00
|
|
|
{
|
func_str.result, func_str.test:
Added a test case for bug #10124.
sql_select.h, item_subselect.cc, sql_select.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
field.cc:
Fixed bug #10124.
When ussuing a warning the store methods return 2 instead of 1 now.
sql/field.cc:
Fixed bug #10124.
When ussuing a warning the store methods return 2 instead of 1 now.
sql/sql_select.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
sql/item_subselect.cc:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
sql/sql_select.h:
Fixed bug #10124.
The copy method of the store_key classes can return
STORE_KEY_OK=0, STORE_KEY_FATAL=1, STORE_KEY_CONV=2 now.
mysql-test/t/func_str.test:
Added a test case for bug #10124.
mysql-test/r/func_str.result:
Added a test case for bug #10124.
2005-06-23 06:15:50 -07:00
|
|
|
if ((tab->ref.key_err= (*copy)->copy()) & 1)
|
2004-08-12 17:31:23 +03:00
|
|
|
{
|
|
|
|
table->status= STATUS_NOT_FOUND;
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2003-07-08 00:08:00 +03:00
|
|
|
}
|
2004-08-12 17:31:23 +03:00
|
|
|
|
|
|
|
if (!table->file->inited)
|
2005-07-18 13:31:02 +02:00
|
|
|
table->file->ha_index_init(tab->ref.key, 1);
|
2004-08-12 17:31:23 +03:00
|
|
|
error= table->file->index_read(table->record[0],
|
|
|
|
tab->ref.key_buff,
|
|
|
|
tab->ref.key_length,HA_READ_KEY_EXACT);
|
2004-10-07 14:13:42 +03:00
|
|
|
if (error &&
|
|
|
|
error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
|
2004-08-12 17:31:23 +03:00
|
|
|
error= report_error(table, error);
|
2003-07-08 00:08:00 +03:00
|
|
|
else
|
|
|
|
{
|
2004-08-12 17:31:23 +03:00
|
|
|
for (;;)
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
2004-08-12 17:31:23 +03:00
|
|
|
error= 0;
|
|
|
|
table->null_row= 0;
|
|
|
|
if (!table->status)
|
2003-07-08 00:08:00 +03:00
|
|
|
{
|
2004-08-12 17:31:23 +03:00
|
|
|
if (!cond || cond->val_int())
|
|
|
|
{
|
|
|
|
if (null_finding)
|
|
|
|
((Item_in_subselect *) item)->was_null= 1;
|
|
|
|
else
|
|
|
|
((Item_in_subselect *) item)->value= 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
error= table->file->index_next_same(table->record[0],
|
|
|
|
tab->ref.key_buff,
|
|
|
|
tab->ref.key_length);
|
|
|
|
if (error && error != HA_ERR_END_OF_FILE)
|
|
|
|
{
|
|
|
|
error= report_error(table, error);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!check_null || null_finding)
|
|
|
|
break; /* We don't need to check nulls */
|
|
|
|
*tab->ref.null_ref_key= 1;
|
|
|
|
null_finding= 1;
|
|
|
|
/* Check if there exists a row with a null value in the index */
|
|
|
|
if ((error= (safe_index_read(tab) == 1)))
|
|
|
|
break;
|
2003-07-08 00:08:00 +03:00
|
|
|
}
|
2003-07-07 18:40:19 +03:00
|
|
|
}
|
|
|
|
}
|
2003-09-29 12:39:38 +03:00
|
|
|
DBUG_RETURN(error != 0);
|
2003-07-07 18:40:19 +03:00
|
|
|
}
|
|
|
|
|
2003-09-29 12:39:38 +03:00
|
|
|
|
2002-09-03 09:50:36 +03:00
|
|
|
uint subselect_single_select_engine::cols()
|
|
|
|
{
|
2005-02-25 16:53:22 +02:00
|
|
|
DBUG_ASSERT(select_lex->join != 0); // should be called after fix_fields()
|
2005-01-24 14:25:44 +02:00
|
|
|
return select_lex->join->fields_list.elements;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2002-09-03 09:50:36 +03:00
|
|
|
uint subselect_union_engine::cols()
|
|
|
|
{
|
2005-01-24 14:25:44 +02:00
|
|
|
DBUG_ASSERT(unit->is_prepared()); // should be called after fix_fields()
|
|
|
|
return unit->types.elements;
|
2002-09-03 09:50:36 +03:00
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2003-11-17 20:53:40 +02:00
|
|
|
uint8 subselect_single_select_engine::uncacheable()
|
2003-01-28 14:48:12 +02:00
|
|
|
{
|
|
|
|
return select_lex->uncacheable;
|
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2003-11-17 20:53:40 +02:00
|
|
|
uint8 subselect_union_engine::uncacheable()
|
2003-01-28 14:48:12 +02:00
|
|
|
{
|
|
|
|
return unit->uncacheable;
|
|
|
|
}
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2002-11-28 19:29:26 +02:00
|
|
|
void subselect_single_select_engine::exclude()
|
|
|
|
{
|
|
|
|
select_lex->master_unit()->exclude_level();
|
|
|
|
}
|
|
|
|
|
|
|
|
void subselect_union_engine::exclude()
|
|
|
|
{
|
|
|
|
unit->exclude_level();
|
|
|
|
}
|
2003-07-07 18:40:19 +03:00
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
|
2003-09-14 09:40:57 +03:00
|
|
|
void subselect_uniquesubquery_engine::exclude()
|
2003-07-07 18:40:19 +03:00
|
|
|
{
|
|
|
|
//this never should be called
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
2003-10-17 00:36:01 +03:00
|
|
|
|
|
|
|
|
|
|
|
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
|
|
|
|
{
|
|
|
|
table_map map= 0;
|
2005-06-01 16:35:09 +03:00
|
|
|
for (; table; table= table->next_leaf)
|
2003-10-17 00:36:01 +03:00
|
|
|
{
|
|
|
|
TABLE *tbl= table->table;
|
|
|
|
if (tbl && tbl->const_table)
|
|
|
|
map|= tbl->map;
|
|
|
|
}
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
table_map subselect_single_select_engine::upper_select_const_tables()
|
|
|
|
{
|
|
|
|
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
|
2004-09-14 19:28:29 +03:00
|
|
|
leaf_tables);
|
2003-10-17 00:36:01 +03:00
|
|
|
}
|
|
|
|
|
2003-10-28 12:45:37 +02:00
|
|
|
|
2003-10-17 00:36:01 +03:00
|
|
|
table_map subselect_union_engine::upper_select_const_tables()
|
|
|
|
{
|
2004-09-14 19:28:29 +03:00
|
|
|
return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables);
|
2003-10-17 00:36:01 +03:00
|
|
|
}
|
2003-10-28 12:45:37 +02:00
|
|
|
|
|
|
|
|
2003-10-16 15:54:47 +03:00
|
|
|
void subselect_single_select_engine::print(String *str)
|
|
|
|
{
|
|
|
|
select_lex->print(thd, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void subselect_union_engine::print(String *str)
|
|
|
|
{
|
|
|
|
unit->print(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void subselect_uniquesubquery_engine::print(String *str)
|
|
|
|
{
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN("<primary_index_lookup>("));
|
2003-10-16 15:54:47 +03:00
|
|
|
tab->ref.items[0]->print(str);
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" in "));
|
Table definition cache, part 2
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
Other noteworthy changes:
- In TABLE_SHARE the most common strings are now LEX_STRING's
- Better error message when table is not found
- Variable table_cache is now renamed 'table_open_cache'
- New variable 'table_definition_cache' that is the number of table defintions that will be cached
- strxnmov() calls are now fixed to avoid overflows
- strxnmov() will now always add one end \0 to result
- engine objects are now created with a TABLE_SHARE object instead of a TABLE object.
- After creating a field object one must call field->init(table) before using it
- For a busy system this change will give you:
- Less memory usage for table object
- Faster opening of tables (if it's has been in use or is in table definition cache)
- Allow you to cache many table definitions objects
- Faster drop of table
mysql-test/mysql-test-run.sh:
Fixed some problems with --gdb option
Test both with socket and tcp/ip port that all old servers are killed
mysql-test/r/flush_table.result:
More tests with lock table with 2 threads + flush table
mysql-test/r/information_schema.result:
Removed old (now wrong) result
mysql-test/r/innodb.result:
Better error messages (thanks to TDC patch)
mysql-test/r/merge.result:
Extra flush table test
mysql-test/r/ndb_bitfield.result:
Better error messages (thanks to TDC patch)
mysql-test/r/ndb_partition_error.result:
Better error messages (thanks to TDC patch)
mysql-test/r/query_cache.result:
Remove tables left from old tests
mysql-test/r/temp_table.result:
Test truncate with temporary tables
mysql-test/r/variables.result:
Table_cache -> Table_open_cache
mysql-test/t/flush_table.test:
More tests with lock table with 2 threads + flush table
mysql-test/t/merge.test:
Extra flush table test
mysql-test/t/multi_update.test:
Added 'sleep' to make test predictable
mysql-test/t/query_cache.test:
Remove tables left from old tests
mysql-test/t/temp_table.test:
Test truncate with temporary tables
mysql-test/t/variables.test:
Table_cache -> Table_open_cache
mysql-test/valgrind.supp:
Remove warning that may happens becasue threads dies in different order
mysys/hash.c:
Fixed wrong DBUG_PRINT
mysys/mf_dirname.c:
More DBUG
mysys/mf_pack.c:
Better comment
mysys/mf_tempdir.c:
More DBUG
Ensure that we call cleanup_dirname() on all temporary directory paths.
If we don't do this, we will get a failure when comparing temporary table
names as in some cases the temporary table name is run through convert_dirname())
mysys/my_alloc.c:
Indentation fix
sql/examples/ha_example.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_example.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/field.cc:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Use s->db instead of s->table_cache_key
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/field.h:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/ha_archive.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_archive.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_berkeley.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Changed name of argument create() to not hide internal 'table' variable.
table->s -> table_share
sql/ha_berkeley.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_federated.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed comments
Remove index variable and replace with pointers (simple optimization)
move_field() -> move_field_offset()
Removed some strlen() calls
sql/ha_federated.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_heap.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Simplify delete_table() and create() as the given file names are now without extension
sql/ha_heap.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisam.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Remove not needed fn_format()
Fixed for new table->s structure
sql/ha_myisam.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisammrg.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Don't set 'is_view' for MERGE tables
Use new interface to find_temporary_table()
sql/ha_myisammrg.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Added flag HA_NO_COPY_ON_ALTER
sql/ha_ndbcluster.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed wrong calls to strxnmov()
Give error HA_ERR_TABLE_DEF_CHANGED if table definition has changed
drop_table -> intern_drop_table()
table->s -> table_share
Move part_info to TABLE
Fixed comments & DBUG print's
New arguments to print_error()
sql/ha_ndbcluster.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_partition.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
We can't set up or use part_info when creating handler as there is not yet any table object
New ha_intialise() to work with TDC (Done by Mikael)
sql/ha_partition.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Got set_part_info() from Mikael
sql/handler.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
ha_delete_table() now also takes database as an argument
handler::ha_open() now takes TABLE as argument
ha_open() now calls ha_allocate_read_write_set()
Simplify ha_allocate_read_write_set()
Remove ha_deallocate_read_write_set()
Use table_share (Cached by table definition cache)
sql/handler.h:
New table flag: HA_NO_COPY_ON_ALTER (used by merge tables)
Remove ha_deallocate_read_write_set()
get_new_handler() now takes TABLE_SHARE as argument
ha_delete_table() now gets database as argument
sql/item.cc:
table_name and db are now LEX_STRING objects
When creating fields, we have now have to call field->init(table)
move_field -> move_field_offset()
sql/item.h:
tmp_table_field_from_field_type() now takes an extra paramenter 'fixed_length' to allow one to force usage of CHAR
instead of BLOB
sql/item_cmpfunc.cc:
Fixed call to tmp_table_field_from_field_type()
sql/item_create.cc:
Assert if new not handled cast type
sql/item_func.cc:
When creating fields, we have now have to call field->init(table)
dummy_table used by 'sp' now needs a TABLE_SHARE object
sql/item_subselect.cc:
Trivial code cleanups
sql/item_sum.cc:
When creating fields, we have now have to call field->init(table)
sql/item_timefunc.cc:
Item_func_str_to_date::tmp_table_field() now replaced by call to
tmp_table_field_from_field_type() (see item_timefunc.h)
sql/item_timefunc.h:
Simply tmp_table_field()
sql/item_uniq.cc:
When creating fields, we have now have to call field->init(table)
sql/key.cc:
Added 'KEY' argument to 'find_ref_key' to simplify code
sql/lock.cc:
More debugging
Use create_table_def_key() to create key for table cache
Allocate TABLE_SHARE properly when creating name lock
Fix that locked_table_name doesn't test same table twice
sql/mysql_priv.h:
New functions for table definition cache
New interfaces to a lot of functions.
New faster interface to find_temporary_table() and close_temporary_table()
sql/mysqld.cc:
Added support for table definition cache of size 'table_def_size'
Fixed som calls to strnmov()
Changed name of 'table_cache' to 'table_open_cache'
sql/opt_range.cc:
Use new interfaces
Fixed warnings from valgrind
sql/parse_file.cc:
Safer calls to strxnmov()
Fixed typo
sql/set_var.cc:
Added variable 'table_definition_cache'
Variable table_cache renamed to 'table_open_cache'
sql/slave.cc:
Use new interface
sql/sp.cc:
Proper use of TABLE_SHARE
sql/sp_head.cc:
Remove compiler warnings
We have now to call field->init(table)
sql/sp_head.h:
Pointers to parsed strings are now const
sql/sql_acl.cc:
table_name is now a LEX_STRING
sql/sql_base.cc:
Main implementation of table definition cache
(The #ifdef's are there for the future when table definition cache will replace open table cache)
Now table definitions are cached indepndent of open tables, which will speed up things when a table is in use at once from several places
Views are not yet cached; For the moment we only cache if a table is a view or not.
Faster implementation of find_temorary_table()
Replace 'wait_for_refresh()' with the more general function 'wait_for_condition()'
Drop table is slightly faster as we can use the table definition cache to know the type of the table
sql/sql_cache.cc:
table_cache_key and table_name are now LEX_STRING
'sDBUG print fixes
sql/sql_class.cc:
table_cache_key is now a LEX_STRING
safer strxnmov()
sql/sql_class.h:
Added number of open table shares (table definitions)
sql/sql_db.cc:
safer strxnmov()
sql/sql_delete.cc:
Use new interface to find_temporary_table()
sql/sql_derived.cc:
table_name is now a LEX_STRING
sql/sql_handler.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_insert.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_lex.cc:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_lex.h:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_load.cc:
Safer strxnmov()
sql/sql_parse.cc:
Better error if wrong DB name
sql/sql_partition.cc:
part_info moved to TABLE from TABLE_SHARE
Indentation changes
sql/sql_select.cc:
Indentation fixes
Call field->init(TABLE) for new created fields
Update create_tmp_table() to use TABLE_SHARE properly
sql/sql_select.h:
Call field->init(TABLE) for new created fields
sql/sql_show.cc:
table_name is now a LEX_STRING
part_info moved to TABLE
sql/sql_table.cc:
Use table definition cache to speed up delete of tables
Fixed calls to functions with new interfaces
Don't use 'share_not_to_be_used'
Instead of doing openfrm() when doing repair, we now have to call
get_table_share() followed by open_table_from_share().
Replace some fn_format() with faster unpack_filename().
Safer strxnmov()
part_info is now in TABLE
Added Mikaels patch for partition and ALTER TABLE
Instead of using 'TABLE_SHARE->is_view' use 'table_flags() & HA_NO_COPY_ON_ALTER
sql/sql_test.cc:
table_name and table_cache_key are now LEX_STRING's
sql/sql_trigger.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
safer strxnmov()
Removed compiler warnings
sql/sql_update.cc:
Call field->init(TABLE) after field is created
sql/sql_view.cc:
safer strxnmov()
Create common TABLE_SHARE object for views to allow us to cache if table is a view
sql/structs.h:
Added SHOW_TABLE_DEFINITIONS
sql/table.cc:
Creation and destruct of TABLE_SHARE objects that are common for many TABLE objects
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
open_table_def() is written in such a way that it should be trival to add parsing of the .frm files in new formats
sql/table.h:
TABLE objects for the same database table now share a common TABLE_SHARE object
In TABLE_SHARE the most common strings are now LEX_STRING's
sql/unireg.cc:
Changed arguments to rea_create_table() to have same order as other functions
Call field->init(table) for new created fields
sql/unireg.h:
Added OPEN_VIEW
strings/strxnmov.c:
Change strxnmov() to always add end \0
This makes usage of strxnmov() safer as most of MySQL code assumes that strxnmov() will create a null terminated string
2005-11-23 22:45:02 +02:00
|
|
|
str->append(tab->table->s->table_name.str, tab->table->s->table_name.length);
|
2003-10-19 14:22:17 +03:00
|
|
|
KEY *key_info= tab->table->key_info+ tab->ref.key;
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" on "));
|
2003-10-19 14:22:17 +03:00
|
|
|
str->append(key_info->name);
|
2003-10-16 15:54:47 +03:00
|
|
|
if (cond)
|
|
|
|
{
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" where "));
|
2003-10-16 15:54:47 +03:00
|
|
|
cond->print(str);
|
|
|
|
}
|
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void subselect_indexsubquery_engine::print(String *str)
|
|
|
|
{
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN("<index_lookup>("));
|
2003-10-16 15:54:47 +03:00
|
|
|
tab->ref.items[0]->print(str);
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" in "));
|
Table definition cache, part 2
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
Other noteworthy changes:
- In TABLE_SHARE the most common strings are now LEX_STRING's
- Better error message when table is not found
- Variable table_cache is now renamed 'table_open_cache'
- New variable 'table_definition_cache' that is the number of table defintions that will be cached
- strxnmov() calls are now fixed to avoid overflows
- strxnmov() will now always add one end \0 to result
- engine objects are now created with a TABLE_SHARE object instead of a TABLE object.
- After creating a field object one must call field->init(table) before using it
- For a busy system this change will give you:
- Less memory usage for table object
- Faster opening of tables (if it's has been in use or is in table definition cache)
- Allow you to cache many table definitions objects
- Faster drop of table
mysql-test/mysql-test-run.sh:
Fixed some problems with --gdb option
Test both with socket and tcp/ip port that all old servers are killed
mysql-test/r/flush_table.result:
More tests with lock table with 2 threads + flush table
mysql-test/r/information_schema.result:
Removed old (now wrong) result
mysql-test/r/innodb.result:
Better error messages (thanks to TDC patch)
mysql-test/r/merge.result:
Extra flush table test
mysql-test/r/ndb_bitfield.result:
Better error messages (thanks to TDC patch)
mysql-test/r/ndb_partition_error.result:
Better error messages (thanks to TDC patch)
mysql-test/r/query_cache.result:
Remove tables left from old tests
mysql-test/r/temp_table.result:
Test truncate with temporary tables
mysql-test/r/variables.result:
Table_cache -> Table_open_cache
mysql-test/t/flush_table.test:
More tests with lock table with 2 threads + flush table
mysql-test/t/merge.test:
Extra flush table test
mysql-test/t/multi_update.test:
Added 'sleep' to make test predictable
mysql-test/t/query_cache.test:
Remove tables left from old tests
mysql-test/t/temp_table.test:
Test truncate with temporary tables
mysql-test/t/variables.test:
Table_cache -> Table_open_cache
mysql-test/valgrind.supp:
Remove warning that may happens becasue threads dies in different order
mysys/hash.c:
Fixed wrong DBUG_PRINT
mysys/mf_dirname.c:
More DBUG
mysys/mf_pack.c:
Better comment
mysys/mf_tempdir.c:
More DBUG
Ensure that we call cleanup_dirname() on all temporary directory paths.
If we don't do this, we will get a failure when comparing temporary table
names as in some cases the temporary table name is run through convert_dirname())
mysys/my_alloc.c:
Indentation fix
sql/examples/ha_example.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_example.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/examples/ha_tina.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/field.cc:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Use s->db instead of s->table_cache_key
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/field.h:
Update for table definition cache:
- Field creation now takes TABLE_SHARE instead of TABLE as argument
(This is becasue field definitions are now cached in TABLE_SHARE)
When a field is created, one now must call field->init(TABLE) before using it
- Added Field::clone() to create a field in TABLE from a field in TABLE_SHARE
- make_field() takes TABLE_SHARE as argument instead of TABLE
- move_field() -> move_field_offset()
sql/ha_archive.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_archive.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_berkeley.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Changed name of argument create() to not hide internal 'table' variable.
table->s -> table_share
sql/ha_berkeley.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_blackhole.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_federated.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed comments
Remove index variable and replace with pointers (simple optimization)
move_field() -> move_field_offset()
Removed some strlen() calls
sql/ha_federated.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_heap.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Simplify delete_table() and create() as the given file names are now without extension
sql/ha_heap.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_innodb.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisam.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Remove not needed fn_format()
Fixed for new table->s structure
sql/ha_myisam.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_myisammrg.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Don't set 'is_view' for MERGE tables
Use new interface to find_temporary_table()
sql/ha_myisammrg.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Added flag HA_NO_COPY_ON_ALTER
sql/ha_ndbcluster.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Fixed wrong calls to strxnmov()
Give error HA_ERR_TABLE_DEF_CHANGED if table definition has changed
drop_table -> intern_drop_table()
table->s -> table_share
Move part_info to TABLE
Fixed comments & DBUG print's
New arguments to print_error()
sql/ha_ndbcluster.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
sql/ha_partition.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
We can't set up or use part_info when creating handler as there is not yet any table object
New ha_intialise() to work with TDC (Done by Mikael)
sql/ha_partition.h:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
Got set_part_info() from Mikael
sql/handler.cc:
We new use TABLE_SHARE instead of TABLE when creating engine handlers
ha_delete_table() now also takes database as an argument
handler::ha_open() now takes TABLE as argument
ha_open() now calls ha_allocate_read_write_set()
Simplify ha_allocate_read_write_set()
Remove ha_deallocate_read_write_set()
Use table_share (Cached by table definition cache)
sql/handler.h:
New table flag: HA_NO_COPY_ON_ALTER (used by merge tables)
Remove ha_deallocate_read_write_set()
get_new_handler() now takes TABLE_SHARE as argument
ha_delete_table() now gets database as argument
sql/item.cc:
table_name and db are now LEX_STRING objects
When creating fields, we have now have to call field->init(table)
move_field -> move_field_offset()
sql/item.h:
tmp_table_field_from_field_type() now takes an extra paramenter 'fixed_length' to allow one to force usage of CHAR
instead of BLOB
sql/item_cmpfunc.cc:
Fixed call to tmp_table_field_from_field_type()
sql/item_create.cc:
Assert if new not handled cast type
sql/item_func.cc:
When creating fields, we have now have to call field->init(table)
dummy_table used by 'sp' now needs a TABLE_SHARE object
sql/item_subselect.cc:
Trivial code cleanups
sql/item_sum.cc:
When creating fields, we have now have to call field->init(table)
sql/item_timefunc.cc:
Item_func_str_to_date::tmp_table_field() now replaced by call to
tmp_table_field_from_field_type() (see item_timefunc.h)
sql/item_timefunc.h:
Simply tmp_table_field()
sql/item_uniq.cc:
When creating fields, we have now have to call field->init(table)
sql/key.cc:
Added 'KEY' argument to 'find_ref_key' to simplify code
sql/lock.cc:
More debugging
Use create_table_def_key() to create key for table cache
Allocate TABLE_SHARE properly when creating name lock
Fix that locked_table_name doesn't test same table twice
sql/mysql_priv.h:
New functions for table definition cache
New interfaces to a lot of functions.
New faster interface to find_temporary_table() and close_temporary_table()
sql/mysqld.cc:
Added support for table definition cache of size 'table_def_size'
Fixed som calls to strnmov()
Changed name of 'table_cache' to 'table_open_cache'
sql/opt_range.cc:
Use new interfaces
Fixed warnings from valgrind
sql/parse_file.cc:
Safer calls to strxnmov()
Fixed typo
sql/set_var.cc:
Added variable 'table_definition_cache'
Variable table_cache renamed to 'table_open_cache'
sql/slave.cc:
Use new interface
sql/sp.cc:
Proper use of TABLE_SHARE
sql/sp_head.cc:
Remove compiler warnings
We have now to call field->init(table)
sql/sp_head.h:
Pointers to parsed strings are now const
sql/sql_acl.cc:
table_name is now a LEX_STRING
sql/sql_base.cc:
Main implementation of table definition cache
(The #ifdef's are there for the future when table definition cache will replace open table cache)
Now table definitions are cached indepndent of open tables, which will speed up things when a table is in use at once from several places
Views are not yet cached; For the moment we only cache if a table is a view or not.
Faster implementation of find_temorary_table()
Replace 'wait_for_refresh()' with the more general function 'wait_for_condition()'
Drop table is slightly faster as we can use the table definition cache to know the type of the table
sql/sql_cache.cc:
table_cache_key and table_name are now LEX_STRING
'sDBUG print fixes
sql/sql_class.cc:
table_cache_key is now a LEX_STRING
safer strxnmov()
sql/sql_class.h:
Added number of open table shares (table definitions)
sql/sql_db.cc:
safer strxnmov()
sql/sql_delete.cc:
Use new interface to find_temporary_table()
sql/sql_derived.cc:
table_name is now a LEX_STRING
sql/sql_handler.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_insert.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
sql/sql_lex.cc:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_lex.h:
Make parsed string a const (to quickly find out if anything is trying to change the query string)
sql/sql_load.cc:
Safer strxnmov()
sql/sql_parse.cc:
Better error if wrong DB name
sql/sql_partition.cc:
part_info moved to TABLE from TABLE_SHARE
Indentation changes
sql/sql_select.cc:
Indentation fixes
Call field->init(TABLE) for new created fields
Update create_tmp_table() to use TABLE_SHARE properly
sql/sql_select.h:
Call field->init(TABLE) for new created fields
sql/sql_show.cc:
table_name is now a LEX_STRING
part_info moved to TABLE
sql/sql_table.cc:
Use table definition cache to speed up delete of tables
Fixed calls to functions with new interfaces
Don't use 'share_not_to_be_used'
Instead of doing openfrm() when doing repair, we now have to call
get_table_share() followed by open_table_from_share().
Replace some fn_format() with faster unpack_filename().
Safer strxnmov()
part_info is now in TABLE
Added Mikaels patch for partition and ALTER TABLE
Instead of using 'TABLE_SHARE->is_view' use 'table_flags() & HA_NO_COPY_ON_ALTER
sql/sql_test.cc:
table_name and table_cache_key are now LEX_STRING's
sql/sql_trigger.cc:
TABLE_SHARE->db and TABLE_SHARE->table_name are now LEX_STRING's
safer strxnmov()
Removed compiler warnings
sql/sql_update.cc:
Call field->init(TABLE) after field is created
sql/sql_view.cc:
safer strxnmov()
Create common TABLE_SHARE object for views to allow us to cache if table is a view
sql/structs.h:
Added SHOW_TABLE_DEFINITIONS
sql/table.cc:
Creation and destruct of TABLE_SHARE objects that are common for many TABLE objects
The table opening process now works the following way:
- Create common TABLE_SHARE object
- Read the .frm file and unpack it into the TABLE_SHARE object
- Create a TABLE object based on the information in the TABLE_SHARE
object and open a handler to the table object
open_table_def() is written in such a way that it should be trival to add parsing of the .frm files in new formats
sql/table.h:
TABLE objects for the same database table now share a common TABLE_SHARE object
In TABLE_SHARE the most common strings are now LEX_STRING's
sql/unireg.cc:
Changed arguments to rea_create_table() to have same order as other functions
Call field->init(table) for new created fields
sql/unireg.h:
Added OPEN_VIEW
strings/strxnmov.c:
Change strxnmov() to always add end \0
This makes usage of strxnmov() safer as most of MySQL code assumes that strxnmov() will create a null terminated string
2005-11-23 22:45:02 +02:00
|
|
|
str->append(tab->table->s->table_name.str, tab->table->s->table_name.length);
|
2003-10-19 14:22:17 +03:00
|
|
|
KEY *key_info= tab->table->key_info+ tab->ref.key;
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" on "));
|
2003-10-19 14:22:17 +03:00
|
|
|
str->append(key_info->name);
|
2003-10-16 15:54:47 +03:00
|
|
|
if (check_null)
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" checking NULL"));
|
2003-10-16 15:54:47 +03:00
|
|
|
if (cond)
|
|
|
|
{
|
2005-11-20 20:47:07 +02:00
|
|
|
str->append(STRING_WITH_LEN(" where "));
|
2003-10-16 15:54:47 +03:00
|
|
|
cond->print(str);
|
|
|
|
}
|
|
|
|
str->append(')');
|
|
|
|
}
|
2004-05-07 23:06:11 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
change select_result object of engine
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-05-07 23:06:11 +03:00
|
|
|
subselect_single_select_engine::change_result()
|
|
|
|
si new subselect Item
|
|
|
|
res new select_result object
|
|
|
|
|
|
|
|
RETURN
|
2004-10-20 04:04:37 +03:00
|
|
|
FALSE OK
|
|
|
|
TRUE error
|
2004-05-07 23:06:11 +03:00
|
|
|
*/
|
|
|
|
|
2004-10-20 04:04:37 +03:00
|
|
|
bool subselect_single_select_engine::change_result(Item_subselect *si,
|
|
|
|
select_subselect *res)
|
2004-05-07 23:06:11 +03:00
|
|
|
{
|
|
|
|
item= si;
|
|
|
|
result= res;
|
|
|
|
return select_lex->join->change_result(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
change select_result object of engine
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-05-07 23:06:11 +03:00
|
|
|
subselect_single_select_engine::change_result()
|
|
|
|
si new subselect Item
|
|
|
|
res new select_result object
|
|
|
|
|
|
|
|
RETURN
|
2004-10-20 04:04:37 +03:00
|
|
|
FALSE OK
|
|
|
|
TRUE error
|
2004-05-07 23:06:11 +03:00
|
|
|
*/
|
|
|
|
|
2004-10-20 04:04:37 +03:00
|
|
|
bool subselect_union_engine::change_result(Item_subselect *si,
|
|
|
|
select_subselect *res)
|
2004-05-07 23:06:11 +03:00
|
|
|
{
|
|
|
|
item= si;
|
|
|
|
int rc= unit->change_result(res, result);
|
|
|
|
result= res;
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
change select_result emulation, never should be called
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-05-07 23:06:11 +03:00
|
|
|
subselect_single_select_engine::change_result()
|
|
|
|
si new subselect Item
|
|
|
|
res new select_result object
|
|
|
|
|
|
|
|
RETURN
|
2004-10-20 04:04:37 +03:00
|
|
|
FALSE OK
|
|
|
|
TRUE error
|
2004-05-07 23:06:11 +03:00
|
|
|
*/
|
|
|
|
|
2004-10-20 04:04:37 +03:00
|
|
|
bool subselect_uniquesubquery_engine::change_result(Item_subselect *si,
|
|
|
|
select_subselect *res)
|
2004-05-07 23:06:11 +03:00
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
2004-10-20 04:04:37 +03:00
|
|
|
return TRUE;
|
2004-05-07 23:06:11 +03:00
|
|
|
}
|
2004-10-27 21:11:06 +03:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Report about presence of tables in subquery
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-10-27 21:11:06 +03:00
|
|
|
subselect_single_select_engine::no_tables()
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
TRUE there are not tables used in subquery
|
|
|
|
FALSE there are some tables in subquery
|
|
|
|
*/
|
|
|
|
bool subselect_single_select_engine::no_tables()
|
|
|
|
{
|
|
|
|
return(select_lex->table_list.elements == 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Report about presence of tables in subquery
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-10-27 21:11:06 +03:00
|
|
|
subselect_union_engine::no_tables()
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
TRUE there are not tables used in subquery
|
|
|
|
FALSE there are some tables in subquery
|
|
|
|
*/
|
|
|
|
bool subselect_union_engine::no_tables()
|
|
|
|
{
|
|
|
|
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
|
|
|
|
{
|
|
|
|
if (sl->table_list.elements)
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Report about presence of tables in subquery
|
|
|
|
|
2005-02-09 02:50:45 +04:00
|
|
|
SYNOPSIS
|
2004-10-27 21:11:06 +03:00
|
|
|
subselect_uniquesubquery_engine::no_tables()
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
TRUE there are not tables used in subquery
|
|
|
|
FALSE there are some tables in subquery
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool subselect_uniquesubquery_engine::no_tables()
|
|
|
|
{
|
|
|
|
/* returning value is correct, but this method should never be called */
|
|
|
|
return 0;
|
|
|
|
}
|