2006-12-31 01:02:27 +01:00
|
|
|
/* Copyright (C) 2000-2006 MySQL AB
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
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
|
2006-12-23 20:17:15 +01:00
|
|
|
the Free Software Foundation; version 2 of the License.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
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.
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
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 */
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
**
|
|
|
|
** This file implements classes defined in sql_class.h
|
|
|
|
** Especially the classes to handle a result from a select
|
|
|
|
**
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2005-05-26 12:09:14 +02:00
|
|
|
#ifdef USE_PRAGMA_IMPLEMENTATION
|
2000-07-31 21:29:14 +02:00
|
|
|
#pragma implementation // gcc: Class implementation
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "mysql_priv.h"
|
2007-04-12 08:58:04 +02:00
|
|
|
#include "rpl_rli.h"
|
2007-04-13 14:55:28 +02:00
|
|
|
#include "rpl_record.h"
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
#include "slave.h"
|
2005-12-22 06:39:02 +01:00
|
|
|
#include <my_bitmap.h>
|
|
|
|
#include "log_event.h"
|
2000-07-31 21:29:14 +02:00
|
|
|
#include <m_ctype.h>
|
|
|
|
#include <sys/stat.h>
|
2001-03-14 07:07:12 +01:00
|
|
|
#include <thr_alarm.h>
|
2000-07-31 21:29:14 +02:00
|
|
|
#ifdef __WIN__
|
|
|
|
#include <io.h>
|
|
|
|
#endif
|
2002-03-15 22:57:31 +01:00
|
|
|
#include <mysys_err.h>
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-12-21 01:07:45 +01:00
|
|
|
#include "sp_rcontext.h"
|
|
|
|
#include "sp_cache.h"
|
2003-07-01 18:14:24 +02:00
|
|
|
|
2003-04-02 12:06:33 +02:00
|
|
|
/*
|
|
|
|
The following is used to initialise Table_ident with a internal
|
|
|
|
table name
|
|
|
|
*/
|
|
|
|
char internal_table_name[2]= "*";
|
2006-07-19 20:33:19 +02:00
|
|
|
char empty_c_string[1]= {0}; /* used for not defined db */
|
2003-04-02 12:06:33 +02:00
|
|
|
|
2005-10-25 11:02:48 +02:00
|
|
|
const char * const THD::DEFAULT_WHERE= "field list";
|
|
|
|
|
2002-10-24 22:33:24 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
** Instansiate templates
|
|
|
|
*****************************************************************************/
|
|
|
|
|
2005-06-22 11:08:28 +02:00
|
|
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Used templates */
|
|
|
|
template class List<Key>;
|
|
|
|
template class List_iterator<Key>;
|
2007-06-10 12:43:57 +02:00
|
|
|
template class List<Key_part_spec>;
|
|
|
|
template class List_iterator<Key_part_spec>;
|
2000-07-31 21:29:14 +02:00
|
|
|
template class List<Alter_drop>;
|
|
|
|
template class List_iterator<Alter_drop>;
|
|
|
|
template class List<Alter_column>;
|
|
|
|
template class List_iterator<Alter_column>;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
** User variables
|
|
|
|
****************************************************************************/
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
extern "C" uchar *get_var_key(user_var_entry *entry, size_t *length,
|
|
|
|
my_bool not_used __attribute__((unused)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
*length= entry->name.length;
|
|
|
|
return (uchar*) entry->name.str;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2002-11-07 11:49:02 +01:00
|
|
|
extern "C" void free_user_var(user_var_entry *entry)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
char *pos= (char*) entry+ALIGN_SIZE(sizeof(*entry));
|
|
|
|
if (entry->value && entry->value != pos)
|
|
|
|
my_free(entry->value, MYF(0));
|
|
|
|
my_free((char*) entry,MYF(0));
|
|
|
|
}
|
|
|
|
|
2007-06-10 12:43:57 +02:00
|
|
|
bool Key_part_spec::operator==(const Key_part_spec& other) const
|
2004-04-21 12:15:43 +02:00
|
|
|
{
|
|
|
|
return length == other.length && !strcmp(field_name, other.field_name);
|
|
|
|
}
|
|
|
|
|
5.1 version of a fix and test cases for bugs:
Bug#4968 ""Stored procedure crash if cursor opened on altered table"
Bug#6895 "Prepared Statements: ALTER TABLE DROP COLUMN does nothing"
Bug#19182 "CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work from
stored procedure."
Bug#19733 "Repeated alter, or repeated create/drop, fails"
Bug#22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
Bug#24879 "Prepared Statements: CREATE TABLE (UTF8 KEY) produces a
growing key length" (this bug is not fixed in 5.0)
Re-execution of CREATE DATABASE, CREATE TABLE and ALTER TABLE
statements in stored routines or as prepared statements caused
incorrect results (and crashes in versions prior to 5.0.25).
In 5.1 the problem occured only for CREATE DATABASE, CREATE TABLE
SELECT and CREATE TABLE with INDEX/DATA DIRECTOY options).
The problem of bugs 4968, 19733, 19282 and 6895 was that functions
mysql_prepare_table, mysql_create_table and mysql_alter_table are not
re-execution friendly: during their operation they modify contents
of LEX (members create_info, alter_info, key_list, create_list),
thus making the LEX unusable for the next execution.
In particular, these functions removed processed columns and keys from
create_list, key_list and drop_list. Search the code in sql_table.cc
for drop_it.remove() and similar patterns to find evidence.
The fix is to supply to these functions a usable copy of each of the
above structures at every re-execution of an SQL statement.
To simplify memory management, LEX::key_list and LEX::create_list
were added to LEX::alter_info, a fresh copy of which is created for
every execution.
The problem of crashing bug 22060 stemmed from the fact that the above
metnioned functions were not only modifying HA_CREATE_INFO structure
in LEX, but also were changing it to point to areas in volatile memory
of the execution memory root.
The patch solves this problem by creating and using an on-stack
copy of HA_CREATE_INFO in mysql_execute_command.
Additionally, this patch splits the part of mysql_alter_table
that analizes and rewrites information from the parser into
a separate function - mysql_prepare_alter_table, in analogy with
mysql_prepare_table, which is renamed to mysql_prepare_create_table.
2007-05-28 13:30:01 +02:00
|
|
|
/**
|
|
|
|
Construct an (almost) deep copy of this key. Only those
|
|
|
|
elements that are known to never change are not copied.
|
|
|
|
If out of memory, a partial copy is returned and an error is set
|
|
|
|
in THD.
|
|
|
|
*/
|
|
|
|
|
|
|
|
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
|
|
|
|
:type(rhs.type),
|
|
|
|
key_create_info(rhs.key_create_info),
|
|
|
|
columns(rhs.columns, mem_root),
|
|
|
|
name(rhs.name),
|
|
|
|
generated(rhs.generated)
|
|
|
|
{
|
|
|
|
list_copy_and_replace_each_value(columns, mem_root);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Construct an (almost) deep copy of this foreign key. Only those
|
|
|
|
elements that are known to never change are not copied.
|
|
|
|
If out of memory, a partial copy is returned and an error is set
|
|
|
|
in THD.
|
|
|
|
*/
|
|
|
|
|
2007-06-10 12:43:57 +02:00
|
|
|
Foreign_key::Foreign_key(const Foreign_key &rhs, MEM_ROOT *mem_root)
|
5.1 version of a fix and test cases for bugs:
Bug#4968 ""Stored procedure crash if cursor opened on altered table"
Bug#6895 "Prepared Statements: ALTER TABLE DROP COLUMN does nothing"
Bug#19182 "CREATE TABLE bar (m INT) SELECT n FROM foo; doesn't work from
stored procedure."
Bug#19733 "Repeated alter, or repeated create/drop, fails"
Bug#22060 "ALTER TABLE x AUTO_INCREMENT=y in SP crashes server"
Bug#24879 "Prepared Statements: CREATE TABLE (UTF8 KEY) produces a
growing key length" (this bug is not fixed in 5.0)
Re-execution of CREATE DATABASE, CREATE TABLE and ALTER TABLE
statements in stored routines or as prepared statements caused
incorrect results (and crashes in versions prior to 5.0.25).
In 5.1 the problem occured only for CREATE DATABASE, CREATE TABLE
SELECT and CREATE TABLE with INDEX/DATA DIRECTOY options).
The problem of bugs 4968, 19733, 19282 and 6895 was that functions
mysql_prepare_table, mysql_create_table and mysql_alter_table are not
re-execution friendly: during their operation they modify contents
of LEX (members create_info, alter_info, key_list, create_list),
thus making the LEX unusable for the next execution.
In particular, these functions removed processed columns and keys from
create_list, key_list and drop_list. Search the code in sql_table.cc
for drop_it.remove() and similar patterns to find evidence.
The fix is to supply to these functions a usable copy of each of the
above structures at every re-execution of an SQL statement.
To simplify memory management, LEX::key_list and LEX::create_list
were added to LEX::alter_info, a fresh copy of which is created for
every execution.
The problem of crashing bug 22060 stemmed from the fact that the above
metnioned functions were not only modifying HA_CREATE_INFO structure
in LEX, but also were changing it to point to areas in volatile memory
of the execution memory root.
The patch solves this problem by creating and using an on-stack
copy of HA_CREATE_INFO in mysql_execute_command.
Additionally, this patch splits the part of mysql_alter_table
that analizes and rewrites information from the parser into
a separate function - mysql_prepare_alter_table, in analogy with
mysql_prepare_table, which is renamed to mysql_prepare_create_table.
2007-05-28 13:30:01 +02:00
|
|
|
:Key(rhs),
|
|
|
|
ref_table(rhs.ref_table),
|
|
|
|
ref_columns(rhs.ref_columns),
|
|
|
|
delete_opt(rhs.delete_opt),
|
|
|
|
update_opt(rhs.update_opt),
|
|
|
|
match_opt(rhs.match_opt)
|
|
|
|
{
|
|
|
|
list_copy_and_replace_each_value(ref_columns, mem_root);
|
|
|
|
}
|
2004-05-11 23:29:52 +02:00
|
|
|
|
|
|
|
/*
|
2004-05-15 10:57:40 +02:00
|
|
|
Test if a foreign key (= generated key) is a prefix of the given key
|
2004-05-11 23:29:52 +02:00
|
|
|
(ignoring key name, key type and order of columns)
|
|
|
|
|
|
|
|
NOTES:
|
|
|
|
This is only used to test if an index for a FOREIGN KEY exists
|
|
|
|
|
|
|
|
IMPLEMENTATION
|
|
|
|
We only compare field names
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 Generated key is a prefix of other key
|
|
|
|
1 Not equal
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool foreign_key_prefix(Key *a, Key *b)
|
2004-04-21 12:15:43 +02:00
|
|
|
{
|
2004-05-11 23:29:52 +02:00
|
|
|
/* Ensure that 'a' is the generated key */
|
|
|
|
if (a->generated)
|
|
|
|
{
|
|
|
|
if (b->generated && a->columns.elements > b->columns.elements)
|
2004-05-25 00:03:49 +02:00
|
|
|
swap_variables(Key*, a, b); // Put shorter key in 'a'
|
2004-05-11 23:29:52 +02:00
|
|
|
}
|
|
|
|
else
|
2004-04-21 12:15:43 +02:00
|
|
|
{
|
2004-05-11 23:29:52 +02:00
|
|
|
if (!b->generated)
|
|
|
|
return TRUE; // No foreign key
|
2004-05-25 00:03:49 +02:00
|
|
|
swap_variables(Key*, a, b); // Put generated key in 'a'
|
2004-05-11 23:29:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Test if 'a' is a prefix of 'b' */
|
|
|
|
if (a->columns.elements > b->columns.elements)
|
|
|
|
return TRUE; // Can't be prefix
|
|
|
|
|
2007-06-10 12:43:57 +02:00
|
|
|
List_iterator<Key_part_spec> col_it1(a->columns);
|
|
|
|
List_iterator<Key_part_spec> col_it2(b->columns);
|
|
|
|
const Key_part_spec *col1, *col2;
|
2004-05-11 23:29:52 +02:00
|
|
|
|
|
|
|
#ifdef ENABLE_WHEN_INNODB_CAN_HANDLE_SWAPED_FOREIGN_KEY_COLUMNS
|
|
|
|
while ((col1= col_it1++))
|
|
|
|
{
|
|
|
|
bool found= 0;
|
|
|
|
col_it2.rewind();
|
|
|
|
while ((col2= col_it2++))
|
2004-04-21 12:15:43 +02:00
|
|
|
{
|
2004-05-11 23:29:52 +02:00
|
|
|
if (*col1 == *col2)
|
|
|
|
{
|
|
|
|
found= TRUE;
|
|
|
|
break;
|
|
|
|
}
|
2004-04-21 12:15:43 +02:00
|
|
|
}
|
2004-05-11 23:29:52 +02:00
|
|
|
if (!found)
|
|
|
|
return TRUE; // Error
|
|
|
|
}
|
|
|
|
return FALSE; // Is prefix
|
|
|
|
#else
|
|
|
|
while ((col1= col_it1++))
|
|
|
|
{
|
|
|
|
col2= col_it2++;
|
|
|
|
if (!(*col1 == *col2))
|
|
|
|
return TRUE;
|
2004-04-21 12:15:43 +02:00
|
|
|
}
|
2004-05-11 23:29:52 +02:00
|
|
|
return FALSE; // Is prefix
|
|
|
|
#endif
|
2004-04-21 12:15:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/****************************************************************************
|
|
|
|
** Thread specific functions
|
|
|
|
****************************************************************************/
|
2005-07-13 11:48:13 +02:00
|
|
|
|
2008-05-20 09:29:16 +02:00
|
|
|
/** Push an error to the error stack and return TRUE for now. */
|
|
|
|
|
|
|
|
bool
|
|
|
|
Reprepare_observer::report_error(THD *thd)
|
|
|
|
{
|
|
|
|
my_error(ER_NEED_REPREPARE, MYF(ME_NO_WARNING_FOR_ERROR|ME_NO_SP_HANDLER));
|
|
|
|
|
|
|
|
m_invalidated= TRUE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
Open_tables_state::Open_tables_state(ulong version_arg)
|
2006-02-16 08:30:53 +01:00
|
|
|
:version(version_arg), state_flags(0U)
|
2005-07-13 11:48:13 +02:00
|
|
|
{
|
|
|
|
reset_open_tables_state();
|
|
|
|
}
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
/*
|
|
|
|
The following functions form part of the C plugin API
|
|
|
|
*/
|
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
extern "C" int mysql_tmpfile(const char *prefix)
|
|
|
|
{
|
|
|
|
char filename[FN_REFLEN];
|
|
|
|
File fd = create_temp_file(filename, mysql_tmpdir, prefix,
|
|
|
|
#ifdef __WIN__
|
|
|
|
O_BINARY | O_TRUNC | O_SEQUENTIAL |
|
|
|
|
O_SHORT_LIVED |
|
|
|
|
#endif /* __WIN__ */
|
|
|
|
O_CREAT | O_EXCL | O_RDWR | O_TEMPORARY,
|
|
|
|
MYF(MY_WME));
|
|
|
|
if (fd >= 0) {
|
|
|
|
#ifndef __WIN__
|
|
|
|
/*
|
|
|
|
This can be removed once the following bug is fixed:
|
|
|
|
Bug #28903 create_temp_file() doesn't honor O_TEMPORARY option
|
|
|
|
(file not removed) (Unix)
|
|
|
|
*/
|
|
|
|
unlink(filename);
|
|
|
|
#endif /* !__WIN__ */
|
|
|
|
}
|
|
|
|
|
|
|
|
return fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-03-02 17:43:45 +01:00
|
|
|
int thd_in_lock_tables(const THD *thd)
|
2006-01-19 22:40:56 +01:00
|
|
|
{
|
2007-03-02 17:43:45 +01:00
|
|
|
return test(thd->in_lock_tables);
|
2006-01-19 22:40:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-03-02 17:43:45 +01:00
|
|
|
int thd_tablespace_op(const THD *thd)
|
2006-01-19 22:40:56 +01:00
|
|
|
{
|
2007-03-02 17:43:45 +01:00
|
|
|
return test(thd->tablespace_op);
|
2006-01-19 22:40:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-05-02 20:13:33 +02:00
|
|
|
const char *set_thd_proc_info(THD *thd, const char *info,
|
|
|
|
const char *calling_function,
|
|
|
|
const char *calling_file,
|
|
|
|
const unsigned int calling_line)
|
2006-01-19 22:40:56 +01:00
|
|
|
{
|
|
|
|
const char *old_info= thd->proc_info;
|
2008-03-05 17:23:58 +01:00
|
|
|
DBUG_PRINT("proc_info", ("%s:%d %s", calling_file, calling_line,
|
|
|
|
(info != NULL) ? info : "(null)"));
|
2007-05-02 20:13:33 +02:00
|
|
|
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
|
|
|
|
thd->profiling.status_change(info, calling_function, calling_file, calling_line);
|
|
|
|
#endif
|
2006-01-19 22:40:56 +01:00
|
|
|
thd->proc_info= info;
|
|
|
|
return old_info;
|
|
|
|
}
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2006-05-27 07:05:39 +02:00
|
|
|
void **thd_ha_data(const THD *thd, const struct handlerton *hton)
|
|
|
|
{
|
2008-02-19 12:43:01 +01:00
|
|
|
return (void **) &thd->ha_data[hton->slot].ha_ptr;
|
2006-05-27 07:05:39 +02:00
|
|
|
}
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-03-02 17:43:45 +01:00
|
|
|
long long thd_test_options(const THD *thd, long long test_options)
|
|
|
|
{
|
|
|
|
return thd->options & test_options;
|
|
|
|
}
|
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-03-02 17:43:45 +01:00
|
|
|
int thd_sql_command(const THD *thd)
|
|
|
|
{
|
|
|
|
return (int) thd->lex->sql_command;
|
|
|
|
}
|
|
|
|
|
2007-04-15 15:47:27 +02:00
|
|
|
extern "C"
|
|
|
|
int thd_tx_isolation(const THD *thd)
|
|
|
|
{
|
|
|
|
return (int) thd->variables.tx_isolation;
|
|
|
|
}
|
|
|
|
|
2007-07-03 14:17:58 +02:00
|
|
|
extern "C"
|
|
|
|
void thd_inc_row_count(THD *thd)
|
|
|
|
{
|
|
|
|
thd->row_count++;
|
|
|
|
}
|
2007-03-02 17:43:45 +01:00
|
|
|
|
2008-11-07 13:12:56 +01:00
|
|
|
|
|
|
|
/**
|
2007-03-02 17:43:45 +01:00
|
|
|
Dumps a text description of a thread, its security context
|
|
|
|
(user, host) and the current query.
|
2007-04-15 15:47:27 +02:00
|
|
|
|
2008-11-07 13:12:56 +01:00
|
|
|
@param thd current thread context
|
|
|
|
@param buffer pointer to preferred result buffer
|
|
|
|
@param length length of buffer
|
|
|
|
@param max_query_len how many chars of query to copy (0 for all)
|
|
|
|
|
|
|
|
@req LOCK_thread_count
|
|
|
|
|
|
|
|
@note LOCK_thread_count mutex is not necessary when the function is invoked on
|
|
|
|
the currently running thread (current_thd) or if the caller in some other
|
|
|
|
way guarantees that access to thd->query is serialized.
|
|
|
|
|
|
|
|
@return Pointer to string
|
2007-03-02 17:43:45 +01:00
|
|
|
*/
|
2008-11-07 13:12:56 +01:00
|
|
|
|
2007-03-23 18:14:46 +01:00
|
|
|
extern "C"
|
2007-04-13 19:23:02 +02:00
|
|
|
char *thd_security_context(THD *thd, char *buffer, unsigned int length,
|
|
|
|
unsigned int max_query_len)
|
2007-03-02 17:43:45 +01:00
|
|
|
{
|
|
|
|
String str(buffer, length, &my_charset_latin1);
|
|
|
|
const Security_context *sctx= &thd->main_security_ctx;
|
|
|
|
char header[64];
|
|
|
|
int len;
|
2008-11-07 13:12:56 +01:00
|
|
|
/*
|
|
|
|
The pointers thd->query and thd->proc_info might change since they are
|
|
|
|
being modified concurrently. This is acceptable for proc_info since its
|
|
|
|
values doesn't have to very accurate and the memory it points to is static,
|
|
|
|
but we need to attempt a snapshot on the pointer values to avoid using NULL
|
|
|
|
values. The pointer to thd->query however, doesn't point to static memory
|
|
|
|
and has to be protected by LOCK_thread_count or risk pointing to
|
|
|
|
uninitialized memory.
|
|
|
|
*/
|
|
|
|
const char *proc_info= thd->proc_info;
|
2007-04-15 15:47:27 +02:00
|
|
|
|
|
|
|
len= my_snprintf(header, sizeof(header),
|
2007-03-02 17:43:45 +01:00
|
|
|
"MySQL thread id %lu, query id %lu",
|
|
|
|
thd->thread_id, (ulong) thd->query_id);
|
|
|
|
str.length(0);
|
|
|
|
str.append(header, len);
|
2007-04-15 15:47:27 +02:00
|
|
|
|
2007-03-02 17:43:45 +01:00
|
|
|
if (sctx->host)
|
|
|
|
{
|
|
|
|
str.append(' ');
|
|
|
|
str.append(sctx->host);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sctx->ip)
|
|
|
|
{
|
|
|
|
str.append(' ');
|
|
|
|
str.append(sctx->ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (sctx->user)
|
|
|
|
{
|
|
|
|
str.append(' ');
|
|
|
|
str.append(sctx->user);
|
|
|
|
}
|
|
|
|
|
2008-11-07 13:12:56 +01:00
|
|
|
if (proc_info)
|
2007-03-02 17:43:45 +01:00
|
|
|
{
|
|
|
|
str.append(' ');
|
2008-11-07 13:12:56 +01:00
|
|
|
str.append(proc_info);
|
2007-03-02 17:43:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (thd->query)
|
|
|
|
{
|
|
|
|
if (max_query_len < 1)
|
|
|
|
len= thd->query_length;
|
|
|
|
else
|
|
|
|
len= min(thd->query_length, max_query_len);
|
|
|
|
str.append('\n');
|
|
|
|
str.append(thd->query, len);
|
|
|
|
}
|
|
|
|
if (str.c_ptr_safe() == buffer)
|
|
|
|
return buffer;
|
|
|
|
return thd->strmake(str.ptr(), str.length());
|
|
|
|
}
|
2005-07-13 11:48:13 +02:00
|
|
|
|
2007-12-12 16:21:01 +01:00
|
|
|
/**
|
|
|
|
Clear this diagnostics area.
|
|
|
|
|
|
|
|
Normally called at the end of a statement.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
Diagnostics_area::reset_diagnostics_area()
|
|
|
|
{
|
|
|
|
#ifdef DBUG_OFF
|
|
|
|
can_overwrite_status= FALSE;
|
|
|
|
/** Don't take chances in production */
|
|
|
|
m_message[0]= '\0';
|
|
|
|
m_sql_errno= 0;
|
|
|
|
m_server_status= 0;
|
|
|
|
m_affected_rows= 0;
|
|
|
|
m_last_insert_id= 0;
|
|
|
|
m_total_warn_count= 0;
|
|
|
|
#endif
|
|
|
|
is_sent= FALSE;
|
|
|
|
/** Tiny reset in debug mode to see garbage right away */
|
|
|
|
m_status= DA_EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set OK status -- ends commands that do not return a
|
|
|
|
result set, e.g. INSERT/UPDATE/DELETE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
|
2007-12-13 03:37:38 +01:00
|
|
|
ulonglong last_insert_id_arg,
|
2007-12-12 16:21:01 +01:00
|
|
|
const char *message_arg)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(! is_set());
|
|
|
|
#ifdef DBUG_OFF
|
2008-03-17 20:39:09 +01:00
|
|
|
/*
|
|
|
|
In production, refuse to overwrite an error or a custom response
|
|
|
|
with an OK packet.
|
|
|
|
*/
|
|
|
|
if (is_error() || is_disabled())
|
2007-12-12 16:21:01 +01:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
/** Only allowed to report success if has not yet reported an error */
|
|
|
|
|
|
|
|
m_server_status= thd->server_status;
|
|
|
|
m_total_warn_count= thd->total_warn_count;
|
|
|
|
m_affected_rows= affected_rows_arg;
|
|
|
|
m_last_insert_id= last_insert_id_arg;
|
|
|
|
if (message_arg)
|
2008-02-09 08:31:22 +01:00
|
|
|
strmake(m_message, message_arg, sizeof(m_message) - 1);
|
2007-12-12 16:21:01 +01:00
|
|
|
else
|
|
|
|
m_message[0]= '\0';
|
|
|
|
m_status= DA_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set EOF status.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
Diagnostics_area::set_eof_status(THD *thd)
|
|
|
|
{
|
|
|
|
/** Only allowed to report eof if has not yet reported an error */
|
|
|
|
|
|
|
|
DBUG_ASSERT(! is_set());
|
|
|
|
#ifdef DBUG_OFF
|
2008-03-17 20:39:09 +01:00
|
|
|
/*
|
|
|
|
In production, refuse to overwrite an error or a custom response
|
|
|
|
with an EOF packet.
|
|
|
|
*/
|
|
|
|
if (is_error() || is_disabled())
|
2007-12-12 16:21:01 +01:00
|
|
|
return;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
m_server_status= thd->server_status;
|
|
|
|
/*
|
|
|
|
If inside a stored procedure, do not return the total
|
|
|
|
number of warnings, since they are not available to the client
|
|
|
|
anyway.
|
|
|
|
*/
|
|
|
|
m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
|
|
|
|
|
|
|
|
m_status= DA_EOF;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Set ERROR status.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
|
|
|
|
const char *message_arg)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Only allowed to report error if has not yet reported a success
|
|
|
|
The only exception is when we flush the message to the client,
|
|
|
|
an error can happen during the flush.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(! is_set() || can_overwrite_status);
|
2008-03-17 20:39:09 +01:00
|
|
|
#ifdef DBUG_OFF
|
|
|
|
/*
|
|
|
|
In production, refuse to overwrite a custom response with an
|
|
|
|
ERROR packet.
|
|
|
|
*/
|
|
|
|
if (is_disabled())
|
|
|
|
return;
|
|
|
|
#endif
|
2007-12-12 16:21:01 +01:00
|
|
|
|
|
|
|
m_sql_errno= sql_errno_arg;
|
2008-02-09 08:31:22 +01:00
|
|
|
strmake(m_message, message_arg, sizeof(m_message) - 1);
|
2007-12-12 16:21:01 +01:00
|
|
|
|
|
|
|
m_status= DA_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
Mark the diagnostics area as 'DISABLED'.
|
|
|
|
|
|
|
|
This is used in rare cases when the COM_ command at hand sends a response
|
|
|
|
in a custom format. One example is the query cache, another is
|
|
|
|
COM_STMT_PREPARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
|
|
|
Diagnostics_area::disable_status()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(! is_set());
|
|
|
|
m_status= DA_DISABLED;
|
|
|
|
}
|
2005-07-13 11:48:13 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2004-08-24 17:00:45 +02:00
|
|
|
THD::THD()
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
:Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
|
|
|
|
/* statement id */ 0),
|
2005-12-22 06:39:02 +01:00
|
|
|
Open_tables_state(refresh_version), rli_fake(0),
|
2005-07-19 20:21:12 +02:00
|
|
|
lock_id(&main_lock_id),
|
2006-04-24 16:39:33 +02:00
|
|
|
user_time(0), in_sub_stmt(0),
|
2007-05-14 14:45:38 +02:00
|
|
|
binlog_table_maps(0), binlog_flags(0UL),
|
2008-08-26 12:07:56 +02:00
|
|
|
table_map_for_update(0),
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
arg_of_last_insert_id_function(FALSE),
|
|
|
|
first_successful_insert_id_in_prev_stmt(0),
|
|
|
|
first_successful_insert_id_in_prev_stmt_for_binlog(0),
|
|
|
|
first_successful_insert_id_in_cur_stmt(0),
|
|
|
|
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
|
2007-04-16 18:16:17 +02:00
|
|
|
global_read_lock(0),
|
|
|
|
is_fatal_error(0),
|
2007-08-02 02:59:41 +02:00
|
|
|
transaction_rollback_request(0),
|
|
|
|
is_fatal_sub_stmt_error(0),
|
2007-04-13 19:23:02 +02:00
|
|
|
rand_used(0),
|
|
|
|
time_zone_used(0),
|
|
|
|
in_lock_tables(0),
|
|
|
|
bootstrap(0),
|
|
|
|
derived_tables_processing(FALSE),
|
2007-06-14 16:35:59 +02:00
|
|
|
spcont(NULL),
|
2008-07-14 23:41:30 +02:00
|
|
|
m_parser_state(NULL)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
ulong tmp;
|
|
|
|
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
/*
|
|
|
|
Pass nominal parameters to init_alloc_root only to ensure that
|
|
|
|
the destructor works OK in case of an error. The main_mem_root
|
|
|
|
will be re-initialized in init_for_queries().
|
|
|
|
*/
|
|
|
|
init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
|
2005-09-02 15:21:19 +02:00
|
|
|
stmt_arena= this;
|
2005-11-24 19:13:13 +01:00
|
|
|
thread_stack= 0;
|
This will be pushed only after I fix the testsuite.
This is the main commit for Worklog tasks:
* A more dynamic binlog format which allows small changes (1064)
* Log session variables in Query_log_event (1063)
Below 5.0 means 5.0.0.
MySQL 5.0 is able to replicate FOREIGN_KEY_CHECKS, UNIQUE_KEY_CHECKS (for speed),
SQL_AUTO_IS_NULL, SQL_MODE. Not charsets (WL#1062), not some vars (I can only think
of SQL_SELECT_LIMIT, which deserves a special treatment). Note that this
works for queries, except LOAD DATA INFILE (for this it would have to wait
for Dmitri's push of WL#874, which in turns waits for the present push, so...
the deadlock must be broken!). Note that when Dmitri pushes WL#874 in 5.0.1,
5.0.0 won't be able to replicate a LOAD DATA INFILE from 5.0.1.
Apart from that, the new binlog format is designed so that it can tolerate
a little variation in the events (so that a 5.0.0 slave could replicate a
5.0.1 master, except for LOAD DATA INFILE unfortunately); that is, when I
later add replication of charsets it should break nothing. And when I later
add a UID to every event, it should break nothing.
The main change brought by this patch is a new type of event, Format_description_log_event,
which describes some lengthes in other event types. This event is needed for
the master/slave/mysqlbinlog to understand a 5.0 log. Thanks to this event,
we can later add more bytes to the header of every event without breaking compatibility.
Inside Query_log_event, we have some additional dynamic format, as every Query_log_event
can have a different number of status variables, stored as pairs (code, value); that's
how SQL_MODE and session variables and catalog are stored. Like this, we can later
add count of affected rows, charsets... and we can have options --don't-log-count-affected-rows
if we want.
MySQL 5.0 is able to run on 4.x relay logs, 4.x binlogs.
Upgrading a 4.x master to 5.0 is ok (no need to delete binlogs),
upgrading a 4.x slave to 5.0 is ok (no need to delete relay logs);
so both can be "hot" upgrades.
Upgrading a 3.23 master to 5.0 requires as much as upgrading it to 4.0.
3.23 and 4.x can't be slaves of 5.0.
So downgrading from 5.0 to 4.x may be complicated.
Log_event::log_pos is now the position of the end of the event, which is
more useful than the position of the beginning. We take care about compatibility
with <5.0 (in which log_pos is the beginning).
I added a short test for replication of SQL_MODE and some other variables.
TODO:
- after committing this, merge the latest 5.0 into it
- fix all tests
- update the manual with upgrade notes.
2003-12-18 01:09:05 +01:00
|
|
|
catalog= (char*)"std"; // the only catalog we have for now
|
2005-09-15 21:29:07 +02:00
|
|
|
main_security_ctx.init();
|
|
|
|
security_ctx= &main_security_ctx;
|
2003-12-01 16:14:40 +01:00
|
|
|
locked=some_tables_deleted=no_errors=password= 0;
|
2003-11-25 15:41:12 +01:00
|
|
|
query_start_used= 0;
|
2003-10-11 22:26:39 +02:00
|
|
|
count_cuted_fields= CHECK_FIELD_IGNORE;
|
2003-03-31 10:39:46 +02:00
|
|
|
killed= NOT_KILLED;
|
2007-08-31 18:42:14 +02:00
|
|
|
col_access=0;
|
2007-10-19 23:20:38 +02:00
|
|
|
is_slave_error= thread_specific_used= FALSE;
|
2004-09-24 18:39:25 +02:00
|
|
|
hash_clear(&handler_tables_hash);
|
2000-07-31 21:29:14 +02:00
|
|
|
tmp_table=0;
|
2000-10-03 13:18:03 +02:00
|
|
|
used_tables=0;
|
2006-06-06 01:47:30 +02:00
|
|
|
cuted_fields= sent_row_count= row_count= 0L;
|
2004-10-27 11:51:17 +02:00
|
|
|
limit_found_rows= 0;
|
2007-08-01 20:40:04 +02:00
|
|
|
row_count_func= -1;
|
2003-11-27 18:51:53 +01:00
|
|
|
statement_id_counter= 0UL;
|
2006-02-03 18:05:30 +01:00
|
|
|
#ifdef ERROR_INJECT_SUPPORT
|
|
|
|
error_inject_value= 0UL;
|
|
|
|
#endif
|
2003-11-02 13:00:25 +01:00
|
|
|
// Must be reset to handle error with THD's created for init of mysqld
|
2003-12-04 20:08:26 +01:00
|
|
|
lex->current_select= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
start_time=(time_t) 0;
|
2007-07-30 10:33:50 +02:00
|
|
|
start_utime= 0L;
|
|
|
|
utime_after_lock= 0L;
|
2000-10-27 06:11:55 +02:00
|
|
|
current_linfo = 0;
|
2000-11-14 07:43:02 +01:00
|
|
|
slave_thread = 0;
|
2007-05-05 01:44:07 +02:00
|
|
|
bzero(&variables, sizeof(variables));
|
2007-07-14 14:58:39 +02:00
|
|
|
thread_id= 0;
|
2004-06-03 23:17:18 +02:00
|
|
|
one_shot_set= 0;
|
2001-07-21 00:22:54 +02:00
|
|
|
file_id = 0;
|
2005-03-23 21:39:20 +01:00
|
|
|
query_id= 0;
|
2002-11-21 01:07:14 +01:00
|
|
|
warn_id= 0;
|
2003-09-15 13:31:04 +02:00
|
|
|
db_charset= global_system_variables.collation_database;
|
2005-01-16 13:16:23 +01:00
|
|
|
bzero(ha_data, sizeof(ha_data));
|
2001-03-21 00:02:22 +01:00
|
|
|
mysys_var=0;
|
2005-08-25 15:34:34 +02:00
|
|
|
binlog_evt_union.do_union= FALSE;
|
This changeset is largely a handler cleanup changeset (WL#3281), but includes fixes and cleanups that was found necessary while testing the handler changes
Changes that requires code changes in other code of other storage engines.
(Note that all changes are very straightforward and one should find all issues
by compiling a --debug build and fixing all compiler errors and all
asserts in field.cc while running the test suite),
- New optional handler function introduced: reset()
This is called after every DML statement to make it easy for a handler to
statement specific cleanups.
(The only case it's not called is if force the file to be closed)
- handler::extra(HA_EXTRA_RESET) is removed. Code that was there before
should be moved to handler::reset()
- table->read_set contains a bitmap over all columns that are needed
in the query. read_row() and similar functions only needs to read these
columns
- table->write_set contains a bitmap over all columns that will be updated
in the query. write_row() and update_row() only needs to update these
columns.
The above bitmaps should now be up to date in all context
(including ALTER TABLE, filesort()).
The handler is informed of any changes to the bitmap after
fix_fields() by calling the virtual function
handler::column_bitmaps_signal(). If the handler does caching of
these bitmaps (instead of using table->read_set, table->write_set),
it should redo the caching in this code. as the signal() may be sent
several times, it's probably best to set a variable in the signal
and redo the caching on read_row() / write_row() if the variable was
set.
- Removed the read_set and write_set bitmap objects from the handler class
- Removed all column bit handling functions from the handler class.
(Now one instead uses the normal bitmap functions in my_bitmap.c instead
of handler dedicated bitmap functions)
- field->query_id is removed. One should instead instead check
table->read_set and table->write_set if a field is used in the query.
- handler::extra(HA_EXTRA_RETRIVE_ALL_COLS) and
handler::extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) are removed. One should now
instead use table->read_set to check for which columns to retrieve.
- If a handler needs to call Field->val() or Field->store() on columns
that are not used in the query, one should install a temporary
all-columns-used map while doing so. For this, we provide the following
functions:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
field->val();
dbug_tmp_restore_column_map(table->read_set, old_map);
and similar for the write map:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
field->val();
dbug_tmp_restore_column_map(table->write_set, old_map);
If this is not done, you will sooner or later hit a DBUG_ASSERT
in the field store() / val() functions.
(For not DBUG binaries, the dbug_tmp_restore_column_map() and
dbug_tmp_restore_column_map() are inline dummy functions and should
be optimized away be the compiler).
- If one needs to temporary set the column map for all binaries (and not
just to avoid the DBUG_ASSERT() in the Field::store() / Field::val()
methods) one should use the functions tmp_use_all_columns() and
tmp_restore_column_map() instead of the above dbug_ variants.
- All 'status' fields in the handler base class (like records,
data_file_length etc) are now stored in a 'stats' struct. This makes
it easier to know what status variables are provided by the base
handler. This requires some trivial variable names in the extra()
function.
- New virtual function handler::records(). This is called to optimize
COUNT(*) if (handler::table_flags() & HA_HAS_RECORDS()) is true.
(stats.records is not supposed to be an exact value. It's only has to
be 'reasonable enough' for the optimizer to be able to choose a good
optimization path).
- Non virtual handler::init() function added for caching of virtual
constants from engine.
- Removed has_transactions() virtual method. Now one should instead return
HA_NO_TRANSACTIONS in table_flags() if the table handler DOES NOT support
transactions.
- The 'xxxx_create_handler()' function now has a MEM_ROOT_root argument
that is to be used with 'new handler_name()' to allocate the handler
in the right area. The xxxx_create_handler() function is also
responsible for any initialization of the object before returning.
For example, one should change:
static handler *myisam_create_handler(TABLE_SHARE *table)
{
return new ha_myisam(table);
}
->
static handler *myisam_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) ha_myisam(table);
}
- New optional virtual function: use_hidden_primary_key().
This is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
but we don't have a primary key. This allows the handler to take precisions
in remembering any hidden primary key to able to update/delete any
found row. The default handler marks all columns to be read.
- handler::table_flags() now returns a ulonglong (to allow for more flags).
- New/changed table_flags()
- HA_HAS_RECORDS Set if ::records() is supported
- HA_NO_TRANSACTIONS Set if engine doesn't support transactions
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE
Set if we should mark all primary key columns for
read when reading rows as part of a DELETE
statement. If there is no primary key,
all columns are marked for read.
- HA_PARTIAL_COLUMN_READ Set if engine will not read all columns in some
cases (based on table->read_set)
- HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
Renamed to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
- HA_DUPP_POS Renamed to HA_DUPLICATE_POS
- HA_REQUIRES_KEY_COLUMNS_FOR_DELETE
Set this if we should mark ALL key columns for
read when when reading rows as part of a DELETE
statement. In case of an update we will mark
all keys for read for which key part changed
value.
- HA_STATS_RECORDS_IS_EXACT
Set this if stats.records is exact.
(This saves us some extra records() calls
when optimizing COUNT(*))
- Removed table_flags()
- HA_NOT_EXACT_COUNT Now one should instead use HA_HAS_RECORDS if
handler::records() gives an exact count() and
HA_STATS_RECORDS_IS_EXACT if stats.records is exact.
- HA_READ_RND_SAME Removed (no one supported this one)
- Removed not needed functions ha_retrieve_all_cols() and ha_retrieve_all_pk()
- Renamed handler::dupp_pos to handler::dup_pos
- Removed not used variable handler::sortkey
Upper level handler changes:
- ha_reset() now does some overall checks and calls ::reset()
- ha_table_flags() added. This is a cached version of table_flags(). The
cache is updated on engine creation time and updated on open.
MySQL level changes (not obvious from the above):
- DBUG_ASSERT() added to check that column usage matches what is set
in the column usage bit maps. (This found a LOT of bugs in current
column marking code).
- In 5.1 before, all used columns was marked in read_set and only updated
columns was marked in write_set. Now we only mark columns for which we
need a value in read_set.
- Column bitmaps are created in open_binary_frm() and open_table_from_share().
(Before this was in table.cc)
- handler::table_flags() calls are replaced with handler::ha_table_flags()
- For calling field->val() you must have the corresponding bit set in
table->read_set. For calling field->store() you must have the
corresponding bit set in table->write_set. (There are asserts in
all store()/val() functions to catch wrong usage)
- thd->set_query_id is renamed to thd->mark_used_columns and instead
of setting this to an integer value, this has now the values:
MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE
Changed also all variables named 'set_query_id' to mark_used_columns.
- In filesort() we now inform the handler of exactly which columns are needed
doing the sort and choosing the rows.
- The TABLE_SHARE object has a 'all_set' column bitmap one can use
when one needs a column bitmap with all columns set.
(This is used for table->use_all_columns() and other places)
- The TABLE object has 3 column bitmaps:
- def_read_set Default bitmap for columns to be read
- def_write_set Default bitmap for columns to be written
- tmp_set Can be used as a temporary bitmap when needed.
The table object has also two pointer to bitmaps read_set and write_set
that the handler should use to find out which columns are used in which way.
- count() optimization now calls handler::records() instead of using
handler->stats.records (if (table_flags() & HA_HAS_RECORDS) is true).
- Added extra argument to Item::walk() to indicate if we should also
traverse sub queries.
- Added TABLE parameter to cp_buffer_from_ref()
- Don't close tables created with CREATE ... SELECT but keep them in
the table cache. (Faster usage of newly created tables).
New interfaces:
- table->clear_column_bitmaps() to initialize the bitmaps for tables
at start of new statements.
- table->column_bitmaps_set() to set up new column bitmaps and signal
the handler about this.
- table->column_bitmaps_set_no_signal() for some few cases where we need
to setup new column bitmaps but don't signal the handler (as the handler
has already been signaled about these before). Used for the momement
only in opt_range.cc when doing ROR scans.
- table->use_all_columns() to install a bitmap where all columns are marked
as use in the read and the write set.
- table->default_column_bitmaps() to install the normal read and write
column bitmaps, but not signaling the handler about this.
This is mainly used when creating TABLE instances.
- table->mark_columns_needed_for_delete(),
table->mark_columns_needed_for_delete() and
table->mark_columns_needed_for_insert() to allow us to put additional
columns in column usage maps if handler so requires.
(The handler indicates what it neads in handler->table_flags())
- table->prepare_for_position() to allow us to tell handler that it
needs to read primary key parts to be able to store them in
future table->position() calls.
(This replaces the table->file->ha_retrieve_all_pk function)
- table->mark_auto_increment_column() to tell handler are going to update
columns part of any auto_increment key.
- table->mark_columns_used_by_index() to mark all columns that is part of
an index. It will also send extra(HA_EXTRA_KEYREAD) to handler to allow
it to quickly know that it only needs to read colums that are part
of the key. (The handler can also use the column map for detecting this,
but simpler/faster handler can just monitor the extra() call).
- table->mark_columns_used_by_index_no_reset() to in addition to other columns,
also mark all columns that is used by the given key.
- table->restore_column_maps_after_mark_index() to restore to default
column maps after a call to table->mark_columns_used_by_index().
- New item function register_field_in_read_map(), for marking used columns
in table->read_map. Used by filesort() to mark all used columns
- Maintain in TABLE->merge_keys set of all keys that are used in query.
(Simplices some optimization loops)
- Maintain Field->part_of_key_not_clustered which is like Field->part_of_key
but the field in the clustered key is not assumed to be part of all index.
(used in opt_range.cc for faster loops)
- dbug_tmp_use_all_columns(), dbug_tmp_restore_column_map()
tmp_use_all_columns() and tmp_restore_column_map() functions to temporally
mark all columns as usable. The 'dbug_' version is primarily intended
inside a handler when it wants to just call Field:store() & Field::val()
functions, but don't need the column maps set for any other usage.
(ie:: bitmap_is_set() is never called)
- We can't use compare_records() to skip updates for handlers that returns
a partial column set and the read_set doesn't cover all columns in the
write set. The reason for this is that if we have a column marked only for
write we can't in the MySQL level know if the value changed or not.
The reason this worked before was that MySQL marked all to be written
columns as also to be read. The new 'optimal' bitmaps exposed this 'hidden
bug'.
- open_table_from_share() does not anymore setup temporary MEM_ROOT
object as a thread specific variable for the handler. Instead we
send the to-be-used MEMROOT to get_new_handler().
(Simpler, faster code)
Bugs fixed:
- Column marking was not done correctly in a lot of cases.
(ALTER TABLE, when using triggers, auto_increment fields etc)
(Could potentially result in wrong values inserted in table handlers
relying on that the old column maps or field->set_query_id was correct)
Especially when it comes to triggers, there may be cases where the
old code would cause lost/wrong values for NDB and/or InnoDB tables.
- Split thd->options flag OPTION_STATUS_NO_TRANS_UPDATE to two flags:
OPTION_STATUS_NO_TRANS_UPDATE and OPTION_KEEP_LOG.
This allowed me to remove some wrong warnings about:
"Some non-transactional changed tables couldn't be rolled back"
- Fixed handling of INSERT .. SELECT and CREATE ... SELECT that wrongly reset
(thd->options & OPTION_STATUS_NO_TRANS_UPDATE) which caused us to loose
some warnings about
"Some non-transactional changed tables couldn't be rolled back")
- Fixed use of uninitialized memory in ha_ndbcluster.cc::delete_table()
which could cause delete_table to report random failures.
- Fixed core dumps for some tests when running with --debug
- Added missing FN_LIBCHAR in mysql_rm_tmp_tables()
(This has probably caused us to not properly remove temporary files after
crash)
- slow_logs was not properly initialized, which could maybe cause
extra/lost entries in slow log.
- If we get an duplicate row on insert, change column map to read and
write all columns while retrying the operation. This is required by
the definition of REPLACE and also ensures that fields that are only
part of UPDATE are properly handled. This fixed a bug in NDB and
REPLACE where REPLACE wrongly copied some column values from the replaced
row.
- For table handler that doesn't support NULL in keys, we would give an error
when creating a primary key with NULL fields, even after the fields has been
automaticly converted to NOT NULL.
- Creating a primary key on a SPATIAL key, would fail if field was not
declared as NOT NULL.
Cleanups:
- Removed not used condition argument to setup_tables
- Removed not needed item function reset_query_id_processor().
- Field->add_index is removed. Now this is instead maintained in
(field->flags & FIELD_IN_ADD_INDEX)
- Field->fieldnr is removed (use field->field_index instead)
- New argument to filesort() to indicate that it should return a set of
row pointers (not used columns). This allowed me to remove some references
to sql_command in filesort and should also enable us to return column
results in some cases where we couldn't before.
- Changed column bitmap handling in opt_range.cc to be aligned with TABLE
bitmap, which allowed me to use bitmap functions instead of looping over
all fields to create some needed bitmaps. (Faster and smaller code)
- Broke up found too long lines
- Moved some variable declaration at start of function for better code
readability.
- Removed some not used arguments from functions.
(setup_fields(), mysql_prepare_insert_check_table())
- setup_fields() now takes an enum instead of an int for marking columns
usage.
- For internal temporary tables, use handler::write_row(),
handler::delete_row() and handler::update_row() instead of
handler::ha_xxxx() for faster execution.
- Changed some constants to enum's and define's.
- Using separate column read and write sets allows for easier checking
of timestamp field was set by statement.
- Remove calls to free_io_cache() as this is now done automaticly in ha_reset()
- Don't build table->normalized_path as this is now identical to table->path
(after bar's fixes to convert filenames)
- Fixed some missed DBUG_PRINT(.."%lx") to use "0x%lx" to make it easier to
do comparision with the 'convert-dbug-for-diff' tool.
Things left to do in 5.1:
- We wrongly log failed CREATE TABLE ... SELECT in some cases when using
row based logging (as shown by testcase binlog_row_mix_innodb_myisam.result)
Mats has promised to look into this.
- Test that my fix for CREATE TABLE ... SELECT is indeed correct.
(I added several test cases for this, but in this case it's better that
someone else also tests this throughly).
Lars has promosed to do this.
2006-06-04 17:52:22 +02:00
|
|
|
enable_slow_log= 0;
|
2002-03-30 20:36:05 +01:00
|
|
|
#ifndef DBUG_OFF
|
|
|
|
dbug_sentry=THD_SENTRY_MAGIC;
|
2002-12-16 14:33:29 +01:00
|
|
|
#endif
|
2005-04-12 23:08:19 +02:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
2001-03-21 00:02:22 +01:00
|
|
|
net.vio=0;
|
2002-12-16 14:33:29 +01:00
|
|
|
#endif
|
2005-10-14 15:34:52 +02:00
|
|
|
client_capabilities= 0; // minimalistic client
|
2007-03-06 22:55:52 +01:00
|
|
|
#ifdef HAVE_QUERY_CACHE
|
2006-08-22 09:47:52 +02:00
|
|
|
query_cache_init_query(&net); // If error on boot
|
2007-03-06 22:55:52 +01:00
|
|
|
#endif
|
2001-03-21 00:02:22 +01:00
|
|
|
ull=0;
|
2006-05-22 20:46:13 +02:00
|
|
|
system_thread= NON_SYSTEM_THREAD;
|
|
|
|
cleanup_done= abort_on_warning= no_warnings_for_error= 0;
|
2003-04-26 19:43:28 +02:00
|
|
|
peer_port= 0; // For SHOW PROCESSLIST
|
2005-12-22 06:39:02 +01:00
|
|
|
transaction.m_pending_rows_event= 0;
|
2007-10-11 17:07:40 +02:00
|
|
|
transaction.on= 1;
|
2001-03-21 00:02:22 +01:00
|
|
|
#ifdef SIGNAL_WITH_VIO_CLOSE
|
|
|
|
active_vio = 0;
|
2005-04-12 23:08:19 +02:00
|
|
|
#endif
|
2002-08-22 15:50:58 +02:00
|
|
|
pthread_mutex_init(&LOCK_delete, MY_MUTEX_INIT_FAST);
|
2001-03-21 00:02:22 +01:00
|
|
|
|
|
|
|
/* Variables with default values */
|
|
|
|
proc_info="login";
|
2005-10-25 11:02:48 +02:00
|
|
|
where= THD::DEFAULT_WHERE;
|
2001-03-21 00:02:22 +01:00
|
|
|
server_id = ::server_id;
|
2001-08-03 23:57:53 +02:00
|
|
|
slave_net = 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
command=COM_CONNECT;
|
2003-07-18 16:57:21 +02:00
|
|
|
*scramble= '\0';
|
2001-03-21 00:02:22 +01:00
|
|
|
|
2002-11-16 19:19:10 +01:00
|
|
|
init();
|
2001-03-21 00:02:22 +01:00
|
|
|
/* Initialize sub structures */
|
2004-10-21 09:58:03 +02:00
|
|
|
init_sql_alloc(&warn_root, WARN_ALLOC_BLOCK_SIZE, WARN_ALLOC_PREALLOC_SIZE);
|
2007-04-25 00:11:55 +02:00
|
|
|
#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
|
2007-01-03 23:15:10 +01:00
|
|
|
profiling.set_thd(this);
|
2007-02-22 16:03:08 +01:00
|
|
|
#endif
|
2002-05-15 12:50:38 +02:00
|
|
|
user_connect=(USER_CONN *)0;
|
2003-05-12 15:36:31 +02:00
|
|
|
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
|
2000-07-31 21:29:14 +02:00
|
|
|
(hash_get_key) get_var_key,
|
2003-05-12 15:36:31 +02:00
|
|
|
(hash_free_key) free_user_var, 0);
|
2003-07-03 15:58:37 +02:00
|
|
|
|
2003-10-21 12:08:35 +02:00
|
|
|
sp_proc_cache= NULL;
|
|
|
|
sp_func_cache= NULL;
|
2002-10-02 12:33:08 +02:00
|
|
|
|
2003-01-30 18:39:54 +01:00
|
|
|
/* For user vars replication*/
|
|
|
|
if (opt_bin_log)
|
|
|
|
my_init_dynamic_array(&user_var_events,
|
2005-01-16 13:16:23 +01:00
|
|
|
sizeof(BINLOG_USER_VAR_EVENT *), 16, 16);
|
2003-01-30 18:39:54 +01:00
|
|
|
else
|
|
|
|
bzero((char*) &user_var_events, sizeof(user_var_events));
|
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
/* Protocol */
|
2007-01-30 22:48:05 +01:00
|
|
|
protocol= &protocol_text; // Default protocol
|
|
|
|
protocol_text.init(this);
|
|
|
|
protocol_binary.init(this);
|
2002-12-11 08:17:51 +01:00
|
|
|
|
2003-10-13 10:20:19 +02:00
|
|
|
tablespace_op=FALSE;
|
2006-12-14 23:51:37 +01:00
|
|
|
tmp= sql_rnd_with_mutex();
|
|
|
|
randominit(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id);
|
2006-07-10 15:27:03 +02:00
|
|
|
substitute_null_with_insert_id = FALSE;
|
2005-07-19 20:21:12 +02:00
|
|
|
thr_lock_info_init(&lock_info); /* safety: will be reset after start */
|
|
|
|
thr_lock_owner_init(&main_lock_id, &lock_info);
|
Bug#8407 (Stored functions/triggers ignore exception handler)
Bug 18914 (Calling certain SPs from triggers fail)
Bug 20713 (Functions will not not continue for SQLSTATE VALUE '42S02')
Bug 21825 (Incorrect message error deleting records in a table with a
trigger for inserting)
Bug 22580 (DROP TABLE in nested stored procedure causes strange dependency
error)
Bug 25345 (Cursors from Functions)
This fix resolves a long standing issue originally reported with bug 8407,
which affect the behavior of Stored Procedures, Stored Functions and Trigger
in many different ways, causing symptoms reported by all the bugs listed.
In all cases, the root cause of the problem traces back to 8407 and how the
server locks tables involved with sub statements.
Prior to this fix, the implementation of stored routines would:
- compute the transitive closure of all the tables referenced by a top level
statement
- open and lock all the tables involved
- execute the top level statement
"transitive closure of tables" means collecting:
- all the tables,
- all the stored functions,
- all the views,
- all the table triggers
- all the stored procedures
involved, and recursively inspect these objects definition to find more
references to more objects, until the list of every object referenced does
not grow any more.
This mechanism is known as "pre-locking" tables before execution.
The motivation for locking all the tables (possibly) used at once is to
prevent dead locks.
One problem with this approach is that, if the execution path the code
really takes during runtime does not use a given table, and if the table is
missing, the server would not execute the statement.
This in particular has a major impact on triggers, since a missing table
referenced by an update/delete trigger would prevent an insert trigger to run.
Another problem is that stored routines might define SQL exception handlers
to deal with missing tables, but the server implementation would never give
user code a chance to execute this logic, since the routine is never
executed when a missing table cause the pre-locking code to fail.
With this fix, the internal implementation of the pre-locking code has been
relaxed of some constraints, so that failure to open a table does not
necessarily prevent execution of a stored routine.
In particular, the pre-locking mechanism is now behaving as follows:
1) the first step, to compute the transitive closure of all the tables
possibly referenced by a statement, is unchanged.
2) the next step, which is to open all the tables involved, only attempts
to open the tables added by the pre-locking code, but silently fails without
reporting any error or invoking any exception handler is the table is not
present. This is achieved by trapping internal errors with
Prelock_error_handler
3) the locking step only locks tables that were successfully opened.
4) when executing sub statements, the list of tables used by each statements
is evaluated as before. The tables needed by the sub statement are expected
to be already opened and locked. Statement referencing tables that were not
opened in step 2) will fail to find the table in the open list, and only at
this point will execution of the user code fail.
5) when a runtime exception is raised at 4), the instruction continuation
destination (the next instruction to execute in case of SQL continue
handlers) is evaluated.
This is achieved with sp_instr::exec_open_and_lock_tables()
6) if a user exception handler is present in the stored routine, that
handler is invoked as usual, so that ER_NO_SUCH_TABLE exceptions can be
trapped by stored routines. If no handler exists, then the runtime execution
will fail as expected.
With all these changes, a side effect is that view security is impacted, in
two different ways.
First, a view defined as "select stored_function()", where the stored
function references a table that may not exist, is considered valid.
The rationale is that, because the stored function might trap exceptions
during execution and still return a valid result, there is no way to decide
when the view is created if a missing table really cause the view to be invalid.
Secondly, testing for existence of tables is now done later during
execution. View security, which consist of trapping errors and return a
generic ER_VIEW_INVALID (to prevent disclosing information) was only
implemented at very specific phases covering *opening* tables, but not
covering the runtime execution. Because of this existing limitation,
errors that were previously trapped and converted into ER_VIEW_INVALID are
not trapped, causing table names to be reported to the user.
This change is exposing an existing problem, which is independent and will
be resolved separately.
2007-03-06 03:42:07 +01:00
|
|
|
|
|
|
|
m_internal_handler= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void THD::push_internal_handler(Internal_error_handler *handler)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
TODO: The current implementation is limited to 1 handler at a time only.
|
|
|
|
THD and sp_rcontext need to be modified to use a common handler stack.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(m_internal_handler == NULL);
|
|
|
|
m_internal_handler= handler;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-30 20:35:14 +01:00
|
|
|
bool THD::handle_error(uint sql_errno, const char *message,
|
Bug#8407 (Stored functions/triggers ignore exception handler)
Bug 18914 (Calling certain SPs from triggers fail)
Bug 20713 (Functions will not not continue for SQLSTATE VALUE '42S02')
Bug 21825 (Incorrect message error deleting records in a table with a
trigger for inserting)
Bug 22580 (DROP TABLE in nested stored procedure causes strange dependency
error)
Bug 25345 (Cursors from Functions)
This fix resolves a long standing issue originally reported with bug 8407,
which affect the behavior of Stored Procedures, Stored Functions and Trigger
in many different ways, causing symptoms reported by all the bugs listed.
In all cases, the root cause of the problem traces back to 8407 and how the
server locks tables involved with sub statements.
Prior to this fix, the implementation of stored routines would:
- compute the transitive closure of all the tables referenced by a top level
statement
- open and lock all the tables involved
- execute the top level statement
"transitive closure of tables" means collecting:
- all the tables,
- all the stored functions,
- all the views,
- all the table triggers
- all the stored procedures
involved, and recursively inspect these objects definition to find more
references to more objects, until the list of every object referenced does
not grow any more.
This mechanism is known as "pre-locking" tables before execution.
The motivation for locking all the tables (possibly) used at once is to
prevent dead locks.
One problem with this approach is that, if the execution path the code
really takes during runtime does not use a given table, and if the table is
missing, the server would not execute the statement.
This in particular has a major impact on triggers, since a missing table
referenced by an update/delete trigger would prevent an insert trigger to run.
Another problem is that stored routines might define SQL exception handlers
to deal with missing tables, but the server implementation would never give
user code a chance to execute this logic, since the routine is never
executed when a missing table cause the pre-locking code to fail.
With this fix, the internal implementation of the pre-locking code has been
relaxed of some constraints, so that failure to open a table does not
necessarily prevent execution of a stored routine.
In particular, the pre-locking mechanism is now behaving as follows:
1) the first step, to compute the transitive closure of all the tables
possibly referenced by a statement, is unchanged.
2) the next step, which is to open all the tables involved, only attempts
to open the tables added by the pre-locking code, but silently fails without
reporting any error or invoking any exception handler is the table is not
present. This is achieved by trapping internal errors with
Prelock_error_handler
3) the locking step only locks tables that were successfully opened.
4) when executing sub statements, the list of tables used by each statements
is evaluated as before. The tables needed by the sub statement are expected
to be already opened and locked. Statement referencing tables that were not
opened in step 2) will fail to find the table in the open list, and only at
this point will execution of the user code fail.
5) when a runtime exception is raised at 4), the instruction continuation
destination (the next instruction to execute in case of SQL continue
handlers) is evaluated.
This is achieved with sp_instr::exec_open_and_lock_tables()
6) if a user exception handler is present in the stored routine, that
handler is invoked as usual, so that ER_NO_SUCH_TABLE exceptions can be
trapped by stored routines. If no handler exists, then the runtime execution
will fail as expected.
With all these changes, a side effect is that view security is impacted, in
two different ways.
First, a view defined as "select stored_function()", where the stored
function references a table that may not exist, is considered valid.
The rationale is that, because the stored function might trap exceptions
during execution and still return a valid result, there is no way to decide
when the view is created if a missing table really cause the view to be invalid.
Secondly, testing for existence of tables is now done later during
execution. View security, which consist of trapping errors and return a
generic ER_VIEW_INVALID (to prevent disclosing information) was only
implemented at very specific phases covering *opening* tables, but not
covering the runtime execution. Because of this existing limitation,
errors that were previously trapped and converted into ER_VIEW_INVALID are
not trapped, causing table names to be reported to the user.
This change is exposing an existing problem, which is independent and will
be resolved separately.
2007-03-06 03:42:07 +01:00
|
|
|
MYSQL_ERROR::enum_warning_level level)
|
|
|
|
{
|
|
|
|
if (m_internal_handler)
|
|
|
|
{
|
2007-10-30 20:35:14 +01:00
|
|
|
return m_internal_handler->handle_error(sql_errno, message, level, this);
|
Bug#8407 (Stored functions/triggers ignore exception handler)
Bug 18914 (Calling certain SPs from triggers fail)
Bug 20713 (Functions will not not continue for SQLSTATE VALUE '42S02')
Bug 21825 (Incorrect message error deleting records in a table with a
trigger for inserting)
Bug 22580 (DROP TABLE in nested stored procedure causes strange dependency
error)
Bug 25345 (Cursors from Functions)
This fix resolves a long standing issue originally reported with bug 8407,
which affect the behavior of Stored Procedures, Stored Functions and Trigger
in many different ways, causing symptoms reported by all the bugs listed.
In all cases, the root cause of the problem traces back to 8407 and how the
server locks tables involved with sub statements.
Prior to this fix, the implementation of stored routines would:
- compute the transitive closure of all the tables referenced by a top level
statement
- open and lock all the tables involved
- execute the top level statement
"transitive closure of tables" means collecting:
- all the tables,
- all the stored functions,
- all the views,
- all the table triggers
- all the stored procedures
involved, and recursively inspect these objects definition to find more
references to more objects, until the list of every object referenced does
not grow any more.
This mechanism is known as "pre-locking" tables before execution.
The motivation for locking all the tables (possibly) used at once is to
prevent dead locks.
One problem with this approach is that, if the execution path the code
really takes during runtime does not use a given table, and if the table is
missing, the server would not execute the statement.
This in particular has a major impact on triggers, since a missing table
referenced by an update/delete trigger would prevent an insert trigger to run.
Another problem is that stored routines might define SQL exception handlers
to deal with missing tables, but the server implementation would never give
user code a chance to execute this logic, since the routine is never
executed when a missing table cause the pre-locking code to fail.
With this fix, the internal implementation of the pre-locking code has been
relaxed of some constraints, so that failure to open a table does not
necessarily prevent execution of a stored routine.
In particular, the pre-locking mechanism is now behaving as follows:
1) the first step, to compute the transitive closure of all the tables
possibly referenced by a statement, is unchanged.
2) the next step, which is to open all the tables involved, only attempts
to open the tables added by the pre-locking code, but silently fails without
reporting any error or invoking any exception handler is the table is not
present. This is achieved by trapping internal errors with
Prelock_error_handler
3) the locking step only locks tables that were successfully opened.
4) when executing sub statements, the list of tables used by each statements
is evaluated as before. The tables needed by the sub statement are expected
to be already opened and locked. Statement referencing tables that were not
opened in step 2) will fail to find the table in the open list, and only at
this point will execution of the user code fail.
5) when a runtime exception is raised at 4), the instruction continuation
destination (the next instruction to execute in case of SQL continue
handlers) is evaluated.
This is achieved with sp_instr::exec_open_and_lock_tables()
6) if a user exception handler is present in the stored routine, that
handler is invoked as usual, so that ER_NO_SUCH_TABLE exceptions can be
trapped by stored routines. If no handler exists, then the runtime execution
will fail as expected.
With all these changes, a side effect is that view security is impacted, in
two different ways.
First, a view defined as "select stored_function()", where the stored
function references a table that may not exist, is considered valid.
The rationale is that, because the stored function might trap exceptions
during execution and still return a valid result, there is no way to decide
when the view is created if a missing table really cause the view to be invalid.
Secondly, testing for existence of tables is now done later during
execution. View security, which consist of trapping errors and return a
generic ER_VIEW_INVALID (to prevent disclosing information) was only
implemented at very specific phases covering *opening* tables, but not
covering the runtime execution. Because of this existing limitation,
errors that were previously trapped and converted into ER_VIEW_INVALID are
not trapped, causing table names to be reported to the user.
This change is exposing an existing problem, which is independent and will
be resolved separately.
2007-03-06 03:42:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE; // 'FALSE', as per coding style
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void THD::pop_internal_handler()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(m_internal_handler != NULL);
|
|
|
|
m_internal_handler= NULL;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
extern "C"
|
|
|
|
void *thd_alloc(MYSQL_THD thd, unsigned int size)
|
|
|
|
{
|
|
|
|
return thd->alloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
void *thd_calloc(MYSQL_THD thd, unsigned int size)
|
|
|
|
{
|
|
|
|
return thd->calloc(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
char *thd_strdup(MYSQL_THD thd, const char *str)
|
|
|
|
{
|
|
|
|
return thd->strdup(str);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
char *thd_strmake(MYSQL_THD thd, const char *str, unsigned int size)
|
|
|
|
{
|
|
|
|
return thd->strmake(str, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
LEX_STRING *thd_make_lex_string(THD *thd, LEX_STRING *lex_str,
|
|
|
|
const char *str, unsigned int size,
|
|
|
|
int allocate_lex_string)
|
|
|
|
{
|
|
|
|
return thd->make_lex_string(lex_str, str, size,
|
|
|
|
(bool) allocate_lex_string);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C"
|
|
|
|
void *thd_memdup(MYSQL_THD thd, const void* str, unsigned int size)
|
|
|
|
{
|
|
|
|
return thd->memdup(str, size);
|
|
|
|
}
|
|
|
|
|
2008-02-19 17:44:09 +01:00
|
|
|
extern "C"
|
2007-07-05 01:05:47 +02:00
|
|
|
void thd_get_xid(const MYSQL_THD thd, MYSQL_XID *xid)
|
|
|
|
{
|
|
|
|
*xid = *(MYSQL_XID *) &thd->transaction.xid_state.xid;
|
|
|
|
}
|
2002-11-16 19:19:10 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Init common variables that has to be reset on start and on change_user
|
|
|
|
*/
|
|
|
|
|
|
|
|
void THD::init(void)
|
|
|
|
{
|
2002-12-02 16:52:22 +01:00
|
|
|
pthread_mutex_lock(&LOCK_global_system_variables);
|
2007-04-02 20:38:58 +02:00
|
|
|
plugin_thdvar_init(this);
|
2003-11-03 13:01:59 +01:00
|
|
|
variables.time_format= date_time_format_copy((THD*) 0,
|
|
|
|
variables.time_format);
|
|
|
|
variables.date_format= date_time_format_copy((THD*) 0,
|
|
|
|
variables.date_format);
|
|
|
|
variables.datetime_format= date_time_format_copy((THD*) 0,
|
|
|
|
variables.datetime_format);
|
2007-07-14 14:58:39 +02:00
|
|
|
/*
|
|
|
|
variables= global_system_variables above has reset
|
|
|
|
variables.pseudo_thread_id to 0. We need to correct it here to
|
|
|
|
avoid temporary tables replication failure.
|
|
|
|
*/
|
|
|
|
variables.pseudo_thread_id= thread_id;
|
2002-12-02 16:52:22 +01:00
|
|
|
pthread_mutex_unlock(&LOCK_global_system_variables);
|
2002-11-16 19:19:10 +01:00
|
|
|
server_status= SERVER_STATUS_AUTOCOMMIT;
|
2005-06-24 03:29:56 +02:00
|
|
|
if (variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)
|
|
|
|
server_status|= SERVER_STATUS_NO_BACKSLASH_ESCAPES;
|
2002-11-16 19:19:10 +01:00
|
|
|
options= thd_startup_options;
|
2007-10-10 15:57:01 +02:00
|
|
|
|
|
|
|
if (variables.max_join_size == HA_POS_ERROR)
|
|
|
|
options |= OPTION_BIG_SELECTS;
|
|
|
|
else
|
|
|
|
options &= ~OPTION_BIG_SELECTS;
|
|
|
|
|
2007-07-30 17:27:36 +02:00
|
|
|
transaction.all.modified_non_trans_table= transaction.stmt.modified_non_trans_table= FALSE;
|
2002-11-16 19:19:10 +01:00
|
|
|
open_options=ha_open_options;
|
2002-12-02 16:52:22 +01:00
|
|
|
update_lock_default= (variables.low_priority_updates ?
|
|
|
|
TL_WRITE_LOW_PRIORITY :
|
|
|
|
TL_WRITE);
|
2002-11-16 19:19:10 +01:00
|
|
|
session_tx_isolation= (enum_tx_isolation) variables.tx_isolation;
|
2002-12-02 16:52:22 +01:00
|
|
|
warn_list.empty();
|
|
|
|
bzero((char*) warn_count, sizeof(warn_count));
|
|
|
|
total_warn_count= 0;
|
2003-08-19 15:00:12 +02:00
|
|
|
update_charset();
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
reset_current_stmt_binlog_row_based();
|
2004-09-13 15:48:01 +02:00
|
|
|
bzero((char *) &status_var, sizeof(status_var));
|
2002-11-16 19:19:10 +01:00
|
|
|
}
|
|
|
|
|
2003-03-19 20:23:13 +01:00
|
|
|
|
2003-12-21 20:26:45 +01:00
|
|
|
/*
|
|
|
|
Init THD for query processing.
|
|
|
|
This has to be called once before we call mysql_parse.
|
|
|
|
See also comments in sql_class.h.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void THD::init_for_queries()
|
|
|
|
{
|
2007-02-19 14:57:54 +01:00
|
|
|
set_time();
|
2004-09-03 17:11:09 +02:00
|
|
|
ha_enable_transaction(this,TRUE);
|
2004-09-23 11:48:17 +02:00
|
|
|
|
2004-11-08 00:13:54 +01:00
|
|
|
reset_root_defaults(mem_root, variables.query_alloc_block_size,
|
2004-09-23 11:48:17 +02:00
|
|
|
variables.query_prealloc_size);
|
2005-01-16 13:16:23 +01:00
|
|
|
#ifdef USING_TRANSACTIONS
|
2004-09-23 11:48:17 +02:00
|
|
|
reset_root_defaults(&transaction.mem_root,
|
|
|
|
variables.trans_alloc_block_size,
|
|
|
|
variables.trans_prealloc_size);
|
2005-01-16 13:16:23 +01:00
|
|
|
#endif
|
2005-08-12 21:15:01 +02:00
|
|
|
transaction.xid_state.xid.null();
|
|
|
|
transaction.xid_state.in_thd=1;
|
2003-12-21 20:26:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-16 19:19:10 +01:00
|
|
|
/*
|
|
|
|
Do what's needed when one invokes change user
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
change_user()
|
|
|
|
|
|
|
|
IMPLEMENTATION
|
|
|
|
Reset all resources that are connection specific
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void THD::change_user(void)
|
|
|
|
{
|
2008-02-12 18:59:09 +01:00
|
|
|
pthread_mutex_lock(&LOCK_status);
|
|
|
|
add_to_status(&global_status_var, &status_var);
|
|
|
|
pthread_mutex_unlock(&LOCK_status);
|
|
|
|
|
2002-11-16 19:19:10 +01:00
|
|
|
cleanup();
|
2007-04-13 00:56:22 +02:00
|
|
|
killed= NOT_KILLED;
|
2002-11-21 21:25:53 +01:00
|
|
|
cleanup_done= 0;
|
2002-11-16 19:19:10 +01:00
|
|
|
init();
|
2004-09-22 13:50:07 +02:00
|
|
|
stmt_map.reset();
|
2003-05-12 15:36:31 +02:00
|
|
|
hash_init(&user_vars, system_charset_info, USER_VARS_HASH_SIZE, 0, 0,
|
2002-11-16 19:19:10 +01:00
|
|
|
(hash_get_key) get_var_key,
|
2002-11-21 21:25:53 +01:00
|
|
|
(hash_free_key) free_user_var, 0);
|
2003-10-21 12:08:35 +02:00
|
|
|
sp_cache_clear(&sp_proc_cache);
|
|
|
|
sp_cache_clear(&sp_func_cache);
|
2002-11-16 19:19:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-08-21 19:06:00 +02:00
|
|
|
/* Do operations that may take a long time */
|
|
|
|
|
|
|
|
void THD::cleanup(void)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2001-08-21 19:06:00 +02:00
|
|
|
DBUG_ENTER("THD::cleanup");
|
2007-02-23 12:13:55 +01:00
|
|
|
DBUG_ASSERT(cleanup_done == 0);
|
|
|
|
|
2007-04-05 21:34:33 +02:00
|
|
|
killed= KILL_CONNECTION;
|
2005-04-06 18:43:35 +02:00
|
|
|
#ifdef ENABLE_WHEN_BINLOG_WILL_BE_ABLE_TO_PREPARE
|
2005-08-12 21:15:01 +02:00
|
|
|
if (transaction.xid_state.xa_state == XA_PREPARED)
|
|
|
|
{
|
|
|
|
#error xid_state in the cache should be replaced by the allocated value
|
|
|
|
}
|
2005-04-06 18:43:35 +02:00
|
|
|
#endif
|
2005-08-12 21:15:01 +02:00
|
|
|
{
|
2005-04-04 00:50:05 +02:00
|
|
|
ha_rollback(this);
|
2005-08-12 21:15:01 +02:00
|
|
|
xid_cache_delete(&transaction.xid_state);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
if (locked_tables)
|
|
|
|
{
|
|
|
|
lock=locked_tables; locked_tables=0;
|
|
|
|
close_thread_tables(this);
|
|
|
|
}
|
2007-11-20 18:17:53 +01:00
|
|
|
mysql_ha_cleanup(this);
|
2005-08-30 15:22:19 +02:00
|
|
|
delete_dynamic(&user_var_events);
|
|
|
|
hash_free(&user_vars);
|
2000-07-31 21:29:14 +02:00
|
|
|
close_temporary_tables(this);
|
2003-11-03 13:01:59 +01:00
|
|
|
my_free((char*) variables.time_format, MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free((char*) variables.date_format, MYF(MY_ALLOW_ZERO_PTR));
|
|
|
|
my_free((char*) variables.datetime_format, MYF(MY_ALLOW_ZERO_PTR));
|
2005-09-09 09:43:26 +02:00
|
|
|
|
2003-10-21 12:08:35 +02:00
|
|
|
sp_cache_clear(&sp_proc_cache);
|
2005-09-09 09:43:26 +02:00
|
|
|
sp_cache_clear(&sp_func_cache);
|
|
|
|
|
2002-11-16 19:19:10 +01:00
|
|
|
if (global_read_lock)
|
|
|
|
unlock_global_read_lock(this);
|
|
|
|
if (ull)
|
2001-03-06 14:24:08 +01:00
|
|
|
{
|
2002-11-16 19:19:10 +01:00
|
|
|
pthread_mutex_lock(&LOCK_user_locks);
|
|
|
|
item_user_lock_release(ull);
|
|
|
|
pthread_mutex_unlock(&LOCK_user_locks);
|
2007-10-11 15:11:12 +02:00
|
|
|
ull= NULL;
|
2001-03-06 14:24:08 +01:00
|
|
|
}
|
2003-04-02 20:42:28 +02:00
|
|
|
|
2001-08-21 19:06:00 +02:00
|
|
|
cleanup_done=1;
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2002-11-16 19:19:10 +01:00
|
|
|
|
2001-08-21 19:06:00 +02:00
|
|
|
THD::~THD()
|
|
|
|
{
|
2002-03-30 20:36:05 +01:00
|
|
|
THD_CHECK_SENTRY(this);
|
2001-08-21 19:06:00 +02:00
|
|
|
DBUG_ENTER("~THD()");
|
2002-08-22 15:50:58 +02:00
|
|
|
/* Ensure that no one is using THD */
|
|
|
|
pthread_mutex_lock(&LOCK_delete);
|
|
|
|
pthread_mutex_unlock(&LOCK_delete);
|
2004-09-13 15:48:01 +02:00
|
|
|
add_to_status(&global_status_var, &status_var);
|
2002-08-22 15:50:58 +02:00
|
|
|
|
2001-08-21 19:06:00 +02:00
|
|
|
/* Close connection */
|
2005-04-04 00:50:05 +02:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
2001-08-21 19:06:00 +02:00
|
|
|
if (net.vio)
|
|
|
|
{
|
|
|
|
vio_delete(net.vio);
|
2005-04-04 00:50:05 +02:00
|
|
|
net_end(&net);
|
2001-08-21 19:06:00 +02:00
|
|
|
}
|
2002-12-16 14:33:29 +01:00
|
|
|
#endif
|
2006-04-12 23:46:44 +02:00
|
|
|
stmt_map.reset(); /* close all prepared statements */
|
2005-07-19 20:21:12 +02:00
|
|
|
DBUG_ASSERT(lock_info.n_cursors == 0);
|
2001-08-21 19:06:00 +02:00
|
|
|
if (!cleanup_done)
|
|
|
|
cleanup();
|
2005-01-16 13:16:23 +01:00
|
|
|
|
2005-04-04 00:50:05 +02:00
|
|
|
ha_close_connection(this);
|
2007-03-02 17:43:45 +01:00
|
|
|
plugin_thdvar_cleanup(this);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-09-15 21:29:07 +02:00
|
|
|
DBUG_PRINT("info", ("freeing security context"));
|
|
|
|
main_security_ctx.destroy();
|
2004-01-07 18:30:15 +01:00
|
|
|
safeFree(db);
|
2002-10-02 12:33:08 +02:00
|
|
|
free_root(&warn_root,MYF(0));
|
2005-01-16 13:16:23 +01:00
|
|
|
#ifdef USING_TRANSACTIONS
|
2002-03-15 22:57:31 +01:00
|
|
|
free_root(&transaction.mem_root,MYF(0));
|
2005-01-16 13:16:23 +01:00
|
|
|
#endif
|
2000-07-31 21:29:14 +02:00
|
|
|
mysys_var=0; // Safety (shouldn't be needed)
|
2002-08-22 15:50:58 +02:00
|
|
|
pthread_mutex_destroy(&LOCK_delete);
|
2002-03-30 20:36:05 +01:00
|
|
|
#ifndef DBUG_OFF
|
2003-12-04 20:08:26 +01:00
|
|
|
dbug_sentry= THD_SENTRY_GONE;
|
2001-03-13 04:17:32 +01:00
|
|
|
#endif
|
2005-12-22 06:39:02 +01:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
|
|
|
if (rli_fake)
|
2008-02-12 18:21:17 +01:00
|
|
|
{
|
2005-12-22 06:39:02 +01:00
|
|
|
delete rli_fake;
|
2008-02-12 18:21:17 +01:00
|
|
|
rli_fake= NULL;
|
|
|
|
}
|
2005-12-22 06:39:02 +01:00
|
|
|
#endif
|
|
|
|
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
free_root(&main_mem_root, MYF(0));
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2002-08-22 15:50:58 +02:00
|
|
|
|
2004-09-13 15:48:01 +02:00
|
|
|
/*
|
2006-01-10 17:56:23 +01:00
|
|
|
Add all status variables to another status variable array
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
add_to_status()
|
|
|
|
to_var add to this array
|
|
|
|
from_var from this array
|
2004-09-13 15:48:01 +02:00
|
|
|
|
|
|
|
NOTES
|
|
|
|
This function assumes that all variables are long/ulong.
|
|
|
|
If this assumption will change, then we have to explictely add
|
|
|
|
the other variables after the while loop
|
|
|
|
*/
|
|
|
|
|
|
|
|
void add_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var)
|
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
ulong *end= (ulong*) ((uchar*) to_var +
|
2006-10-30 13:35:57 +01:00
|
|
|
offsetof(STATUS_VAR, last_system_status_var) +
|
2004-09-13 15:48:01 +02:00
|
|
|
sizeof(ulong));
|
|
|
|
ulong *to= (ulong*) to_var, *from= (ulong*) from_var;
|
|
|
|
|
|
|
|
while (to != end)
|
|
|
|
*(to++)+= *(from++);
|
|
|
|
}
|
|
|
|
|
2006-06-20 12:20:32 +02:00
|
|
|
/*
|
|
|
|
Add the difference between two status variable arrays to another one.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
add_diff_to_status
|
|
|
|
to_var add to this array
|
|
|
|
from_var from this array
|
|
|
|
dec_var minus this array
|
|
|
|
|
|
|
|
NOTE
|
|
|
|
This function assumes that all variables are long/ulong.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var,
|
|
|
|
STATUS_VAR *dec_var)
|
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
ulong *end= (ulong*) ((uchar*) to_var + offsetof(STATUS_VAR,
|
2006-06-20 12:20:32 +02:00
|
|
|
last_system_status_var) +
|
|
|
|
sizeof(ulong));
|
|
|
|
ulong *to= (ulong*) to_var, *from= (ulong*) from_var, *dec= (ulong*) dec_var;
|
|
|
|
|
|
|
|
while (to != end)
|
|
|
|
*(to++)+= *(from++) - *(dec++);
|
|
|
|
}
|
|
|
|
|
2004-09-13 15:48:01 +02:00
|
|
|
|
2003-03-31 10:39:46 +02:00
|
|
|
void THD::awake(THD::killed_state state_to_set)
|
2001-03-14 07:07:12 +01:00
|
|
|
{
|
2006-05-22 20:46:13 +02:00
|
|
|
DBUG_ENTER("THD::awake");
|
2006-11-27 00:47:38 +01:00
|
|
|
DBUG_PRINT("enter", ("this: 0x%lx", (long) this));
|
2002-03-30 20:36:05 +01:00
|
|
|
THD_CHECK_SENTRY(this);
|
2002-08-22 15:50:58 +02:00
|
|
|
safe_mutex_assert_owner(&LOCK_delete);
|
|
|
|
|
2003-03-31 10:39:46 +02:00
|
|
|
killed= state_to_set;
|
|
|
|
if (state_to_set != THD::KILL_QUERY)
|
2005-12-14 18:42:08 +01:00
|
|
|
{
|
2007-02-23 12:13:55 +01:00
|
|
|
thr_alarm_kill(thread_id);
|
|
|
|
if (!slave_thread)
|
|
|
|
thread_scheduler.post_kill_notification(this);
|
2001-03-14 07:07:12 +01:00
|
|
|
#ifdef SIGNAL_WITH_VIO_CLOSE
|
2007-11-15 13:35:35 +01:00
|
|
|
if (this != current_thd)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
In addition to a signal, let's close the socket of the thread that
|
|
|
|
is being killed. This is to make sure it does not block if the
|
|
|
|
signal is lost. This needs to be done only on platforms where
|
|
|
|
signals are not a reliable interruption mechanism.
|
|
|
|
|
|
|
|
If we're killing ourselves, we know that we're not blocked, so this
|
|
|
|
hack is not used.
|
|
|
|
*/
|
|
|
|
|
|
|
|
close_active_vio();
|
|
|
|
}
|
2001-03-14 07:07:12 +01:00
|
|
|
#endif
|
2005-12-14 18:42:08 +01:00
|
|
|
}
|
2001-03-14 07:07:12 +01:00
|
|
|
if (mysys_var)
|
2002-06-12 14:04:18 +02:00
|
|
|
{
|
|
|
|
pthread_mutex_lock(&mysys_var->mutex);
|
|
|
|
if (!system_thread) // Don't abort locks
|
|
|
|
mysys_var->abort=1;
|
|
|
|
/*
|
|
|
|
This broadcast could be up in the air if the victim thread
|
|
|
|
exits the cond in the time between read and broadcast, but that is
|
|
|
|
ok since all we want to do is to make the victim thread get out
|
|
|
|
of waiting on current_cond.
|
2004-07-30 00:53:25 +02:00
|
|
|
If we see a non-zero current_cond: it cannot be an old value (because
|
|
|
|
then exit_cond() should have run and it can't because we have mutex); so
|
|
|
|
it is the true value but maybe current_mutex is not yet non-zero (we're
|
|
|
|
in the middle of enter_cond() and there is a "memory order
|
|
|
|
inversion"). So we test the mutex too to not lock 0.
|
2004-08-24 17:00:45 +02:00
|
|
|
|
2004-07-30 00:53:25 +02:00
|
|
|
Note that there is a small chance we fail to kill. If victim has locked
|
2004-08-24 17:00:45 +02:00
|
|
|
current_mutex, but hasn't yet entered enter_cond() (which means that
|
|
|
|
current_cond and current_mutex are 0), then the victim will not get
|
|
|
|
a signal and it may wait "forever" on the cond (until
|
|
|
|
we issue a second KILL or the status it's waiting for happens).
|
|
|
|
It's true that we have set its thd->killed but it may not
|
2004-07-30 00:53:25 +02:00
|
|
|
see it immediately and so may have time to reach the cond_wait().
|
2002-06-12 14:04:18 +02:00
|
|
|
*/
|
2004-07-30 00:53:25 +02:00
|
|
|
if (mysys_var->current_cond && mysys_var->current_mutex)
|
2001-03-14 07:07:12 +01:00
|
|
|
{
|
2002-06-12 14:04:18 +02:00
|
|
|
pthread_mutex_lock(mysys_var->current_mutex);
|
|
|
|
pthread_cond_broadcast(mysys_var->current_cond);
|
|
|
|
pthread_mutex_unlock(mysys_var->current_mutex);
|
2001-03-14 07:07:12 +01:00
|
|
|
}
|
2002-06-12 14:04:18 +02:00
|
|
|
pthread_mutex_unlock(&mysys_var->mutex);
|
|
|
|
}
|
2006-05-22 20:46:13 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2001-03-14 07:07:12 +01:00
|
|
|
}
|
|
|
|
|
2002-06-12 14:04:18 +02:00
|
|
|
/*
|
|
|
|
Remember the location of thread info, the structure needed for
|
|
|
|
sql_alloc() and the structure for the net buffer
|
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
bool THD::store_globals()
|
|
|
|
{
|
2005-11-23 19:18:10 +01:00
|
|
|
/*
|
|
|
|
Assert that thread_stack is initialized: it's necessary to be able
|
|
|
|
to track stack overrun.
|
|
|
|
*/
|
2007-02-23 12:13:55 +01:00
|
|
|
DBUG_ASSERT(thread_stack);
|
2005-11-23 19:18:10 +01:00
|
|
|
|
2002-09-05 15:17:08 +02:00
|
|
|
if (my_pthread_setspecific_ptr(THR_THD, this) ||
|
2002-10-02 16:55:12 +02:00
|
|
|
my_pthread_setspecific_ptr(THR_MALLOC, &mem_root))
|
2002-09-05 15:17:08 +02:00
|
|
|
return 1;
|
|
|
|
mysys_var=my_thread_var;
|
2003-10-31 23:20:23 +01:00
|
|
|
/*
|
2007-02-23 12:13:55 +01:00
|
|
|
Let mysqld define the thread id (not mysys)
|
|
|
|
This allows us to move THD to different threads if needed.
|
2003-10-31 23:20:23 +01:00
|
|
|
*/
|
2007-02-23 12:13:55 +01:00
|
|
|
mysys_var->id= thread_id;
|
|
|
|
real_id= pthread_self(); // For debugging
|
|
|
|
|
2005-07-31 11:49:55 +02:00
|
|
|
/*
|
|
|
|
We have to call thr_lock_info_init() again here as THD may have been
|
|
|
|
created in another thread
|
|
|
|
*/
|
2005-07-19 20:21:12 +02:00
|
|
|
thr_lock_info_init(&lock_info);
|
2002-09-05 15:17:08 +02:00
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2002-06-12 14:04:18 +02:00
|
|
|
|
2006-10-02 12:28:23 +02:00
|
|
|
/*
|
|
|
|
Cleanup after query.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
THD::cleanup_after_query()
|
2004-09-15 21:10:31 +02:00
|
|
|
|
2006-10-02 12:28:23 +02:00
|
|
|
DESCRIPTION
|
2006-10-03 15:07:30 +02:00
|
|
|
This function is used to reset thread data to its default state.
|
2006-10-02 12:28:23 +02:00
|
|
|
|
|
|
|
NOTE
|
|
|
|
This function is not suitable for setting thread data to some
|
|
|
|
non-default values, as there is only one replication thread, so
|
|
|
|
different master threads may overwrite data of each other on
|
|
|
|
slave.
|
|
|
|
*/
|
2006-10-03 15:07:30 +02:00
|
|
|
|
2004-09-15 21:10:31 +02:00
|
|
|
void THD::cleanup_after_query()
|
|
|
|
{
|
2007-03-09 18:18:28 +01:00
|
|
|
/*
|
|
|
|
Reset rand_used so that detection of calls to rand() will save random
|
|
|
|
seeds if needed by the slave.
|
|
|
|
|
|
|
|
Do not reset rand_used if inside a stored function or trigger because
|
|
|
|
only the call to these operations is logged. Thus only the calling
|
|
|
|
statement needs to detect rand() calls made by its substatements. These
|
|
|
|
substatements must not set rand_used to 0 because it would remove the
|
|
|
|
detection of rand() by the calling statement.
|
|
|
|
*/
|
2006-09-12 15:42:13 +02:00
|
|
|
if (!in_sub_stmt) /* stored functions and triggers are a special case */
|
|
|
|
{
|
|
|
|
/* Forget those values, for next binlogger: */
|
|
|
|
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
|
|
|
|
auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
2007-03-09 18:18:28 +01:00
|
|
|
rand_used= 0;
|
2006-09-12 15:42:13 +02:00
|
|
|
}
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
if (first_successful_insert_id_in_cur_stmt > 0)
|
2004-09-15 21:10:31 +02:00
|
|
|
{
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
/* set what LAST_INSERT_ID() will return */
|
|
|
|
first_successful_insert_id_in_prev_stmt=
|
|
|
|
first_successful_insert_id_in_cur_stmt;
|
|
|
|
first_successful_insert_id_in_cur_stmt= 0;
|
2006-08-01 06:49:43 +02:00
|
|
|
substitute_null_with_insert_id= TRUE;
|
2004-09-15 21:10:31 +02:00
|
|
|
}
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
arg_of_last_insert_id_function= 0;
|
2004-09-15 21:10:31 +02:00
|
|
|
/* Free Items that were created during this execution */
|
2005-06-23 18:22:08 +02:00
|
|
|
free_items();
|
2005-10-25 11:02:48 +02:00
|
|
|
/* Reset where. */
|
|
|
|
where= THD::DEFAULT_WHERE;
|
2008-08-26 12:01:49 +02:00
|
|
|
/* reset table map for multi-table update */
|
|
|
|
table_map_for_update= 0;
|
2004-09-15 21:10:31 +02:00
|
|
|
}
|
|
|
|
|
2006-10-03 15:07:30 +02:00
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
/**
|
2007-10-16 21:37:31 +02:00
|
|
|
Create a LEX_STRING in this connection.
|
2007-07-05 01:05:47 +02:00
|
|
|
|
|
|
|
@param lex_str pointer to LEX_STRING object to be initialized
|
|
|
|
@param str initializer to be copied into lex_str
|
|
|
|
@param length length of str, in bytes
|
|
|
|
@param allocate_lex_string if TRUE, allocate new LEX_STRING object,
|
|
|
|
instead of using lex_str value
|
|
|
|
@return NULL on failure, or pointer to the LEX_STRING object
|
|
|
|
*/
|
|
|
|
LEX_STRING *THD::make_lex_string(LEX_STRING *lex_str,
|
|
|
|
const char* str, uint length,
|
|
|
|
bool allocate_lex_string)
|
|
|
|
{
|
|
|
|
if (allocate_lex_string)
|
|
|
|
if (!(lex_str= (LEX_STRING *)alloc(sizeof(LEX_STRING))))
|
|
|
|
return 0;
|
|
|
|
if (!(lex_str->str= strmake_root(mem_root, str, length)))
|
|
|
|
return 0;
|
|
|
|
lex_str->length= length;
|
|
|
|
return lex_str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-18 23:08:08 +02:00
|
|
|
/*
|
|
|
|
Convert a string to another character set
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
convert_string()
|
|
|
|
to Store new allocated string here
|
|
|
|
to_cs New character set for allocated string
|
|
|
|
from String to convert
|
|
|
|
from_length Length of string to convert
|
|
|
|
from_cs Original character set
|
|
|
|
|
|
|
|
NOTES
|
|
|
|
to will be 0-terminated to make it easy to pass to system funcs
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 ok
|
|
|
|
1 End of memory.
|
|
|
|
In this case to->str will point to 0 and to->length will be 0.
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
|
|
|
|
const char *from, uint from_length,
|
|
|
|
CHARSET_INFO *from_cs)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("convert_string");
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t new_length= to_cs->mbmaxlen * from_length;
|
2004-10-29 14:00:39 +02:00
|
|
|
uint dummy_errors;
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (!(to->str= (char*) alloc(new_length+1)))
|
2003-08-18 23:08:08 +02:00
|
|
|
{
|
|
|
|
to->length= 0; // Safety fix
|
|
|
|
DBUG_RETURN(1); // EOM
|
|
|
|
}
|
|
|
|
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
|
2004-10-29 14:00:39 +02:00
|
|
|
from, from_length, from_cs, &dummy_errors);
|
2003-08-18 23:08:08 +02:00
|
|
|
to->str[to->length]=0; // Safety
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-05-25 00:03:49 +02:00
|
|
|
/*
|
|
|
|
Convert string from source character set to target character set inplace.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
THD::convert_string
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
Convert string using convert_buffer - buffer for character set
|
|
|
|
conversion shared between all protocols.
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
0 ok
|
|
|
|
!0 out of memory
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
|
|
|
|
{
|
2004-10-29 14:00:39 +02:00
|
|
|
uint dummy_errors;
|
|
|
|
if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
|
2004-05-25 00:03:49 +02:00
|
|
|
return TRUE;
|
|
|
|
/* If convert_buffer >> s copying is more efficient long term */
|
|
|
|
if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
|
|
|
|
!s->is_alloced())
|
|
|
|
{
|
|
|
|
return s->copy(convert_buffer);
|
|
|
|
}
|
|
|
|
s->swap(convert_buffer);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-07-06 14:15:43 +02:00
|
|
|
|
2003-08-18 23:08:08 +02:00
|
|
|
/*
|
|
|
|
Update some cache variables when character set changes
|
|
|
|
*/
|
|
|
|
|
|
|
|
void THD::update_charset()
|
|
|
|
{
|
2004-07-06 14:15:43 +02:00
|
|
|
uint32 not_used;
|
|
|
|
charset_is_system_charset= !String::needs_conversion(0,charset(),
|
|
|
|
system_charset_info,
|
|
|
|
¬_used);
|
|
|
|
charset_is_collation_connection=
|
|
|
|
!String::needs_conversion(0,charset(),variables.collation_connection,
|
|
|
|
¬_used);
|
2006-01-18 09:55:38 +01:00
|
|
|
charset_is_character_set_filesystem=
|
|
|
|
!String::needs_conversion(0, charset(),
|
|
|
|
variables.character_set_filesystem, ¬_used);
|
2003-08-18 23:08:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-03-15 22:57:31 +01:00
|
|
|
/* routings to adding tables to list of changed in transaction tables */
|
|
|
|
|
|
|
|
inline static void list_include(CHANGED_TABLE_LIST** prev,
|
|
|
|
CHANGED_TABLE_LIST* curr,
|
|
|
|
CHANGED_TABLE_LIST* new_table)
|
|
|
|
{
|
|
|
|
if (new_table)
|
|
|
|
{
|
|
|
|
*prev = new_table;
|
|
|
|
(*prev)->next = curr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* add table to list of changed in transaction tables */
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2002-03-15 22:57:31 +01:00
|
|
|
void THD::add_changed_table(TABLE *table)
|
|
|
|
{
|
2002-06-11 10:20:31 +02:00
|
|
|
DBUG_ENTER("THD::add_changed_table(table)");
|
2002-03-15 22:57:31 +01:00
|
|
|
|
2002-07-23 17:31:22 +02:00
|
|
|
DBUG_ASSERT((options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) &&
|
2002-06-11 10:20:31 +02:00
|
|
|
table->file->has_transactions());
|
2005-11-23 21:45:02 +01:00
|
|
|
add_changed_table(table->s->table_cache_key.str,
|
2007-05-31 16:45:22 +02:00
|
|
|
(long) table->s->table_cache_key.length);
|
2002-09-19 19:10:06 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2002-09-19 09:36:19 +02:00
|
|
|
}
|
2002-03-15 22:57:31 +01:00
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
|
2002-09-19 09:36:19 +02:00
|
|
|
void THD::add_changed_table(const char *key, long key_length)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("THD::add_changed_table(key)");
|
2002-11-07 02:54:00 +01:00
|
|
|
CHANGED_TABLE_LIST **prev_changed = &transaction.changed_tables;
|
|
|
|
CHANGED_TABLE_LIST *curr = transaction.changed_tables;
|
2002-03-15 22:57:31 +01:00
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
for (; curr; prev_changed = &(curr->next), curr = curr->next)
|
2002-03-15 22:57:31 +01:00
|
|
|
{
|
2002-09-19 09:36:19 +02:00
|
|
|
int cmp = (long)curr->key_length - (long)key_length;
|
2002-03-15 22:57:31 +01:00
|
|
|
if (cmp < 0)
|
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
list_include(prev_changed, curr, changed_table_dup(key, key_length));
|
2002-03-15 22:57:31 +01:00
|
|
|
DBUG_PRINT("info",
|
2007-03-22 19:32:07 +01:00
|
|
|
("key_length: %ld %u", key_length,
|
|
|
|
(*prev_changed)->key_length));
|
2002-03-15 22:57:31 +01:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
else if (cmp == 0)
|
|
|
|
{
|
2002-09-19 09:36:19 +02:00
|
|
|
cmp = memcmp(curr->key, key, curr->key_length);
|
2002-03-15 22:57:31 +01:00
|
|
|
if (cmp < 0)
|
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
list_include(prev_changed, curr, changed_table_dup(key, key_length));
|
2002-03-15 22:57:31 +01:00
|
|
|
DBUG_PRINT("info",
|
2007-03-28 19:46:42 +02:00
|
|
|
("key_length: %ld %u", key_length,
|
2002-11-07 02:54:00 +01:00
|
|
|
(*prev_changed)->key_length));
|
2002-03-15 22:57:31 +01:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
else if (cmp == 0)
|
|
|
|
{
|
|
|
|
DBUG_PRINT("info", ("already in list"));
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-11-07 02:54:00 +01:00
|
|
|
*prev_changed = changed_table_dup(key, key_length);
|
2007-03-22 19:32:07 +01:00
|
|
|
DBUG_PRINT("info", ("key_length: %ld %u", key_length,
|
2002-11-07 02:54:00 +01:00
|
|
|
(*prev_changed)->key_length));
|
2002-03-15 22:57:31 +01:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2002-09-19 09:36:19 +02:00
|
|
|
CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
|
2002-03-15 22:57:31 +01:00
|
|
|
{
|
|
|
|
CHANGED_TABLE_LIST* new_table =
|
|
|
|
(CHANGED_TABLE_LIST*) trans_alloc(ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST))+
|
2002-09-19 09:36:19 +02:00
|
|
|
key_length + 1);
|
2002-03-15 22:57:31 +01:00
|
|
|
if (!new_table)
|
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
|
|
|
|
ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
|
2003-03-31 10:39:46 +02:00
|
|
|
killed= KILL_CONNECTION;
|
2002-03-15 22:57:31 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
new_table->key= ((char*)new_table)+ ALIGN_SIZE(sizeof(CHANGED_TABLE_LIST));
|
2002-03-15 22:57:31 +01:00
|
|
|
new_table->next = 0;
|
2002-09-19 09:36:19 +02:00
|
|
|
new_table->key_length = key_length;
|
|
|
|
::memcpy(new_table->key, key, key_length);
|
2002-03-15 22:57:31 +01:00
|
|
|
return new_table;
|
|
|
|
}
|
|
|
|
|
2004-09-16 11:47:39 +02:00
|
|
|
|
2002-09-26 22:08:22 +02:00
|
|
|
int THD::send_explain_fields(select_result *result)
|
|
|
|
{
|
|
|
|
List<Item> field_list;
|
|
|
|
Item *item;
|
2004-09-16 11:47:39 +02:00
|
|
|
CHARSET_INFO *cs= system_charset_info;
|
2002-12-11 08:17:51 +01:00
|
|
|
field_list.push_back(new Item_return_int("id",3, MYSQL_TYPE_LONGLONG));
|
2004-09-16 11:47:39 +02:00
|
|
|
field_list.push_back(new Item_empty_string("select_type", 19, cs));
|
2007-04-03 13:13:27 +02:00
|
|
|
field_list.push_back(item= new Item_empty_string("table", NAME_CHAR_LEN, cs));
|
2005-06-07 15:34:13 +02:00
|
|
|
item->maybe_null= 1;
|
2005-12-22 10:29:00 +01:00
|
|
|
if (lex->describe & DESCRIBE_PARTITIONS)
|
|
|
|
{
|
2005-12-27 13:04:35 +01:00
|
|
|
/* Maximum length of string that make_used_partitions_str() can produce */
|
|
|
|
item= new Item_empty_string("partitions", MAX_PARTITIONS * (1 + FN_LEN),
|
|
|
|
cs);
|
|
|
|
field_list.push_back(item);
|
2005-12-22 10:29:00 +01:00
|
|
|
item->maybe_null= 1;
|
|
|
|
}
|
2005-06-07 15:34:13 +02:00
|
|
|
field_list.push_back(item= new Item_empty_string("type", 10, cs));
|
|
|
|
item->maybe_null= 1;
|
2002-09-26 22:08:22 +02:00
|
|
|
field_list.push_back(item=new Item_empty_string("possible_keys",
|
2007-04-03 13:13:27 +02:00
|
|
|
NAME_CHAR_LEN*MAX_KEY, cs));
|
2002-09-26 22:08:22 +02:00
|
|
|
item->maybe_null=1;
|
2007-04-03 13:13:27 +02:00
|
|
|
field_list.push_back(item=new Item_empty_string("key", NAME_CHAR_LEN, cs));
|
2002-09-26 22:08:22 +02:00
|
|
|
item->maybe_null=1;
|
2003-11-13 15:52:02 +01:00
|
|
|
field_list.push_back(item=new Item_empty_string("key_len",
|
2007-04-03 13:13:27 +02:00
|
|
|
NAME_CHAR_LEN*MAX_KEY));
|
2002-09-26 22:08:22 +02:00
|
|
|
item->maybe_null=1;
|
|
|
|
field_list.push_back(item=new Item_empty_string("ref",
|
2007-04-03 13:13:27 +02:00
|
|
|
NAME_CHAR_LEN*MAX_REF_PARTS,
|
|
|
|
cs));
|
2002-09-26 22:08:22 +02:00
|
|
|
item->maybe_null=1;
|
2005-06-07 15:34:13 +02:00
|
|
|
field_list.push_back(item= new Item_return_int("rows", 10,
|
|
|
|
MYSQL_TYPE_LONGLONG));
|
2006-07-28 19:27:01 +02:00
|
|
|
if (lex->describe & DESCRIBE_EXTENDED)
|
|
|
|
{
|
|
|
|
field_list.push_back(item= new Item_float("filtered", 0.1234, 2, 4));
|
|
|
|
item->maybe_null=1;
|
|
|
|
}
|
2005-06-07 15:34:13 +02:00
|
|
|
item->maybe_null= 1;
|
2004-09-16 11:47:39 +02:00
|
|
|
field_list.push_back(new Item_empty_string("Extra", 255, cs));
|
2004-08-03 12:32:21 +02:00
|
|
|
return (result->send_fields(field_list,
|
|
|
|
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF));
|
2002-09-26 22:08:22 +02:00
|
|
|
}
|
2002-03-15 22:57:31 +01:00
|
|
|
|
2002-09-03 14:44:25 +02:00
|
|
|
#ifdef SIGNAL_WITH_VIO_CLOSE
|
|
|
|
void THD::close_active_vio()
|
|
|
|
{
|
2003-03-12 00:40:06 +01:00
|
|
|
DBUG_ENTER("close_active_vio");
|
2002-09-03 14:44:25 +02:00
|
|
|
safe_mutex_assert_owner(&LOCK_delete);
|
2003-01-28 18:03:05 +01:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
2002-09-03 14:44:25 +02:00
|
|
|
if (active_vio)
|
|
|
|
{
|
|
|
|
vio_close(active_vio);
|
|
|
|
active_vio = 0;
|
|
|
|
}
|
2003-01-28 18:03:05 +01:00
|
|
|
#endif
|
2003-03-13 13:52:15 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2002-09-03 14:44:25 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-11-14 08:43:24 +01:00
|
|
|
|
2004-10-08 00:21:19 +02:00
|
|
|
struct Item_change_record: public ilink
|
|
|
|
{
|
|
|
|
Item **place;
|
|
|
|
Item *old_value;
|
|
|
|
/* Placement new was hidden by `new' in ilink (TODO: check): */
|
2004-10-08 15:00:36 +02:00
|
|
|
static void *operator new(size_t size, void *mem) { return mem; }
|
2005-02-15 01:55:44 +01:00
|
|
|
static void operator delete(void *ptr, size_t size) {}
|
|
|
|
static void operator delete(void *ptr, void *mem) { /* never called */ }
|
2004-10-08 00:21:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
Register an item tree tree transformation, performed by the query
|
|
|
|
optimizer. We need a pointer to runtime_memroot because it may be !=
|
2005-09-02 15:21:19 +02:00
|
|
|
thd->mem_root (due to possible set_n_backup_active_arena called for thd).
|
2004-10-08 00:21:19 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
void THD::nocheck_register_item_tree_change(Item **place, Item *old_value,
|
|
|
|
MEM_ROOT *runtime_memroot)
|
|
|
|
{
|
|
|
|
Item_change_record *change;
|
|
|
|
/*
|
|
|
|
Now we use one node per change, which adds some memory overhead,
|
|
|
|
but still is rather fast as we use alloc_root for allocations.
|
|
|
|
A list of item tree changes of an average query should be short.
|
|
|
|
*/
|
|
|
|
void *change_mem= alloc_root(runtime_memroot, sizeof(*change));
|
|
|
|
if (change_mem == 0)
|
|
|
|
{
|
2005-07-01 13:47:45 +02:00
|
|
|
/*
|
|
|
|
OOM, thd->fatal_error() is called by the error handler of the
|
|
|
|
memroot. Just return.
|
|
|
|
*/
|
2004-10-08 00:21:19 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
change= new (change_mem) Item_change_record;
|
|
|
|
change->place= place;
|
|
|
|
change->old_value= old_value;
|
A fix and test case for Bug#5987 "subselect in bool function
crashes server (prepared statements)": the bug was that all boolean
items always recovered its original arguments at statement cleanup
stage.
This collided with Item_subselect::select_transformer, which tries to
permanently change the item tree to use a transformed subselect instead of
original one.
So we had this call sequence for prepare:
mysql_stmt_prepare -> JOIN::prepare ->
Item_subselect::fix_fields -> the item tree gets transformed ->
Item_bool_rowready_func2::cleanup, item tree is recovered to original
state, while it shouldn't have been;
mysql_stmt_execute -> attempts to execute a broken tree -> crash.
Now instead of bluntly recovering all arguments of bool functions in
Item_bool_rowready_func2::cleanup, we recover only those
which were changed, and do it in one place.
There still would exist a possibility for a collision with subselect
tranformation, if permanent and temporary changes were performed at the
same stage.
But fortunately subselect transformation is always done first, so it
doesn't conflict with the optimization done by propogate_cond_constants.
Now we have:
mysql_stmt_prepare -> JOIN::prepare -> subselect transformation
permanently changes the tree -> cleanup doesn't recover anything,
because nothing was registered for recovery.
mysql_stmt_execute -> JOIN::prepare (the tree is already transformed,
so it doesn't change), JOIN::optimize ->
propogate_cond_constants -> temporary changes the item tree
with constants -> JOIN::execute -> cleanup ->
the changes done by propogate_cond_constants are recovered, as
they were registered for recovery.
2004-10-10 00:39:22 +02:00
|
|
|
change_list.append(change);
|
2004-10-08 00:21:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void THD::rollback_item_tree_changes()
|
|
|
|
{
|
|
|
|
I_List_iterator<Item_change_record> it(change_list);
|
|
|
|
Item_change_record *change;
|
2004-11-03 11:39:38 +01:00
|
|
|
DBUG_ENTER("rollback_item_tree_changes");
|
|
|
|
|
2004-10-08 00:21:19 +02:00
|
|
|
while ((change= it++))
|
|
|
|
*change->place= change->old_value;
|
|
|
|
/* We can forget about changes memory: it's allocated in runtime memroot */
|
|
|
|
change_list.empty();
|
2004-11-03 11:39:38 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2004-10-08 00:21:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/*****************************************************************************
|
|
|
|
** Functions to provide a interface to select results
|
|
|
|
*****************************************************************************/
|
|
|
|
|
|
|
|
select_result::select_result()
|
|
|
|
{
|
|
|
|
thd=current_thd;
|
2008-05-13 17:10:46 +02:00
|
|
|
nest_level= -1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-10-08 17:53:31 +02:00
|
|
|
void select_result::send_error(uint errcode,const char *err)
|
|
|
|
{
|
2004-10-20 03:04:37 +02:00
|
|
|
my_message(errcode, err, MYF(0));
|
2003-10-08 17:53:31 +02:00
|
|
|
}
|
|
|
|
|
2004-08-24 18:17:11 +02:00
|
|
|
|
|
|
|
void select_result::cleanup()
|
|
|
|
{
|
|
|
|
/* do nothing */
|
|
|
|
}
|
|
|
|
|
2006-12-01 11:25:06 +01:00
|
|
|
bool select_result::check_simple_select() const
|
|
|
|
{
|
|
|
|
my_error(ER_SP_BAD_CURSOR_QUERY, MYF(0));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-08 17:53:31 +02:00
|
|
|
static String default_line_term("\n",default_charset_info);
|
|
|
|
static String default_escaped("\\",default_charset_info);
|
|
|
|
static String default_field_term("\t",default_charset_info);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
sql_exchange::sql_exchange(char *name,bool flag)
|
|
|
|
:file_name(name), opt_enclosed(0), dumpfile(flag), skip_lines(0)
|
|
|
|
{
|
|
|
|
field_term= &default_field_term;
|
2003-09-18 15:58:02 +02:00
|
|
|
enclosed= line_start= &my_empty_string;
|
2000-07-31 21:29:14 +02:00
|
|
|
line_term= &default_line_term;
|
|
|
|
escaped= &default_escaped;
|
2007-02-28 14:06:57 +01:00
|
|
|
cs= NULL;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2008-09-17 08:34:00 +02:00
|
|
|
bool sql_exchange::escaped_given(void)
|
|
|
|
{
|
|
|
|
return escaped != &default_escaped;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-03 12:32:21 +02:00
|
|
|
bool select_send::send_fields(List<Item> &list, uint flags)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-09-13 15:32:42 +02:00
|
|
|
bool res;
|
|
|
|
if (!(res= thd->protocol->send_fields(&list, flags)))
|
2007-10-31 16:33:13 +01:00
|
|
|
is_result_set_started= 1;
|
2005-09-13 15:32:42 +02:00
|
|
|
return res;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-09-13 15:32:42 +02:00
|
|
|
void select_send::abort()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("select_send::abort");
|
2007-10-31 16:33:13 +01:00
|
|
|
if (is_result_set_started && thd->spcont &&
|
2007-12-12 16:21:01 +01:00
|
|
|
thd->spcont->find_handler(thd, thd->main_da.sql_errno(),
|
2005-09-13 15:32:42 +02:00
|
|
|
MYSQL_ERROR::WARN_LEVEL_ERROR))
|
|
|
|
{
|
|
|
|
/*
|
2007-10-31 16:33:13 +01:00
|
|
|
We're executing a stored procedure, have an open result
|
2007-12-12 16:21:01 +01:00
|
|
|
set, an SQL exception condition and a handler for it.
|
2007-10-31 16:33:13 +01:00
|
|
|
In this situation we must abort the current statement,
|
|
|
|
silence the error and start executing the continue/exit
|
|
|
|
handler.
|
|
|
|
Before aborting the statement, let's end the open result set, as
|
|
|
|
otherwise the client will hang due to the violation of the
|
|
|
|
client/server protocol.
|
2005-09-13 15:32:42 +02:00
|
|
|
*/
|
2007-12-12 16:21:01 +01:00
|
|
|
thd->protocol->end_partial_result_set(thd);
|
2005-09-13 15:32:42 +02:00
|
|
|
}
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-31 16:33:13 +01:00
|
|
|
/**
|
|
|
|
Cleanup an instance of this class for re-use
|
|
|
|
at next execution of a prepared statement/
|
|
|
|
stored procedure statement.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void select_send::cleanup()
|
|
|
|
{
|
|
|
|
is_result_set_started= FALSE;
|
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Send data to client. Returns 0 if ok */
|
|
|
|
|
|
|
|
bool select_send::send_data(List<Item> &items)
|
|
|
|
{
|
2002-05-08 22:14:40 +02:00
|
|
|
if (unit->offset_limit_cnt)
|
2000-07-31 21:29:14 +02:00
|
|
|
{ // using limit offset,count
|
2002-05-08 22:14:40 +02:00
|
|
|
unit->offset_limit_cnt--;
|
2002-12-14 16:43:01 +01:00
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2002-12-11 08:17:51 +01:00
|
|
|
|
2003-03-16 18:17:54 +01:00
|
|
|
/*
|
|
|
|
We may be passing the control from mysqld to the client: release the
|
|
|
|
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
|
|
|
|
by thd
|
|
|
|
*/
|
2006-03-23 14:51:31 +01:00
|
|
|
ha_release_temporary_latches(thd);
|
2003-03-03 18:31:01 +01:00
|
|
|
|
2002-12-11 08:17:51 +01:00
|
|
|
List_iterator_fast<Item> li(items);
|
|
|
|
Protocol *protocol= thd->protocol;
|
|
|
|
char buff[MAX_FIELD_WIDTH];
|
2003-01-29 14:31:20 +01:00
|
|
|
String buffer(buff, sizeof(buff), &my_charset_bin);
|
2006-07-04 19:10:13 +02:00
|
|
|
DBUG_ENTER("select_send::send_data");
|
2002-12-11 08:17:51 +01:00
|
|
|
|
|
|
|
protocol->prepare_for_resend();
|
2000-07-31 21:29:14 +02:00
|
|
|
Item *item;
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
if (item->send(protocol, &buffer))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-12-11 08:17:51 +01:00
|
|
|
protocol->free(); // Free used buffer
|
2002-09-03 08:50:36 +02:00
|
|
|
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
|
2002-12-11 08:17:51 +01:00
|
|
|
break;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
2000-09-16 03:27:21 +02:00
|
|
|
thd->sent_row_count++;
|
2007-12-12 16:21:01 +01:00
|
|
|
if (thd->is_error())
|
|
|
|
{
|
|
|
|
protocol->remove_last_row();
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
if (thd->vio_ok())
|
2002-12-11 08:17:51 +01:00
|
|
|
DBUG_RETURN(protocol->write());
|
2007-12-12 16:21:01 +01:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool select_send::send_eof()
|
|
|
|
{
|
2006-03-23 14:51:31 +01:00
|
|
|
/*
|
|
|
|
We may be passing the control from mysqld to the client: release the
|
|
|
|
InnoDB adaptive hash S-latch to avoid thread deadlocks if it was reserved
|
|
|
|
by thd
|
|
|
|
*/
|
|
|
|
ha_release_temporary_latches(thd);
|
2003-03-03 18:31:01 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Unlock tables before sending packet to gain some speed */
|
|
|
|
if (thd->lock)
|
|
|
|
{
|
2004-10-26 18:30:01 +02:00
|
|
|
mysql_unlock_tables(thd, thd->lock);
|
|
|
|
thd->lock=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2008-08-19 15:15:29 +02:00
|
|
|
/*
|
|
|
|
Don't send EOF if we're in error condition (which implies we've already
|
|
|
|
sent or are sending an error)
|
|
|
|
*/
|
|
|
|
if (thd->is_error())
|
|
|
|
return TRUE;
|
2008-02-19 13:58:08 +01:00
|
|
|
::my_eof(thd);
|
2007-12-12 16:21:01 +01:00
|
|
|
is_result_set_started= 0;
|
|
|
|
return FALSE;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
/************************************************************************
|
|
|
|
Handling writing to file
|
|
|
|
************************************************************************/
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
void select_to_file::send_error(uint errcode,const char *err)
|
|
|
|
{
|
2004-10-20 03:04:37 +02:00
|
|
|
my_message(errcode, err, MYF(0));
|
2004-02-05 10:22:08 +01:00
|
|
|
if (file > 0)
|
|
|
|
{
|
|
|
|
(void) end_io_cache(&cache);
|
|
|
|
(void) my_close(file,MYF(0));
|
|
|
|
(void) my_delete(path,MYF(0)); // Delete file on error
|
|
|
|
file= -1;
|
|
|
|
}
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
|
2004-08-24 18:17:11 +02:00
|
|
|
bool select_to_file::send_eof()
|
|
|
|
{
|
|
|
|
int error= test(end_io_cache(&cache));
|
|
|
|
if (my_close(file,MYF(MY_WME)))
|
|
|
|
error= 1;
|
|
|
|
if (!error)
|
2007-10-15 14:42:41 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
In order to remember the value of affected rows for ROW_COUNT()
|
|
|
|
function, SELECT INTO has to have an own SQLCOM.
|
|
|
|
TODO: split from SQLCOM_SELECT
|
|
|
|
*/
|
2008-02-19 13:45:21 +01:00
|
|
|
::my_ok(thd,row_count);
|
2007-10-15 14:42:41 +02:00
|
|
|
}
|
2004-08-24 18:17:11 +02:00
|
|
|
file= -1;
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void select_to_file::cleanup()
|
|
|
|
{
|
|
|
|
/* In case of error send_eof() may be not called: close the file here. */
|
|
|
|
if (file >= 0)
|
|
|
|
{
|
|
|
|
(void) end_io_cache(&cache);
|
|
|
|
(void) my_close(file,MYF(0));
|
|
|
|
file= -1;
|
|
|
|
}
|
|
|
|
path[0]= '\0';
|
|
|
|
row_count= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
select_to_file::~select_to_file()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
if (file >= 0)
|
|
|
|
{ // This only happens in case of error
|
|
|
|
(void) end_io_cache(&cache);
|
|
|
|
(void) my_close(file,MYF(0));
|
|
|
|
file= -1;
|
|
|
|
}
|
2004-02-05 10:22:08 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
** Export of select to textfile
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
select_export::~select_export()
|
|
|
|
{
|
2000-09-16 03:27:21 +02:00
|
|
|
thd->sent_row_count=row_count;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
/*
|
|
|
|
Create file with IO cache
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
create_file()
|
|
|
|
thd Thread handle
|
|
|
|
path File name
|
|
|
|
exchange Excange class
|
|
|
|
cache IO cache
|
|
|
|
|
|
|
|
RETURN
|
|
|
|
>= 0 File handle
|
|
|
|
-1 Error
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
static File create_file(THD *thd, char *path, sql_exchange *exchange,
|
|
|
|
IO_CACHE *cache)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-02-05 10:22:08 +01:00
|
|
|
File file;
|
2007-02-14 14:44:34 +01:00
|
|
|
uint option= MY_UNPACK_FILENAME | MY_RELATIVE_PATH;
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
#ifdef DONT_ALLOW_FULL_LOAD_DATA_PATHS
|
2004-02-05 10:22:08 +01:00
|
|
|
option|= MY_REPLACE_DIR; // Force use of db directory
|
2000-07-31 21:29:14 +02:00
|
|
|
#endif
|
2004-08-24 19:45:32 +02:00
|
|
|
|
2004-09-13 18:49:41 +02:00
|
|
|
if (!dirname_length(exchange->file_name))
|
2004-09-07 08:55:34 +02:00
|
|
|
{
|
2005-11-23 21:45:02 +01:00
|
|
|
strxnmov(path, FN_REFLEN-1, mysql_real_data_home, thd->db ? thd->db : "",
|
|
|
|
NullS);
|
2004-09-07 08:55:34 +02:00
|
|
|
(void) fn_format(path, exchange->file_name, path, "", option);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
(void) fn_format(path, exchange->file_name, mysql_real_data_home, "", option);
|
2007-02-14 14:44:34 +01:00
|
|
|
|
|
|
|
if (opt_secure_file_priv &&
|
|
|
|
strncmp(opt_secure_file_priv, path, strlen(opt_secure_file_priv)))
|
|
|
|
{
|
|
|
|
/* Write only allowed to dir or subdir specified by secure_file_priv */
|
|
|
|
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
if (!access(path, F_OK))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_FILE_EXISTS_ERROR, MYF(0), exchange->file_name);
|
2004-02-09 12:31:03 +01:00
|
|
|
return -1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
/* Create the file world readable */
|
2004-12-10 18:49:36 +01:00
|
|
|
if ((file= my_create(path, 0666, O_WRONLY|O_EXCL, MYF(MY_WME))) < 0)
|
2004-02-05 10:22:08 +01:00
|
|
|
return file;
|
2000-07-31 21:29:14 +02:00
|
|
|
#ifdef HAVE_FCHMOD
|
2004-02-05 10:22:08 +01:00
|
|
|
(void) fchmod(file, 0666); // Because of umask()
|
2000-07-31 21:29:14 +02:00
|
|
|
#else
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
(void) chmod(path, 0666);
|
2000-07-31 21:29:14 +02:00
|
|
|
#endif
|
2004-02-05 10:22:08 +01:00
|
|
|
if (init_io_cache(cache, file, 0L, WRITE_CACHE, 0L, 1, MYF(MY_WME)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-02-05 10:22:08 +01:00
|
|
|
my_close(file, MYF(0));
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
my_delete(path, MYF(0)); // Delete file on error, it was just created
|
2004-02-05 10:22:08 +01:00
|
|
|
return -1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2004-02-05 10:22:08 +01:00
|
|
|
return file;
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
select_export::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
|
|
|
{
|
|
|
|
bool blob_flag=0;
|
2007-10-23 13:16:59 +02:00
|
|
|
bool string_results= FALSE, non_string_results= FALSE;
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
unit= u;
|
|
|
|
if ((uint) strlen(exchange->file_name) + NAME_LEN >= FN_REFLEN)
|
|
|
|
strmake(path,exchange->file_name,FN_REFLEN-1);
|
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
if ((file= create_file(thd, path, exchange, &cache)) < 0)
|
Fixed Bug#2123, mysqld segmentation faulted when it tried to
open a file that already existed. The problem was that end_io_cache()
was called even if init_io_cache() was not. This affected both
OUTFILE and DUMPFILE (both fixed). Sometimes wrongly aligned pointer was freed,
sometimes mysqld core dumped.
Other problem was that select_dump::send_error removed the dumpfile,
even if it was created by an earlier run, or by some other program, if
the file permissions just permitted it. Fixed it so that the file will
only be deleted, if an error occurred, but the file was created by mysqld
just a moment ago, in that thread.
On the other hand, select_export did not handle the corresponding garbage
file at all. Both fixed.
After these fixes, a big part of the select_export::prepare and select_dump::prepare
code became identical. Merged the code into a new function called create_file(),
which is now called by the two latter functions.
Regards,
Jani
2004-01-15 05:48:31 +01:00
|
|
|
return 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Check if there is any blobs in data */
|
|
|
|
{
|
2001-08-02 05:29:50 +02:00
|
|
|
List_iterator_fast<Item> li(list);
|
2000-07-31 21:29:14 +02:00
|
|
|
Item *item;
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
|
|
|
if (item->max_length >= MAX_BLOB_WIDTH)
|
|
|
|
{
|
|
|
|
blob_flag=1;
|
|
|
|
break;
|
|
|
|
}
|
2007-10-23 13:16:59 +02:00
|
|
|
if (item->result_type() == STRING_RESULT)
|
|
|
|
string_results= TRUE;
|
|
|
|
else
|
|
|
|
non_string_results= TRUE;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
field_term_length=exchange->field_term->length();
|
2007-11-20 17:15:20 +01:00
|
|
|
field_term_char= field_term_length ?
|
|
|
|
(int) (uchar) (*exchange->field_term)[0] : INT_MAX;
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!exchange->line_term->length())
|
|
|
|
exchange->line_term=exchange->field_term; // Use this if it exists
|
2007-11-20 17:15:20 +01:00
|
|
|
field_sep_char= (exchange->enclosed->length() ?
|
|
|
|
(int) (uchar) (*exchange->enclosed)[0] : field_term_char);
|
2008-09-17 08:34:00 +02:00
|
|
|
if (exchange->escaped->length() && (exchange->escaped_given() ||
|
|
|
|
!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)))
|
|
|
|
escape_char= (int) (uchar) (*exchange->escaped)[0];
|
|
|
|
else
|
|
|
|
escape_char= -1;
|
2007-07-03 18:05:17 +02:00
|
|
|
is_ambiguous_field_sep= test(strchr(ESCAPE_CHARS, field_sep_char));
|
2007-07-06 00:43:23 +02:00
|
|
|
is_unsafe_field_sep= test(strchr(NUMERIC_CHARS, field_sep_char));
|
2000-07-31 21:29:14 +02:00
|
|
|
line_sep_char= (exchange->line_term->length() ?
|
2007-11-20 17:15:20 +01:00
|
|
|
(int) (uchar) (*exchange->line_term)[0] : INT_MAX);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!field_term_length)
|
|
|
|
exchange->opt_enclosed=0;
|
|
|
|
if (!exchange->enclosed->length())
|
|
|
|
exchange->opt_enclosed=1; // A little quicker loop
|
|
|
|
fixed_row_size= (!field_term_length && !exchange->enclosed->length() &&
|
|
|
|
!blob_flag);
|
2007-10-23 13:16:59 +02:00
|
|
|
if ((is_ambiguous_field_sep && exchange->enclosed->is_empty() &&
|
|
|
|
(string_results || is_unsafe_field_sep)) ||
|
|
|
|
(exchange->opt_enclosed && non_string_results &&
|
|
|
|
field_term_length && strchr(NUMERIC_CHARS, field_term_char)))
|
|
|
|
{
|
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_AMBIGUOUS_FIELD_TERM, ER(ER_AMBIGUOUS_FIELD_TERM));
|
|
|
|
is_ambiguous_field_term= TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
is_ambiguous_field_term= FALSE;
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-07 10:16:49 +02:00
|
|
|
#define NEED_ESCAPING(x) ((int) (uchar) (x) == escape_char || \
|
2007-10-23 13:16:59 +02:00
|
|
|
(enclosed ? (int) (uchar) (x) == field_sep_char \
|
|
|
|
: (int) (uchar) (x) == field_term_char) || \
|
2007-06-07 10:16:49 +02:00
|
|
|
(int) (uchar) (x) == line_sep_char || \
|
|
|
|
!(x))
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
bool select_export::send_data(List<Item> &items)
|
|
|
|
{
|
|
|
|
|
2006-06-28 18:55:30 +02:00
|
|
|
DBUG_ENTER("select_export::send_data");
|
2000-07-31 21:29:14 +02:00
|
|
|
char buff[MAX_FIELD_WIDTH],null_buff[2],space[MAX_FIELD_WIDTH];
|
|
|
|
bool space_inited=0;
|
2003-01-29 14:31:20 +01:00
|
|
|
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
|
2000-07-31 21:29:14 +02:00
|
|
|
tmp.length(0);
|
|
|
|
|
2002-05-08 22:14:40 +02:00
|
|
|
if (unit->offset_limit_cnt)
|
2000-07-31 21:29:14 +02:00
|
|
|
{ // using limit offset,count
|
2002-05-08 22:14:40 +02:00
|
|
|
unit->offset_limit_cnt--;
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
row_count++;
|
|
|
|
Item *item;
|
|
|
|
uint used_length=0,items_left=items.elements;
|
2001-08-02 05:29:50 +02:00
|
|
|
List_iterator_fast<Item> li(items);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) exchange->line_start->ptr(),
|
2000-07-31 21:29:14 +02:00
|
|
|
exchange->line_start->length()))
|
|
|
|
goto err;
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
|
|
|
Item_result result_type=item->result_type();
|
2007-10-23 13:16:59 +02:00
|
|
|
bool enclosed = (exchange->enclosed->length() &&
|
|
|
|
(!exchange->opt_enclosed || result_type == STRING_RESULT));
|
2000-07-31 21:29:14 +02:00
|
|
|
res=item->str_result(&tmp);
|
2007-10-23 13:16:59 +02:00
|
|
|
if (res && enclosed)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) exchange->enclosed->ptr(),
|
2000-07-31 21:29:14 +02:00
|
|
|
exchange->enclosed->length()))
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (!res)
|
|
|
|
{ // NULL
|
|
|
|
if (!fixed_row_size)
|
|
|
|
{
|
|
|
|
if (escape_char != -1) // Use \N syntax
|
|
|
|
{
|
|
|
|
null_buff[0]=escape_char;
|
|
|
|
null_buff[1]='N';
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) null_buff,2))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
else if (my_b_write(&cache,(uchar*) "NULL",4))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
used_length=0; // Fill with space
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (fixed_row_size)
|
|
|
|
used_length=min(res->length(),item->max_length);
|
|
|
|
else
|
|
|
|
used_length=res->length();
|
2007-07-06 00:43:23 +02:00
|
|
|
if ((result_type == STRING_RESULT || is_unsafe_field_sep) &&
|
|
|
|
escape_char != -1)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2007-06-07 10:16:49 +02:00
|
|
|
char *pos, *start, *end;
|
|
|
|
CHARSET_INFO *res_charset= res->charset();
|
|
|
|
CHARSET_INFO *character_set_client= thd->variables.
|
|
|
|
character_set_client;
|
|
|
|
bool check_second_byte= (res_charset == &my_charset_bin) &&
|
|
|
|
character_set_client->
|
|
|
|
escape_with_backslash_is_dangerous;
|
|
|
|
DBUG_ASSERT(character_set_client->mbmaxlen == 2 ||
|
|
|
|
!character_set_client->escape_with_backslash_is_dangerous);
|
2000-07-31 21:29:14 +02:00
|
|
|
for (start=pos=(char*) res->ptr(),end=pos+used_length ;
|
|
|
|
pos != end ;
|
|
|
|
pos++)
|
|
|
|
{
|
|
|
|
#ifdef USE_MB
|
2002-12-20 14:57:24 +01:00
|
|
|
if (use_mb(res_charset))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
int l;
|
2002-12-20 14:57:24 +01:00
|
|
|
if ((l=my_ismbchar(res_charset, pos, end)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
pos += l-1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2007-06-07 10:16:49 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Special case when dumping BINARY/VARBINARY/BLOB values
|
|
|
|
for the clients with character sets big5, cp932, gbk and sjis,
|
|
|
|
which can have the escape character (0x5C "\" by default)
|
|
|
|
as the second byte of a multi-byte sequence.
|
|
|
|
|
|
|
|
If
|
|
|
|
- pos[0] is a valid multi-byte head (e.g 0xEE) and
|
|
|
|
- pos[1] is 0x00, which will be escaped as "\0",
|
|
|
|
|
|
|
|
then we'll get "0xEE + 0x5C + 0x30" in the output file.
|
|
|
|
|
|
|
|
If this file is later loaded using this sequence of commands:
|
|
|
|
|
|
|
|
mysql> create table t1 (a varchar(128)) character set big5;
|
|
|
|
mysql> LOAD DATA INFILE 'dump.txt' INTO TABLE t1;
|
|
|
|
|
|
|
|
then 0x5C will be misinterpreted as the second byte
|
|
|
|
of a multi-byte character "0xEE + 0x5C", instead of
|
|
|
|
escape character for 0x00.
|
|
|
|
|
|
|
|
To avoid this confusion, we'll escape the multi-byte
|
|
|
|
head character too, so the sequence "0xEE + 0x00" will be
|
|
|
|
dumped as "0x5C + 0xEE + 0x5C + 0x30".
|
|
|
|
|
|
|
|
Note, in the condition below we only check if
|
|
|
|
mbcharlen is equal to 2, because there are no
|
|
|
|
character sets with mbmaxlen longer than 2
|
|
|
|
and with escape_with_backslash_is_dangerous set.
|
|
|
|
DBUG_ASSERT before the loop makes that sure.
|
|
|
|
*/
|
|
|
|
|
2007-10-23 13:16:59 +02:00
|
|
|
if ((NEED_ESCAPING(*pos) ||
|
|
|
|
(check_second_byte &&
|
|
|
|
my_mbcharlen(character_set_client, (uchar) *pos) == 2 &&
|
|
|
|
pos + 1 < end &&
|
|
|
|
NEED_ESCAPING(pos[1]))) &&
|
|
|
|
/*
|
|
|
|
Don't escape field_term_char by doubling - doubling is only
|
|
|
|
valid for ENCLOSED BY characters:
|
|
|
|
*/
|
2007-11-20 17:15:20 +01:00
|
|
|
(enclosed || !is_ambiguous_field_term ||
|
|
|
|
(int) (uchar) *pos != field_term_char))
|
2007-06-07 10:16:49 +02:00
|
|
|
{
|
2000-07-31 21:29:14 +02:00
|
|
|
char tmp_buff[2];
|
2007-11-20 17:15:20 +01:00
|
|
|
tmp_buff[0]= ((int) (uchar) *pos == field_sep_char &&
|
Fixed bug #29294.
The `SELECT 'r' INTO OUTFILE ... FIELDS ENCLOSED BY 'r' ' statement
encoded the 'r' string to a 4 byte string of value x'725c7272'
(sequence of 4 characters: r\rr).
The LOAD DATA statement decoded this string to a 1 byte string of
value x'0d' (ASCII Carriage Return character) instead of the original
'r' character.
The same error also happened with the FIELDS ENCLOSED BY clause
followed by special characters: 'n', 't', 'r', 'b', '0', 'Z' and 'N'.
NOTE 1: This is a result of the undocumented feature: the LOAD DATA INFILE
recognises 2-byte input sequences like \n, \t, \r and \Z in addition
to documented 2-byte sequences: \0 and \N. This feature should be
documented (here backspace character is a default ESCAPED BY character,
in the real-life example it may be any ESCAPED BY character).
NOTE 2, changed behaviour:
Now the `SELECT INTO OUTFILE' statement with the `FIELDS ENCLOSED BY'
clause followed by one of: 'n', 't', 'r', 'b', '0', 'Z' or 'N' characters
encodes this special character itself by doubling it ('r' --> 'rr'),
not by prepending it with an escape character.
2007-07-03 16:37:46 +02:00
|
|
|
is_ambiguous_field_sep) ?
|
|
|
|
field_sep_char : escape_char;
|
2000-07-31 21:29:14 +02:00
|
|
|
tmp_buff[1]= *pos ? *pos : '0';
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)) ||
|
|
|
|
my_b_write(&cache,(uchar*) tmp_buff,2))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
start=pos+1;
|
|
|
|
}
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) start,(uint) (pos-start)))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
else if (my_b_write(&cache,(uchar*) res->ptr(),used_length))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
if (fixed_row_size)
|
|
|
|
{ // Fill with space
|
|
|
|
if (item->max_length > used_length)
|
|
|
|
{
|
|
|
|
/* QQ: Fix by adding a my_b_fill() function */
|
|
|
|
if (!space_inited)
|
|
|
|
{
|
|
|
|
space_inited=1;
|
|
|
|
bfill(space,sizeof(space),' ');
|
|
|
|
}
|
|
|
|
uint length=item->max_length-used_length;
|
2002-06-11 10:20:31 +02:00
|
|
|
for (; length > sizeof(space) ; length-=sizeof(space))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) space,sizeof(space)))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) space,length))
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2007-10-23 13:16:59 +02:00
|
|
|
if (res && enclosed)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache, (uchar*) exchange->enclosed->ptr(),
|
2007-03-20 19:09:28 +01:00
|
|
|
exchange->enclosed->length()))
|
|
|
|
goto err;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
if (--items_left)
|
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache, (uchar*) exchange->field_term->ptr(),
|
2007-03-20 19:09:28 +01:00
|
|
|
field_term_length))
|
|
|
|
goto err;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) exchange->line_term->ptr(),
|
2000-07-31 21:29:14 +02:00
|
|
|
exchange->line_term->length()))
|
|
|
|
goto err;
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
err:
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
** Dump of select to a binary file
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2002-05-08 22:14:40 +02:00
|
|
|
select_dump::prepare(List<Item> &list __attribute__((unused)),
|
|
|
|
SELECT_LEX_UNIT *u)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-05-08 22:14:40 +02:00
|
|
|
unit= u;
|
2004-02-05 10:22:08 +01:00
|
|
|
return (int) ((file= create_file(thd, path, exchange, &cache)) < 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool select_dump::send_data(List<Item> &items)
|
|
|
|
{
|
2001-08-02 05:29:50 +02:00
|
|
|
List_iterator_fast<Item> li(items);
|
2000-07-31 21:29:14 +02:00
|
|
|
char buff[MAX_FIELD_WIDTH];
|
2003-01-29 14:31:20 +01:00
|
|
|
String tmp(buff,sizeof(buff),&my_charset_bin),*res;
|
2000-07-31 21:29:14 +02:00
|
|
|
tmp.length(0);
|
|
|
|
Item *item;
|
2006-06-28 18:55:30 +02:00
|
|
|
DBUG_ENTER("select_dump::send_data");
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2002-05-08 22:14:40 +02:00
|
|
|
if (unit->offset_limit_cnt)
|
2000-07-31 21:29:14 +02:00
|
|
|
{ // using limit offset,count
|
2002-05-08 22:14:40 +02:00
|
|
|
unit->offset_limit_cnt--;
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
if (row_count++ > 1)
|
|
|
|
{
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
|
|
|
res=item->str_result(&tmp);
|
2000-09-28 23:58:16 +02:00
|
|
|
if (!res) // If NULL
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_b_write(&cache,(uchar*) "",1))
|
2000-09-28 23:58:16 +02:00
|
|
|
goto err;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
else if (my_b_write(&cache,(uchar*) res->ptr(),res->length()))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
err:
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-11-28 11:18:13 +01:00
|
|
|
select_subselect::select_subselect(Item_subselect *item_arg)
|
2002-05-12 22:46:42 +02:00
|
|
|
{
|
2003-11-28 11:18:13 +01:00
|
|
|
item= item_arg;
|
2002-05-12 22:46:42 +02:00
|
|
|
}
|
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
|
2002-12-19 20:15:09 +01:00
|
|
|
bool select_singlerow_subselect::send_data(List<Item> &items)
|
2002-05-12 22:46:42 +02:00
|
|
|
{
|
2002-12-19 20:15:09 +01:00
|
|
|
DBUG_ENTER("select_singlerow_subselect::send_data");
|
|
|
|
Item_singlerow_subselect *it= (Item_singlerow_subselect *)item;
|
2002-11-18 21:41:57 +01:00
|
|
|
if (it->assigned())
|
|
|
|
{
|
2004-01-02 23:12:07 +01:00
|
|
|
my_message(ER_SUBQUERY_NO_1_ROW, ER(ER_SUBQUERY_NO_1_ROW), MYF(0));
|
2002-05-28 21:38:17 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
|
|
|
if (unit->offset_limit_cnt)
|
2002-06-01 22:35:36 +02:00
|
|
|
{ // Using limit offset,count
|
2002-05-28 21:38:17 +02:00
|
|
|
unit->offset_limit_cnt--;
|
|
|
|
DBUG_RETURN(0);
|
2002-05-12 22:46:42 +02:00
|
|
|
}
|
2002-06-01 22:35:36 +02:00
|
|
|
List_iterator_fast<Item> li(items);
|
2002-12-19 06:38:33 +01:00
|
|
|
Item *val_item;
|
|
|
|
for (uint i= 0; (val_item= li++); i++)
|
|
|
|
it->store(i, val_item);
|
2002-09-03 08:50:36 +02:00
|
|
|
it->assigned(1);
|
2002-05-28 21:38:17 +02:00
|
|
|
DBUG_RETURN(0);
|
2002-05-12 22:46:42 +02:00
|
|
|
}
|
2002-06-19 16:52:44 +02:00
|
|
|
|
2004-02-05 10:22:08 +01:00
|
|
|
|
2005-01-26 14:27:45 +01:00
|
|
|
void select_max_min_finder_subselect::cleanup()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("select_max_min_finder_subselect::cleanup");
|
|
|
|
cache= 0;
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-08-12 11:38:03 +02:00
|
|
|
bool select_max_min_finder_subselect::send_data(List<Item> &items)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("select_max_min_finder_subselect::send_data");
|
2004-11-18 17:10:07 +01:00
|
|
|
Item_maxmin_subselect *it= (Item_maxmin_subselect *)item;
|
2003-08-12 11:38:03 +02:00
|
|
|
List_iterator_fast<Item> li(items);
|
|
|
|
Item *val_item= li++;
|
2004-11-18 17:10:07 +01:00
|
|
|
it->register_value();
|
2003-08-12 11:38:03 +02:00
|
|
|
if (it->assigned())
|
|
|
|
{
|
|
|
|
cache->store(val_item);
|
|
|
|
if ((this->*op)())
|
|
|
|
it->store(0, cache);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!cache)
|
|
|
|
{
|
2007-11-10 20:44:48 +01:00
|
|
|
cache= Item_cache::get_cache(val_item);
|
2003-08-12 11:38:03 +02:00
|
|
|
switch (val_item->result_type())
|
|
|
|
{
|
|
|
|
case REAL_RESULT:
|
|
|
|
op= &select_max_min_finder_subselect::cmp_real;
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
|
|
|
op= &select_max_min_finder_subselect::cmp_int;
|
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
|
|
|
op= &select_max_min_finder_subselect::cmp_str;
|
|
|
|
break;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
op= &select_max_min_finder_subselect::cmp_decimal;
|
|
|
|
break;
|
2003-08-12 11:38:03 +02:00
|
|
|
case ROW_RESULT:
|
|
|
|
// This case should never be choosen
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
op= 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
cache->store(val_item);
|
|
|
|
it->store(0, cache);
|
|
|
|
}
|
|
|
|
it->assigned(1);
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool select_max_min_finder_subselect::cmp_real()
|
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
|
2004-11-11 19:39:35 +01:00
|
|
|
double val1= cache->val_real(), val2= maxmin->val_real();
|
2003-08-12 11:38:03 +02:00
|
|
|
if (fmax)
|
|
|
|
return (cache->null_value && !maxmin->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
val1 > val2);
|
2005-02-19 17:58:27 +01:00
|
|
|
return (maxmin->null_value && !cache->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
val1 < val2);
|
2003-08-12 11:38:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool select_max_min_finder_subselect::cmp_int()
|
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
|
2003-08-12 11:38:03 +02:00
|
|
|
longlong val1= cache->val_int(), val2= maxmin->val_int();
|
|
|
|
if (fmax)
|
|
|
|
return (cache->null_value && !maxmin->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
val1 > val2);
|
2005-02-19 17:58:27 +01:00
|
|
|
return (maxmin->null_value && !cache->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
val1 < val2);
|
2003-08-12 11:38:03 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
bool select_max_min_finder_subselect::cmp_decimal()
|
|
|
|
{
|
2006-12-14 23:51:37 +01:00
|
|
|
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal cval, *cvalue= cache->val_decimal(&cval);
|
|
|
|
my_decimal mval, *mvalue= maxmin->val_decimal(&mval);
|
|
|
|
if (fmax)
|
|
|
|
return (cache->null_value && !maxmin->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
my_decimal_cmp(cvalue, mvalue) > 0) ;
|
2005-02-19 17:58:27 +01:00
|
|
|
return (maxmin->null_value && !cache->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
my_decimal_cmp(cvalue,mvalue) < 0);
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
2003-08-12 11:38:03 +02:00
|
|
|
bool select_max_min_finder_subselect::cmp_str()
|
|
|
|
{
|
|
|
|
String *val1, *val2, buf1, buf2;
|
2006-12-14 23:51:37 +01:00
|
|
|
Item *maxmin= ((Item_singlerow_subselect *)item)->element_index(0);
|
2003-08-12 11:38:03 +02:00
|
|
|
/*
|
|
|
|
as far as both operand is Item_cache buf1 & buf2 will not be used,
|
|
|
|
but added for safety
|
|
|
|
*/
|
|
|
|
val1= cache->val_str(&buf1);
|
|
|
|
val2= maxmin->val_str(&buf1);
|
|
|
|
if (fmax)
|
|
|
|
return (cache->null_value && !maxmin->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
sortcmp(val1, val2, cache->collation.collation) > 0) ;
|
2005-02-19 17:58:27 +01:00
|
|
|
return (maxmin->null_value && !cache->null_value) ||
|
|
|
|
(!cache->null_value && !maxmin->null_value &&
|
|
|
|
sortcmp(val1, val2, cache->collation.collation) < 0);
|
2003-08-12 11:38:03 +02:00
|
|
|
}
|
|
|
|
|
2002-06-19 16:52:44 +02:00
|
|
|
bool select_exists_subselect::send_data(List<Item> &items)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("select_exists_subselect::send_data");
|
|
|
|
Item_exists_subselect *it= (Item_exists_subselect *)item;
|
|
|
|
if (unit->offset_limit_cnt)
|
|
|
|
{ // Using limit offset,count
|
|
|
|
unit->offset_limit_cnt--;
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
it->value= 1;
|
2002-09-03 08:50:36 +02:00
|
|
|
it->assigned(1);
|
2002-06-19 16:52:44 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2002-10-11 20:49:10 +02:00
|
|
|
|
|
|
|
/***************************************************************************
|
2004-02-05 10:22:08 +01:00
|
|
|
Dump of select to variables
|
2002-10-11 20:49:10 +02:00
|
|
|
***************************************************************************/
|
2004-02-05 10:22:08 +01:00
|
|
|
|
2002-10-16 15:55:08 +02:00
|
|
|
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
|
2002-10-11 20:49:10 +02:00
|
|
|
{
|
2003-10-01 16:15:24 +02:00
|
|
|
unit= u;
|
2006-11-28 23:21:39 +01:00
|
|
|
|
2002-10-16 15:55:08 +02:00
|
|
|
if (var_list.elements != list.elements)
|
2002-10-11 20:49:10 +02:00
|
|
|
{
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
|
|
|
|
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
|
2002-10-16 15:55:08 +02:00
|
|
|
return 1;
|
2006-11-29 18:15:15 +01:00
|
|
|
}
|
2002-10-16 15:55:08 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2003-03-06 19:16:46 +01:00
|
|
|
|
2003-10-01 16:15:24 +02:00
|
|
|
|
2006-12-01 11:25:06 +01:00
|
|
|
bool select_dumpvar::check_simple_select() const
|
|
|
|
{
|
|
|
|
my_error(ER_SP_BAD_CURSOR_SELECT, MYF(0));
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-24 18:17:11 +02:00
|
|
|
void select_dumpvar::cleanup()
|
|
|
|
{
|
2006-11-28 23:21:39 +01:00
|
|
|
row_count= 0;
|
2004-08-24 18:17:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-15 19:58:35 +02:00
|
|
|
Query_arena::Type Query_arena::type() const
|
2004-08-21 00:02:46 +02:00
|
|
|
{
|
2004-09-06 14:14:10 +02:00
|
|
|
DBUG_ASSERT(0); /* Should never be called */
|
2004-08-21 00:02:46 +02:00
|
|
|
return STATEMENT;
|
2004-05-20 01:02:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-23 18:22:08 +02:00
|
|
|
void Query_arena::free_items()
|
|
|
|
{
|
|
|
|
Item *next;
|
|
|
|
DBUG_ENTER("Query_arena::free_items");
|
|
|
|
/* This works because items are allocated with sql_alloc() */
|
|
|
|
for (; free_list; free_list= next)
|
|
|
|
{
|
|
|
|
next= free_list->next;
|
|
|
|
free_list->delete_self();
|
|
|
|
}
|
|
|
|
/* Postcondition: free_list is 0 */
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-22 00:11:21 +02:00
|
|
|
void Query_arena::set_query_arena(Query_arena *set)
|
|
|
|
{
|
|
|
|
mem_root= set->mem_root;
|
|
|
|
free_list= set->free_list;
|
|
|
|
state= set->state;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Query_arena::cleanup_stmt()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT("Query_arena::cleanup_stmt()" == "not implemented");
|
|
|
|
}
|
|
|
|
|
2003-12-20 00:16:10 +01:00
|
|
|
/*
|
2007-04-13 19:23:02 +02:00
|
|
|
Statement functions
|
2003-12-20 00:16:10 +01:00
|
|
|
*/
|
|
|
|
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
Statement::Statement(LEX *lex_arg, MEM_ROOT *mem_root_arg,
|
|
|
|
enum enum_state state_arg, ulong id_arg)
|
|
|
|
:Query_arena(mem_root_arg, state_arg),
|
2005-06-22 21:12:25 +02:00
|
|
|
id(id_arg),
|
This changeset is largely a handler cleanup changeset (WL#3281), but includes fixes and cleanups that was found necessary while testing the handler changes
Changes that requires code changes in other code of other storage engines.
(Note that all changes are very straightforward and one should find all issues
by compiling a --debug build and fixing all compiler errors and all
asserts in field.cc while running the test suite),
- New optional handler function introduced: reset()
This is called after every DML statement to make it easy for a handler to
statement specific cleanups.
(The only case it's not called is if force the file to be closed)
- handler::extra(HA_EXTRA_RESET) is removed. Code that was there before
should be moved to handler::reset()
- table->read_set contains a bitmap over all columns that are needed
in the query. read_row() and similar functions only needs to read these
columns
- table->write_set contains a bitmap over all columns that will be updated
in the query. write_row() and update_row() only needs to update these
columns.
The above bitmaps should now be up to date in all context
(including ALTER TABLE, filesort()).
The handler is informed of any changes to the bitmap after
fix_fields() by calling the virtual function
handler::column_bitmaps_signal(). If the handler does caching of
these bitmaps (instead of using table->read_set, table->write_set),
it should redo the caching in this code. as the signal() may be sent
several times, it's probably best to set a variable in the signal
and redo the caching on read_row() / write_row() if the variable was
set.
- Removed the read_set and write_set bitmap objects from the handler class
- Removed all column bit handling functions from the handler class.
(Now one instead uses the normal bitmap functions in my_bitmap.c instead
of handler dedicated bitmap functions)
- field->query_id is removed. One should instead instead check
table->read_set and table->write_set if a field is used in the query.
- handler::extra(HA_EXTRA_RETRIVE_ALL_COLS) and
handler::extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) are removed. One should now
instead use table->read_set to check for which columns to retrieve.
- If a handler needs to call Field->val() or Field->store() on columns
that are not used in the query, one should install a temporary
all-columns-used map while doing so. For this, we provide the following
functions:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
field->val();
dbug_tmp_restore_column_map(table->read_set, old_map);
and similar for the write map:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
field->val();
dbug_tmp_restore_column_map(table->write_set, old_map);
If this is not done, you will sooner or later hit a DBUG_ASSERT
in the field store() / val() functions.
(For not DBUG binaries, the dbug_tmp_restore_column_map() and
dbug_tmp_restore_column_map() are inline dummy functions and should
be optimized away be the compiler).
- If one needs to temporary set the column map for all binaries (and not
just to avoid the DBUG_ASSERT() in the Field::store() / Field::val()
methods) one should use the functions tmp_use_all_columns() and
tmp_restore_column_map() instead of the above dbug_ variants.
- All 'status' fields in the handler base class (like records,
data_file_length etc) are now stored in a 'stats' struct. This makes
it easier to know what status variables are provided by the base
handler. This requires some trivial variable names in the extra()
function.
- New virtual function handler::records(). This is called to optimize
COUNT(*) if (handler::table_flags() & HA_HAS_RECORDS()) is true.
(stats.records is not supposed to be an exact value. It's only has to
be 'reasonable enough' for the optimizer to be able to choose a good
optimization path).
- Non virtual handler::init() function added for caching of virtual
constants from engine.
- Removed has_transactions() virtual method. Now one should instead return
HA_NO_TRANSACTIONS in table_flags() if the table handler DOES NOT support
transactions.
- The 'xxxx_create_handler()' function now has a MEM_ROOT_root argument
that is to be used with 'new handler_name()' to allocate the handler
in the right area. The xxxx_create_handler() function is also
responsible for any initialization of the object before returning.
For example, one should change:
static handler *myisam_create_handler(TABLE_SHARE *table)
{
return new ha_myisam(table);
}
->
static handler *myisam_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) ha_myisam(table);
}
- New optional virtual function: use_hidden_primary_key().
This is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
but we don't have a primary key. This allows the handler to take precisions
in remembering any hidden primary key to able to update/delete any
found row. The default handler marks all columns to be read.
- handler::table_flags() now returns a ulonglong (to allow for more flags).
- New/changed table_flags()
- HA_HAS_RECORDS Set if ::records() is supported
- HA_NO_TRANSACTIONS Set if engine doesn't support transactions
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE
Set if we should mark all primary key columns for
read when reading rows as part of a DELETE
statement. If there is no primary key,
all columns are marked for read.
- HA_PARTIAL_COLUMN_READ Set if engine will not read all columns in some
cases (based on table->read_set)
- HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
Renamed to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
- HA_DUPP_POS Renamed to HA_DUPLICATE_POS
- HA_REQUIRES_KEY_COLUMNS_FOR_DELETE
Set this if we should mark ALL key columns for
read when when reading rows as part of a DELETE
statement. In case of an update we will mark
all keys for read for which key part changed
value.
- HA_STATS_RECORDS_IS_EXACT
Set this if stats.records is exact.
(This saves us some extra records() calls
when optimizing COUNT(*))
- Removed table_flags()
- HA_NOT_EXACT_COUNT Now one should instead use HA_HAS_RECORDS if
handler::records() gives an exact count() and
HA_STATS_RECORDS_IS_EXACT if stats.records is exact.
- HA_READ_RND_SAME Removed (no one supported this one)
- Removed not needed functions ha_retrieve_all_cols() and ha_retrieve_all_pk()
- Renamed handler::dupp_pos to handler::dup_pos
- Removed not used variable handler::sortkey
Upper level handler changes:
- ha_reset() now does some overall checks and calls ::reset()
- ha_table_flags() added. This is a cached version of table_flags(). The
cache is updated on engine creation time and updated on open.
MySQL level changes (not obvious from the above):
- DBUG_ASSERT() added to check that column usage matches what is set
in the column usage bit maps. (This found a LOT of bugs in current
column marking code).
- In 5.1 before, all used columns was marked in read_set and only updated
columns was marked in write_set. Now we only mark columns for which we
need a value in read_set.
- Column bitmaps are created in open_binary_frm() and open_table_from_share().
(Before this was in table.cc)
- handler::table_flags() calls are replaced with handler::ha_table_flags()
- For calling field->val() you must have the corresponding bit set in
table->read_set. For calling field->store() you must have the
corresponding bit set in table->write_set. (There are asserts in
all store()/val() functions to catch wrong usage)
- thd->set_query_id is renamed to thd->mark_used_columns and instead
of setting this to an integer value, this has now the values:
MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE
Changed also all variables named 'set_query_id' to mark_used_columns.
- In filesort() we now inform the handler of exactly which columns are needed
doing the sort and choosing the rows.
- The TABLE_SHARE object has a 'all_set' column bitmap one can use
when one needs a column bitmap with all columns set.
(This is used for table->use_all_columns() and other places)
- The TABLE object has 3 column bitmaps:
- def_read_set Default bitmap for columns to be read
- def_write_set Default bitmap for columns to be written
- tmp_set Can be used as a temporary bitmap when needed.
The table object has also two pointer to bitmaps read_set and write_set
that the handler should use to find out which columns are used in which way.
- count() optimization now calls handler::records() instead of using
handler->stats.records (if (table_flags() & HA_HAS_RECORDS) is true).
- Added extra argument to Item::walk() to indicate if we should also
traverse sub queries.
- Added TABLE parameter to cp_buffer_from_ref()
- Don't close tables created with CREATE ... SELECT but keep them in
the table cache. (Faster usage of newly created tables).
New interfaces:
- table->clear_column_bitmaps() to initialize the bitmaps for tables
at start of new statements.
- table->column_bitmaps_set() to set up new column bitmaps and signal
the handler about this.
- table->column_bitmaps_set_no_signal() for some few cases where we need
to setup new column bitmaps but don't signal the handler (as the handler
has already been signaled about these before). Used for the momement
only in opt_range.cc when doing ROR scans.
- table->use_all_columns() to install a bitmap where all columns are marked
as use in the read and the write set.
- table->default_column_bitmaps() to install the normal read and write
column bitmaps, but not signaling the handler about this.
This is mainly used when creating TABLE instances.
- table->mark_columns_needed_for_delete(),
table->mark_columns_needed_for_delete() and
table->mark_columns_needed_for_insert() to allow us to put additional
columns in column usage maps if handler so requires.
(The handler indicates what it neads in handler->table_flags())
- table->prepare_for_position() to allow us to tell handler that it
needs to read primary key parts to be able to store them in
future table->position() calls.
(This replaces the table->file->ha_retrieve_all_pk function)
- table->mark_auto_increment_column() to tell handler are going to update
columns part of any auto_increment key.
- table->mark_columns_used_by_index() to mark all columns that is part of
an index. It will also send extra(HA_EXTRA_KEYREAD) to handler to allow
it to quickly know that it only needs to read colums that are part
of the key. (The handler can also use the column map for detecting this,
but simpler/faster handler can just monitor the extra() call).
- table->mark_columns_used_by_index_no_reset() to in addition to other columns,
also mark all columns that is used by the given key.
- table->restore_column_maps_after_mark_index() to restore to default
column maps after a call to table->mark_columns_used_by_index().
- New item function register_field_in_read_map(), for marking used columns
in table->read_map. Used by filesort() to mark all used columns
- Maintain in TABLE->merge_keys set of all keys that are used in query.
(Simplices some optimization loops)
- Maintain Field->part_of_key_not_clustered which is like Field->part_of_key
but the field in the clustered key is not assumed to be part of all index.
(used in opt_range.cc for faster loops)
- dbug_tmp_use_all_columns(), dbug_tmp_restore_column_map()
tmp_use_all_columns() and tmp_restore_column_map() functions to temporally
mark all columns as usable. The 'dbug_' version is primarily intended
inside a handler when it wants to just call Field:store() & Field::val()
functions, but don't need the column maps set for any other usage.
(ie:: bitmap_is_set() is never called)
- We can't use compare_records() to skip updates for handlers that returns
a partial column set and the read_set doesn't cover all columns in the
write set. The reason for this is that if we have a column marked only for
write we can't in the MySQL level know if the value changed or not.
The reason this worked before was that MySQL marked all to be written
columns as also to be read. The new 'optimal' bitmaps exposed this 'hidden
bug'.
- open_table_from_share() does not anymore setup temporary MEM_ROOT
object as a thread specific variable for the handler. Instead we
send the to-be-used MEMROOT to get_new_handler().
(Simpler, faster code)
Bugs fixed:
- Column marking was not done correctly in a lot of cases.
(ALTER TABLE, when using triggers, auto_increment fields etc)
(Could potentially result in wrong values inserted in table handlers
relying on that the old column maps or field->set_query_id was correct)
Especially when it comes to triggers, there may be cases where the
old code would cause lost/wrong values for NDB and/or InnoDB tables.
- Split thd->options flag OPTION_STATUS_NO_TRANS_UPDATE to two flags:
OPTION_STATUS_NO_TRANS_UPDATE and OPTION_KEEP_LOG.
This allowed me to remove some wrong warnings about:
"Some non-transactional changed tables couldn't be rolled back"
- Fixed handling of INSERT .. SELECT and CREATE ... SELECT that wrongly reset
(thd->options & OPTION_STATUS_NO_TRANS_UPDATE) which caused us to loose
some warnings about
"Some non-transactional changed tables couldn't be rolled back")
- Fixed use of uninitialized memory in ha_ndbcluster.cc::delete_table()
which could cause delete_table to report random failures.
- Fixed core dumps for some tests when running with --debug
- Added missing FN_LIBCHAR in mysql_rm_tmp_tables()
(This has probably caused us to not properly remove temporary files after
crash)
- slow_logs was not properly initialized, which could maybe cause
extra/lost entries in slow log.
- If we get an duplicate row on insert, change column map to read and
write all columns while retrying the operation. This is required by
the definition of REPLACE and also ensures that fields that are only
part of UPDATE are properly handled. This fixed a bug in NDB and
REPLACE where REPLACE wrongly copied some column values from the replaced
row.
- For table handler that doesn't support NULL in keys, we would give an error
when creating a primary key with NULL fields, even after the fields has been
automaticly converted to NOT NULL.
- Creating a primary key on a SPATIAL key, would fail if field was not
declared as NOT NULL.
Cleanups:
- Removed not used condition argument to setup_tables
- Removed not needed item function reset_query_id_processor().
- Field->add_index is removed. Now this is instead maintained in
(field->flags & FIELD_IN_ADD_INDEX)
- Field->fieldnr is removed (use field->field_index instead)
- New argument to filesort() to indicate that it should return a set of
row pointers (not used columns). This allowed me to remove some references
to sql_command in filesort and should also enable us to return column
results in some cases where we couldn't before.
- Changed column bitmap handling in opt_range.cc to be aligned with TABLE
bitmap, which allowed me to use bitmap functions instead of looping over
all fields to create some needed bitmaps. (Faster and smaller code)
- Broke up found too long lines
- Moved some variable declaration at start of function for better code
readability.
- Removed some not used arguments from functions.
(setup_fields(), mysql_prepare_insert_check_table())
- setup_fields() now takes an enum instead of an int for marking columns
usage.
- For internal temporary tables, use handler::write_row(),
handler::delete_row() and handler::update_row() instead of
handler::ha_xxxx() for faster execution.
- Changed some constants to enum's and define's.
- Using separate column read and write sets allows for easier checking
of timestamp field was set by statement.
- Remove calls to free_io_cache() as this is now done automaticly in ha_reset()
- Don't build table->normalized_path as this is now identical to table->path
(after bar's fixes to convert filenames)
- Fixed some missed DBUG_PRINT(.."%lx") to use "0x%lx" to make it easier to
do comparision with the 'convert-dbug-for-diff' tool.
Things left to do in 5.1:
- We wrongly log failed CREATE TABLE ... SELECT in some cases when using
row based logging (as shown by testcase binlog_row_mix_innodb_myisam.result)
Mats has promised to look into this.
- Test that my fix for CREATE TABLE ... SELECT is indeed correct.
(I added several test cases for this, but in this case it's better that
someone else also tests this throughly).
Lars has promosed to do this.
2006-06-04 17:52:22 +02:00
|
|
|
mark_used_columns(MARK_COLUMNS_READ),
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
lex(lex_arg),
|
2003-12-20 00:16:10 +01:00
|
|
|
query(0),
|
2004-08-03 12:32:21 +02:00
|
|
|
query_length(0),
|
2007-08-31 18:42:14 +02:00
|
|
|
cursor(0),
|
|
|
|
db(NULL),
|
|
|
|
db_length(0)
|
2003-12-20 00:16:10 +01:00
|
|
|
{
|
2004-04-12 23:58:48 +02:00
|
|
|
name.str= NULL;
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-06-15 19:58:35 +02:00
|
|
|
Query_arena::Type Statement::type() const
|
2003-12-20 00:16:10 +01:00
|
|
|
{
|
|
|
|
return STATEMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Statement::set_statement(Statement *stmt)
|
|
|
|
{
|
|
|
|
id= stmt->id;
|
This changeset is largely a handler cleanup changeset (WL#3281), but includes fixes and cleanups that was found necessary while testing the handler changes
Changes that requires code changes in other code of other storage engines.
(Note that all changes are very straightforward and one should find all issues
by compiling a --debug build and fixing all compiler errors and all
asserts in field.cc while running the test suite),
- New optional handler function introduced: reset()
This is called after every DML statement to make it easy for a handler to
statement specific cleanups.
(The only case it's not called is if force the file to be closed)
- handler::extra(HA_EXTRA_RESET) is removed. Code that was there before
should be moved to handler::reset()
- table->read_set contains a bitmap over all columns that are needed
in the query. read_row() and similar functions only needs to read these
columns
- table->write_set contains a bitmap over all columns that will be updated
in the query. write_row() and update_row() only needs to update these
columns.
The above bitmaps should now be up to date in all context
(including ALTER TABLE, filesort()).
The handler is informed of any changes to the bitmap after
fix_fields() by calling the virtual function
handler::column_bitmaps_signal(). If the handler does caching of
these bitmaps (instead of using table->read_set, table->write_set),
it should redo the caching in this code. as the signal() may be sent
several times, it's probably best to set a variable in the signal
and redo the caching on read_row() / write_row() if the variable was
set.
- Removed the read_set and write_set bitmap objects from the handler class
- Removed all column bit handling functions from the handler class.
(Now one instead uses the normal bitmap functions in my_bitmap.c instead
of handler dedicated bitmap functions)
- field->query_id is removed. One should instead instead check
table->read_set and table->write_set if a field is used in the query.
- handler::extra(HA_EXTRA_RETRIVE_ALL_COLS) and
handler::extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) are removed. One should now
instead use table->read_set to check for which columns to retrieve.
- If a handler needs to call Field->val() or Field->store() on columns
that are not used in the query, one should install a temporary
all-columns-used map while doing so. For this, we provide the following
functions:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
field->val();
dbug_tmp_restore_column_map(table->read_set, old_map);
and similar for the write map:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
field->val();
dbug_tmp_restore_column_map(table->write_set, old_map);
If this is not done, you will sooner or later hit a DBUG_ASSERT
in the field store() / val() functions.
(For not DBUG binaries, the dbug_tmp_restore_column_map() and
dbug_tmp_restore_column_map() are inline dummy functions and should
be optimized away be the compiler).
- If one needs to temporary set the column map for all binaries (and not
just to avoid the DBUG_ASSERT() in the Field::store() / Field::val()
methods) one should use the functions tmp_use_all_columns() and
tmp_restore_column_map() instead of the above dbug_ variants.
- All 'status' fields in the handler base class (like records,
data_file_length etc) are now stored in a 'stats' struct. This makes
it easier to know what status variables are provided by the base
handler. This requires some trivial variable names in the extra()
function.
- New virtual function handler::records(). This is called to optimize
COUNT(*) if (handler::table_flags() & HA_HAS_RECORDS()) is true.
(stats.records is not supposed to be an exact value. It's only has to
be 'reasonable enough' for the optimizer to be able to choose a good
optimization path).
- Non virtual handler::init() function added for caching of virtual
constants from engine.
- Removed has_transactions() virtual method. Now one should instead return
HA_NO_TRANSACTIONS in table_flags() if the table handler DOES NOT support
transactions.
- The 'xxxx_create_handler()' function now has a MEM_ROOT_root argument
that is to be used with 'new handler_name()' to allocate the handler
in the right area. The xxxx_create_handler() function is also
responsible for any initialization of the object before returning.
For example, one should change:
static handler *myisam_create_handler(TABLE_SHARE *table)
{
return new ha_myisam(table);
}
->
static handler *myisam_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) ha_myisam(table);
}
- New optional virtual function: use_hidden_primary_key().
This is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
but we don't have a primary key. This allows the handler to take precisions
in remembering any hidden primary key to able to update/delete any
found row. The default handler marks all columns to be read.
- handler::table_flags() now returns a ulonglong (to allow for more flags).
- New/changed table_flags()
- HA_HAS_RECORDS Set if ::records() is supported
- HA_NO_TRANSACTIONS Set if engine doesn't support transactions
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE
Set if we should mark all primary key columns for
read when reading rows as part of a DELETE
statement. If there is no primary key,
all columns are marked for read.
- HA_PARTIAL_COLUMN_READ Set if engine will not read all columns in some
cases (based on table->read_set)
- HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
Renamed to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
- HA_DUPP_POS Renamed to HA_DUPLICATE_POS
- HA_REQUIRES_KEY_COLUMNS_FOR_DELETE
Set this if we should mark ALL key columns for
read when when reading rows as part of a DELETE
statement. In case of an update we will mark
all keys for read for which key part changed
value.
- HA_STATS_RECORDS_IS_EXACT
Set this if stats.records is exact.
(This saves us some extra records() calls
when optimizing COUNT(*))
- Removed table_flags()
- HA_NOT_EXACT_COUNT Now one should instead use HA_HAS_RECORDS if
handler::records() gives an exact count() and
HA_STATS_RECORDS_IS_EXACT if stats.records is exact.
- HA_READ_RND_SAME Removed (no one supported this one)
- Removed not needed functions ha_retrieve_all_cols() and ha_retrieve_all_pk()
- Renamed handler::dupp_pos to handler::dup_pos
- Removed not used variable handler::sortkey
Upper level handler changes:
- ha_reset() now does some overall checks and calls ::reset()
- ha_table_flags() added. This is a cached version of table_flags(). The
cache is updated on engine creation time and updated on open.
MySQL level changes (not obvious from the above):
- DBUG_ASSERT() added to check that column usage matches what is set
in the column usage bit maps. (This found a LOT of bugs in current
column marking code).
- In 5.1 before, all used columns was marked in read_set and only updated
columns was marked in write_set. Now we only mark columns for which we
need a value in read_set.
- Column bitmaps are created in open_binary_frm() and open_table_from_share().
(Before this was in table.cc)
- handler::table_flags() calls are replaced with handler::ha_table_flags()
- For calling field->val() you must have the corresponding bit set in
table->read_set. For calling field->store() you must have the
corresponding bit set in table->write_set. (There are asserts in
all store()/val() functions to catch wrong usage)
- thd->set_query_id is renamed to thd->mark_used_columns and instead
of setting this to an integer value, this has now the values:
MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE
Changed also all variables named 'set_query_id' to mark_used_columns.
- In filesort() we now inform the handler of exactly which columns are needed
doing the sort and choosing the rows.
- The TABLE_SHARE object has a 'all_set' column bitmap one can use
when one needs a column bitmap with all columns set.
(This is used for table->use_all_columns() and other places)
- The TABLE object has 3 column bitmaps:
- def_read_set Default bitmap for columns to be read
- def_write_set Default bitmap for columns to be written
- tmp_set Can be used as a temporary bitmap when needed.
The table object has also two pointer to bitmaps read_set and write_set
that the handler should use to find out which columns are used in which way.
- count() optimization now calls handler::records() instead of using
handler->stats.records (if (table_flags() & HA_HAS_RECORDS) is true).
- Added extra argument to Item::walk() to indicate if we should also
traverse sub queries.
- Added TABLE parameter to cp_buffer_from_ref()
- Don't close tables created with CREATE ... SELECT but keep them in
the table cache. (Faster usage of newly created tables).
New interfaces:
- table->clear_column_bitmaps() to initialize the bitmaps for tables
at start of new statements.
- table->column_bitmaps_set() to set up new column bitmaps and signal
the handler about this.
- table->column_bitmaps_set_no_signal() for some few cases where we need
to setup new column bitmaps but don't signal the handler (as the handler
has already been signaled about these before). Used for the momement
only in opt_range.cc when doing ROR scans.
- table->use_all_columns() to install a bitmap where all columns are marked
as use in the read and the write set.
- table->default_column_bitmaps() to install the normal read and write
column bitmaps, but not signaling the handler about this.
This is mainly used when creating TABLE instances.
- table->mark_columns_needed_for_delete(),
table->mark_columns_needed_for_delete() and
table->mark_columns_needed_for_insert() to allow us to put additional
columns in column usage maps if handler so requires.
(The handler indicates what it neads in handler->table_flags())
- table->prepare_for_position() to allow us to tell handler that it
needs to read primary key parts to be able to store them in
future table->position() calls.
(This replaces the table->file->ha_retrieve_all_pk function)
- table->mark_auto_increment_column() to tell handler are going to update
columns part of any auto_increment key.
- table->mark_columns_used_by_index() to mark all columns that is part of
an index. It will also send extra(HA_EXTRA_KEYREAD) to handler to allow
it to quickly know that it only needs to read colums that are part
of the key. (The handler can also use the column map for detecting this,
but simpler/faster handler can just monitor the extra() call).
- table->mark_columns_used_by_index_no_reset() to in addition to other columns,
also mark all columns that is used by the given key.
- table->restore_column_maps_after_mark_index() to restore to default
column maps after a call to table->mark_columns_used_by_index().
- New item function register_field_in_read_map(), for marking used columns
in table->read_map. Used by filesort() to mark all used columns
- Maintain in TABLE->merge_keys set of all keys that are used in query.
(Simplices some optimization loops)
- Maintain Field->part_of_key_not_clustered which is like Field->part_of_key
but the field in the clustered key is not assumed to be part of all index.
(used in opt_range.cc for faster loops)
- dbug_tmp_use_all_columns(), dbug_tmp_restore_column_map()
tmp_use_all_columns() and tmp_restore_column_map() functions to temporally
mark all columns as usable. The 'dbug_' version is primarily intended
inside a handler when it wants to just call Field:store() & Field::val()
functions, but don't need the column maps set for any other usage.
(ie:: bitmap_is_set() is never called)
- We can't use compare_records() to skip updates for handlers that returns
a partial column set and the read_set doesn't cover all columns in the
write set. The reason for this is that if we have a column marked only for
write we can't in the MySQL level know if the value changed or not.
The reason this worked before was that MySQL marked all to be written
columns as also to be read. The new 'optimal' bitmaps exposed this 'hidden
bug'.
- open_table_from_share() does not anymore setup temporary MEM_ROOT
object as a thread specific variable for the handler. Instead we
send the to-be-used MEMROOT to get_new_handler().
(Simpler, faster code)
Bugs fixed:
- Column marking was not done correctly in a lot of cases.
(ALTER TABLE, when using triggers, auto_increment fields etc)
(Could potentially result in wrong values inserted in table handlers
relying on that the old column maps or field->set_query_id was correct)
Especially when it comes to triggers, there may be cases where the
old code would cause lost/wrong values for NDB and/or InnoDB tables.
- Split thd->options flag OPTION_STATUS_NO_TRANS_UPDATE to two flags:
OPTION_STATUS_NO_TRANS_UPDATE and OPTION_KEEP_LOG.
This allowed me to remove some wrong warnings about:
"Some non-transactional changed tables couldn't be rolled back"
- Fixed handling of INSERT .. SELECT and CREATE ... SELECT that wrongly reset
(thd->options & OPTION_STATUS_NO_TRANS_UPDATE) which caused us to loose
some warnings about
"Some non-transactional changed tables couldn't be rolled back")
- Fixed use of uninitialized memory in ha_ndbcluster.cc::delete_table()
which could cause delete_table to report random failures.
- Fixed core dumps for some tests when running with --debug
- Added missing FN_LIBCHAR in mysql_rm_tmp_tables()
(This has probably caused us to not properly remove temporary files after
crash)
- slow_logs was not properly initialized, which could maybe cause
extra/lost entries in slow log.
- If we get an duplicate row on insert, change column map to read and
write all columns while retrying the operation. This is required by
the definition of REPLACE and also ensures that fields that are only
part of UPDATE are properly handled. This fixed a bug in NDB and
REPLACE where REPLACE wrongly copied some column values from the replaced
row.
- For table handler that doesn't support NULL in keys, we would give an error
when creating a primary key with NULL fields, even after the fields has been
automaticly converted to NOT NULL.
- Creating a primary key on a SPATIAL key, would fail if field was not
declared as NOT NULL.
Cleanups:
- Removed not used condition argument to setup_tables
- Removed not needed item function reset_query_id_processor().
- Field->add_index is removed. Now this is instead maintained in
(field->flags & FIELD_IN_ADD_INDEX)
- Field->fieldnr is removed (use field->field_index instead)
- New argument to filesort() to indicate that it should return a set of
row pointers (not used columns). This allowed me to remove some references
to sql_command in filesort and should also enable us to return column
results in some cases where we couldn't before.
- Changed column bitmap handling in opt_range.cc to be aligned with TABLE
bitmap, which allowed me to use bitmap functions instead of looping over
all fields to create some needed bitmaps. (Faster and smaller code)
- Broke up found too long lines
- Moved some variable declaration at start of function for better code
readability.
- Removed some not used arguments from functions.
(setup_fields(), mysql_prepare_insert_check_table())
- setup_fields() now takes an enum instead of an int for marking columns
usage.
- For internal temporary tables, use handler::write_row(),
handler::delete_row() and handler::update_row() instead of
handler::ha_xxxx() for faster execution.
- Changed some constants to enum's and define's.
- Using separate column read and write sets allows for easier checking
of timestamp field was set by statement.
- Remove calls to free_io_cache() as this is now done automaticly in ha_reset()
- Don't build table->normalized_path as this is now identical to table->path
(after bar's fixes to convert filenames)
- Fixed some missed DBUG_PRINT(.."%lx") to use "0x%lx" to make it easier to
do comparision with the 'convert-dbug-for-diff' tool.
Things left to do in 5.1:
- We wrongly log failed CREATE TABLE ... SELECT in some cases when using
row based logging (as shown by testcase binlog_row_mix_innodb_myisam.result)
Mats has promised to look into this.
- Test that my fix for CREATE TABLE ... SELECT is indeed correct.
(I added several test cases for this, but in this case it's better that
someone else also tests this throughly).
Lars has promosed to do this.
2006-06-04 17:52:22 +02:00
|
|
|
mark_used_columns= stmt->mark_used_columns;
|
2003-12-20 00:16:10 +01:00
|
|
|
lex= stmt->lex;
|
|
|
|
query= stmt->query;
|
|
|
|
query_length= stmt->query_length;
|
2004-08-03 12:32:21 +02:00
|
|
|
cursor= stmt->cursor;
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-08-21 00:02:46 +02:00
|
|
|
void
|
|
|
|
Statement::set_n_backup_statement(Statement *stmt, Statement *backup)
|
|
|
|
{
|
2005-07-01 06:05:42 +02:00
|
|
|
DBUG_ENTER("Statement::set_n_backup_statement");
|
2004-08-21 00:02:46 +02:00
|
|
|
backup->set_statement(this);
|
|
|
|
set_statement(stmt);
|
2005-07-01 06:05:42 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-08-21 00:02:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Statement::restore_backup_statement(Statement *stmt, Statement *backup)
|
|
|
|
{
|
2005-07-01 06:05:42 +02:00
|
|
|
DBUG_ENTER("Statement::restore_backup_statement");
|
2004-08-21 00:02:46 +02:00
|
|
|
stmt->set_statement(this);
|
|
|
|
set_statement(backup);
|
2005-07-01 06:05:42 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-08-21 00:02:46 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-14 00:53:59 +02:00
|
|
|
void THD::end_statement()
|
2004-08-24 18:17:11 +02:00
|
|
|
{
|
A fix for Bug#26750 "valgrind leak in sp_head" (and post-review
fixes).
The legend: on a replication slave, in case a trigger creation
was filtered out because of application of replicate-do-table/
replicate-ignore-table rule, the parsed definition of a trigger was not
cleaned up properly. LEX::sphead member was left around and leaked
memory. Until the actual implementation of support of
replicate-ignore-table rules for triggers by the patch for Bug 24478 it
was never the case that "case SQLCOM_CREATE_TRIGGER"
was not executed once a trigger was parsed,
so the deletion of lex->sphead there worked and the memory did not leak.
The fix:
The real cause of the bug is that there is no 1 or 2 places where
we can clean up the main LEX after parse. And the reason we
can not have just one or two places where we clean up the LEX is
asymmetric behaviour of MYSQLparse in case of success or error.
One of the root causes of this behaviour is the code in Item::Item()
constructor. There, a newly created item adds itself to THD::free_list
- a single-linked list of Items used in a statement. Yuck. This code
is unaware that we may have more than one statement active at a time,
and always assumes that the free_list of the current statement is
located in THD::free_list. One day we need to be able to explicitly
allocate an item in a given Query_arena.
Thus, when parsing a definition of a stored procedure, like
CREATE PROCEDURE p1() BEGIN SELECT a FROM t1; SELECT b FROM t1; END;
we actually need to reset THD::mem_root, THD::free_list and THD::lex
to parse the nested procedure statement (SELECT *).
The actual reset and restore is implemented in semantic actions
attached to sp_proc_stmt grammar rule.
The problem is that in case of a parsing error inside a nested statement
Bison generated parser would abort immediately, without executing the
restore part of the semantic action. This would leave THD in an
in-the-middle-of-parsing state.
This is why we couldn't have had a single place where we clean up the LEX
after MYSQLparse - in case of an error we needed to do a clean up
immediately, in case of success a clean up could have been delayed.
This left the door open for a memory leak.
One of the following possibilities were considered when working on a fix:
- patch the replication logic to do the clean up. Rejected
as breaks module borders, replication code should not need to know the
gory details of clean up procedure after CREATE TRIGGER.
- wrap MYSQLparse with a function that would do a clean up.
Rejected as ideally we should fix the problem when it happens, not
adjust for it outside of the problematic code.
- make sure MYSQLparse cleans up after itself by invoking the clean up
functionality in the appropriate places before return. Implemented in
this patch.
- use %destructor rule for sp_proc_stmt to restore THD - cleaner
than the prevoius approach, but rejected
because needs a careful analysis of the side effects, and this patch is
for 5.0, and long term we need to use the next alternative anyway
- make sure that sp_proc_stmt doesn't juggle with THD - this is a
large work that will affect many modules.
Cleanup: move main_lex and main_mem_root from Statement to its
only two descendants Prepared_statement and THD. This ensures that
when a Statement instance was created for purposes of statement backup,
we do not involve LEX constructor/destructor, which is fairly expensive.
In order to track that the transformation produces equivalent
functionality please check the respective constructors and destructors
of Statement, Prepared_statement and THD - these members were
used only there.
This cleanup is unrelated to the patch.
2007-03-07 10:24:46 +01:00
|
|
|
/* Cleanup SQL processing state to reuse this statement in next query. */
|
2004-08-24 18:17:11 +02:00
|
|
|
lex_end(lex);
|
|
|
|
delete lex->result;
|
|
|
|
lex->result= 0;
|
2004-09-15 21:10:31 +02:00
|
|
|
/* Note that free_list is freed in cleanup_after_query() */
|
|
|
|
|
2004-08-24 18:17:11 +02:00
|
|
|
/*
|
|
|
|
Don't free mem_root, as mem_root is freed in the end of dispatch_command
|
|
|
|
(once for any command).
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-02 15:21:19 +02:00
|
|
|
void THD::set_n_backup_active_arena(Query_arena *set, Query_arena *backup)
|
2004-02-08 19:14:13 +01:00
|
|
|
{
|
2005-09-02 15:21:19 +02:00
|
|
|
DBUG_ENTER("THD::set_n_backup_active_arena");
|
2005-06-23 18:22:08 +02:00
|
|
|
DBUG_ASSERT(backup->is_backup_arena == FALSE);
|
2005-07-01 06:05:42 +02:00
|
|
|
|
2005-09-02 15:21:19 +02:00
|
|
|
backup->set_query_arena(this);
|
|
|
|
set_query_arena(set);
|
2004-11-03 11:39:38 +01:00
|
|
|
#ifndef DBUG_OFF
|
2005-06-23 18:22:08 +02:00
|
|
|
backup->is_backup_arena= TRUE;
|
2004-11-03 11:39:38 +01:00
|
|
|
#endif
|
2004-09-09 05:59:26 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2004-02-08 19:14:13 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-02 15:21:19 +02:00
|
|
|
void THD::restore_active_arena(Query_arena *set, Query_arena *backup)
|
2004-02-12 02:10:26 +01:00
|
|
|
{
|
2005-09-02 15:21:19 +02:00
|
|
|
DBUG_ENTER("THD::restore_active_arena");
|
2005-06-23 18:22:08 +02:00
|
|
|
DBUG_ASSERT(backup->is_backup_arena);
|
2005-09-02 15:21:19 +02:00
|
|
|
set->set_query_arena(this);
|
|
|
|
set_query_arena(backup);
|
2004-11-03 11:39:38 +01:00
|
|
|
#ifndef DBUG_OFF
|
2005-06-23 18:22:08 +02:00
|
|
|
backup->is_backup_arena= FALSE;
|
2004-09-23 11:48:17 +02:00
|
|
|
#endif
|
2004-11-03 11:39:38 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2004-02-12 02:10:26 +01:00
|
|
|
}
|
|
|
|
|
2003-12-20 00:16:10 +01:00
|
|
|
Statement::~Statement()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
C_MODE_START
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
static uchar *
|
|
|
|
get_statement_id_as_hash_key(const uchar *record, size_t *key_length,
|
2003-12-20 00:16:10 +01:00
|
|
|
my_bool not_used __attribute__((unused)))
|
|
|
|
{
|
|
|
|
const Statement *statement= (const Statement *) record;
|
|
|
|
*key_length= sizeof(statement->id);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
return (uchar *) &((const Statement *) statement)->id;
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void delete_statement_as_hash_key(void *key)
|
|
|
|
{
|
|
|
|
delete (Statement *) key;
|
|
|
|
}
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
static uchar *get_stmt_name_hash_key(Statement *entry, size_t *length,
|
2004-04-30 18:08:38 +02:00
|
|
|
my_bool not_used __attribute__((unused)))
|
2004-04-12 23:58:48 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
*length= entry->name.length;
|
|
|
|
return (uchar*) entry->name.str;
|
2004-04-12 23:58:48 +02:00
|
|
|
}
|
|
|
|
|
2003-12-20 00:16:10 +01:00
|
|
|
C_MODE_END
|
|
|
|
|
|
|
|
Statement_map::Statement_map() :
|
|
|
|
last_found_statement(0)
|
|
|
|
{
|
2004-04-12 23:58:48 +02:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
START_STMT_HASH_SIZE = 16,
|
|
|
|
START_NAME_HASH_SIZE = 16
|
|
|
|
};
|
2004-09-08 10:33:05 +02:00
|
|
|
hash_init(&st_hash, &my_charset_bin, START_STMT_HASH_SIZE, 0, 0,
|
2003-12-20 00:16:10 +01:00
|
|
|
get_statement_id_as_hash_key,
|
|
|
|
delete_statement_as_hash_key, MYF(0));
|
2004-08-29 17:44:28 +02:00
|
|
|
hash_init(&names_hash, system_charset_info, START_NAME_HASH_SIZE, 0, 0,
|
2004-04-30 18:08:38 +02:00
|
|
|
(hash_get_key) get_stmt_name_hash_key,
|
|
|
|
NULL,MYF(0));
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
Implement WL#2661 "Prepared Statements: Dynamic SQL in Stored Procedures".
The idea of the patch is to separate statement processing logic,
such as parsing, validation of the parsed tree, execution and cleanup,
from global query processing logic, such as logging, resetting
priorities of a thread, resetting stored procedure cache, resetting
thread count of errors and warnings.
This makes PREPARE and EXECUTE behave similarly to the rest of SQL
statements and allows their use in stored procedures.
This patch contains a change in behaviour:
until recently for each SQL prepared statement command, 2 queries
were written to the general log, e.g.
[Query] prepare stmt from @stmt_text;
[Prepare] select * from t1 <-- contents of @stmt_text
The chagne was necessary to prevent [Prepare] commands from being written
to the general log when executing a stored procedure with Dynamic SQL.
We should consider whether the old behavior is preferrable and probably
restore it.
This patch refixes Bug#7115, Bug#10975 (partially), Bug#10605 (various bugs
in Dynamic SQL reported before it was disabled).
2005-09-03 01:13:18 +02:00
|
|
|
|
2006-04-07 21:37:06 +02:00
|
|
|
/*
|
|
|
|
Insert a new statement to the thread-local statement map.
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
If there was an old statement with the same name, replace it with the
|
|
|
|
new one. Otherwise, check if max_prepared_stmt_count is not reached yet,
|
|
|
|
increase prepared_stmt_count, and insert the new statement. It's okay
|
|
|
|
to delete an old statement and fail to insert the new one.
|
|
|
|
|
|
|
|
POSTCONDITIONS
|
|
|
|
All named prepared statements are also present in names_hash.
|
|
|
|
Statement names in names_hash are unique.
|
|
|
|
The statement is added only if prepared_stmt_count < max_prepard_stmt_count
|
|
|
|
last_found_statement always points to a valid statement or is 0
|
|
|
|
|
|
|
|
RETURN VALUE
|
|
|
|
0 success
|
|
|
|
1 error: out of resources or max_prepared_stmt_count limit has been
|
|
|
|
reached. An error is sent to the client, the statement is deleted.
|
|
|
|
*/
|
|
|
|
|
|
|
|
int Statement_map::insert(THD *thd, Statement *statement)
|
2004-04-12 23:58:48 +02:00
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (my_hash_insert(&st_hash, (uchar*) statement))
|
2004-04-12 23:58:48 +02:00
|
|
|
{
|
2006-04-07 21:37:06 +02:00
|
|
|
/*
|
|
|
|
Delete is needed only in case of an insert failure. In all other
|
|
|
|
cases hash_delete will also delete the statement.
|
|
|
|
*/
|
|
|
|
delete statement;
|
|
|
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
|
|
|
goto err_st_hash;
|
|
|
|
}
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
if (statement->name.str && my_hash_insert(&names_hash, (uchar*) statement))
|
2004-04-12 23:58:48 +02:00
|
|
|
{
|
2006-04-12 23:46:44 +02:00
|
|
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
|
|
|
goto err_names_hash;
|
2004-04-12 23:58:48 +02:00
|
|
|
}
|
2006-04-07 21:37:06 +02:00
|
|
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
|
|
|
/*
|
|
|
|
We don't check that prepared_stmt_count is <= max_prepared_stmt_count
|
|
|
|
because we would like to allow to lower the total limit
|
|
|
|
of prepared statements below the current count. In that case
|
|
|
|
no new statements can be added until prepared_stmt_count drops below
|
|
|
|
the limit.
|
|
|
|
*/
|
|
|
|
if (prepared_stmt_count >= max_prepared_stmt_count)
|
|
|
|
{
|
|
|
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
2006-04-12 23:46:44 +02:00
|
|
|
my_error(ER_MAX_PREPARED_STMT_COUNT_REACHED, MYF(0),
|
|
|
|
max_prepared_stmt_count);
|
2006-04-07 21:37:06 +02:00
|
|
|
goto err_max;
|
|
|
|
}
|
|
|
|
prepared_stmt_count++;
|
|
|
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
|
|
|
|
2005-10-06 16:54:43 +02:00
|
|
|
last_found_statement= statement;
|
2006-04-07 21:37:06 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err_max:
|
|
|
|
if (statement->name.str)
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
hash_delete(&names_hash, (uchar*) statement);
|
2006-04-07 21:37:06 +02:00
|
|
|
err_names_hash:
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
hash_delete(&st_hash, (uchar*) statement);
|
2006-04-07 21:37:06 +02:00
|
|
|
err_st_hash:
|
|
|
|
return 1;
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
2004-04-12 23:58:48 +02:00
|
|
|
|
2005-07-19 20:21:12 +02:00
|
|
|
void Statement_map::close_transient_cursors()
|
|
|
|
{
|
2005-09-22 00:11:21 +02:00
|
|
|
#ifdef TO_BE_IMPLEMENTED
|
2005-07-19 20:21:12 +02:00
|
|
|
Statement *stmt;
|
|
|
|
while ((stmt= transient_cursor_list.head()))
|
|
|
|
stmt->close_cursor(); /* deletes itself from the list */
|
2005-09-22 00:11:21 +02:00
|
|
|
#endif
|
2005-07-19 20:21:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-04-07 21:37:06 +02:00
|
|
|
void Statement_map::erase(Statement *statement)
|
|
|
|
{
|
|
|
|
if (statement == last_found_statement)
|
|
|
|
last_found_statement= 0;
|
|
|
|
if (statement->name.str)
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
hash_delete(&names_hash, (uchar *) statement);
|
2006-04-12 23:46:44 +02:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
hash_delete(&st_hash, (uchar *) statement);
|
2006-04-07 21:37:06 +02:00
|
|
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
|
|
|
DBUG_ASSERT(prepared_stmt_count > 0);
|
|
|
|
prepared_stmt_count--;
|
|
|
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Statement_map::reset()
|
|
|
|
{
|
|
|
|
/* Must be first, hash_free will reset st_hash.records */
|
|
|
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
|
|
|
DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
|
|
|
|
prepared_stmt_count-= st_hash.records;
|
|
|
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
|
|
|
|
|
|
|
my_hash_reset(&names_hash);
|
|
|
|
my_hash_reset(&st_hash);
|
|
|
|
last_found_statement= 0;
|
2003-12-20 00:16:10 +01:00
|
|
|
}
|
|
|
|
|
2004-04-12 23:58:48 +02:00
|
|
|
|
2006-04-07 21:37:06 +02:00
|
|
|
Statement_map::~Statement_map()
|
|
|
|
{
|
|
|
|
/* Must go first, hash_free will reset st_hash.records */
|
|
|
|
pthread_mutex_lock(&LOCK_prepared_stmt_count);
|
|
|
|
DBUG_ASSERT(prepared_stmt_count >= st_hash.records);
|
|
|
|
prepared_stmt_count-= st_hash.records;
|
|
|
|
pthread_mutex_unlock(&LOCK_prepared_stmt_count);
|
|
|
|
|
|
|
|
hash_free(&names_hash);
|
|
|
|
hash_free(&st_hash);
|
|
|
|
}
|
|
|
|
|
2002-10-16 15:55:08 +02:00
|
|
|
bool select_dumpvar::send_data(List<Item> &items)
|
|
|
|
{
|
2006-11-29 18:15:15 +01:00
|
|
|
List_iterator_fast<my_var> var_li(var_list);
|
2005-05-09 00:59:10 +02:00
|
|
|
List_iterator<Item> it(items);
|
2006-11-28 23:21:39 +01:00
|
|
|
Item *item;
|
2006-11-29 18:15:15 +01:00
|
|
|
my_var *mv;
|
2006-06-21 00:21:10 +02:00
|
|
|
DBUG_ENTER("select_dumpvar::send_data");
|
2002-10-16 15:55:08 +02:00
|
|
|
|
2003-01-18 15:23:37 +01:00
|
|
|
if (unit->offset_limit_cnt)
|
2006-06-21 00:21:10 +02:00
|
|
|
{ // using limit offset,count
|
2003-01-18 15:23:37 +01:00
|
|
|
unit->offset_limit_cnt--;
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
2002-10-16 15:55:08 +02:00
|
|
|
if (row_count++)
|
|
|
|
{
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
|
2002-10-16 15:55:08 +02:00
|
|
|
DBUG_RETURN(1);
|
|
|
|
}
|
2006-11-29 18:15:15 +01:00
|
|
|
while ((mv= var_li++) && (item= it++))
|
2003-10-24 20:14:26 +02:00
|
|
|
{
|
2006-11-29 18:15:15 +01:00
|
|
|
if (mv->local)
|
2003-01-18 17:21:13 +01:00
|
|
|
{
|
2006-11-30 19:09:48 +01:00
|
|
|
if (thd->spcont->set_variable(thd, mv->offset, &item))
|
|
|
|
DBUG_RETURN(1);
|
2003-01-18 17:21:13 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2006-11-30 19:09:48 +01:00
|
|
|
Item_func_set_user_var *suv= new Item_func_set_user_var(mv->s, item);
|
|
|
|
suv->fix_fields(thd, 0);
|
|
|
|
suv->check(0);
|
2006-11-29 18:15:15 +01:00
|
|
|
suv->update();
|
2003-01-18 17:21:13 +01:00
|
|
|
}
|
2003-10-24 20:14:26 +02:00
|
|
|
}
|
2008-02-19 12:43:01 +01:00
|
|
|
DBUG_RETURN(thd->is_error());
|
2002-10-11 20:49:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool select_dumpvar::send_eof()
|
|
|
|
{
|
2003-11-19 11:26:18 +01:00
|
|
|
if (! row_count)
|
2004-11-24 17:22:29 +01:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
|
2007-10-15 14:42:41 +02:00
|
|
|
/*
|
|
|
|
In order to remember the value of affected rows for ROW_COUNT()
|
|
|
|
function, SELECT INTO has to have an own SQLCOM.
|
|
|
|
TODO: split from SQLCOM_SELECT
|
|
|
|
*/
|
2008-02-19 13:45:21 +01:00
|
|
|
::my_ok(thd,row_count);
|
2003-11-19 11:26:18 +01:00
|
|
|
return 0;
|
2002-10-11 20:49:10 +02:00
|
|
|
}
|
2003-11-28 11:18:13 +01:00
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
TMP_TABLE_PARAM
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void TMP_TABLE_PARAM::init()
|
|
|
|
{
|
2006-01-18 12:48:57 +01:00
|
|
|
DBUG_ENTER("TMP_TABLE_PARAM::init");
|
|
|
|
DBUG_PRINT("enter", ("this: 0x%lx", (ulong)this));
|
2003-11-28 11:18:13 +01:00
|
|
|
field_count= sum_func_count= func_count= hidden_field_count= 0;
|
|
|
|
group_parts= group_length= group_null_parts= 0;
|
|
|
|
quick_group= 1;
|
2004-11-18 10:16:06 +01:00
|
|
|
table_charset= 0;
|
2005-11-30 11:52:12 +01:00
|
|
|
precomputed_group_by= 0;
|
2006-01-18 12:48:57 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2003-11-28 11:18:13 +01:00
|
|
|
}
|
2004-09-13 15:48:01 +02:00
|
|
|
|
|
|
|
|
|
|
|
void thd_increment_bytes_sent(ulong length)
|
|
|
|
{
|
2005-03-09 19:22:30 +01:00
|
|
|
THD *thd=current_thd;
|
2005-03-09 20:49:44 +01:00
|
|
|
if (likely(thd != 0))
|
2005-03-09 19:22:30 +01:00
|
|
|
{ /* current_thd==0 when close_connection() calls net_send_error() */
|
|
|
|
thd->status_var.bytes_sent+= length;
|
|
|
|
}
|
2004-09-13 15:48:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void thd_increment_bytes_received(ulong length)
|
|
|
|
{
|
|
|
|
current_thd->status_var.bytes_received+= length;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void thd_increment_net_big_packet_count(ulong length)
|
|
|
|
{
|
|
|
|
current_thd->status_var.net_big_packet_count+= length;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void THD::set_status_var_init()
|
|
|
|
{
|
|
|
|
bzero((char*) &status_var, sizeof(status_var));
|
|
|
|
}
|
2005-07-13 11:48:13 +02:00
|
|
|
|
2005-09-15 21:29:07 +02:00
|
|
|
|
2005-09-20 20:20:38 +02:00
|
|
|
void Security_context::init()
|
2005-09-15 21:29:07 +02:00
|
|
|
{
|
|
|
|
host= user= priv_user= ip= 0;
|
|
|
|
host_or_ip= "connecting host";
|
2006-07-04 21:46:15 +02:00
|
|
|
priv_host[0]= '\0';
|
2007-10-19 17:57:08 +02:00
|
|
|
master_access= 0;
|
2005-09-15 21:29:07 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
|
|
db_access= NO_ACCESS;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-20 20:20:38 +02:00
|
|
|
void Security_context::destroy()
|
2005-09-15 21:29:07 +02:00
|
|
|
{
|
|
|
|
// If not pointer to constant
|
|
|
|
if (host != my_localhost)
|
|
|
|
safeFree(host);
|
|
|
|
if (user != delayed_user)
|
|
|
|
safeFree(user);
|
|
|
|
safeFree(ip);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-09-20 20:20:38 +02:00
|
|
|
void Security_context::skip_grants()
|
2005-09-15 21:29:07 +02:00
|
|
|
{
|
|
|
|
/* privileges for the user are unknown everything is allowed */
|
|
|
|
host_or_ip= (char *)"";
|
|
|
|
master_access= ~NO_ACCESS;
|
|
|
|
priv_user= (char *)"";
|
|
|
|
*priv_host= '\0';
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-22 20:46:13 +02:00
|
|
|
bool Security_context::set_user(char *user_arg)
|
|
|
|
{
|
|
|
|
safeFree(user);
|
|
|
|
user= my_strdup(user_arg, MYF(0));
|
|
|
|
return user == 0;
|
|
|
|
}
|
|
|
|
|
2007-04-13 22:35:56 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
|
|
/**
|
|
|
|
Initialize this security context from the passed in credentials
|
|
|
|
and activate it in the current thread.
|
|
|
|
|
2007-08-16 16:07:48 +02:00
|
|
|
@param thd
|
|
|
|
@param definer_user
|
|
|
|
@param definer_host
|
|
|
|
@param db
|
2007-04-13 22:35:56 +02:00
|
|
|
@param[out] backup Save a pointer to the current security context
|
|
|
|
in the thread. In case of success it points to the
|
|
|
|
saved old context, otherwise it points to NULL.
|
|
|
|
|
|
|
|
|
|
|
|
During execution of a statement, multiple security contexts may
|
|
|
|
be needed:
|
|
|
|
- the security context of the authenticated user, used as the
|
|
|
|
default security context for all top-level statements
|
|
|
|
- in case of a view or a stored program, possibly the security
|
|
|
|
context of the definer of the routine, if the object is
|
|
|
|
defined with SQL SECURITY DEFINER option.
|
|
|
|
|
|
|
|
The currently "active" security context is parameterized in THD
|
|
|
|
member security_ctx. By default, after a connection is
|
|
|
|
established, this member points at the "main" security context
|
|
|
|
- the credentials of the authenticated user.
|
|
|
|
|
|
|
|
Later, if we would like to execute some sub-statement or a part
|
|
|
|
of a statement under credentials of a different user, e.g.
|
|
|
|
definer of a procedure, we authenticate this user in a local
|
|
|
|
instance of Security_context by means of this method (and
|
|
|
|
ultimately by means of acl_getroot_no_password), and make the
|
|
|
|
local instance active in the thread by re-setting
|
|
|
|
thd->security_ctx pointer.
|
|
|
|
|
|
|
|
Note, that the life cycle and memory management of the "main" and
|
|
|
|
temporary security contexts are different.
|
|
|
|
For the main security context, the memory for user/host/ip is
|
|
|
|
allocated on system heap, and the THD class frees this memory in
|
|
|
|
its destructor. The only case when contents of the main security
|
|
|
|
context may change during its life time is when someone issued
|
|
|
|
CHANGE USER command.
|
|
|
|
Memory management of a "temporary" security context is
|
|
|
|
responsibility of the module that creates it.
|
|
|
|
|
|
|
|
@retval TRUE there is no user with the given credentials. The erro
|
|
|
|
is reported in the thread.
|
|
|
|
@retval FALSE success
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
|
|
|
Security_context::
|
|
|
|
change_security_context(THD *thd,
|
|
|
|
LEX_STRING *definer_user,
|
|
|
|
LEX_STRING *definer_host,
|
|
|
|
LEX_STRING *db,
|
|
|
|
Security_context **backup)
|
|
|
|
{
|
|
|
|
bool needs_change;
|
|
|
|
|
|
|
|
DBUG_ENTER("Security_context::change_security_context");
|
|
|
|
|
|
|
|
DBUG_ASSERT(definer_user->str && definer_host->str);
|
|
|
|
|
|
|
|
*backup= NULL;
|
|
|
|
/*
|
|
|
|
The current security context may have NULL members
|
|
|
|
if we have just started the thread and not authenticated
|
|
|
|
any user. This use case is currently in events worker thread.
|
|
|
|
*/
|
|
|
|
needs_change= (thd->security_ctx->priv_user == NULL ||
|
|
|
|
strcmp(definer_user->str, thd->security_ctx->priv_user) ||
|
|
|
|
thd->security_ctx->priv_host == NULL ||
|
|
|
|
my_strcasecmp(system_charset_info, definer_host->str,
|
|
|
|
thd->security_ctx->priv_host));
|
|
|
|
if (needs_change)
|
|
|
|
{
|
|
|
|
if (acl_getroot_no_password(this, definer_user->str, definer_host->str,
|
|
|
|
definer_host->str, db->str))
|
|
|
|
{
|
|
|
|
my_error(ER_NO_SUCH_USER, MYF(0), definer_user->str,
|
|
|
|
definer_host->str);
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
}
|
|
|
|
*backup= thd->security_ctx;
|
|
|
|
thd->security_ctx= this;
|
|
|
|
}
|
|
|
|
|
|
|
|
DBUG_RETURN(FALSE);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Security_context::restore_security_context(THD *thd,
|
|
|
|
Security_context *backup)
|
|
|
|
{
|
|
|
|
if (backup)
|
|
|
|
thd->security_ctx= backup;
|
|
|
|
}
|
|
|
|
#endif
|
2006-06-28 01:28:03 +02:00
|
|
|
|
2005-07-13 11:48:13 +02:00
|
|
|
/****************************************************************************
|
|
|
|
Handling of open and locked tables states.
|
|
|
|
|
|
|
|
This is used when we want to open/lock (and then close) some tables when
|
|
|
|
we already have a set of tables open and locked. We use these methods for
|
|
|
|
access to mysql.proc table to find definitions of stored routines.
|
|
|
|
****************************************************************************/
|
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
void THD::reset_n_backup_open_tables_state(Open_tables_state *backup)
|
2005-07-13 11:48:13 +02:00
|
|
|
{
|
2005-08-08 15:46:06 +02:00
|
|
|
DBUG_ENTER("reset_n_backup_open_tables_state");
|
|
|
|
backup->set_open_tables_state(this);
|
2005-07-13 11:48:13 +02:00
|
|
|
reset_open_tables_state();
|
2006-02-16 08:30:53 +01:00
|
|
|
state_flags|= Open_tables_state::BACKUPS_AVAIL;
|
2005-08-08 15:46:06 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2005-07-13 11:48:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-08-08 15:46:06 +02:00
|
|
|
void THD::restore_backup_open_tables_state(Open_tables_state *backup)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("restore_backup_open_tables_state");
|
|
|
|
/*
|
|
|
|
Before we will throw away current open tables state we want
|
|
|
|
to be sure that it was properly cleaned up.
|
|
|
|
*/
|
|
|
|
DBUG_ASSERT(open_tables == 0 && temporary_tables == 0 &&
|
|
|
|
handler_tables == 0 && derived_tables == 0 &&
|
|
|
|
lock == 0 && locked_tables == 0 &&
|
2008-04-08 18:01:20 +02:00
|
|
|
prelocked_mode == NON_PRELOCKED &&
|
2008-05-20 09:29:16 +02:00
|
|
|
m_reprepare_observer == NULL);
|
2005-08-08 15:46:06 +02:00
|
|
|
set_open_tables_state(backup);
|
2005-07-13 11:48:13 +02:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
/**
|
|
|
|
Check the killed state of a user thread
|
|
|
|
@param thd user thread
|
|
|
|
@retval 0 the user thread is active
|
|
|
|
@retval 1 the user thread has been killed
|
|
|
|
*/
|
|
|
|
extern "C" int thd_killed(const MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
return(thd->killed);
|
|
|
|
}
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2008-02-19 17:44:09 +01:00
|
|
|
/**
|
|
|
|
Return the thread id of a user thread
|
|
|
|
@param thd user thread
|
|
|
|
@return thread id
|
|
|
|
*/
|
|
|
|
extern "C" unsigned long thd_get_thread_id(const MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
return((unsigned long)thd->thread_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
#ifdef INNODB_COMPATIBILITY_HOOKS
|
|
|
|
extern "C" struct charset_info_st *thd_charset(MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
return(thd->charset());
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" char **thd_query(MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
return(&thd->query);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern "C" int thd_slave_thread(const MYSQL_THD thd)
|
|
|
|
{
|
|
|
|
return(thd->slave_thread);
|
|
|
|
}
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-07-05 01:05:47 +02:00
|
|
|
extern "C" int thd_non_transactional_update(const MYSQL_THD thd)
|
|
|
|
{
|
2007-07-31 13:58:04 +02:00
|
|
|
return(thd->transaction.all.modified_non_trans_table);
|
2007-07-05 01:05:47 +02:00
|
|
|
}
|
|
|
|
|
2007-07-10 13:37:43 +02:00
|
|
|
extern "C" int thd_binlog_format(const MYSQL_THD thd)
|
2007-07-05 01:05:47 +02:00
|
|
|
{
|
|
|
|
return (int) thd->variables.binlog_format;
|
|
|
|
}
|
2007-08-02 10:22:31 +02:00
|
|
|
|
|
|
|
extern "C" void thd_mark_transaction_to_rollback(MYSQL_THD thd, bool all)
|
|
|
|
{
|
|
|
|
mark_transaction_to_rollback(thd, all);
|
|
|
|
}
|
2007-07-05 01:05:47 +02:00
|
|
|
#endif // INNODB_COMPATIBILITY_HOOKS */
|
2005-08-15 17:35:48 +02:00
|
|
|
|
2005-08-15 17:15:12 +02:00
|
|
|
/****************************************************************************
|
|
|
|
Handling of statement states in functions and triggers.
|
|
|
|
|
|
|
|
This is used to ensure that the function/trigger gets a clean state
|
|
|
|
to work with and does not cause any side effects of the calling statement.
|
|
|
|
|
|
|
|
It also allows most stored functions and triggers to replicate even
|
|
|
|
if they are used items that would normally be stored in the binary
|
|
|
|
replication (like last_insert_id() etc...)
|
|
|
|
|
|
|
|
The following things is done
|
|
|
|
- Disable binary logging for the duration of the statement
|
|
|
|
- Disable multi-result-sets for the duration of the statement
|
2006-04-21 16:55:04 +02:00
|
|
|
- Value of last_insert_id() is saved and restored
|
2005-08-15 17:15:12 +02:00
|
|
|
- Value set by 'SET INSERT_ID=#' is reset and restored
|
|
|
|
- Value for found_rows() is reset and restored
|
|
|
|
- examined_row_count is added to the total
|
|
|
|
- cuted_fields is added to the total
|
2005-11-19 13:09:23 +01:00
|
|
|
- new savepoint level is created and destroyed
|
2005-08-15 17:15:12 +02:00
|
|
|
|
|
|
|
NOTES:
|
|
|
|
Seed for random() is saved for the first! usage of RAND()
|
|
|
|
We reset examined_row_count and cuted_fields and add these to the
|
|
|
|
result to ensure that if we have a bug that would reset these within
|
|
|
|
a function, we are not loosing any rows from the main statement.
|
2006-04-21 16:55:04 +02:00
|
|
|
|
|
|
|
We do not reset value of last_insert_id().
|
2005-08-15 17:15:12 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|
|
|
uint new_state)
|
|
|
|
{
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
|
|
|
/* BUG#33029, if we are replicating from a buggy master, reset
|
|
|
|
auto_inc_intervals_forced to prevent substatement
|
|
|
|
(triggers/functions) from using erroneous INSERT_ID value
|
|
|
|
*/
|
|
|
|
if (rpl_master_erroneous_autoinc(this))
|
|
|
|
{
|
2008-06-19 20:47:59 +02:00
|
|
|
DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
|
|
|
|
auto_inc_intervals_forced.swap(&backup->auto_inc_intervals_forced);
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-08-15 17:15:12 +02:00
|
|
|
backup->options= options;
|
|
|
|
backup->in_sub_stmt= in_sub_stmt;
|
|
|
|
backup->enable_slow_log= enable_slow_log;
|
|
|
|
backup->limit_found_rows= limit_found_rows;
|
|
|
|
backup->examined_row_count= examined_row_count;
|
|
|
|
backup->sent_row_count= sent_row_count;
|
|
|
|
backup->cuted_fields= cuted_fields;
|
|
|
|
backup->client_capabilities= client_capabilities;
|
2005-11-19 13:09:23 +01:00
|
|
|
backup->savepoints= transaction.savepoints;
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
backup->first_successful_insert_id_in_prev_stmt=
|
|
|
|
first_successful_insert_id_in_prev_stmt;
|
|
|
|
backup->first_successful_insert_id_in_cur_stmt=
|
|
|
|
first_successful_insert_id_in_cur_stmt;
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
!current_stmt_binlog_row_based)
|
2006-05-16 11:16:23 +02:00
|
|
|
{
|
2005-08-25 15:34:34 +02:00
|
|
|
options&= ~OPTION_BIN_LOG;
|
2007-02-27 19:20:47 +01:00
|
|
|
}
|
2007-02-26 20:06:10 +01:00
|
|
|
|
|
|
|
if ((backup->options & OPTION_BIN_LOG) && is_update_query(lex->sql_command)&&
|
|
|
|
!current_stmt_binlog_row_based)
|
|
|
|
mysql_bin_log.start_union_events(this, this->query_id);
|
|
|
|
|
2005-08-15 17:15:12 +02:00
|
|
|
/* Disable result sets */
|
|
|
|
client_capabilities &= ~CLIENT_MULTI_RESULTS;
|
|
|
|
in_sub_stmt|= new_state;
|
|
|
|
examined_row_count= 0;
|
|
|
|
sent_row_count= 0;
|
|
|
|
cuted_fields= 0;
|
2005-11-19 13:09:23 +01:00
|
|
|
transaction.savepoints= 0;
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
first_successful_insert_id_in_cur_stmt= 0;
|
2005-08-15 17:15:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
|
|
|
{
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
#ifndef EMBEDDED_LIBRARY
|
|
|
|
/* BUG#33029, if we are replicating from a buggy master, restore
|
|
|
|
auto_inc_intervals_forced so that the top statement can use the
|
|
|
|
INSERT_ID value set before this statement.
|
|
|
|
*/
|
|
|
|
if (rpl_master_erroneous_autoinc(this))
|
|
|
|
{
|
2008-06-19 20:47:59 +02:00
|
|
|
backup->auto_inc_intervals_forced.swap(&auto_inc_intervals_forced);
|
|
|
|
DBUG_ASSERT(backup->auto_inc_intervals_forced.nb_elements() == 0);
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2005-11-19 13:09:23 +01:00
|
|
|
/*
|
|
|
|
To save resources we want to release savepoints which were created
|
|
|
|
during execution of function or trigger before leaving their savepoint
|
|
|
|
level. It is enough to release first savepoint set on this level since
|
|
|
|
all later savepoints will be released automatically.
|
|
|
|
*/
|
|
|
|
if (transaction.savepoints)
|
|
|
|
{
|
|
|
|
SAVEPOINT *sv;
|
|
|
|
for (sv= transaction.savepoints; sv->prev; sv= sv->prev)
|
|
|
|
{}
|
|
|
|
/* ha_release_savepoint() never returns error. */
|
|
|
|
(void)ha_release_savepoint(this, sv);
|
|
|
|
}
|
|
|
|
transaction.savepoints= backup->savepoints;
|
2005-08-15 17:15:12 +02:00
|
|
|
options= backup->options;
|
|
|
|
in_sub_stmt= backup->in_sub_stmt;
|
|
|
|
enable_slow_log= backup->enable_slow_log;
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
first_successful_insert_id_in_prev_stmt=
|
|
|
|
backup->first_successful_insert_id_in_prev_stmt;
|
|
|
|
first_successful_insert_id_in_cur_stmt=
|
|
|
|
backup->first_successful_insert_id_in_cur_stmt;
|
2005-08-15 17:15:12 +02:00
|
|
|
limit_found_rows= backup->limit_found_rows;
|
|
|
|
sent_row_count= backup->sent_row_count;
|
|
|
|
client_capabilities= backup->client_capabilities;
|
2007-07-30 15:14:34 +02:00
|
|
|
/*
|
|
|
|
If we've left sub-statement mode, reset the fatal error flag.
|
|
|
|
Otherwise keep the current value, to propagate it up the sub-statement
|
|
|
|
stack.
|
|
|
|
*/
|
|
|
|
if (!in_sub_stmt)
|
|
|
|
is_fatal_sub_stmt_error= FALSE;
|
2005-08-15 17:15:12 +02:00
|
|
|
|
2007-02-26 20:06:10 +01:00
|
|
|
if ((options & OPTION_BIN_LOG) && is_update_query(lex->sql_command) &&
|
|
|
|
!current_stmt_binlog_row_based)
|
|
|
|
mysql_bin_log.stop_union_events(this);
|
2007-02-23 18:58:56 +01:00
|
|
|
|
2005-08-15 17:15:12 +02:00
|
|
|
/*
|
|
|
|
The following is added to the old values as we are interested in the
|
|
|
|
total complexity of the query
|
|
|
|
*/
|
|
|
|
examined_row_count+= backup->examined_row_count;
|
|
|
|
cuted_fields+= backup->cuted_fields;
|
|
|
|
}
|
2005-08-15 17:35:48 +02:00
|
|
|
|
|
|
|
|
2007-07-30 15:14:34 +02:00
|
|
|
/**
|
|
|
|
Mark transaction to rollback and mark error as fatal to a sub-statement.
|
|
|
|
|
|
|
|
@param thd Thread handle
|
|
|
|
@param all TRUE <=> rollback main transaction.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void mark_transaction_to_rollback(THD *thd, bool all)
|
|
|
|
{
|
2007-10-10 22:00:57 +02:00
|
|
|
if (thd)
|
|
|
|
{
|
|
|
|
thd->is_fatal_sub_stmt_error= TRUE;
|
|
|
|
thd->transaction_rollback_request= all;
|
|
|
|
}
|
2007-07-30 15:14:34 +02:00
|
|
|
}
|
2005-08-15 17:35:48 +02:00
|
|
|
/***************************************************************************
|
|
|
|
Handling of XA id cacheing
|
|
|
|
***************************************************************************/
|
|
|
|
|
2005-08-12 21:15:01 +02:00
|
|
|
pthread_mutex_t LOCK_xid_cache;
|
|
|
|
HASH xid_cache;
|
|
|
|
|
2007-08-13 15:11:25 +02:00
|
|
|
extern "C" uchar *xid_get_hash_key(const uchar *, size_t *, my_bool);
|
|
|
|
extern "C" void xid_free_hash(void *);
|
|
|
|
|
|
|
|
uchar *xid_get_hash_key(const uchar *ptr, size_t *length,
|
2005-08-12 21:15:01 +02:00
|
|
|
my_bool not_used __attribute__((unused)))
|
|
|
|
{
|
2005-10-05 16:38:53 +02:00
|
|
|
*length=((XID_STATE*)ptr)->xid.key_length();
|
|
|
|
return ((XID_STATE*)ptr)->xid.key();
|
2005-08-12 21:15:01 +02:00
|
|
|
}
|
|
|
|
|
2007-08-13 15:11:25 +02:00
|
|
|
void xid_free_hash(void *ptr)
|
2005-08-12 21:15:01 +02:00
|
|
|
{
|
|
|
|
if (!((XID_STATE*)ptr)->in_thd)
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
my_free((uchar*)ptr, MYF(0));
|
2005-08-12 21:15:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
bool xid_cache_init()
|
|
|
|
{
|
|
|
|
pthread_mutex_init(&LOCK_xid_cache, MY_MUTEX_INIT_FAST);
|
2005-08-14 23:20:06 +02:00
|
|
|
return hash_init(&xid_cache, &my_charset_bin, 100, 0, 0,
|
|
|
|
xid_get_hash_key, xid_free_hash, 0) != 0;
|
2005-08-12 21:15:01 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void xid_cache_free()
|
|
|
|
{
|
|
|
|
if (hash_inited(&xid_cache))
|
|
|
|
{
|
|
|
|
hash_free(&xid_cache);
|
|
|
|
pthread_mutex_destroy(&LOCK_xid_cache);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
XID_STATE *xid_cache_search(XID *xid)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&LOCK_xid_cache);
|
2005-10-05 16:38:53 +02:00
|
|
|
XID_STATE *res=(XID_STATE *)hash_search(&xid_cache, xid->key(), xid->key_length());
|
2005-08-12 21:15:01 +02:00
|
|
|
pthread_mutex_unlock(&LOCK_xid_cache);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:35:48 +02:00
|
|
|
|
2005-08-12 21:15:01 +02:00
|
|
|
bool xid_cache_insert(XID *xid, enum xa_states xa_state)
|
|
|
|
{
|
|
|
|
XID_STATE *xs;
|
|
|
|
my_bool res;
|
|
|
|
pthread_mutex_lock(&LOCK_xid_cache);
|
2005-10-05 16:38:53 +02:00
|
|
|
if (hash_search(&xid_cache, xid->key(), xid->key_length()))
|
2005-08-12 21:15:01 +02:00
|
|
|
res=0;
|
|
|
|
else if (!(xs=(XID_STATE *)my_malloc(sizeof(*xs), MYF(MY_WME))))
|
|
|
|
res=1;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
xs->xa_state=xa_state;
|
|
|
|
xs->xid.set(xid);
|
|
|
|
xs->in_thd=0;
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
res=my_hash_insert(&xid_cache, (uchar*)xs);
|
2005-08-12 21:15:01 +02:00
|
|
|
}
|
|
|
|
pthread_mutex_unlock(&LOCK_xid_cache);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:35:48 +02:00
|
|
|
|
2005-08-12 21:15:01 +02:00
|
|
|
bool xid_cache_insert(XID_STATE *xid_state)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&LOCK_xid_cache);
|
2005-10-05 16:38:53 +02:00
|
|
|
DBUG_ASSERT(hash_search(&xid_cache, xid_state->xid.key(),
|
|
|
|
xid_state->xid.key_length())==0);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
my_bool res=my_hash_insert(&xid_cache, (uchar*)xid_state);
|
2005-08-12 21:15:01 +02:00
|
|
|
pthread_mutex_unlock(&LOCK_xid_cache);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:35:48 +02:00
|
|
|
|
2005-08-12 21:15:01 +02:00
|
|
|
void xid_cache_delete(XID_STATE *xid_state)
|
|
|
|
{
|
|
|
|
pthread_mutex_lock(&LOCK_xid_cache);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
hash_delete(&xid_cache, (uchar *)xid_state);
|
2005-08-12 21:15:01 +02:00
|
|
|
pthread_mutex_unlock(&LOCK_xid_cache);
|
|
|
|
}
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
|
|
|
Implementation of interface to write rows to the binary log through the
|
|
|
|
thread. The thread is responsible for writing the rows it has
|
|
|
|
inserted/updated/deleted.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef MYSQL_CLIENT
|
|
|
|
|
|
|
|
/*
|
|
|
|
Template member function for ensuring that there is an rows log
|
|
|
|
event of the apropriate type before proceeding.
|
|
|
|
|
|
|
|
PRE CONDITION:
|
|
|
|
- Events of type 'RowEventT' have the type code 'type_code'.
|
|
|
|
|
|
|
|
POST CONDITION:
|
|
|
|
If a non-NULL pointer is returned, the pending event for thread 'thd' will
|
|
|
|
be an event of type 'RowEventT' (which have the type code 'type_code')
|
|
|
|
will either empty or have enough space to hold 'needed' bytes. In
|
|
|
|
addition, the columns bitmap will be correct for the row, meaning that
|
|
|
|
the pending event will be flushed if the columns in the event differ from
|
|
|
|
the columns suppled to the function.
|
|
|
|
|
|
|
|
RETURNS
|
|
|
|
If no error, a non-NULL pending event (either one which already existed or
|
|
|
|
the newly created one).
|
|
|
|
If error, NULL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <class RowsEventT> Rows_log_event*
|
|
|
|
THD::binlog_prepare_pending_rows_event(TABLE* table, uint32 serv_id,
|
|
|
|
MY_BITMAP const* cols,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t colcnt,
|
|
|
|
size_t needed,
|
2006-01-09 15:59:39 +01:00
|
|
|
bool is_transactional,
|
|
|
|
RowsEventT *hint __attribute__((unused)))
|
2005-12-22 06:39:02 +01:00
|
|
|
{
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_ENTER("binlog_prepare_pending_rows_event");
|
2005-12-22 06:39:02 +01:00
|
|
|
/* Pre-conditions */
|
2006-03-09 03:56:14 +01:00
|
|
|
DBUG_ASSERT(table->s->table_map_id != ~0UL);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
/* Fetch the type code for the RowsEventT template parameter */
|
|
|
|
int const type_code= RowsEventT::TYPE_CODE;
|
|
|
|
|
|
|
|
/*
|
|
|
|
There is no good place to set up the transactional data, so we
|
|
|
|
have to do it here.
|
|
|
|
*/
|
|
|
|
if (binlog_setup_trx_data())
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(NULL);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
Rows_log_event* pending= binlog_get_pending_rows_event();
|
|
|
|
|
|
|
|
if (unlikely(pending && !pending->is_valid()))
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(NULL);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Check if the current event is non-NULL and a write-rows
|
|
|
|
event. Also check if the table provided is mapped: if it is not,
|
|
|
|
then we have switched to writing to a new table.
|
|
|
|
If there is no pending event, we need to create one. If there is a pending
|
|
|
|
event, but it's not about the same table id, or not of the same type
|
|
|
|
(between Write, Update and Delete), or not the same affected columns, or
|
|
|
|
going to be too big, flush this event to disk and create a new pending
|
|
|
|
event.
|
|
|
|
*/
|
|
|
|
if (!pending ||
|
|
|
|
pending->server_id != serv_id ||
|
|
|
|
pending->get_table_id() != table->s->table_map_id ||
|
|
|
|
pending->get_type_code() != type_code ||
|
|
|
|
pending->get_data_size() + needed > opt_binlog_rows_event_max_size ||
|
|
|
|
pending->get_width() != colcnt ||
|
|
|
|
!bitmap_cmp(pending->get_cols(), cols))
|
|
|
|
{
|
|
|
|
/* Create a new RowsEventT... */
|
|
|
|
Rows_log_event* const
|
|
|
|
ev= new RowsEventT(this, table, table->s->table_map_id, cols,
|
|
|
|
is_transactional);
|
|
|
|
if (unlikely(!ev))
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(NULL);
|
2005-12-22 06:39:02 +01:00
|
|
|
ev->server_id= serv_id; // I don't like this, it's too easy to forget.
|
|
|
|
/*
|
|
|
|
flush the pending event and replace it with the newly created
|
|
|
|
event...
|
|
|
|
*/
|
|
|
|
if (unlikely(mysql_bin_log.flush_and_set_pending_rows_event(this, ev)))
|
|
|
|
{
|
|
|
|
delete ev;
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(NULL);
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(ev); /* This is the new pending event */
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
2006-02-16 08:30:53 +01:00
|
|
|
DBUG_RETURN(pending); /* This is the current pending event */
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
2006-02-02 15:22:31 +01:00
|
|
|
#ifdef HAVE_EXPLICIT_TEMPLATE_INSTANTIATION
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
2006-02-16 08:30:53 +01:00
|
|
|
Instantiate the versions we need, we have -fno-implicit-template as
|
2005-12-22 06:39:02 +01:00
|
|
|
compiling option.
|
|
|
|
*/
|
|
|
|
template Rows_log_event*
|
2006-01-09 15:59:39 +01:00
|
|
|
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t, size_t, bool,
|
2006-01-09 15:59:39 +01:00
|
|
|
Write_rows_log_event*);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
template Rows_log_event*
|
2006-01-09 15:59:39 +01:00
|
|
|
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t colcnt, size_t, bool,
|
2006-01-09 15:59:39 +01:00
|
|
|
Delete_rows_log_event *);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
template Rows_log_event*
|
2006-01-09 15:59:39 +01:00
|
|
|
THD::binlog_prepare_pending_rows_event(TABLE*, uint32, MY_BITMAP const*,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t colcnt, size_t, bool,
|
2006-01-09 15:59:39 +01:00
|
|
|
Update_rows_log_event *);
|
2006-02-02 15:22:31 +01:00
|
|
|
#endif
|
2007-01-29 00:47:35 +01:00
|
|
|
|
|
|
|
#ifdef NOT_USED
|
2005-12-22 06:39:02 +01:00
|
|
|
static char const*
|
|
|
|
field_type_name(enum_field_types type)
|
|
|
|
{
|
2007-01-29 00:47:35 +01:00
|
|
|
switch (type) {
|
2005-12-22 06:39:02 +01:00
|
|
|
case MYSQL_TYPE_DECIMAL:
|
|
|
|
return "MYSQL_TYPE_DECIMAL";
|
|
|
|
case MYSQL_TYPE_TINY:
|
|
|
|
return "MYSQL_TYPE_TINY";
|
|
|
|
case MYSQL_TYPE_SHORT:
|
|
|
|
return "MYSQL_TYPE_SHORT";
|
|
|
|
case MYSQL_TYPE_LONG:
|
|
|
|
return "MYSQL_TYPE_LONG";
|
|
|
|
case MYSQL_TYPE_FLOAT:
|
|
|
|
return "MYSQL_TYPE_FLOAT";
|
|
|
|
case MYSQL_TYPE_DOUBLE:
|
|
|
|
return "MYSQL_TYPE_DOUBLE";
|
|
|
|
case MYSQL_TYPE_NULL:
|
|
|
|
return "MYSQL_TYPE_NULL";
|
|
|
|
case MYSQL_TYPE_TIMESTAMP:
|
|
|
|
return "MYSQL_TYPE_TIMESTAMP";
|
|
|
|
case MYSQL_TYPE_LONGLONG:
|
|
|
|
return "MYSQL_TYPE_LONGLONG";
|
|
|
|
case MYSQL_TYPE_INT24:
|
|
|
|
return "MYSQL_TYPE_INT24";
|
|
|
|
case MYSQL_TYPE_DATE:
|
|
|
|
return "MYSQL_TYPE_DATE";
|
|
|
|
case MYSQL_TYPE_TIME:
|
|
|
|
return "MYSQL_TYPE_TIME";
|
|
|
|
case MYSQL_TYPE_DATETIME:
|
|
|
|
return "MYSQL_TYPE_DATETIME";
|
|
|
|
case MYSQL_TYPE_YEAR:
|
|
|
|
return "MYSQL_TYPE_YEAR";
|
|
|
|
case MYSQL_TYPE_NEWDATE:
|
|
|
|
return "MYSQL_TYPE_NEWDATE";
|
|
|
|
case MYSQL_TYPE_VARCHAR:
|
|
|
|
return "MYSQL_TYPE_VARCHAR";
|
|
|
|
case MYSQL_TYPE_BIT:
|
|
|
|
return "MYSQL_TYPE_BIT";
|
|
|
|
case MYSQL_TYPE_NEWDECIMAL:
|
|
|
|
return "MYSQL_TYPE_NEWDECIMAL";
|
|
|
|
case MYSQL_TYPE_ENUM:
|
|
|
|
return "MYSQL_TYPE_ENUM";
|
|
|
|
case MYSQL_TYPE_SET:
|
|
|
|
return "MYSQL_TYPE_SET";
|
|
|
|
case MYSQL_TYPE_TINY_BLOB:
|
|
|
|
return "MYSQL_TYPE_TINY_BLOB";
|
|
|
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
|
|
return "MYSQL_TYPE_MEDIUM_BLOB";
|
|
|
|
case MYSQL_TYPE_LONG_BLOB:
|
|
|
|
return "MYSQL_TYPE_LONG_BLOB";
|
|
|
|
case MYSQL_TYPE_BLOB:
|
|
|
|
return "MYSQL_TYPE_BLOB";
|
|
|
|
case MYSQL_TYPE_VAR_STRING:
|
|
|
|
return "MYSQL_TYPE_VAR_STRING";
|
|
|
|
case MYSQL_TYPE_STRING:
|
|
|
|
return "MYSQL_TYPE_STRING";
|
|
|
|
case MYSQL_TYPE_GEOMETRY:
|
|
|
|
return "MYSQL_TYPE_GEOMETRY";
|
|
|
|
}
|
|
|
|
return "Unknown";
|
|
|
|
}
|
2007-01-29 00:47:35 +01:00
|
|
|
#endif
|
2005-12-22 06:39:02 +01:00
|
|
|
|
This changeset is largely a handler cleanup changeset (WL#3281), but includes fixes and cleanups that was found necessary while testing the handler changes
Changes that requires code changes in other code of other storage engines.
(Note that all changes are very straightforward and one should find all issues
by compiling a --debug build and fixing all compiler errors and all
asserts in field.cc while running the test suite),
- New optional handler function introduced: reset()
This is called after every DML statement to make it easy for a handler to
statement specific cleanups.
(The only case it's not called is if force the file to be closed)
- handler::extra(HA_EXTRA_RESET) is removed. Code that was there before
should be moved to handler::reset()
- table->read_set contains a bitmap over all columns that are needed
in the query. read_row() and similar functions only needs to read these
columns
- table->write_set contains a bitmap over all columns that will be updated
in the query. write_row() and update_row() only needs to update these
columns.
The above bitmaps should now be up to date in all context
(including ALTER TABLE, filesort()).
The handler is informed of any changes to the bitmap after
fix_fields() by calling the virtual function
handler::column_bitmaps_signal(). If the handler does caching of
these bitmaps (instead of using table->read_set, table->write_set),
it should redo the caching in this code. as the signal() may be sent
several times, it's probably best to set a variable in the signal
and redo the caching on read_row() / write_row() if the variable was
set.
- Removed the read_set and write_set bitmap objects from the handler class
- Removed all column bit handling functions from the handler class.
(Now one instead uses the normal bitmap functions in my_bitmap.c instead
of handler dedicated bitmap functions)
- field->query_id is removed. One should instead instead check
table->read_set and table->write_set if a field is used in the query.
- handler::extra(HA_EXTRA_RETRIVE_ALL_COLS) and
handler::extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) are removed. One should now
instead use table->read_set to check for which columns to retrieve.
- If a handler needs to call Field->val() or Field->store() on columns
that are not used in the query, one should install a temporary
all-columns-used map while doing so. For this, we provide the following
functions:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
field->val();
dbug_tmp_restore_column_map(table->read_set, old_map);
and similar for the write map:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
field->val();
dbug_tmp_restore_column_map(table->write_set, old_map);
If this is not done, you will sooner or later hit a DBUG_ASSERT
in the field store() / val() functions.
(For not DBUG binaries, the dbug_tmp_restore_column_map() and
dbug_tmp_restore_column_map() are inline dummy functions and should
be optimized away be the compiler).
- If one needs to temporary set the column map for all binaries (and not
just to avoid the DBUG_ASSERT() in the Field::store() / Field::val()
methods) one should use the functions tmp_use_all_columns() and
tmp_restore_column_map() instead of the above dbug_ variants.
- All 'status' fields in the handler base class (like records,
data_file_length etc) are now stored in a 'stats' struct. This makes
it easier to know what status variables are provided by the base
handler. This requires some trivial variable names in the extra()
function.
- New virtual function handler::records(). This is called to optimize
COUNT(*) if (handler::table_flags() & HA_HAS_RECORDS()) is true.
(stats.records is not supposed to be an exact value. It's only has to
be 'reasonable enough' for the optimizer to be able to choose a good
optimization path).
- Non virtual handler::init() function added for caching of virtual
constants from engine.
- Removed has_transactions() virtual method. Now one should instead return
HA_NO_TRANSACTIONS in table_flags() if the table handler DOES NOT support
transactions.
- The 'xxxx_create_handler()' function now has a MEM_ROOT_root argument
that is to be used with 'new handler_name()' to allocate the handler
in the right area. The xxxx_create_handler() function is also
responsible for any initialization of the object before returning.
For example, one should change:
static handler *myisam_create_handler(TABLE_SHARE *table)
{
return new ha_myisam(table);
}
->
static handler *myisam_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) ha_myisam(table);
}
- New optional virtual function: use_hidden_primary_key().
This is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
but we don't have a primary key. This allows the handler to take precisions
in remembering any hidden primary key to able to update/delete any
found row. The default handler marks all columns to be read.
- handler::table_flags() now returns a ulonglong (to allow for more flags).
- New/changed table_flags()
- HA_HAS_RECORDS Set if ::records() is supported
- HA_NO_TRANSACTIONS Set if engine doesn't support transactions
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE
Set if we should mark all primary key columns for
read when reading rows as part of a DELETE
statement. If there is no primary key,
all columns are marked for read.
- HA_PARTIAL_COLUMN_READ Set if engine will not read all columns in some
cases (based on table->read_set)
- HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
Renamed to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
- HA_DUPP_POS Renamed to HA_DUPLICATE_POS
- HA_REQUIRES_KEY_COLUMNS_FOR_DELETE
Set this if we should mark ALL key columns for
read when when reading rows as part of a DELETE
statement. In case of an update we will mark
all keys for read for which key part changed
value.
- HA_STATS_RECORDS_IS_EXACT
Set this if stats.records is exact.
(This saves us some extra records() calls
when optimizing COUNT(*))
- Removed table_flags()
- HA_NOT_EXACT_COUNT Now one should instead use HA_HAS_RECORDS if
handler::records() gives an exact count() and
HA_STATS_RECORDS_IS_EXACT if stats.records is exact.
- HA_READ_RND_SAME Removed (no one supported this one)
- Removed not needed functions ha_retrieve_all_cols() and ha_retrieve_all_pk()
- Renamed handler::dupp_pos to handler::dup_pos
- Removed not used variable handler::sortkey
Upper level handler changes:
- ha_reset() now does some overall checks and calls ::reset()
- ha_table_flags() added. This is a cached version of table_flags(). The
cache is updated on engine creation time and updated on open.
MySQL level changes (not obvious from the above):
- DBUG_ASSERT() added to check that column usage matches what is set
in the column usage bit maps. (This found a LOT of bugs in current
column marking code).
- In 5.1 before, all used columns was marked in read_set and only updated
columns was marked in write_set. Now we only mark columns for which we
need a value in read_set.
- Column bitmaps are created in open_binary_frm() and open_table_from_share().
(Before this was in table.cc)
- handler::table_flags() calls are replaced with handler::ha_table_flags()
- For calling field->val() you must have the corresponding bit set in
table->read_set. For calling field->store() you must have the
corresponding bit set in table->write_set. (There are asserts in
all store()/val() functions to catch wrong usage)
- thd->set_query_id is renamed to thd->mark_used_columns and instead
of setting this to an integer value, this has now the values:
MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE
Changed also all variables named 'set_query_id' to mark_used_columns.
- In filesort() we now inform the handler of exactly which columns are needed
doing the sort and choosing the rows.
- The TABLE_SHARE object has a 'all_set' column bitmap one can use
when one needs a column bitmap with all columns set.
(This is used for table->use_all_columns() and other places)
- The TABLE object has 3 column bitmaps:
- def_read_set Default bitmap for columns to be read
- def_write_set Default bitmap for columns to be written
- tmp_set Can be used as a temporary bitmap when needed.
The table object has also two pointer to bitmaps read_set and write_set
that the handler should use to find out which columns are used in which way.
- count() optimization now calls handler::records() instead of using
handler->stats.records (if (table_flags() & HA_HAS_RECORDS) is true).
- Added extra argument to Item::walk() to indicate if we should also
traverse sub queries.
- Added TABLE parameter to cp_buffer_from_ref()
- Don't close tables created with CREATE ... SELECT but keep them in
the table cache. (Faster usage of newly created tables).
New interfaces:
- table->clear_column_bitmaps() to initialize the bitmaps for tables
at start of new statements.
- table->column_bitmaps_set() to set up new column bitmaps and signal
the handler about this.
- table->column_bitmaps_set_no_signal() for some few cases where we need
to setup new column bitmaps but don't signal the handler (as the handler
has already been signaled about these before). Used for the momement
only in opt_range.cc when doing ROR scans.
- table->use_all_columns() to install a bitmap where all columns are marked
as use in the read and the write set.
- table->default_column_bitmaps() to install the normal read and write
column bitmaps, but not signaling the handler about this.
This is mainly used when creating TABLE instances.
- table->mark_columns_needed_for_delete(),
table->mark_columns_needed_for_delete() and
table->mark_columns_needed_for_insert() to allow us to put additional
columns in column usage maps if handler so requires.
(The handler indicates what it neads in handler->table_flags())
- table->prepare_for_position() to allow us to tell handler that it
needs to read primary key parts to be able to store them in
future table->position() calls.
(This replaces the table->file->ha_retrieve_all_pk function)
- table->mark_auto_increment_column() to tell handler are going to update
columns part of any auto_increment key.
- table->mark_columns_used_by_index() to mark all columns that is part of
an index. It will also send extra(HA_EXTRA_KEYREAD) to handler to allow
it to quickly know that it only needs to read colums that are part
of the key. (The handler can also use the column map for detecting this,
but simpler/faster handler can just monitor the extra() call).
- table->mark_columns_used_by_index_no_reset() to in addition to other columns,
also mark all columns that is used by the given key.
- table->restore_column_maps_after_mark_index() to restore to default
column maps after a call to table->mark_columns_used_by_index().
- New item function register_field_in_read_map(), for marking used columns
in table->read_map. Used by filesort() to mark all used columns
- Maintain in TABLE->merge_keys set of all keys that are used in query.
(Simplices some optimization loops)
- Maintain Field->part_of_key_not_clustered which is like Field->part_of_key
but the field in the clustered key is not assumed to be part of all index.
(used in opt_range.cc for faster loops)
- dbug_tmp_use_all_columns(), dbug_tmp_restore_column_map()
tmp_use_all_columns() and tmp_restore_column_map() functions to temporally
mark all columns as usable. The 'dbug_' version is primarily intended
inside a handler when it wants to just call Field:store() & Field::val()
functions, but don't need the column maps set for any other usage.
(ie:: bitmap_is_set() is never called)
- We can't use compare_records() to skip updates for handlers that returns
a partial column set and the read_set doesn't cover all columns in the
write set. The reason for this is that if we have a column marked only for
write we can't in the MySQL level know if the value changed or not.
The reason this worked before was that MySQL marked all to be written
columns as also to be read. The new 'optimal' bitmaps exposed this 'hidden
bug'.
- open_table_from_share() does not anymore setup temporary MEM_ROOT
object as a thread specific variable for the handler. Instead we
send the to-be-used MEMROOT to get_new_handler().
(Simpler, faster code)
Bugs fixed:
- Column marking was not done correctly in a lot of cases.
(ALTER TABLE, when using triggers, auto_increment fields etc)
(Could potentially result in wrong values inserted in table handlers
relying on that the old column maps or field->set_query_id was correct)
Especially when it comes to triggers, there may be cases where the
old code would cause lost/wrong values for NDB and/or InnoDB tables.
- Split thd->options flag OPTION_STATUS_NO_TRANS_UPDATE to two flags:
OPTION_STATUS_NO_TRANS_UPDATE and OPTION_KEEP_LOG.
This allowed me to remove some wrong warnings about:
"Some non-transactional changed tables couldn't be rolled back"
- Fixed handling of INSERT .. SELECT and CREATE ... SELECT that wrongly reset
(thd->options & OPTION_STATUS_NO_TRANS_UPDATE) which caused us to loose
some warnings about
"Some non-transactional changed tables couldn't be rolled back")
- Fixed use of uninitialized memory in ha_ndbcluster.cc::delete_table()
which could cause delete_table to report random failures.
- Fixed core dumps for some tests when running with --debug
- Added missing FN_LIBCHAR in mysql_rm_tmp_tables()
(This has probably caused us to not properly remove temporary files after
crash)
- slow_logs was not properly initialized, which could maybe cause
extra/lost entries in slow log.
- If we get an duplicate row on insert, change column map to read and
write all columns while retrying the operation. This is required by
the definition of REPLACE and also ensures that fields that are only
part of UPDATE are properly handled. This fixed a bug in NDB and
REPLACE where REPLACE wrongly copied some column values from the replaced
row.
- For table handler that doesn't support NULL in keys, we would give an error
when creating a primary key with NULL fields, even after the fields has been
automaticly converted to NOT NULL.
- Creating a primary key on a SPATIAL key, would fail if field was not
declared as NOT NULL.
Cleanups:
- Removed not used condition argument to setup_tables
- Removed not needed item function reset_query_id_processor().
- Field->add_index is removed. Now this is instead maintained in
(field->flags & FIELD_IN_ADD_INDEX)
- Field->fieldnr is removed (use field->field_index instead)
- New argument to filesort() to indicate that it should return a set of
row pointers (not used columns). This allowed me to remove some references
to sql_command in filesort and should also enable us to return column
results in some cases where we couldn't before.
- Changed column bitmap handling in opt_range.cc to be aligned with TABLE
bitmap, which allowed me to use bitmap functions instead of looping over
all fields to create some needed bitmaps. (Faster and smaller code)
- Broke up found too long lines
- Moved some variable declaration at start of function for better code
readability.
- Removed some not used arguments from functions.
(setup_fields(), mysql_prepare_insert_check_table())
- setup_fields() now takes an enum instead of an int for marking columns
usage.
- For internal temporary tables, use handler::write_row(),
handler::delete_row() and handler::update_row() instead of
handler::ha_xxxx() for faster execution.
- Changed some constants to enum's and define's.
- Using separate column read and write sets allows for easier checking
of timestamp field was set by statement.
- Remove calls to free_io_cache() as this is now done automaticly in ha_reset()
- Don't build table->normalized_path as this is now identical to table->path
(after bar's fixes to convert filenames)
- Fixed some missed DBUG_PRINT(.."%lx") to use "0x%lx" to make it easier to
do comparision with the 'convert-dbug-for-diff' tool.
Things left to do in 5.1:
- We wrongly log failed CREATE TABLE ... SELECT in some cases when using
row based logging (as shown by testcase binlog_row_mix_innodb_myisam.result)
Mats has promised to look into this.
- Test that my fix for CREATE TABLE ... SELECT is indeed correct.
(I added several test cases for this, but in this case it's better that
someone else also tests this throughly).
Lars has promosed to do this.
2006-06-04 17:52:22 +02:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
namespace {
|
|
|
|
/**
|
|
|
|
Class to handle temporary allocation of memory for row data.
|
|
|
|
|
|
|
|
The responsibilities of the class is to provide memory for
|
|
|
|
packing one or two rows of packed data (depending on what
|
|
|
|
constructor is called).
|
|
|
|
|
|
|
|
In order to make the allocation more efficient for "simple" rows,
|
|
|
|
i.e., rows that do not contain any blobs, a pointer to the
|
|
|
|
allocated memory is of memory is stored in the table structure
|
|
|
|
for simple rows. If memory for a table containing a blob field
|
|
|
|
is requested, only memory for that is allocated, and subsequently
|
|
|
|
released when the object is destroyed.
|
|
|
|
|
|
|
|
*/
|
|
|
|
class Row_data_memory {
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
Build an object to keep track of a block-local piece of memory
|
|
|
|
for storing a row of data.
|
|
|
|
|
|
|
|
@param table
|
|
|
|
Table where the pre-allocated memory is stored.
|
|
|
|
|
|
|
|
@param length
|
|
|
|
Length of data that is needed, if the record contain blobs.
|
|
|
|
*/
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
Row_data_memory(TABLE *table, size_t const len1)
|
2006-11-15 16:49:03 +01:00
|
|
|
: m_memory(0)
|
|
|
|
{
|
|
|
|
#ifndef DBUG_OFF
|
2007-02-23 21:48:15 +01:00
|
|
|
m_alloc_checked= FALSE;
|
2006-11-15 16:49:03 +01:00
|
|
|
#endif
|
|
|
|
allocate_memory(table, len1);
|
|
|
|
m_ptr[0]= has_memory() ? m_memory : 0;
|
|
|
|
m_ptr[1]= 0;
|
|
|
|
}
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
Row_data_memory(TABLE *table, size_t const len1, size_t const len2)
|
2006-11-15 16:49:03 +01:00
|
|
|
: m_memory(0)
|
|
|
|
{
|
|
|
|
#ifndef DBUG_OFF
|
2007-02-23 21:48:15 +01:00
|
|
|
m_alloc_checked= FALSE;
|
2006-11-15 16:49:03 +01:00
|
|
|
#endif
|
|
|
|
allocate_memory(table, len1 + len2);
|
|
|
|
m_ptr[0]= has_memory() ? m_memory : 0;
|
|
|
|
m_ptr[1]= has_memory() ? m_memory + len1 : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
~Row_data_memory()
|
|
|
|
{
|
|
|
|
if (m_memory != 0 && m_release_memory_on_destruction)
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
my_free((uchar*) m_memory, MYF(MY_WME));
|
2006-11-15 16:49:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
Is there memory allocated?
|
|
|
|
|
|
|
|
@retval true There is memory allocated
|
|
|
|
@retval false Memory allocation failed
|
|
|
|
*/
|
|
|
|
bool has_memory() const {
|
|
|
|
#ifndef DBUG_OFF
|
2007-02-23 21:48:15 +01:00
|
|
|
m_alloc_checked= TRUE;
|
2006-11-15 16:49:03 +01:00
|
|
|
#endif
|
|
|
|
return m_memory != 0;
|
|
|
|
}
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *slot(uint s)
|
2006-11-15 16:49:03 +01:00
|
|
|
{
|
2006-11-27 00:47:38 +01:00
|
|
|
DBUG_ASSERT(s < sizeof(m_ptr)/sizeof(*m_ptr));
|
2006-11-15 16:49:03 +01:00
|
|
|
DBUG_ASSERT(m_ptr[s] != 0);
|
2007-02-23 21:48:15 +01:00
|
|
|
DBUG_ASSERT(m_alloc_checked == TRUE);
|
2006-11-15 16:49:03 +01:00
|
|
|
return m_ptr[s];
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
void allocate_memory(TABLE *const table, size_t const total_length)
|
2006-11-15 16:49:03 +01:00
|
|
|
{
|
|
|
|
if (table->s->blob_fields == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The maximum length of a packed record is less than this
|
|
|
|
length. We use this value instead of the supplied length
|
|
|
|
when allocating memory for records, since we don't know how
|
|
|
|
the memory will be used in future allocations.
|
|
|
|
|
|
|
|
Since table->s->reclength is for unpacked records, we have
|
|
|
|
to add two bytes for each field, which can potentially be
|
|
|
|
added to hold the length of a packed field.
|
|
|
|
*/
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const maxlen= table->s->reclength + 2 * table->s->fields;
|
2006-11-15 16:49:03 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Allocate memory for two records if memory hasn't been
|
|
|
|
allocated. We allocate memory for two records so that it can
|
|
|
|
be used when processing update rows as well.
|
|
|
|
*/
|
|
|
|
if (table->write_row_record == 0)
|
|
|
|
table->write_row_record=
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
(uchar *) alloc_root(&table->mem_root, 2 * maxlen);
|
2006-11-15 16:49:03 +01:00
|
|
|
m_memory= table->write_row_record;
|
2007-02-23 21:48:15 +01:00
|
|
|
m_release_memory_on_destruction= FALSE;
|
2006-11-15 16:49:03 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
m_memory= (uchar *) my_malloc(total_length, MYF(MY_WME));
|
2007-02-23 21:48:15 +01:00
|
|
|
m_release_memory_on_destruction= TRUE;
|
2006-11-15 16:49:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef DBUG_OFF
|
|
|
|
mutable bool m_alloc_checked;
|
|
|
|
#endif
|
|
|
|
bool m_release_memory_on_destruction;
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *m_memory;
|
|
|
|
uchar *m_ptr[2];
|
2006-11-15 16:49:03 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
int THD::binlog_write_row(TABLE* table, bool is_trans,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
MY_BITMAP const* cols, size_t colcnt,
|
|
|
|
uchar const *record)
|
2005-12-22 06:39:02 +01:00
|
|
|
{
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
|
2005-12-22 06:39:02 +01:00
|
|
|
|
This changeset is largely a handler cleanup changeset (WL#3281), but includes fixes and cleanups that was found necessary while testing the handler changes
Changes that requires code changes in other code of other storage engines.
(Note that all changes are very straightforward and one should find all issues
by compiling a --debug build and fixing all compiler errors and all
asserts in field.cc while running the test suite),
- New optional handler function introduced: reset()
This is called after every DML statement to make it easy for a handler to
statement specific cleanups.
(The only case it's not called is if force the file to be closed)
- handler::extra(HA_EXTRA_RESET) is removed. Code that was there before
should be moved to handler::reset()
- table->read_set contains a bitmap over all columns that are needed
in the query. read_row() and similar functions only needs to read these
columns
- table->write_set contains a bitmap over all columns that will be updated
in the query. write_row() and update_row() only needs to update these
columns.
The above bitmaps should now be up to date in all context
(including ALTER TABLE, filesort()).
The handler is informed of any changes to the bitmap after
fix_fields() by calling the virtual function
handler::column_bitmaps_signal(). If the handler does caching of
these bitmaps (instead of using table->read_set, table->write_set),
it should redo the caching in this code. as the signal() may be sent
several times, it's probably best to set a variable in the signal
and redo the caching on read_row() / write_row() if the variable was
set.
- Removed the read_set and write_set bitmap objects from the handler class
- Removed all column bit handling functions from the handler class.
(Now one instead uses the normal bitmap functions in my_bitmap.c instead
of handler dedicated bitmap functions)
- field->query_id is removed. One should instead instead check
table->read_set and table->write_set if a field is used in the query.
- handler::extra(HA_EXTRA_RETRIVE_ALL_COLS) and
handler::extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY) are removed. One should now
instead use table->read_set to check for which columns to retrieve.
- If a handler needs to call Field->val() or Field->store() on columns
that are not used in the query, one should install a temporary
all-columns-used map while doing so. For this, we provide the following
functions:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
field->val();
dbug_tmp_restore_column_map(table->read_set, old_map);
and similar for the write map:
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->write_set);
field->val();
dbug_tmp_restore_column_map(table->write_set, old_map);
If this is not done, you will sooner or later hit a DBUG_ASSERT
in the field store() / val() functions.
(For not DBUG binaries, the dbug_tmp_restore_column_map() and
dbug_tmp_restore_column_map() are inline dummy functions and should
be optimized away be the compiler).
- If one needs to temporary set the column map for all binaries (and not
just to avoid the DBUG_ASSERT() in the Field::store() / Field::val()
methods) one should use the functions tmp_use_all_columns() and
tmp_restore_column_map() instead of the above dbug_ variants.
- All 'status' fields in the handler base class (like records,
data_file_length etc) are now stored in a 'stats' struct. This makes
it easier to know what status variables are provided by the base
handler. This requires some trivial variable names in the extra()
function.
- New virtual function handler::records(). This is called to optimize
COUNT(*) if (handler::table_flags() & HA_HAS_RECORDS()) is true.
(stats.records is not supposed to be an exact value. It's only has to
be 'reasonable enough' for the optimizer to be able to choose a good
optimization path).
- Non virtual handler::init() function added for caching of virtual
constants from engine.
- Removed has_transactions() virtual method. Now one should instead return
HA_NO_TRANSACTIONS in table_flags() if the table handler DOES NOT support
transactions.
- The 'xxxx_create_handler()' function now has a MEM_ROOT_root argument
that is to be used with 'new handler_name()' to allocate the handler
in the right area. The xxxx_create_handler() function is also
responsible for any initialization of the object before returning.
For example, one should change:
static handler *myisam_create_handler(TABLE_SHARE *table)
{
return new ha_myisam(table);
}
->
static handler *myisam_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root)
{
return new (mem_root) ha_myisam(table);
}
- New optional virtual function: use_hidden_primary_key().
This is called in case of an update/delete when
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
but we don't have a primary key. This allows the handler to take precisions
in remembering any hidden primary key to able to update/delete any
found row. The default handler marks all columns to be read.
- handler::table_flags() now returns a ulonglong (to allow for more flags).
- New/changed table_flags()
- HA_HAS_RECORDS Set if ::records() is supported
- HA_NO_TRANSACTIONS Set if engine doesn't support transactions
- HA_PRIMARY_KEY_REQUIRED_FOR_DELETE
Set if we should mark all primary key columns for
read when reading rows as part of a DELETE
statement. If there is no primary key,
all columns are marked for read.
- HA_PARTIAL_COLUMN_READ Set if engine will not read all columns in some
cases (based on table->read_set)
- HA_PRIMARY_KEY_ALLOW_RANDOM_ACCESS
Renamed to HA_PRIMARY_KEY_REQUIRED_FOR_POSITION.
- HA_DUPP_POS Renamed to HA_DUPLICATE_POS
- HA_REQUIRES_KEY_COLUMNS_FOR_DELETE
Set this if we should mark ALL key columns for
read when when reading rows as part of a DELETE
statement. In case of an update we will mark
all keys for read for which key part changed
value.
- HA_STATS_RECORDS_IS_EXACT
Set this if stats.records is exact.
(This saves us some extra records() calls
when optimizing COUNT(*))
- Removed table_flags()
- HA_NOT_EXACT_COUNT Now one should instead use HA_HAS_RECORDS if
handler::records() gives an exact count() and
HA_STATS_RECORDS_IS_EXACT if stats.records is exact.
- HA_READ_RND_SAME Removed (no one supported this one)
- Removed not needed functions ha_retrieve_all_cols() and ha_retrieve_all_pk()
- Renamed handler::dupp_pos to handler::dup_pos
- Removed not used variable handler::sortkey
Upper level handler changes:
- ha_reset() now does some overall checks and calls ::reset()
- ha_table_flags() added. This is a cached version of table_flags(). The
cache is updated on engine creation time and updated on open.
MySQL level changes (not obvious from the above):
- DBUG_ASSERT() added to check that column usage matches what is set
in the column usage bit maps. (This found a LOT of bugs in current
column marking code).
- In 5.1 before, all used columns was marked in read_set and only updated
columns was marked in write_set. Now we only mark columns for which we
need a value in read_set.
- Column bitmaps are created in open_binary_frm() and open_table_from_share().
(Before this was in table.cc)
- handler::table_flags() calls are replaced with handler::ha_table_flags()
- For calling field->val() you must have the corresponding bit set in
table->read_set. For calling field->store() you must have the
corresponding bit set in table->write_set. (There are asserts in
all store()/val() functions to catch wrong usage)
- thd->set_query_id is renamed to thd->mark_used_columns and instead
of setting this to an integer value, this has now the values:
MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE
Changed also all variables named 'set_query_id' to mark_used_columns.
- In filesort() we now inform the handler of exactly which columns are needed
doing the sort and choosing the rows.
- The TABLE_SHARE object has a 'all_set' column bitmap one can use
when one needs a column bitmap with all columns set.
(This is used for table->use_all_columns() and other places)
- The TABLE object has 3 column bitmaps:
- def_read_set Default bitmap for columns to be read
- def_write_set Default bitmap for columns to be written
- tmp_set Can be used as a temporary bitmap when needed.
The table object has also two pointer to bitmaps read_set and write_set
that the handler should use to find out which columns are used in which way.
- count() optimization now calls handler::records() instead of using
handler->stats.records (if (table_flags() & HA_HAS_RECORDS) is true).
- Added extra argument to Item::walk() to indicate if we should also
traverse sub queries.
- Added TABLE parameter to cp_buffer_from_ref()
- Don't close tables created with CREATE ... SELECT but keep them in
the table cache. (Faster usage of newly created tables).
New interfaces:
- table->clear_column_bitmaps() to initialize the bitmaps for tables
at start of new statements.
- table->column_bitmaps_set() to set up new column bitmaps and signal
the handler about this.
- table->column_bitmaps_set_no_signal() for some few cases where we need
to setup new column bitmaps but don't signal the handler (as the handler
has already been signaled about these before). Used for the momement
only in opt_range.cc when doing ROR scans.
- table->use_all_columns() to install a bitmap where all columns are marked
as use in the read and the write set.
- table->default_column_bitmaps() to install the normal read and write
column bitmaps, but not signaling the handler about this.
This is mainly used when creating TABLE instances.
- table->mark_columns_needed_for_delete(),
table->mark_columns_needed_for_delete() and
table->mark_columns_needed_for_insert() to allow us to put additional
columns in column usage maps if handler so requires.
(The handler indicates what it neads in handler->table_flags())
- table->prepare_for_position() to allow us to tell handler that it
needs to read primary key parts to be able to store them in
future table->position() calls.
(This replaces the table->file->ha_retrieve_all_pk function)
- table->mark_auto_increment_column() to tell handler are going to update
columns part of any auto_increment key.
- table->mark_columns_used_by_index() to mark all columns that is part of
an index. It will also send extra(HA_EXTRA_KEYREAD) to handler to allow
it to quickly know that it only needs to read colums that are part
of the key. (The handler can also use the column map for detecting this,
but simpler/faster handler can just monitor the extra() call).
- table->mark_columns_used_by_index_no_reset() to in addition to other columns,
also mark all columns that is used by the given key.
- table->restore_column_maps_after_mark_index() to restore to default
column maps after a call to table->mark_columns_used_by_index().
- New item function register_field_in_read_map(), for marking used columns
in table->read_map. Used by filesort() to mark all used columns
- Maintain in TABLE->merge_keys set of all keys that are used in query.
(Simplices some optimization loops)
- Maintain Field->part_of_key_not_clustered which is like Field->part_of_key
but the field in the clustered key is not assumed to be part of all index.
(used in opt_range.cc for faster loops)
- dbug_tmp_use_all_columns(), dbug_tmp_restore_column_map()
tmp_use_all_columns() and tmp_restore_column_map() functions to temporally
mark all columns as usable. The 'dbug_' version is primarily intended
inside a handler when it wants to just call Field:store() & Field::val()
functions, but don't need the column maps set for any other usage.
(ie:: bitmap_is_set() is never called)
- We can't use compare_records() to skip updates for handlers that returns
a partial column set and the read_set doesn't cover all columns in the
write set. The reason for this is that if we have a column marked only for
write we can't in the MySQL level know if the value changed or not.
The reason this worked before was that MySQL marked all to be written
columns as also to be read. The new 'optimal' bitmaps exposed this 'hidden
bug'.
- open_table_from_share() does not anymore setup temporary MEM_ROOT
object as a thread specific variable for the handler. Instead we
send the to-be-used MEMROOT to get_new_handler().
(Simpler, faster code)
Bugs fixed:
- Column marking was not done correctly in a lot of cases.
(ALTER TABLE, when using triggers, auto_increment fields etc)
(Could potentially result in wrong values inserted in table handlers
relying on that the old column maps or field->set_query_id was correct)
Especially when it comes to triggers, there may be cases where the
old code would cause lost/wrong values for NDB and/or InnoDB tables.
- Split thd->options flag OPTION_STATUS_NO_TRANS_UPDATE to two flags:
OPTION_STATUS_NO_TRANS_UPDATE and OPTION_KEEP_LOG.
This allowed me to remove some wrong warnings about:
"Some non-transactional changed tables couldn't be rolled back"
- Fixed handling of INSERT .. SELECT and CREATE ... SELECT that wrongly reset
(thd->options & OPTION_STATUS_NO_TRANS_UPDATE) which caused us to loose
some warnings about
"Some non-transactional changed tables couldn't be rolled back")
- Fixed use of uninitialized memory in ha_ndbcluster.cc::delete_table()
which could cause delete_table to report random failures.
- Fixed core dumps for some tests when running with --debug
- Added missing FN_LIBCHAR in mysql_rm_tmp_tables()
(This has probably caused us to not properly remove temporary files after
crash)
- slow_logs was not properly initialized, which could maybe cause
extra/lost entries in slow log.
- If we get an duplicate row on insert, change column map to read and
write all columns while retrying the operation. This is required by
the definition of REPLACE and also ensures that fields that are only
part of UPDATE are properly handled. This fixed a bug in NDB and
REPLACE where REPLACE wrongly copied some column values from the replaced
row.
- For table handler that doesn't support NULL in keys, we would give an error
when creating a primary key with NULL fields, even after the fields has been
automaticly converted to NOT NULL.
- Creating a primary key on a SPATIAL key, would fail if field was not
declared as NOT NULL.
Cleanups:
- Removed not used condition argument to setup_tables
- Removed not needed item function reset_query_id_processor().
- Field->add_index is removed. Now this is instead maintained in
(field->flags & FIELD_IN_ADD_INDEX)
- Field->fieldnr is removed (use field->field_index instead)
- New argument to filesort() to indicate that it should return a set of
row pointers (not used columns). This allowed me to remove some references
to sql_command in filesort and should also enable us to return column
results in some cases where we couldn't before.
- Changed column bitmap handling in opt_range.cc to be aligned with TABLE
bitmap, which allowed me to use bitmap functions instead of looping over
all fields to create some needed bitmaps. (Faster and smaller code)
- Broke up found too long lines
- Moved some variable declaration at start of function for better code
readability.
- Removed some not used arguments from functions.
(setup_fields(), mysql_prepare_insert_check_table())
- setup_fields() now takes an enum instead of an int for marking columns
usage.
- For internal temporary tables, use handler::write_row(),
handler::delete_row() and handler::update_row() instead of
handler::ha_xxxx() for faster execution.
- Changed some constants to enum's and define's.
- Using separate column read and write sets allows for easier checking
of timestamp field was set by statement.
- Remove calls to free_io_cache() as this is now done automaticly in ha_reset()
- Don't build table->normalized_path as this is now identical to table->path
(after bar's fixes to convert filenames)
- Fixed some missed DBUG_PRINT(.."%lx") to use "0x%lx" to make it easier to
do comparision with the 'convert-dbug-for-diff' tool.
Things left to do in 5.1:
- We wrongly log failed CREATE TABLE ... SELECT in some cases when using
row based logging (as shown by testcase binlog_row_mix_innodb_myisam.result)
Mats has promised to look into this.
- Test that my fix for CREATE TABLE ... SELECT is indeed correct.
(I added several test cases for this, but in this case it's better that
someone else also tests this throughly).
Lars has promosed to do this.
2006-06-04 17:52:22 +02:00
|
|
|
/*
|
|
|
|
Pack records into format for transfer. We are allocating more
|
|
|
|
memory than needed, but that doesn't matter.
|
2005-12-22 06:39:02 +01:00
|
|
|
*/
|
2006-11-15 16:49:03 +01:00
|
|
|
Row_data_memory memory(table, max_row_length(table, record));
|
|
|
|
if (!memory.has_memory())
|
|
|
|
return HA_ERR_OUT_OF_MEM;
|
2005-12-22 06:39:02 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *row_data= memory.slot(0);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const len= pack_row(table, cols, row_data, record);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
Rows_log_event* const ev=
|
|
|
|
binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
|
|
|
|
len, is_trans,
|
|
|
|
static_cast<Write_rows_log_event*>(0));
|
|
|
|
|
|
|
|
if (unlikely(ev == 0))
|
|
|
|
return HA_ERR_OUT_OF_MEM;
|
|
|
|
|
|
|
|
return ev->add_row_data(row_data, len);
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int THD::binlog_update_row(TABLE* table, bool is_trans,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
MY_BITMAP const* cols, size_t colcnt,
|
|
|
|
const uchar *before_record,
|
|
|
|
const uchar *after_record)
|
2005-12-22 06:39:02 +01:00
|
|
|
{
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
|
2005-12-22 06:39:02 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const before_maxlen = max_row_length(table, before_record);
|
|
|
|
size_t const after_maxlen = max_row_length(table, after_record);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
Row_data_memory row_data(table, before_maxlen, after_maxlen);
|
|
|
|
if (!row_data.has_memory())
|
|
|
|
return HA_ERR_OUT_OF_MEM;
|
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *before_row= row_data.slot(0);
|
|
|
|
uchar *after_row= row_data.slot(1);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const before_size= pack_row(table, cols, before_row,
|
2005-12-22 06:39:02 +01:00
|
|
|
before_record);
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const after_size= pack_row(table, cols, after_row,
|
2005-12-22 06:39:02 +01:00
|
|
|
after_record);
|
2006-11-21 13:57:52 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Don't print debug messages when running valgrind since they can
|
|
|
|
trigger false warnings.
|
|
|
|
*/
|
|
|
|
#ifndef HAVE_purify
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
DBUG_DUMP("before_record", before_record, table->s->reclength);
|
|
|
|
DBUG_DUMP("after_record", after_record, table->s->reclength);
|
|
|
|
DBUG_DUMP("before_row", before_row, before_size);
|
|
|
|
DBUG_DUMP("after_row", after_row, after_size);
|
2006-11-21 13:57:52 +01:00
|
|
|
#endif
|
2006-09-21 18:05:02 +02:00
|
|
|
|
2006-01-09 15:59:39 +01:00
|
|
|
Rows_log_event* const ev=
|
|
|
|
binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
|
|
|
|
before_size + after_size, is_trans,
|
|
|
|
static_cast<Update_rows_log_event*>(0));
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
if (unlikely(ev == 0))
|
|
|
|
return HA_ERR_OUT_OF_MEM;
|
|
|
|
|
|
|
|
return
|
2006-09-21 18:05:02 +02:00
|
|
|
ev->add_row_data(before_row, before_size) ||
|
2005-12-22 06:39:02 +01:00
|
|
|
ev->add_row_data(after_row, after_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int THD::binlog_delete_row(TABLE* table, bool is_trans,
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
MY_BITMAP const* cols, size_t colcnt,
|
|
|
|
uchar const *record)
|
2005-12-22 06:39:02 +01:00
|
|
|
{
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
DBUG_ASSERT(current_stmt_binlog_row_based && mysql_bin_log.is_open());
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Pack records into format for transfer. We are allocating more
|
|
|
|
memory than needed, but that doesn't matter.
|
|
|
|
*/
|
2006-11-15 16:49:03 +01:00
|
|
|
Row_data_memory memory(table, max_row_length(table, record));
|
|
|
|
if (unlikely(!memory.has_memory()))
|
2005-12-22 06:39:02 +01:00
|
|
|
return HA_ERR_OUT_OF_MEM;
|
2006-11-15 16:49:03 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
uchar *row_data= memory.slot(0);
|
2006-11-15 16:49:03 +01:00
|
|
|
|
WL#3817: Simplify string / memory area types and make things more consistent (first part)
The following type conversions was done:
- Changed byte to uchar
- Changed gptr to uchar*
- Change my_string to char *
- Change my_size_t to size_t
- Change size_s to size_t
Removed declaration of byte, gptr, my_string, my_size_t and size_s.
Following function parameter changes was done:
- All string functions in mysys/strings was changed to use size_t
instead of uint for string lengths.
- All read()/write() functions changed to use size_t (including vio).
- All protocoll functions changed to use size_t instead of uint
- Functions that used a pointer to a string length was changed to use size_t*
- Changed malloc(), free() and related functions from using gptr to use void *
as this requires fewer casts in the code and is more in line with how the
standard functions work.
- Added extra length argument to dirname_part() to return the length of the
created string.
- Changed (at least) following functions to take uchar* as argument:
- db_dump()
- my_net_write()
- net_write_command()
- net_store_data()
- DBUG_DUMP()
- decimal2bin() & bin2decimal()
- Changed my_compress() and my_uncompress() to use size_t. Changed one
argument to my_uncompress() from a pointer to a value as we only return
one value (makes function easier to use).
- Changed type of 'pack_data' argument to packfrm() to avoid casts.
- Changed in readfrm() and writefrom(), ha_discover and handler::discover()
the type for argument 'frmdata' to uchar** to avoid casts.
- Changed most Field functions to use uchar* instead of char* (reduced a lot of
casts).
- Changed field->val_xxx(xxx, new_ptr) to take const pointers.
Other changes:
- Removed a lot of not needed casts
- Added a few new cast required by other changes
- Added some cast to my_multi_malloc() arguments for safety (as string lengths
needs to be uint, not size_t).
- Fixed all calls to hash-get-key functions to use size_t*. (Needed to be done
explicitely as this conflict was often hided by casting the function to
hash_get_key).
- Changed some buffers to memory regions to uchar* to avoid casts.
- Changed some string lengths from uint to size_t.
- Changed field->ptr to be uchar* instead of char*. This allowed us to
get rid of a lot of casts.
- Some changes from true -> TRUE, false -> FALSE, unsigned char -> uchar
- Include zlib.h in some files as we needed declaration of crc32()
- Changed MY_FILE_ERROR to be (size_t) -1.
- Changed many variables to hold the result of my_read() / my_write() to be
size_t. This was needed to properly detect errors (which are
returned as (size_t) -1).
- Removed some very old VMS code
- Changed packfrm()/unpackfrm() to not be depending on uint size
(portability fix)
- Removed windows specific code to restore cursor position as this
causes slowdown on windows and we should not mix read() and pread()
calls anyway as this is not thread safe. Updated function comment to
reflect this. Changed function that depended on original behavior of
my_pwrite() to itself restore the cursor position (one such case).
- Added some missing checking of return value of malloc().
- Changed definition of MOD_PAD_CHAR_TO_FULL_LENGTH to avoid 'long' overflow.
- Changed type of table_def::m_size from my_size_t to ulong to reflect that
m_size is the number of elements in the array, not a string/memory
length.
- Moved THD::max_row_length() to table.cc (as it's not depending on THD).
Inlined max_row_length_blob() into this function.
- More function comments
- Fixed some compiler warnings when compiled without partitions.
- Removed setting of LEX_STRING() arguments in declaration (portability fix).
- Some trivial indentation/variable name changes.
- Some trivial code simplifications:
- Replaced some calls to alloc_root + memcpy to use
strmake_root()/strdup_root().
- Changed some calls from memdup() to strmake() (Safety fix)
- Simpler loops in client-simple.c
2007-05-10 11:59:39 +02:00
|
|
|
size_t const len= pack_row(table, cols, row_data, record);
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-01-09 15:59:39 +01:00
|
|
|
Rows_log_event* const ev=
|
|
|
|
binlog_prepare_pending_rows_event(table, server_id, cols, colcnt,
|
|
|
|
len, is_trans,
|
|
|
|
static_cast<Delete_rows_log_event*>(0));
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
if (unlikely(ev == 0))
|
|
|
|
return HA_ERR_OUT_OF_MEM;
|
2005-12-22 06:39:02 +01:00
|
|
|
|
2006-11-15 16:49:03 +01:00
|
|
|
return ev->add_row_data(row_data, len);
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-03 22:04:07 +02:00
|
|
|
int THD::binlog_remove_pending_rows_event(bool clear_maps)
|
|
|
|
{
|
2008-10-10 13:00:27 +02:00
|
|
|
DBUG_ENTER("THD::binlog_remove_pending_rows_event");
|
2008-09-03 22:04:07 +02:00
|
|
|
|
|
|
|
if (!mysql_bin_log.is_open())
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
|
|
|
mysql_bin_log.remove_pending_rows_event(this);
|
|
|
|
|
|
|
|
if (clear_maps)
|
|
|
|
binlog_table_maps= 0;
|
|
|
|
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
int THD::binlog_flush_pending_rows_event(bool stmt_end)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("THD::binlog_flush_pending_rows_event");
|
2006-08-16 14:55:57 +02:00
|
|
|
/*
|
|
|
|
We shall flush the pending event even if we are not in row-based
|
|
|
|
mode: it might be the case that we left row-based mode before
|
|
|
|
flushing anything (e.g., if we have explicitly locked tables).
|
|
|
|
*/
|
|
|
|
if (!mysql_bin_log.is_open())
|
2005-12-22 06:39:02 +01:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
Mark the event as the last event of a statement if the stmt_end
|
|
|
|
flag is set.
|
|
|
|
*/
|
|
|
|
int error= 0;
|
|
|
|
if (Rows_log_event *pending= binlog_get_pending_rows_event())
|
|
|
|
{
|
|
|
|
if (stmt_end)
|
|
|
|
{
|
|
|
|
pending->set_flags(Rows_log_event::STMT_END_F);
|
|
|
|
pending->flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
|
2006-02-16 08:30:53 +01:00
|
|
|
binlog_table_maps= 0;
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
|
2006-02-16 08:30:53 +01:00
|
|
|
error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0);
|
|
|
|
}
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
DBUG_RETURN(error);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 17:25:24 +02:00
|
|
|
#if !defined(DBUG_OFF) && !defined(_lint)
|
2008-10-08 11:15:00 +02:00
|
|
|
static const char *
|
|
|
|
show_query_type(THD::enum_binlog_query_type qtype)
|
|
|
|
{
|
|
|
|
switch (qtype) {
|
|
|
|
case THD::ROW_QUERY_TYPE:
|
|
|
|
return "ROW";
|
|
|
|
case THD::STMT_QUERY_TYPE:
|
|
|
|
return "STMT";
|
|
|
|
case THD::MYSQL_QUERY_TYPE:
|
|
|
|
return "MYSQL";
|
2008-10-08 17:25:24 +02:00
|
|
|
case THD::QUERY_TYPE_COUNT:
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0 <= qtype && qtype < THD::QUERY_TYPE_COUNT);
|
2008-10-08 11:15:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static char buf[64];
|
|
|
|
sprintf(buf, "UNKNOWN#%d", qtype);
|
|
|
|
return buf;
|
|
|
|
}
|
2008-10-08 17:25:24 +02:00
|
|
|
#endif
|
2008-10-08 11:15:00 +02:00
|
|
|
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
/*
|
|
|
|
Member function that will log query, either row-based or
|
WL#2977 and WL#2712 global and session-level variable to set the binlog format (row/statement),
and new binlog format called "mixed" (which is statement-based except if only row-based is correct,
in this cset it means if UDF or UUID is used; more cases could be added in later 5.1 release):
SET GLOBAL|SESSION BINLOG_FORMAT=row|statement|mixed|default;
the global default is statement unless cluster is enabled (then it's row) as in 5.1-alpha.
It's not possible to use SET on this variable if a session is currently in row-based mode and has open temporary tables (because CREATE
TEMPORARY TABLE was not binlogged so temp table is not known on slave), or if NDB is enabled (because
NDB does not support such change on-the-fly, though it will later), of if in a stored function (see below).
The added tests test the possibility or impossibility to SET, their effects, and the mixed mode,
including in prepared statements and in stored procedures and functions.
Caveats:
a) The mixed mode will not work for stored functions: in mixed mode, a stored function will
always be binlogged as one call and in a statement-based way (e.g. INSERT VALUES(myfunc()) or SELECT myfunc()).
b) for the same reason, changing the thread's binlog format inside a stored function is
refused with an error message.
c) the same problems apply to triggers; implementing b) for triggers will be done later (will ask
Dmitri).
Additionally, as the binlog format is now changeable by each user for his session, I remove the implication
which was done at startup, where row-based automatically set log-bin-trust-routine-creators to 1
(not possible anymore as a user can now switch to stmt-based and do nasty things again), and automatically
set --innodb-locks-unsafe-for-binlog to 1 (was anyway theoretically incorrect as it disabled
phantom protection).
Plus fixes for compiler warnings.
2006-02-25 22:21:03 +01:00
|
|
|
statement-based depending on the value of the 'current_stmt_binlog_row_based'
|
|
|
|
the value of the 'qtype' flag.
|
2005-12-22 06:39:02 +01:00
|
|
|
|
|
|
|
This function should be called after the all calls to ha_*_row()
|
|
|
|
functions have been issued, but before tables are unlocked and
|
|
|
|
closed.
|
|
|
|
|
2006-02-16 08:30:53 +01:00
|
|
|
OBSERVE
|
|
|
|
There shall be no writes to any system table after calling
|
|
|
|
binlog_query(), so these writes has to be moved to before the call
|
|
|
|
of binlog_query() for correct functioning.
|
|
|
|
|
|
|
|
This is necessesary not only for RBR, but the master might crash
|
|
|
|
after binlogging the query but before changing the system tables.
|
|
|
|
This means that the slave and the master are not in the same state
|
|
|
|
(after the master has restarted), so therefore we have to
|
|
|
|
eliminate this problem.
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
RETURN VALUE
|
|
|
|
Error code, or 0 if no error.
|
|
|
|
*/
|
2007-08-13 15:11:25 +02:00
|
|
|
int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
|
2007-05-29 21:17:09 +02:00
|
|
|
ulong query_len, bool is_trans, bool suppress_use,
|
|
|
|
THD::killed_state killed_status_arg)
|
2005-12-22 06:39:02 +01:00
|
|
|
{
|
|
|
|
DBUG_ENTER("THD::binlog_query");
|
2008-10-08 11:15:00 +02:00
|
|
|
DBUG_PRINT("enter", ("qtype: %s query: '%s'",
|
|
|
|
show_query_type(qtype), query_arg));
|
2007-08-13 15:11:25 +02:00
|
|
|
DBUG_ASSERT(query_arg && mysql_bin_log.is_open());
|
2006-02-16 08:30:53 +01:00
|
|
|
|
2006-08-16 14:55:57 +02:00
|
|
|
/*
|
|
|
|
If we are not in prelocked mode, mysql_unlock_tables() will be
|
|
|
|
called after this binlog_query(), so we have to flush the pending
|
|
|
|
rows event with the STMT_END_F set to unlock all tables at the
|
|
|
|
slave side as well.
|
|
|
|
|
|
|
|
If we are in prelocked mode, the flushing will be done inside the
|
|
|
|
top-most close_thread_tables().
|
|
|
|
*/
|
|
|
|
if (this->prelocked_mode == NON_PRELOCKED)
|
|
|
|
if (int error= binlog_flush_pending_rows_event(TRUE))
|
|
|
|
DBUG_RETURN(error);
|
|
|
|
|
2007-05-27 22:20:01 +02:00
|
|
|
/*
|
|
|
|
If we are in statement mode and trying to log an unsafe statement,
|
|
|
|
we should print a warning.
|
|
|
|
*/
|
|
|
|
if (lex->is_stmt_unsafe() &&
|
|
|
|
variables.binlog_format == BINLOG_FORMAT_STMT)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(this->query != NULL);
|
|
|
|
push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_BINLOG_UNSAFE_STATEMENT,
|
|
|
|
ER(ER_BINLOG_UNSAFE_STATEMENT));
|
|
|
|
if (!(binlog_flags & BINLOG_FLAG_UNSAFE_STMT_PRINTED))
|
|
|
|
{
|
|
|
|
char warn_buf[MYSQL_ERRMSG_SIZE];
|
|
|
|
my_snprintf(warn_buf, MYSQL_ERRMSG_SIZE, "%s Statement: %s",
|
|
|
|
ER(ER_BINLOG_UNSAFE_STATEMENT), this->query);
|
|
|
|
sql_print_warning(warn_buf);
|
|
|
|
binlog_flags|= BINLOG_FLAG_UNSAFE_STMT_PRINTED;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-05-05 19:08:40 +02:00
|
|
|
switch (qtype) {
|
2006-11-01 09:49:03 +01:00
|
|
|
case THD::ROW_QUERY_TYPE:
|
2008-10-08 11:15:00 +02:00
|
|
|
DBUG_PRINT("debug",
|
|
|
|
("current_stmt_binlog_row_based: %d",
|
|
|
|
current_stmt_binlog_row_based));
|
2006-11-01 09:49:03 +01:00
|
|
|
if (current_stmt_binlog_row_based)
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
/* Otherwise, we fall through */
|
2005-12-22 06:39:02 +01:00
|
|
|
case THD::MYSQL_QUERY_TYPE:
|
|
|
|
/*
|
|
|
|
Using this query type is a conveniece hack, since we have been
|
|
|
|
moving back and forth between using RBR for replication of
|
|
|
|
system tables and not using it.
|
|
|
|
|
2006-03-17 18:11:07 +01:00
|
|
|
Make sure to change in check_table_binlog_row_based() according
|
2005-12-22 06:39:02 +01:00
|
|
|
to how you treat this.
|
|
|
|
*/
|
|
|
|
case THD::STMT_QUERY_TYPE:
|
|
|
|
/*
|
2006-02-16 08:30:53 +01:00
|
|
|
The MYSQL_LOG::write() function will set the STMT_END_F flag and
|
|
|
|
flush the pending rows event if necessary.
|
2005-12-22 06:39:02 +01:00
|
|
|
*/
|
|
|
|
{
|
2007-08-13 15:11:25 +02:00
|
|
|
Query_log_event qinfo(this, query_arg, query_len, is_trans, suppress_use,
|
2007-05-29 21:17:09 +02:00
|
|
|
killed_status_arg);
|
2005-12-22 06:39:02 +01:00
|
|
|
qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F;
|
2006-02-16 08:30:53 +01:00
|
|
|
/*
|
|
|
|
Binlog table maps will be irrelevant after a Query_log_event
|
|
|
|
(they are just removed on the slave side) so after the query
|
|
|
|
log event is written to the binary log, we pretend that no
|
|
|
|
table maps were written.
|
|
|
|
*/
|
|
|
|
int error= mysql_bin_log.write(&qinfo);
|
|
|
|
binlog_table_maps= 0;
|
|
|
|
DBUG_RETURN(error);
|
2005-12-22 06:39:02 +01:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case THD::QUERY_TYPE_COUNT:
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0 <= qtype && qtype < QUERY_TYPE_COUNT);
|
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
|
|
|
|
ulonglong incr)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Discrete_intervals_list::append");
|
|
|
|
/* first, see if this can be merged with previous */
|
|
|
|
if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
|
|
|
|
{
|
|
|
|
/* it cannot, so need to add a new interval */
|
|
|
|
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
DBUG_RETURN(append(new_interval));
|
WL#3146 "less locking in auto_increment":
this is a cleanup patch for our current auto_increment handling:
new names for auto_increment variables in THD, new methods to manipulate them
(see sql_class.h), some move into handler::, causing less backup/restore
work when executing substatements.
This makes the logic hopefully clearer, less work is is needed in
mysql_insert().
By cleaning up, using different variables for different purposes (instead
of one for 3 things...), we fix those bugs, which someone may want to fix
in 5.0 too:
BUG#20339 "stored procedure using LAST_INSERT_ID() does not replicate
statement-based"
BUG#20341 "stored function inserting into one auto_increment puts bad
data in slave"
BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY UPDATE"
(now if a row is updated, LAST_INSERT_ID() will return its id)
and re-fixes:
BUG#6880 "LAST_INSERT_ID() value changes during multi-row INSERT"
(already fixed differently by Ramil in 4.1)
Test of documented behaviour of mysql_insert_id() (there was no test).
The behaviour changes introduced are:
- LAST_INSERT_ID() now returns "the first autogenerated auto_increment value
successfully inserted", instead of "the first autogenerated auto_increment
value if any row was successfully inserted", see auto_increment.test.
Same for mysql_insert_id(), see mysql_client_test.c.
- LAST_INSERT_ID() returns the id of the updated row if ON DUPLICATE KEY
UPDATE, see auto_increment.test. Same for mysql_insert_id(), see
mysql_client_test.c.
- LAST_INSERT_ID() does not change if no autogenerated value was successfully
inserted (it used to then be 0), see auto_increment.test.
- if in INSERT SELECT no autogenerated value was successfully inserted,
mysql_insert_id() now returns the id of the last inserted row (it already
did this for INSERT VALUES), see mysql_client_test.c.
- if INSERT SELECT uses LAST_INSERT_ID(X), mysql_insert_id() now returns X
(it already did this for INSERT VALUES), see mysql_client_test.c.
- NDB now behaves like other engines wrt SET INSERT_ID: with INSERT IGNORE,
the id passed in SET INSERT_ID is re-used until a row succeeds; SET INSERT_ID
influences not only the first row now.
Additionally, when unlocking a table we check that the thread is not keeping
a next_insert_id (as the table is unlocked that id is potentially out-of-date);
forgetting about this next_insert_id is done in a new
handler::ha_release_auto_increment().
Finally we prepare for engines capable of reserving finite-length intervals
of auto_increment values: we store such intervals in THD. The next step
(to be done by the replication team in 5.1) is to read those intervals from
THD and actually store them in the statement-based binary log. NDB
will be a good engine to test that.
2006-07-09 17:52:19 +02:00
|
|
|
}
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
BUG#33029 5.0 to 5.1 replication fails on dup key when inserting
using a trig in SP
For all 5.0 and up to 5.1.12 exclusive, when a stored routine or
trigger caused an INSERT into an AUTO_INCREMENT column, the
generated AUTO_INCREMENT value should not be written into the
binary log, which means if a statement does not generate
AUTO_INCREMENT value itself, there will be no Intvar event (SET
INSERT_ID) associated with it even if one of the stored routine
or trigger caused generation of such a value. And meanwhile, when
executing a stored routine or trigger, it would ignore the
INSERT_ID value even if there is a INSERT_ID value available set
by a SET INSERT_ID statement.
Starting from MySQL 5.1.12, the generated AUTO_INCREMENT value is
written into the binary log, and the value will be used if
available when executing the stored routine or trigger.
Prior fix of this bug in MySQL 5.0 and prior MySQL 5.1.12
(referenced as the buggy versions in the text below), when a
statement that generates AUTO_INCREMENT value by the top
statement was executed in the body of a SP, all statements in the
SP after this statement would be treated as if they had generated
AUTO_INCREMENT by the top statement. When a statement that did
not generate AUTO_INCREMENT value by the top statement but by a
function/trigger called by it, an erroneous Intvar event would be
associated with the statement, this erroneous INSERT_ID value
wouldn't cause problem when replicating between masters and
slaves of 5.0.x or prior 5.1.12, because the erroneous INSERT_ID
value was not used when executing functions/triggers. But when
replicating from buggy versions to 5.1.12 or newer, which will
use the INSERT_ID value in functions/triggers, the erroneous
value will be used, which would cause duplicate entry error and
cause the slave to stop.
The patch for 5.1 fixed it to ignore the SET INSERT_ID value when
executing functions/triggers if it is replicating from a master
of buggy versions, another patch for 5.0 fixed it not to generate
the erroneous Intvar event.
2008-03-14 04:35:41 +01:00
|
|
|
bool Discrete_intervals_list::append(Discrete_interval *new_interval)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Discrete_intervals_list::append");
|
|
|
|
if (unlikely(new_interval == NULL))
|
|
|
|
DBUG_RETURN(1);
|
|
|
|
DBUG_PRINT("info",("adding new auto_increment interval"));
|
|
|
|
if (head == NULL)
|
|
|
|
head= current= new_interval;
|
|
|
|
else
|
|
|
|
tail->next= new_interval;
|
|
|
|
tail= new_interval;
|
|
|
|
elements++;
|
|
|
|
DBUG_RETURN(0);
|
|
|
|
}
|
|
|
|
|
2005-12-22 06:39:02 +01:00
|
|
|
#endif /* !defined(MYSQL_CLIENT) */
|