2011-01-14 10:05:14 +01:00
|
|
|
/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
|
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.
|
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.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software
|
Fix for BUG#11755168 '46895: test "outfile_loaddata" fails (reproducible)'.
In sql_class.cc, 'row_count', of type 'ha_rows', was used as last argument for
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD which is
"Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld".
So 'ha_rows' was used as 'long'.
On SPARC32 Solaris builds, 'long' is 4 bytes and 'ha_rows' is 'longlong' i.e. 8 bytes.
So the printf-like code was reading only the first 4 bytes.
Because the CPU is big-endian, 1LL is 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
so the first four bytes yield 0. So the warning message had "row 0" instead of
"row 1" in test outfile_loaddata.test:
-Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 1
+Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 0
All error-messaging functions which internally invoke some printf-life function
are potential candidate for such mistakes.
One apparently easy way to catch such mistakes is to use
ATTRIBUTE_FORMAT (from my_attribute.h).
But this works only when call site has both:
a) the format as a string literal
b) the types of arguments.
So:
func(ER(ER_BLAH), 10);
will silently not be checked, because ER(ER_BLAH) is not known at
compile time (it is known at run-time, and depends on the chosen
language).
And
func("%s", a va_list argument);
has the same problem, as the *real* type of arguments is not
known at this site at compile time (it's known in some caller).
Moreover,
func(ER(ER_BLAH));
though possibly correct (if ER(ER_BLAH) has no '%' markers), will not
compile (gcc says "error: format not a string literal and no format
arguments").
Consequences:
1) ATTRIBUTE_FORMAT is here added only to functions which in practice
take "string literal" formats: "my_error_reporter" and "print_admin_msg".
2) it cannot be added to the other functions: my_error(),
push_warning_printf(), Table_check_intact::report_error(),
general_log_print().
To do a one-time check of functions listed in (2), the following
"static code analysis" has been done:
1) replace
my_error(ER_xxx, arguments for substitution in format)
with the equivalent
my_printf_error(ER_xxx,ER(ER_xxx), arguments for substitution in
format),
so that we have ER(ER_xxx) and the arguments *in the same call site*
2) add ATTRIBUTE_FORMAT to push_warning_printf(),
Table_check_intact::report_error(), general_log_print()
3) replace ER(xxx) with the hard-coded English text found in
errmsg.txt (like: ER(ER_UNKNOWN_ERROR) is replaced with
"Unknown error"), so that a call site has the format as string literal
4) this way, ATTRIBUTE_FORMAT can effectively do its job
5) compile, fix errors detected by ATTRIBUTE_FORMAT
6) revert steps 1-2-3.
The present patch has no compiler error when submitted again to the
static code analysis above.
It cannot catch all problems though: see Field::set_warning(), in
which a call to push_warning_printf() has a variable error
(thus, not replacable by a string literal); I checked set_warning() calls
by hand though.
See also WL 5883 for one proposal to avoid such bugs from appearing
again in the future.
The issues fixed in the patch are:
a) mismatch in types (like 'int' passed to '%ld')
b) more arguments passed than specified in the format.
This patch resolves mismatches by changing the type/number of arguments,
not by changing error messages of sql/share/errmsg.txt. The latter would be wrong,
per the following old rule: errmsg.txt must be as stable as possible; no insertions
or deletions of messages, no changes of type or number of printf-like format specifiers,
are allowed, as long as the change impacts a message already released in a GA version.
If this rule is not followed:
- Connectors, which use error message numbers, will be confused (by insertions/deletions
of messages)
- using errmsg.sys of MySQL 5.1.n with mysqld of MySQL 5.1.(n+1)
could produce wrong messages or crash; such usage can easily happen if
installing 5.1.(n+1) while /etc/my.cnf still has --language=/path/to/5.1.n/xxx;
or if copying mysqld from 5.1.(n+1) into a 5.1.n installation.
When fixing b), I have verified that the superfluous arguments were not used in the format
in the first 5.1 GA (5.1.30 'bteam@astra04-20081114162938-z8mctjp6st27uobm').
Had they been used, then passing them today, even if the message doesn't use them
anymore, would have been necessary, as explained above.
2011-05-16 22:04:01 +02:00
|
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
@file
|
|
|
|
|
|
|
|
@brief
|
|
|
|
This file defines all numerical functions
|
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
|
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
|
|
|
|
|
2010-04-07 13:58:40 +02:00
|
|
|
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_priv.h"
|
|
|
|
/*
|
|
|
|
It is necessary to include set_var.h instead of item.h because there
|
|
|
|
are dependencies on include order for set_var.h and item.h. This
|
|
|
|
will be resolved later.
|
|
|
|
*/
|
|
|
|
#include "sql_class.h" // set_var.h: THD
|
|
|
|
#include "set_var.h"
|
2003-08-07 19:42:26 +02:00
|
|
|
#include "slave.h" // for wait_for_master_pos
|
2010-03-31 16:05:33 +02:00
|
|
|
#include "sql_show.h" // append_identifier
|
|
|
|
#include "strfunc.h" // find_type
|
|
|
|
#include "sql_parse.h" // is_update_query
|
|
|
|
#include "sql_acl.h" // EXECUTE_ACL
|
|
|
|
#include "mysqld.h" // LOCK_uuid_generator
|
2007-04-12 08:58:04 +02:00
|
|
|
#include "rpl_mi.h"
|
2000-07-31 21:29:14 +02:00
|
|
|
#include <m_ctype.h>
|
|
|
|
#include <hash.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <ft_global.h>
|
2007-10-11 17:07:40 +02:00
|
|
|
#include <my_bit.h>
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-02-26 19:22:29 +01:00
|
|
|
#include "sp_head.h"
|
|
|
|
#include "sp_rcontext.h"
|
|
|
|
#include "sp.h"
|
2009-12-22 10:35:56 +01:00
|
|
|
#include "set_var.h"
|
2010-06-25 17:32:59 +02:00
|
|
|
#include "debug_sync.h"
|
2010-10-27 20:29:09 +02:00
|
|
|
#include <mysql/plugin.h>
|
|
|
|
#include <mysql/service_thd_wait.h>
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-10-11 23:58:22 +02:00
|
|
|
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
|
|
|
#define sp_restore_security_context(A,B) while (0) {}
|
|
|
|
#endif
|
|
|
|
|
2004-03-16 11:01:05 +01:00
|
|
|
bool check_reserved_words(LEX_STRING *name)
|
|
|
|
{
|
|
|
|
if (!my_strcasecmp(system_charset_info, name->str, "GLOBAL") ||
|
|
|
|
!my_strcasecmp(system_charset_info, name->str, "LOCAL") ||
|
|
|
|
!my_strcasecmp(system_charset_info, name->str, "SESSION"))
|
|
|
|
return TRUE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
@return
|
|
|
|
TRUE if item is a constant
|
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
bool
|
|
|
|
eval_const_cond(COND *cond)
|
|
|
|
{
|
|
|
|
return ((Item_func*) cond)->val_int() ? TRUE : FALSE;
|
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2010-03-18 11:38:29 +01:00
|
|
|
/**
|
|
|
|
Test if the sum of arguments overflows the ulonglong range.
|
|
|
|
*/
|
|
|
|
static inline bool test_if_sum_overflows_ull(ulonglong arg1, ulonglong arg2)
|
|
|
|
{
|
|
|
|
return ULONGLONG_MAX - arg1 < arg2;
|
|
|
|
}
|
|
|
|
|
2003-07-17 13:07:56 +02:00
|
|
|
void Item_func::set_arguments(List<Item> &list)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-07-17 13:07:56 +02:00
|
|
|
allowed_arg_cols= 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
arg_count=list.elements;
|
2005-06-05 16:01:20 +02:00
|
|
|
args= tmp_arg; // If 2 arguments
|
|
|
|
if (arg_count <= 2 || (args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2001-08-02 05:29:50 +02:00
|
|
|
List_iterator_fast<Item> li(list);
|
2000-07-31 21:29:14 +02:00
|
|
|
Item *item;
|
2005-06-05 16:01:20 +02:00
|
|
|
Item **save_args= args;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
while ((item=li++))
|
|
|
|
{
|
2005-06-05 16:01:20 +02:00
|
|
|
*(save_args++)= item;
|
2000-07-31 21:29:14 +02:00
|
|
|
with_sum_func|=item->with_sum_func;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
list.empty(); // Fields are used
|
|
|
|
}
|
|
|
|
|
2003-07-17 13:07:56 +02:00
|
|
|
Item_func::Item_func(List<Item> &list)
|
|
|
|
:allowed_arg_cols(1)
|
|
|
|
{
|
|
|
|
set_arguments(list);
|
|
|
|
}
|
|
|
|
|
2004-01-19 16:53:25 +01:00
|
|
|
Item_func::Item_func(THD *thd, Item_func *item)
|
2003-09-02 18:56:55 +02:00
|
|
|
:Item_result_field(thd, item),
|
2004-01-19 16:53:25 +01:00
|
|
|
allowed_arg_cols(item->allowed_arg_cols),
|
|
|
|
arg_count(item->arg_count),
|
|
|
|
used_tables_cache(item->used_tables_cache),
|
|
|
|
not_null_tables_cache(item->not_null_tables_cache),
|
|
|
|
const_item_cache(item->const_item_cache)
|
2003-09-02 18:56:55 +02:00
|
|
|
{
|
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
if (arg_count <=2)
|
|
|
|
args= tmp_arg;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (!(args=(Item**) thd->alloc(sizeof(Item*)*arg_count)))
|
|
|
|
return;
|
|
|
|
}
|
2004-01-19 16:53:25 +01:00
|
|
|
memcpy((char*) args, (char*) item->args, sizeof(Item*)*arg_count);
|
2003-09-02 18:56:55 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-30 11:40:40 +02:00
|
|
|
|
|
|
|
/*
|
2006-11-06 23:13:19 +01:00
|
|
|
Resolve references to table column for a function and its argument
|
2002-08-30 11:40:40 +02:00
|
|
|
|
|
|
|
SYNOPSIS:
|
|
|
|
fix_fields()
|
|
|
|
thd Thread object
|
|
|
|
ref Pointer to where this object is used. This reference
|
|
|
|
is used if we want to replace this object with another
|
|
|
|
one (for example in the summary functions).
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
Call fix_fields() for all arguments to the function. The main intention
|
|
|
|
is to allow all Item_field() objects to setup pointers to the table fields.
|
|
|
|
|
|
|
|
Sets as a side effect the following class variables:
|
|
|
|
maybe_null Set if any argument may return NULL
|
|
|
|
with_sum_func Set if any of the arguments contains a sum function
|
2004-11-16 21:27:31 +01:00
|
|
|
used_tables_cache Set to union of the tables used by arguments
|
2002-08-30 11:40:40 +02:00
|
|
|
|
|
|
|
str_value.charset If this is a string function, set this to the
|
|
|
|
character set for the first argument.
|
2003-02-12 20:55:37 +01:00
|
|
|
If any argument is binary, this is set to binary
|
2002-08-30 11:40:40 +02:00
|
|
|
|
|
|
|
If for any item any of the defaults are wrong, then this can
|
|
|
|
be fixed in the fix_length_and_dec() function that is called
|
|
|
|
after this one or by writing a specialized fix_fields() for the
|
|
|
|
item.
|
|
|
|
|
|
|
|
RETURN VALUES
|
2004-10-20 03:04:37 +02:00
|
|
|
FALSE ok
|
|
|
|
TRUE Got error. Stored with my_error().
|
2002-08-30 11:40:40 +02:00
|
|
|
*/
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
bool
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_func::fix_fields(THD *thd, Item **ref)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-17 13:26:26 +01:00
|
|
|
DBUG_ASSERT(fixed == 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
Item **arg,**arg_end;
|
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 buff[STACK_BUFF_ALLOC]; // Max argument in function
|
2003-02-12 20:55:37 +01:00
|
|
|
|
2003-06-26 04:38:19 +02:00
|
|
|
used_tables_cache= not_null_tables_cache= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
const_item_cache=1;
|
|
|
|
|
2010-11-10 06:49:37 +01:00
|
|
|
/*
|
|
|
|
Use stack limit of STACK_MIN_SIZE * 2 since
|
|
|
|
on some platforms a recursive call to fix_fields
|
|
|
|
requires more than STACK_MIN_SIZE bytes (e.g. for
|
|
|
|
MIPS, it takes about 22kB to make one recursive
|
|
|
|
call to Item_func::fix_fields())
|
|
|
|
*/
|
|
|
|
if (check_stack_overrun(thd, STACK_MIN_SIZE * 2, buff))
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE; // Fatal error if flag is set!
|
2000-07-31 21:29:14 +02:00
|
|
|
if (arg_count)
|
|
|
|
{ // Print purify happy
|
|
|
|
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
|
|
|
|
{
|
2003-05-21 20:39:58 +02:00
|
|
|
Item *item;
|
2004-03-18 14:21:06 +01:00
|
|
|
/*
|
|
|
|
We can't yet set item to *arg as fix_fields may change *arg
|
|
|
|
We shouldn't call fix_fields() twice, so check 'fixed' field first
|
|
|
|
*/
|
2005-07-01 06:05:42 +02:00
|
|
|
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg)))
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE; /* purecov: inspected */
|
2003-05-21 20:39:58 +02:00
|
|
|
item= *arg;
|
2005-01-24 13:25:44 +01:00
|
|
|
|
|
|
|
if (allowed_arg_cols)
|
|
|
|
{
|
|
|
|
if (item->check_cols(allowed_arg_cols))
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* we have to fetch allowed_arg_cols from first argument */
|
|
|
|
DBUG_ASSERT(arg == args); // it is first argument
|
|
|
|
allowed_arg_cols= item->cols();
|
|
|
|
DBUG_ASSERT(allowed_arg_cols); // Can't be 0 any more
|
|
|
|
}
|
|
|
|
|
2003-03-24 21:52:46 +01:00
|
|
|
if (item->maybe_null)
|
2000-07-31 21:29:14 +02:00
|
|
|
maybe_null=1;
|
2003-10-20 15:53:48 +02:00
|
|
|
|
2003-03-24 21:52:46 +01:00
|
|
|
with_sum_func= with_sum_func || item->with_sum_func;
|
2003-06-26 04:38:19 +02:00
|
|
|
used_tables_cache|= item->used_tables();
|
|
|
|
not_null_tables_cache|= item->not_null_tables();
|
|
|
|
const_item_cache&= item->const_item();
|
2006-05-17 22:55:28 +02:00
|
|
|
with_subselect|= item->with_subselect;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
fix_length_and_dec();
|
2007-10-30 18:08:16 +01:00
|
|
|
if (thd->is_error()) // An error inside fix_length_and_dec occured
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE;
|
2002-11-21 10:01:33 +01:00
|
|
|
fixed= 1;
|
2004-10-20 03:04:37 +02:00
|
|
|
return FALSE;
|
2000-07-31 21:29:14 +02: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
|
|
|
|
|
|
|
bool Item_func::walk(Item_processor processor, bool walk_subquery,
|
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 *argument)
|
2003-07-02 12:12:18 +02:00
|
|
|
{
|
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
Item **arg,**arg_end;
|
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; 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
|
|
|
if ((*arg)->walk(processor, walk_subquery, argument))
|
2003-07-02 12:12:18 +02:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (this->*processor)(argument);
|
|
|
|
}
|
2002-12-26 00:28:59 +01:00
|
|
|
|
2005-03-02 10:38:25 +01:00
|
|
|
void Item_func::traverse_cond(Cond_traverser traverser,
|
|
|
|
void *argument, traverse_order order)
|
2004-12-17 21:13:22 +01:00
|
|
|
{
|
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
Item **arg,**arg_end;
|
2004-12-20 10:58:00 +01:00
|
|
|
|
|
|
|
switch (order) {
|
|
|
|
case(PREFIX):
|
2005-02-11 22:05:24 +01:00
|
|
|
(*traverser)(this, argument);
|
2004-12-20 10:58:00 +01:00
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
|
|
|
{
|
|
|
|
(*arg)->traverse_cond(traverser, argument, order);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case (POSTFIX):
|
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
|
|
|
{
|
|
|
|
(*arg)->traverse_cond(traverser, argument, order);
|
|
|
|
}
|
2005-02-11 22:05:24 +01:00
|
|
|
(*traverser)(this, argument);
|
2004-12-17 21:13:22 +01:00
|
|
|
}
|
|
|
|
}
|
2007-02-09 16:31:12 +01:00
|
|
|
else
|
|
|
|
(*traverser)(this, argument);
|
2004-12-17 21:13:22 +01:00
|
|
|
}
|
|
|
|
|
2004-02-19 07:21:37 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Transform an Item_func object with a transformer callback function.
|
|
|
|
|
2006-09-07 20:06:37 +02:00
|
|
|
The function recursively applies the transform method to each
|
|
|
|
argument of the Item_func node.
|
|
|
|
If the call of the method for an argument item returns a new item
|
2004-02-19 07:21:37 +01:00
|
|
|
the old item is substituted for a new one.
|
2006-09-07 20:06:37 +02:00
|
|
|
After this the transformer is applied to the root node
|
2004-02-19 07:21:37 +01:00
|
|
|
of the Item_func object.
|
2007-10-11 19:29:09 +02:00
|
|
|
@param transformer the transformer callback function to be applied to
|
|
|
|
the nodes of the tree of the object
|
|
|
|
@param argument parameter to be passed to the transformer
|
|
|
|
|
|
|
|
@return
|
|
|
|
Item returned as the result of transformation of the root node
|
2004-02-19 07:21:37 +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
|
|
|
Item *Item_func::transform(Item_transformer transformer, uchar *argument)
|
2003-11-27 02:23:52 +01:00
|
|
|
{
|
2011-05-06 13:39:40 +02:00
|
|
|
DBUG_ASSERT(!current_thd->stmt_arena->is_stmt_prepare());
|
2006-08-24 13:49:12 +02:00
|
|
|
|
2003-11-27 02:23:52 +01:00
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
Item **arg,**arg_end;
|
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
|
|
|
{
|
2004-02-19 07:21:37 +01:00
|
|
|
Item *new_item= (*arg)->transform(transformer, argument);
|
2003-11-27 02:23:52 +01:00
|
|
|
if (!new_item)
|
|
|
|
return 0;
|
2006-08-24 13:49:12 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
THD::change_item_tree() should be called only if the tree was
|
|
|
|
really transformed, i.e. when a new item has been created.
|
|
|
|
Otherwise we'll be allocating a lot of unnecessary memory for
|
|
|
|
change records at each execution.
|
|
|
|
*/
|
2004-11-03 11:39:38 +01:00
|
|
|
if (*arg != new_item)
|
|
|
|
current_thd->change_item_tree(arg, new_item);
|
2003-11-27 02:23:52 +01:00
|
|
|
}
|
|
|
|
}
|
2004-02-19 07:21:37 +01:00
|
|
|
return (this->*transformer)(argument);
|
2003-11-27 02:23:52 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Compile Item_func object with a processor and a transformer
|
|
|
|
callback functions.
|
|
|
|
|
2006-09-07 20:06:37 +02:00
|
|
|
First the function applies the analyzer to the root node of
|
|
|
|
the Item_func object. Then if the analizer succeeeds (returns TRUE)
|
|
|
|
the function recursively applies the compile method to each argument
|
|
|
|
of the Item_func node.
|
|
|
|
If the call of the method for an argument item returns a new item
|
|
|
|
the old item is substituted for a new one.
|
|
|
|
After this the transformer is applied to the root node
|
|
|
|
of the Item_func object.
|
2007-10-11 19:29:09 +02:00
|
|
|
|
|
|
|
@param analyzer the analyzer callback function to be applied to the
|
|
|
|
nodes of the tree of the object
|
|
|
|
@param[in,out] arg_p parameter to be passed to the processor
|
|
|
|
@param transformer the transformer callback function to be applied to the
|
|
|
|
nodes of the tree of the object
|
|
|
|
@param arg_t parameter to be passed to the transformer
|
|
|
|
|
|
|
|
@return
|
|
|
|
Item returned as the result of transformation of the root node
|
2006-09-07 20:06:37 +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
|
|
|
Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
|
|
|
|
Item_transformer transformer, uchar *arg_t)
|
2006-09-07 20:06:37 +02:00
|
|
|
{
|
|
|
|
if (!(this->*analyzer)(arg_p))
|
|
|
|
return 0;
|
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
Item **arg,**arg_end;
|
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
The same parameter value of arg_p must be passed
|
|
|
|
to analyze any argument of the condition formula.
|
|
|
|
*/
|
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 *arg_v= *arg_p;
|
2006-09-07 20:06:37 +02:00
|
|
|
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
|
|
|
|
if (new_item && *arg != new_item)
|
|
|
|
current_thd->change_item_tree(arg, new_item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (this->*transformer)(arg_t);
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
See comments in Item_cmp_func::split_sum_func()
|
|
|
|
*/
|
2005-02-08 13:41:09 +01:00
|
|
|
|
2004-10-08 17:13:09 +02:00
|
|
|
void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|
|
|
List<Item> &fields)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-01-29 19:44:47 +01:00
|
|
|
Item **arg, **arg_end;
|
|
|
|
for (arg= args, arg_end= args+arg_count; arg != arg_end ; arg++)
|
2005-10-15 23:32:37 +02:00
|
|
|
(*arg)->split_sum_func2(thd, ref_pointer_array, fields, arg, TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func::update_used_tables()
|
|
|
|
{
|
|
|
|
used_tables_cache=0;
|
|
|
|
const_item_cache=1;
|
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
|
|
{
|
|
|
|
args[i]->update_used_tables();
|
|
|
|
used_tables_cache|=args[i]->used_tables();
|
|
|
|
const_item_cache&=args[i]->const_item();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
table_map Item_func::used_tables() const
|
|
|
|
{
|
|
|
|
return used_tables_cache;
|
|
|
|
}
|
|
|
|
|
2003-06-26 04:38:19 +02:00
|
|
|
|
|
|
|
table_map Item_func::not_null_tables() const
|
|
|
|
{
|
|
|
|
return not_null_tables_cache;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func::print(String *str, enum_query_type query_type)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
str->append(func_name());
|
|
|
|
str->append('(');
|
2008-02-22 11:30:33 +01:00
|
|
|
print_args(str, 0, query_type);
|
2003-10-30 11:57:26 +01:00
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func::print_args(String *str, uint from, enum_query_type query_type)
|
2003-10-30 11:57:26 +01:00
|
|
|
{
|
2003-11-03 11:28:36 +01:00
|
|
|
for (uint i=from ; i < arg_count ; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-11-03 11:28:36 +01:00
|
|
|
if (i != from)
|
2000-07-31 21:29:14 +02:00
|
|
|
str->append(',');
|
2008-02-22 11:30:33 +01:00
|
|
|
args[i]->print(str, query_type);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func::print_op(String *str, enum_query_type query_type)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
str->append('(');
|
|
|
|
for (uint i=0 ; i < arg_count-1 ; i++)
|
|
|
|
{
|
2008-02-22 11:30:33 +01:00
|
|
|
args[i]->print(str, query_type);
|
2000-07-31 21:29:14 +02:00
|
|
|
str->append(' ');
|
|
|
|
str->append(func_name());
|
|
|
|
str->append(' ');
|
|
|
|
}
|
2008-02-22 11:30:33 +01:00
|
|
|
args[arg_count-1]->print(str, query_type);
|
2000-07-31 21:29:14 +02:00
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
2003-12-19 15:25:50 +01:00
|
|
|
|
2002-03-22 13:03:42 +01:00
|
|
|
bool Item_func::eq(const Item *item, bool binary_cmp) const
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
/* Assume we don't have rtti */
|
|
|
|
if (this == item)
|
|
|
|
return 1;
|
|
|
|
if (item->type() != FUNC_ITEM)
|
|
|
|
return 0;
|
|
|
|
Item_func *item_func=(Item_func*) item;
|
2007-03-07 20:11:57 +01:00
|
|
|
Item_func::Functype func_type;
|
|
|
|
if ((func_type= functype()) != item_func->functype() ||
|
|
|
|
arg_count != item_func->arg_count ||
|
|
|
|
(func_type != Item_func::FUNC_SP &&
|
|
|
|
func_name() != item_func->func_name()) ||
|
|
|
|
(func_type == Item_func::FUNC_SP &&
|
|
|
|
my_strcasecmp(system_charset_info, func_name(), item_func->func_name())))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
for (uint i=0; i < arg_count ; i++)
|
2002-03-22 13:03:42 +01:00
|
|
|
if (!args[i]->eq(item_func->args[i], binary_cmp))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2004-12-07 14:47:00 +01:00
|
|
|
|
2005-11-23 21:45:02 +01:00
|
|
|
Field *Item_func::tmp_table_field(TABLE *table)
|
2002-08-08 19:49:06 +02:00
|
|
|
{
|
2009-09-17 17:25:52 +02:00
|
|
|
Field *field= NULL;
|
2002-08-08 19:49:06 +02:00
|
|
|
|
2002-09-04 14:24:27 +02:00
|
|
|
switch (result_type()) {
|
2002-08-08 19:49:06 +02:00
|
|
|
case INT_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
if (max_char_length() > MY_INT32_NUM_DECIMAL_DIGITS)
|
|
|
|
field= new Field_longlong(max_char_length(), maybe_null, name,
|
|
|
|
unsigned_flag);
|
2002-08-08 19:49:06 +02:00
|
|
|
else
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
field= new Field_long(max_char_length(), maybe_null, name,
|
|
|
|
unsigned_flag);
|
2002-08-08 19:49:06 +02:00
|
|
|
break;
|
|
|
|
case REAL_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
field= new Field_double(max_char_length(), maybe_null, name, decimals);
|
2002-08-08 19:49:06 +02:00
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
2005-11-23 21:45:02 +01:00
|
|
|
return make_string_field(table);
|
2002-08-08 19:49:06 +02:00
|
|
|
break;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
2009-11-20 11:10:47 +01:00
|
|
|
field= Field_new_decimal::create_from_item(this);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
2003-02-17 15:06:51 +01:00
|
|
|
case ROW_RESULT:
|
2003-01-31 11:07:07 +01:00
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2002-11-15 19:32:09 +01:00
|
|
|
DBUG_ASSERT(0);
|
2005-11-23 21:45:02 +01:00
|
|
|
field= 0;
|
2002-11-15 19:32:09 +01:00
|
|
|
break;
|
2002-08-08 19:49:06 +02:00
|
|
|
}
|
2005-11-23 21:45:02 +01:00
|
|
|
if (field)
|
|
|
|
field->init(table);
|
|
|
|
return field;
|
2002-08-08 19:49:06 +02:00
|
|
|
}
|
|
|
|
|
2005-11-23 21:45: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
|
|
|
bool Item_func::is_expensive_processor(uchar *arg)
|
2006-07-25 22:31:29 +02:00
|
|
|
{
|
2006-07-26 19:36:03 +02:00
|
|
|
return is_expensive();
|
2006-07-25 22:31:29 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed);
|
2011-03-28 15:27:44 +02:00
|
|
|
longlong nr= val_int();
|
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
|
2005-02-08 23:50:45 +01:00
|
|
|
return decimal_value;
|
|
|
|
}
|
|
|
|
|
2002-08-08 19:49:06 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
String *Item_real_func::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double nr= val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_real(nr, decimals, collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-07 17:28:47 +02:00
|
|
|
my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed);
|
|
|
|
double nr= val_real();
|
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
double2my_decimal(E_DEC_FATAL_ERROR, nr, decimal_value);
|
|
|
|
return decimal_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
void Item_func::fix_num_length_and_dec()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-10-15 16:47:23 +02:00
|
|
|
uint fl_length= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
decimals=0;
|
2005-02-08 23:50:45 +01:00
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
set_if_bigger(decimals,args[i]->decimals);
|
2005-10-15 16:47:23 +02:00
|
|
|
set_if_bigger(fl_length, args[i]->max_length);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
max_length=float_length(decimals);
|
2005-10-15 16:47:23 +02:00
|
|
|
if (fl_length > max_length)
|
|
|
|
{
|
|
|
|
decimals= NOT_FIXED_DEC;
|
|
|
|
max_length= float_length(NOT_FIXED_DEC);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_numhybrid::fix_num_length_and_dec()
|
|
|
|
{}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-02-08 23:50:45 +01:00
|
|
|
Set max_length/decimals of function if function is fixed point and
|
2007-10-11 19:29:09 +02:00
|
|
|
result length/precision depends on argument ones.
|
2005-02-08 23:50:45 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
void Item_func::count_decimal_length()
|
|
|
|
{
|
2005-05-05 17:06:49 +02:00
|
|
|
int max_int_part= 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
decimals= 0;
|
2005-05-05 17:06:49 +02:00
|
|
|
unsigned_flag= 1;
|
2005-02-08 23:50:45 +01:00
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
set_if_bigger(decimals, args[i]->decimals);
|
2005-05-05 17:06:49 +02:00
|
|
|
set_if_bigger(max_int_part, args[i]->decimal_int_part());
|
|
|
|
set_if_smaller(unsigned_flag, args[i]->unsigned_flag);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-05-05 17:06:49 +02:00
|
|
|
int precision= min(max_int_part + decimals, DECIMAL_MAX_PRECISION);
|
2010-08-19 13:55:35 +02:00
|
|
|
fix_char_length(my_decimal_precision_to_length_no_truncation(precision,
|
|
|
|
decimals,
|
|
|
|
unsigned_flag));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Set max_length of if it is maximum length of its arguments.
|
2005-02-08 23:50:45 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
void Item_func::count_only_length()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2010-08-19 13:55:35 +02:00
|
|
|
uint32 char_length= 0;
|
2005-05-05 17:06:49 +02:00
|
|
|
unsigned_flag= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
2005-05-05 17:06:49 +02:00
|
|
|
{
|
2010-08-19 13:55:35 +02:00
|
|
|
set_if_bigger(char_length, args[i]->max_char_length());
|
2005-05-05 17:06:49 +02:00
|
|
|
set_if_bigger(unsigned_flag, args[i]->unsigned_flag);
|
|
|
|
}
|
2010-08-19 13:55:35 +02:00
|
|
|
fix_char_length(char_length);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-02-08 23:50:45 +01:00
|
|
|
Set max_length/decimals of function if function is floating point and
|
2007-10-11 19:29:09 +02:00
|
|
|
result length/precision depends on argument ones.
|
2005-02-08 23:50:45 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
void Item_func::count_real_length()
|
|
|
|
{
|
|
|
|
uint32 length= 0;
|
|
|
|
decimals= 0;
|
|
|
|
max_length= 0;
|
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
|
|
{
|
|
|
|
if (decimals != NOT_FIXED_DEC)
|
|
|
|
{
|
|
|
|
set_if_bigger(decimals, args[i]->decimals);
|
|
|
|
set_if_bigger(length, (args[i]->max_length - args[i]->decimals));
|
|
|
|
}
|
|
|
|
set_if_bigger(max_length, args[i]->max_length);
|
|
|
|
}
|
|
|
|
if (decimals != NOT_FIXED_DEC)
|
|
|
|
{
|
|
|
|
max_length= length;
|
|
|
|
length+= decimals;
|
|
|
|
if (length < max_length) // If previous operation gave overflow
|
|
|
|
max_length= UINT_MAX32;
|
|
|
|
else
|
|
|
|
max_length= length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2004-09-28 19:08:00 +02:00
|
|
|
void Item_func::signal_divide_by_null()
|
|
|
|
{
|
|
|
|
THD *thd= current_thd;
|
|
|
|
if (thd->variables.sql_mode & MODE_ERROR_FOR_DIVISION_BY_ZERO)
|
2009-09-10 11:18:29 +02:00
|
|
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_DIVISION_BY_ZERO,
|
2004-09-28 19:08:00 +02:00
|
|
|
ER(ER_DIVISION_BY_ZERO));
|
|
|
|
null_value= 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-30 17:07:39 +01:00
|
|
|
Item *Item_func::get_tmp_table_item(THD *thd)
|
2003-01-25 01:25:52 +01:00
|
|
|
{
|
2009-12-22 10:52:23 +01:00
|
|
|
if (!with_sum_func && !const_item())
|
2003-01-25 01:25:52 +01:00
|
|
|
return new Item_field(result_field);
|
2003-01-30 17:07:39 +01:00
|
|
|
return copy_or_same(thd);
|
2003-01-25 01:25:52 +01:00
|
|
|
}
|
|
|
|
|
2007-04-28 18:01:01 +02:00
|
|
|
double Item_int_func::val_real()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
|
|
|
|
return unsigned_flag ? (double) ((ulonglong) val_int()) : (double) val_int();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
String *Item_int_func::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong nr=val_int();
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_int(nr, unsigned_flag, collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
2006-04-12 17:31:00 +02:00
|
|
|
void Item_func_connection_id::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
Item_int_func::fix_length_and_dec();
|
|
|
|
max_length= 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Item_func_connection_id::fix_fields(THD *thd, Item **ref)
|
|
|
|
{
|
|
|
|
if (Item_int_func::fix_fields(thd, ref))
|
|
|
|
return TRUE;
|
2007-08-02 11:51:03 +02:00
|
|
|
thd->thread_specific_used= TRUE;
|
2007-08-01 12:27:03 +02:00
|
|
|
value= thd->variables.pseudo_thread_id;
|
2006-04-12 17:31:00 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-06-03 13:43:17 +02:00
|
|
|
Check arguments here to determine result's type for a numeric
|
|
|
|
function of two arguments.
|
2001-09-27 20:45:48 +02:00
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
void Item_num_op::find_num_type(void)
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
DBUG_ENTER("Item_num_op::find_num_type");
|
|
|
|
DBUG_PRINT("info", ("name %s", func_name()));
|
|
|
|
DBUG_ASSERT(arg_count == 2);
|
|
|
|
Item_result r0= args[0]->result_type();
|
|
|
|
Item_result r1= args[1]->result_type();
|
|
|
|
|
|
|
|
if (r0 == REAL_RESULT || r1 == REAL_RESULT ||
|
|
|
|
r0 == STRING_RESULT || r1 ==STRING_RESULT)
|
2001-09-27 20:45:48 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
count_real_length();
|
|
|
|
max_length= float_length(decimals);
|
|
|
|
hybrid_type= REAL_RESULT;
|
|
|
|
}
|
|
|
|
else if (r0 == DECIMAL_RESULT || r1 == DECIMAL_RESULT)
|
|
|
|
{
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
|
|
|
result_precision();
|
|
|
|
}
|
2005-06-03 13:43:17 +02:00
|
|
|
else
|
2001-09-27 20:45:48 +02:00
|
|
|
{
|
2005-06-03 13:43:17 +02:00
|
|
|
DBUG_ASSERT(r0 == INT_RESULT && r1 == INT_RESULT);
|
2005-02-08 23:50:45 +01:00
|
|
|
decimals= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
hybrid_type=INT_RESULT;
|
2005-02-08 23:50:45 +01:00
|
|
|
result_precision();
|
2001-09-27 20:45:48 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
DBUG_PRINT("info", ("Type: %s",
|
|
|
|
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
|
|
|
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
|
|
|
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
|
|
|
"--ILLEGAL!!!--")));
|
|
|
|
DBUG_VOID_RETURN;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-06-03 13:43:17 +02:00
|
|
|
Set result type for a numeric function of one argument
|
|
|
|
(can be also used by a numeric function of many arguments, if the result
|
|
|
|
type depends only on the first argument)
|
2005-02-08 23:50:45 +01:00
|
|
|
*/
|
2005-02-19 17:58:27 +01:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
void Item_func_num1::find_num_type()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_num1::find_num_type");
|
|
|
|
DBUG_PRINT("info", ("name %s", func_name()));
|
2005-02-19 17:58:27 +01:00
|
|
|
switch (hybrid_type= args[0]->result_type()) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case INT_RESULT:
|
2005-02-19 17:58:27 +01:00
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
|
|
|
case REAL_RESULT:
|
|
|
|
hybrid_type= REAL_RESULT;
|
|
|
|
max_length= float_length(decimals);
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
2001-09-27 20:45:48 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
DBUG_PRINT("info", ("Type: %s",
|
|
|
|
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
|
|
|
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
|
|
|
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
|
|
|
"--ILLEGAL!!!--")));
|
|
|
|
DBUG_VOID_RETURN;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
void Item_func_num1::fix_num_length_and_dec()
|
|
|
|
{
|
|
|
|
decimals= args[0]->decimals;
|
|
|
|
max_length= args[0]->max_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_numhybrid::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
fix_num_length_and_dec();
|
|
|
|
find_num_type();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_numhybrid::val_str(String *str)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-02-19 17:58:27 +01:00
|
|
|
switch (hybrid_type) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal decimal_value, *val;
|
|
|
|
if (!(val= decimal_op(&decimal_value)))
|
2005-02-19 17:58:27 +01:00
|
|
|
return 0; // null is set
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal_round(E_DEC_FATAL_ERROR, val, decimals, FALSE, val);
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_charset(collation.collation);
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2string(E_DEC_FATAL_ERROR, val, 0, 0, 0, str);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
{
|
|
|
|
longlong nr= int_op();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_int(nr, unsigned_flag, collation.collation);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case REAL_RESULT:
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
double nr= real_op();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_real(nr, decimals, collation.collation);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
}
|
2005-06-02 16:27:02 +02:00
|
|
|
case STRING_RESULT:
|
|
|
|
return str_op(&str_value);
|
2005-02-08 23:50:45 +01:00
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_numhybrid::val_real()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-02-19 17:58:27 +01:00
|
|
|
switch (hybrid_type) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal decimal_value, *val;
|
|
|
|
double result;
|
2005-02-19 17:58:27 +01:00
|
|
|
if (!(val= decimal_op(&decimal_value)))
|
|
|
|
return 0.0; // null is set
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2double(E_DEC_FATAL_ERROR, val, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
2007-04-28 18:01:01 +02:00
|
|
|
{
|
|
|
|
longlong result= int_op();
|
|
|
|
return unsigned_flag ? (double) ((ulonglong) result) : (double) result;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case REAL_RESULT:
|
|
|
|
return real_op();
|
2005-06-02 16:27:02 +02:00
|
|
|
case STRING_RESULT:
|
|
|
|
{
|
|
|
|
char *end_not_used;
|
|
|
|
int err_not_used;
|
|
|
|
String *res= str_op(&str_value);
|
|
|
|
return (res ? my_strntod(res->charset(), (char*) res->ptr(), res->length(),
|
|
|
|
&end_not_used, &err_not_used) : 0.0);
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_numhybrid::val_int()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-02-19 17:58:27 +01:00
|
|
|
switch (hybrid_type) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal decimal_value, *val;
|
|
|
|
if (!(val= decimal_op(&decimal_value)))
|
2005-02-19 17:58:27 +01:00
|
|
|
return 0; // null is set
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong result;
|
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, val, unsigned_flag, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
return int_op();
|
|
|
|
case REAL_RESULT:
|
2005-11-28 11:52:38 +01:00
|
|
|
return (longlong) rint(real_op());
|
2005-06-02 16:27:02 +02:00
|
|
|
case STRING_RESULT:
|
|
|
|
{
|
|
|
|
int err_not_used;
|
2005-08-29 15:45:03 +02:00
|
|
|
String *res;
|
|
|
|
if (!(res= str_op(&str_value)))
|
|
|
|
return 0;
|
|
|
|
|
2005-06-14 10:40:12 +02:00
|
|
|
char *end= (char*) res->ptr() + res->length();
|
2011-03-03 13:04:04 +01:00
|
|
|
CHARSET_INFO *cs= res->charset();
|
2005-08-29 15:45:03 +02:00
|
|
|
return (*(cs->cset->strtoll10))(cs, res->ptr(), &end, &err_not_used);
|
2005-06-02 16:27:02 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_numhybrid::val_decimal(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
my_decimal *val= decimal_value;
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-02-19 17:58:27 +01:00
|
|
|
switch (hybrid_type) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
val= decimal_op(decimal_value);
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
|
|
|
{
|
|
|
|
longlong result= int_op();
|
|
|
|
int2my_decimal(E_DEC_FATAL_ERROR, result, unsigned_flag, decimal_value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case REAL_RESULT:
|
|
|
|
{
|
2005-09-14 05:25:32 +02:00
|
|
|
double result= (double)real_op();
|
2005-02-08 23:50:45 +01:00
|
|
|
double2my_decimal(E_DEC_FATAL_ERROR, result, decimal_value);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case STRING_RESULT:
|
2005-06-02 16:27:02 +02:00
|
|
|
{
|
2005-08-29 15:45:03 +02:00
|
|
|
String *res;
|
|
|
|
if (!(res= str_op(&str_value)))
|
|
|
|
return NULL;
|
|
|
|
|
2005-06-02 16:27:02 +02:00
|
|
|
str2my_decimal(E_DEC_FATAL_ERROR, (char*) res->ptr(),
|
|
|
|
res->length(), res->charset(), decimal_value);
|
|
|
|
break;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case ROW_RESULT:
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_signed::print(String *str, enum_query_type query_type)
|
2003-10-12 16:56:05 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("cast("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(" as signed)"));
|
2003-10-12 16:56:05 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-29 16:03:34 +02:00
|
|
|
longlong Item_func_signed::val_int_from_str(int *error)
|
|
|
|
{
|
2006-12-04 13:26:05 +01:00
|
|
|
char buff[MAX_FIELD_WIDTH], *end, *start;
|
|
|
|
uint32 length;
|
2005-04-29 16:03:34 +02:00
|
|
|
String tmp(buff,sizeof(buff), &my_charset_bin), *res;
|
|
|
|
longlong value;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
CHARSET_INFO *cs;
|
2005-04-29 16:03:34 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
For a string result, we must first get the string and then convert it
|
|
|
|
to a longlong
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (!(res= args[0]->val_str(&tmp)))
|
|
|
|
{
|
|
|
|
null_value= 1;
|
|
|
|
*error= 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
null_value= 0;
|
2006-12-04 13:26:05 +01:00
|
|
|
start= (char *)res->ptr();
|
|
|
|
length= res->length();
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
cs= res->charset();
|
2006-12-04 13:26:05 +01:00
|
|
|
|
|
|
|
end= start + length;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
value= cs->cset->strtoll10(cs, start, &end, error);
|
2006-12-04 13:26:05 +01:00
|
|
|
if (*error > 0 || end != start+ length)
|
|
|
|
{
|
|
|
|
char err_buff[128];
|
|
|
|
String err_tmp(err_buff,(uint32) sizeof(err_buff), system_charset_info);
|
|
|
|
err_tmp.copy(start, length, system_charset_info);
|
2005-04-29 16:03:34 +02:00
|
|
|
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
|
|
|
ER_TRUNCATED_WRONG_VALUE,
|
|
|
|
ER(ER_TRUNCATED_WRONG_VALUE), "INTEGER",
|
2006-12-04 13:26:05 +01:00
|
|
|
err_tmp.c_ptr());
|
|
|
|
}
|
2005-04-29 16:03:34 +02:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_signed::val_int()
|
|
|
|
{
|
|
|
|
longlong value;
|
|
|
|
int error;
|
|
|
|
|
2007-05-03 22:53:37 +02:00
|
|
|
if (args[0]->cast_to_int_type() != STRING_RESULT ||
|
|
|
|
args[0]->result_as_longlong())
|
2005-04-29 16:03:34 +02:00
|
|
|
{
|
|
|
|
value= args[0]->val_int();
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
value= val_int_from_str(&error);
|
|
|
|
if (value < 0 && error == 0)
|
|
|
|
{
|
|
|
|
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
|
|
|
|
"Cast to signed converted positive out-of-range integer to "
|
|
|
|
"it's negative complement");
|
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_unsigned::print(String *str, enum_query_type query_type)
|
2003-10-12 16:56:05 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("cast("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(" as unsigned)"));
|
2003-10-12 16:56:05 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-29 16:03:34 +02:00
|
|
|
longlong Item_func_unsigned::val_int()
|
|
|
|
{
|
|
|
|
longlong value;
|
|
|
|
int error;
|
|
|
|
|
2006-10-30 06:52:50 +01:00
|
|
|
if (args[0]->cast_to_int_type() == DECIMAL_RESULT)
|
|
|
|
{
|
|
|
|
my_decimal tmp, *dec= args[0]->val_decimal(&tmp);
|
|
|
|
if (!(null_value= args[0]->null_value))
|
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, dec, 1, &value);
|
2007-05-23 14:43:06 +02:00
|
|
|
else
|
|
|
|
value= 0;
|
2006-10-30 06:52:50 +01:00
|
|
|
return value;
|
|
|
|
}
|
2007-05-04 10:27:21 +02:00
|
|
|
else if (args[0]->cast_to_int_type() != STRING_RESULT ||
|
|
|
|
args[0]->result_as_longlong())
|
2005-04-29 16:03:34 +02:00
|
|
|
{
|
|
|
|
value= args[0]->val_int();
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
value= val_int_from_str(&error);
|
|
|
|
if (error < 0)
|
|
|
|
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
|
|
|
|
"Cast to unsigned converted negative integer to it's "
|
|
|
|
"positive complement");
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
String *Item_decimal_typecast::val_str(String *str)
|
|
|
|
{
|
|
|
|
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
|
2005-06-15 16:02:35 +02:00
|
|
|
if (null_value)
|
|
|
|
return NULL;
|
2007-01-29 00:47:35 +01:00
|
|
|
my_decimal2string(E_DEC_FATAL_ERROR, tmp, 0, 0, 0, str);
|
2005-02-08 23:50:45 +01:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_decimal_typecast::val_real()
|
|
|
|
{
|
|
|
|
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
|
|
|
|
double res;
|
2005-06-15 16:02:35 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0.0;
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2double(E_DEC_FATAL_ERROR, tmp, &res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_decimal_typecast::val_int()
|
|
|
|
{
|
|
|
|
my_decimal tmp_buf, *tmp= val_decimal(&tmp_buf);
|
|
|
|
longlong res;
|
2005-06-15 16:02:35 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, tmp, unsigned_flag, &res);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_decimal_typecast::val_decimal(my_decimal *dec)
|
|
|
|
{
|
|
|
|
my_decimal tmp_buf, *tmp= args[0]->val_decimal(&tmp_buf);
|
2006-08-08 13:03:42 +02:00
|
|
|
bool sign;
|
2007-05-11 17:56:22 +02:00
|
|
|
uint precision;
|
|
|
|
|
2005-06-15 16:02:35 +02:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return NULL;
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal_round(E_DEC_FATAL_ERROR, tmp, decimals, FALSE, dec);
|
2006-08-08 13:03:42 +02:00
|
|
|
sign= dec->sign();
|
|
|
|
if (unsigned_flag)
|
|
|
|
{
|
|
|
|
if (sign)
|
|
|
|
{
|
|
|
|
my_decimal_set_zero(dec);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
2007-05-11 17:56:22 +02:00
|
|
|
precision= my_decimal_length_to_precision(max_length,
|
|
|
|
decimals, unsigned_flag);
|
|
|
|
if (precision - decimals < (uint) my_decimal_intg(dec))
|
2006-08-08 13:03:42 +02:00
|
|
|
{
|
2007-05-11 17:56:22 +02:00
|
|
|
max_my_decimal(dec, precision, decimals);
|
2006-08-08 13:03:42 +02:00
|
|
|
dec->sign(sign);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
return dec;
|
|
|
|
|
|
|
|
err:
|
2009-09-10 11:18:29 +02:00
|
|
|
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
2006-08-08 13:03:42 +02:00
|
|
|
ER_WARN_DATA_OUT_OF_RANGE,
|
|
|
|
ER(ER_WARN_DATA_OUT_OF_RANGE),
|
Fix for BUG#11755168 '46895: test "outfile_loaddata" fails (reproducible)'.
In sql_class.cc, 'row_count', of type 'ha_rows', was used as last argument for
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD which is
"Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld".
So 'ha_rows' was used as 'long'.
On SPARC32 Solaris builds, 'long' is 4 bytes and 'ha_rows' is 'longlong' i.e. 8 bytes.
So the printf-like code was reading only the first 4 bytes.
Because the CPU is big-endian, 1LL is 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
so the first four bytes yield 0. So the warning message had "row 0" instead of
"row 1" in test outfile_loaddata.test:
-Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 1
+Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 0
All error-messaging functions which internally invoke some printf-life function
are potential candidate for such mistakes.
One apparently easy way to catch such mistakes is to use
ATTRIBUTE_FORMAT (from my_attribute.h).
But this works only when call site has both:
a) the format as a string literal
b) the types of arguments.
So:
func(ER(ER_BLAH), 10);
will silently not be checked, because ER(ER_BLAH) is not known at
compile time (it is known at run-time, and depends on the chosen
language).
And
func("%s", a va_list argument);
has the same problem, as the *real* type of arguments is not
known at this site at compile time (it's known in some caller).
Moreover,
func(ER(ER_BLAH));
though possibly correct (if ER(ER_BLAH) has no '%' markers), will not
compile (gcc says "error: format not a string literal and no format
arguments").
Consequences:
1) ATTRIBUTE_FORMAT is here added only to functions which in practice
take "string literal" formats: "my_error_reporter" and "print_admin_msg".
2) it cannot be added to the other functions: my_error(),
push_warning_printf(), Table_check_intact::report_error(),
general_log_print().
To do a one-time check of functions listed in (2), the following
"static code analysis" has been done:
1) replace
my_error(ER_xxx, arguments for substitution in format)
with the equivalent
my_printf_error(ER_xxx,ER(ER_xxx), arguments for substitution in
format),
so that we have ER(ER_xxx) and the arguments *in the same call site*
2) add ATTRIBUTE_FORMAT to push_warning_printf(),
Table_check_intact::report_error(), general_log_print()
3) replace ER(xxx) with the hard-coded English text found in
errmsg.txt (like: ER(ER_UNKNOWN_ERROR) is replaced with
"Unknown error"), so that a call site has the format as string literal
4) this way, ATTRIBUTE_FORMAT can effectively do its job
5) compile, fix errors detected by ATTRIBUTE_FORMAT
6) revert steps 1-2-3.
The present patch has no compiler error when submitted again to the
static code analysis above.
It cannot catch all problems though: see Field::set_warning(), in
which a call to push_warning_printf() has a variable error
(thus, not replacable by a string literal); I checked set_warning() calls
by hand though.
See also WL 5883 for one proposal to avoid such bugs from appearing
again in the future.
The issues fixed in the patch are:
a) mismatch in types (like 'int' passed to '%ld')
b) more arguments passed than specified in the format.
This patch resolves mismatches by changing the type/number of arguments,
not by changing error messages of sql/share/errmsg.txt. The latter would be wrong,
per the following old rule: errmsg.txt must be as stable as possible; no insertions
or deletions of messages, no changes of type or number of printf-like format specifiers,
are allowed, as long as the change impacts a message already released in a GA version.
If this rule is not followed:
- Connectors, which use error message numbers, will be confused (by insertions/deletions
of messages)
- using errmsg.sys of MySQL 5.1.n with mysqld of MySQL 5.1.(n+1)
could produce wrong messages or crash; such usage can easily happen if
installing 5.1.(n+1) while /etc/my.cnf still has --language=/path/to/5.1.n/xxx;
or if copying mysqld from 5.1.(n+1) into a 5.1.n installation.
When fixing b), I have verified that the superfluous arguments were not used in the format
in the first 5.1 GA (5.1.30 'bteam@astra04-20081114162938-z8mctjp6st27uobm').
Had they been used, then passing them today, even if the message doesn't use them
anymore, would have been necessary, as explained above.
2011-05-16 22:04:01 +02:00
|
|
|
name, 1L);
|
2005-02-08 23:50:45 +01:00
|
|
|
return dec;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_decimal_typecast::print(String *str, enum_query_type query_type)
|
2005-06-17 16:27:47 +02:00
|
|
|
{
|
2007-05-09 21:17:21 +02:00
|
|
|
char len_buf[20*3 + 1];
|
|
|
|
char *end;
|
|
|
|
|
|
|
|
uint precision= my_decimal_length_to_precision(max_length, decimals,
|
|
|
|
unsigned_flag);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("cast("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2007-05-09 21:17:21 +02:00
|
|
|
str->append(STRING_WITH_LEN(" as decimal("));
|
|
|
|
|
|
|
|
end=int10_to_str(precision, len_buf,10);
|
|
|
|
str->append(len_buf, (uint32) (end - len_buf));
|
|
|
|
|
|
|
|
str->append(',');
|
|
|
|
|
|
|
|
end=int10_to_str(decimals, len_buf,10);
|
|
|
|
str->append(len_buf, (uint32) (end - len_buf));
|
|
|
|
|
|
|
|
str->append(')');
|
|
|
|
str->append(')');
|
2005-06-17 16:27:47 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_plus::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real() + args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value || args[1]->null_value))
|
|
|
|
return 0.0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
longlong Item_func_plus::int_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2010-03-18 11:38:29 +01:00
|
|
|
longlong val0= args[0]->val_int();
|
|
|
|
longlong val1= args[1]->val_int();
|
|
|
|
longlong res= val0 + val1;
|
|
|
|
bool res_unsigned= FALSE;
|
|
|
|
|
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
2005-02-08 23:50:45 +01:00
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
First check whether the result can be represented as a
|
|
|
|
(bool unsigned_flag, longlong value) pair, then check if it is compatible
|
|
|
|
with this Item's unsigned_flag by calling check_integer_overflow().
|
|
|
|
*/
|
|
|
|
if (args[0]->unsigned_flag)
|
|
|
|
{
|
|
|
|
if (args[1]->unsigned_flag || val1 >= 0)
|
|
|
|
{
|
|
|
|
if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
|
|
|
|
goto err;
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* val1 is negative */
|
|
|
|
if ((ulonglong) val0 > (ulonglong) LONGLONG_MAX)
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (args[1]->unsigned_flag)
|
|
|
|
{
|
|
|
|
if (val0 >= 0)
|
|
|
|
{
|
|
|
|
if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) val1))
|
|
|
|
goto err;
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ((ulonglong) val1 > (ulonglong) LONGLONG_MAX)
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (val0 >=0 && val1 >= 0)
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
else if (val0 < 0 && val1 < 0 && res >= 0)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return check_integer_overflow(res, res_unsigned);
|
|
|
|
|
|
|
|
err:
|
|
|
|
return raise_integer_overflow();
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Calculate plus of two decimals.
|
2005-02-19 17:58:27 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@param decimal_value Buffer that can be used to store result
|
2005-02-19 17:58:27 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
|
|
|
0 Value was NULL; In this case null_value is set
|
|
|
|
@retval
|
|
|
|
\# Value of operation as a decimal
|
2005-02-19 17:58:27 +01:00
|
|
|
*/
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_plus::decimal_op(my_decimal *decimal_value)
|
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
my_decimal value1, *val1;
|
|
|
|
my_decimal value2, *val2;
|
|
|
|
val1= args[0]->val_decimal(&value1);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2005-02-19 17:58:27 +01:00
|
|
|
val2= args[1]->val_decimal(&value2);
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[1]->null_value ||
|
2010-03-18 11:38:29 +01:00
|
|
|
check_decimal_overflow(my_decimal_add(E_DEC_FATAL_ERROR &
|
|
|
|
~E_DEC_OVERFLOW,
|
|
|
|
decimal_value,
|
|
|
|
val1, val2)) > 3)))
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-02-08 23:50:45 +01:00
|
|
|
Set precision of results for additive operations (+ and -)
|
|
|
|
*/
|
|
|
|
void Item_func_additive_op::result_precision()
|
|
|
|
{
|
|
|
|
decimals= max(args[0]->decimals, args[1]->decimals);
|
2008-07-30 13:07:37 +02:00
|
|
|
int arg1_int= args[0]->decimal_precision() - args[0]->decimals;
|
|
|
|
int arg2_int= args[1]->decimal_precision() - args[1]->decimals;
|
2009-07-03 09:41:19 +02:00
|
|
|
int precision= max(arg1_int, arg2_int) + 1 + decimals;
|
2005-05-05 17:06:49 +02:00
|
|
|
|
|
|
|
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
|
|
if (result_type() == INT_RESULT)
|
|
|
|
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
|
|
else
|
|
|
|
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
2009-07-03 09:41:19 +02:00
|
|
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
|
|
|
unsigned_flag);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2002-01-30 14:32:48 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2002-01-30 14:32:48 +01:00
|
|
|
The following function is here to allow the user to force
|
|
|
|
subtraction of UNSIGNED BIGINT to return negative values.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Item_func_minus::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
Item_num_op::fix_length_and_dec();
|
|
|
|
if (unsigned_flag &&
|
2003-01-16 01:04:50 +01:00
|
|
|
(current_thd->variables.sql_mode & MODE_NO_UNSIGNED_SUBTRACTION))
|
2002-01-30 14:32:48 +01:00
|
|
|
unsigned_flag=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_minus::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real() - args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value || args[1]->null_value))
|
|
|
|
return 0.0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
longlong Item_func_minus::int_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2010-03-18 11:38:29 +01:00
|
|
|
longlong val0= args[0]->val_int();
|
|
|
|
longlong val1= args[1]->val_int();
|
|
|
|
longlong res= val0 - val1;
|
|
|
|
bool res_unsigned= FALSE;
|
|
|
|
|
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
2005-02-08 23:50:45 +01:00
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
First check whether the result can be represented as a
|
|
|
|
(bool unsigned_flag, longlong value) pair, then check if it is compatible
|
|
|
|
with this Item's unsigned_flag by calling check_integer_overflow().
|
|
|
|
*/
|
|
|
|
if (args[0]->unsigned_flag)
|
|
|
|
{
|
|
|
|
if (args[1]->unsigned_flag)
|
|
|
|
{
|
|
|
|
if ((ulonglong) val0 < (ulonglong) val1)
|
|
|
|
{
|
|
|
|
if (res >= 0)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (val1 >= 0)
|
|
|
|
{
|
|
|
|
if ((ulonglong) val0 > (ulonglong) val1)
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (test_if_sum_overflows_ull((ulonglong) val0, (ulonglong) -val1))
|
|
|
|
goto err;
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (args[1]->unsigned_flag)
|
|
|
|
{
|
|
|
|
if ((ulonglong) (val0 - LONGLONG_MIN) < (ulonglong) val1)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (val0 > 0 && val1 < 0)
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
else if (val0 < 0 && val1 > 0 && res >= 0)
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return check_integer_overflow(res, res_unsigned);
|
|
|
|
|
|
|
|
err:
|
|
|
|
return raise_integer_overflow();
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2001-08-18 13:24:01 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
See Item_func_plus::decimal_op for comments.
|
|
|
|
*/
|
2005-02-19 17:58:27 +01:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_minus::decimal_op(my_decimal *decimal_value)
|
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
my_decimal value1, *val1;
|
|
|
|
my_decimal value2, *val2=
|
|
|
|
|
|
|
|
val1= args[0]->val_decimal(&value1);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2005-02-19 17:58:27 +01:00
|
|
|
val2= args[1]->val_decimal(&value2);
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[1]->null_value ||
|
2010-03-18 11:38:29 +01:00
|
|
|
(check_decimal_overflow(my_decimal_sub(E_DEC_FATAL_ERROR &
|
|
|
|
~E_DEC_OVERFLOW,
|
|
|
|
decimal_value, val1,
|
|
|
|
val2)) > 3))))
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2001-08-18 13:24:01 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_mul::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real() * args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value || args[1]->null_value))
|
2005-02-08 23:50:45 +01:00
|
|
|
return 0.0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
longlong Item_func_mul::int_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2010-03-18 11:38:29 +01:00
|
|
|
longlong a= args[0]->val_int();
|
|
|
|
longlong b= args[1]->val_int();
|
|
|
|
longlong res;
|
|
|
|
ulonglong res0, res1;
|
|
|
|
ulong a0, a1, b0, b1;
|
|
|
|
bool res_unsigned= FALSE;
|
|
|
|
bool a_negative= FALSE, b_negative= FALSE;
|
|
|
|
|
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
2005-02-08 23:50:45 +01:00
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
First check whether the result can be represented as a
|
|
|
|
(bool unsigned_flag, longlong value) pair, then check if it is compatible
|
|
|
|
with this Item's unsigned_flag by calling check_integer_overflow().
|
|
|
|
|
|
|
|
Let a = a1 * 2^32 + a0 and b = b1 * 2^32 + b0. Then
|
|
|
|
a * b = (a1 * 2^32 + a0) * (b1 * 2^32 + b0) = a1 * b1 * 2^64 +
|
|
|
|
+ (a1 * b0 + a0 * b1) * 2^32 + a0 * b0;
|
|
|
|
We can determine if the above sum overflows the ulonglong range by
|
|
|
|
sequentially checking the following conditions:
|
|
|
|
1. If both a1 and b1 are non-zero.
|
|
|
|
2. Otherwise, if (a1 * b0 + a0 * b1) is greater than ULONG_MAX.
|
|
|
|
3. Otherwise, if (a1 * b0 + a0 * b1) * 2^32 + a0 * b0 is greater than
|
|
|
|
ULONGLONG_MAX.
|
|
|
|
|
|
|
|
Since we also have to take the unsigned_flag for a and b into account,
|
|
|
|
it is easier to first work with absolute values and set the
|
|
|
|
correct sign later.
|
|
|
|
*/
|
|
|
|
if (!args[0]->unsigned_flag && a < 0)
|
|
|
|
{
|
|
|
|
a_negative= TRUE;
|
|
|
|
a= -a;
|
|
|
|
}
|
|
|
|
if (!args[1]->unsigned_flag && b < 0)
|
|
|
|
{
|
|
|
|
b_negative= TRUE;
|
|
|
|
b= -b;
|
|
|
|
}
|
|
|
|
|
|
|
|
a0= 0xFFFFFFFFUL & a;
|
|
|
|
a1= ((ulonglong) a) >> 32;
|
|
|
|
b0= 0xFFFFFFFFUL & b;
|
|
|
|
b1= ((ulonglong) b) >> 32;
|
|
|
|
|
|
|
|
if (a1 && b1)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
res1= (ulonglong) a1 * b0 + (ulonglong) a0 * b1;
|
|
|
|
if (res1 > 0xFFFFFFFFUL)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
res1= res1 << 32;
|
|
|
|
res0= (ulonglong) a0 * b0;
|
|
|
|
|
|
|
|
if (test_if_sum_overflows_ull(res1, res0))
|
|
|
|
goto err;
|
|
|
|
res= res1 + res0;
|
|
|
|
|
|
|
|
if (a_negative != b_negative)
|
|
|
|
{
|
|
|
|
if ((ulonglong) res > (ulonglong) LONGLONG_MIN + 1)
|
|
|
|
goto err;
|
|
|
|
res= -res;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
res_unsigned= TRUE;
|
|
|
|
|
|
|
|
return check_integer_overflow(res, res_unsigned);
|
|
|
|
|
|
|
|
err:
|
|
|
|
return raise_integer_overflow();
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** See Item_func_plus::decimal_op for comments. */
|
2005-02-19 17:58:27 +01:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_mul::decimal_op(my_decimal *decimal_value)
|
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
my_decimal value1, *val1;
|
|
|
|
my_decimal value2, *val2;
|
|
|
|
val1= args[0]->val_decimal(&value1);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2005-02-19 17:58:27 +01:00
|
|
|
val2= args[1]->val_decimal(&value2);
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[1]->null_value ||
|
2010-03-18 11:38:29 +01:00
|
|
|
(check_decimal_overflow(my_decimal_mul(E_DEC_FATAL_ERROR &
|
|
|
|
~E_DEC_OVERFLOW,
|
|
|
|
decimal_value, val1,
|
|
|
|
val2)) > 3))))
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
void Item_func_mul::result_precision()
|
|
|
|
{
|
2005-05-05 17:06:49 +02:00
|
|
|
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
|
|
if (result_type() == INT_RESULT)
|
|
|
|
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
|
|
else
|
|
|
|
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
|
|
|
decimals= min(args[0]->decimals + args[1]->decimals, DECIMAL_MAX_SCALE);
|
2008-07-30 13:07:37 +02:00
|
|
|
uint est_prec = args[0]->decimal_precision() + args[1]->decimal_precision();
|
|
|
|
uint precision= min(est_prec, DECIMAL_MAX_PRECISION);
|
2009-07-03 09:41:19 +02:00
|
|
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
|
|
|
unsigned_flag);
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_func_div::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
|
|
|
double val2= args[1]->val_real();
|
2004-09-28 19:08:00 +02:00
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
|
|
|
return 0.0;
|
|
|
|
if (val2 == 0.0)
|
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0.0;
|
2004-09-28 19:08:00 +02:00
|
|
|
}
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(value/val2);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-09-28 19:08:00 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_div::decimal_op(my_decimal *decimal_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
my_decimal value1, *val1;
|
|
|
|
my_decimal value2, *val2;
|
2005-10-26 08:54:15 +02:00
|
|
|
int err;
|
2005-02-19 17:58:27 +01:00
|
|
|
|
|
|
|
val1= args[0]->val_decimal(&value1);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2005-02-19 17:58:27 +01:00
|
|
|
val2= args[1]->val_decimal(&value2);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[1]->null_value))
|
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
if ((err= check_decimal_overflow(my_decimal_div(E_DEC_FATAL_ERROR &
|
|
|
|
~E_DEC_OVERFLOW &
|
|
|
|
~E_DEC_DIV_ZERO,
|
|
|
|
decimal_value,
|
|
|
|
val1, val2,
|
|
|
|
prec_increment))) > 3)
|
2005-10-26 08:54:15 +02:00
|
|
|
{
|
|
|
|
if (err == E_DEC_DIV_ZERO)
|
|
|
|
signal_divide_by_null();
|
|
|
|
null_value= 1;
|
2005-02-08 23:50:45 +01:00
|
|
|
return 0;
|
2001-08-18 13:24:01 +02:00
|
|
|
}
|
2005-10-26 08:54:15 +02:00
|
|
|
return decimal_value;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_div::result_precision()
|
|
|
|
{
|
2008-11-17 16:41:09 +01:00
|
|
|
uint precision=min(args[0]->decimal_precision() +
|
|
|
|
args[1]->decimals + prec_increment,
|
|
|
|
DECIMAL_MAX_PRECISION);
|
|
|
|
|
2005-05-05 17:06:49 +02:00
|
|
|
/* Integer operations keep unsigned_flag if one of arguments is unsigned */
|
|
|
|
if (result_type() == INT_RESULT)
|
|
|
|
unsigned_flag= args[0]->unsigned_flag | args[1]->unsigned_flag;
|
|
|
|
else
|
|
|
|
unsigned_flag= args[0]->unsigned_flag & args[1]->unsigned_flag;
|
|
|
|
decimals= min(args[0]->decimals + prec_increment, DECIMAL_MAX_SCALE);
|
2009-07-03 09:41:19 +02:00
|
|
|
max_length= my_decimal_precision_to_length_no_truncation(precision, decimals,
|
|
|
|
unsigned_flag);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-09-28 19:08:00 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
void Item_func_div::fix_length_and_dec()
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
DBUG_ENTER("Item_func_div::fix_length_and_dec");
|
2005-05-05 17:06:49 +02:00
|
|
|
prec_increment= current_thd->variables.div_precincrement;
|
2005-05-13 11:29:30 +02:00
|
|
|
Item_num_op::fix_length_and_dec();
|
2005-02-19 17:58:27 +01:00
|
|
|
switch(hybrid_type) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case REAL_RESULT:
|
|
|
|
{
|
2005-05-05 17:06:49 +02:00
|
|
|
decimals=max(args[0]->decimals,args[1]->decimals)+prec_increment;
|
2005-02-08 23:50:45 +01:00
|
|
|
set_if_smaller(decimals, NOT_FIXED_DEC);
|
|
|
|
uint tmp=float_length(decimals);
|
2010-12-24 12:05:04 +01:00
|
|
|
if (decimals == NOT_FIXED_DEC)
|
|
|
|
max_length= tmp;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
max_length=args[0]->max_length - args[0]->decimals + decimals;
|
|
|
|
set_if_smaller(max_length,tmp);
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
|
|
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
|
|
|
result_precision();
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
result_precision();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
maybe_null= 1; // devision by zero
|
|
|
|
DBUG_VOID_RETURN;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2002-11-21 01:07:14 +01:00
|
|
|
|
|
|
|
/* Integer division */
|
|
|
|
longlong Item_func_int_div::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2009-10-13 10:31:42 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
Perform division using DECIMAL math if either of the operands has a
|
|
|
|
non-integer type
|
|
|
|
*/
|
|
|
|
if (args[0]->result_type() != INT_RESULT ||
|
|
|
|
args[1]->result_type() != INT_RESULT)
|
|
|
|
{
|
2011-01-14 10:05:14 +01:00
|
|
|
my_decimal tmp;
|
2011-01-14 15:03:37 +01:00
|
|
|
my_decimal *val0p= args[0]->val_decimal(&tmp);
|
|
|
|
if ((null_value= args[0]->null_value))
|
2009-10-13 10:31:42 +02:00
|
|
|
return 0;
|
2011-01-14 15:03:37 +01:00
|
|
|
my_decimal val0= *val0p;
|
|
|
|
|
|
|
|
my_decimal *val1p= args[1]->val_decimal(&tmp);
|
|
|
|
if ((null_value= args[1]->null_value))
|
|
|
|
return 0;
|
|
|
|
my_decimal val1= *val1p;
|
2009-10-13 10:31:42 +02:00
|
|
|
|
2011-01-14 10:05:14 +01:00
|
|
|
int err;
|
2009-10-13 10:31:42 +02:00
|
|
|
if ((err= my_decimal_div(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, &tmp,
|
2011-01-14 10:05:14 +01:00
|
|
|
&val0, &val1, 0)) > 3)
|
2009-10-13 10:31:42 +02:00
|
|
|
{
|
|
|
|
if (err == E_DEC_DIV_ZERO)
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-07-18 11:21:14 +02:00
|
|
|
my_decimal truncated;
|
|
|
|
const bool do_truncate= true;
|
|
|
|
if (my_decimal_round(E_DEC_FATAL_ERROR, &tmp, 0, do_truncate, &truncated))
|
|
|
|
DBUG_ASSERT(false);
|
|
|
|
|
2011-01-14 10:05:14 +01:00
|
|
|
longlong res;
|
2011-07-18 11:21:14 +02:00
|
|
|
if (my_decimal2int(E_DEC_FATAL_ERROR, &truncated, unsigned_flag, &res) &
|
2009-10-13 10:31:42 +02:00
|
|
|
E_DEC_OVERFLOW)
|
2010-03-18 11:38:29 +01:00
|
|
|
raise_integer_overflow();
|
2009-10-13 10:31:42 +02:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2010-03-18 11:38:29 +01:00
|
|
|
longlong val0=args[0]->val_int();
|
|
|
|
longlong val1=args[1]->val_int();
|
|
|
|
bool val0_negative, val1_negative, res_negative;
|
|
|
|
ulonglong uval0, uval1, res;
|
2005-02-19 17:58:27 +01:00
|
|
|
if ((null_value= (args[0]->null_value || args[1]->null_value)))
|
2004-09-28 19:08:00 +02:00
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
if (val1 == 0)
|
2004-09-28 19:08:00 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
2002-11-21 01:07:14 +01:00
|
|
|
return 0;
|
2004-09-28 19:08:00 +02:00
|
|
|
}
|
2010-03-18 11:38:29 +01:00
|
|
|
|
|
|
|
val0_negative= !args[0]->unsigned_flag && val0 < 0;
|
|
|
|
val1_negative= !args[1]->unsigned_flag && val1 < 0;
|
|
|
|
res_negative= val0_negative != val1_negative;
|
|
|
|
uval0= (ulonglong) (val0_negative ? -val0 : val0);
|
|
|
|
uval1= (ulonglong) (val1_negative ? -val1 : val1);
|
|
|
|
res= uval0 / uval1;
|
|
|
|
if (res_negative)
|
|
|
|
{
|
|
|
|
if (res > (ulonglong) LONGLONG_MAX)
|
|
|
|
return raise_integer_overflow();
|
|
|
|
res= (ulonglong) (-(longlong) res);
|
|
|
|
}
|
|
|
|
return check_integer_overflow(res, !res_negative);
|
2002-11-21 01:07:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_int_div::fix_length_and_dec()
|
|
|
|
{
|
2007-09-28 15:46:05 +02:00
|
|
|
Item_result argtype= args[0]->result_type();
|
|
|
|
/* use precision ony for the data type it is applicable for and valid */
|
|
|
|
max_length=args[0]->max_length -
|
|
|
|
(argtype == DECIMAL_RESULT || argtype == INT_RESULT ?
|
|
|
|
args[0]->decimals : 0);
|
2002-11-21 01:07:14 +01:00
|
|
|
maybe_null=1;
|
2005-02-08 23:50:45 +01:00
|
|
|
unsigned_flag=args[0]->unsigned_flag | args[1]->unsigned_flag;
|
2002-11-21 01:07:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong Item_func_mod::int_op()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2010-03-18 11:38:29 +01:00
|
|
|
longlong val0= args[0]->val_int();
|
|
|
|
longlong val1= args[1]->val_int();
|
|
|
|
bool val0_negative, val1_negative;
|
|
|
|
ulonglong uval0, uval1;
|
|
|
|
ulonglong res;
|
2007-04-28 18:01:01 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
|
|
|
return 0; /* purecov: inspected */
|
2010-03-18 11:38:29 +01:00
|
|
|
if (val1 == 0)
|
2005-02-08 23:50:45 +01:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0;
|
|
|
|
}
|
2006-11-15 18:23:07 +01:00
|
|
|
|
2010-03-18 11:38:29 +01:00
|
|
|
/*
|
|
|
|
'%' is calculated by integer division internally. Since dividing
|
|
|
|
LONGLONG_MIN by -1 generates SIGFPE, we calculate using unsigned values and
|
|
|
|
then adjust the sign appropriately.
|
|
|
|
*/
|
|
|
|
val0_negative= !args[0]->unsigned_flag && val0 < 0;
|
|
|
|
val1_negative= !args[1]->unsigned_flag && val1 < 0;
|
|
|
|
uval0= (ulonglong) (val0_negative ? -val0 : val0);
|
|
|
|
uval1= (ulonglong) (val1_negative ? -val1 : val1);
|
|
|
|
res= uval0 % uval1;
|
|
|
|
return check_integer_overflow(val0_negative ? -(longlong) res : res,
|
|
|
|
!val0_negative);
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
double Item_func_mod::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
|
|
|
double val2= args[1]->val_real();
|
2004-09-28 19:08:00 +02:00
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0.0; /* purecov: inspected */
|
2004-09-28 19:08:00 +02:00
|
|
|
if (val2 == 0.0)
|
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0.0;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
return fmod(value,val2);
|
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
my_decimal *Item_func_mod::decimal_op(my_decimal *decimal_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
my_decimal value1, *val1;
|
|
|
|
my_decimal value2, *val2;
|
|
|
|
|
|
|
|
val1= args[0]->val_decimal(&value1);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2005-02-19 17:58:27 +01:00
|
|
|
val2= args[1]->val_decimal(&value2);
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[1]->null_value))
|
|
|
|
return 0;
|
|
|
|
switch (my_decimal_mod(E_DEC_FATAL_ERROR & ~E_DEC_DIV_ZERO, decimal_value,
|
2005-02-19 17:58:27 +01:00
|
|
|
val1, val2)) {
|
2005-02-08 23:50:45 +01:00
|
|
|
case E_DEC_TRUNCATED:
|
|
|
|
case E_DEC_OK:
|
|
|
|
return decimal_value;
|
|
|
|
case E_DEC_DIV_ZERO:
|
2004-09-28 19:08:00 +02:00
|
|
|
signal_divide_by_null();
|
2005-02-08 23:50:45 +01:00
|
|
|
default:
|
2005-02-19 17:58:27 +01:00
|
|
|
null_value= 1;
|
2004-09-28 19:08:00 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
void Item_func_mod::result_precision()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
decimals= max(args[0]->decimals, args[1]->decimals);
|
|
|
|
max_length= max(args[0]->max_length, args[1]->max_length);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_mod::fix_length_and_dec()
|
|
|
|
{
|
2004-10-21 16:52:55 +02:00
|
|
|
Item_num_op::fix_length_and_dec();
|
2006-11-06 23:13:19 +01:00
|
|
|
maybe_null= 1;
|
2007-04-28 18:01:01 +02:00
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_neg::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-02-08 23:50:45 +01:00
|
|
|
null_value= args[0]->null_value;
|
2000-07-31 21:29:14 +02:00
|
|
|
return -value;
|
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong Item_func_neg::int_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong value= args[0]->val_int();
|
2010-03-18 11:38:29 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
|
|
|
if (args[0]->unsigned_flag &&
|
|
|
|
(ulonglong) value > (ulonglong) LONGLONG_MAX + 1)
|
|
|
|
return raise_integer_overflow();
|
|
|
|
return check_integer_overflow(-value, !args[0]->unsigned_flag && value < 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_neg::decimal_op(my_decimal *decimal_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal val, *value= args[0]->val_decimal(&val);
|
|
|
|
if (!(null_value= args[0]->null_value))
|
|
|
|
{
|
|
|
|
my_decimal2decimal(value, decimal_value);
|
|
|
|
my_decimal_neg(decimal_value);
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
2005-05-19 14:59:14 +02:00
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
2004-12-17 10:14:45 +01:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
void Item_func_neg::fix_num_length_and_dec()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
decimals= args[0]->decimals;
|
|
|
|
/* 1 add because sign can appear */
|
|
|
|
max_length= args[0]->max_length + 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-19 17:58:27 +01:00
|
|
|
void Item_func_neg::fix_length_and_dec()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-19 17:58:27 +01:00
|
|
|
DBUG_ENTER("Item_func_neg::fix_length_and_dec");
|
2005-02-08 23:50:45 +01:00
|
|
|
Item_func_num1::fix_length_and_dec();
|
2005-02-19 17:58:27 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
If this is in integer context keep the context as integer if possible
|
|
|
|
(This is how multiplication and other integer functions works)
|
2005-05-03 10:47:27 +02:00
|
|
|
Use val() to get value as arg_type doesn't mean that item is
|
|
|
|
Item_int or Item_real due to existence of Item_param.
|
2005-02-19 17:58:27 +01:00
|
|
|
*/
|
2007-06-16 10:05:07 +02:00
|
|
|
if (hybrid_type == INT_RESULT && args[0]->const_item())
|
2003-08-07 19:42:26 +02:00
|
|
|
{
|
2007-06-16 10:05:07 +02:00
|
|
|
longlong val= args[0]->val_int();
|
|
|
|
if ((ulonglong) val >= (ulonglong) LONGLONG_MIN &&
|
|
|
|
((ulonglong) val != (ulonglong) LONGLONG_MIN ||
|
|
|
|
args[0]->type() != INT_ITEM))
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Ensure that result is converted to DECIMAL, as longlong can't hold
|
|
|
|
the negated number
|
|
|
|
*/
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
|
|
|
DBUG_PRINT("info", ("Type changed: DECIMAL_RESULT"));
|
|
|
|
}
|
2003-08-07 19:42:26 +02:00
|
|
|
}
|
2005-05-05 17:06:49 +02:00
|
|
|
unsigned_flag= 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
DBUG_VOID_RETURN;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double Item_func_abs::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-02-08 23:50:45 +01:00
|
|
|
null_value= args[0]->null_value;
|
2000-07-31 21:29:14 +02:00
|
|
|
return fabs(value);
|
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong Item_func_abs::int_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong value= args[0]->val_int();
|
2007-04-28 18:01:01 +02:00
|
|
|
if ((null_value= args[0]->null_value))
|
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
if (unsigned_flag)
|
|
|
|
return value;
|
|
|
|
/* -LONGLONG_MIN = LONGLONG_MAX + 1 => outside of signed longlong range */
|
|
|
|
if (value == LONGLONG_MIN)
|
|
|
|
return raise_integer_overflow();
|
|
|
|
return (value >= 0) ? value : -value;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_abs::decimal_op(my_decimal *decimal_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal val, *value= args[0]->val_decimal(&val);
|
|
|
|
if (!(null_value= args[0]->null_value))
|
2003-08-07 19:42:26 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2decimal(value, decimal_value);
|
|
|
|
if (decimal_value->sign())
|
|
|
|
my_decimal_neg(decimal_value);
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
2003-08-07 19:42:26 +02:00
|
|
|
}
|
2005-05-19 14:59:14 +02:00
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_abs::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
Item_func_num1::fix_length_and_dec();
|
2007-04-28 18:01:01 +02:00
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** Gateway to natural LOG function. */
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_ln::val_real()
|
2002-07-17 10:11:48 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-10-27 21:45:18 +02:00
|
|
|
if ((null_value= args[0]->null_value))
|
2005-10-17 09:32:22 +02:00
|
|
|
return 0.0;
|
2005-10-27 21:45:18 +02:00
|
|
|
if (value <= 0.0)
|
2005-10-17 09:32:22 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
2002-07-17 10:11:48 +02:00
|
|
|
return 0.0;
|
2005-10-17 09:32:22 +02:00
|
|
|
}
|
2002-07-17 10:11:48 +02:00
|
|
|
return log(value);
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Extended but so slower LOG function.
|
|
|
|
|
|
|
|
We have to check if all values are > zero and first one is not one
|
|
|
|
as these are the cases then result is not a number.
|
2002-07-17 10:11:48 +02:00
|
|
|
*/
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_log::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-10-27 21:45:18 +02:00
|
|
|
if ((null_value= args[0]->null_value))
|
2002-07-17 10:11:48 +02:00
|
|
|
return 0.0;
|
2005-10-27 21:45:18 +02:00
|
|
|
if (value <= 0.0)
|
2005-10-17 09:32:22 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0.0;
|
|
|
|
}
|
2002-07-17 10:11:48 +02:00
|
|
|
if (arg_count == 2)
|
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double value2= args[1]->val_real();
|
2005-10-27 21:45:18 +02:00
|
|
|
if ((null_value= args[1]->null_value))
|
2002-07-17 10:11:48 +02:00
|
|
|
return 0.0;
|
2005-10-27 21:45:18 +02:00
|
|
|
if (value2 <= 0.0 || value == 1.0)
|
2005-10-17 09:32:22 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0.0;
|
|
|
|
}
|
2002-07-17 10:11:48 +02:00
|
|
|
return log(value2) / log(value);
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
return log(value);
|
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_log2::val_real()
|
2002-07-17 10:11:48 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-10-17 09:32:22 +02:00
|
|
|
|
|
|
|
if ((null_value=args[0]->null_value))
|
2002-07-17 10:11:48 +02:00
|
|
|
return 0.0;
|
2005-10-27 21:45:18 +02:00
|
|
|
if (value <= 0.0)
|
2005-10-17 09:32:22 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0.0;
|
|
|
|
}
|
2003-12-19 22:53:14 +01:00
|
|
|
return log(value) / M_LN2;
|
2002-07-17 10:11:48 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_log10::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2005-10-27 21:45:18 +02:00
|
|
|
if ((null_value= args[0]->null_value))
|
2005-10-17 09:32:22 +02:00
|
|
|
return 0.0;
|
2005-10-27 21:45:18 +02:00
|
|
|
if (value <= 0.0)
|
2005-10-17 09:32:22 +02:00
|
|
|
{
|
|
|
|
signal_divide_by_null();
|
|
|
|
return 0.0;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
return log10(value);
|
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_exp::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0; /* purecov: inspected */
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(exp(value));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_sqrt::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=(args[0]->null_value || value < 0)))
|
|
|
|
return 0.0; /* purecov: inspected */
|
|
|
|
return sqrt(value);
|
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_pow::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
|
|
|
double val2= args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=(args[0]->null_value || args[1]->null_value)))
|
|
|
|
return 0.0; /* purecov: inspected */
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(pow(value,val2));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Trigonometric functions
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_acos::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2010-06-25 17:32:59 +02:00
|
|
|
/* One can use this to defer SELECT processing. */
|
|
|
|
DEBUG_SYNC(current_thd, "before_acos_function");
|
2004-02-03 15:21:48 +01:00
|
|
|
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
|
2004-11-11 19:39:35 +01:00
|
|
|
volatile double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
|
|
|
|
return 0.0;
|
2008-02-19 22:33:43 +01:00
|
|
|
return acos(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_asin::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-02-03 15:21:48 +01:00
|
|
|
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
|
2004-11-11 19:39:35 +01:00
|
|
|
volatile double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
|
|
|
|
return 0.0;
|
2008-02-19 22:33:43 +01:00
|
|
|
return asin(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_atan::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0;
|
|
|
|
if (arg_count == 2)
|
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double val2= args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[1]->null_value))
|
|
|
|
return 0.0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(atan2(value,val2));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2008-02-19 22:33:43 +01:00
|
|
|
return atan(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_cos::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0;
|
2008-02-19 22:33:43 +01:00
|
|
|
return cos(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_sin::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0;
|
2008-02-19 22:33:43 +01:00
|
|
|
return sin(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_tan::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(tan(value));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_func_cot::val_real()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
double value= args[0]->val_real();
|
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0.0;
|
|
|
|
return check_float_overflow(1.0 / tan(value));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Shift-functions, same as << and >> in C/C++
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_shift_left::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
uint shift;
|
|
|
|
ulonglong res= ((ulonglong) args[0]->val_int() <<
|
|
|
|
(shift=(uint) args[1]->val_int()));
|
|
|
|
if (args[0]->null_value || args[1]->null_value)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_shift_right::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
uint shift;
|
|
|
|
ulonglong res= (ulonglong) args[0]->val_int() >>
|
|
|
|
(shift=(uint) args[1]->val_int());
|
|
|
|
if (args[0]->null_value || args[1]->null_value)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
return (shift < sizeof(longlong)*8 ? (longlong) res : LL(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_bit_neg::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
ulonglong res= (ulonglong) args[0]->val_int();
|
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0;
|
|
|
|
return ~res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Conversion functions
|
|
|
|
|
|
|
|
void Item_func_integer::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
max_length=args[0]->max_length - args[0]->decimals+1;
|
|
|
|
uint tmp=float_length(decimals);
|
|
|
|
set_if_smaller(max_length,tmp);
|
|
|
|
decimals=0;
|
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
void Item_func_int_val::fix_num_length_and_dec()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2011-03-28 10:35:50 +02:00
|
|
|
ulonglong tmp_max_length= (ulonglong ) args[0]->max_length -
|
|
|
|
(args[0]->decimals ? args[0]->decimals + 1 : 0) + 2;
|
2011-03-28 10:52:47 +02:00
|
|
|
max_length= tmp_max_length > (ulonglong) 4294967295U ?
|
|
|
|
(uint32) 4294967295U : (uint32) tmp_max_length;
|
2005-02-08 23:50:45 +01:00
|
|
|
uint tmp= float_length(decimals);
|
|
|
|
set_if_smaller(max_length,tmp);
|
|
|
|
decimals= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_int_val::find_num_type()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_int_val::find_num_type");
|
|
|
|
DBUG_PRINT("info", ("name %s", func_name()));
|
|
|
|
switch(hybrid_type= args[0]->result_type())
|
|
|
|
{
|
|
|
|
case STRING_RESULT:
|
|
|
|
case REAL_RESULT:
|
|
|
|
hybrid_type= REAL_RESULT;
|
|
|
|
max_length= float_length(decimals);
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
/*
|
|
|
|
-2 because in most high position can't be used any digit for longlong
|
|
|
|
and one position for increasing value during operation
|
|
|
|
*/
|
|
|
|
if ((args[0]->max_length - args[0]->decimals) >=
|
|
|
|
(DECIMAL_LONGLONG_DIGITS - 2))
|
|
|
|
{
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
|
|
|
hybrid_type= INT_RESULT;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
}
|
|
|
|
DBUG_PRINT("info", ("Type: %s",
|
|
|
|
(hybrid_type == REAL_RESULT ? "REAL_RESULT" :
|
|
|
|
hybrid_type == DECIMAL_RESULT ? "DECIMAL_RESULT" :
|
|
|
|
hybrid_type == INT_RESULT ? "INT_RESULT" :
|
|
|
|
"--ILLEGAL!!!--")));
|
|
|
|
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_ceiling::int_op()
|
|
|
|
{
|
2005-03-04 17:35:55 +01:00
|
|
|
longlong result;
|
|
|
|
switch (args[0]->result_type()) {
|
|
|
|
case INT_RESULT:
|
|
|
|
result= args[0]->val_int();
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec;
|
2005-03-04 20:06:00 +01:00
|
|
|
if ((dec= Item_func_ceiling::decimal_op(&dec_buf)))
|
2005-03-04 17:35:55 +01:00
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
|
|
|
|
else
|
|
|
|
result= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
2005-03-04 20:06:00 +01:00
|
|
|
result= (longlong)Item_func_ceiling::real_op();
|
2005-03-04 17:35:55 +01:00
|
|
|
};
|
|
|
|
return result;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
double Item_func_ceiling::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
/*
|
|
|
|
the volatile's for BUG #3051 to calm optimizer down (because of gcc's
|
|
|
|
bug)
|
|
|
|
*/
|
2004-11-11 19:39:35 +01:00
|
|
|
volatile double value= args[0]->val_real();
|
2005-02-08 23:50:45 +01:00
|
|
|
null_value= args[0]->null_value;
|
|
|
|
return ceil(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_ceiling::decimal_op(my_decimal *decimal_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal val, *value= args[0]->val_decimal(&val);
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[0]->null_value ||
|
|
|
|
my_decimal_ceiling(E_DEC_FATAL_ERROR, value,
|
|
|
|
decimal_value) > 1)))
|
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_floor::int_op()
|
|
|
|
{
|
2005-03-04 20:06:00 +01:00
|
|
|
longlong result;
|
|
|
|
switch (args[0]->result_type()) {
|
|
|
|
case INT_RESULT:
|
|
|
|
result= args[0]->val_int();
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec;
|
|
|
|
if ((dec= Item_func_floor::decimal_op(&dec_buf)))
|
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
|
|
|
|
else
|
|
|
|
result= 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
result= (longlong)Item_func_floor::real_op();
|
|
|
|
};
|
|
|
|
return result;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
double Item_func_floor::real_op()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
/*
|
|
|
|
the volatile's for BUG #3051 to calm optimizer down (because of gcc's
|
|
|
|
bug)
|
|
|
|
*/
|
|
|
|
volatile double value= args[0]->val_real();
|
|
|
|
null_value= args[0]->null_value;
|
|
|
|
return floor(value);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_floor::decimal_op(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
my_decimal val, *value= args[0]->val_decimal(&val);
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[0]->null_value ||
|
|
|
|
my_decimal_floor(E_DEC_FATAL_ERROR, value,
|
|
|
|
decimal_value) > 1)))
|
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-05 17:06:49 +02:00
|
|
|
void Item_func_round::fix_length_and_dec()
|
2005-02-08 23:50:45 +01:00
|
|
|
{
|
2007-04-28 18:01:01 +02:00
|
|
|
int decimals_to_set;
|
|
|
|
longlong val1;
|
|
|
|
bool val1_unsigned;
|
|
|
|
|
2005-05-05 17:06:49 +02:00
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
|
|
|
if (!args[1]->const_item())
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-05-05 17:06:49 +02:00
|
|
|
decimals= args[0]->decimals;
|
2009-06-02 08:38:13 +02:00
|
|
|
max_length= float_length(decimals);
|
2007-06-13 18:32:36 +02:00
|
|
|
if (args[0]->result_type() == DECIMAL_RESULT)
|
|
|
|
{
|
|
|
|
max_length++;
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
hybrid_type= REAL_RESULT;
|
2005-05-05 17:06:49 +02:00
|
|
|
return;
|
|
|
|
}
|
2007-04-28 18:01:01 +02:00
|
|
|
|
|
|
|
val1= args[1]->val_int();
|
2011-05-26 12:06:39 +02:00
|
|
|
if ((null_value= args[1]->is_null()))
|
|
|
|
return;
|
|
|
|
|
2007-04-28 18:01:01 +02:00
|
|
|
val1_unsigned= args[1]->unsigned_flag;
|
|
|
|
if (val1 < 0)
|
|
|
|
decimals_to_set= val1_unsigned ? INT_MAX : 0;
|
|
|
|
else
|
|
|
|
decimals_to_set= (val1 > INT_MAX) ? INT_MAX : (int) val1;
|
|
|
|
|
2005-05-05 17:06:49 +02:00
|
|
|
if (args[0]->decimals == NOT_FIXED_DEC)
|
|
|
|
{
|
|
|
|
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
2009-06-02 08:38:13 +02:00
|
|
|
max_length= float_length(decimals);
|
2005-05-05 17:06:49 +02:00
|
|
|
hybrid_type= REAL_RESULT;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2005-07-04 02:42:33 +02:00
|
|
|
switch (args[0]->result_type()) {
|
2005-05-05 17:06:49 +02:00
|
|
|
case REAL_RESULT:
|
|
|
|
case STRING_RESULT:
|
|
|
|
hybrid_type= REAL_RESULT;
|
|
|
|
decimals= min(decimals_to_set, NOT_FIXED_DEC);
|
|
|
|
max_length= float_length(decimals);
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
2007-04-28 18:01:01 +02:00
|
|
|
if ((!decimals_to_set && truncate) || (args[0]->decimal_precision() < DECIMAL_LONGLONG_DIGITS))
|
2005-05-05 17:06:49 +02:00
|
|
|
{
|
2007-04-28 18:01:01 +02:00
|
|
|
int length_can_increase= test(!truncate && (val1 < 0) && !val1_unsigned);
|
2005-07-04 02:42:33 +02:00
|
|
|
max_length= args[0]->max_length + length_can_increase;
|
2005-05-05 17:06:49 +02:00
|
|
|
/* Here we can keep INT_RESULT */
|
|
|
|
hybrid_type= INT_RESULT;
|
|
|
|
decimals= 0;
|
|
|
|
break;
|
|
|
|
}
|
2005-07-04 02:42:33 +02:00
|
|
|
/* fall through */
|
2005-05-05 17:06:49 +02:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
hybrid_type= DECIMAL_RESULT;
|
2007-10-29 12:39:56 +01:00
|
|
|
decimals_to_set= min(DECIMAL_MAX_SCALE, decimals_to_set);
|
2005-05-05 17:06:49 +02:00
|
|
|
int decimals_delta= args[0]->decimals - decimals_to_set;
|
|
|
|
int precision= args[0]->decimal_precision();
|
2005-06-09 12:27:26 +02:00
|
|
|
int length_increase= ((decimals_delta <= 0) || truncate) ? 0:1;
|
|
|
|
|
|
|
|
precision-= decimals_delta - length_increase;
|
2008-01-14 16:16:36 +01:00
|
|
|
decimals= min(decimals_to_set, DECIMAL_MAX_SCALE);
|
2009-07-03 09:41:19 +02:00
|
|
|
max_length= my_decimal_precision_to_length_no_truncation(precision,
|
|
|
|
decimals,
|
|
|
|
unsigned_flag);
|
2005-05-05 17:06:49 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0); /* This result type isn't handled */
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-28 18:01:01 +02:00
|
|
|
double my_double_round(double value, longlong dec, bool dec_unsigned,
|
|
|
|
bool truncate)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-03-10 11:00:19 +01:00
|
|
|
double tmp;
|
2007-04-28 18:01:01 +02:00
|
|
|
bool dec_negative= (dec < 0) && !dec_unsigned;
|
|
|
|
ulonglong abs_dec= dec_negative ? -dec : dec;
|
2003-03-10 11:00:19 +01:00
|
|
|
/*
|
|
|
|
tmp2 is here to avoid return the value with 80 bit precision
|
|
|
|
This will fix that the test round(0.1,1) = round(0.1,1) is true
|
2011-11-15 10:01:29 +01:00
|
|
|
Tagging with volatile is no guarantee, it may still be optimized away...
|
2003-03-10 11:00:19 +01:00
|
|
|
*/
|
|
|
|
volatile double tmp2;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-03-10 11:00:19 +01:00
|
|
|
tmp=(abs_dec < array_elements(log_10) ?
|
|
|
|
log_10[abs_dec] : pow(10.0,(double) abs_dec));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2011-11-15 10:01:29 +01:00
|
|
|
// Pre-compute these, to avoid optimizing away e.g. 'floor(v/tmp) * tmp'.
|
|
|
|
volatile double value_div_tmp= value / tmp;
|
|
|
|
volatile double value_mul_tmp= value * tmp;
|
|
|
|
|
2007-05-08 19:11:46 +02:00
|
|
|
if (dec_negative && my_isinf(tmp))
|
2011-11-15 10:01:29 +01:00
|
|
|
tmp2= 0.0;
|
|
|
|
else if (!dec_negative && my_isinf(value_mul_tmp))
|
2007-04-28 18:01:01 +02:00
|
|
|
tmp2= value;
|
|
|
|
else if (truncate)
|
2002-05-31 14:22:38 +02:00
|
|
|
{
|
2011-11-15 10:01:29 +01:00
|
|
|
if (value >= 0.0)
|
|
|
|
tmp2= dec < 0 ? floor(value_div_tmp) * tmp : floor(value_mul_tmp) / tmp;
|
2002-05-31 14:22:38 +02:00
|
|
|
else
|
2011-11-15 10:01:29 +01:00
|
|
|
tmp2= dec < 0 ? ceil(value_div_tmp) * tmp : ceil(value_mul_tmp) / tmp;
|
2002-05-31 14:22:38 +02:00
|
|
|
}
|
2003-03-10 11:00:19 +01:00
|
|
|
else
|
2011-11-15 10:01:29 +01:00
|
|
|
tmp2=dec < 0 ? rint(value_div_tmp) * tmp : rint(value_mul_tmp) / tmp;
|
|
|
|
|
2003-03-10 11:00:19 +01:00
|
|
|
return tmp2;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-05-19 22:04:08 +02:00
|
|
|
double Item_func_round::real_op()
|
|
|
|
{
|
|
|
|
double value= args[0]->val_real();
|
|
|
|
|
|
|
|
if (!(null_value= args[0]->null_value || args[1]->null_value))
|
2007-04-28 18:01:01 +02:00
|
|
|
return my_double_round(value, args[1]->val_int(), args[1]->unsigned_flag,
|
|
|
|
truncate);
|
2005-05-19 22:04:08 +02:00
|
|
|
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
2007-04-28 18:01:01 +02:00
|
|
|
/*
|
|
|
|
Rounds a given value to a power of 10 specified as the 'to' argument,
|
|
|
|
avoiding overflows when the value is close to the ulonglong range boundary.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static inline ulonglong my_unsigned_round(ulonglong value, ulonglong to)
|
|
|
|
{
|
|
|
|
ulonglong tmp= value / to * to;
|
|
|
|
return (value - tmp < (to >> 1)) ? tmp : tmp + to;
|
|
|
|
}
|
|
|
|
|
2005-05-19 22:04:08 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
longlong Item_func_round::int_op()
|
|
|
|
{
|
|
|
|
longlong value= args[0]->val_int();
|
2007-04-28 18:01:01 +02:00
|
|
|
longlong dec= args[1]->val_int();
|
2005-02-08 23:50:45 +01:00
|
|
|
decimals= 0;
|
2007-04-28 18:01:01 +02:00
|
|
|
ulonglong abs_dec;
|
2005-02-08 23:50:45 +01:00
|
|
|
if ((null_value= args[0]->null_value || args[1]->null_value))
|
|
|
|
return 0;
|
2007-04-28 18:01:01 +02:00
|
|
|
if ((dec >= 0) || args[1]->unsigned_flag)
|
2005-02-08 23:50:45 +01:00
|
|
|
return value; // integer have not digits after point
|
|
|
|
|
|
|
|
abs_dec= -dec;
|
2006-02-07 13:26:35 +01:00
|
|
|
longlong tmp;
|
|
|
|
|
|
|
|
if(abs_dec >= array_elements(log_10_int))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
tmp= log_10_int[abs_dec];
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
if (truncate)
|
2007-04-28 18:01:01 +02:00
|
|
|
value= (unsigned_flag) ?
|
|
|
|
((ulonglong) value / tmp) * tmp : (value / tmp) * tmp;
|
2005-02-08 23:50:45 +01:00
|
|
|
else
|
2007-04-28 18:01:01 +02:00
|
|
|
value= (unsigned_flag || value >= 0) ?
|
|
|
|
my_unsigned_round((ulonglong) value, tmp) :
|
2007-04-28 21:25:31 +02:00
|
|
|
-(longlong) my_unsigned_round((ulonglong) -value, tmp);
|
2006-02-07 13:26:35 +01:00
|
|
|
return value;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_round::decimal_op(my_decimal *decimal_value)
|
|
|
|
{
|
|
|
|
my_decimal val, *value= args[0]->val_decimal(&val);
|
2007-04-28 18:01:01 +02:00
|
|
|
longlong dec= args[1]->val_int();
|
2008-01-14 16:16:36 +01:00
|
|
|
if (dec >= 0 || args[1]->unsigned_flag)
|
2007-10-29 12:39:56 +01:00
|
|
|
dec= min((ulonglong) dec, decimals);
|
2007-04-28 18:01:01 +02:00
|
|
|
else if (dec < INT_MIN)
|
|
|
|
dec= INT_MIN;
|
|
|
|
|
2005-05-19 14:59:14 +02:00
|
|
|
if (!(null_value= (args[0]->null_value || args[1]->null_value ||
|
2007-04-28 21:25:31 +02:00
|
|
|
my_decimal_round(E_DEC_FATAL_ERROR, value, (int) dec,
|
2008-01-14 16:16:36 +01:00
|
|
|
truncate, decimal_value) > 1)))
|
2005-05-19 14:59:14 +02:00
|
|
|
return decimal_value;
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-01-23 18:45:58 +01:00
|
|
|
void Item_func_rand::seed_random(Item *arg)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
TODO: do not do reinit 'rand' for every execute of PS/SP if
|
|
|
|
args[0] is a constant.
|
|
|
|
*/
|
|
|
|
uint32 tmp= (uint32) arg->val_int();
|
|
|
|
randominit(rand, (uint32) (tmp*0x10001L+55555555L),
|
|
|
|
(uint32) (tmp*0x10000001L));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
bool Item_func_rand::fix_fields(THD *thd,Item **ref)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-07-01 06:05:42 +02:00
|
|
|
if (Item_real_func::fix_fields(thd, ref))
|
2004-12-20 10:47:38 +01:00
|
|
|
return TRUE;
|
2004-02-05 11:32:22 +01:00
|
|
|
used_tables_cache|= RAND_TABLE_BIT;
|
2000-07-31 21:29:14 +02:00
|
|
|
if (arg_count)
|
|
|
|
{ // Only use argument once in query
|
2004-10-14 00:53:59 +02:00
|
|
|
/*
|
2005-09-02 15:21:19 +02:00
|
|
|
Allocate rand structure once: we must use thd->stmt_arena
|
2004-10-14 00:53:59 +02:00
|
|
|
to create rand in proper mem_root if it's a prepared statement or
|
|
|
|
stored procedure.
|
2005-08-15 17:15:12 +02:00
|
|
|
|
|
|
|
No need to send a Rand log event if seed was given eg: RAND(seed),
|
|
|
|
as it will be replicated in the query as such.
|
2004-10-14 00:53:59 +02:00
|
|
|
*/
|
|
|
|
if (!rand && !(rand= (struct rand_struct*)
|
2005-09-02 15:21:19 +02:00
|
|
|
thd->stmt_arena->alloc(sizeof(*rand))))
|
2004-10-14 00:53:59 +02:00
|
|
|
return TRUE;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2002-12-03 12:08:25 +01:00
|
|
|
else
|
2002-10-25 00:48:34 +02:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
/*
|
|
|
|
Save the seed only the first time RAND() is used in the query
|
|
|
|
Once events are forwarded rather than recreated,
|
|
|
|
the following can be skipped if inside the slave thread
|
|
|
|
*/
|
2005-08-15 17:15:12 +02:00
|
|
|
if (!thd->rand_used)
|
|
|
|
{
|
|
|
|
thd->rand_used= 1;
|
|
|
|
thd->rand_saved_seed1= thd->rand.seed1;
|
|
|
|
thd->rand_saved_seed2= thd->rand.seed2;
|
|
|
|
}
|
2002-12-03 12:08:25 +01:00
|
|
|
rand= &thd->rand;
|
2002-10-25 00:48:34 +02:00
|
|
|
}
|
2004-10-14 00:53:59 +02:00
|
|
|
return FALSE;
|
2002-12-03 12:08:25 +01:00
|
|
|
}
|
|
|
|
|
2004-03-16 19:19:36 +01:00
|
|
|
void Item_func_rand::update_used_tables()
|
|
|
|
{
|
|
|
|
Item_real_func::update_used_tables();
|
|
|
|
used_tables_cache|= RAND_TABLE_BIT;
|
|
|
|
}
|
|
|
|
|
2002-12-03 12:08:25 +01:00
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_rand::val_real()
|
2002-12-03 12:08:25 +01:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2009-05-18 06:21:25 +02:00
|
|
|
if (arg_count)
|
|
|
|
{
|
|
|
|
if (!args[0]->const_item())
|
|
|
|
seed_random(args[0]);
|
|
|
|
else if (first_eval)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Constantness of args[0] may be set during JOIN::optimize(), if arg[0]
|
|
|
|
is a field item of "constant" table. Thus, we have to evaluate
|
|
|
|
seed_random() for constant arg there but not at the fix_fields method.
|
|
|
|
*/
|
|
|
|
first_eval= FALSE;
|
|
|
|
seed_random(args[0]);
|
|
|
|
}
|
|
|
|
}
|
2003-03-18 22:14:02 +01:00
|
|
|
return my_rnd(rand);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_sign::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
null_value=args[0]->null_value;
|
|
|
|
return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_units::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double value= args[0]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((null_value=args[0]->null_value))
|
|
|
|
return 0;
|
2010-03-18 11:38:29 +01:00
|
|
|
return check_float_overflow(value * mul + add);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_min_max::fix_length_and_dec()
|
|
|
|
{
|
2005-05-05 17:06:49 +02:00
|
|
|
int max_int_part=0;
|
2007-05-04 16:57:10 +02:00
|
|
|
bool datetime_found= FALSE;
|
2000-07-31 21:29:14 +02:00
|
|
|
decimals=0;
|
|
|
|
max_length=0;
|
2005-08-27 07:25:45 +02:00
|
|
|
maybe_null=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
cmp_type=args[0]->result_type();
|
2003-03-04 15:01:59 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
set_if_bigger(max_length, args[i]->max_length);
|
|
|
|
set_if_bigger(decimals, args[i]->decimals);
|
2005-05-05 17:06:49 +02:00
|
|
|
set_if_bigger(max_int_part, args[i]->decimal_int_part());
|
2005-08-27 07:25:45 +02:00
|
|
|
if (args[i]->maybe_null)
|
|
|
|
maybe_null=1;
|
2000-07-31 21:29:14 +02:00
|
|
|
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
|
2007-05-04 16:57:10 +02:00
|
|
|
if (args[i]->result_type() != ROW_RESULT && args[i]->is_datetime())
|
|
|
|
{
|
|
|
|
datetime_found= TRUE;
|
|
|
|
if (!datetime_item || args[i]->field_type() == MYSQL_TYPE_DATETIME)
|
|
|
|
datetime_item= args[i];
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-07-04 17:19:07 +02:00
|
|
|
if (cmp_type == STRING_RESULT)
|
2007-05-04 16:57:10 +02:00
|
|
|
{
|
2011-04-08 15:15:23 +02:00
|
|
|
agg_arg_charsets_for_string_result_with_comparison(collation,
|
|
|
|
args, arg_count);
|
2007-05-04 16:57:10 +02:00
|
|
|
if (datetime_found)
|
|
|
|
{
|
|
|
|
thd= current_thd;
|
|
|
|
compare_as_dates= TRUE;
|
|
|
|
}
|
|
|
|
}
|
2005-05-05 17:06:49 +02:00
|
|
|
else if ((cmp_type == DECIMAL_RESULT) || (cmp_type == INT_RESULT))
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
{
|
|
|
|
collation.set_numeric();
|
|
|
|
fix_char_length(my_decimal_precision_to_length_no_truncation(max_int_part +
|
|
|
|
decimals,
|
|
|
|
decimals,
|
|
|
|
unsigned_flag));
|
|
|
|
}
|
Bug #54461: crash with longblob and union or update with subquery
Queries may crash, if
1) the GREATEST or the LEAST function has a mixed list of
numeric and LONGBLOB arguments and
2) the result of such a function goes through an intermediate
temporary table.
An Item that references a LONGBLOB field has max_length of
UINT_MAX32 == (2^32 - 1).
The current implementation of GREATEST/LEAST returns REAL
result for a mixed list of numeric and string arguments (that
contradicts with the current documentation, this contradiction
was discussed and it was decided to update the documentation).
The max_length of such a function call was calculated as a
maximum of argument max_length values (i.e. UINT_MAX32).
That max_length value of UINT_MAX32 was used as a length for
the intermediate temporary table Field_double to hold
GREATEST/LEAST function result.
The Field_double::val_str() method call on that field
allocates a String value.
Since an allocation of String reserves an additional byte
for a zero-termination, the size of String buffer was
set to (UINT_MAX32 + 1), that caused an integer overflow:
actually, an empty buffer of size 0 was allocated.
An initialization of the "first" byte of that zero-size
buffer with '\0' caused a crash.
The Item_func_min_max::fix_length_and_dec() has been
modified to calculate max_length for the REAL result like
we do it for arithmetical operators.
******
Bug #54461: crash with longblob and union or update with subquery
Queries may crash, if
1) the GREATEST or the LEAST function has a mixed list of
numeric and LONGBLOB arguments and
2) the result of such a function goes through an intermediate
temporary table.
An Item that references a LONGBLOB field has max_length of
UINT_MAX32 == (2^32 - 1).
The current implementation of GREATEST/LEAST returns REAL
result for a mixed list of numeric and string arguments (that
contradicts with the current documentation, this contradiction
was discussed and it was decided to update the documentation).
The max_length of such a function call was calculated as a
maximum of argument max_length values (i.e. UINT_MAX32).
That max_length value of UINT_MAX32 was used as a length for
the intermediate temporary table Field_double to hold
GREATEST/LEAST function result.
The Field_double::val_str() method call on that field
allocates a String value.
Since an allocation of String reserves an additional byte
for a zero-termination, the size of String buffer was
set to (UINT_MAX32 + 1), that caused an integer overflow:
actually, an empty buffer of size 0 was allocated.
An initialization of the "first" byte of that zero-size
buffer with '\0' caused a crash.
The Item_func_min_max::fix_length_and_dec() has been
modified to calculate max_length for the REAL result like
we do it for arithmetical operators.
2010-08-01 20:12:36 +02:00
|
|
|
else if (cmp_type == REAL_RESULT)
|
2010-08-20 13:22:46 +02:00
|
|
|
fix_char_length(float_length(decimals));
|
2007-09-22 09:49:27 +02:00
|
|
|
cached_field_type= agg_field_type(args, arg_count);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-05-04 16:57:10 +02:00
|
|
|
/*
|
|
|
|
Compare item arguments in the DATETIME context.
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
cmp_datetimes()
|
|
|
|
value [out] found least/greatest DATE/DATETIME value
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
Compare item arguments as DATETIME values and return the index of the
|
|
|
|
least/greatest argument in the arguments array.
|
|
|
|
The correct integer DATE/DATETIME value of the found argument is
|
|
|
|
stored to the value pointer, if latter is provided.
|
|
|
|
|
|
|
|
RETURN
|
2010-08-20 10:52:16 +02:00
|
|
|
0 If one of arguments is NULL or there was a execution error
|
2007-05-04 16:57:10 +02:00
|
|
|
# index of the least/greatest argument
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint Item_func_min_max::cmp_datetimes(ulonglong *value)
|
|
|
|
{
|
2009-08-28 17:51:31 +02:00
|
|
|
longlong UNINIT_VAR(min_max);
|
2007-05-04 16:57:10 +02:00
|
|
|
uint min_max_idx= 0;
|
|
|
|
|
|
|
|
for (uint i=0; i < arg_count ; i++)
|
|
|
|
{
|
|
|
|
Item **arg= args + i;
|
|
|
|
bool is_null;
|
2008-11-26 09:28:17 +01:00
|
|
|
longlong res= get_datetime_value(thd, &arg, 0, datetime_item, &is_null);
|
2010-08-20 10:52:16 +02:00
|
|
|
|
|
|
|
/* Check if we need to stop (because of error or KILL) and stop the loop */
|
|
|
|
if (thd->is_error())
|
|
|
|
{
|
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-05-04 16:57:10 +02:00
|
|
|
if ((null_value= args[i]->null_value))
|
|
|
|
return 0;
|
|
|
|
if (i == 0 || (res < min_max ? cmp_sign : -cmp_sign) > 0)
|
|
|
|
{
|
|
|
|
min_max= res;
|
|
|
|
min_max_idx= i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (value)
|
|
|
|
{
|
|
|
|
*value= min_max;
|
|
|
|
if (datetime_item->field_type() == MYSQL_TYPE_DATE)
|
|
|
|
*value/= 1000000L;
|
|
|
|
}
|
|
|
|
return min_max_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
String *Item_func_min_max::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2007-05-04 16:57:10 +02:00
|
|
|
if (compare_as_dates)
|
|
|
|
{
|
|
|
|
String *str_res;
|
|
|
|
uint min_max_idx= cmp_datetimes(NULL);
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
|
|
|
str_res= args[min_max_idx]->val_str(str);
|
2010-08-20 10:52:16 +02:00
|
|
|
if (args[min_max_idx]->null_value)
|
|
|
|
{
|
|
|
|
// check if the call to val_str() above returns a NULL value
|
|
|
|
null_value= 1;
|
|
|
|
return NULL;
|
|
|
|
}
|
2007-05-04 16:57:10 +02:00
|
|
|
str_res->set_charset(collation.collation);
|
|
|
|
return str_res;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
switch (cmp_type) {
|
|
|
|
case INT_RESULT:
|
|
|
|
{
|
|
|
|
longlong nr=val_int();
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_int(nr, unsigned_flag, collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec_val= val_decimal(&dec_buf);
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
|
|
|
my_decimal2string(E_DEC_FATAL_ERROR, dec_val, 0, 0, 0, str);
|
|
|
|
return str;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
case REAL_RESULT:
|
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double nr= val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_real(nr, decimals, collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
case STRING_RESULT:
|
|
|
|
{
|
2009-08-28 17:51:31 +02:00
|
|
|
String *UNINIT_VAR(res);
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint i=0; i < arg_count ; i++)
|
|
|
|
{
|
2005-08-27 07:25:45 +02:00
|
|
|
if (i == 0)
|
2000-07-31 21:29:14 +02:00
|
|
|
res=args[i]->val_str(str);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
String *res2;
|
|
|
|
res2= args[i]->val_str(res == str ? &tmp_value : str);
|
|
|
|
if (res2)
|
|
|
|
{
|
2003-08-05 09:52:37 +02:00
|
|
|
int cmp= sortcmp(res,res2,collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
if ((cmp_sign < 0 ? cmp : -cmp) < 0)
|
|
|
|
res=res2;
|
|
|
|
}
|
|
|
|
}
|
2005-08-27 07:25:45 +02:00
|
|
|
if ((null_value= args[i]->null_value))
|
2005-10-06 16:54:43 +02:00
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-10-06 16:54:43 +02:00
|
|
|
res->set_charset(collation.collation);
|
2000-07-31 21:29:14 +02:00
|
|
|
return res;
|
|
|
|
}
|
2003-02-17 15:06:51 +01:00
|
|
|
case ROW_RESULT:
|
2003-01-31 11:07:07 +01:00
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2002-11-15 19:32:09 +01:00
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return 0; // Keep compiler happy
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_min_max::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
double value=0.0;
|
2007-05-04 16:57:10 +02:00
|
|
|
if (compare_as_dates)
|
|
|
|
{
|
2007-05-07 16:24:46 +02:00
|
|
|
ulonglong result= 0;
|
2007-05-04 16:57:10 +02:00
|
|
|
(void)cmp_datetimes(&result);
|
|
|
|
return (double)result;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint i=0; i < arg_count ; i++)
|
|
|
|
{
|
2005-08-27 07:25:45 +02:00
|
|
|
if (i == 0)
|
2004-11-11 19:39:35 +01:00
|
|
|
value= args[i]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double tmp= args[i]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
|
|
|
|
value=tmp;
|
|
|
|
}
|
2005-08-27 07:25:45 +02:00
|
|
|
if ((null_value= args[i]->null_value))
|
|
|
|
break;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_min_max::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong value=0;
|
2007-05-04 16:57:10 +02:00
|
|
|
if (compare_as_dates)
|
|
|
|
{
|
2007-05-08 08:42:40 +02:00
|
|
|
ulonglong result= 0;
|
2007-05-04 16:57:10 +02:00
|
|
|
(void)cmp_datetimes(&result);
|
|
|
|
return (longlong)result;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
for (uint i=0; i < arg_count ; i++)
|
|
|
|
{
|
2005-08-27 07:25:45 +02:00
|
|
|
if (i == 0)
|
2006-09-13 12:41:28 +02:00
|
|
|
value=args[i]->val_int();
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
|
|
|
{
|
2006-09-13 12:41:28 +02:00
|
|
|
longlong tmp=args[i]->val_int();
|
|
|
|
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
|
|
|
|
value=tmp;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2006-09-13 13:18:14 +02:00
|
|
|
if ((null_value= args[i]->null_value))
|
|
|
|
break;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
my_decimal *Item_func_min_max::val_decimal(my_decimal *dec)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2009-08-28 17:51:31 +02:00
|
|
|
my_decimal tmp_buf, *tmp, *UNINIT_VAR(res);
|
2005-10-06 16:54:43 +02:00
|
|
|
|
2007-05-04 16:57:10 +02:00
|
|
|
if (compare_as_dates)
|
|
|
|
{
|
2007-05-08 08:42:40 +02:00
|
|
|
ulonglong value= 0;
|
2007-05-04 16:57:10 +02:00
|
|
|
(void)cmp_datetimes(&value);
|
|
|
|
ulonglong2decimal(value, dec);
|
|
|
|
return dec;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
for (uint i=0; i < arg_count ; i++)
|
|
|
|
{
|
2005-08-27 07:25:45 +02:00
|
|
|
if (i == 0)
|
2005-02-08 23:50:45 +01:00
|
|
|
res= args[i]->val_decimal(dec);
|
|
|
|
else
|
|
|
|
{
|
2005-10-06 16:54:43 +02:00
|
|
|
tmp= args[i]->val_decimal(&tmp_buf); // Zero if NULL
|
|
|
|
if (tmp && (my_decimal_cmp(tmp, res) * cmp_sign) < 0)
|
2005-02-08 23:50:45 +01:00
|
|
|
{
|
|
|
|
if (tmp == &tmp_buf)
|
|
|
|
{
|
2005-10-06 16:54:43 +02:00
|
|
|
/* Move value out of tmp_buf as this will be reused on next loop */
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal2decimal(tmp, dec);
|
|
|
|
res= dec;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
res= tmp;
|
|
|
|
}
|
|
|
|
}
|
2005-08-27 07:25:45 +02:00
|
|
|
if ((null_value= args[i]->null_value))
|
2005-10-06 16:54:43 +02:00
|
|
|
{
|
|
|
|
res= 0;
|
2005-08-27 07:25:45 +02:00
|
|
|
break;
|
2005-10-06 16:54:43 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_length::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
|
|
|
if (!res)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
return (longlong) res->length();
|
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_char_length::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
|
|
|
if (!res)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
}
|
|
|
|
null_value=0;
|
2003-03-13 12:34:46 +01:00
|
|
|
return (longlong) res->numchars();
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2003-02-28 16:22:20 +01:00
|
|
|
longlong Item_func_coercibility::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-02-28 16:22:20 +01:00
|
|
|
null_value= 0;
|
2003-08-05 09:52:37 +02:00
|
|
|
return (longlong) args[0]->collation.derivation;
|
2003-02-28 16:22:20 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2003-06-25 12:07:20 +02:00
|
|
|
void Item_func_locate::fix_length_and_dec()
|
|
|
|
{
|
2007-03-09 06:05:08 +01:00
|
|
|
max_length= MY_INT32_NUM_DECIMAL_DIGITS;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
agg_arg_charsets_for_comparison(cmp_collation, args, 2);
|
2003-06-25 12:07:20 +02:00
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_locate::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *a=args[0]->val_str(&value1);
|
|
|
|
String *b=args[1]->val_str(&value2);
|
|
|
|
if (!a || !b)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
}
|
|
|
|
null_value=0;
|
2006-11-08 16:11:02 +01:00
|
|
|
/* must be longlong to avoid truncation */
|
|
|
|
longlong start= 0;
|
|
|
|
longlong start0= 0;
|
2003-09-25 10:35:21 +02:00
|
|
|
my_match_t match;
|
2003-09-19 12:18:19 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
if (arg_count == 3)
|
|
|
|
{
|
2006-11-08 16:11:02 +01:00
|
|
|
start0= start= args[2]->val_int() - 1;
|
|
|
|
|
|
|
|
if ((start < 0) || (start > a->length()))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* start is now sufficiently valid to pass to charpos function */
|
2006-11-30 02:40:42 +01:00
|
|
|
start= a->charpos((int) start);
|
2006-11-08 16:11:02 +01:00
|
|
|
|
|
|
|
if (start + b->length() > a->length())
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
2003-09-19 12:18:19 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!b->length()) // Found empty string at start
|
2006-11-08 16:11:02 +01:00
|
|
|
return start + 1;
|
2003-09-19 12:18:19 +02:00
|
|
|
|
2003-09-25 10:35:21 +02:00
|
|
|
if (!cmp_collation.collation->coll->instr(cmp_collation.collation,
|
2006-11-30 02:40:42 +01:00
|
|
|
a->ptr()+start,
|
|
|
|
(uint) (a->length()-start),
|
2003-09-25 10:35:21 +02:00
|
|
|
b->ptr(), b->length(),
|
|
|
|
&match, 1))
|
|
|
|
return 0;
|
2006-12-14 23:51:37 +01:00
|
|
|
return (longlong) match.mb_len + start0 + 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_locate::print(String *str, enum_query_type query_type)
|
2003-10-30 11:57:26 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("locate("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[1]->print(str, query_type);
|
2003-10-30 11:57:26 +01:00
|
|
|
str->append(',');
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2003-10-30 11:57:26 +01:00
|
|
|
if (arg_count == 3)
|
|
|
|
{
|
|
|
|
str->append(',');
|
2008-02-22 11:30:33 +01:00
|
|
|
args[2]->print(str, query_type);
|
2003-10-30 11:57:26 +01:00
|
|
|
}
|
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_field::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-06-01 18:48:25 +02:00
|
|
|
|
2003-07-03 16:24:38 +02:00
|
|
|
if (cmp_type == STRING_RESULT)
|
|
|
|
{
|
|
|
|
String *field;
|
2005-06-02 03:08:39 +02:00
|
|
|
if (!(field= args[0]->val_str(&value)))
|
|
|
|
return 0;
|
2003-07-15 14:33:00 +02:00
|
|
|
for (uint i=1 ; i < arg_count ; i++)
|
2003-07-03 16:24:38 +02:00
|
|
|
{
|
|
|
|
String *tmp_value=args[i]->val_str(&tmp);
|
2003-08-05 08:26:31 +02:00
|
|
|
if (tmp_value && !sortcmp(field,tmp_value,cmp_collation.collation))
|
2003-07-15 14:33:00 +02:00
|
|
|
return (longlong) (i);
|
2003-07-03 16:24:38 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (cmp_type == INT_RESULT)
|
|
|
|
{
|
2003-07-15 14:33:00 +02:00
|
|
|
longlong val= args[0]->val_int();
|
2005-06-02 15:45:20 +02:00
|
|
|
if (args[0]->null_value)
|
|
|
|
return 0;
|
2003-07-15 14:33:00 +02:00
|
|
|
for (uint i=1; i < arg_count ; i++)
|
2003-07-03 16:24:38 +02:00
|
|
|
{
|
2005-06-03 22:46:03 +02:00
|
|
|
if (val == args[i]->val_int() && !args[i]->null_value)
|
2005-06-02 01:13:24 +02:00
|
|
|
return (longlong) (i);
|
2003-07-03 16:24:38 +02:00
|
|
|
}
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
else if (cmp_type == DECIMAL_RESULT)
|
|
|
|
{
|
|
|
|
my_decimal dec_arg_buf, *dec_arg,
|
|
|
|
dec_buf, *dec= args[0]->val_decimal(&dec_buf);
|
2005-06-02 15:45:20 +02:00
|
|
|
if (args[0]->null_value)
|
|
|
|
return 0;
|
2005-02-08 23:50:45 +01:00
|
|
|
for (uint i=1; i < arg_count; i++)
|
|
|
|
{
|
|
|
|
dec_arg= args[i]->val_decimal(&dec_arg_buf);
|
2005-06-06 23:31:53 +02:00
|
|
|
if (!args[i]->null_value && !my_decimal_cmp(dec_arg, dec))
|
2005-02-08 23:50:45 +01:00
|
|
|
return (longlong) (i);
|
|
|
|
}
|
|
|
|
}
|
2003-07-03 16:24:38 +02:00
|
|
|
else
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-11 19:39:35 +01:00
|
|
|
double val= args[0]->val_real();
|
2005-06-02 15:45:20 +02:00
|
|
|
if (args[0]->null_value)
|
|
|
|
return 0;
|
2003-07-15 14:33:00 +02:00
|
|
|
for (uint i=1; i < arg_count ; i++)
|
2003-07-03 16:24:38 +02:00
|
|
|
{
|
2005-06-07 04:43:59 +02:00
|
|
|
if (val == args[i]->val_real() && !args[i]->null_value)
|
2005-06-01 18:48:25 +02:00
|
|
|
return (longlong) (i);
|
2003-07-03 16:24:38 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-08-07 19:42:26 +02:00
|
|
|
|
2003-07-03 16:24:38 +02:00
|
|
|
void Item_func_field::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
maybe_null=0; max_length=3;
|
2003-07-15 14:33:00 +02:00
|
|
|
cmp_type= args[0]->result_type();
|
|
|
|
for (uint i=1; i < arg_count ; i++)
|
2003-07-03 16:24:38 +02:00
|
|
|
cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
|
|
|
|
if (cmp_type == STRING_RESULT)
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count);
|
2003-01-29 09:38:56 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-02-07 14:47:24 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_ascii::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
|
|
|
if (!res)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
return (longlong) (res->length() ? (uchar) (*res)[0] : (uchar) 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_ord::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
|
|
|
if (!res)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
if (!res->length()) return 0;
|
|
|
|
#ifdef USE_MB
|
2003-03-13 12:34:46 +01:00
|
|
|
if (use_mb(res->charset()))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
register const char *str=res->ptr();
|
2002-03-19 17:03:10 +01:00
|
|
|
register uint32 n=0, l=my_ismbchar(res->charset(),str,str+res->length());
|
2002-08-30 11:40:40 +02:00
|
|
|
if (!l)
|
|
|
|
return (longlong)((uchar) *str);
|
2000-07-31 21:29:14 +02:00
|
|
|
while (l--)
|
|
|
|
n=(n<<8)|(uint32)((uchar) *str++);
|
|
|
|
return (longlong) n;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return (longlong) ((uchar) (*res)[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Search after a string in a string of strings separated by ',' */
|
|
|
|
/* Returns number of found type >= 1 or 0 if not found */
|
|
|
|
/* This optimizes searching in enums to bit testing! */
|
|
|
|
|
|
|
|
void Item_func_find_in_set::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
decimals=0;
|
|
|
|
max_length=3; // 1-999
|
|
|
|
if (args[0]->const_item() && args[1]->type() == FIELD_ITEM)
|
|
|
|
{
|
|
|
|
Field *field= ((Item_field*) args[1])->field;
|
2006-12-02 02:26:52 +01:00
|
|
|
if (field->real_type() == MYSQL_TYPE_SET)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
String *find=args[0]->val_str(&value);
|
|
|
|
if (find)
|
|
|
|
{
|
2011-03-04 15:46:17 +01:00
|
|
|
// find is not NULL pointer so args[0] is not a null-value
|
|
|
|
DBUG_ASSERT(!args[0]->null_value);
|
2003-11-03 13:01:59 +01:00
|
|
|
enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
|
|
|
|
find->length(), 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
enum_bit=0;
|
|
|
|
if (enum_value)
|
|
|
|
enum_bit=LL(1) << (enum_value-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
agg_arg_charsets_for_comparison(cmp_collation, args, 2);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static const char separator=',';
|
|
|
|
|
|
|
|
longlong Item_func_find_in_set::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (enum_value)
|
|
|
|
{
|
2011-03-04 15:46:17 +01:00
|
|
|
// enum_value is set iff args[0]->const_item() in fix_length_and_dec().
|
|
|
|
DBUG_ASSERT(args[0]->const_item());
|
|
|
|
|
|
|
|
ulonglong tmp= (ulonglong) args[1]->val_int();
|
|
|
|
null_value= args[1]->null_value;
|
|
|
|
/*
|
|
|
|
No need to check args[0]->null_value since enum_value is set iff
|
|
|
|
args[0] is a non-null const item. Note: no DBUG_ASSERT on
|
|
|
|
args[0]->null_value here because args[0] may have been replaced
|
|
|
|
by an Item_cache on which val_int() has not been called. See
|
|
|
|
BUG#11766317
|
|
|
|
*/
|
|
|
|
if (!null_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
if (tmp & enum_bit)
|
2011-03-04 15:46:17 +01:00
|
|
|
return enum_value;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return 0L;
|
|
|
|
}
|
|
|
|
|
|
|
|
String *find=args[0]->val_str(&value);
|
|
|
|
String *buffer=args[1]->val_str(&value2);
|
|
|
|
if (!find || !buffer)
|
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0; /* purecov: inspected */
|
|
|
|
}
|
|
|
|
null_value=0;
|
|
|
|
|
|
|
|
int diff;
|
|
|
|
if ((diff=buffer->length() - find->length()) >= 0)
|
|
|
|
{
|
2009-04-23 09:50:34 +02:00
|
|
|
my_wc_t wc= 0;
|
2004-08-24 18:18:59 +02:00
|
|
|
CHARSET_INFO *cs= cmp_collation.collation;
|
|
|
|
const char *str_begin= buffer->ptr();
|
|
|
|
const char *str_end= buffer->ptr();
|
|
|
|
const char *real_end= str_end+buffer->length();
|
|
|
|
const uchar *find_str= (const uchar *) find->ptr();
|
|
|
|
uint find_str_len= find->length();
|
|
|
|
int position= 0;
|
|
|
|
while (1)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-08-24 18:18:59 +02:00
|
|
|
int symbol_len;
|
|
|
|
if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end,
|
|
|
|
(uchar*) real_end)) > 0)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-08-24 18:18:59 +02:00
|
|
|
const char *substr_end= str_end + symbol_len;
|
|
|
|
bool is_last_item= (substr_end == real_end);
|
2004-09-11 13:48:23 +02:00
|
|
|
bool is_separator= (wc == (my_wc_t) separator);
|
|
|
|
if (is_separator || is_last_item)
|
2004-08-24 18:18:59 +02:00
|
|
|
{
|
|
|
|
position++;
|
2004-09-11 13:48:23 +02:00
|
|
|
if (is_last_item && !is_separator)
|
2004-08-24 18:18:59 +02:00
|
|
|
str_end= substr_end;
|
|
|
|
if (!my_strnncoll(cs, (const uchar *) str_begin,
|
2009-02-10 23:47:54 +01:00
|
|
|
(uint) (str_end - str_begin),
|
2004-08-24 18:18:59 +02:00
|
|
|
find_str, find_str_len))
|
|
|
|
return (longlong) position;
|
|
|
|
else
|
|
|
|
str_begin= substr_end;
|
|
|
|
}
|
|
|
|
str_end= substr_end;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-04-30 19:48:45 +02:00
|
|
|
else if (str_end - str_begin == 0 &&
|
|
|
|
find_str_len == 0 &&
|
2004-08-24 18:18:59 +02:00
|
|
|
wc == (my_wc_t) separator)
|
|
|
|
return (longlong) ++position;
|
|
|
|
else
|
2005-04-30 19:48:45 +02:00
|
|
|
return LL(0);
|
2004-08-24 18:18:59 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_bit_count::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
ulonglong value= (ulonglong) args[0]->val_int();
|
2005-11-06 09:35:49 +01:00
|
|
|
if ((null_value= args[0]->null_value))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0; /* purecov: inspected */
|
2003-05-04 18:43:07 +02:00
|
|
|
return (longlong) my_count_bits(value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
|
|
|
** Functions to handle dynamic loadable functions
|
|
|
|
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
|
2000-09-12 02:02:33 +02:00
|
|
|
** Rewritten by monty.
|
2000-07-31 21:29:14 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#ifdef HAVE_DLOPEN
|
|
|
|
|
2005-04-30 18:23:40 +02:00
|
|
|
void udf_handler::cleanup()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-06 06:37:30 +01:00
|
|
|
if (!not_original)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-06 06:37:30 +01:00
|
|
|
if (initialized)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-06 06:37:30 +01:00
|
|
|
if (u_d->func_deinit != NULL)
|
|
|
|
{
|
2006-07-09 11:03:51 +02:00
|
|
|
Udf_func_deinit deinit= u_d->func_deinit;
|
2004-11-06 06:37:30 +01:00
|
|
|
(*deinit)(&initid);
|
|
|
|
}
|
|
|
|
free_udf(u_d);
|
2005-04-30 18:23:40 +02:00
|
|
|
initialized= FALSE;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2004-11-06 06:37:30 +01:00
|
|
|
if (buffers) // Because of bug in ecc
|
|
|
|
delete [] buffers;
|
2005-04-30 18:23:40 +02:00
|
|
|
buffers= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2005-07-01 06:05:42 +02:00
|
|
|
udf_handler::fix_fields(THD *thd, Item_result_field *func,
|
2000-07-31 21:29:14 +02:00
|
|
|
uint arg_count, Item **arguments)
|
|
|
|
{
|
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 buff[STACK_BUFF_ALLOC]; // Max argument in function
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("Item_udf_func::fix_fields");
|
|
|
|
|
2005-05-31 12:06:15 +02:00
|
|
|
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE); // Fatal error flag is set!
|
2003-10-31 15:52:00 +01:00
|
|
|
|
2003-01-09 14:09:21 +01:00
|
|
|
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
if (!tmp_udf)
|
|
|
|
{
|
Fix for BUG#11755168 '46895: test "outfile_loaddata" fails (reproducible)'.
In sql_class.cc, 'row_count', of type 'ha_rows', was used as last argument for
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD which is
"Incorrect %-.32s value: '%-.128s' for column '%.192s' at row %ld".
So 'ha_rows' was used as 'long'.
On SPARC32 Solaris builds, 'long' is 4 bytes and 'ha_rows' is 'longlong' i.e. 8 bytes.
So the printf-like code was reading only the first 4 bytes.
Because the CPU is big-endian, 1LL is 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01
so the first four bytes yield 0. So the warning message had "row 0" instead of
"row 1" in test outfile_loaddata.test:
-Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 1
+Warning 1366 Incorrect string value: '\xE1\xE2\xF7' for column 'b' at row 0
All error-messaging functions which internally invoke some printf-life function
are potential candidate for such mistakes.
One apparently easy way to catch such mistakes is to use
ATTRIBUTE_FORMAT (from my_attribute.h).
But this works only when call site has both:
a) the format as a string literal
b) the types of arguments.
So:
func(ER(ER_BLAH), 10);
will silently not be checked, because ER(ER_BLAH) is not known at
compile time (it is known at run-time, and depends on the chosen
language).
And
func("%s", a va_list argument);
has the same problem, as the *real* type of arguments is not
known at this site at compile time (it's known in some caller).
Moreover,
func(ER(ER_BLAH));
though possibly correct (if ER(ER_BLAH) has no '%' markers), will not
compile (gcc says "error: format not a string literal and no format
arguments").
Consequences:
1) ATTRIBUTE_FORMAT is here added only to functions which in practice
take "string literal" formats: "my_error_reporter" and "print_admin_msg".
2) it cannot be added to the other functions: my_error(),
push_warning_printf(), Table_check_intact::report_error(),
general_log_print().
To do a one-time check of functions listed in (2), the following
"static code analysis" has been done:
1) replace
my_error(ER_xxx, arguments for substitution in format)
with the equivalent
my_printf_error(ER_xxx,ER(ER_xxx), arguments for substitution in
format),
so that we have ER(ER_xxx) and the arguments *in the same call site*
2) add ATTRIBUTE_FORMAT to push_warning_printf(),
Table_check_intact::report_error(), general_log_print()
3) replace ER(xxx) with the hard-coded English text found in
errmsg.txt (like: ER(ER_UNKNOWN_ERROR) is replaced with
"Unknown error"), so that a call site has the format as string literal
4) this way, ATTRIBUTE_FORMAT can effectively do its job
5) compile, fix errors detected by ATTRIBUTE_FORMAT
6) revert steps 1-2-3.
The present patch has no compiler error when submitted again to the
static code analysis above.
It cannot catch all problems though: see Field::set_warning(), in
which a call to push_warning_printf() has a variable error
(thus, not replacable by a string literal); I checked set_warning() calls
by hand though.
See also WL 5883 for one proposal to avoid such bugs from appearing
again in the future.
The issues fixed in the patch are:
a) mismatch in types (like 'int' passed to '%ld')
b) more arguments passed than specified in the format.
This patch resolves mismatches by changing the type/number of arguments,
not by changing error messages of sql/share/errmsg.txt. The latter would be wrong,
per the following old rule: errmsg.txt must be as stable as possible; no insertions
or deletions of messages, no changes of type or number of printf-like format specifiers,
are allowed, as long as the change impacts a message already released in a GA version.
If this rule is not followed:
- Connectors, which use error message numbers, will be confused (by insertions/deletions
of messages)
- using errmsg.sys of MySQL 5.1.n with mysqld of MySQL 5.1.(n+1)
could produce wrong messages or crash; such usage can easily happen if
installing 5.1.(n+1) while /etc/my.cnf still has --language=/path/to/5.1.n/xxx;
or if copying mysqld from 5.1.(n+1) into a 5.1.n installation.
When fixing b), I have verified that the superfluous arguments were not used in the format
in the first 5.1 GA (5.1.30 'bteam@astra04-20081114162938-z8mctjp6st27uobm').
Had they been used, then passing them today, even if the message doesn't use them
anymore, would have been necessary, as explained above.
2011-05-16 22:04:01 +02:00
|
|
|
my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
u_d=tmp_udf;
|
|
|
|
args=arguments;
|
|
|
|
|
|
|
|
/* Fix all arguments */
|
2002-10-25 10:58:32 +02:00
|
|
|
func->maybe_null=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
used_tables_cache=0;
|
|
|
|
const_item_cache=1;
|
|
|
|
|
|
|
|
if ((f_args.arg_count=arg_count))
|
|
|
|
{
|
|
|
|
if (!(f_args.arg_type= (Item_result*)
|
|
|
|
sql_alloc(f_args.arg_count*sizeof(Item_result))))
|
|
|
|
|
|
|
|
{
|
|
|
|
free_udf(u_d);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
uint i;
|
|
|
|
Item **arg,**arg_end;
|
|
|
|
for (i=0, arg=arguments, arg_end=arguments+arg_count;
|
|
|
|
arg != arg_end ;
|
|
|
|
arg++,i++)
|
|
|
|
{
|
2005-02-08 23:50:45 +01:00
|
|
|
if (!(*arg)->fixed &&
|
2005-07-01 06:05:42 +02:00
|
|
|
(*arg)->fix_fields(thd, arg))
|
2004-03-19 11:35:00 +01:00
|
|
|
DBUG_RETURN(1);
|
2004-02-18 00:08:52 +01:00
|
|
|
// we can't assign 'item' before, because fix_fields() can change arg
|
2003-05-19 15:35:49 +02:00
|
|
|
Item *item= *arg;
|
2004-02-18 00:08:52 +01:00
|
|
|
if (item->check_cols(1))
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2003-07-02 15:34:43 +02:00
|
|
|
/*
|
|
|
|
TODO: We should think about this. It is not always
|
|
|
|
right way just to set an UDF result to return my_charset_bin
|
|
|
|
if one argument has binary sorting order.
|
|
|
|
The result collation should be calculated according to arguments
|
|
|
|
derivations in some cases and should not in other cases.
|
|
|
|
Moreover, some arguments can represent a numeric input
|
|
|
|
which doesn't effect the result character set and collation.
|
|
|
|
There is no a general rule for UDF. Everything depends on
|
2005-02-08 23:50:45 +01:00
|
|
|
the particular user defined function.
|
2003-07-02 15:34:43 +02:00
|
|
|
*/
|
2003-08-05 09:52:37 +02:00
|
|
|
if (item->collation.collation->state & MY_CS_BINSORT)
|
|
|
|
func->collation.set(&my_charset_bin);
|
2003-03-24 21:52:46 +01:00
|
|
|
if (item->maybe_null)
|
2000-07-31 21:29:14 +02:00
|
|
|
func->maybe_null=1;
|
2003-03-24 21:52:46 +01:00
|
|
|
func->with_sum_func= func->with_sum_func || item->with_sum_func;
|
|
|
|
used_tables_cache|=item->used_tables();
|
|
|
|
const_item_cache&=item->const_item();
|
|
|
|
f_args.arg_type[i]=item->result_type();
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
//TODO: why all following memory is not allocated with 1 call of sql_alloc?
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!(buffers=new String[arg_count]) ||
|
|
|
|
!(f_args.args= (char**) sql_alloc(arg_count * sizeof(char *))) ||
|
2003-09-13 16:47:59 +02:00
|
|
|
!(f_args.lengths= (ulong*) sql_alloc(arg_count * sizeof(long))) ||
|
|
|
|
!(f_args.maybe_null= (char*) sql_alloc(arg_count * sizeof(char))) ||
|
|
|
|
!(num_buffer= (char*) sql_alloc(arg_count *
|
|
|
|
ALIGN_SIZE(sizeof(double)))) ||
|
|
|
|
!(f_args.attributes= (char**) sql_alloc(arg_count * sizeof(char *))) ||
|
|
|
|
!(f_args.attribute_lengths= (ulong*) sql_alloc(arg_count *
|
|
|
|
sizeof(long))))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
free_udf(u_d);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
func->fix_length_and_dec();
|
|
|
|
initid.max_length=func->max_length;
|
|
|
|
initid.maybe_null=func->maybe_null;
|
|
|
|
initid.const_item=const_item_cache;
|
|
|
|
initid.decimals=func->decimals;
|
|
|
|
initid.ptr=0;
|
|
|
|
|
|
|
|
if (u_d->func_init)
|
|
|
|
{
|
2007-10-31 22:31:57 +01:00
|
|
|
char init_msg_buff[MYSQL_ERRMSG_SIZE];
|
2000-07-31 21:29:14 +02:00
|
|
|
char *to=num_buffer;
|
|
|
|
for (uint i=0; i < arg_count; i++)
|
|
|
|
{
|
2006-11-13 19:13:44 +01:00
|
|
|
/*
|
|
|
|
For a constant argument i, args->args[i] points to the argument value.
|
|
|
|
For non-constant, args->args[i] is NULL.
|
|
|
|
*/
|
|
|
|
f_args.args[i]= NULL; /* Non-const unless updated below. */
|
|
|
|
|
2003-09-13 16:47:59 +02:00
|
|
|
f_args.lengths[i]= arguments[i]->max_length;
|
|
|
|
f_args.maybe_null[i]= (char) arguments[i]->maybe_null;
|
|
|
|
f_args.attributes[i]= arguments[i]->name;
|
|
|
|
f_args.attribute_lengths[i]= arguments[i]->name_length;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2006-11-13 19:13:44 +01:00
|
|
|
if (arguments[i]->const_item())
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2006-11-13 19:13:44 +01:00
|
|
|
switch (arguments[i]->result_type())
|
|
|
|
{
|
|
|
|
case STRING_RESULT:
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
String *res= arguments[i]->val_str(&buffers[i]);
|
2007-01-18 16:33:38 +01:00
|
|
|
if (arguments[i]->null_value)
|
|
|
|
continue;
|
2009-12-22 13:37:21 +01:00
|
|
|
f_args.args[i]= (char*) res->c_ptr_safe();
|
2007-08-06 03:37:55 +02:00
|
|
|
f_args.lengths[i]= res->length();
|
2006-11-13 19:13:44 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
*((longlong*) to)= arguments[i]->val_int();
|
2007-01-18 16:33:38 +01:00
|
|
|
if (arguments[i]->null_value)
|
|
|
|
continue;
|
2006-11-13 19:13:44 +01:00
|
|
|
f_args.args[i]= to;
|
|
|
|
to+= ALIGN_SIZE(sizeof(longlong));
|
|
|
|
break;
|
|
|
|
case REAL_RESULT:
|
|
|
|
*((double*) to)= arguments[i]->val_real();
|
2007-01-18 16:33:38 +01:00
|
|
|
if (arguments[i]->null_value)
|
|
|
|
continue;
|
2006-11-13 19:13:44 +01:00
|
|
|
f_args.args[i]= to;
|
|
|
|
to+= ALIGN_SIZE(sizeof(double));
|
|
|
|
break;
|
|
|
|
case ROW_RESULT:
|
|
|
|
default:
|
|
|
|
// This case should never be chosen
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
break;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
2006-07-09 11:03:51 +02:00
|
|
|
Udf_func_init init= u_d->func_init;
|
2007-10-31 22:31:57 +01:00
|
|
|
if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
|
2007-10-31 22:31:57 +01:00
|
|
|
u_d->name.str, init_msg_buff);
|
2000-07-31 21:29:14 +02:00
|
|
|
free_udf(u_d);
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
|
|
|
|
func->maybe_null=initid.maybe_null;
|
|
|
|
const_item_cache=initid.const_item;
|
2007-11-27 16:16:52 +01:00
|
|
|
/*
|
|
|
|
Keep used_tables_cache in sync with const_item_cache.
|
|
|
|
See the comment in Item_udf_func::update_used tables.
|
|
|
|
*/
|
|
|
|
if (!const_item_cache && !used_tables_cache)
|
|
|
|
used_tables_cache= RAND_TABLE_BIT;
|
2004-07-31 22:39:10 +02:00
|
|
|
func->decimals=min(initid.decimals,NOT_FIXED_DEC);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
initialized=1;
|
|
|
|
if (error)
|
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
|
|
|
|
u_d->name.str, ER(ER_UNKNOWN_ERROR));
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(TRUE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool udf_handler::get_arguments()
|
|
|
|
{
|
|
|
|
if (error)
|
|
|
|
return 1; // Got an error earlier
|
|
|
|
char *to= num_buffer;
|
|
|
|
uint str_count=0;
|
|
|
|
for (uint i=0; i < f_args.arg_count; i++)
|
|
|
|
{
|
|
|
|
f_args.args[i]=0;
|
|
|
|
switch (f_args.arg_type[i]) {
|
|
|
|
case STRING_RESULT:
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
String *res=args[i]->val_str(&buffers[str_count++]);
|
|
|
|
if (!(args[i]->null_value))
|
|
|
|
{
|
|
|
|
f_args.args[i]= (char*) res->ptr();
|
|
|
|
f_args.lengths[i]= res->length();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
*((longlong*) to) = args[i]->val_int();
|
|
|
|
if (!args[i]->null_value)
|
|
|
|
{
|
|
|
|
f_args.args[i]=to;
|
|
|
|
to+= ALIGN_SIZE(sizeof(longlong));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case REAL_RESULT:
|
2004-11-11 19:39:35 +01:00
|
|
|
*((double*) to)= args[i]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!args[i]->null_value)
|
|
|
|
{
|
|
|
|
f_args.args[i]=to;
|
|
|
|
to+= ALIGN_SIZE(sizeof(double));
|
|
|
|
}
|
|
|
|
break;
|
2003-02-17 15:06:51 +01:00
|
|
|
case ROW_RESULT:
|
2003-01-31 11:07:07 +01:00
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2002-11-15 19:32:09 +01:00
|
|
|
DBUG_ASSERT(0);
|
2003-02-17 15:06:51 +01:00
|
|
|
break;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
@return
|
|
|
|
(String*)NULL in case of NULL values
|
|
|
|
*/
|
2000-07-31 21:29:14 +02:00
|
|
|
String *udf_handler::val_str(String *str,String *save_str)
|
|
|
|
{
|
2003-11-28 11:18:13 +01:00
|
|
|
uchar is_null_tmp=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
ulong res_length;
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_ENTER("udf_handler::val_str");
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
if (get_arguments())
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
char * (*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
|
|
|
|
(char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
|
|
|
|
u_d->func;
|
|
|
|
|
|
|
|
if ((res_length=str->alloced_length()) < MAX_FIELD_WIDTH)
|
|
|
|
{ // This happens VERY seldom
|
|
|
|
if (str->alloc(MAX_FIELD_WIDTH))
|
|
|
|
{
|
|
|
|
error=1;
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
2003-11-28 11:18:13 +01:00
|
|
|
char *res=func(&initid, &f_args, (char*) str->ptr(), &res_length,
|
|
|
|
&is_null_tmp, &error);
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_PRINT("info", ("udf func returned, res_length: %lu", res_length));
|
2003-11-28 11:18:13 +01:00
|
|
|
if (is_null_tmp || !res || error) // The !res is for safety
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_PRINT("info", ("Null or error"));
|
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
if (res == str->ptr())
|
|
|
|
{
|
|
|
|
str->length(res_length);
|
2009-12-02 11:00:44 +01:00
|
|
|
DBUG_PRINT("exit", ("str: %*.s", (int) str->length(), str->ptr()));
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_RETURN(str);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-03-07 10:39:53 +01:00
|
|
|
save_str->set(res, res_length, str->charset());
|
2006-04-28 11:37:20 +02:00
|
|
|
DBUG_PRINT("exit", ("save_str: %s", save_str->ptr()));
|
|
|
|
DBUG_RETURN(save_str);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-19 17:58:27 +01:00
|
|
|
/*
|
|
|
|
For the moment, UDF functions are returning DECIMAL values as strings
|
|
|
|
*/
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *udf_handler::val_decimal(my_bool *null_value, my_decimal *dec_buf)
|
|
|
|
{
|
|
|
|
char buf[DECIMAL_MAX_STR_LENGTH+1], *end;
|
|
|
|
ulong res_length= DECIMAL_MAX_STR_LENGTH;
|
|
|
|
|
|
|
|
if (get_arguments())
|
|
|
|
{
|
|
|
|
*null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
char *(*func)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *)=
|
|
|
|
(char* (*)(UDF_INIT *, UDF_ARGS *, char *, ulong *, uchar *, uchar *))
|
|
|
|
u_d->func;
|
|
|
|
|
|
|
|
char *res= func(&initid, &f_args, buf, &res_length, &is_null, &error);
|
|
|
|
if (is_null || error)
|
|
|
|
{
|
|
|
|
*null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2005-02-19 17:58:27 +01:00
|
|
|
end= res+ res_length;
|
|
|
|
str2my_decimal(E_DEC_FATAL_ERROR, res, dec_buf, &end);
|
2005-02-08 23:50:45 +01:00
|
|
|
return dec_buf;
|
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-04-30 18:23:40 +02:00
|
|
|
void Item_udf_func::cleanup()
|
|
|
|
{
|
|
|
|
udf.cleanup();
|
|
|
|
Item_func::cleanup();
|
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_udf_func::print(String *str, enum_query_type query_type)
|
2006-10-24 14:26:41 +02:00
|
|
|
{
|
|
|
|
str->append(func_name());
|
|
|
|
str->append('(');
|
|
|
|
for (uint i=0 ; i < arg_count ; i++)
|
|
|
|
{
|
|
|
|
if (i != 0)
|
|
|
|
str->append(',');
|
2008-02-22 11:30:33 +01:00
|
|
|
args[i]->print_item_w_name(str, query_type);
|
2006-10-24 14:26:41 +02:00
|
|
|
}
|
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_udf_float::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("Item_func_udf_float::val");
|
|
|
|
DBUG_PRINT("info",("result_type: %d arg_count: %d",
|
|
|
|
args[0]->result_type(), arg_count));
|
|
|
|
DBUG_RETURN(udf.val(&null_value));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_udf_float::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-11-11 19:39:35 +01:00
|
|
|
double nr= val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
if (null_value)
|
|
|
|
return 0; /* purecov: inspected */
|
2006-06-16 12:17:20 +02:00
|
|
|
str->set_real(nr,decimals,&my_charset_bin);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_udf_int::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
DBUG_ENTER("Item_func_udf_int::val_int");
|
|
|
|
DBUG_RETURN(udf.val_int(&null_value));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_udf_int::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong nr=val_int();
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
2006-06-16 12:17:20 +02:00
|
|
|
str->set_int(nr, unsigned_flag, &my_charset_bin);
|
2000-07-31 21:29:14 +02:00
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
longlong Item_func_udf_decimal::val_int()
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
|
2005-02-19 17:58:27 +01:00
|
|
|
longlong result;
|
2005-02-08 23:50:45 +01:00
|
|
|
if (null_value)
|
|
|
|
return 0;
|
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, dec, unsigned_flag, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_func_udf_decimal::val_real()
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
|
2005-02-19 17:58:27 +01:00
|
|
|
double result;
|
2005-02-08 23:50:45 +01:00
|
|
|
if (null_value)
|
|
|
|
return 0.0;
|
|
|
|
my_decimal2double(E_DEC_FATAL_ERROR, dec, &result);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_udf_decimal::val_decimal(my_decimal *dec_buf)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
DBUG_ENTER("Item_func_udf_decimal::val_decimal");
|
|
|
|
DBUG_PRINT("info",("result_type: %d arg_count: %d",
|
|
|
|
args[0]->result_type(), arg_count));
|
|
|
|
|
|
|
|
DBUG_RETURN(udf.val_decimal(&null_value, dec_buf));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String *Item_func_udf_decimal::val_str(String *str)
|
|
|
|
{
|
|
|
|
my_decimal dec_buf, *dec= udf.val_decimal(&null_value, &dec_buf);
|
|
|
|
if (null_value)
|
|
|
|
return 0;
|
|
|
|
if (str->length() < DECIMAL_MAX_STR_LENGTH)
|
|
|
|
str->length(DECIMAL_MAX_STR_LENGTH);
|
|
|
|
my_decimal_round(E_DEC_FATAL_ERROR, dec, decimals, FALSE, &dec_buf);
|
|
|
|
my_decimal2string(E_DEC_FATAL_ERROR, &dec_buf, 0, 0, '0', str);
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_func_udf_decimal::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
fix_num_length_and_dec();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/* Default max_length is max argument length */
|
|
|
|
|
|
|
|
void Item_func_udf_str::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_udf_str::fix_length_and_dec");
|
|
|
|
max_length=0;
|
|
|
|
for (uint i = 0; i < arg_count; i++)
|
|
|
|
set_if_bigger(max_length,args[i]->max_length);
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
String *Item_func_udf_str::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=udf.val_str(str,&str_value);
|
|
|
|
null_value = !res;
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2005-02-24 20:10:12 +01:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
@note
|
|
|
|
This has to come last in the udf_handler methods, or C for AIX
|
|
|
|
version 6.0.0.0 fails to compile with debugging enabled. (Yes, really.)
|
|
|
|
*/
|
2005-02-24 20:10:12 +01:00
|
|
|
|
|
|
|
udf_handler::~udf_handler()
|
|
|
|
{
|
2005-05-09 14:21:57 +02:00
|
|
|
/* Everything should be properly cleaned up by this moment. */
|
|
|
|
DBUG_ASSERT(not_original || !(initialized || buffers));
|
2005-02-24 20:10:12 +01:00
|
|
|
}
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
#else
|
|
|
|
bool udf_handler::get_arguments() { return 0; }
|
|
|
|
#endif /* HAVE_DLOPEN */
|
|
|
|
|
|
|
|
/*
|
|
|
|
** User level locks
|
|
|
|
*/
|
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_t LOCK_user_locks;
|
2000-07-31 21:29:14 +02:00
|
|
|
static HASH hash_user_locks;
|
|
|
|
|
2004-03-15 20:39:36 +01:00
|
|
|
class User_level_lock
|
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
|
|
|
uchar *key;
|
|
|
|
size_t key_length;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
int count;
|
|
|
|
bool locked;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_t cond;
|
2007-02-23 12:13:55 +01:00
|
|
|
my_thread_id thread_id;
|
|
|
|
void set_thread(THD *thd) { thread_id= thd->thread_id; }
|
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
|
|
|
User_level_lock(const uchar *key_arg,uint length, ulong id)
|
2003-03-14 10:10:33 +01:00
|
|
|
:key_length(length),count(1),locked(1), thread_id(id)
|
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
|
|
|
key= (uchar*) my_memdup(key_arg,length,MYF(0));
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_init(key_user_level_lock_cond, &cond, NULL);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (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
|
|
|
if (my_hash_insert(&hash_user_locks,(uchar*) this))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.
Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.
Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost.
The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.
Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.
2010-07-08 23:20:08 +02:00
|
|
|
my_free(key);
|
2000-07-31 21:29:14 +02:00
|
|
|
key=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-03-15 20:39:36 +01:00
|
|
|
~User_level_lock()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
if (key)
|
|
|
|
{
|
2009-10-14 18:37:38 +02:00
|
|
|
my_hash_delete(&hash_user_locks,(uchar*) this);
|
Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.
Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.
Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost.
The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.
Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.
2010-07-08 23:20:08 +02:00
|
|
|
my_free(key);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_destroy(&cond);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
inline bool initialized() { return key != 0; }
|
2004-03-15 20:39:36 +01:00
|
|
|
friend void item_user_lock_release(User_level_lock *ull);
|
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
|
|
|
friend uchar *ull_get_key(const User_level_lock *ull, size_t *length,
|
|
|
|
my_bool not_used);
|
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
|
|
|
uchar *ull_get_key(const User_level_lock *ull, 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= ull->key_length;
|
|
|
|
return ull->key;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
|
|
|
static PSI_mutex_key key_LOCK_user_locks;
|
|
|
|
|
|
|
|
static PSI_mutex_info all_user_mutexes[]=
|
|
|
|
{
|
|
|
|
{ &key_LOCK_user_locks, "LOCK_user_locks", PSI_FLAG_GLOBAL}
|
|
|
|
};
|
|
|
|
|
|
|
|
static void init_user_lock_psi_keys(void)
|
|
|
|
{
|
|
|
|
const char* category= "sql";
|
|
|
|
int count;
|
|
|
|
|
|
|
|
if (PSI_server == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
count= array_elements(all_user_mutexes);
|
|
|
|
PSI_server->register_mutex(category, all_user_mutexes, count);
|
|
|
|
}
|
|
|
|
#endif
|
2003-12-21 18:39:32 +01:00
|
|
|
|
|
|
|
static bool item_user_lock_inited= 0;
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
void item_user_lock_init(void)
|
|
|
|
{
|
2009-12-10 04:19:51 +01:00
|
|
|
#ifdef HAVE_PSI_INTERFACE
|
|
|
|
init_user_lock_psi_keys();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
mysql_mutex_init(key_LOCK_user_locks, &LOCK_user_locks, MY_MUTEX_INIT_SLOW);
|
2009-10-14 18:37:38 +02:00
|
|
|
my_hash_init(&hash_user_locks,system_charset_info,
|
|
|
|
16,0,0,(my_hash_get_key) ull_get_key,NULL,0);
|
2003-12-21 18:39:32 +01:00
|
|
|
item_user_lock_inited= 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void item_user_lock_free(void)
|
|
|
|
{
|
2003-12-21 18:39:32 +01:00
|
|
|
if (item_user_lock_inited)
|
|
|
|
{
|
|
|
|
item_user_lock_inited= 0;
|
2009-10-14 18:37:38 +02:00
|
|
|
my_hash_free(&hash_user_locks);
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_destroy(&LOCK_user_locks);
|
2003-12-21 18:39:32 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2004-03-15 20:39:36 +01:00
|
|
|
void item_user_lock_release(User_level_lock *ull)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
ull->locked=0;
|
2006-04-24 16:06:43 +02:00
|
|
|
ull->thread_id= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
if (--ull->count)
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_signal(&ull->cond);
|
2000-07-31 21:29:14 +02:00
|
|
|
else
|
|
|
|
delete ull;
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Wait until we are at or past the given position in the master binlog
|
|
|
|
on the slave.
|
|
|
|
*/
|
2001-01-17 13:47:33 +01:00
|
|
|
|
|
|
|
longlong Item_master_pos_wait::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2001-01-17 13:47:33 +01:00
|
|
|
THD* thd = current_thd;
|
|
|
|
String *log_name = args[0]->val_str(&value);
|
2003-02-12 20:55:37 +01:00
|
|
|
int event_count= 0;
|
2001-12-06 13:10:51 +01:00
|
|
|
|
2001-01-22 03:46:32 +01:00
|
|
|
null_value=0;
|
|
|
|
if (thd->slave_thread || !log_name || !log_name->length())
|
|
|
|
{
|
|
|
|
null_value = 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2006-12-14 23:51:37 +01:00
|
|
|
#ifdef HAVE_REPLICATION
|
2003-02-04 20:52:14 +01:00
|
|
|
longlong pos = (ulong)args[1]->val_int();
|
2003-01-25 14:07:51 +01:00
|
|
|
longlong timeout = (arg_count==3) ? args[2]->val_int() : 0 ;
|
|
|
|
if ((event_count = active_mi->rli.wait_for_pos(thd, log_name, pos, timeout)) == -2)
|
2001-01-22 03:46:32 +01:00
|
|
|
{
|
|
|
|
null_value = 1;
|
|
|
|
event_count=0;
|
|
|
|
}
|
2002-12-16 14:33:29 +01:00
|
|
|
#endif
|
2001-01-17 13:47:33 +01:00
|
|
|
return event_count;
|
|
|
|
}
|
|
|
|
|
2001-10-03 21:55:31 +02:00
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
/**
|
|
|
|
Enables a session to wait on a condition until a timeout or a network
|
|
|
|
disconnect occurs.
|
|
|
|
|
|
|
|
@remark The connection is polled every m_interrupt_interval nanoseconds.
|
|
|
|
*/
|
|
|
|
|
|
|
|
class Interruptible_wait
|
|
|
|
{
|
|
|
|
THD *m_thd;
|
|
|
|
struct timespec m_abs_timeout;
|
|
|
|
static const ulonglong m_interrupt_interval;
|
|
|
|
|
|
|
|
public:
|
|
|
|
Interruptible_wait(THD *thd)
|
|
|
|
: m_thd(thd) {}
|
|
|
|
|
|
|
|
~Interruptible_wait() {}
|
|
|
|
|
|
|
|
public:
|
|
|
|
/**
|
|
|
|
Set the absolute timeout.
|
|
|
|
|
|
|
|
@param timeout The amount of time in nanoseconds to wait
|
|
|
|
*/
|
|
|
|
void set_timeout(ulonglong timeout)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
Calculate the absolute system time at the start so it can
|
|
|
|
be controlled in slices. It relies on the fact that once
|
|
|
|
the absolute time passes, the timed wait call will fail
|
|
|
|
automatically with a timeout error.
|
|
|
|
*/
|
|
|
|
set_timespec_nsec(m_abs_timeout, timeout);
|
|
|
|
}
|
|
|
|
|
|
|
|
/** The timed wait. */
|
|
|
|
int wait(mysql_cond_t *, mysql_mutex_t *);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/** Time to wait before polling the connection status. */
|
|
|
|
const ulonglong Interruptible_wait::m_interrupt_interval= 5 * ULL(1000000000);
|
|
|
|
|
2009-11-10 20:09:27 +01:00
|
|
|
|
|
|
|
/**
|
2010-10-14 03:54:07 +02:00
|
|
|
Wait for a given condition to be signaled.
|
2009-11-10 20:09:27 +01:00
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
@param cond The condition variable to wait on.
|
|
|
|
@param mutex The associated mutex.
|
|
|
|
|
|
|
|
@remark The absolute timeout is preserved across calls.
|
2009-11-10 20:09:27 +01:00
|
|
|
|
2010-01-12 02:47:27 +01:00
|
|
|
@retval return value from mysql_cond_timedwait
|
2009-11-10 20:09:27 +01:00
|
|
|
*/
|
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
int Interruptible_wait::wait(mysql_cond_t *cond, mysql_mutex_t *mutex)
|
2009-11-10 20:09:27 +01:00
|
|
|
{
|
|
|
|
int error;
|
2010-10-14 03:54:07 +02:00
|
|
|
struct timespec timeout;
|
2009-11-10 20:09:27 +01:00
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
while (1)
|
2009-11-10 20:09:27 +01:00
|
|
|
{
|
|
|
|
/* Wait for a fixed interval. */
|
2010-10-14 03:54:07 +02:00
|
|
|
set_timespec_nsec(timeout, m_interrupt_interval);
|
2009-11-10 20:09:27 +01:00
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
/* But only if not past the absolute timeout. */
|
|
|
|
if (cmp_timespec(timeout, m_abs_timeout) > 0)
|
|
|
|
timeout= m_abs_timeout;
|
|
|
|
|
|
|
|
error= mysql_cond_timedwait(cond, mutex, &timeout);
|
2009-11-10 20:09:27 +01:00
|
|
|
if (error == ETIMEDOUT || error == ETIME)
|
|
|
|
{
|
|
|
|
/* Return error if timed out or connection is broken. */
|
2010-10-14 03:54:07 +02:00
|
|
|
if (!cmp_timespec(timeout, m_abs_timeout) || !m_thd->is_connected())
|
2009-11-10 20:09:27 +01:00
|
|
|
break;
|
|
|
|
}
|
2010-10-14 03:54:07 +02:00
|
|
|
/* Otherwise, propagate status to the caller. */
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2009-11-10 20:09:27 +01:00
|
|
|
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Get a user level lock. If the thread has an old lock this is first released.
|
|
|
|
|
|
|
|
@retval
|
|
|
|
1 : Got lock
|
|
|
|
@retval
|
|
|
|
0 : Timeout
|
|
|
|
@retval
|
|
|
|
NULL : Error
|
2000-07-31 21:29:14 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
longlong Item_func_get_lock::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
2010-10-14 03:54:07 +02:00
|
|
|
ulonglong timeout= args[1]->val_int();
|
2000-07-31 21:29:14 +02:00
|
|
|
THD *thd=current_thd;
|
2004-03-15 20:39:36 +01:00
|
|
|
User_level_lock *ull;
|
2005-10-11 23:58:22 +02:00
|
|
|
int error;
|
2010-10-14 03:54:07 +02:00
|
|
|
Interruptible_wait timed_cond(thd);
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_ENTER("Item_func_get_lock::val_int");
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-03-02 16:37:54 +01:00
|
|
|
/*
|
|
|
|
In slave thread no need to get locks, everything is serialized. Anyway
|
|
|
|
there is no way to make GET_LOCK() work on slave like it did on master
|
|
|
|
(i.e. make it return exactly the same value) because we don't have the
|
|
|
|
same other concurrent threads environment. No matter what we return here,
|
|
|
|
it's not guaranteed to be same as on master.
|
|
|
|
*/
|
|
|
|
if (thd->slave_thread)
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(1);
|
2005-03-02 16:37:54 +01:00
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_lock(&LOCK_user_locks);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
if (!res || !res->length())
|
|
|
|
{
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2000-07-31 21:29:14 +02:00
|
|
|
null_value=1;
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("lock %.*s, thd=%ld", res->length(), res->ptr(),
|
|
|
|
(long) thd->real_id));
|
2000-07-31 21:29:14 +02:00
|
|
|
null_value=0;
|
|
|
|
|
|
|
|
if (thd->ull)
|
|
|
|
{
|
|
|
|
item_user_lock_release(thd->ull);
|
|
|
|
thd->ull=0;
|
|
|
|
}
|
|
|
|
|
2009-10-14 18:37:38 +02:00
|
|
|
if (!(ull= ((User_level_lock *) my_hash_search(&hash_user_locks,
|
|
|
|
(uchar*) res->ptr(),
|
|
|
|
(size_t) res->length()))))
|
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
|
|
|
ull= new User_level_lock((uchar*) res->ptr(), (size_t) res->length(),
|
|
|
|
thd->thread_id);
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!ull || !ull->initialized())
|
|
|
|
{
|
|
|
|
delete ull;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2000-07-31 21:29:14 +02:00
|
|
|
null_value=1; // Probably out of memory
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2007-01-29 14:39:28 +01:00
|
|
|
ull->set_thread(thd);
|
2000-07-31 21:29:14 +02:00
|
|
|
thd->ull=ull;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("made new lock"));
|
|
|
|
DBUG_RETURN(1); // Got new lock
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
ull->count++;
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("ull->count=%d", ull->count));
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
/*
|
|
|
|
Structure is now initialized. Try to get the lock.
|
|
|
|
Set up control struct to allow others to abort locks.
|
|
|
|
*/
|
2007-02-22 16:03:08 +01:00
|
|
|
thd_proc_info(thd, "User lock");
|
2000-07-31 21:29:14 +02:00
|
|
|
thd->mysys_var->current_mutex= &LOCK_user_locks;
|
|
|
|
thd->mysys_var->current_cond= &ull->cond;
|
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
timed_cond.set_timeout(timeout * ULL(1000000000));
|
|
|
|
|
2005-10-11 23:58:22 +02:00
|
|
|
error= 0;
|
2011-03-04 13:12:31 +01:00
|
|
|
thd_wait_begin(thd, THD_WAIT_USER_LOCK);
|
2005-10-11 23:58:22 +02:00
|
|
|
while (ull->locked && !thd->killed)
|
|
|
|
{
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("waiting on lock"));
|
2010-10-14 03:54:07 +02:00
|
|
|
error= timed_cond.wait(&ull->cond, &LOCK_user_locks);
|
2005-10-11 23:58:22 +02:00
|
|
|
if (error == ETIMEDOUT || error == ETIME)
|
2007-06-12 13:35:36 +02:00
|
|
|
{
|
|
|
|
DBUG_PRINT("info", ("lock wait timeout"));
|
2005-10-11 23:58:22 +02:00
|
|
|
break;
|
2007-06-12 13:35:36 +02:00
|
|
|
}
|
2005-10-11 23:58:22 +02:00
|
|
|
error= 0;
|
|
|
|
}
|
2011-03-04 13:12:31 +01:00
|
|
|
thd_wait_end(thd);
|
2005-10-11 23:58:22 +02:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
if (ull->locked)
|
|
|
|
{
|
|
|
|
if (!--ull->count)
|
2005-10-11 23:58:22 +02:00
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
delete ull; // Should never happen
|
2005-10-11 23:58:22 +02:00
|
|
|
}
|
|
|
|
if (!error) // Killed (thd->killed != 0)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
error=1;
|
|
|
|
null_value=1; // Return NULL
|
|
|
|
}
|
|
|
|
}
|
2005-10-11 23:58:22 +02:00
|
|
|
else // We got the lock
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
ull->locked=1;
|
2007-01-29 14:39:28 +01:00
|
|
|
ull->set_thread(thd);
|
2006-04-24 16:06:43 +02:00
|
|
|
ull->thread_id= thd->thread_id;
|
2000-07-31 21:29:14 +02:00
|
|
|
thd->ull=ull;
|
|
|
|
error=0;
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("got the lock"));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_lock(&thd->mysys_var->mutex);
|
2007-02-22 16:03:08 +01:00
|
|
|
thd_proc_info(thd, 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
thd->mysys_var->current_mutex= 0;
|
|
|
|
thd->mysys_var->current_cond= 0;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&thd->mysys_var->mutex);
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(!error ? 1 : 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2002-06-11 10:20:31 +02:00
|
|
|
Release a user level lock.
|
2007-10-11 19:29:09 +02:00
|
|
|
@return
|
|
|
|
- 1 if lock released
|
|
|
|
- 0 if lock wasn't held
|
|
|
|
- (SQL) NULL if no such lock
|
2000-07-31 21:29:14 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
longlong Item_func_release_lock::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
2004-03-15 20:39:36 +01:00
|
|
|
User_level_lock *ull;
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong result;
|
2007-06-12 13:35:36 +02:00
|
|
|
THD *thd=current_thd;
|
|
|
|
DBUG_ENTER("Item_func_release_lock::val_int");
|
2000-07-31 21:29:14 +02:00
|
|
|
if (!res || !res->length())
|
|
|
|
{
|
|
|
|
null_value=1;
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(0);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("lock %.*s", res->length(), res->ptr()));
|
2000-07-31 21:29:14 +02:00
|
|
|
null_value=0;
|
|
|
|
|
|
|
|
result=0;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_lock(&LOCK_user_locks);
|
2009-10-14 18:37:38 +02:00
|
|
|
if (!(ull= ((User_level_lock*) my_hash_search(&hash_user_locks,
|
|
|
|
(const uchar*) res->ptr(),
|
|
|
|
(size_t) res->length()))))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2007-06-12 17:41:56 +02:00
|
|
|
DBUG_PRINT("info", ("ull->locked=%d ull->thread=%lu thd=%lu",
|
2007-06-12 13:35:36 +02:00
|
|
|
(int) ull->locked,
|
2007-06-12 17:41:56 +02:00
|
|
|
(long)ull->thread_id,
|
|
|
|
(long)thd->thread_id));
|
2007-02-23 12:13:55 +01:00
|
|
|
if (ull->locked && current_thd->thread_id == ull->thread_id)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_PRINT("info", ("release lock"));
|
2000-07-31 21:29:14 +02:00
|
|
|
result=1; // Release is ok
|
|
|
|
item_user_lock_release(ull);
|
2007-06-12 13:35:36 +02:00
|
|
|
thd->ull=0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2007-06-12 13:35:36 +02:00
|
|
|
DBUG_RETURN(result);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-03-25 17:42:13 +01:00
|
|
|
longlong Item_func_last_insert_id::val_int()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-02-05 15:05:46 +01:00
|
|
|
THD *thd= current_thd;
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2004-03-25 17:42:13 +01:00
|
|
|
if (arg_count)
|
|
|
|
{
|
2005-02-05 15:05:46 +01:00
|
|
|
longlong value= args[0]->val_int();
|
|
|
|
null_value= args[0]->null_value;
|
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
|
|
|
/*
|
|
|
|
LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
|
|
|
|
documented in the manual. We don't want to touch
|
|
|
|
first_successful_insert_id_in_cur_stmt because it would make
|
|
|
|
LAST_INSERT_ID(X) take precedence over an generated auto_increment
|
|
|
|
value for this row.
|
|
|
|
*/
|
|
|
|
thd->arg_of_last_insert_id_function= TRUE;
|
|
|
|
thd->first_successful_insert_id_in_prev_stmt= value;
|
|
|
|
return value;
|
2004-03-25 17:42:13 +01:00
|
|
|
}
|
2012-10-16 19:48:48 +02:00
|
|
|
return
|
|
|
|
static_cast<longlong>(thd->read_first_successful_insert_id_in_prev_stmt());
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2007-10-19 14:43:19 +02:00
|
|
|
|
|
|
|
bool Item_func_last_insert_id::fix_fields(THD *thd, Item **ref)
|
|
|
|
{
|
|
|
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
|
|
|
return Item_int_func::fix_fields(thd, ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
/* This function is just used to test speed of different functions */
|
|
|
|
|
|
|
|
longlong Item_func_benchmark::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
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);
|
2007-03-02 04:04:49 +01:00
|
|
|
my_decimal tmp_decimal;
|
2000-07-31 21:29:14 +02:00
|
|
|
THD *thd=current_thd;
|
2008-02-24 01:31:54 +01:00
|
|
|
ulonglong loop_count;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2008-02-24 01:31:54 +01:00
|
|
|
loop_count= (ulonglong) args[0]->val_int();
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
|
2008-02-24 01:31:54 +01:00
|
|
|
if (args[0]->null_value ||
|
|
|
|
(!args[0]->unsigned_flag && (((longlong) loop_count) < 0)))
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
{
|
2008-02-24 01:31:54 +01:00
|
|
|
if (!args[0]->null_value)
|
|
|
|
{
|
|
|
|
char buff[22];
|
|
|
|
llstr(((longlong) loop_count), buff);
|
2009-09-10 11:18:29 +02:00
|
|
|
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
2008-02-24 01:31:54 +01:00
|
|
|
ER_WRONG_VALUE_FOR_TYPE, ER(ER_WRONG_VALUE_FOR_TYPE),
|
|
|
|
"count", buff, "benchmark");
|
|
|
|
}
|
|
|
|
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
null_value= 1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
null_value=0;
|
2008-02-24 01:31:54 +01:00
|
|
|
for (ulonglong loop=0 ; loop < loop_count && !thd->killed; loop++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
switch (args[1]->result_type()) {
|
2000-07-31 21:29:14 +02:00
|
|
|
case REAL_RESULT:
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
(void) args[1]->val_real();
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
(void) args[1]->val_int();
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
(void) args[1]->val_str(&tmp);
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
2007-03-02 04:04:49 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
(void) args[1]->val_decimal(&tmp_decimal);
|
|
|
|
break;
|
2003-02-17 15:06:51 +01:00
|
|
|
case ROW_RESULT:
|
2003-01-31 11:07:07 +01:00
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2002-11-15 19:32:09 +01:00
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_benchmark::print(String *str, enum_query_type query_type)
|
2003-10-30 11:57:26 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("benchmark("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
Bug#22684 (BENCHMARK, ENCODE, DECODE and FORMAT are not real functions)
Before this change, the functions BENCHMARK, ENCODE, DECODE and FORMAT could
only accept a constant for some parameters.
After this change, this restriction has been removed. An implication is that
these functions can also be used in prepared statements.
The change consist of changing the following classes:
- Item_func_benchmark
- Item_func_encode
- Item_func_decode
- Item_func_format
to:
- only accept Item* in the constructor,
- and evaluate arguments during calls to val_xxx()
which fits the general design of all the other functions.
The 'TODO' items identified in item_create.cc during the work done for
Bug 21114 are addressed by this fix, as a natural consequence of aligning
the design.
In the 'func_str' test, a single very long test line involving an explain
extended select with many functions has been rewritten into multiple
separate tests, to improve maintainability.
The result of explain extended select decode(encode(...)) has changed,
since the encode and decode functions now print all their parameters.
2006-11-16 17:03:47 +01:00
|
|
|
str->append(',');
|
2008-02-22 11:30:33 +01:00
|
|
|
args[1]->print(str, query_type);
|
2003-10-30 11:57:26 +01:00
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
2005-10-11 23:58:22 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** This function is just used to create tests with time gaps. */
|
2005-08-12 03:58:22 +02:00
|
|
|
|
|
|
|
longlong Item_func_sleep::val_int()
|
|
|
|
{
|
2005-08-17 01:31:16 +02:00
|
|
|
THD *thd= current_thd;
|
2010-10-14 03:54:07 +02:00
|
|
|
Interruptible_wait timed_cond(thd);
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_t cond;
|
2009-11-10 20:09:27 +01:00
|
|
|
double timeout;
|
2005-08-18 04:57:07 +02:00
|
|
|
int error;
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2005-08-12 03:58:22 +02:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2009-11-10 20:09:27 +01:00
|
|
|
timeout= args[0]->val_real();
|
2008-02-15 13:03:54 +01:00
|
|
|
/*
|
2010-01-12 02:47:27 +01:00
|
|
|
On 64-bit OSX mysql_cond_timedwait() waits forever
|
2008-02-15 13:03:54 +01:00
|
|
|
if passed abstime time has already been exceeded by
|
|
|
|
the system time.
|
|
|
|
When given a very short timeout (< 10 mcs) just return
|
|
|
|
immediately.
|
|
|
|
We assume that the lines between this test and the call
|
2009-12-10 04:19:51 +01:00
|
|
|
to mysql_cond_timedwait() will be executed in less than 0.00001 sec.
|
2008-02-15 13:03:54 +01:00
|
|
|
*/
|
2009-11-10 20:09:27 +01:00
|
|
|
if (timeout < 0.00001)
|
2008-02-15 13:03:54 +01:00
|
|
|
return 0;
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2010-10-14 03:54:07 +02:00
|
|
|
timed_cond.set_timeout((ulonglong) (timeout * 1000000000.0));
|
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_init(key_item_func_sleep_cond, &cond, NULL);
|
|
|
|
mysql_mutex_lock(&LOCK_user_locks);
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2008-03-07 15:41:50 +01:00
|
|
|
thd_proc_info(thd, "User sleep");
|
2005-08-17 01:31:16 +02:00
|
|
|
thd->mysys_var->current_mutex= &LOCK_user_locks;
|
|
|
|
thd->mysys_var->current_cond= &cond;
|
|
|
|
|
2005-10-11 23:58:22 +02:00
|
|
|
error= 0;
|
2011-03-04 13:12:31 +01:00
|
|
|
thd_wait_begin(thd, THD_WAIT_SLEEP);
|
2005-10-11 23:58:22 +02:00
|
|
|
while (!thd->killed)
|
|
|
|
{
|
2010-10-14 03:54:07 +02:00
|
|
|
error= timed_cond.wait(&cond, &LOCK_user_locks);
|
2005-10-11 23:58:22 +02:00
|
|
|
if (error == ETIMEDOUT || error == ETIME)
|
|
|
|
break;
|
|
|
|
error= 0;
|
|
|
|
}
|
2011-03-04 13:12:31 +01:00
|
|
|
thd_wait_end(thd);
|
2008-03-07 15:41:50 +01:00
|
|
|
thd_proc_info(thd, 0);
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
|
|
|
mysql_mutex_lock(&thd->mysys_var->mutex);
|
2005-08-17 01:31:16 +02:00
|
|
|
thd->mysys_var->current_mutex= 0;
|
|
|
|
thd->mysys_var->current_cond= 0;
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&thd->mysys_var->mutex);
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_cond_destroy(&cond);
|
2005-08-17 01:31:16 +02:00
|
|
|
|
2005-10-11 23:58:22 +02:00
|
|
|
return test(!error); // Return 1 killed
|
2005-08-12 03:58:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
#define extra_size sizeof(double)
|
|
|
|
|
|
|
|
static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
|
|
|
bool create_if_not_exists)
|
|
|
|
{
|
|
|
|
user_var_entry *entry;
|
|
|
|
|
2009-10-14 18:37:38 +02:00
|
|
|
if (!(entry = (user_var_entry*) my_hash_search(hash, (uchar*) name.str,
|
|
|
|
name.length)) &&
|
2000-07-31 21:29:14 +02:00
|
|
|
create_if_not_exists)
|
|
|
|
{
|
|
|
|
uint size=ALIGN_SIZE(sizeof(user_var_entry))+name.length+1+extra_size;
|
2009-10-14 18:37:38 +02:00
|
|
|
if (!my_hash_inited(hash))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
2009-11-10 21:31:28 +01:00
|
|
|
if (!(entry = (user_var_entry*) my_malloc(size,MYF(MY_WME | ME_FATALERROR))))
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
entry->name.str=(char*) entry+ ALIGN_SIZE(sizeof(user_var_entry))+
|
|
|
|
extra_size;
|
|
|
|
entry->name.length=name.length;
|
|
|
|
entry->value=0;
|
|
|
|
entry->length=0;
|
2001-03-15 10:55:44 +01:00
|
|
|
entry->update_query_id=0;
|
2007-08-03 12:25:23 +02:00
|
|
|
entry->collation.set(NULL, DERIVATION_IMPLICIT, 0);
|
2006-09-13 19:25:33 +02:00
|
|
|
entry->unsigned_flag= 0;
|
2003-10-02 10:31:37 +02:00
|
|
|
/*
|
|
|
|
If we are here, we were called from a SET or a query which sets a
|
|
|
|
variable. Imagine it is this:
|
|
|
|
INSERT INTO t SELECT @a:=10, @a:=@a+1.
|
|
|
|
Then when we have a Item_func_get_user_var (because of the @a+1) so we
|
|
|
|
think we have to write the value of @a to the binlog. But before that,
|
|
|
|
we have a Item_func_set_user_var to create @a (@a:=10), in this we mark
|
|
|
|
the variable as "already logged" (line below) so that it won't be logged
|
|
|
|
by Item_func_get_user_var (because that's not necessary).
|
|
|
|
*/
|
2003-01-30 18:39:54 +01:00
|
|
|
entry->used_query_id=current_thd->query_id;
|
2000-07-31 21:29:14 +02:00
|
|
|
entry->type=STRING_RESULT;
|
|
|
|
memcpy(entry->name.str, name.str, name.length+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_hash_insert(hash,(uchar*) entry))
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.
Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.
Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost.
The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.
Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.
2010-07-08 23:20:08 +02:00
|
|
|
my_free(entry);
|
2000-07-31 21:29:14 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
2008-09-18 10:38:44 +02:00
|
|
|
|
2009-01-23 19:18:02 +01:00
|
|
|
void Item_func_set_user_var::cleanup()
|
|
|
|
{
|
|
|
|
Item_func::cleanup();
|
|
|
|
entry= NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-18 10:38:44 +02:00
|
|
|
bool Item_func_set_user_var::set_entry(THD *thd, bool create_if_not_exists)
|
|
|
|
{
|
2008-11-20 12:25:26 +01:00
|
|
|
if (entry && thd->thread_id == entry_thread_id)
|
2008-09-18 14:24:09 +02:00
|
|
|
goto end; // update entry->update_query_id for PS
|
2008-09-18 10:38:44 +02:00
|
|
|
if (!(entry= get_variable(&thd->user_vars, name, create_if_not_exists)))
|
2008-11-20 12:25:26 +01:00
|
|
|
{
|
|
|
|
entry_thread_id= 0;
|
2008-09-18 10:38:44 +02:00
|
|
|
return TRUE;
|
2008-11-20 12:25:26 +01:00
|
|
|
}
|
|
|
|
entry_thread_id= thd->thread_id;
|
2012-11-07 14:38:33 +01:00
|
|
|
|
2008-09-18 14:24:09 +02:00
|
|
|
end:
|
2012-11-07 14:38:33 +01:00
|
|
|
/*
|
|
|
|
Remember the last query which updated it, this way a query can later know
|
|
|
|
if this variable is a constant item in the query (it is if update_query_id
|
|
|
|
is different from query_id).
|
|
|
|
|
|
|
|
If this object has delayed setting of non-constness, we delay this
|
|
|
|
until Item_func_set-user_var::save_item_result()
|
|
|
|
*/
|
|
|
|
if (!delayed_non_constness)
|
|
|
|
entry->update_query_id= thd->query_id;
|
2008-09-18 10:38:44 +02:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-10-02 10:31:37 +02:00
|
|
|
/*
|
2003-11-03 13:01:59 +01:00
|
|
|
When a user variable is updated (in a SET command or a query like
|
|
|
|
SELECT @a:= ).
|
2003-10-02 10:31:37 +02:00
|
|
|
*/
|
2003-03-03 10:16:39 +01:00
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-17 13:26:26 +01:00
|
|
|
DBUG_ASSERT(fixed == 0);
|
2002-12-14 16:43:01 +01:00
|
|
|
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
|
2008-09-18 10:38:44 +02:00
|
|
|
if (Item_func::fix_fields(thd, ref) || set_entry(thd, TRUE))
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE;
|
2004-11-05 10:37:36 +01:00
|
|
|
/*
|
|
|
|
As it is wrong and confusing to associate any
|
|
|
|
character set with NULL, @a should be latin2
|
|
|
|
after this query sequence:
|
|
|
|
|
|
|
|
SET @a=_latin2'string';
|
|
|
|
SET @a=NULL;
|
|
|
|
|
|
|
|
I.e. the second query should not change the charset
|
|
|
|
to the current default value, but should keep the
|
|
|
|
original value assigned during the first query.
|
|
|
|
In order to do it, we don't copy charset
|
|
|
|
from the argument if the argument is NULL
|
|
|
|
and the variable has previously been initialized.
|
|
|
|
*/
|
2005-04-30 02:14:42 +02:00
|
|
|
null_item= (args[0]->type() == NULL_ITEM);
|
|
|
|
if (!entry->collation.collation || !null_item)
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
entry->collation.set(args[0]->collation.derivation == DERIVATION_NUMERIC ?
|
|
|
|
default_charset() : args[0]->collation.collation,
|
|
|
|
DERIVATION_IMPLICIT);
|
2005-02-22 12:55:40 +01:00
|
|
|
collation.set(entry->collation.collation, DERIVATION_IMPLICIT);
|
2003-10-02 23:40:27 +02:00
|
|
|
cached_result_type= args[0]->result_type();
|
2004-10-20 03:04:37 +02:00
|
|
|
return FALSE;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
Item_func_set_user_var::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
maybe_null=args[0]->maybe_null;
|
|
|
|
decimals=args[0]->decimals;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set(DERIVATION_IMPLICIT);
|
|
|
|
if (args[0]->collation.derivation == DERIVATION_NUMERIC)
|
|
|
|
fix_length_and_charset(args[0]->max_char_length(), default_charset());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
fix_length_and_charset(args[0]->max_char_length(),
|
|
|
|
args[0]->collation.collation);
|
|
|
|
}
|
2011-03-28 10:28:30 +02:00
|
|
|
unsigned_flag= args[0]->unsigned_flag;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-10-02 23:40:27 +02:00
|
|
|
|
2007-06-03 19:52:00 +02:00
|
|
|
/*
|
|
|
|
Mark field in read_map
|
|
|
|
|
|
|
|
NOTES
|
|
|
|
This is used by filesort to register used fields in a a temporary
|
|
|
|
column read set or to register used fields in a view
|
|
|
|
*/
|
|
|
|
|
|
|
|
bool Item_func_set_user_var::register_field_in_read_map(uchar *arg)
|
|
|
|
{
|
2007-12-07 20:54:47 +01:00
|
|
|
if (result_field)
|
|
|
|
{
|
|
|
|
TABLE *table= (TABLE *) arg;
|
|
|
|
if (result_field->table == table || !table)
|
|
|
|
bitmap_set_bit(result_field->table->read_set, result_field->field_index);
|
|
|
|
}
|
2007-06-03 19:52:00 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2005-03-16 02:32:47 +01:00
|
|
|
Set value to user variable.
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@param entry pointer to structure representing variable
|
|
|
|
@param set_null should we set NULL value ?
|
|
|
|
@param ptr pointer to buffer with new value
|
|
|
|
@param length length of new value
|
|
|
|
@param type type of new value
|
|
|
|
@param cs charset info for new value
|
|
|
|
@param dv derivation for new value
|
|
|
|
@param unsigned_arg indiates if a value of type INT_RESULT is unsigned
|
|
|
|
|
2009-11-10 21:31:28 +01:00
|
|
|
@note Sets error and fatal error if allocation fails.
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
|
|
|
false success
|
|
|
|
@retval
|
|
|
|
true failure
|
2005-03-16 02:32:47 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
static bool
|
|
|
|
update_hash(user_var_entry *entry, bool set_null, void *ptr, uint length,
|
2006-06-09 19:35:54 +02:00
|
|
|
Item_result type, CHARSET_INFO *cs, Derivation dv,
|
|
|
|
bool unsigned_arg)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2005-03-16 02:32:47 +01:00
|
|
|
if (set_null)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
|
|
|
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
|
|
|
if (entry->value && entry->value != pos)
|
Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.
Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.
Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost.
The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.
Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.
2010-07-08 23:20:08 +02:00
|
|
|
my_free(entry->value);
|
2005-04-30 02:14:42 +02:00
|
|
|
entry->value= 0;
|
|
|
|
entry->length= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2003-10-02 23:40:27 +02:00
|
|
|
if (type == STRING_RESULT)
|
|
|
|
length++; // Store strings with end \0
|
2000-07-31 21:29:14 +02:00
|
|
|
if (length <= extra_size)
|
|
|
|
{
|
|
|
|
/* Save value in value struct */
|
|
|
|
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
|
|
|
if (entry->value != pos)
|
|
|
|
{
|
|
|
|
if (entry->value)
|
Bug#34043: Server loops excessively in _checkchunk() when safemalloc is enabled
Essentially, the problem is that safemalloc is excruciatingly
slow as it checks all allocated blocks for overrun at each
memory management primitive, yielding a almost exponential
slowdown for the memory management functions (malloc, realloc,
free). The overrun check basically consists of verifying some
bytes of a block for certain magic keys, which catches some
simple forms of overrun. Another minor problem is violation
of aliasing rules and that its own internal list of blocks
is prone to corruption.
Another issue with safemalloc is rather the maintenance cost
as the tool has a significant impact on the server code.
Given the magnitude of memory debuggers available nowadays,
especially those that are provided with the platform malloc
implementation, maintenance of a in-house and largely obsolete
memory debugger becomes a burden that is not worth the effort
due to its slowness and lack of support for detecting more
common forms of heap corruption.
Since there are third-party tools that can provide the same
functionality at a lower or comparable performance cost, the
solution is to simply remove safemalloc. Third-party tools
can provide the same functionality at a lower or comparable
performance cost.
The removal of safemalloc also allows a simplification of the
malloc wrappers, removing quite a bit of kludge: redefinition
of my_malloc, my_free and the removal of the unused second
argument of my_free. Since free() always check whether the
supplied pointer is null, redudant checks are also removed.
Also, this patch adds unit testing for my_malloc and moves
my_realloc implementation into the same file as the other
memory allocation primitives.
2010-07-08 23:20:08 +02:00
|
|
|
my_free(entry->value);
|
2000-07-31 21:29:14 +02:00
|
|
|
entry->value=pos;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* Allocate variable */
|
|
|
|
if (entry->length != length)
|
|
|
|
{
|
|
|
|
char *pos= (char*) entry+ ALIGN_SIZE(sizeof(user_var_entry));
|
|
|
|
if (entry->value == pos)
|
|
|
|
entry->value=0;
|
2007-01-09 10:24:25 +01:00
|
|
|
entry->value= (char*) my_realloc(entry->value, length,
|
2009-11-10 21:31:28 +01:00
|
|
|
MYF(MY_ALLOW_ZERO_PTR | MY_WME |
|
|
|
|
ME_FATALERROR));
|
2007-01-09 10:24:25 +01:00
|
|
|
if (!entry->value)
|
2005-03-16 02:32:47 +01:00
|
|
|
return 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
if (type == STRING_RESULT)
|
|
|
|
{
|
|
|
|
length--; // Fix length change above
|
|
|
|
entry->value[length]= 0; // Store end \0
|
|
|
|
}
|
2010-11-22 09:57:59 +01:00
|
|
|
memmove(entry->value, ptr, length);
|
2005-02-08 23:50:45 +01:00
|
|
|
if (type == DECIMAL_RESULT)
|
|
|
|
((my_decimal*)entry->value)->fix_buffer_pointer();
|
2000-07-31 21:29:14 +02:00
|
|
|
entry->length= length;
|
2003-06-24 12:11:07 +02:00
|
|
|
entry->collation.set(cs, dv);
|
2006-09-13 19:25:33 +02:00
|
|
|
entry->unsigned_flag= unsigned_arg;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2005-04-30 02:14:42 +02:00
|
|
|
entry->type=type;
|
2003-10-02 23:40:27 +02:00
|
|
|
return 0;
|
2005-03-16 02:32:47 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-03-16 02:32:47 +01:00
|
|
|
|
|
|
|
bool
|
2006-12-14 23:51:37 +01:00
|
|
|
Item_func_set_user_var::update_hash(void *ptr, uint length,
|
|
|
|
Item_result res_type,
|
2006-06-09 19:35:54 +02:00
|
|
|
CHARSET_INFO *cs, Derivation dv,
|
|
|
|
bool unsigned_arg)
|
2005-03-16 02:32:47 +01:00
|
|
|
{
|
2005-04-30 02:14:42 +02:00
|
|
|
/*
|
|
|
|
If we set a variable explicitely to NULL then keep the old
|
|
|
|
result type of the variable
|
|
|
|
*/
|
|
|
|
if ((null_value= args[0]->null_value) && null_item)
|
2006-12-14 23:51:37 +01:00
|
|
|
res_type= entry->type; // Don't change type of item
|
2005-03-16 02:32:47 +01:00
|
|
|
if (::update_hash(entry, (null_value= args[0]->null_value),
|
2006-12-14 23:51:37 +01:00
|
|
|
ptr, length, res_type, cs, dv, unsigned_arg))
|
2005-03-16 02:32:47 +01:00
|
|
|
{
|
|
|
|
null_value= 1;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** Get the value of a variable as a double. */
|
2003-10-02 23:40:27 +02:00
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
double user_var_entry::val_real(my_bool *null_value)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-02 23:40:27 +02:00
|
|
|
if ((*null_value= (value == 0)))
|
|
|
|
return 0.0;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case REAL_RESULT:
|
|
|
|
return *(double*) value;
|
|
|
|
case INT_RESULT:
|
|
|
|
return (double) *(longlong*) value;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
double result;
|
|
|
|
my_decimal2double(E_DEC_FATAL_ERROR, (my_decimal *)value, &result);
|
|
|
|
return result;
|
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
case STRING_RESULT:
|
2004-02-13 15:27:21 +01:00
|
|
|
return my_atof(value); // This is null terminated
|
2003-10-11 22:26:39 +02:00
|
|
|
case ROW_RESULT:
|
|
|
|
DBUG_ASSERT(1); // Impossible
|
|
|
|
break;
|
2003-09-25 01:30:20 +02:00
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
return 0.0; // Impossible
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** Get the value of a variable as an integer. */
|
2003-10-02 23:40:27 +02:00
|
|
|
|
2008-02-28 15:34:08 +01:00
|
|
|
longlong user_var_entry::val_int(my_bool *null_value) const
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-02 23:40:27 +02:00
|
|
|
if ((*null_value= (value == 0)))
|
|
|
|
return LL(0);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case REAL_RESULT:
|
|
|
|
return (longlong) *(double*) value;
|
|
|
|
case INT_RESULT:
|
|
|
|
return *(longlong*) value;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
longlong result;
|
2005-05-27 14:48:33 +02:00
|
|
|
my_decimal2int(E_DEC_FATAL_ERROR, (my_decimal *)value, 0, &result);
|
2005-02-08 23:50:45 +01:00
|
|
|
return result;
|
|
|
|
}
|
2003-09-25 01:30:20 +02:00
|
|
|
case STRING_RESULT:
|
2004-05-12 01:38:57 +02:00
|
|
|
{
|
|
|
|
int error;
|
|
|
|
return my_strtoll10(value, (char**) 0, &error);// String is null terminated
|
|
|
|
}
|
2003-10-11 22:26:39 +02:00
|
|
|
case ROW_RESULT:
|
|
|
|
DBUG_ASSERT(1); // Impossible
|
|
|
|
break;
|
2003-09-25 01:30:20 +02:00
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
return LL(0); // Impossible
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** Get the value of a variable as a string. */
|
2003-10-02 23:40:27 +02:00
|
|
|
|
|
|
|
String *user_var_entry::val_str(my_bool *null_value, String *str,
|
|
|
|
uint decimals)
|
|
|
|
{
|
|
|
|
if ((*null_value= (value == 0)))
|
|
|
|
return (String*) 0;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case REAL_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set_real(*(double*) value, decimals, collation.collation);
|
2003-10-02 23:40:27 +02:00
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
2006-06-09 19:35:54 +02:00
|
|
|
if (!unsigned_flag)
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set(*(longlong*) value, collation.collation);
|
2006-06-09 19:35:54 +02:00
|
|
|
else
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str->set(*(ulonglong*) value, collation.collation);
|
2003-10-02 23:40:27 +02:00
|
|
|
break;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
str_set_decimal((my_decimal *) value, str, collation.collation);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
2003-10-02 23:40:27 +02:00
|
|
|
case STRING_RESULT:
|
2003-10-07 14:42:26 +02:00
|
|
|
if (str->copy(value, length, collation.collation))
|
2003-10-02 23:40:27 +02:00
|
|
|
str= 0; // EOM error
|
2003-10-11 22:26:39 +02:00
|
|
|
case ROW_RESULT:
|
|
|
|
DBUG_ASSERT(1); // Impossible
|
|
|
|
break;
|
2003-09-25 01:30:20 +02:00
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
return(str);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/** Get the value of a variable as a decimal. */
|
2005-02-08 23:50:45 +01:00
|
|
|
|
|
|
|
my_decimal *user_var_entry::val_decimal(my_bool *null_value, my_decimal *val)
|
|
|
|
{
|
|
|
|
if ((*null_value= (value == 0)))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case REAL_RESULT:
|
|
|
|
double2my_decimal(E_DEC_FATAL_ERROR, *(double*) value, val);
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
|
|
|
int2my_decimal(E_DEC_FATAL_ERROR, *(longlong*) value, 0, val);
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
2010-12-06 21:38:31 +01:00
|
|
|
my_decimal2decimal((my_decimal *) value, val);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
|
|
|
str2my_decimal(E_DEC_FATAL_ERROR, value, length, collation.collation, val);
|
|
|
|
break;
|
|
|
|
case ROW_RESULT:
|
|
|
|
DBUG_ASSERT(1); // Impossible
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return(val);
|
|
|
|
}
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
This functions is invoked on SET \@variable or
|
|
|
|
\@variable:= expression.
|
2003-10-24 16:28:32 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
Evaluate (and check expression), store results.
|
2003-10-24 16:28:32 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@note
|
2005-02-08 23:50:45 +01:00
|
|
|
For now it always return OK. All problem with value evaluating
|
2007-10-30 18:08:16 +01:00
|
|
|
will be caught by thd->is_error() check in sql_set_variables().
|
2003-10-24 16:28:32 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
2004-10-20 03:04:37 +02:00
|
|
|
FALSE OK.
|
2003-10-24 16:28:32 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
bool
|
2006-08-22 15:37:41 +02:00
|
|
|
Item_func_set_user_var::check(bool use_result_field)
|
2003-10-24 16:28:32 +02:00
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_set_user_var::check");
|
2007-06-02 23:24:56 +02:00
|
|
|
if (use_result_field && !result_field)
|
|
|
|
use_result_field= FALSE;
|
2003-10-24 16:28:32 +02:00
|
|
|
|
|
|
|
switch (cached_result_type) {
|
|
|
|
case REAL_RESULT:
|
|
|
|
{
|
2006-08-22 15:37:41 +02:00
|
|
|
save_result.vreal= use_result_field ? result_field->val_real() :
|
|
|
|
args[0]->val_real();
|
2003-10-24 16:28:32 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case INT_RESULT:
|
|
|
|
{
|
2006-08-22 15:37:41 +02:00
|
|
|
save_result.vint= use_result_field ? result_field->val_int() :
|
|
|
|
args[0]->val_int();
|
|
|
|
unsigned_flag= use_result_field ? ((Field_num*)result_field)->unsigned_flag:
|
|
|
|
args[0]->unsigned_flag;
|
2003-10-24 16:28:32 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case STRING_RESULT:
|
|
|
|
{
|
2006-08-22 15:37:41 +02:00
|
|
|
save_result.vstr= use_result_field ? result_field->val_str(&value) :
|
|
|
|
args[0]->val_str(&value);
|
2003-10-24 16:28:32 +02:00
|
|
|
break;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
2006-08-22 15:37:41 +02:00
|
|
|
save_result.vdec= use_result_field ?
|
|
|
|
result_field->val_decimal(&decimal_buff) :
|
|
|
|
args[0]->val_decimal(&decimal_buff);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
}
|
2003-10-24 16:28:32 +02:00
|
|
|
case ROW_RESULT:
|
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2003-10-24 16:28:32 +02:00
|
|
|
DBUG_ASSERT(0);
|
|
|
|
break;
|
|
|
|
}
|
2004-10-20 03:04:37 +02:00
|
|
|
DBUG_RETURN(FALSE);
|
2003-10-24 16:28:32 +02:00
|
|
|
}
|
|
|
|
|
2003-10-02 23:40:27 +02:00
|
|
|
|
2009-02-24 15:47:12 +01:00
|
|
|
/**
|
|
|
|
@brief Evaluate and store item's result.
|
|
|
|
This function is invoked on "SELECT ... INTO @var ...".
|
|
|
|
|
|
|
|
@param item An item to get value from.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void Item_func_set_user_var::save_item_result(Item *item)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_set_user_var::save_item_result");
|
|
|
|
|
|
|
|
switch (cached_result_type) {
|
|
|
|
case REAL_RESULT:
|
|
|
|
save_result.vreal= item->val_result();
|
|
|
|
break;
|
|
|
|
case INT_RESULT:
|
|
|
|
save_result.vint= item->val_int_result();
|
|
|
|
unsigned_flag= item->unsigned_flag;
|
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
|
|
|
save_result.vstr= item->str_result(&value);
|
|
|
|
break;
|
|
|
|
case DECIMAL_RESULT:
|
|
|
|
save_result.vdec= item->val_decimal_result(&decimal_buff);
|
|
|
|
break;
|
|
|
|
case ROW_RESULT:
|
|
|
|
default:
|
|
|
|
// Should never happen
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
break;
|
|
|
|
}
|
2012-11-07 14:38:33 +01:00
|
|
|
/*
|
|
|
|
Set the ID of the query that last updated this variable. This is
|
|
|
|
usually set by Item_func_set_user_var::set_entry(), but if this
|
|
|
|
item has delayed setting of non-constness, we must do it now.
|
|
|
|
*/
|
|
|
|
if (delayed_non_constness)
|
|
|
|
entry->update_query_id= current_thd->query_id;
|
2009-02-24 15:47:12 +01:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
This functions is invoked on
|
|
|
|
SET \@variable or \@variable:= expression.
|
2003-10-02 23:40:27 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@note
|
2003-10-02 23:40:27 +02:00
|
|
|
We have to store the expression as such in the variable, independent of
|
|
|
|
the value method used by the user
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
2005-02-08 23:50:45 +01:00
|
|
|
0 OK
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
2003-10-02 23:40:27 +02:00
|
|
|
1 EOM Error
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
bool
|
|
|
|
Item_func_set_user_var::update()
|
|
|
|
{
|
2009-09-24 15:21:46 +02:00
|
|
|
bool res= 0;
|
2003-10-02 23:40:27 +02:00
|
|
|
DBUG_ENTER("Item_func_set_user_var::update");
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
switch (cached_result_type) {
|
|
|
|
case REAL_RESULT:
|
2003-09-25 01:30:20 +02:00
|
|
|
{
|
2003-10-24 16:28:32 +02:00
|
|
|
res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal),
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
REAL_RESULT, default_charset(), DERIVATION_IMPLICIT, 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
2003-09-25 01:30:20 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
case INT_RESULT:
|
2003-10-02 23:40:27 +02:00
|
|
|
{
|
2003-10-24 16:28:32 +02:00
|
|
|
res= update_hash((void*) &save_result.vint, sizeof(save_result.vint),
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
INT_RESULT, default_charset(), DERIVATION_IMPLICIT,
|
2006-06-09 19:35:54 +02:00
|
|
|
unsigned_flag);
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
2003-09-25 01:30:20 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
case STRING_RESULT:
|
2002-11-15 19:32:09 +01:00
|
|
|
{
|
2003-10-24 16:28:32 +02:00
|
|
|
if (!save_result.vstr) // Null value
|
2003-10-07 14:42:26 +02:00
|
|
|
res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin,
|
2006-09-13 19:25:33 +02:00
|
|
|
DERIVATION_IMPLICIT, 0);
|
2003-10-02 23:40:27 +02:00
|
|
|
else
|
2003-10-24 16:28:32 +02:00
|
|
|
res= update_hash((void*) save_result.vstr->ptr(),
|
|
|
|
save_result.vstr->length(), STRING_RESULT,
|
|
|
|
save_result.vstr->charset(),
|
2006-09-13 19:25:33 +02:00
|
|
|
DERIVATION_IMPLICIT, 0);
|
2000-07-31 21:29:14 +02:00
|
|
|
break;
|
|
|
|
}
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
|
|
|
{
|
|
|
|
if (!save_result.vdec) // Null value
|
|
|
|
res= update_hash((void*) 0, 0, DECIMAL_RESULT, &my_charset_bin,
|
2006-09-12 16:28:36 +02:00
|
|
|
DERIVATION_IMPLICIT, 0);
|
2005-02-08 23:50:45 +01:00
|
|
|
else
|
|
|
|
res= update_hash((void*) save_result.vdec,
|
|
|
|
sizeof(my_decimal), DECIMAL_RESULT,
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
default_charset(), DERIVATION_IMPLICIT, 0);
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
|
|
|
}
|
2003-02-17 15:06:51 +01:00
|
|
|
case ROW_RESULT:
|
2003-01-31 11:07:07 +01:00
|
|
|
default:
|
2005-02-08 23:50:45 +01:00
|
|
|
// This case should never be chosen
|
2002-11-15 19:32:09 +01:00
|
|
|
DBUG_ASSERT(0);
|
|
|
|
break;
|
|
|
|
}
|
2003-10-02 23:40:27 +02:00
|
|
|
DBUG_RETURN(res);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_set_user_var::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2006-08-22 15:37:41 +02:00
|
|
|
check(0);
|
2003-10-02 23:40:27 +02:00
|
|
|
update(); // Store expression
|
2005-02-08 23:50:45 +01:00
|
|
|
return entry->val_real(&null_value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-10-02 23:40:27 +02:00
|
|
|
longlong Item_func_set_user_var::val_int()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2006-08-22 15:37:41 +02:00
|
|
|
check(0);
|
2003-10-02 23:40:27 +02:00
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_int(&null_value);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2003-10-02 23:40:27 +02:00
|
|
|
String *Item_func_set_user_var::val_str(String *str)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2006-08-22 15:37:41 +02:00
|
|
|
check(0);
|
2003-10-02 23:40:27 +02:00
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_str(&null_value, str, decimals);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-02-08 23:50:45 +01:00
|
|
|
my_decimal *Item_func_set_user_var::val_decimal(my_decimal *val)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2006-08-22 15:37:41 +02:00
|
|
|
check(0);
|
2005-02-08 23:50:45 +01:00
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_decimal(&null_value, val);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-06-03 13:56:48 +02:00
|
|
|
double Item_func_set_user_var::val_result()
|
2007-06-02 21:17:46 +02:00
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_real(&null_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
longlong Item_func_set_user_var::val_int_result()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_int(&null_value);
|
|
|
|
}
|
|
|
|
|
2010-08-13 13:20:49 +02:00
|
|
|
bool Item_func_set_user_var::val_bool_result()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_int(&null_value) != 0;
|
|
|
|
}
|
|
|
|
|
2007-06-03 13:56:48 +02:00
|
|
|
String *Item_func_set_user_var::str_result(String *str)
|
2007-06-02 21:17:46 +02:00
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_str(&null_value, str, decimals);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_set_user_var::val_decimal_result(my_decimal *val)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return entry->val_decimal(&null_value, val);
|
2005-02-08 23:50:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-17 12:55:16 +02:00
|
|
|
bool Item_func_set_user_var::is_null_result()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
check(TRUE);
|
|
|
|
update(); // Store expression
|
|
|
|
return is_null();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_set_user_var::print(String *str, enum_query_type query_type)
|
2001-12-27 01:04:27 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("(@"));
|
2003-10-30 11:57:26 +01:00
|
|
|
str->append(name.str, name.length);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(":="));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2001-12-27 01:04:27 +01:00
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_set_user_var::print_as_stmt(String *str,
|
|
|
|
enum_query_type query_type)
|
2004-09-07 14:29:46 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("set @"));
|
2004-09-07 14:29:46 +02:00
|
|
|
str->append(name.str, name.length);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(":="));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2004-09-07 14:29:46 +02:00
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
2006-08-22 15:37:41 +02:00
|
|
|
bool Item_func_set_user_var::send(Protocol *protocol, String *str_arg)
|
|
|
|
{
|
|
|
|
if (result_field)
|
|
|
|
{
|
|
|
|
check(1);
|
|
|
|
update();
|
|
|
|
return protocol->store(result_field);
|
|
|
|
}
|
|
|
|
return Item::send(protocol, str_arg);
|
|
|
|
}
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2006-08-22 23:03:28 +02:00
|
|
|
void Item_func_set_user_var::make_field(Send_field *tmp_field)
|
|
|
|
{
|
|
|
|
if (result_field)
|
|
|
|
{
|
|
|
|
result_field->make_field(tmp_field);
|
|
|
|
DBUG_ASSERT(tmp_field->table_name != 0);
|
|
|
|
if (Item::name)
|
|
|
|
tmp_field->col_name=Item::name; // Use user supplied name
|
|
|
|
}
|
|
|
|
else
|
|
|
|
Item::make_field(tmp_field);
|
|
|
|
}
|
2004-09-07 14:29:46 +02:00
|
|
|
|
2007-01-09 21:24:56 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Save the value of a user variable into a field
|
|
|
|
|
|
|
|
SYNOPSIS
|
|
|
|
save_in_field()
|
|
|
|
field target field to save the value to
|
|
|
|
no_conversion flag indicating whether conversions are allowed
|
|
|
|
|
|
|
|
DESCRIPTION
|
|
|
|
Save the function value into a field and update the user variable
|
|
|
|
accordingly. If a result field is defined and the target field doesn't
|
|
|
|
coincide with it then the value from the result field will be used as
|
|
|
|
the new value of the user variable.
|
|
|
|
|
|
|
|
The reason to have this method rather than simply using the result
|
|
|
|
field in the val_xxx() methods is that the value from the result field
|
|
|
|
not always can be used when the result field is defined.
|
|
|
|
Let's consider the following cases:
|
|
|
|
1) when filling a tmp table the result field is defined but the value of it
|
|
|
|
is undefined because it has to be produced yet. Thus we can't use it.
|
|
|
|
2) on execution of an INSERT ... SELECT statement the save_in_field()
|
|
|
|
function will be called to fill the data in the new record. If the SELECT
|
|
|
|
part uses a tmp table then the result field is defined and should be
|
|
|
|
used in order to get the correct result.
|
|
|
|
|
|
|
|
The difference between the SET_USER_VAR function and regular functions
|
|
|
|
like CONCAT is that the Item_func objects for the regular functions are
|
|
|
|
replaced by Item_field objects after the values of these functions have
|
|
|
|
been stored in a tmp table. Yet an object of the Item_field class cannot
|
|
|
|
be used to update a user variable.
|
|
|
|
Due to this we have to handle the result field in a special way here and
|
|
|
|
in the Item_func_set_user_var::send() function.
|
|
|
|
|
|
|
|
RETURN VALUES
|
|
|
|
FALSE Ok
|
|
|
|
TRUE Error
|
|
|
|
*/
|
|
|
|
|
2007-05-31 23:17:14 +02:00
|
|
|
int Item_func_set_user_var::save_in_field(Field *field, bool no_conversions,
|
|
|
|
bool can_use_result_field)
|
2007-01-09 21:24:56 +01:00
|
|
|
{
|
2007-05-31 23:17:14 +02:00
|
|
|
bool use_result_field= (!can_use_result_field ? 0 :
|
|
|
|
(result_field && result_field != field));
|
2007-01-09 21:24:56 +01:00
|
|
|
int error;
|
|
|
|
|
|
|
|
/* Update the value of the user variable */
|
|
|
|
check(use_result_field);
|
|
|
|
update();
|
|
|
|
|
|
|
|
if (result_type() == STRING_RESULT ||
|
2009-06-09 14:55:30 +02:00
|
|
|
(result_type() == REAL_RESULT &&
|
|
|
|
field->result_type() == STRING_RESULT))
|
2007-01-09 21:24:56 +01:00
|
|
|
{
|
|
|
|
String *result;
|
|
|
|
CHARSET_INFO *cs= collation.collation;
|
|
|
|
char buff[MAX_FIELD_WIDTH]; // Alloc buffer for small columns
|
|
|
|
str_value.set_quick(buff, sizeof(buff), cs);
|
|
|
|
result= entry->val_str(&null_value, &str_value, decimals);
|
|
|
|
|
|
|
|
if (null_value)
|
|
|
|
{
|
|
|
|
str_value.set_quick(0, 0, cs);
|
|
|
|
return set_field_to_null_with_conversions(field, no_conversions);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* NOTE: If null_value == FALSE, "result" must be not NULL. */
|
|
|
|
|
|
|
|
field->set_notnull();
|
|
|
|
error=field->store(result->ptr(),result->length(),cs);
|
|
|
|
str_value.set_quick(0, 0, cs);
|
|
|
|
}
|
|
|
|
else if (result_type() == REAL_RESULT)
|
|
|
|
{
|
|
|
|
double nr= entry->val_real(&null_value);
|
|
|
|
if (null_value)
|
|
|
|
return set_field_to_null(field);
|
|
|
|
field->set_notnull();
|
|
|
|
error=field->store(nr);
|
|
|
|
}
|
|
|
|
else if (result_type() == DECIMAL_RESULT)
|
|
|
|
{
|
|
|
|
my_decimal decimal_value;
|
2007-08-13 15:11:25 +02:00
|
|
|
my_decimal *val= entry->val_decimal(&null_value, &decimal_value);
|
2007-01-09 21:24:56 +01:00
|
|
|
if (null_value)
|
|
|
|
return set_field_to_null(field);
|
|
|
|
field->set_notnull();
|
2007-08-13 15:11:25 +02:00
|
|
|
error=field->store_decimal(val);
|
2007-01-09 21:24:56 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
longlong nr= entry->val_int(&null_value);
|
|
|
|
if (null_value)
|
|
|
|
return set_field_to_null_with_conversions(field, no_conversions);
|
|
|
|
field->set_notnull();
|
|
|
|
error=field->store(nr, unsigned_flag);
|
|
|
|
}
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
String *
|
|
|
|
Item_func_get_user_var::val_str(String *str)
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-09-25 01:30:20 +02:00
|
|
|
DBUG_ENTER("Item_func_get_user_var::val_str");
|
2003-10-02 23:40:27 +02:00
|
|
|
if (!var_entry)
|
2003-12-21 18:39:32 +01:00
|
|
|
DBUG_RETURN((String*) 0); // No such variable
|
2003-10-02 23:40:27 +02:00
|
|
|
DBUG_RETURN(var_entry->val_str(&null_value, str, decimals));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_get_user_var::val_real()
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-10-02 23:40:27 +02:00
|
|
|
if (!var_entry)
|
|
|
|
return 0.0; // No such variable
|
2005-02-08 23:50:45 +01:00
|
|
|
return (var_entry->val_real(&null_value));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal *Item_func_get_user_var::val_decimal(my_decimal *dec)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
if (!var_entry)
|
|
|
|
return 0;
|
|
|
|
return var_entry->val_decimal(&null_value, dec);
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_get_user_var::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-10-02 23:40:27 +02:00
|
|
|
if (!var_entry)
|
|
|
|
return LL(0); // No such variable
|
|
|
|
return (var_entry->val_int(&null_value));
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2004-06-01 15:27:40 +02:00
|
|
|
Get variable by name and, if necessary, put the record of variable
|
|
|
|
use into the binary log.
|
|
|
|
|
2003-10-02 10:31:37 +02:00
|
|
|
When a user variable is invoked from an update query (INSERT, UPDATE etc),
|
|
|
|
stores this variable and its value in thd->user_var_events, so that it can be
|
|
|
|
written to the binlog (will be written just before the query is written, see
|
|
|
|
log.cc).
|
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
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@param thd Current thread
|
|
|
|
@param name Variable name
|
|
|
|
@param[out] out_entry variable structure or NULL. The pointer is set
|
|
|
|
regardless of whether function succeeded or not.
|
|
|
|
|
|
|
|
@retval
|
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
|
|
|
0 OK
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
2005-02-08 23:50:45 +01:00
|
|
|
1 Failed to put appropriate record into binary log
|
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
|
|
|
|
2003-10-02 10:31:37 +02:00
|
|
|
*/
|
|
|
|
|
2011-07-07 13:22:43 +02:00
|
|
|
static int
|
|
|
|
get_var_with_binlog(THD *thd, enum_sql_command sql_command,
|
|
|
|
LEX_STRING &name, user_var_entry **out_entry)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-02 10:31:37 +02:00
|
|
|
BINLOG_USER_VAR_EVENT *user_var_event;
|
2004-06-01 15:27:40 +02:00
|
|
|
user_var_entry *var_entry;
|
|
|
|
var_entry= get_variable(&thd->user_vars, name, 0);
|
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
|
|
|
|
2007-02-26 20:06:10 +01:00
|
|
|
/*
|
|
|
|
Any reference to user-defined variable which is done from stored
|
2007-02-23 18:58:56 +01:00
|
|
|
function or trigger affects their execution and the execution of the
|
|
|
|
calling statement. We must log all such variables even if they are
|
|
|
|
not involved in table-updating statements.
|
2007-02-26 20:06:10 +01:00
|
|
|
*/
|
|
|
|
if (!(opt_bin_log &&
|
|
|
|
(is_update_query(sql_command) || thd->in_sub_stmt)))
|
2004-06-01 15:27:40 +02:00
|
|
|
{
|
|
|
|
*out_entry= var_entry;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-10-02 16:19:33 +02:00
|
|
|
|
|
|
|
if (!var_entry)
|
2003-01-30 18:39:54 +01:00
|
|
|
{
|
2003-10-02 10:31:37 +02:00
|
|
|
/*
|
2003-10-02 16:19:33 +02:00
|
|
|
If the variable does not exist, it's NULL, but we want to create it so
|
|
|
|
that it gets into the binlog (if it didn't, the slave could be
|
|
|
|
influenced by a variable of the same name previously set by another
|
|
|
|
thread).
|
2005-02-08 23:50:45 +01:00
|
|
|
We create it like if it had been explicitly set with SET before.
|
|
|
|
The 'new' mimics what sql_yacc.yy does when 'SET @a=10;'.
|
2003-10-02 10:31:37 +02:00
|
|
|
sql_set_variables() is what is called from 'case SQLCOM_SET_OPTION'
|
|
|
|
in dispatch_command()). Instead of building a one-element list to pass to
|
|
|
|
sql_set_variables(), we could instead manually call check() and update();
|
2003-11-03 13:01:59 +01:00
|
|
|
this would save memory and time; but calling sql_set_variables() makes
|
|
|
|
one unique place to maintain (sql_set_variables()).
|
2006-05-05 10:21:21 +02:00
|
|
|
|
|
|
|
Manipulation with lex is necessary since free_underlaid_joins
|
|
|
|
is going to release memory belonging to the main query.
|
2003-10-02 10:31:37 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
List<set_var_base> tmp_var_list;
|
2006-05-05 10:21:21 +02:00
|
|
|
LEX *sav_lex= thd->lex, lex_tmp;
|
|
|
|
thd->lex= &lex_tmp;
|
Bug#25411 (trigger code truncated), PART I
The issue found with bug 25411 is due to the function skip_rear_comments()
which damages the source code while implementing a work around.
The root cause of the problem is in the lexical analyser, which does not
process special comments properly.
For special comments like :
[1] aaa /*!50000 bbb */ ccc
since 5.0 is a version older that the current code, the parser is in lining
the content of the special comment, so that the query to process is
[2] aaa bbb ccc
However, the text of the query captured when processing a stored procedure,
stored function or trigger (or event in 5.1), can be after rebuilding it:
[3] aaa bbb */ ccc
which is wrong.
To fix bug 25411 properly, the lexical analyser needs to return [2] when
in lining special comments.
In order to implement this, some preliminary cleanup is required in the code,
which is implemented by this patch.
Before this change, the structure named LEX (or st_lex) contains attributes
that belong to lexical analysis, as well as attributes that represents the
abstract syntax tree (AST) of a statement.
Creating a new LEX structure for each statements (which makes sense for the
AST part) also re-initialized the lexical analysis phase each time, which
is conceptually wrong.
With this patch, the previous st_lex structure has been split in two:
- st_lex represents the Abstract Syntax Tree for a statement. The name "lex"
has not been changed to avoid a bigger impact in the code base.
- class lex_input_stream represents the internal state of the lexical
analyser, which by definition should *not* be reinitialized when parsing
multiple statements from the same input stream.
This change is a pre-requisite for bug 25411, since the implementation of
lex_input_stream will later improve to deal properly with special comments,
and this processing can not be done with the current implementation of
sp_head::reset_lex and sp_head::restore_lex, which interfere with the lexer.
This change set alone does not fix bug 25411.
2007-04-24 17:24:21 +02:00
|
|
|
lex_start(thd);
|
2003-10-02 10:31:37 +02:00
|
|
|
tmp_var_list.push_back(new set_var_user(new Item_func_set_user_var(name,
|
2012-11-07 14:38:33 +01:00
|
|
|
new Item_null(),
|
|
|
|
false)));
|
2003-11-03 13:01:59 +01:00
|
|
|
/* Create the variable */
|
|
|
|
if (sql_set_variables(thd, &tmp_var_list))
|
2006-05-05 10:21:21 +02:00
|
|
|
{
|
|
|
|
thd->lex= sav_lex;
|
2003-10-02 10:31:37 +02:00
|
|
|
goto err;
|
2006-05-05 10:21:21 +02:00
|
|
|
}
|
|
|
|
thd->lex= sav_lex;
|
2003-10-02 10:31:37 +02:00
|
|
|
if (!(var_entry= get_variable(&thd->user_vars, name, 0)))
|
|
|
|
goto err;
|
|
|
|
}
|
2005-09-07 17:39:47 +02:00
|
|
|
else if (var_entry->used_query_id == thd->query_id ||
|
|
|
|
mysql_bin_log.is_query_in_union(thd, var_entry->used_query_id))
|
2004-06-01 15:27:40 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
If this variable was already stored in user_var_events by this query
|
|
|
|
(because it's used in more than one place in the query), don't store
|
|
|
|
it.
|
|
|
|
*/
|
|
|
|
*out_entry= var_entry;
|
|
|
|
return 0;
|
|
|
|
}
|
2003-10-02 10:31:37 +02:00
|
|
|
|
|
|
|
uint size;
|
|
|
|
/*
|
|
|
|
First we need to store value of var_entry, when the next situation
|
2005-02-08 23:50:45 +01:00
|
|
|
appears:
|
2003-10-02 10:31:37 +02:00
|
|
|
> set @a:=1;
|
|
|
|
> insert into t1 values (@a), (@a:=@a+1), (@a:=@a+1);
|
2005-09-07 17:39:47 +02:00
|
|
|
We have to write to binlog value @a= 1.
|
2007-05-18 12:44:03 +02:00
|
|
|
|
2005-09-07 17:39:47 +02:00
|
|
|
We allocate the user_var_event on user_var_events_alloc pool, not on
|
|
|
|
the this-statement-execution pool because in SPs user_var_event objects
|
|
|
|
may need to be valid after current [SP] statement execution pool is
|
|
|
|
destroyed.
|
2003-10-02 10:31:37 +02:00
|
|
|
*/
|
2005-09-07 17:39:47 +02:00
|
|
|
size= ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT)) + var_entry->length;
|
|
|
|
if (!(user_var_event= (BINLOG_USER_VAR_EVENT *)
|
|
|
|
alloc_root(thd->user_var_events_alloc, size)))
|
2003-10-02 10:31:37 +02:00
|
|
|
goto err;
|
2007-05-18 12:44:03 +02:00
|
|
|
|
2003-10-02 10:31:37 +02:00
|
|
|
user_var_event->value= (char*) user_var_event +
|
|
|
|
ALIGN_SIZE(sizeof(BINLOG_USER_VAR_EVENT));
|
|
|
|
user_var_event->user_var_event= var_entry;
|
|
|
|
user_var_event->type= var_entry->type;
|
|
|
|
user_var_event->charset_number= var_entry->collation.collation->number;
|
2010-03-17 01:06:13 +01:00
|
|
|
user_var_event->unsigned_flag= var_entry->unsigned_flag;
|
2003-10-02 10:31:37 +02:00
|
|
|
if (!var_entry->value)
|
|
|
|
{
|
|
|
|
/* NULL value*/
|
|
|
|
user_var_event->length= 0;
|
|
|
|
user_var_event->value= 0;
|
2003-01-30 18:39:54 +01:00
|
|
|
}
|
2003-10-02 10:31:37 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
user_var_event->length= var_entry->length;
|
|
|
|
memcpy(user_var_event->value, var_entry->value,
|
|
|
|
var_entry->length);
|
|
|
|
}
|
|
|
|
/* Mark that this variable has been used by this query */
|
|
|
|
var_entry->used_query_id= thd->query_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
|
|
|
if (insert_dynamic(&thd->user_var_events, (uchar*) &user_var_event))
|
2003-10-02 10:31:37 +02:00
|
|
|
goto err;
|
2007-05-18 12:44:03 +02:00
|
|
|
|
2004-06-01 15:27:40 +02:00
|
|
|
*out_entry= var_entry;
|
|
|
|
return 0;
|
2003-02-14 10:47:41 +01:00
|
|
|
|
2003-01-30 18:39:54 +01:00
|
|
|
err:
|
2004-06-01 15:27:40 +02:00
|
|
|
*out_entry= var_entry;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Item_func_get_user_var::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
THD *thd=current_thd;
|
|
|
|
int error;
|
|
|
|
maybe_null=1;
|
|
|
|
decimals=NOT_FIXED_DEC;
|
|
|
|
max_length=MAX_BLOB_WIDTH;
|
2004-06-07 10:09:10 +02: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
|
|
|
error= get_var_with_binlog(thd, thd->lex->sql_command, name, &var_entry);
|
2004-06-07 10:09:10 +02:00
|
|
|
|
2007-05-18 12:44:03 +02:00
|
|
|
/*
|
|
|
|
If the variable didn't exist it has been created as a STRING-type.
|
|
|
|
'var_entry' is NULL only if there occured an error during the call to
|
|
|
|
get_var_with_binlog.
|
|
|
|
*/
|
2011-07-07 13:22:43 +02:00
|
|
|
if (!error && var_entry)
|
2004-09-10 18:56:47 +02:00
|
|
|
{
|
2007-05-18 12:44:03 +02:00
|
|
|
m_cached_result_type= var_entry->type;
|
|
|
|
unsigned_flag= var_entry->unsigned_flag;
|
|
|
|
max_length= var_entry->length;
|
|
|
|
|
2004-06-01 15:27:40 +02:00
|
|
|
collation.set(var_entry->collation);
|
2007-05-18 12:44:03 +02:00
|
|
|
switch(m_cached_result_type) {
|
2004-09-10 18:56:47 +02:00
|
|
|
case REAL_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
fix_char_length(DBL_DIG + 8);
|
2005-05-05 17:06:49 +02:00
|
|
|
break;
|
2004-09-10 18:56:47 +02:00
|
|
|
case INT_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
fix_char_length(MAX_BIGINT_WIDTH);
|
2005-05-05 17:06:49 +02:00
|
|
|
decimals=0;
|
2004-09-10 18:56:47 +02:00
|
|
|
break;
|
|
|
|
case STRING_RESULT:
|
2010-08-16 15:43:21 +02:00
|
|
|
max_length= MAX_BLOB_WIDTH - 1;
|
2004-09-10 18:56:47 +02:00
|
|
|
break;
|
2005-02-08 23:50:45 +01:00
|
|
|
case DECIMAL_RESULT:
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
fix_char_length(DECIMAL_MAX_STR_LENGTH);
|
2005-05-05 17:06:49 +02:00
|
|
|
decimals= DECIMAL_MAX_SCALE;
|
2005-02-08 23:50:45 +01:00
|
|
|
break;
|
2004-10-07 09:50:13 +02:00
|
|
|
case ROW_RESULT: // Keep compiler happy
|
2005-02-08 23:50:45 +01:00
|
|
|
default:
|
|
|
|
DBUG_ASSERT(0);
|
2004-10-07 09:50:13 +02:00
|
|
|
break;
|
2004-09-10 18:56:47 +02:00
|
|
|
}
|
|
|
|
}
|
2004-06-07 10:09:10 +02:00
|
|
|
else
|
2005-03-28 11:01:57 +02:00
|
|
|
{
|
|
|
|
collation.set(&my_charset_bin, DERIVATION_IMPLICIT);
|
2004-06-07 10:09:10 +02:00
|
|
|
null_value= 1;
|
2007-05-18 12:44:03 +02:00
|
|
|
m_cached_result_type= STRING_RESULT;
|
|
|
|
max_length= MAX_BLOB_WIDTH;
|
2005-03-28 11:01:57 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-12-20 13:58:27 +01:00
|
|
|
bool Item_func_get_user_var::const_item() const
|
2003-02-14 10:47:41 +01:00
|
|
|
{
|
2003-10-21 12:14:06 +02:00
|
|
|
return (!var_entry || current_thd->query_id != var_entry->update_query_id);
|
2003-02-14 10:47:41 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
|
|
|
|
enum Item_result Item_func_get_user_var::result_type() const
|
|
|
|
{
|
2007-05-18 12:44:03 +02:00
|
|
|
return m_cached_result_type;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
|
2001-12-27 01:04:27 +01:00
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_get_user_var::print(String *str, enum_query_type query_type)
|
2001-12-27 01:04:27 +01:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("(@"));
|
2001-12-27 01:04:27 +01:00
|
|
|
str->append(name.str,name.length);
|
|
|
|
str->append(')');
|
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2002-03-22 13:03:42 +01:00
|
|
|
bool Item_func_get_user_var::eq(const Item *item, bool binary_cmp) const
|
2001-12-27 01:04:27 +01:00
|
|
|
{
|
|
|
|
/* Assume we don't have rtti */
|
|
|
|
if (this == item)
|
|
|
|
return 1; // Same item is same.
|
|
|
|
/* Check if other type is also a get_user_var() object */
|
|
|
|
if (item->type() != FUNC_ITEM ||
|
2005-06-17 16:27:47 +02:00
|
|
|
((Item_func*) item)->functype() != functype())
|
2001-12-27 01:04:27 +01:00
|
|
|
return 0;
|
|
|
|
Item_func_get_user_var *other=(Item_func_get_user_var*) item;
|
|
|
|
return (name.length == other->name.length &&
|
|
|
|
!memcmp(name.str, other->name.str, name.length));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-05-12 11:55:21 +02:00
|
|
|
bool Item_func_get_user_var::set_value(THD *thd,
|
2006-11-30 02:40:42 +01:00
|
|
|
sp_rcontext * /*ctx*/, Item **it)
|
2006-05-12 11:55:21 +02:00
|
|
|
{
|
2012-11-07 14:38:33 +01:00
|
|
|
Item_func_set_user_var *suv= new Item_func_set_user_var(get_name(), *it, false);
|
2006-05-12 11:55:21 +02:00
|
|
|
/*
|
|
|
|
Item_func_set_user_var is not fixed after construction, call
|
|
|
|
fix_fields().
|
|
|
|
*/
|
2006-08-22 15:37:41 +02:00
|
|
|
return (!suv || suv->fix_fields(thd, it) || suv->check(0) || suv->update());
|
2006-05-12 11:55:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
bool Item_user_var_as_out_param::fix_fields(THD *thd, Item **ref)
|
2005-03-16 02:32:47 +01:00
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 0);
|
2010-07-14 13:54:51 +02:00
|
|
|
DBUG_ASSERT(thd->lex->exchange);
|
2005-07-01 06:05:42 +02:00
|
|
|
if (Item::fix_fields(thd, ref) ||
|
2005-03-16 02:32:47 +01:00
|
|
|
!(entry= get_variable(&thd->user_vars, name, 1)))
|
|
|
|
return TRUE;
|
|
|
|
entry->type= STRING_RESULT;
|
|
|
|
/*
|
|
|
|
Let us set the same collation which is used for loading
|
|
|
|
of fields in LOAD DATA INFILE.
|
|
|
|
(Since Item_user_var_as_out_param is used only there).
|
|
|
|
*/
|
2010-07-14 13:54:51 +02:00
|
|
|
entry->collation.set(thd->lex->exchange->cs ?
|
|
|
|
thd->lex->exchange->cs :
|
|
|
|
thd->variables.collation_database);
|
2005-03-16 02:32:47 +01:00
|
|
|
entry->update_query_id= thd->query_id;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_user_var_as_out_param::set_null_value(CHARSET_INFO* cs)
|
|
|
|
{
|
2009-11-10 21:31:28 +01:00
|
|
|
::update_hash(entry, TRUE, 0, 0, STRING_RESULT, cs,
|
|
|
|
DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
|
2005-03-16 02:32:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Item_user_var_as_out_param::set_value(const char *str, uint length,
|
|
|
|
CHARSET_INFO* cs)
|
|
|
|
{
|
2009-11-10 21:31:28 +01:00
|
|
|
::update_hash(entry, FALSE, (void*)str, length, STRING_RESULT, cs,
|
|
|
|
DERIVATION_IMPLICIT, 0 /* unsigned_arg */);
|
2005-03-16 02:32:47 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_user_var_as_out_param::val_real()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_user_var_as_out_param::val_int()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String* Item_user_var_as_out_param::val_str(String *str)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
my_decimal* Item_user_var_as_out_param::val_decimal(my_decimal *decimal_buffer)
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_user_var_as_out_param::print(String *str, enum_query_type query_type)
|
2005-03-16 02:32:47 +01:00
|
|
|
{
|
|
|
|
str->append('@');
|
|
|
|
str->append(name.str,name.length);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-16 01:29:13 +02:00
|
|
|
Item_func_get_system_var::
|
|
|
|
Item_func_get_system_var(sys_var *var_arg, enum_var_type var_type_arg,
|
|
|
|
LEX_STRING *component_arg, const char *name_arg,
|
|
|
|
size_t name_len_arg)
|
2008-10-09 17:03:23 +02:00
|
|
|
:var(var_arg), var_type(var_type_arg), orig_var_type(var_type_arg),
|
|
|
|
component(*component_arg), cache_present(0)
|
2005-07-16 01:29:13 +02:00
|
|
|
{
|
|
|
|
/* set_name() will allocate the name */
|
2009-02-10 23:47:54 +01:00
|
|
|
set_name(name_arg, (uint) name_len_arg, system_charset_info);
|
2005-07-16 01:29:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 13:23:53 +02:00
|
|
|
bool Item_func_get_system_var::is_written_to_binlog()
|
2005-07-16 01:29:13 +02:00
|
|
|
{
|
2008-10-08 13:23:53 +02:00
|
|
|
return var->is_written_to_binlog(var_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-05-21 22:22:46 +02:00
|
|
|
void Item_func_get_system_var::update_null_value()
|
|
|
|
{
|
|
|
|
THD *thd= current_thd;
|
|
|
|
int save_no_errors= thd->no_errors;
|
|
|
|
thd->no_errors= TRUE;
|
|
|
|
Item::update_null_value();
|
|
|
|
thd->no_errors= save_no_errors;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 13:23:53 +02:00
|
|
|
void Item_func_get_system_var::fix_length_and_dec()
|
|
|
|
{
|
2009-03-05 12:34:02 +01:00
|
|
|
char *cptr;
|
2009-05-21 22:22:46 +02:00
|
|
|
maybe_null= TRUE;
|
2009-03-05 12:34:02 +01:00
|
|
|
max_length= 0;
|
2008-10-08 13:23:53 +02:00
|
|
|
|
|
|
|
if (var->check_type(var_type))
|
|
|
|
{
|
|
|
|
if (var_type != OPT_DEFAULT)
|
|
|
|
{
|
|
|
|
my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
|
2009-12-22 10:35:56 +01:00
|
|
|
var->name.str, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
|
2008-10-08 13:23:53 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* As there was no local variable, return the global value */
|
|
|
|
var_type= OPT_GLOBAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (var->show_type())
|
|
|
|
{
|
|
|
|
case SHOW_LONG:
|
|
|
|
case SHOW_INT:
|
|
|
|
case SHOW_HA_ROWS:
|
|
|
|
unsigned_flag= TRUE;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set_numeric();
|
|
|
|
fix_char_length(MY_INT64_NUM_DECIMAL_DIGITS);
|
2008-10-08 13:23:53 +02:00
|
|
|
decimals=0;
|
|
|
|
break;
|
|
|
|
case SHOW_LONGLONG:
|
2009-12-22 10:35:56 +01:00
|
|
|
unsigned_flag= TRUE;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set_numeric();
|
|
|
|
fix_char_length(MY_INT64_NUM_DECIMAL_DIGITS);
|
2008-10-08 13:23:53 +02:00
|
|
|
decimals=0;
|
|
|
|
break;
|
|
|
|
case SHOW_CHAR:
|
|
|
|
case SHOW_CHAR_PTR:
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
2009-12-22 10:35:56 +01:00
|
|
|
cptr= var->show_type() == SHOW_CHAR ?
|
|
|
|
(char*) var->value_ptr(current_thd, var_type, &component) :
|
|
|
|
*(char**) var->value_ptr(current_thd, var_type, &component);
|
2009-03-05 12:34:02 +01:00
|
|
|
if (cptr)
|
2009-12-22 10:35:56 +01:00
|
|
|
max_length= system_charset_info->cset->numchars(system_charset_info,
|
|
|
|
cptr,
|
|
|
|
cptr + strlen(cptr));
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
2008-10-08 13:23:53 +02:00
|
|
|
collation.set(system_charset_info, DERIVATION_SYSCONST);
|
2009-12-22 10:35:56 +01:00
|
|
|
max_length*= system_charset_info->mbmaxlen;
|
2008-10-08 13:23:53 +02:00
|
|
|
decimals=NOT_FIXED_DEC;
|
|
|
|
break;
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
|
|
|
{
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
2009-12-22 10:35:56 +01:00
|
|
|
LEX_STRING *ls= ((LEX_STRING*)var->value_ptr(current_thd, var_type, &component));
|
|
|
|
max_length= system_charset_info->cset->numchars(system_charset_info,
|
|
|
|
ls->str,
|
|
|
|
ls->str + ls->length);
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
2009-12-22 10:35:56 +01:00
|
|
|
collation.set(system_charset_info, DERIVATION_SYSCONST);
|
|
|
|
max_length*= system_charset_info->mbmaxlen;
|
|
|
|
decimals=NOT_FIXED_DEC;
|
|
|
|
}
|
|
|
|
break;
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
unsigned_flag= FALSE;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set_numeric();
|
|
|
|
fix_char_length(1);
|
2008-10-08 13:23:53 +02:00
|
|
|
decimals=0;
|
|
|
|
break;
|
|
|
|
case SHOW_DOUBLE:
|
|
|
|
unsigned_flag= FALSE;
|
|
|
|
decimals= 6;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
collation.set_numeric();
|
|
|
|
fix_char_length(DBL_DIG + 6);
|
2008-10-08 13:23:53 +02:00
|
|
|
break;
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2005-07-19 18:25:05 +02:00
|
|
|
|
2005-07-16 01:29:13 +02:00
|
|
|
|
2008-10-08 13:23:53 +02:00
|
|
|
void Item_func_get_system_var::print(String *str, enum_query_type query_type)
|
|
|
|
{
|
|
|
|
str->append(name, name_length);
|
2005-07-16 01:29:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 13:23:53 +02:00
|
|
|
enum Item_result Item_func_get_system_var::result_type() const
|
2008-03-07 13:59:36 +01:00
|
|
|
{
|
2008-10-08 13:23:53 +02:00
|
|
|
switch (var->show_type())
|
|
|
|
{
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
case SHOW_INT:
|
|
|
|
case SHOW_LONG:
|
|
|
|
case SHOW_LONGLONG:
|
|
|
|
case SHOW_HA_ROWS:
|
|
|
|
return INT_RESULT;
|
|
|
|
case SHOW_CHAR:
|
|
|
|
case SHOW_CHAR_PTR:
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
2008-10-08 13:23:53 +02:00
|
|
|
return STRING_RESULT;
|
|
|
|
case SHOW_DOUBLE:
|
|
|
|
return REAL_RESULT;
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
return STRING_RESULT; // keep the compiler happy
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
enum_field_types Item_func_get_system_var::field_type() const
|
|
|
|
{
|
|
|
|
switch (var->show_type())
|
|
|
|
{
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
case SHOW_INT:
|
|
|
|
case SHOW_LONG:
|
|
|
|
case SHOW_LONGLONG:
|
|
|
|
case SHOW_HA_ROWS:
|
|
|
|
return MYSQL_TYPE_LONGLONG;
|
|
|
|
case SHOW_CHAR:
|
|
|
|
case SHOW_CHAR_PTR:
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
2008-10-08 13:23:53 +02:00
|
|
|
return MYSQL_TYPE_VARCHAR;
|
|
|
|
case SHOW_DOUBLE:
|
|
|
|
return MYSQL_TYPE_DOUBLE;
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
return MYSQL_TYPE_VARCHAR; // keep the compiler happy
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-11-22 00:22:21 +01:00
|
|
|
/*
|
|
|
|
Uses var, var_type, component, cache_present, used_query_id, thd,
|
|
|
|
cached_llval, null_value, cached_null_value
|
|
|
|
*/
|
2008-10-08 13:23:53 +02:00
|
|
|
#define get_sys_var_safe(type) \
|
|
|
|
do { \
|
|
|
|
type value; \
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables); \
|
2008-10-08 13:23:53 +02:00
|
|
|
value= *(type*) var->value_ptr(thd, var_type, &component); \
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables); \
|
2008-10-08 13:23:53 +02:00
|
|
|
cache_present |= GET_SYS_VAR_CACHE_LONG; \
|
|
|
|
used_query_id= thd->query_id; \
|
|
|
|
cached_llval= null_value ? 0 : (longlong) value; \
|
|
|
|
cached_null_value= null_value; \
|
|
|
|
return cached_llval; \
|
|
|
|
} while (0)
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_get_system_var::val_int()
|
|
|
|
{
|
|
|
|
THD *thd= current_thd;
|
|
|
|
|
2008-10-10 11:52:23 +02:00
|
|
|
if (cache_present && thd->query_id == used_query_id)
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
|
|
|
if (cache_present & GET_SYS_VAR_CACHE_LONG)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
return cached_llval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
cached_llval= (longlong) cached_dval;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_LONG;
|
|
|
|
return cached_llval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_STRING)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
if (!null_value)
|
|
|
|
cached_llval= longlong_from_string_with_check (cached_strval.charset(),
|
|
|
|
cached_strval.c_ptr(),
|
|
|
|
cached_strval.c_ptr() +
|
|
|
|
cached_strval.length());
|
|
|
|
else
|
|
|
|
cached_llval= 0;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_LONG;
|
|
|
|
return cached_llval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (var->show_type())
|
|
|
|
{
|
|
|
|
case SHOW_INT: get_sys_var_safe (uint);
|
|
|
|
case SHOW_LONG: get_sys_var_safe (ulong);
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LONGLONG: get_sys_var_safe (ulonglong);
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_HA_ROWS: get_sys_var_safe (ha_rows);
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL: get_sys_var_safe (bool);
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL: get_sys_var_safe (my_bool);
|
|
|
|
case SHOW_DOUBLE:
|
|
|
|
{
|
|
|
|
double dval= val_real();
|
|
|
|
|
|
|
|
used_query_id= thd->query_id;
|
|
|
|
cached_llval= (longlong) dval;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_LONG;
|
|
|
|
return cached_llval;
|
|
|
|
}
|
|
|
|
case SHOW_CHAR:
|
|
|
|
case SHOW_CHAR_PTR:
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
|
|
|
String *str_val= val_str(NULL);
|
|
|
|
|
|
|
|
if (str_val && str_val->length())
|
|
|
|
cached_llval= longlong_from_string_with_check (system_charset_info,
|
|
|
|
str_val->c_ptr(),
|
|
|
|
str_val->c_ptr() +
|
|
|
|
str_val->length());
|
|
|
|
else
|
|
|
|
{
|
|
|
|
null_value= TRUE;
|
|
|
|
cached_llval= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_LONG;
|
|
|
|
return cached_llval;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
return 0; // keep the compiler happy
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
String* Item_func_get_system_var::val_str(String* str)
|
|
|
|
{
|
|
|
|
THD *thd= current_thd;
|
|
|
|
|
2008-10-10 11:52:23 +02:00
|
|
|
if (cache_present && thd->query_id == used_query_id)
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
|
|
|
if (cache_present & GET_SYS_VAR_CACHE_STRING)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
return null_value ? NULL : &cached_strval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_LONG)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
if (!null_value)
|
|
|
|
cached_strval.set (cached_llval, collation.collation);
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_STRING;
|
|
|
|
return null_value ? NULL : &cached_strval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
if (!null_value)
|
|
|
|
cached_strval.set_real (cached_dval, decimals, collation.collation);
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_STRING;
|
|
|
|
return null_value ? NULL : &cached_strval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
str= &cached_strval;
|
|
|
|
switch (var->show_type())
|
|
|
|
{
|
|
|
|
case SHOW_CHAR:
|
|
|
|
case SHOW_CHAR_PTR:
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
2009-12-22 10:35:56 +01:00
|
|
|
char *cptr= var->show_type() == SHOW_CHAR ?
|
|
|
|
(char*) var->value_ptr(thd, var_type, &component) :
|
|
|
|
*(char**) var->value_ptr(thd, var_type, &component);
|
2008-10-08 13:23:53 +02:00
|
|
|
if (cptr)
|
|
|
|
{
|
2009-12-22 10:35:56 +01:00
|
|
|
size_t len= var->show_type() == SHOW_LEX_STRING ?
|
|
|
|
((LEX_STRING*)(var->value_ptr(thd, var_type, &component)))->length :
|
|
|
|
strlen(cptr);
|
|
|
|
if (str->copy(cptr, len, collation.collation))
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
|
|
|
null_value= TRUE;
|
|
|
|
str= NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
null_value= TRUE;
|
|
|
|
str= NULL;
|
|
|
|
}
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
2008-10-08 13:23:53 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case SHOW_INT:
|
|
|
|
case SHOW_LONG:
|
|
|
|
case SHOW_LONGLONG:
|
|
|
|
case SHOW_HA_ROWS:
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
str->set (val_int(), collation.collation);
|
|
|
|
break;
|
|
|
|
case SHOW_DOUBLE:
|
|
|
|
str->set_real (val_real(), decimals, collation.collation);
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
str= NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_STRING;
|
|
|
|
used_query_id= thd->query_id;
|
|
|
|
cached_null_value= null_value;
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
double Item_func_get_system_var::val_real()
|
|
|
|
{
|
|
|
|
THD *thd= current_thd;
|
|
|
|
|
2008-10-10 11:52:23 +02:00
|
|
|
if (cache_present && thd->query_id == used_query_id)
|
2008-10-08 13:23:53 +02:00
|
|
|
{
|
|
|
|
if (cache_present & GET_SYS_VAR_CACHE_DOUBLE)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
return cached_dval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_LONG)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
cached_dval= (double)cached_llval;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
|
|
|
|
return cached_dval;
|
|
|
|
}
|
|
|
|
else if (cache_present & GET_SYS_VAR_CACHE_STRING)
|
|
|
|
{
|
|
|
|
null_value= cached_null_value;
|
|
|
|
if (!null_value)
|
|
|
|
cached_dval= double_from_string_with_check (cached_strval.charset(),
|
|
|
|
cached_strval.c_ptr(),
|
|
|
|
cached_strval.c_ptr() +
|
|
|
|
cached_strval.length());
|
|
|
|
else
|
|
|
|
cached_dval= 0;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
|
|
|
|
return cached_dval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (var->show_type())
|
|
|
|
{
|
|
|
|
case SHOW_DOUBLE:
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
2008-10-08 13:23:53 +02:00
|
|
|
cached_dval= *(double*) var->value_ptr(thd, var_type, &component);
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
2008-10-08 13:23:53 +02:00
|
|
|
used_query_id= thd->query_id;
|
|
|
|
cached_null_value= null_value;
|
|
|
|
if (null_value)
|
|
|
|
cached_dval= 0;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
|
|
|
|
return cached_dval;
|
|
|
|
case SHOW_CHAR:
|
2009-12-22 10:35:56 +01:00
|
|
|
case SHOW_LEX_STRING:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_CHAR_PTR:
|
|
|
|
{
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_global_system_variables);
|
2009-12-22 10:35:56 +01:00
|
|
|
char *cptr= var->show_type() == SHOW_CHAR ?
|
2008-10-08 13:23:53 +02:00
|
|
|
(char*) var->value_ptr(thd, var_type, &component) :
|
|
|
|
*(char**) var->value_ptr(thd, var_type, &component);
|
|
|
|
if (cptr)
|
|
|
|
cached_dval= double_from_string_with_check (system_charset_info,
|
|
|
|
cptr, cptr + strlen (cptr));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
null_value= TRUE;
|
|
|
|
cached_dval= 0;
|
|
|
|
}
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_global_system_variables);
|
2008-10-08 13:23:53 +02:00
|
|
|
used_query_id= thd->query_id;
|
|
|
|
cached_null_value= null_value;
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
|
|
|
|
return cached_dval;
|
|
|
|
}
|
|
|
|
case SHOW_INT:
|
|
|
|
case SHOW_LONG:
|
|
|
|
case SHOW_LONGLONG:
|
|
|
|
case SHOW_HA_ROWS:
|
2008-11-22 00:22:21 +01:00
|
|
|
case SHOW_BOOL:
|
2008-10-08 13:23:53 +02:00
|
|
|
case SHOW_MY_BOOL:
|
|
|
|
cached_dval= (double) val_int();
|
|
|
|
cache_present|= GET_SYS_VAR_CACHE_DOUBLE;
|
|
|
|
used_query_id= thd->query_id;
|
|
|
|
cached_null_value= null_value;
|
|
|
|
return cached_dval;
|
|
|
|
default:
|
2009-12-22 10:35:56 +01:00
|
|
|
my_error(ER_VAR_CANT_BE_READ, MYF(0), var->name.str);
|
2008-10-08 13:23:53 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Item_func_get_system_var::eq(const Item *item, bool binary_cmp) const
|
|
|
|
{
|
|
|
|
/* Assume we don't have rtti */
|
|
|
|
if (this == item)
|
|
|
|
return 1; // Same item is same.
|
|
|
|
/* Check if other type is also a get_user_var() object */
|
|
|
|
if (item->type() != FUNC_ITEM ||
|
|
|
|
((Item_func*) item)->functype() != functype())
|
|
|
|
return 0;
|
|
|
|
Item_func_get_system_var *other=(Item_func_get_system_var*) item;
|
|
|
|
return (var == other->var && var_type == other->var_type);
|
2008-03-07 13:59:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-09 17:03:23 +02:00
|
|
|
void Item_func_get_system_var::cleanup()
|
|
|
|
{
|
|
|
|
Item_func::cleanup();
|
2008-10-10 11:52:23 +02:00
|
|
|
cache_present= 0;
|
2008-10-09 17:03:23 +02:00
|
|
|
var_type= orig_var_type;
|
|
|
|
cached_strval.free();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
longlong Item_func_inet_aton::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2000-07-31 21:29:14 +02:00
|
|
|
uint byte_result = 0;
|
|
|
|
ulonglong result = 0; // We are ready for 64 bit addresses
|
|
|
|
const char *p,* end;
|
|
|
|
char c = '.'; // we mark c to indicate invalid IP in case length is 0
|
|
|
|
char buff[36];
|
2004-01-19 21:32:25 +01:00
|
|
|
int dot_count= 0;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
String *s, tmp(buff, sizeof(buff), &my_charset_latin1);
|
|
|
|
if (!(s = args[0]->val_str_ascii(&tmp))) // If null value
|
2000-07-31 21:29:14 +02:00
|
|
|
goto err;
|
|
|
|
null_value=0;
|
|
|
|
|
|
|
|
end= (p = s->ptr()) + s->length();
|
|
|
|
while (p < end)
|
|
|
|
{
|
|
|
|
c = *p++;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
int digit = (int) (c - '0');
|
2000-07-31 21:29:14 +02:00
|
|
|
if (digit >= 0 && digit <= 9)
|
|
|
|
{
|
|
|
|
if ((byte_result = byte_result * 10 + digit) > 255)
|
|
|
|
goto err; // Wrong address
|
|
|
|
}
|
|
|
|
else if (c == '.')
|
|
|
|
{
|
2004-01-19 21:32:25 +01:00
|
|
|
dot_count++;
|
2000-07-31 21:29:14 +02:00
|
|
|
result= (result << 8) + (ulonglong) byte_result;
|
|
|
|
byte_result = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
goto err; // Invalid character
|
|
|
|
}
|
|
|
|
if (c != '.') // IP number can't end on '.'
|
2004-01-19 21:32:25 +01:00
|
|
|
{
|
2004-02-05 10:22:08 +01:00
|
|
|
/*
|
|
|
|
Handle short-forms addresses according to standard. Examples:
|
|
|
|
127 -> 0.0.0.127
|
|
|
|
127.1 -> 127.0.0.1
|
|
|
|
127.2.1 -> 127.2.0.1
|
|
|
|
*/
|
2004-02-05 15:58:10 +01:00
|
|
|
switch (dot_count) {
|
2004-02-05 10:22:08 +01:00
|
|
|
case 1: result<<= 8; /* Fall through */
|
|
|
|
case 2: result<<= 8; /* Fall through */
|
2004-01-19 21:32:25 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
return (result << 8) + (ulonglong) byte_result;
|
2004-01-19 21:32:25 +01:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
err:
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-06-27 10:27:04 +02:00
|
|
|
|
2000-11-04 15:48:06 +01:00
|
|
|
void Item_func_match::init_search(bool no_order)
|
2000-08-28 15:43:58 +02:00
|
|
|
{
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_ENTER("Item_func_match::init_search");
|
2003-11-18 12:47:27 +01:00
|
|
|
|
|
|
|
/* Check if init_search() has been called before */
|
2000-11-02 17:36:21 +01:00
|
|
|
if (ft_handler)
|
2010-10-18 12:47:26 +02:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
We should reset ft_handler as it is cleaned up
|
|
|
|
on destruction of FT_SELECT object
|
|
|
|
(necessary in case of re-execution of subquery).
|
|
|
|
TODO: FT_SELECT should not clean up ft_handler.
|
|
|
|
*/
|
|
|
|
if (join_key)
|
|
|
|
table->file->ft_handler= ft_handler;
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2010-10-18 12:47:26 +02:00
|
|
|
}
|
2000-08-28 15:43:58 +02:00
|
|
|
|
2002-05-07 13:43:25 +02:00
|
|
|
if (key == NO_SUCH_KEY)
|
2003-10-20 15:53:48 +02:00
|
|
|
{
|
|
|
|
List<Item> fields;
|
2004-10-28 08:43:31 +02:00
|
|
|
fields.push_back(new Item_string(" ",1, cmp_collation.collation));
|
2003-10-20 15:53:48 +02:00
|
|
|
for (uint i=1; i < arg_count; i++)
|
|
|
|
fields.push_back(args[i]);
|
2007-04-02 14:26:39 +02:00
|
|
|
concat_ws=new Item_func_concat_ws(fields);
|
2004-03-20 12:36:26 +01:00
|
|
|
/*
|
|
|
|
Above function used only to get value and do not need fix_fields for it:
|
|
|
|
Item_string - basic constant
|
2004-03-25 21:11:22 +01:00
|
|
|
fields - fix_fields() was already called for this arguments
|
|
|
|
Item_func_concat_ws - do not need fix_fields() to produce value
|
2004-03-20 12:36:26 +01:00
|
|
|
*/
|
2007-04-02 14:26:39 +02:00
|
|
|
concat_ws->quick_fix_field();
|
2003-10-20 15:53:48 +02:00
|
|
|
}
|
2002-05-07 13:43:25 +02:00
|
|
|
|
2000-08-28 15:43:58 +02:00
|
|
|
if (master)
|
|
|
|
{
|
2000-11-04 15:48:06 +01:00
|
|
|
join_key=master->join_key=join_key|master->join_key;
|
|
|
|
master->init_search(no_order);
|
2000-08-28 15:43:58 +02:00
|
|
|
ft_handler=master->ft_handler;
|
|
|
|
join_key=master->join_key;
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_VOID_RETURN;
|
2000-08-28 15:43:58 +02:00
|
|
|
}
|
|
|
|
|
2002-08-30 11:40:40 +02:00
|
|
|
String *ft_tmp= 0;
|
2000-08-28 15:43:58 +02:00
|
|
|
|
2001-09-21 18:38:17 +02:00
|
|
|
// MATCH ... AGAINST (NULL) is meaningless, but possible
|
2003-10-20 15:53:48 +02:00
|
|
|
if (!(ft_tmp=key_item()->val_str(&value)))
|
2001-02-28 11:43:08 +01:00
|
|
|
{
|
2003-10-20 15:53:48 +02:00
|
|
|
ft_tmp= &value;
|
|
|
|
value.set("",0,cmp_collation.collation);
|
2001-02-28 11:43:08 +01:00
|
|
|
}
|
|
|
|
|
2003-10-20 15:53:48 +02:00
|
|
|
if (ft_tmp->charset() != cmp_collation.collation)
|
|
|
|
{
|
2004-10-29 14:00:39 +02:00
|
|
|
uint dummy_errors;
|
2003-10-20 15:53:48 +02:00
|
|
|
search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
|
2004-10-29 14:00:39 +02:00
|
|
|
cmp_collation.collation, &dummy_errors);
|
2003-10-20 15:53:48 +02:00
|
|
|
ft_tmp= &search_value;
|
2001-02-28 11:43:08 +01:00
|
|
|
}
|
|
|
|
|
2003-11-18 12:47:27 +01:00
|
|
|
if (join_key && !no_order)
|
|
|
|
flags|=FT_SORTED;
|
2005-02-04 15:24:06 +01:00
|
|
|
ft_handler=table->file->ft_init_ext(flags, key, ft_tmp);
|
2000-11-02 17:36:21 +01:00
|
|
|
|
|
|
|
if (join_key)
|
|
|
|
table->file->ft_handler=ft_handler;
|
2002-10-18 16:53:46 +02:00
|
|
|
|
|
|
|
DBUG_VOID_RETURN;
|
2000-08-28 15:43:58 +02:00
|
|
|
}
|
|
|
|
|
2002-06-27 10:27:04 +02:00
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
bool Item_func_match::fix_fields(THD *thd, Item **ref)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2004-03-17 13:26:26 +01:00
|
|
|
DBUG_ASSERT(fixed == 0);
|
2009-08-28 17:51:31 +02:00
|
|
|
Item *UNINIT_VAR(item); // Safe as arg_count is > 1
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2001-07-03 17:58:47 +02:00
|
|
|
maybe_null=1;
|
|
|
|
join_key=0;
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
/*
|
|
|
|
const_item is assumed in quite a bit of places, so it would be difficult
|
|
|
|
to remove; If it would ever to be removed, this should include
|
|
|
|
modifications to find_best and auto_close as complement to auto_init code
|
|
|
|
above.
|
2001-11-28 17:55:45 +01:00
|
|
|
*/
|
2005-07-01 06:05:42 +02:00
|
|
|
if (Item_func::fix_fields(thd, ref) ||
|
2003-11-22 22:48:18 +01:00
|
|
|
!args[0]->const_during_execution())
|
2001-08-03 23:10:00 +02:00
|
|
|
{
|
|
|
|
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE;
|
2001-08-03 23:10:00 +02:00
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-10-20 15:53:48 +02:00
|
|
|
const_item_cache=0;
|
|
|
|
for (uint i=1 ; i < arg_count ; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-20 15:53:48 +02:00
|
|
|
item=args[i];
|
2001-04-17 14:17:22 +02:00
|
|
|
if (item->type() == Item::REF_ITEM)
|
2003-10-20 15:53:48 +02:00
|
|
|
args[i]= item= *((Item_ref *)item)->ref;
|
|
|
|
if (item->type() != Item::FIELD_ITEM)
|
2009-02-12 10:49:44 +01:00
|
|
|
{
|
|
|
|
my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
|
|
|
|
return TRUE;
|
|
|
|
}
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
2003-11-22 22:48:18 +01:00
|
|
|
/*
|
|
|
|
Check that all columns come from the same table.
|
2005-02-04 15:24:06 +01:00
|
|
|
We've already checked that columns in MATCH are fields so
|
2003-11-22 22:48:18 +01:00
|
|
|
PARAM_TABLE_BIT can only appear from AGAINST argument.
|
|
|
|
*/
|
|
|
|
if ((used_tables_cache & ~PARAM_TABLE_BIT) != item->used_tables())
|
2002-06-11 10:20:31 +02:00
|
|
|
key=NO_SUCH_KEY;
|
2005-02-04 15:24:06 +01:00
|
|
|
|
2003-10-22 17:57:09 +02:00
|
|
|
if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
|
2001-08-03 23:10:00 +02:00
|
|
|
{
|
|
|
|
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
|
2004-10-20 03:04:37 +02:00
|
|
|
return TRUE;
|
2001-08-03 23:10:00 +02:00
|
|
|
}
|
2003-10-20 15:53:48 +02:00
|
|
|
table=((Item_field *)item)->field->table;
|
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
|
|
|
if (!(table->file->ha_table_flags() & HA_CAN_FULLTEXT))
|
2001-08-03 23:10:00 +02:00
|
|
|
{
|
2005-05-14 15:24:36 +02:00
|
|
|
my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
|
2000-07-31 21:29:14 +02:00
|
|
|
return 1;
|
2001-08-03 23:10:00 +02:00
|
|
|
}
|
2003-10-20 15:53:48 +02:00
|
|
|
table->fulltext_searched=1;
|
WL#2649 Number-to-string conversions
added:
include/ctype_numconv.inc
mysql-test/include/ctype_numconv.inc
mysql-test/r/ctype_binary.result
mysql-test/t/ctype_binary.test
Adding tests
modified:
mysql-test/r/bigint.result
mysql-test/r/case.result
mysql-test/r/create.result
mysql-test/r/ctype_cp1251.result
mysql-test/r/ctype_latin1.result
mysql-test/r/ctype_ucs.result
mysql-test/r/func_gconcat.result
mysql-test/r/func_str.result
mysql-test/r/metadata.result
mysql-test/r/ps_1general.result
mysql-test/r/ps_2myisam.result
mysql-test/r/ps_3innodb.result
mysql-test/r/ps_4heap.result
mysql-test/r/ps_5merge.result
mysql-test/r/show_check.result
mysql-test/r/type_datetime.result
mysql-test/r/type_ranges.result
mysql-test/r/union.result
mysql-test/suite/ndb/r/ps_7ndb.result
mysql-test/t/ctype_cp1251.test
mysql-test/t/ctype_latin1.test
mysql-test/t/ctype_ucs.test
mysql-test/t/func_str.test
Fixing tests
@ sql/field.cc
- Return str result using my_charset_numeric.
- Using real multi-byte aware str_to_XXX functions
to handle tricky charset values propely (e.g. UCS2)
@ sql/field.h
- Changing derivation of non-string field types to DERIVATION_NUMERIC.
- Changing binary() for numeric/datetime fields to always
return TRUE even if charset is not my_charset_bin. We need
this to keep ha_base_keytype() return HA_KEYTYPE_BINARY.
- Adding BINARY_FLAG into some fields, because it's not
being set automatically anymore with
"my_charset_bin to my_charset_numeric" change.
- Changing derivation for numeric/datetime datatypes to a weaker
value, to make "SELECT concat('string', field)" use character
set of the string literal for the result of the function.
@ sql/item.cc
- Implementing generic val_str_ascii().
- Using max_char_length() instead of direct read of max_length
to make "tricky" charsets like UCS2 work.
NOTE: in the future we'll possibly remove all direct reads of max_length
- Fixing Item_num::safe_charset_converter().
Previously it alligned binary string to
character string (for example by adding leading 0x00
when doing binary->UCS2 conversion). Now it just
converts from my_charset_numbner to "tocs".
- Using val_str_ascii() in Item::get_time() to make UCS2 arguments work.
- Other misc changes
@ sql/item.h
- Changing MY_COLL_CMP_CONV and MY_COLL_ALLOW_CONV to
bit operations instead of hard-coded bit masks.
- Addding new method DTCollation.set_numeric().
- Adding new methods to Item.
- Adding helper functions to make code look nicer:
agg_item_charsets_for_string_result()
agg_item_charsets_for_comparison()
- Changing charset for Item_num-derived items
from my_charset_bin to my_charset_numeric
(which is an alias for latin1).
@ sql/item_cmpfunc.cc
- Using new helper functions
- Other misc changes
@ sql/item_cmpfunc.h
- Fixing strcmp() to return max_length=2.
Previously it returned 1, which was wrong,
because it did not fit '-1'.
@ sql/item_func.cc
- Using new helper functions
- Other minor changes
@ sql/item_func.h
- Removing unused functions
- Adding helper functions
agg_arg_charsets_for_string_result()
agg_arg_charsets_for_comparison()
- Adding set_numeric() into constructors of numeric items.
- Using fix_length_and_charset() and fix_char_length()
instead of direct write to max_length.
@ sql/item_geofunc.cc
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when character_set_connection=ucs2).
@ sql/item_geofunc.h
- Changing class for Item_func_geometry_type and
Item_func_as_wkt from Item_str_func to
Item_str_ascii_func, to make them return UCS2 result
properly (when @@character_set_connection=ucs2).
@ sql/item_strfunc.cc
- Implementing Item_str_func::val_str().
- Renaming val_str to val_str_ascii for some items,
to make them work with UCS2 properly.
- Using new helper functions
- All single-argument functions that expect string
result now call this method:
agg_arg_charsets_for_string_result(collation, args, 1);
This enables character set conversion to @@character_set_connection
in case of pure numeric input.
@ sql/item_strfunc.h
- Introducing Item_str_ascii_func - for functions
which return pure ASCII data, for performance purposes,
as well as for the cases when the old implementation
of val_str() was heavily 8-bit oriented and implementing
a UCS2-aware version is tricky.
@ sql/item_sum.cc
- Using new helper functions.
@ sql/item_timefunc.cc
- Using my_charset_numeric instead of my_charset_bin.
- Using fix_char_length(), fix_length_and_charset()
and fix_length_and_charset_datetime()
instead of direct write to max_length.
- Using tricky-charset aware function str_to_time_with_warn()
@ sql/item_timefunc.h
- Using new helper functions for charset and length initialization.
- Changing base class for Item_func_get_format() to make
it return UCS2 properly (when character_set_connection=ucs2).
@ sql/item_xmlfunc.cc
- Using new helper function
@ sql/my_decimal.cc
- Adding a new DECIMAL to CHAR converter
with real multibyte support (e.g. UCS2)
@ sql/mysql_priv.h
- Introducing a new derivation level for numeric/datetime data types.
- Adding macros for my_charset_numeric and MY_REPERTOIRE_NUMERIC.
- Adding prototypes for str_set_decimal()
- Adding prototypes for character-set aware str_to_xxx() functions.
@ sql/protocol.cc
- Changing charsetnr to "binary" client-side metadata for
numeric/datetime data types.
@ sql/time.cc
- Adding to_ascii() helper function, to convert a string
in any character set to ascii representation. In the
future can be extended to understand digits written
in various non-Latin word scripts.
- Adding real multy-byte character set aware versions for str_to_XXXX,
to make these these type of queries work correct:
INSERT INTO t1 SET datetime_column=ucs2_expression;
@ strings/ctype-ucs2.c
- endptr was not calculated correctly. INSERTing of UCS2
values into numeric columns returned warnings about
truncated wrong data.
2010-02-11 05:17:25 +01:00
|
|
|
return agg_item_collations_for_comparison(cmp_collation, func_name(),
|
|
|
|
args+1, arg_count-1, 0);
|
2003-07-02 12:12:18 +02:00
|
|
|
}
|
2002-12-26 00:28:59 +01:00
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
bool Item_func_match::fix_index()
|
|
|
|
{
|
|
|
|
Item_field *item;
|
2002-11-07 02:54:00 +01:00
|
|
|
uint ft_to_key[MAX_KEY], ft_cnt[MAX_KEY], fts=0, keynr;
|
2003-11-12 09:38:46 +01:00
|
|
|
uint max_cnt=0, mkeys=0, i;
|
2001-11-28 17:55:45 +01:00
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
if (key == NO_SUCH_KEY)
|
2001-11-28 17:55:45 +01:00
|
|
|
return 0;
|
2005-07-14 17:19:26 +02:00
|
|
|
|
|
|
|
if (!table)
|
|
|
|
goto err;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2005-01-06 12:00:13 +01:00
|
|
|
for (keynr=0 ; keynr < table->s->keys ; keynr++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
if ((table->key_info[keynr].flags & HA_FULLTEXT) &&
|
2008-11-11 10:10:51 +01:00
|
|
|
(flags & FT_BOOL ? table->keys_in_use_for_query.is_set(keynr) :
|
|
|
|
table->s->keys_in_use.is_set(keynr)))
|
|
|
|
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
ft_to_key[fts]=keynr;
|
2000-07-31 21:29:14 +02:00
|
|
|
ft_cnt[fts]=0;
|
|
|
|
fts++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!fts)
|
2001-11-28 17:55:45 +01:00
|
|
|
goto err;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2003-11-12 09:38:46 +01:00
|
|
|
for (i=1; i < arg_count; i++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-20 15:53:48 +02:00
|
|
|
item=(Item_field*)args[i];
|
2002-11-07 02:54:00 +01:00
|
|
|
for (keynr=0 ; keynr < fts ; keynr++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
KEY *ft_key=&table->key_info[ft_to_key[keynr]];
|
2000-07-31 21:29:14 +02:00
|
|
|
uint key_parts=ft_key->key_parts;
|
|
|
|
|
|
|
|
for (uint part=0 ; part < key_parts ; part++)
|
|
|
|
{
|
|
|
|
if (item->field->eq(ft_key->key_part[part].field))
|
2002-11-07 02:54:00 +01:00
|
|
|
ft_cnt[keynr]++;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
for (keynr=0 ; keynr < fts ; keynr++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
if (ft_cnt[keynr] > max_cnt)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2000-11-16 13:08:20 +01:00
|
|
|
mkeys=0;
|
2002-11-07 02:54:00 +01:00
|
|
|
max_cnt=ft_cnt[mkeys]=ft_cnt[keynr];
|
|
|
|
ft_to_key[mkeys]=ft_to_key[keynr];
|
2000-11-16 13:08:20 +01:00
|
|
|
continue;
|
|
|
|
}
|
2002-11-07 02:54:00 +01:00
|
|
|
if (max_cnt && ft_cnt[keynr] == max_cnt)
|
2000-11-16 13:08:20 +01:00
|
|
|
{
|
|
|
|
mkeys++;
|
2002-11-07 02:54:00 +01:00
|
|
|
ft_cnt[mkeys]=ft_cnt[keynr];
|
|
|
|
ft_to_key[mkeys]=ft_to_key[keynr];
|
2000-11-16 13:08:20 +01:00
|
|
|
continue;
|
2000-07-31 21:29:14 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
for (keynr=0 ; keynr <= mkeys ; keynr++)
|
2000-07-31 21:29:14 +02:00
|
|
|
{
|
2003-10-20 15:53:48 +02:00
|
|
|
// partial keys doesn't work
|
|
|
|
if (max_cnt < arg_count-1 ||
|
2002-11-07 02:54:00 +01:00
|
|
|
max_cnt < table->key_info[ft_to_key[keynr]].key_parts)
|
2000-11-16 13:08:20 +01:00
|
|
|
continue;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
2002-11-07 02:54:00 +01:00
|
|
|
key=ft_to_key[keynr];
|
2000-08-28 15:43:58 +02:00
|
|
|
|
2000-11-16 13:08:20 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2001-11-28 17:55:45 +01:00
|
|
|
err:
|
2003-10-22 17:57:09 +02:00
|
|
|
if (flags & FT_BOOL)
|
2001-11-28 17:55:45 +01:00
|
|
|
{
|
2002-11-07 02:54:00 +01:00
|
|
|
key=NO_SUCH_KEY;
|
2001-11-28 17:55:45 +01:00
|
|
|
return 0;
|
|
|
|
}
|
2004-11-12 13:34:00 +01:00
|
|
|
my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
|
|
|
|
ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
|
2000-11-16 13:08:20 +01:00
|
|
|
return 1;
|
2000-08-28 15:43:58 +02:00
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2002-03-22 13:03:42 +01:00
|
|
|
bool Item_func_match::eq(const Item *item, bool binary_cmp) const
|
2000-08-28 15:43:58 +02:00
|
|
|
{
|
2005-07-04 02:42:33 +02:00
|
|
|
if (item->type() != FUNC_ITEM ||
|
|
|
|
((Item_func*)item)->functype() != FT_FUNC ||
|
2003-10-22 17:57:09 +02:00
|
|
|
flags != ((Item_func_match*)item)->flags)
|
2000-08-28 15:43:58 +02:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
Item_func_match *ifm=(Item_func_match*) item;
|
|
|
|
|
|
|
|
if (key == ifm->key && table == ifm->table &&
|
2002-03-22 13:03:42 +01:00
|
|
|
key_item()->eq(ifm->key_item(), binary_cmp))
|
2000-08-28 15:43:58 +02:00
|
|
|
return 1;
|
2000-07-31 21:29:14 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2004-11-11 19:39:35 +01:00
|
|
|
double Item_func_match::val_real()
|
2001-10-09 14:53:54 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_ENTER("Item_func_match::val");
|
2001-12-02 13:34:01 +01:00
|
|
|
if (ft_handler == NULL)
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_RETURN(-1.0);
|
2001-10-09 14:53:54 +02:00
|
|
|
|
2006-06-14 09:19:02 +02:00
|
|
|
if (key != NO_SUCH_KEY && table->null_row) /* NULL row from an outer join */
|
2006-03-29 16:04:00 +02:00
|
|
|
DBUG_RETURN(0.0);
|
2003-06-16 23:05:45 +02:00
|
|
|
|
2001-10-09 14:53:54 +02:00
|
|
|
if (join_key)
|
|
|
|
{
|
|
|
|
if (table->file->ft_handler)
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_RETURN(ft_handler->please->get_relevance(ft_handler));
|
2001-10-09 14:53:54 +02:00
|
|
|
join_key=0;
|
|
|
|
}
|
|
|
|
|
2001-11-28 17:55:45 +01:00
|
|
|
if (key == NO_SUCH_KEY)
|
2001-10-09 14:53:54 +02:00
|
|
|
{
|
2007-04-02 14:26:39 +02:00
|
|
|
String *a= concat_ws->val_str(&value);
|
|
|
|
if ((null_value= (a == 0)) || !a->length())
|
2002-10-18 16:53:46 +02:00
|
|
|
DBUG_RETURN(0);
|
|
|
|
DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
|
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 *)a->ptr(), a->length()));
|
2001-10-09 14:53:54 +02:00
|
|
|
}
|
2006-03-29 16:04:00 +02:00
|
|
|
DBUG_RETURN(ft_handler->please->find_relevance(ft_handler,
|
|
|
|
table->record[0], 0));
|
2001-10-09 14:53:54 +02:00
|
|
|
}
|
|
|
|
|
2008-02-22 11:30:33 +01:00
|
|
|
void Item_func_match::print(String *str, enum_query_type query_type)
|
2003-10-12 16:56:05 +02:00
|
|
|
{
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN("(match "));
|
2008-02-22 11:30:33 +01:00
|
|
|
print_args(str, 1, query_type);
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(" against ("));
|
2008-02-22 11:30:33 +01:00
|
|
|
args[0]->print(str, query_type);
|
2003-11-03 11:28:36 +01:00
|
|
|
if (flags & FT_BOOL)
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(" in boolean mode"));
|
2003-11-03 11:28:36 +01:00
|
|
|
else if (flags & FT_EXPAND)
|
2005-11-20 19:47:07 +01:00
|
|
|
str->append(STRING_WITH_LEN(" with query expansion"));
|
|
|
|
str->append(STRING_WITH_LEN("))"));
|
2003-10-12 16:56:05 +02:00
|
|
|
}
|
2002-08-30 11:40:40 +02:00
|
|
|
|
2002-06-29 15:25:09 +02:00
|
|
|
longlong Item_func_bit_xor::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2002-06-29 15:25:09 +02:00
|
|
|
ulonglong arg1= (ulonglong) args[0]->val_int();
|
|
|
|
ulonglong arg2= (ulonglong) args[1]->val_int();
|
2002-06-30 17:57:21 +02:00
|
|
|
if ((null_value= (args[0]->null_value || args[1]->null_value)))
|
2002-06-29 15:25:09 +02:00
|
|
|
return 0;
|
|
|
|
return (longlong) (arg1 ^ arg2);
|
|
|
|
}
|
|
|
|
|
2002-06-11 10:20:31 +02:00
|
|
|
|
2000-09-25 23:33:25 +02:00
|
|
|
/***************************************************************************
|
|
|
|
System variables
|
|
|
|
****************************************************************************/
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
|
|
|
Return value of an system variable base[.name] as a constant item.
|
2003-07-06 18:09:57 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@param thd Thread handler
|
|
|
|
@param var_type global / session
|
|
|
|
@param name Name of base or system variable
|
|
|
|
@param component Component.
|
2003-07-06 18:09:57 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@note
|
2003-07-06 18:09:57 +02:00
|
|
|
If component.str = 0 then the variable name is in 'name'
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@return
|
|
|
|
- 0 : error
|
|
|
|
- # : constant item
|
2003-07-06 18:09:57 +02:00
|
|
|
*/
|
2005-07-16 01:29:13 +02:00
|
|
|
|
2003-07-06 18:09:57 +02:00
|
|
|
|
|
|
|
Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
|
|
|
|
LEX_STRING component)
|
2000-09-25 23:33:25 +02:00
|
|
|
{
|
2005-07-16 01:29:13 +02:00
|
|
|
sys_var *var;
|
|
|
|
LEX_STRING *base_name, *component_name;
|
|
|
|
|
2003-07-06 18:09:57 +02:00
|
|
|
if (component.str)
|
|
|
|
{
|
|
|
|
base_name= &component;
|
|
|
|
component_name= &name;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
base_name= &name;
|
|
|
|
component_name= &component; // Empty string
|
|
|
|
}
|
2002-07-23 17:31:22 +02:00
|
|
|
|
2007-03-02 17:43:45 +01:00
|
|
|
if (!(var= find_sys_var(thd, base_name->str, base_name->length)))
|
2002-07-23 17:31:22 +02:00
|
|
|
return 0;
|
2003-07-06 18:09:57 +02:00
|
|
|
if (component.str)
|
|
|
|
{
|
|
|
|
if (!var->is_struct())
|
|
|
|
{
|
2004-11-13 18:35:51 +01:00
|
|
|
my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
|
2003-07-06 18:09:57 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2003-11-19 15:19:46 +01:00
|
|
|
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
2005-07-16 01:29:13 +02:00
|
|
|
|
2003-07-06 18:09:57 +02:00
|
|
|
set_if_smaller(component_name->length, MAX_SYS_VAR_LENGTH);
|
|
|
|
|
2005-07-16 01:29:13 +02:00
|
|
|
return new Item_func_get_system_var(var, var_type, component_name,
|
2005-07-25 20:25:28 +02:00
|
|
|
NULL, 0);
|
2002-10-02 12:33:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
/**
|
2002-06-29 15:25:09 +02:00
|
|
|
Check a user level lock.
|
2002-06-30 17:57:21 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
Sets null_value=TRUE on error.
|
2002-06-30 17:57:21 +02:00
|
|
|
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
2002-06-30 17:57:21 +02:00
|
|
|
1 Available
|
2007-10-11 19:29:09 +02:00
|
|
|
@retval
|
|
|
|
0 Already taken, or error
|
2002-06-29 15:25:09 +02:00
|
|
|
*/
|
|
|
|
|
2002-06-30 17:57:21 +02:00
|
|
|
longlong Item_func_is_free_lock::val_int()
|
2002-06-29 15:25:09 +02:00
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2002-06-29 15:25:09 +02:00
|
|
|
String *res=args[0]->val_str(&value);
|
2004-03-15 20:39:36 +01:00
|
|
|
User_level_lock *ull;
|
2002-06-29 15:25:09 +02:00
|
|
|
|
|
|
|
null_value=0;
|
2002-06-30 17:57:21 +02:00
|
|
|
if (!res || !res->length())
|
2002-06-29 15:25:09 +02:00
|
|
|
{
|
|
|
|
null_value=1;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_lock(&LOCK_user_locks);
|
2009-10-14 18:37:38 +02:00
|
|
|
ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
|
|
|
|
(size_t) res->length());
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2002-06-29 15:25:09 +02:00
|
|
|
if (!ull || !ull->locked)
|
|
|
|
return 1;
|
|
|
|
return 0;
|
|
|
|
}
|
2002-02-22 12:24:42 +01:00
|
|
|
|
2003-03-14 10:10:33 +01:00
|
|
|
longlong Item_func_is_used_lock::val_int()
|
|
|
|
{
|
2004-03-18 14:14:36 +01:00
|
|
|
DBUG_ASSERT(fixed == 1);
|
2003-03-14 10:10:33 +01:00
|
|
|
String *res=args[0]->val_str(&value);
|
2004-03-15 20:39:36 +01:00
|
|
|
User_level_lock *ull;
|
2003-03-14 10:10:33 +01:00
|
|
|
|
|
|
|
null_value=1;
|
|
|
|
if (!res || !res->length())
|
|
|
|
return 0;
|
|
|
|
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_lock(&LOCK_user_locks);
|
2009-10-14 18:37:38 +02:00
|
|
|
ull= (User_level_lock *) my_hash_search(&hash_user_locks, (uchar*) res->ptr(),
|
|
|
|
(size_t) res->length());
|
2009-12-10 04:19:51 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_user_locks);
|
2003-03-14 10:10:33 +01:00
|
|
|
if (!ull || !ull->locked)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
null_value=0;
|
|
|
|
return ull->thread_id;
|
|
|
|
}
|
|
|
|
|
2004-02-17 17:36:53 +01:00
|
|
|
|
2004-05-04 13:45:20 +02:00
|
|
|
longlong Item_func_row_count::val_int()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
|
|
|
THD *thd= current_thd;
|
|
|
|
|
2010-05-14 07:28:51 +02:00
|
|
|
return thd->get_row_count_func();
|
2004-05-04 13:45:20 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-23 19:14:13 +01:00
|
|
|
|
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg, sp_name *name)
|
2007-03-16 14:25:11 +01:00
|
|
|
:Item_func(), context(context_arg), m_name(name), m_sp(NULL), sp_result_field(NULL)
|
2004-02-17 17:36:53 +01:00
|
|
|
{
|
2005-03-04 22:14:35 +01:00
|
|
|
maybe_null= 1;
|
2004-02-17 17:36:53 +01:00
|
|
|
m_name->init_qname(current_thd);
|
2005-11-23 21:45:02 +01:00
|
|
|
dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
|
|
|
|
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
|
2004-02-17 17:36:53 +01:00
|
|
|
}
|
|
|
|
|
2005-03-16 15:11:01 +01:00
|
|
|
|
2005-07-01 06:05:42 +02:00
|
|
|
Item_func_sp::Item_func_sp(Name_resolution_context *context_arg,
|
|
|
|
sp_name *name, List<Item> &list)
|
2007-03-16 14:25:11 +01:00
|
|
|
:Item_func(list), context(context_arg), m_name(name), m_sp(NULL),sp_result_field(NULL)
|
2004-02-17 17:36:53 +01:00
|
|
|
{
|
2005-03-04 22:14:35 +01:00
|
|
|
maybe_null= 1;
|
2004-02-17 17:36:53 +01:00
|
|
|
m_name->init_qname(current_thd);
|
2005-11-23 21:45:02 +01:00
|
|
|
dummy_table= (TABLE*) sql_calloc(sizeof(TABLE)+ sizeof(TABLE_SHARE));
|
|
|
|
dummy_table->s= (TABLE_SHARE*) (dummy_table+1);
|
2004-02-17 17:36:53 +01:00
|
|
|
}
|
|
|
|
|
2005-11-23 21:45:02 +01:00
|
|
|
|
2005-06-10 16:14:01 +02:00
|
|
|
void
|
|
|
|
Item_func_sp::cleanup()
|
|
|
|
{
|
2007-03-16 14:25:11 +01:00
|
|
|
if (sp_result_field)
|
2005-06-10 16:14:01 +02:00
|
|
|
{
|
2007-03-16 14:25:11 +01:00
|
|
|
delete sp_result_field;
|
|
|
|
sp_result_field= NULL;
|
2005-06-10 16:14:01 +02:00
|
|
|
}
|
2005-07-09 19:51:59 +02:00
|
|
|
m_sp= NULL;
|
2006-11-13 12:30:12 +01:00
|
|
|
dummy_table->alias= NULL;
|
2005-06-10 16:14:01 +02:00
|
|
|
Item_func::cleanup();
|
|
|
|
}
|
2005-03-16 15:11:01 +01:00
|
|
|
|
2004-02-17 17:36:53 +01:00
|
|
|
const char *
|
|
|
|
Item_func_sp::func_name() const
|
|
|
|
{
|
2004-09-01 18:00:41 +02:00
|
|
|
THD *thd= current_thd;
|
2005-02-08 23:50:45 +01:00
|
|
|
/* Calculate length to avoid reallocation of string for sure */
|
2007-05-29 13:45:30 +02:00
|
|
|
uint len= (((m_name->m_explicit_name ? m_name->m_db.length : 0) +
|
2004-08-30 20:47:52 +02:00
|
|
|
m_name->m_name.length)*2 + //characters*quoting
|
|
|
|
2 + // ` and `
|
2007-05-29 13:45:30 +02:00
|
|
|
(m_name->m_explicit_name ?
|
|
|
|
3 : 0) + // '`', '`' and '.' for the db
|
2004-08-30 21:52:50 +02:00
|
|
|
1 + // end of string
|
|
|
|
ALIGN_SIZE(1)); // to avoid String reallocation
|
2004-11-09 02:58:44 +01:00
|
|
|
String qname((char *)alloc_root(thd->mem_root, len), len,
|
2004-08-30 20:47:52 +02:00
|
|
|
system_charset_info);
|
2004-09-01 18:00:41 +02:00
|
|
|
|
2004-08-30 20:47:52 +02:00
|
|
|
qname.length(0);
|
2007-03-27 18:31:44 +02:00
|
|
|
if (m_name->m_explicit_name)
|
|
|
|
{
|
|
|
|
append_identifier(thd, &qname, m_name->m_db.str, m_name->m_db.length);
|
|
|
|
qname.append('.');
|
|
|
|
}
|
2004-08-30 20:47:52 +02:00
|
|
|
append_identifier(thd, &qname, m_name->m_name.str, m_name->m_name.length);
|
|
|
|
return qname.ptr();
|
2004-02-17 17:36:53 +01:00
|
|
|
}
|
|
|
|
|
2004-08-30 20:47:52 +02:00
|
|
|
|
2009-09-10 11:18:29 +02:00
|
|
|
void my_missing_function_error(const LEX_STRING &token, const char *func_name)
|
2009-05-27 15:05:29 +02:00
|
|
|
{
|
|
|
|
if (token.length && is_lex_native_function (&token))
|
2009-09-10 11:18:29 +02:00
|
|
|
my_error(ER_FUNC_INEXISTENT_NAME_COLLISION, MYF(0), func_name);
|
2009-05-27 15:05:29 +02:00
|
|
|
else
|
2009-09-10 11:18:29 +02:00
|
|
|
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", func_name);
|
2009-05-27 15:05:29 +02:00
|
|
|
}
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
/**
|
|
|
|
@brief Initialize the result field by creating a temporary dummy table
|
|
|
|
and assign it to a newly created field object. Meta data used to
|
|
|
|
create the field is fetched from the sp_head belonging to the stored
|
|
|
|
proceedure found in the stored procedure functon cache.
|
|
|
|
|
|
|
|
@note This function should be called from fix_fields to init the result
|
|
|
|
field. It is some what related to Item_field.
|
|
|
|
|
|
|
|
@see Item_field
|
|
|
|
|
|
|
|
@param thd A pointer to the session and thread context.
|
|
|
|
|
|
|
|
@return Function return error status.
|
|
|
|
@retval TRUE is returned on an error
|
|
|
|
@retval FALSE is returned on success.
|
|
|
|
*/
|
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
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
bool
|
|
|
|
Item_func_sp::init_result_field(THD *thd)
|
2005-03-04 22:14:35 +01:00
|
|
|
{
|
2007-03-27 19:57:33 +02:00
|
|
|
LEX_STRING empty_name= { C_STRING_WITH_LEN("") };
|
2007-03-16 14:25:11 +01:00
|
|
|
TABLE_SHARE *share;
|
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_ENTER("Item_func_sp::init_result_field");
|
2005-05-06 10:39:30 +02:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(m_sp == NULL);
|
|
|
|
DBUG_ASSERT(sp_result_field == NULL);
|
2005-05-06 10:39:30 +02:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
if (!(m_sp= sp_find_routine(thd, TYPE_ENUM_FUNCTION, m_name,
|
|
|
|
&thd->sp_func_cache, TRUE)))
|
2005-03-09 22:53:04 +01:00
|
|
|
{
|
2009-05-27 15:05:29 +02:00
|
|
|
my_missing_function_error (m_name->m_name, m_name->m_qname.str);
|
2007-03-16 14:25:11 +01:00
|
|
|
context->process_error(thd);
|
|
|
|
DBUG_RETURN(TRUE);
|
2005-03-09 22:53:04 +01:00
|
|
|
}
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
A Field need to be attached to a Table.
|
|
|
|
Below we "create" a dummy table by initializing
|
|
|
|
the needed pointers.
|
|
|
|
*/
|
2007-03-19 16:45:09 +01:00
|
|
|
|
|
|
|
share= dummy_table->s;
|
|
|
|
dummy_table->alias = "";
|
2007-03-16 14:25:11 +01:00
|
|
|
dummy_table->maybe_null = maybe_null;
|
|
|
|
dummy_table->in_use= thd;
|
|
|
|
dummy_table->copy_blobs= TRUE;
|
|
|
|
share->table_cache_key = empty_name;
|
|
|
|
share->table_name = empty_name;
|
|
|
|
|
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 (!(sp_result_field= m_sp->create_result_field(max_length, name,
|
|
|
|
dummy_table)))
|
2005-05-06 10:39:30 +02:00
|
|
|
{
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_RETURN(TRUE);
|
2005-05-06 10:39:30 +02:00
|
|
|
}
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
if (sp_result_field->pack_length() > sizeof(result_buf))
|
2005-05-06 10:39:30 +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
|
|
|
void *tmp;
|
|
|
|
if (!(tmp= sql_alloc(sp_result_field->pack_length())))
|
|
|
|
DBUG_RETURN(TRUE);
|
|
|
|
sp_result_field->move_field((uchar*) tmp);
|
2005-05-06 10:39:30 +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
|
|
|
|
sp_result_field->move_field(result_buf);
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
sp_result_field->null_ptr= (uchar *) &null_value;
|
|
|
|
sp_result_field->null_bit= 1;
|
|
|
|
DBUG_RETURN(FALSE);
|
2005-03-04 22:14:35 +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
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
/**
|
|
|
|
@brief Initialize local members with values from the Field interface.
|
2005-03-04 22:14:35 +01:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
@note called from Item::fix_fields.
|
|
|
|
*/
|
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
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
void Item_func_sp::fix_length_and_dec()
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_sp::fix_length_and_dec");
|
2005-05-06 10:39:30 +02:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(sp_result_field);
|
|
|
|
decimals= sp_result_field->decimals();
|
|
|
|
max_length= sp_result_field->field_length;
|
|
|
|
collation.set(sp_result_field->charset());
|
|
|
|
maybe_null= 1;
|
|
|
|
unsigned_flag= test(sp_result_field->flags & UNSIGNED_FLAG);
|
|
|
|
|
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
/**
|
|
|
|
@brief Execute function & store value in field.
|
|
|
|
|
|
|
|
@return Function returns error status.
|
|
|
|
@retval FALSE on success.
|
|
|
|
@retval TRUE if an error occurred.
|
2005-05-06 10:39:30 +02:00
|
|
|
*/
|
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
bool
|
2007-03-16 14:25:11 +01:00
|
|
|
Item_func_sp::execute()
|
2005-04-20 19:08:42 +02:00
|
|
|
{
|
2005-12-07 15:01:17 +01:00
|
|
|
THD *thd= current_thd;
|
2007-03-16 14:25:11 +01:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
/* Execute function and store the return value in the field. */
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
if (execute_impl(thd))
|
2005-12-07 15:01:17 +01:00
|
|
|
{
|
|
|
|
null_value= 1;
|
|
|
|
context->process_error(thd);
|
2007-05-23 21:24:16 +02:00
|
|
|
if (thd->killed)
|
|
|
|
thd->send_kill_message();
|
2005-12-07 15:01:17 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check that the field (the value) is not NULL. */
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
null_value= sp_result_field->is_null();
|
2005-12-07 15:01:17 +01:00
|
|
|
|
|
|
|
return null_value;
|
2005-04-20 19:08:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
/**
|
|
|
|
@brief Execute function and store the return value in the field.
|
|
|
|
|
|
|
|
@note This function was intended to be the concrete implementation of
|
|
|
|
the interface function execute. This was never realized.
|
|
|
|
|
|
|
|
@return The error state.
|
|
|
|
@retval FALSE on success
|
|
|
|
@retval TRUE if an error occurred.
|
|
|
|
*/
|
2005-12-07 15:01:17 +01:00
|
|
|
bool
|
2007-03-16 14:25:11 +01:00
|
|
|
Item_func_sp::execute_impl(THD *thd)
|
2003-02-26 19:22:29 +01:00
|
|
|
{
|
2005-12-07 15:01:17 +01:00
|
|
|
bool err_status= TRUE;
|
2005-08-15 17:15:12 +02:00
|
|
|
Sub_statement_state statement_state;
|
2006-07-13 15:12:31 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
|
|
Security_context *save_security_ctx= thd->security_ctx;
|
|
|
|
#endif
|
2009-07-28 19:44:38 +02:00
|
|
|
enum enum_sp_data_access access=
|
|
|
|
(m_sp->m_chistics->daccess == SP_DEFAULT_ACCESS) ?
|
|
|
|
SP_DEFAULT_ACCESS_MAPPING : m_sp->m_chistics->daccess;
|
2003-02-26 19:22:29 +01:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
DBUG_ENTER("Item_func_sp::execute_impl");
|
|
|
|
|
2005-10-27 23:18:23 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
|
|
|
if (context->security_ctx)
|
|
|
|
{
|
|
|
|
/* Set view definer security context */
|
|
|
|
thd->security_ctx= context->security_ctx;
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-16 14:25:11 +01:00
|
|
|
if (sp_check_access(thd))
|
2005-06-23 17:29:10 +02:00
|
|
|
goto error;
|
2003-02-26 19:22:29 +01:00
|
|
|
|
2006-11-15 01:27:39 +01:00
|
|
|
/*
|
|
|
|
Throw an error if a non-deterministic function is called while
|
|
|
|
statement-based replication (SBR) is active.
|
|
|
|
*/
|
2009-07-28 19:44:38 +02:00
|
|
|
|
2006-11-17 21:30:28 +01:00
|
|
|
if (!m_sp->m_chistics->detistic && !trust_function_creators &&
|
2009-07-28 19:44:38 +02:00
|
|
|
(access == SP_CONTAINS_SQL || access == SP_MODIFIES_SQL_DATA) &&
|
2006-11-15 01:27:39 +01:00
|
|
|
(mysql_bin_log.is_open() &&
|
|
|
|
thd->variables.binlog_format == BINLOG_FORMAT_STMT))
|
|
|
|
{
|
2009-07-28 19:44:38 +02:00
|
|
|
my_error(ER_BINLOG_UNSAFE_ROUTINE, MYF(0));
|
2006-11-15 01:27:39 +01:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2005-08-25 15:34:34 +02:00
|
|
|
/*
|
|
|
|
Disable the binlogging if this is not a SELECT statement. If this is a
|
|
|
|
SELECT, leave binlogging on, so execute_function() code writes the
|
|
|
|
function call into binlog.
|
|
|
|
*/
|
2005-08-15 17:15:12 +02:00
|
|
|
thd->reset_sub_statement_state(&statement_state, SUB_STMT_FUNCTION);
|
2007-03-16 14:25:11 +01:00
|
|
|
err_status= m_sp->execute_function(thd, args, arg_count, sp_result_field);
|
2005-08-15 17:15:12 +02:00
|
|
|
thd->restore_sub_statement_state(&statement_state);
|
2005-09-21 07:29:47 +02:00
|
|
|
|
2005-06-23 17:29:10 +02:00
|
|
|
error:
|
2006-07-13 15:12:31 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2005-10-31 21:14:27 +01:00
|
|
|
thd->security_ctx= save_security_ctx;
|
2005-10-27 23:18:23 +02:00
|
|
|
#endif
|
2006-07-13 15:12:31 +02:00
|
|
|
|
2005-12-07 15:01:17 +01:00
|
|
|
DBUG_RETURN(err_status);
|
2003-02-26 19:22:29 +01:00
|
|
|
}
|
|
|
|
|
2004-12-07 14:47:00 +01:00
|
|
|
|
2005-03-04 22:14:35 +01:00
|
|
|
void
|
|
|
|
Item_func_sp::make_field(Send_field *tmp_field)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_sp::make_field");
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(sp_result_field);
|
|
|
|
sp_result_field->make_field(tmp_field);
|
2008-01-31 21:46:26 +01:00
|
|
|
if (name)
|
|
|
|
tmp_field->col_name= name;
|
2005-03-04 22:14:35 +01:00
|
|
|
DBUG_VOID_RETURN;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-02-27 19:08:52 +01:00
|
|
|
enum enum_field_types
|
|
|
|
Item_func_sp::field_type() const
|
2003-02-26 19:22:29 +01:00
|
|
|
{
|
2003-02-27 19:08:52 +01:00
|
|
|
DBUG_ENTER("Item_func_sp::field_type");
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(sp_result_field);
|
|
|
|
DBUG_RETURN(sp_result_field->type());
|
2003-02-26 19:22:29 +01:00
|
|
|
}
|
|
|
|
|
2003-02-27 19:08:52 +01:00
|
|
|
Item_result
|
|
|
|
Item_func_sp::result_type() const
|
2003-02-26 19:22:29 +01:00
|
|
|
{
|
2003-02-27 19:08:52 +01:00
|
|
|
DBUG_ENTER("Item_func_sp::result_type");
|
2008-02-22 11:30:33 +01:00
|
|
|
DBUG_PRINT("info", ("m_sp = %p", (void *) m_sp));
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(sp_result_field);
|
|
|
|
DBUG_RETURN(sp_result_field->result_type());
|
2003-02-26 19:22:29 +01:00
|
|
|
}
|
|
|
|
|
2004-06-22 19:38:07 +02:00
|
|
|
longlong Item_func_found_rows::val_int()
|
|
|
|
{
|
|
|
|
DBUG_ASSERT(fixed == 1);
|
2005-05-06 10:39:30 +02:00
|
|
|
return current_thd->found_rows();
|
2004-06-22 19:38:07 +02:00
|
|
|
}
|
2005-03-04 22:14:35 +01:00
|
|
|
|
2005-05-06 10:39:30 +02:00
|
|
|
|
2005-03-04 22:14:35 +01:00
|
|
|
Field *
|
|
|
|
Item_func_sp::tmp_table_field(TABLE *t_arg)
|
|
|
|
{
|
|
|
|
DBUG_ENTER("Item_func_sp::tmp_table_field");
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ASSERT(sp_result_field);
|
|
|
|
DBUG_RETURN(sp_result_field);
|
2005-03-04 22:14:35 +01:00
|
|
|
}
|
2005-09-20 01:05:35 +02:00
|
|
|
|
2005-09-21 07:29:47 +02:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
/**
|
|
|
|
@brief Checks if requested access to function can be granted to user.
|
2005-09-20 01:05:35 +02:00
|
|
|
If function isn't found yet, it searches function first.
|
|
|
|
If function can't be found or user don't have requested access
|
2005-09-21 07:29:47 +02:00
|
|
|
error is raised.
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
@param thd thread handler
|
|
|
|
|
|
|
|
@return Indication if the access was granted or not.
|
|
|
|
@retval FALSE Access is granted.
|
|
|
|
@retval TRUE Requested access can't be granted or function doesn't exists.
|
|
|
|
|
2005-09-20 01:05:35 +02:00
|
|
|
*/
|
2005-09-21 07:29:47 +02:00
|
|
|
|
2005-09-20 01:05:35 +02:00
|
|
|
bool
|
2007-03-16 14:25:11 +01:00
|
|
|
Item_func_sp::sp_check_access(THD *thd)
|
2005-09-20 01:05:35 +02:00
|
|
|
{
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ENTER("Item_func_sp::sp_check_access");
|
|
|
|
DBUG_ASSERT(m_sp);
|
2005-09-21 07:29:47 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2006-07-13 15:12:31 +02:00
|
|
|
if (check_routine_access(thd, EXECUTE_ACL,
|
2005-09-21 07:29:47 +02:00
|
|
|
m_sp->m_db.str, m_sp->m_name.str, 0, FALSE))
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_RETURN(TRUE);
|
2005-09-20 01:05:35 +02:00
|
|
|
#endif
|
2005-10-11 23:58:22 +02:00
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_RETURN(FALSE);
|
2005-09-21 14:36:55 +02:00
|
|
|
}
|
2005-09-20 01:05:35 +02:00
|
|
|
|
2006-07-13 15:12:31 +02:00
|
|
|
|
2005-09-20 01:05:35 +02:00
|
|
|
bool
|
|
|
|
Item_func_sp::fix_fields(THD *thd, Item **ref)
|
|
|
|
{
|
|
|
|
bool res;
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_ENTER("Item_func_sp::fix_fields");
|
2005-09-20 01:05:35 +02:00
|
|
|
DBUG_ASSERT(fixed == 0);
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
We must call init_result_field before Item_func::fix_fields()
|
|
|
|
to make m_sp and result_field members available to fix_length_and_dec(),
|
|
|
|
which is called from Item_func::fix_fields().
|
|
|
|
*/
|
|
|
|
res= init_result_field(thd);
|
|
|
|
|
|
|
|
if (res)
|
|
|
|
DBUG_RETURN(res);
|
|
|
|
|
2005-09-20 01:05:35 +02:00
|
|
|
res= Item_func::fix_fields(thd, ref);
|
2007-03-16 14:25:11 +01:00
|
|
|
|
|
|
|
if (res)
|
|
|
|
DBUG_RETURN(res);
|
|
|
|
|
Fixed following problems:
--Bug#52157 various crashes and assertions with multi-table update, stored function
--Bug#54475 improper error handling causes cascading crashing failures in innodb/ndb
--Bug#57703 create view cause Assertion failed: 0, file .\item_subselect.cc, line 846
--Bug#57352 valgrind warnings when creating view
--Recently discovered problem when a nested materialized derived table is used
before being populated and it leads to incorrect result
We have several modes when we should disable subquery evaluation.
The reasons for disabling are different. It could be
uselessness of the evaluation as in case of 'CREATE VIEW'
or 'PREPARE stmt', or we should disable subquery evaluation
if tables are not locked yet as it happens in bug#54475, or
too early evaluation of subqueries can lead to wrong result
as it happened in Bug#19077.
Main problem is that if subquery items are treated as const
they are evaluated in ::fix_fields(), ::fix_length_and_dec()
of the parental items as a lot of these methods have
Item::val_...() calls inside.
We have to make subqueries non-const to prevent unnecessary
subquery evaluation. At the moment we have different methods
for this. Here is a list of these modes:
1. PREPARE stmt;
We use UNCACHEABLE_PREPARE flag.
It is set during parsing in sql_parse.cc, mysql_new_select() for
each SELECT_LEX object and cleared at the end of PREPARE in
sql_prepare.cc, init_stmt_after_parse(). If this flag is set
subquery becomes non-const and evaluation does not happen.
2. CREATE|ALTER VIEW, SHOW CREATE VIEW, I_S tables which
process FRM files
We use LEX::view_prepare_mode field. We set it before
view preparation and check this flag in
::fix_fields(), ::fix_length_and_dec().
Some bugs are fixed using this approach,
some are not(Bug#57352, Bug#57703). The problem here is
that we have a lot of ::fix_fields(), ::fix_length_and_dec()
where we use Item::val_...() calls for const items.
3. Derived tables with subquery = wrong result(Bug19077)
The reason of this bug is too early subquery evaluation.
It was fixed by adding Item::with_subselect field
The check of this field in appropriate places prevents
const item evaluation if the item have subquery.
The fix for Bug19077 fixes only the problem with
convert_constant_item() function and does not cover
other places(::fix_fields(), ::fix_length_and_dec() again)
where subqueries could be evaluated.
Example:
CREATE TABLE t1 (i INT, j BIGINT);
INSERT INTO t1 VALUES (1, 2), (2, 2), (3, 2);
SELECT * FROM (SELECT MIN(i) FROM t1
WHERE j = SUBSTRING('12', (SELECT * FROM (SELECT MIN(j) FROM t1) t2))) t3;
DROP TABLE t1;
4. Derived tables with subquery where subquery
is evaluated before table locking(Bug#54475, Bug#52157)
Suggested solution is following:
-Introduce new field LEX::context_analysis_only with the following
possible flags:
#define CONTEXT_ANALYSIS_ONLY_PREPARE 1
#define CONTEXT_ANALYSIS_ONLY_VIEW 2
#define CONTEXT_ANALYSIS_ONLY_DERIVED 4
-Set/clean these flags when we perform
context analysis operation
-Item_subselect::const_item() returns
result depending on LEX::context_analysis_only.
If context_analysis_only is set then we return
FALSE that means that subquery is non-const.
As all subquery types are wrapped by Item_subselect
it allow as to make subquery non-const when
it's necessary.
2010-12-14 10:33:03 +01:00
|
|
|
if (thd->lex->context_analysis_only & CONTEXT_ANALYSIS_ONLY_VIEW)
|
2005-10-11 23:58:22 +02:00
|
|
|
{
|
2005-10-27 23:18:23 +02:00
|
|
|
/*
|
|
|
|
Here we check privileges of the stored routine only during view
|
2006-07-13 15:12:31 +02:00
|
|
|
creation, in order to validate the view. A runtime check is
|
|
|
|
perfomed in Item_func_sp::execute(), and this method is not
|
|
|
|
called during context analysis. Notice, that during view
|
|
|
|
creation we do not infer into stored routine bodies and do not
|
|
|
|
check privileges of its statements, which would probably be a
|
|
|
|
good idea especially if the view has SQL SECURITY DEFINER and
|
|
|
|
the used stored procedure has SQL SECURITY DEFINER.
|
2005-10-27 23:18:23 +02:00
|
|
|
*/
|
2007-03-16 14:25:11 +01:00
|
|
|
res= sp_check_access(thd);
|
2006-07-13 15:12:31 +02:00
|
|
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
2007-03-16 14:25:11 +01:00
|
|
|
/*
|
|
|
|
Try to set and restore the security context to see whether it's valid
|
|
|
|
*/
|
2006-07-13 15:12:31 +02:00
|
|
|
Security_context *save_secutiry_ctx;
|
2007-03-16 14:25:11 +01:00
|
|
|
res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
|
|
|
|
if (!res)
|
2007-04-13 22:35:56 +02:00
|
|
|
m_sp->m_security_ctx.restore_security_context(thd, save_secutiry_ctx);
|
2007-03-16 14:25:11 +01:00
|
|
|
|
2006-07-13 15:12:31 +02:00
|
|
|
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
2005-10-11 23:58:22 +02:00
|
|
|
}
|
2007-10-04 15:19:14 +02:00
|
|
|
|
2007-07-19 15:39:01 +02:00
|
|
|
if (!m_sp->m_chistics->detistic)
|
2007-10-04 15:19:14 +02:00
|
|
|
{
|
|
|
|
used_tables_cache |= RAND_TABLE_BIT;
|
|
|
|
const_item_cache= FALSE;
|
|
|
|
}
|
|
|
|
|
2007-03-16 14:25:11 +01:00
|
|
|
DBUG_RETURN(res);
|
2005-09-20 01:05:35 +02:00
|
|
|
}
|
2007-04-27 00:12:09 +02:00
|
|
|
|
|
|
|
|
2007-07-19 15:39:01 +02:00
|
|
|
void Item_func_sp::update_used_tables()
|
|
|
|
{
|
|
|
|
Item_func::update_used_tables();
|
2007-10-04 15:19:14 +02:00
|
|
|
|
2007-07-19 15:39:01 +02:00
|
|
|
if (!m_sp->m_chistics->detistic)
|
2007-10-04 15:19:14 +02:00
|
|
|
{
|
|
|
|
used_tables_cache |= RAND_TABLE_BIT;
|
|
|
|
const_item_cache= FALSE;
|
|
|
|
}
|
2007-07-19 15:39:01 +02:00
|
|
|
}
|
2007-07-21 21:53:01 +02:00
|
|
|
|
|
|
|
|
2007-04-27 00:12:09 +02:00
|
|
|
/*
|
|
|
|
uuid_short handling.
|
|
|
|
|
|
|
|
The short uuid is defined as a longlong that contains the following bytes:
|
|
|
|
|
|
|
|
Bytes Comment
|
|
|
|
1 Server_id & 255
|
|
|
|
4 Startup time of server in seconds
|
|
|
|
3 Incrementor
|
|
|
|
|
|
|
|
This means that an uuid is guaranteed to be unique
|
|
|
|
even in a replication environment if the following holds:
|
|
|
|
|
|
|
|
- The last byte of the server id is unique
|
|
|
|
- If you between two shutdown of the server don't get more than
|
|
|
|
an average of 2^24 = 16M calls to uuid_short() per second.
|
|
|
|
*/
|
|
|
|
|
|
|
|
ulonglong uuid_value;
|
|
|
|
|
|
|
|
void uuid_short_init()
|
|
|
|
{
|
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
|
|
|
uuid_value= ((((ulonglong) server_id) << 56) +
|
|
|
|
(((ulonglong) server_start_time) << 24));
|
2007-04-27 00:12:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
longlong Item_func_uuid_short::val_int()
|
|
|
|
{
|
|
|
|
ulonglong val;
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_lock(&LOCK_uuid_generator);
|
2007-04-27 00:12:09 +02:00
|
|
|
val= uuid_value++;
|
2010-01-07 06:42:07 +01:00
|
|
|
mysql_mutex_unlock(&LOCK_uuid_generator);
|
2007-04-27 00:12:09 +02:00
|
|
|
return (longlong) val;
|
|
|
|
}
|